Skip to content

Commit 94f488e

Browse files
committed
Creating a new role to deploy MAAS
1 parent cf9d52c commit 94f488e

15 files changed

+649
-0
lines changed

maas.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
- hosts: maas
3+
serial: 1
4+
strategy: free
5+
roles:
6+
- maas
7+
become: true

roles/maas/README.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Ansible Playbook: MAAS Installation and Configuration
2+
3+
This Ansible playbook automates the installation and initial configuration of [MAAS (Metal as a Service)](https://maas.io/) on Ubuntu-based systems.
4+
5+
## Features
6+
7+
- Installs MAAS packages
8+
- Initializes MAAS with a default user with HA
9+
- Configures networking (DHCP, DNS, etc.)
10+
- Adds Machines from invetory into MAAS
11+
12+
## Requirements
13+
14+
- Ansible 2.10+
15+
- Ubuntu 20.04 or later on the target system(s)
16+
- Sudo access on target host
17+
- Internet access (for downloading MAAS packages and images)
18+
- At least 2 Nodes to deploy MAAS with HA
19+
20+
## Inventory
21+
22+
Define your inventory in `hosts.ini` with the following structure:
23+
24+
```ini
25+
[maas_region_rack_server]
26+
test1 ip=172.x.x.x ipmi=10.0.8.x mac=08:00:27:ed:43:x
27+
28+
[maas_rack_server]
29+
test2 ip=172.x.x.x ipmi=10.0.8.x mac=08:00:27:ed:43:x
30+
31+
[maas_db_server]
32+
test1 ip=172.x.x.x ipmi=10.0.8.x mac=08:00:27:ed:43:x
33+
34+
The systems you want to add into MAAS should be on a group called [testnodes] with the same structure.
35+
36+
## Variables
37+
38+
You can configure the playbook via group_vars/maas.yml in the secret repo or defaults/main.yml. Common variables include:
39+
maas_admin_username: "admin"
40+
maas_admin_password: "adminpass"
41+
maas_admin_email: "admin@example.com"
42+
maas_admin_username: "admin"
43+
maas_db_name: "maasdb"
44+
maas_db_user: "maas"
45+
maas_version: "3.5"
46+
maas_snap_channel: "stable"
47+
48+
DNS variables include:
49+
dns_domains:
50+
- ceph: Static primary domain (e.g., `internal.ceph.tucson.com`).
51+
- ipmi: Static IPMI domain (`ipmi.ceph.tucson.com`).
52+
- vlan104: Static sub-domain for vlan104 address(`vlan104.internal.ceph.tucson.com`).
53+
default_domains: List of domains to preserve/ignore (default: `["maas"]`). The default domain is a DNS domain that is used by maas when you deploy a machine it is used by maas for internal dns records so we choose to exclude it from our ansible role.
54+
55+
DHCP variables include:
56+
dhcp_global_options:
57+
- ddns-update-style: none
58+
- default-lease-time: 43200
59+
- max-lease-time: 172800
60+
- one-lease-per-client: "true"
61+
62+
This list will be used to populate the global snippet. You can add additional keys and values. Just make sure they follow the syntax required for dhcpd.conf.
63+
64+
dhcp_maas_subnets:
65+
front:
66+
cidr: 10.0.8.0/24
67+
ipvar: ip
68+
macvar: mac
69+
start_ip: 10.0.8.10
70+
end_ip: 10.0.8.20
71+
ip_range_type: dynamic
72+
classes:
73+
virtual: "match if substring(hardware, 0, 4) = 01:52:54:00"
74+
lxc: "match if substring(hardware, 0, 4) = 01:52:54:ff"
75+
pools:
76+
virtual:
77+
range: 172.21.10.20 172.21.10.250
78+
unknown_clients:
79+
range:
80+
- 172.21.11.0 172.21.11.19
81+
- 172.21.13.170 172.21.13.250
82+
lxc:
83+
range: 172.21.14.1 172.21.14.200
84+
back:
85+
cidr: 172.21.16.0/20
86+
ipvar: back
87+
macvar: backmac
88+
89+
This is large dictionary that gets parsed out into individual snippet files. Each top-level key (front and back in the example) will get its own snippet file created. The example shown to the left is our actual dhcp_maas_subnets dictionary.
90+
91+
Under each subnet, cidr, ipvar, and macvar are required. ipvar and macvar tell the Jinja2 template which IP address and MAC address should be used for each host in each subnet snippet.
92+
93+
Here's a line from our Ansible inventory host file
94+
95+
smithi001.front.sepia.ceph.com mac=0C:C4:7A:BD:15:E8 ip=172.21.15.1 ipmi=172.21.47.1 bmc=0C:C4:7A:6E:21:A7
96+
97+
This will result in a static IP entry for smithi001-front with IP 172.21.15.1 and MAC 0C:C4:7A:BD:15:E8 in front_hosts snippet and a smithi001-ipmi entry with IP 172.21.47.1 with MAC 0C:C4:7A:6E:21:A7 in ipmi_hosts snippet.
98+
99+
## Usage
100+
101+
1. Clone the repository:
102+
103+
git clone https://github.com/ceph/ceph-cm-ansible.git
104+
cd ceph-cm-ansible
105+
106+
2. Update inventory and variables.
107+
108+
3. Run the playbook:
109+
110+
ansible-playbook -i hosts.ini maas.yml
111+
112+
## Role Structure
113+
114+
maas
115+
   ├── defaults
116+
   │   └── main.yml
117+
   ├── meta
118+
   │   └── main.yml
119+
   ├── tasks
120+
   │   ├── add_machines.yml
121+
   │   ├── config_dhcpd.yml
122+
   │   ├── config_dns.yml
123+
   │   ├── initialize_region_rack.yml
124+
   │   ├── initialize_secondary_rack.yml
125+
   │   ├── install_maasdb.yml
126+
   │   └── main.yml
127+
   └── templates
128+
   ├── dhcpd.classes.conf.j2
129+
   ├── dhcpd.global.conf.j2
130+
   ├── dhcpd.hosts.conf.j2
131+
   └── dhcpd.pools.conf.j2
132+
133+
## Tags
134+
135+
- install_maas #Install MAAS and postgreSQL only and initializes the region+rack server and the secondary rack.
136+
- add-machines #Add Machines to MAAS only if they are not already present.
137+
- config_dhcp #Configures DHCP options only if there are any change in the DHCP variables.
138+
- config_dns #Configure DNS domains and add the DNS Records that are not currenlty into a Domain.

roles/maas/defaults/main.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
# MAAS user and database variables
3+
maas_admin_username: "admin"
4+
maas_db_name: "maasdb"
5+
maas_db_user: "maas"
6+
maas_version: "3.5"
7+
maas_snap_channel: "stable"
8+
9+
# DNS Variables
10+
default_domains:
11+
- "maas"
12+
13+
maas_dns_domains:
14+
ceph: "front.sepia.ceph.com"
15+
ipmi: "ipmi.sepia.ceph.com"
16+
17+

roles/maas/meta/main.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
dependencies:
3+
- role: secrets

roles/maas/tasks/add_machines.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
- name: Add all machines from inventory to MAAS
3+
vars:
4+
arch: "amd64" # Change if needed
5+
when: inventory_hostname in groups['maas_region_rack_server'] and logged_into_maas.rc == 0
6+
tags: add_machines
7+
block:
8+
- name: Get existing machines in MAAS
9+
command: "maas {{ maas_admin_username }} machines read"
10+
register: existing_machines
11+
12+
- name: Extract existing hostnames
13+
set_fact:
14+
existing_hostnames: "{{ existing_machines.stdout | from_json | map(attribute='hostname') | list }}"
15+
16+
- name: Add Machines into MAAS
17+
vars:
18+
hostname: "{{ item.split('.')[0] }}"
19+
mac_address: "{{ hostvars[item]['mac'] }}"
20+
when: hostname not in existing_hostnames and mac_address is defined
21+
loop: "{{ groups['testnodes'] }}"
22+
command: "maas {{ maas_admin_username }} machines create architecture={{ arch }} mac_addresses={{ mac_address }} hostname={{ item }} power_type=manual deployed=true"
23+

roles/maas/tasks/config_dhcpd.yml

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
---
2+
- name: Configures MAAS DHCP
3+
when: inventory_hostname in groups['maas_region_rack_server'] and logged_into_maas.rc == 0
4+
tags: config_dhcp
5+
block:
6+
# This section enables DHCP on the subnets included into the secrets repo group_vars and creates an IP range for them
7+
- name: Creating IP Range for {{ subnet_name }} subnet
8+
command: "maas admin ipranges create type={{ subnet_data.ip_range_type }} start_ip={{ subnet_data.start_ip }} end_ip={{ subnet_data.end_ip }}"
9+
ignore_errors: true
10+
tags: skip
11+
12+
- name: Selecting the correct fabric to configure {{ subnet_name }} subnet
13+
command: bash -c "maas admin subnet read {{ subnet_data.cidr }}|grep 'fabric-'|cut -d '\"' -f 4"
14+
register: fabric_selected
15+
16+
- name: Getting {{ subnet_name }} subnet ID
17+
command: bash -c "maas admin subnet read {{ subnet_data.cidr }}|grep '\"id\"'|cut -d ':' -f 2|cut -d ',' -f 1|head -1"
18+
register: subnet_id
19+
20+
- name: Enabling DHCP with HA on {{ subnet_name }} subnet
21+
command: "maas admin vlan update {{ fabric_selected.stdout }} 0 dhcp_on=True primary_rack={{ groups['maas_region_rack_server'][0] }} secondary_rack={{ groups['maas_rack_server'][0] }}"
22+
tags: skip
23+
24+
# This task creates the directory where the snippets are going to be copied
25+
26+
- name: Creating snippets directory
27+
file:
28+
path: /var/snap/maas/common/maas/dhcp/snippets
29+
state: directory
30+
mode: '0755'
31+
register: snippets_directory
32+
33+
# This section verifies if the snippets already exist
34+
35+
- name: Verifying if the global dhcp snippet exists
36+
command: bash -c "maas admin dhcpsnippets read|grep 'global_dhcp'"
37+
ignore_errors: true
38+
register: global_exists
39+
40+
- name: Verifying if the {{ subnet_name }} subnet classes snippet exists
41+
command: bash -c "maas admin dhcpsnippets read |grep '{{ subnet_name }}_classes'"
42+
when: subnet_data.classes is defined
43+
ignore_errors: true
44+
register: classes_exists
45+
46+
- name: Verifying if the {{ subnet_name }} subnet pools snippet exists
47+
command: bash -c "maas admin dhcpsnippets read |grep '{{ subnet_name }}_pools'"
48+
when: subnet_data.pools is defined
49+
ignore_errors: true
50+
register: pools_exists
51+
52+
- name: Verifying if the {{ subnet_name }} subnet hosts snippet exists
53+
command: bash -c "maas admin dhcpsnippets read |grep '{{ subnet_name }}_hosts'"
54+
ignore_errors: true
55+
register: hosts_exists
56+
57+
# This section copies the snippets
58+
59+
- name: Copying global DHCP snippet
60+
template:
61+
src: dhcpd.global.conf.j2
62+
dest: "/var/snap/maas/common/maas/dhcp/snippets/global_dhcp_snippet"
63+
when: snippets_directory.failed == false
64+
register: dhcp_global_config
65+
66+
- name: Copying {{ subnet_name }} subnet classes snippet
67+
template:
68+
src: dhcpd.classes.conf.j2
69+
dest: "/var/snap/maas/common/maas/dhcp/snippets/{{ subnet_name }}_classes_snippet"
70+
when: subnet_data.classes is defined and snippets_directory.failed == false
71+
register: dhcp_classes_config
72+
73+
- name: Copying {{ subnet_name }} subnet pools snippet
74+
template:
75+
src: dhcpd.pools.conf.j2
76+
dest: "/var/snap/maas/common/maas/dhcp/snippets/{{ subnet_name }}_pools_snippet"
77+
when: subnet_data.pools is defined and snippets_directory.failed == false
78+
register: dhcp_pools_config
79+
80+
- name: Copying {{ subnet_name }} subnet hosts snippet
81+
template:
82+
src: dhcpd.hosts.conf.j2
83+
dest: "/var/snap/maas/common/maas/dhcp/snippets/{{ subnet_name }}_hosts_snippet"
84+
when: snippets_directory.failed == false
85+
register: dhcp_hosts_config
86+
87+
# This section decodes the snippet files and creates the variables to add them into MAAS
88+
89+
- name: Slurp global DHCP file content
90+
slurp:
91+
src: "/var/snap/maas/common/maas/dhcp/snippets/global_dhcp_snippet"
92+
when: dhcp_global_config.failed == false
93+
register: global_file
94+
95+
- name: Decode global DHCP file content
96+
set_fact:
97+
global_content: "{{ global_file.content | b64decode }}"
98+
when: dhcp_global_config.failed == false
99+
100+
- name: Slurp {{ subnet_name }} classes file content
101+
slurp:
102+
src: "/var/snap/maas/common/maas/dhcp/snippets/{{ subnet_name }}_classes_snippet"
103+
when: subnet_data.classes is defined and dhcp_classes_config.failed == false
104+
register: classes_file
105+
106+
- name: Decode {{ subnet_name }} classes file content
107+
set_fact:
108+
classes_content: "{{ classes_file.content | b64decode }}"
109+
when: subnet_data.classes is defined and dhcp_classes_config.failed == false
110+
111+
- name: Slurp {{ subnet_name }} pools file content
112+
slurp:
113+
src: "/var/snap/maas/common/maas/dhcp/snippets/{{ subnet_name }}_pools_snippet"
114+
when: subnet_data.pools is defined and dhcp_pools_config.failed == false
115+
register: pools_file
116+
117+
- name: Decode {{ subnet_name }} pools file content
118+
set_fact:
119+
pools_content: "{{ pools_file.content | b64decode }}"
120+
when: subnet_data.pools is defined and dhcp_pools_config.failed == false
121+
122+
- name: Slurp {{ subnet_name }} hosts file content
123+
slurp:
124+
src: "/var/snap/maas/common/maas/dhcp/snippets/{{ subnet_name }}_hosts_snippet"
125+
register: hosts_file
126+
127+
- name: Decode {{ subnet_name }} hosts file content
128+
set_fact:
129+
hosts_content: "{{ hosts_file.content | b64decode }}"
130+
131+
# This section deletes the snippets if already exist
132+
133+
- name: Delete global DHCP snippet if already exists
134+
command: "maas admin dhcpsnippet delete global_dhcp"
135+
when: dhcp_global_config.changed == true and global_exists.failed == false
136+
137+
- name: Delete {{ subnet_name }} subnet classes snippet if already exists
138+
command: "maas admin dhcpsnippet delete {{ subnet_name }}_classes"
139+
when: subnet_data.classes is defined and dhcp_classes_config.changed == true and classes_exists.failed == false
140+
141+
- name: Delete {{ subnet_name }} subnet pools snippet if already exists
142+
command: "maas admin dhcpsnippet delete {{ subnet_name }}_pools"
143+
when: subnet_data.pools is defined and dhcp_pools_config.changed == true and pools_exists.failed == false
144+
145+
- name: Delete {{ subnet_name }} subnet hosts snippet if already exists
146+
command: "maas admin dhcpsnippet delete {{ subnet_name }}_hosts"
147+
when: dhcp_hosts_config.changed == true and hosts_exists.failed == false
148+
149+
# This section adds snippets into MAAS
150+
151+
- name: Adding global DHCP snippets into MAAS
152+
command: "maas {{ maas_admin_username }} dhcpsnippets create name='global_dhcp' value='{{ global_content }}' description='This snippet configures the global DHCP options' global_snippet=true"
153+
when: dhcp_global_config.failed == false and dhcp_global_config.changed == true
154+
155+
- name: Adding {{ subnet_name }} classes snippets into MAAS
156+
command: "maas {{ maas_admin_username }} dhcpsnippets create name='{{ subnet_name }}_classes' value='{{ classes_content }}' description='This snippet configures the classes in {{ subnet_name }} subnet' subnet='{{ subnet_id.stdout }}'"
157+
when: dhcp_classes_config.failed == false and dhcp_classes_config.changed == true
158+
159+
- name: Adding {{ subnet_name }} pools snippets into MAAS
160+
command: "maas {{ maas_admin_username }} dhcpsnippets create name='{{ subnet_name }}_pools' value='{{ pools_content }}' description='This snippet configures the pools in {{ subnet_name }} subnet' subnet='{{ subnet_id.stdout }}'"
161+
when: dhcp_pools_config.failed == false and dhcp_pools_config.changed == true
162+
163+
- name: Adding {{ subnet_name }} hosts snippets into MAAS
164+
command: "maas {{ maas_admin_username }} dhcpsnippets create name='{{ subnet_name }}_hosts' value='{{ hosts_content }}' description='This snippet configures the hosts in {{ subnet_name }} subnet' subnet='{{ subnet_id.stdout }}'"
165+
when: dhcp_hosts_config.failed == false and dhcp_hosts_config.changed == true

0 commit comments

Comments
 (0)