From f2293c5106b3fd431c74f2fa9297040ef1c49790 Mon Sep 17 00:00:00 2001 From: Ricardo Carrillo Cruz Date: Thu, 17 Dec 2015 10:48:03 +0100 Subject: [PATCH] Allow configuring provisioning IP address when using inventory_dhcp This change adds flag 'inventory_dhcp_static_ip' to the deploy-nodes-dynamic role. If set to true, it will read the new 'provisioning_ipv4_address' key from the inventory machine section and use that as assigned IP for the machine mac. If set to false, dnsmasq will assign IPs from the configured DHCP range. An inventory machine example specifying provisioning_ipv4_address: "compute00.hpuseast.ic.openstack.org": { "ansible_ssh_host": "15.126.48.52", "ipv4_address": "15.126.48.52", "provisioning_ipv4_address": "10.23.212.5", "uuid": "30303536-3734-5355-4532-333745314C41", "driver_info": { "power": { "ipmi_address": "1.1.1.1", "ipmi_username": "xxx" "ipmi_password": "moarxxx" } } Change-Id: I9083cd34096aad04136564c2ded024527c88c711 --- README.rst | 4 ++- bifrost/inventory.py | 10 +++++++ .../functional/test_inventory_functional.py | 26 ++++++++++++------ .../bifrost-deploy-nodes-dynamic/README.md | 27 +++++++++++++++---- .../defaults/main.yml | 1 + .../templates/dhcp-host.j2 | 6 ++++- ...sioning_ipv4_address-d2779f1abc38324a.yaml | 16 +++++++++++ 7 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 releasenotes/notes/inventory_dhcp_provisioning_ipv4_address-d2779f1abc38324a.yaml diff --git a/README.rst b/README.rst index c1a394732..46d0a2b75 100644 --- a/README.rst +++ b/README.rst @@ -256,6 +256,7 @@ Example:: "driver": "agent_ssh", "ansible_ssh_host": "192.168.122.2", "ipv4_address": "192.168.122.2", + "provisioning_ipv4_address": "10.0.0.9", "properties": { "cpu_arch": "x86_64", "ram": "3072", @@ -296,10 +297,11 @@ The CSV file has the following columns: 14. ``ipmi_transit_channel`` - Requires: ``ipmi_bridging`` set to dual 15. ``ipmi_transit_address`` - Requires: ``ipmi_bridging`` set to dual 16. ironic driver +17. Host provisioning IP Address Example definition:: - 00:11:22:33:44:55,root,undefined,192.168.122.1,1,8192,512,NA,NA,aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee,hostname_100,192.168.2.100,,,,agent_ipmitool + 00:11:22:33:44:55,root,undefined,192.168.122.1,1,8192,512,NA,NA,aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee,hostname_100,192.168.2.100,,,,agent_ipmitool,10.0.0.9 This file format is fairly flexible and can be easily modified although the enrollment and deployment playbooks utilize the model diff --git a/bifrost/inventory.py b/bifrost/inventory.py index 4530f0da2..0e57b5e42 100755 --- a/bifrost/inventory.py +++ b/bifrost/inventory.py @@ -188,6 +188,9 @@ def _process_baremetal_data(data_source, groups, hostvars): host['addressing_mode'] = "dhcp" else: host['ansible_ssh_host'] = host['ipv4_address'] + + if 'provisioning_ipv4_address' not in host.keys(): + host['provisioning_ipv4_address'] = host['ipv4_address'] # Add each host to the values to be returned. groups['baremetal']['hosts'].append(host['name']) hostvars.update({host['name']: host}) @@ -228,8 +231,15 @@ def _process_baremetal_csv(data_source, groups, hostvars): host['ipv4_address'] = _val_or_none(row, 11) if not host['ipv4_address']: host['addressing_mode'] = "dhcp" + host['provisioning_ipv4_address'] = None else: host['ansible_ssh_host'] = host['ipv4_address'] + + if len(row) > 17: + host['provisioning_ipv4_address'] = row[18] + else: + host['provisioning_ipv4_address'] = host['ipv4_address'] + # Default Driver unless otherwise defined or determined. host['driver'] = "agent_ssh" diff --git a/bifrost/tests/functional/test_inventory_functional.py b/bifrost/tests/functional/test_inventory_functional.py index 015385c13..8d53154f7 100644 --- a/bifrost/tests/functional/test_inventory_functional.py +++ b/bifrost/tests/functional/test_inventory_functional.py @@ -41,7 +41,8 @@ unused,,00000000-0000-0000-0000-000000000002,hostname1, 192.168.1.3,,,,,agent_ipmitool""".replace('\n', '').replace('|', '\n') expected_hostvars = """{"hostname1": {"uuid": "00000000-0000-0000-0000-000000000002", "driver": "agent_ipmitool", - "name": "hostname1", "ipv4_address": "192.168.1.3", "ansible_ssh_host": + "name": "hostname1", "ipv4_address": "192.168.1.3", + "provisioning_ipv4_address": "192.168.1.3" ,"ansible_ssh_host": "192.168.1.3", "driver_info": {"power": {"ipmi_address": "192.0.2.3", "ipmi_password": "undefined", "ipmi_username": "root", "ipmi_target_address": null, "ipmi_target_channel": null, @@ -49,7 +50,8 @@ unused,,00000000-0000-0000-0000-000000000002,hostname1, [{"mac": "00:01:02:03:04:06"}], "properties": {"ram": "8192", "cpu_arch": "x86_64", "disk_size": "1024", "cpus": "2"}}, "hostname0": {"uuid": "00000000-0000-0000-0000-000000000001", "driver": "agent_ssh", - "name": "hostname0", "ipv4_address": "192.168.1.2", "ansible_ssh_host": + "name": "hostname0", "ipv4_address": "192.168.1.2", + "provisioning_ipv4_address": "192.168.1.2", "ansible_ssh_host": "192.168.1.2", "driver_info": {"power": {"ssh_virt_type": "virsh", "ssh_key_filename": "/home/ironic/.ssh/id_rsa", "ssh_username": "ironic", "ssh_port": 22, "ssh_address": "192.0.2.2"}}, "nics": @@ -69,7 +71,8 @@ unused,,00000000-0000-0000-0000-000000000002,hostname1, expected_hostvars = """{"hostname1": {"uuid": "00000000-0000-0000-0000-000000000002", "driver": "agent_ipmitool", - "name": "hostname1", "ipv4_address": "192.168.1.3", "ansible_ssh_host": + "name": "hostname1", "ipv4_address": "192.168.1.3", + "provisioning_ipv4_address": "192.168.1.3", "ansible_ssh_host": "192.168.1.3", "driver_info": {"power": {"ipmi_address": "192.0.2.3", "ipmi_password": "undefined", "ipmi_username": "root", "ipmi_target_address": "20", "ipmi_target_channel": "10", @@ -92,7 +95,8 @@ unused,,00000000-0000-0000-0000-000000000002,hostname1, expected_hostvars = """{"hostname1": {"uuid": "00000000-0000-0000-0000-000000000002", "driver": "agent_ipmitool", - "name": "hostname1", "ipv4_address": "192.168.1.3", "ansible_ssh_host": + "name": "hostname1", "ipv4_address": "192.168.1.3", + "provisioning_ipv4_address": "192.168.1.3", "ansible_ssh_host": "192.168.1.3", "driver_info": {"power": {"ipmi_address": "192.0.2.3", "ipmi_password": "undefined", "ipmi_username": "root", "ipmi_target_address": "20", "ipmi_target_channel": "10", @@ -112,6 +116,7 @@ unused,,00000000-0000-0000-0000-000000000002,hostname1 expected_hostvars = """{"hostname1": {"uuid": "00000000-0000-0000-0000-000000000002", "driver": "agent_ipmitool", "name": "hostname1", "addressing_mode": "dhcp", "ipv4_address": null, + "provisioning_ipv4_address": null, "driver_info": {"power": {"ipmi_address": "192.0.2.3", "ipmi_password": "undefined", "ipmi_username": "root", "ipmi_target_address": null, "ipmi_target_channel": null, "ipmi_transit_address": null, @@ -134,6 +139,7 @@ unused,,00000000-0000-0000-0000-000000000002,hostname1 expected_hostvars = """{"hostname1": {"uuid": "00000000-0000-0000-0000-000000000002", "driver": "agent_ipmitool", "name": "hostname1", "addressing_mode": "dhcp", "ipv4_address": null, + "provisioning_ipv4_address": null, "driver_info": {"power": {"ipmi_address": "192.0.2.3", "ipmi_password": "undefined", "ipmi_username": "root", "ipmi_target_address": null, "ipmi_target_channel": null, "ipmi_transit_address": null, @@ -157,7 +163,8 @@ unused,,00000000-0000-0000-0000-000000000002,hostname1, expected_hostvars = """{"hostname1": {"uuid": "00000000-0000-0000-0000-000000000002", "driver": "agent_ipmitool", "name": "hostname1", "ipv4_address": "192.168.1.3", "ansible_ssh_host": - "192.168.1.3", "driver_info": {"power": {"ipmi_address": "192.0.2.3", + "192.168.1.3", "provisioning_ipv4_address": "192.168.1.3", + "driver_info": {"power": {"ipmi_address": "192.0.2.3", "ipmi_password": "undefined", "ipmi_username": "root", "ipmi_target_address": null, "ipmi_target_channel": null, "ipmi_transit_address": null, "ipmi_transit_channel": null}}, "nics": @@ -165,7 +172,8 @@ unused,,00000000-0000-0000-0000-000000000002,hostname1, "x86_64", "disk_size": "1024", "cpus": "2"}}, "hostname0": {"uuid": "00000000-0000-0000-0000-000000000001", "driver": "agent_ssh", "name": "hostname0", "ipv4_address": "192.168.1.2", "ansible_ssh_host": - "192.168.1.2", "driver_info": {"power": {"ssh_virt_type": "virsh", + "192.168.1.2", "provisioning_ipv4_address": "192.168.1.2", + "driver_info": {"power": {"ssh_virt_type": "virsh", "ssh_key_filename": "/home/ironic/.ssh/id_rsa", "ssh_username": "ironic", "ssh_port": 22, "ssh_address": "192.0.2.2"}}, "nics": [{"mac": "00:01:02:03:04:05"}], "properties": {"ram": "8192", @@ -184,7 +192,8 @@ unused,,00000000-0000-0000-0000-000000000002,hostname1, expected_hostvars = """{"hostname1": {"uuid": "00000000-0000-0000-0000-000000000002", "driver": "agent_ipmitool", "name": "hostname1", "ipv4_address": "192.168.1.3", "ansible_ssh_host": - "192.168.1.3", "driver_info": {"power": {"ipmi_address": "192.0.2.3", + "192.168.1.3", "provisioning_ipv4_address": "192.168.1.3", + "driver_info": {"power": {"ipmi_address": "192.0.2.3", "ipmi_password": "undefined", "ipmi_username": "root", "ipmi_target_address": null, "ipmi_target_channel": null, "ipmi_transit_address": null, "ipmi_transit_channel": null}}, "nics": @@ -192,7 +201,8 @@ unused,,00000000-0000-0000-0000-000000000002,hostname1, "x86_64", "disk_size": "1024", "cpus": "2"}}, "hostname0": {"uuid": "00000000-0000-0000-0000-000000000001", "driver": "agent_ssh", "name": "hostname0", "ipv4_address": "192.168.1.2", "ansible_ssh_host": - "192.168.1.2", "driver_info": {"power": {"ssh_virt_type": "virsh", + "192.168.1.2", "provisioning_ipv4_address": "192.168.1.2", + "driver_info": {"power": {"ssh_virt_type": "virsh", "ssh_key_filename": "/home/ironic/.ssh/id_rsa", "ssh_username": "ironic", "ssh_port": 22, "ssh_address": "192.0.2.2"}}, "nics": [{"mac": "00:01:02:03:04:05"}], "properties": {"ram": "8192", diff --git a/playbooks/roles/bifrost-deploy-nodes-dynamic/README.md b/playbooks/roles/bifrost-deploy-nodes-dynamic/README.md index e159d32ff..dee5a0816 100644 --- a/playbooks/roles/bifrost-deploy-nodes-dynamic/README.md +++ b/playbooks/roles/bifrost-deploy-nodes-dynamic/README.md @@ -56,10 +56,28 @@ instance_info: A dictionary containing the information to define an instance. expected are image_source, image_checksum, root_gb, however, any supported key/value can be submitted to the API. -inventory_dhcp: A boolean value, defaulted to false, which causes the role - to update a template file and reload dhsmasq upon each update - in order to perform static dhcp assignments utilizing the - ipv4_address parameter. + +inventory_dhcp: A boolean value, defaulted to false, which allows dnsmasq + to configure the IP of the machines, rather than putting + the IP configuration of the machine in the config drive. + If set to true, the role will create a file for each machine + under /etc/dnsmasq.d/bifrost.dhcp-hosts.d containing the mac, + name of the machine, lease time and optionally the IP address + that will be offered to the machine by DHCP. + This optional IP is controlled by the inventory_dhcp_static_ip + parameter. + +inventory_dhcp_static_ip: A boolean value, defaulted to true, which configures + the mechanism for setting up the IP of machines when + inventory_dhcp is enabled. + If set to true, it will read the value of the key + 'provisioning_ipv4_address' from the inventory section + of each machine and dnsmasq will assign that IP to each + machine accordingly. Note, that if you don't assign + the key 'provisioning_ipv4_address' it will default + to the value of 'ipv4_address'. + If set to false, dnsmasq will assign IPs + automatically from the configured DHCP range. noauth_mode: Controls if the module is called in noauth mode. By default, this is the standard mode of operation, @@ -67,7 +85,6 @@ noauth_mode: Controls if the module is called in noauth mode. which expects a clouds.yml file. More information about this file format can be found at: http://docs.openstack.org/developer/os-client-config/ - Dependencies ------------ diff --git a/playbooks/roles/bifrost-deploy-nodes-dynamic/defaults/main.yml b/playbooks/roles/bifrost-deploy-nodes-dynamic/defaults/main.yml index 6a78bae81..2e6d89579 100644 --- a/playbooks/roles/bifrost-deploy-nodes-dynamic/defaults/main.yml +++ b/playbooks/roles/bifrost-deploy-nodes-dynamic/defaults/main.yml @@ -8,5 +8,6 @@ http_boot_folder: "/httpboot" deploy_image_filename: "deployment_image.qcow2" deploy_image: "{{http_boot_folder}}/{{deploy_image_filename}}" inventory_dhcp: false +inventory_dhcp_static_ip: true deploy_url_protocol: "http" noauth_mode: true diff --git a/playbooks/roles/bifrost-deploy-nodes-dynamic/templates/dhcp-host.j2 b/playbooks/roles/bifrost-deploy-nodes-dynamic/templates/dhcp-host.j2 index fef151525..da4b107be 100644 --- a/playbooks/roles/bifrost-deploy-nodes-dynamic/templates/dhcp-host.j2 +++ b/playbooks/roles/bifrost-deploy-nodes-dynamic/templates/dhcp-host.j2 @@ -1,2 +1,6 @@ # This file is managed by bifrost -{{ nics[0]['mac'] }},{{ipv4_address}},{{name}},12h +{% if inventory_dhcp_static_ip %} +{{ nics[0]['mac'] }},{{provisioning_ipv4_address}},{{name}},12h +{% else %} +{{ nics[0]['mac'] }},{{name}},12h +{% endif %} diff --git a/releasenotes/notes/inventory_dhcp_provisioning_ipv4_address-d2779f1abc38324a.yaml b/releasenotes/notes/inventory_dhcp_provisioning_ipv4_address-d2779f1abc38324a.yaml new file mode 100644 index 000000000..ac50d417f --- /dev/null +++ b/releasenotes/notes/inventory_dhcp_provisioning_ipv4_address-d2779f1abc38324a.yaml @@ -0,0 +1,16 @@ +--- +features: + - + The inventory_dhcp feature permits configuration + of dnsmasq to provide the IP configuration on + servers deployed by Bifrost, rather than setting + that information into the config drive. + Previously, the feature assumed the IP set by + dnsmasq was both the provisioning and the + management IP, but on some scenarios that is + not always the case. + With the inclusion of the inventory_dhcp_static_ip + option a user can provide an specific provisioning + IP via the JSON/YAML/CSV inventory in a server by + server basis, which will be used just for the + provisioning.