aboutsummaryrefslogtreecommitdiff
path: root/ansible
diff options
context:
space:
mode:
authorJeff Peeler <jpeeler@redhat.com>2015-08-28 11:26:40 -0400
committerJeff Peeler <jpeeler@redhat.com>2015-09-28 16:10:43 -0400
commitf5a50a1d7d40fb39bbc503ab1079e89e4aafe3fe (patch)
treefd734b1ab909a3c9e06be5cce1eae160f2b5d692 /ansible
parent40f9f0816f8f94b4d11012a39af21d50195f9a74 (diff)
downloadkolla-f5a50a1d7d40fb39bbc503ab1079e89e4aafe3fe.tar.gz
kolla-f5a50a1d7d40fb39bbc503ab1079e89e4aafe3fe.zip
Add Ansible support for Ironic
Configuration based off upstream documentation here: http://docs.openstack.org/developer/ironic/deploy/install-guide.html A few notes: -ironic-api is not configured to use mod_wsgi -several places it's noted that discoverd is going away and needs to be replaced with ironic-inspector - (sqlite connection should be changed too) -currently enabling ironic reconfigures nova compute (driver and scheduler) as well as changes neutron network settings -a nice enhancement would be to configure the web console Required post-deployment configuration: Create the flat network to launch the instances: neutron net-create --tenant-id $TENANT_ID sharednet1 --shared \ --provider:network_type flat --provider:physical_network physnet1 neutron subnet-create sharednet1 $NETWORK_CIDR --name $SUBNET_NAME \ --ip-version=4 --gateway=$GATEWAY_IP --allocation-pool \ start=$START_IP,end=$END_IP --enable-dhcp And then the above ID is used to set cleaning_network_uuid in the neutron section of ironic.conf. Change-Id: I572e7ff1f23c4e57a2c50817cafe9269fd9950dd Implements: blueprint ironic-container
Diffstat (limited to 'ansible')
-rw-r--r--ansible/group_vars/all.yml5
-rw-r--r--ansible/inventory/all-in-one15
-rw-r--r--ansible/inventory/multinode16
-rw-r--r--ansible/roles/haproxy/templates/haproxy.cfg.j28
-rw-r--r--ansible/roles/ironic/defaults/main.yml42
-rw-r--r--ansible/roles/ironic/meta/main.yml3
-rw-r--r--ansible/roles/ironic/tasks/bootstrap.yml64
-rw-r--r--ansible/roles/ironic/tasks/config.yml78
-rw-r--r--ansible/roles/ironic/tasks/main.yml8
-rw-r--r--ansible/roles/ironic/tasks/register.yml37
-rw-r--r--ansible/roles/ironic/tasks/start.yml77
-rw-r--r--ansible/roles/ironic/templates/discoverd.conf.j211
-rw-r--r--ansible/roles/ironic/templates/ironic-api.json.j211
-rw-r--r--ansible/roles/ironic/templates/ironic-conductor.json.j211
-rw-r--r--ansible/roles/ironic/templates/ironic-discoverd.json.j211
-rw-r--r--ansible/roles/ironic/templates/ironic-pxe.json.j24
-rw-r--r--ansible/roles/ironic/templates/ironic.conf.j230
-rw-r--r--ansible/roles/neutron/tasks/ironic-check.yml4
-rw-r--r--ansible/roles/neutron/tasks/main.yml3
-rw-r--r--ansible/roles/neutron/templates/ml2_conf.ini.j210
-rw-r--r--ansible/roles/nova/templates/nova.conf.j222
-rwxr-xr-xansible/site.yml4
22 files changed, 473 insertions, 1 deletions
diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml
index a7f7c408e..3f3072d1c 100644
--- a/ansible/group_vars/all.yml
+++ b/ansible/group_vars/all.yml
@@ -104,6 +104,9 @@ heat_api_cfn_port: "8000"
murano_api_port: "8082"
+ironic_api_port: "6385"
+
+
####################
# Openstack options
####################
@@ -146,7 +149,9 @@ enable_heat: "yes"
enable_horizon: "yes"
enable_swift: "no"
enable_murano: "no"
+enable_ironic: "no"
+ironic_keystone_user: "ironic"
####################
# RabbitMQ options
diff --git a/ansible/inventory/all-in-one b/ansible/inventory/all-in-one
index d820c3e60..ab6eceeb2 100644
--- a/ansible/inventory/all-in-one
+++ b/ansible/inventory/all-in-one
@@ -60,6 +60,8 @@ control
[ceph-osd:children]
storage
+[ironic:children]
+control
# Additional control implemented here. These groups allow you to control which
# services run on which hosts at a per-service level.
@@ -140,3 +142,16 @@ murano
[murano-engine:children]
murano
+
+# Ironic
+[ironic-api:children]
+ironic
+
+[ironic-conductor:children]
+ironic
+
+[ironic-discoverd:children]
+ironic
+
+[ironic-pxe:children]
+ironic
diff --git a/ansible/inventory/multinode b/ansible/inventory/multinode
index e677fcaef..cc643be11 100644
--- a/ansible/inventory/multinode
+++ b/ansible/inventory/multinode
@@ -62,6 +62,9 @@ control
[murano:children]
control
+[ironic:children]
+control
+
[ceph-mon:children]
control
@@ -148,3 +151,16 @@ murano
[murano-engine:children]
murano
+
+# Ironic
+[ironic-api:children]
+ironic
+
+[ironic-conductor:children]
+ironic
+
+[ironic-discoverd:children]
+ironic
+
+[ironic-pxe:children]
+ironic
diff --git a/ansible/roles/haproxy/templates/haproxy.cfg.j2 b/ansible/roles/haproxy/templates/haproxy.cfg.j2
index 637cb1ce1..0c8d59c91 100644
--- a/ansible/roles/haproxy/templates/haproxy.cfg.j2
+++ b/ansible/roles/haproxy/templates/haproxy.cfg.j2
@@ -141,3 +141,11 @@ listen heat_api_cfn
server {{ hostvars[host]['ansible_hostname'] }} {{ hostvars[host]['ansible_' + api_interface]['ipv4']['address'] }}:{{ heat_api_cfn_port }} check inter 2000 rise 2 fall 5
{% endfor %}
{% endif %}
+
+{% if enable_ironic | bool %}
+listen ironic_api
+ bind {{ kolla_internal_address}}:{{ ironic_api_port }}
+{% for host in groups['ironic-api'] %}
+ server {{ hostvars[host]['ansible_hostname'] }} {{ hostvars[host]['ansible_' + api_interface]['ipv4']['address'] }}:{{ ironic_api_port }} check inter 2000 rise 2 fall 5
+{% endfor %}
+{% endif %}
diff --git a/ansible/roles/ironic/defaults/main.yml b/ansible/roles/ironic/defaults/main.yml
new file mode 100644
index 000000000..8a9ee32cd
--- /dev/null
+++ b/ansible/roles/ironic/defaults/main.yml
@@ -0,0 +1,42 @@
+---
+project_name: "ironic"
+
+####################
+# Database
+####################
+ironic_database_name: "ironic"
+ironic_database_user: "ironic"
+ironic_database_address: "{{ kolla_internal_address }}"
+
+
+####################
+# Docker
+####################
+ironic_api_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ kolla_install_type }}-ironic-api"
+ironic_api_tag: "{{ openstack_release }}"
+ironic_api_image_full: "{{ ironic_api_image }}:{{ ironic_api_tag }}"
+
+ironic_conductor_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ kolla_install_type }}-ironic-conductor"
+ironic_conductor_tag: "{{ openstack_release }}"
+ironic_conductor_image_full: "{{ ironic_conductor_image }}:{{ ironic_conductor_tag }}"
+
+ironic_discoverd_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ kolla_install_type }}-ironic-discoverd"
+ironic_discoverd_tag: "{{ openstack_release }}"
+ironic_discoverd_image_full: "{{ ironic_discoverd_image }}:{{ ironic_discoverd_tag }}"
+
+ironic_pxe_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ kolla_install_type }}-ironic-pxe"
+ironic_pxe_tag: "{{ openstack_release }}"
+ironic_pxe_image_full: "{{ ironic_pxe_image }}:{{ ironic_pxe_tag }}"
+
+
+####################
+# Openstack
+####################
+ironic_public_address: "{{ kolla_external_address }}"
+ironic_admin_address: "{{ kolla_internal_address }}"
+ironic_internal_address: "{{ kolla_internal_address }}"
+
+ironic_logging_verbose: "{{ openstack_logging_verbose }}"
+ironic_logging_debug: "{{ openstack_logging_debug }}"
+
+openstack_ironic_auth: "{'auth_url':'{{ openstack_auth_v2.auth_url }}','username':'{{ openstack_auth_v2.username }}','password':'{{ openstack_auth_v2.password }}','project_name':'{{ openstack_auth_v2.project_name }}'}"
diff --git a/ansible/roles/ironic/meta/main.yml b/ansible/roles/ironic/meta/main.yml
new file mode 100644
index 000000000..6b4fff8fe
--- /dev/null
+++ b/ansible/roles/ironic/meta/main.yml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - { role: common }
diff --git a/ansible/roles/ironic/tasks/bootstrap.yml b/ansible/roles/ironic/tasks/bootstrap.yml
new file mode 100644
index 000000000..2f99cf59f
--- /dev/null
+++ b/ansible/roles/ironic/tasks/bootstrap.yml
@@ -0,0 +1,64 @@
+---
+- name: Creating Ironic database
+ command: docker exec -t kolla_ansible /usr/bin/ansible localhost
+ -m mysql_db
+ -a "login_host='{{ database_address }}'
+ login_port='{{ mariadb_port }}'
+ login_user='{{ database_user }}'
+ login_password='{{ database_password }}'
+ name='{{ ironic_database_name }}'"
+ register: database
+ changed_when: "{{ database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
+ failed_when: database.stdout.split()[2] != 'SUCCESS'
+ run_once: True
+
+- name: Creating Ironic database user and setting permissions
+ command: docker exec -t kolla_ansible /usr/bin/ansible localhost
+ -m mysql_user
+ -a "login_host='{{ database_address }}'
+ login_port='{{ mariadb_port }}'
+ login_user='{{ database_user }}'
+ login_password='{{ database_password }}'
+ name='{{ ironic_database_name }}'
+ password='{{ ironic_database_password }}'
+ host='%'
+ priv='{{ ironic_database_name }}.*:ALL'
+ append_privs='yes'"
+ register: database_user_create
+ changed_when: "{{ database.stdout.find('localhost | SUCCESS => ') != -1 and (database_user_create.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
+ failed_when: database_user_create.stdout.split()[2] != 'SUCCESS'
+ run_once: True
+
+- name: Starting Ironic bootstrap container
+ docker:
+ detach: False
+ docker_api_version: "{{ docker_api_version }}"
+ net: host
+ pull: "{{ docker_pull_policy }}"
+ restart_policy: "no"
+ state: reloaded
+ registry: "{{ docker_registry }}"
+ username: "{{ docker_registry_username }}"
+ password: "{{ docker_registry_password }}"
+ insecure_registry: "{{ docker_insecure_registry }}"
+ name: bootstrap_ironic
+ image: "{{ ironic_api_image_full }}"
+ volumes: "{{ node_config_directory }}/ironic-api/:/opt/kolla/config_files/:ro"
+ env:
+ KOLLA_BOOTSTRAP:
+ KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
+ run_once: True
+ when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
+
+# https://github.com/ansible/ansible-modules-core/pull/1031
+- name: Waiting for Ironic bootstrap container to exit
+ command: docker wait bootstrap_ironic
+ run_once: True
+ when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
+
+- name: Cleaning up boostrap container
+ docker:
+ name: bootstrap_ironic
+ image: "{{ ironic_api_image_full }}"
+ state: absent
+ when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
diff --git a/ansible/roles/ironic/tasks/config.yml b/ansible/roles/ironic/tasks/config.yml
new file mode 100644
index 000000000..45a3f7ea5
--- /dev/null
+++ b/ansible/roles/ironic/tasks/config.yml
@@ -0,0 +1,78 @@
+---
+- include: ../../config.yml
+ vars:
+ service_name: "ironic-api"
+ config_source:
+ - "roles/ironic/templates/ironic.conf.j2"
+ - "/etc/kolla/config/global.conf"
+ - "/etc/kolla/config/database.conf"
+ - "/etc/kolla/config/messaging.conf"
+ - "/etc/kolla/config/{{ project_name }}.conf"
+ - "/etc/kolla/config/{{ project_name }}/{{ service_name }}.conf"
+ config_template_dest:
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ project_name }}.conf_minimal"
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ project_name }}.conf_global"
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ project_name }}.conf_database"
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ project_name }}.conf_messaging"
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ project_name }}.conf_augment"
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ service_name }}.conf_augment"
+ config_dest: "{{ node_config_directory }}/{{ service_name }}/ironic.conf"
+ when: inventory_hostname in groups['ironic-api']
+
+- name: Copying Ironic API JSON configuration file
+ template:
+ src: "roles/ironic/templates/ironic-api.json.j2"
+ dest: "{{ node_config_directory }}/ironic-api/config.json"
+
+- include: ../../config.yml
+ vars:
+ service_name: "ironic-conductor"
+ config_source:
+ - "roles/ironic/templates/ironic.conf.j2"
+ - "/etc/kolla/config/global.conf"
+ - "/etc/kolla/config/database.conf"
+ - "/etc/kolla/config/messaging.conf"
+ - "/etc/kolla/config/{{ project_name }}.conf"
+ - "/etc/kolla/config/{{ project_name }}/{{ service_name }}.conf"
+ config_template_dest:
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ project_name }}.conf_minimal"
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ project_name }}.conf_global"
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ project_name }}.conf_database"
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ project_name }}.conf_messaging"
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ project_name }}.conf_augment"
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ service_name }}.conf_augment"
+ config_dest: "{{ node_config_directory }}/{{ service_name }}/ironic.conf"
+ when: inventory_hostname in groups['ironic-conductor']
+
+- name: Copying Ironic conductor JSON configuration file
+ template:
+ src: "roles/ironic/templates/ironic-conductor.json.j2"
+ dest: "{{ node_config_directory }}/ironic-conductor/config.json"
+
+- include: ../../config.yml
+ vars:
+ service_name: "ironic-discoverd"
+ config_source:
+ - "roles/ironic/templates/discoverd.conf.j2"
+ - "/etc/kolla/config/global.conf"
+ - "/etc/kolla/config/database.conf"
+ - "/etc/kolla/config/messaging.conf"
+ - "/etc/kolla/config/{{ project_name }}/discoverd.conf"
+ config_template_dest:
+ - "{{ node_templates_directory }}/{{ service_name }}/discoverd.conf_minimal"
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ project_name }}.conf_global"
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ project_name }}.conf_database"
+ - "{{ node_templates_directory }}/{{ service_name }}/{{ project_name }}.conf_messaging"
+ - "{{ node_templates_directory }}/{{ service_name }}/discoverd.conf_augment"
+ config_dest: "{{ node_config_directory }}/{{ service_name }}/discoverd.conf"
+ when: inventory_hostname in groups['ironic-discoverd']
+
+- name: Copying Ironic discoverd JSON configuration file
+ template:
+ src: "roles/ironic/templates/ironic-discoverd.json.j2"
+ dest: "{{ node_config_directory }}/ironic-discoverd/config.json"
+
+- name: Copying Ironic PXE JSON configuration file
+ template:
+ src: "roles/ironic/templates/ironic-pxe.json.j2"
+ dest: "{{ node_config_directory }}/ironic-pxe/config.json"
diff --git a/ansible/roles/ironic/tasks/main.yml b/ansible/roles/ironic/tasks/main.yml
new file mode 100644
index 000000000..5c48120b7
--- /dev/null
+++ b/ansible/roles/ironic/tasks/main.yml
@@ -0,0 +1,8 @@
+---
+- include: register.yml
+
+- include: config.yml
+
+- include: bootstrap.yml
+
+- include: start.yml
diff --git a/ansible/roles/ironic/tasks/register.yml b/ansible/roles/ironic/tasks/register.yml
new file mode 100644
index 000000000..ce44210f2
--- /dev/null
+++ b/ansible/roles/ironic/tasks/register.yml
@@ -0,0 +1,37 @@
+---
+- name: Creating the Ironic service and endpoint
+ command: docker exec -t kolla_ansible /usr/bin/ansible localhost
+ -m kolla_keystone_service
+ -a "service_name=ironic
+ service_type=baremetal
+ description='Ironic bare metal provisioning service'
+ endpoint_region={{ openstack_region_name }}
+ admin_url='http://{{ ironic_admin_address }}:{{ ironic_api_port }}'
+ internal_url='http://{{ ironic_internal_address }}:{{ ironic_api_port }}'
+ public_url='http://{{ ironic_public_address }}:{{ ironic_api_port }}'
+ region_name={{ openstack_region_name }}
+ auth={{ '{{ openstack_ironic_auth }}' }}"
+ -e "{'openstack_ironic_auth':{{ openstack_ironic_auth }}}"
+ register: ironic_endpoint
+ changed_when: "{{ ironic_endpoint.stdout.find('localhost | SUCCESS => ') != -1 and (ironic_endpoint.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
+ until: ironic_endpoint.stdout.split()[2] == 'SUCCESS'
+ retries: 10
+ delay: 5
+ run_once: True
+
+- name: Creating the Ironic project, user, and role
+ command: docker exec -t kolla_ansible /usr/bin/ansible localhost
+ -m kolla_keystone_user
+ -a "project=service
+ user=ironic
+ password={{ ironic_keystone_password }}
+ role=admin
+ region_name={{ openstack_region_name }}
+ auth={{ '{{ openstack_ironic_auth }}' }}"
+ -e "{'openstack_ironic_auth':{{ openstack_ironic_auth }}}"
+ register: ironic_user
+ changed_when: "{{ ironic_user.stdout.find('localhost | SUCCESS => ') != -1 and (ironic_user.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
+ until: ironic_user.stdout.split()[2] == 'SUCCESS'
+ retries: 10
+ delay: 5
+ run_once: True
diff --git a/ansible/roles/ironic/tasks/start.yml b/ansible/roles/ironic/tasks/start.yml
new file mode 100644
index 000000000..4b6c5b453
--- /dev/null
+++ b/ansible/roles/ironic/tasks/start.yml
@@ -0,0 +1,77 @@
+---
+- name: Starting Ironic-api container
+ docker:
+ docker_api_version: "{{ docker_api_version }}"
+ net: host
+ pull: "{{ docker_pull_policy }}"
+ restart_policy: "{{ docker_restart_policy }}"
+ restart_policy_retry: "{{ docker_restart_policy_retry }}"
+ state: reloaded
+ registry: "{{ docker_registry }}"
+ username: "{{ docker_registry_username }}"
+ password: "{{ docker_registry_password }}"
+ insecure_registry: "{{ docker_insecure_registry }}"
+ name: ironic-api
+ image: "{{ ironic_api_image_full }}"
+ volumes: "{{ node_config_directory }}/ironic-api/:/opt/kolla/config_files/:ro"
+ env:
+ KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
+ when: inventory_hostname in groups['ironic-api']
+
+- name: Starting Ironic-conductor container
+ docker:
+ docker_api_version: "{{ docker_api_version }}"
+ net: host
+ pull: "{{ docker_pull_policy }}"
+ restart_policy: "{{ docker_restart_policy }}"
+ restart_policy_retry: "{{ docker_restart_policy_retry }}"
+ state: reloaded
+ registry: "{{ docker_registry }}"
+ username: "{{ docker_registry_username }}"
+ password: "{{ docker_registry_password }}"
+ insecure_registry: "{{ docker_insecure_registry }}"
+ name: ironic-conductor
+ image: "{{ ironic_conductor_image_full }}"
+ volumes: "{{ node_config_directory }}/ironic-conductor/:/opt/kolla/config_files/:ro"
+ env:
+ KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
+ when: inventory_hostname in groups['ironic-conductor']
+
+- name: Starting Ironic-discoverd container
+ docker:
+ docker_api_version: "{{ docker_api_version }}"
+ net: host
+ pull: "{{ docker_pull_policy }}"
+ restart_policy: "{{ docker_restart_policy }}"
+ restart_policy_retry: "{{ docker_restart_policy_retry }}"
+ state: reloaded
+ registry: "{{ docker_registry }}"
+ username: "{{ docker_registry_username }}"
+ password: "{{ docker_registry_password }}"
+ insecure_registry: "{{ docker_insecure_registry }}"
+ privileged: True
+ name: ironic-discoverd
+ image: "{{ ironic_discoverd_image_full }}"
+ volumes: "{{ node_config_directory }}/ironic-discoverd/:/opt/kolla/config_files/:ro"
+ env:
+ KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
+ when: inventory_hostname in groups['ironic-discoverd']
+
+- name: Starting Ironic-pxe container
+ docker:
+ docker_api_version: "{{ docker_api_version }}"
+ net: host
+ pull: "{{ docker_pull_policy }}"
+ restart_policy: "{{ docker_restart_policy }}"
+ restart_policy_retry: "{{ docker_restart_policy_retry }}"
+ state: reloaded
+ registry: "{{ docker_registry }}"
+ username: "{{ docker_registry_username }}"
+ password: "{{ docker_registry_password }}"
+ insecure_registry: "{{ docker_insecure_registry }}"
+ name: ironic-pxe
+ image: "{{ ironic_pxe_image_full }}"
+ volumes: "{{ node_config_directory }}/ironic-pxe/:/opt/kolla/config_files/:ro"
+ env:
+ KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
+ when: inventory_hostname in groups['ironic-pxe']
diff --git a/ansible/roles/ironic/templates/discoverd.conf.j2 b/ansible/roles/ironic/templates/discoverd.conf.j2
new file mode 100644
index 000000000..1f64d564a
--- /dev/null
+++ b/ansible/roles/ironic/templates/discoverd.conf.j2
@@ -0,0 +1,11 @@
+[discoverd]
+database = inspector.sqlite3
+os_auth_url = http://{{ kolla_internal_address }}:{{ keystone_public_port }}/v2.0
+os_username = {{ openstack_auth.username }}
+os_password = {{ openstack_auth.password }}
+os_tenant_name = {{ openstack_auth.project_name }}
+identity_uri = {{ openstack_auth.auth_url }}
+
+# Note: this will be in the firewall section once upgraded to inspector
+# unsure of the correct interface here
+dnsmasq_interface = {{ api_interface }}
diff --git a/ansible/roles/ironic/templates/ironic-api.json.j2 b/ansible/roles/ironic/templates/ironic-api.json.j2
new file mode 100644
index 000000000..dd2caadf4
--- /dev/null
+++ b/ansible/roles/ironic/templates/ironic-api.json.j2
@@ -0,0 +1,11 @@
+{
+ "command": "/usr/bin/ironic-api",
+ "config_files": [
+ {
+ "source": "/opt/kolla/config_files/ironic.conf",
+ "dest": "/etc/ironic/ironic.conf",
+ "owner": "ironic",
+ "perm": "0600"
+ }
+ ]
+}
diff --git a/ansible/roles/ironic/templates/ironic-conductor.json.j2 b/ansible/roles/ironic/templates/ironic-conductor.json.j2
new file mode 100644
index 000000000..e77781c11
--- /dev/null
+++ b/ansible/roles/ironic/templates/ironic-conductor.json.j2
@@ -0,0 +1,11 @@
+{
+ "command": "/usr/bin/ironic-conductor",
+ "config_files": [
+ {
+ "source": "/opt/kolla/config_files/ironic.conf",
+ "dest": "/etc/ironic/ironic.conf",
+ "owner": "ironic",
+ "perm": "0600"
+ }
+ ]
+}
diff --git a/ansible/roles/ironic/templates/ironic-discoverd.json.j2 b/ansible/roles/ironic/templates/ironic-discoverd.json.j2
new file mode 100644
index 000000000..a4dc91d56
--- /dev/null
+++ b/ansible/roles/ironic/templates/ironic-discoverd.json.j2
@@ -0,0 +1,11 @@
+{
+ "command": "/usr/bin/ironic-discoverd --config-file /etc/ironic-discoverd/discoverd.conf",
+ "config_files": [
+ {
+ "source": "/opt/kolla/config_files/discoverd.conf",
+ "dest": "/etc/ironic-discoverd/discoverd.conf",
+ "owner": "root",
+ "perm": "0600"
+ }
+ ]
+}
diff --git a/ansible/roles/ironic/templates/ironic-pxe.json.j2 b/ansible/roles/ironic/templates/ironic-pxe.json.j2
new file mode 100644
index 000000000..f8f1666e7
--- /dev/null
+++ b/ansible/roles/ironic/templates/ironic-pxe.json.j2
@@ -0,0 +1,4 @@
+{
+ "command": "/usr/sbin/in.tftpd --verbose --foreground --user root --address 0.0.0.0:69 --map-file /tftpboot/map-file /tftpboot",
+ "config_files": []
+}
diff --git a/ansible/roles/ironic/templates/ironic.conf.j2 b/ansible/roles/ironic/templates/ironic.conf.j2
new file mode 100644
index 000000000..6860aee12
--- /dev/null
+++ b/ansible/roles/ironic/templates/ironic.conf.j2
@@ -0,0 +1,30 @@
+[DEFAULT]
+debug = {{ ironic_logging_debug }}
+verbose = {{ ironic_logging_verbose }}
+
+admin_token = {{ keystone_admin_token }}
+
+[database]
+connection = mysql://{{ ironic_database_user }}:{{ ironic_database_password }}@{{ ironic_database_address }}/{{ ironic_database_name }}
+
+[keystone_authtoken]
+auth_uri = http://{{ kolla_internal_address }}:{{ keystone_public_port }}
+auth_url = http://{{ kolla_internal_address }}:{{ keystone_admin_port }}
+auth_plugin = password
+project_domain_id = default
+user_domain_id = default
+project_name = service
+username = {{ ironic_keystone_user }}
+password = {{ ironic_keystone_password }}
+
+[glance]
+glance_host = {{ kolla_internal_address }}
+
+[neutron]
+url = http://{{ kolla_internal_address }}:{{ neutron_server_port }}
+
+[oslo_messaging_rabbit]
+rabbit_host = {{ kolla_internal_address }}
+rabbit_userid = {{ rabbitmq_user }}
+rabbit_password = {{ rabbitmq_password }}
+rabbit_ha_queues = true
diff --git a/ansible/roles/neutron/tasks/ironic-check.yml b/ansible/roles/neutron/tasks/ironic-check.yml
new file mode 100644
index 000000000..f32a58a72
--- /dev/null
+++ b/ansible/roles/neutron/tasks/ironic-check.yml
@@ -0,0 +1,4 @@
+---
+# TODO(SamYaple): run verification checks at start of playbook
+- fail: msg="neutron_plugin_agent must use openvswitch with Ironic"
+ when: enable_ironic | bool and neutron_plugin_agent != "openvswitch"
diff --git a/ansible/roles/neutron/tasks/main.yml b/ansible/roles/neutron/tasks/main.yml
index 5c48120b7..3ff224469 100644
--- a/ansible/roles/neutron/tasks/main.yml
+++ b/ansible/roles/neutron/tasks/main.yml
@@ -1,4 +1,7 @@
---
+# enforce ironic usage only with openvswtich
+- include: ironic-check.yml
+
- include: register.yml
- include: config.yml
diff --git a/ansible/roles/neutron/templates/ml2_conf.ini.j2 b/ansible/roles/neutron/templates/ml2_conf.ini.j2
index 92ec89c87..18816147f 100644
--- a/ansible/roles/neutron/templates/ml2_conf.ini.j2
+++ b/ansible/roles/neutron/templates/ml2_conf.ini.j2
@@ -1,8 +1,14 @@
# ml2_conf.ini
[ml2]
+{% if enable_ironic | bool %}
+type_drivers = flat
+tenant_network_types = flat
+mechanism_drivers = openvswitch
+{% else %}
# Changing type_drivers after bootstrap can lead to database inconsistencies
type_drivers = flat,vlan,vxlan
tenant_network_types = vxlan
+{% endif %}
{% if neutron_plugin_agent == "openvswitch" %}
mechanism_drivers = openvswitch,l2population
@@ -11,7 +17,11 @@ mechanism_drivers = linuxbridge,l2population
{% endif %}
[ml2_type_vlan]
+{% if enable_ironic | bool %}
+network_vlan_ranges = physnet1
+{% else %}
network_vlan_ranges =
+{% endif %}
[ml2_type_flat]
flat_networks = physnet1
diff --git a/ansible/roles/nova/templates/nova.conf.j2 b/ansible/roles/nova/templates/nova.conf.j2
index 28be05408..a07751261 100644
--- a/ansible/roles/nova/templates/nova.conf.j2
+++ b/ansible/roles/nova/templates/nova.conf.j2
@@ -30,7 +30,6 @@ linuxnet_interface_driver = nova.network.linux_net.LinuxOVSInterfaceDriver
linuxnet_interface_driver = nova.network.linux_net.BridgeInterfaceDriver
{% endif %}
-compute_driver = libvirt.LibvirtDriver
allow_resize_to_same_host = true
# Though my_ip is not used directly, lots of other variables use $my_ip
@@ -46,6 +45,27 @@ novncproxy_port = {{ nova_novncproxy_port }}
novncproxy_base_url = http://{{ kolla_internal_address }}:{{ nova_novncproxy_port }}/vnc_auto.html
{% endif %}
+{% if enable_ironic | bool %}
+compute_driver = nova.virt.ironic.IronicDriver
+scheduler_host_manager = nova.scheduler.ironic_host_manager.IronicHostManager
+ram_allocation_ratio = 1.0
+reserved_host_memory_mb = 0
+compute_manager = ironic.nova.compute.manager.ClusteredComputeManager
+scheduler_use_baremetal_filters = True
+{% else %}
+compute_driver = libvirt.LibvirtDriver
+{% endif %}
+
+{% if enable_ironic == 'yes' %}
+[ironic]
+#(TODO) remember to update this once discoverd is replaced by inspector
+admin_username = {{ ironic_keystone_user }}
+admin_password = {{ ironic_keystone_password }}
+admin_url = {{ openstack_auth.auth_url }}
+admin_tenant_name = {{ openstack_auth.project_name }}
+api_endpoint = http://{{ kolla_internal_address }}:{{ ironic_api_port }}/v1
+{% endif %}
+
[oslo_messaging_rabbit]
rabbit_host = {{ kolla_internal_address }}
rabbit_userid = {{ rabbitmq_user }}
diff --git a/ansible/site.yml b/ansible/site.yml
index 6f1236360..b31c6a546 100755
--- a/ansible/site.yml
+++ b/ansible/site.yml
@@ -51,3 +51,7 @@
- hosts: [murano-api, murano-engine]
roles:
- { role: murano, tags: murano, when: enable_murano | bool }
+
+- hosts: [ironic-api, ironic-conductor, ironic-discoverd, ironic-pxe]
+ roles:
+ - {role: ironic, tags: ironic, when: enable_ironic | bool }