aboutsummaryrefslogtreecommitdiff
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
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
-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
-rw-r--r--doc/ironic-guide.rst42
-rw-r--r--docker/ironic/ironic-api/Dockerfile.j27
-rwxr-xr-xdocker/ironic/ironic-api/start.sh13
-rw-r--r--docker/ironic/ironic-base/Dockerfile.j21
-rw-r--r--docker/ironic/ironic-conductor/Dockerfile.j27
-rw-r--r--docker/ironic/ironic-conductor/config-external.sh11
-rwxr-xr-xdocker/ironic/ironic-conductor/start.sh6
-rw-r--r--docker/ironic/ironic-discoverd/Dockerfile.j215
-rw-r--r--docker/ironic/ironic-discoverd/config-external.sh11
-rwxr-xr-xdocker/ironic/ironic-discoverd/start.sh6
-rw-r--r--docker/ironic/ironic-pxe/Dockerfile.j235
-rwxr-xr-xdocker/ironic/ironic-pxe/start.sh6
-rw-r--r--etc/kolla/config/discoverd.conf0
-rw-r--r--etc/kolla/config/ironic.conf0
-rw-r--r--etc/kolla/config/ironic/discoverd.conf0
-rw-r--r--etc/kolla/config/ironic/ironic-api.conf0
-rw-r--r--etc/kolla/config/ironic/ironic-conductor.conf0
-rw-r--r--etc/kolla/passwords.yml3
-rw-r--r--tests/test_build.py4
41 files changed, 592 insertions, 49 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 }
diff --git a/doc/ironic-guide.rst b/doc/ironic-guide.rst
new file mode 100644
index 000000000..da8795d63
--- /dev/null
+++ b/doc/ironic-guide.rst
@@ -0,0 +1,42 @@
+Ironic in Kolla
+===============
+
+Overview
+--------
+Currently Kolla can deploy the Ironic services:
+
+- ironic-api
+- ironic-conductor
+- ironic-discoverd
+
+As well as a required PXE service, deployed as ironic-pxe.
+
+Current status
+--------------
+The Ironic implementation is "tech preview", so currently instances can only be
+deployed on baremetal. Further work will be done to allow scheduling for both
+virtualized and baremetal deployments. Most probably at that time discoverd
+will be replaced by ironic-inspector.
+
+Post-deployment configuration
+-----------------------------
+Configuration based off upstream documentation_.
+
+Again, remember that enabling Ironic reconfigures nova compute (driver and
+scheduler) as well as changes neutron network settings. Further neutron setup
+is required as outlined below.
+
+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.
+
+.. _documentation: http://docs.openstack.org/developer/ironic/deploy/install-guide.html
diff --git a/docker/ironic/ironic-api/Dockerfile.j2 b/docker/ironic/ironic-api/Dockerfile.j2
index 112ff8b2d..016b3560b 100644
--- a/docker/ironic/ironic-api/Dockerfile.j2
+++ b/docker/ironic/ironic-api/Dockerfile.j2
@@ -4,15 +4,16 @@ MAINTAINER Kolla Project (https://launchpad.net/kolla)
{% if install_type == 'binary' %}
{% if base_distro in ['centos', 'fedora', 'oraclelinux', 'rhel'] %}
-RUN yum -y install \
- openstack-ironic-api \
+# Install delorean version even though version number is less
+# http://lists.openstack.org/pipermail/openstack-dev/2015-August/073100.html
+RUN VER_TO_GET=$(yum --showduplicates list openstack-ironic-api | awk '/delorean/ {print $2}') \
+ && yum -y install openstack-ironic-api-$VER_TO_GET \
&& yum clean all
{% endif %}
{% endif %}
COPY start.sh /
-COPY config-external.sh /opt/kolla/
CMD ["/start.sh"]
diff --git a/docker/ironic/ironic-api/start.sh b/docker/ironic/ironic-api/start.sh
index 9d449defb..60b3ea5a0 100755
--- a/docker/ironic/ironic-api/start.sh
+++ b/docker/ironic/ironic-api/start.sh
@@ -1,10 +1,13 @@
#!/bin/bash
set -o errexit
-CMD="/usr/bin/ironic-api"
-ARGS=""
-
source /opt/kolla/kolla-common.sh
-set_configs
-exec $CMD $ARGS
+# Bootstrap and exit if KOLLA_BOOTSTRAP variable is set. This catches all cases
+# of the KOLLA_BOOTSTRAP variable being set, including empty.
+if [[ "${!KOLLA_BOOTSTRAP[@]}" ]]; then
+ su -s /bin/sh -c "ironic-dbsync upgrade" ironic
+ exit 0
+fi
+
+exec $CMD
diff --git a/docker/ironic/ironic-base/Dockerfile.j2 b/docker/ironic/ironic-base/Dockerfile.j2
index 2f8207c0e..bb05d2dd7 100644
--- a/docker/ironic/ironic-base/Dockerfile.j2
+++ b/docker/ironic/ironic-base/Dockerfile.j2
@@ -10,6 +10,7 @@ RUN yum -y install \
python-oslo-log \
python-oslo-concurrency \
python-oslo-policy \
+ python-oslo-versionedobjects \
&& yum clean all
{% endif %}
diff --git a/docker/ironic/ironic-conductor/Dockerfile.j2 b/docker/ironic/ironic-conductor/Dockerfile.j2
index f62f7b7a0..7fe401b4d 100644
--- a/docker/ironic/ironic-conductor/Dockerfile.j2
+++ b/docker/ironic/ironic-conductor/Dockerfile.j2
@@ -4,15 +4,16 @@ MAINTAINER Kolla Project (https://launchpad.net/kolla)
{% if install_type == 'binary' %}
{% if base_distro in ['centos', 'fedora', 'oraclelinux', 'rhel'] %}
-RUN yum -y install \
- openstack-ironic-conductor \
+# Install delorean version even though version number is less
+# http://lists.openstack.org/pipermail/openstack-dev/2015-August/073100.html
+RUN VER_TO_GET=$(yum --showduplicates list openstack-ironic-conductor | awk '/delorean/ {print $2}') \
+ && yum -y install openstack-ironic-conductor-$VER_TO_GET \
&& yum clean all
{% endif %}
{% endif %}
COPY start.sh /
-COPY config-external.sh /opt/kolla/
CMD ["/start.sh"]
diff --git a/docker/ironic/ironic-conductor/config-external.sh b/docker/ironic/ironic-conductor/config-external.sh
deleted file mode 100644
index b838ee19d..000000000
--- a/docker/ironic/ironic-conductor/config-external.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-SOURCE="/opt/kolla/ironic-api/ironic.conf"
-TARGET="/etc/ironic/ironic.conf"
-OWNER="ironic"
-
-if [[ -f "$SOURCE" ]]; then
- cp $SOURCE $TARGET
- chown ${OWNER}: $TARGET
- chmod 0644 $TARGET
-fi
diff --git a/docker/ironic/ironic-conductor/start.sh b/docker/ironic/ironic-conductor/start.sh
index c766f04c5..e6b7c5bb5 100755
--- a/docker/ironic/ironic-conductor/start.sh
+++ b/docker/ironic/ironic-conductor/start.sh
@@ -1,10 +1,6 @@
#!/bin/bash
set -o errexit
-CMD="/usr/bin/ironic-conductor"
-ARGS=""
-
source /opt/kolla/kolla-common.sh
-set_configs
-exec $CMD $ARGS
+exec $CMD
diff --git a/docker/ironic/ironic-discoverd/Dockerfile.j2 b/docker/ironic/ironic-discoverd/Dockerfile.j2
index 1843cb24c..5e15c8d58 100644
--- a/docker/ironic/ironic-discoverd/Dockerfile.j2
+++ b/docker/ironic/ironic-discoverd/Dockerfile.j2
@@ -4,15 +4,22 @@ MAINTAINER Kolla Project (https://launchpad.net/kolla)
{% if install_type == 'binary' %}
{% if base_distro in ['centos', 'fedora', 'oraclelinux', 'rhel'] %}
-RUN yum -y install \
- openstack-ironic-discoverd \
- && yum clean all
+RUN pip install ironic-discoverd
+# discoverd no longer in delorean 9/28/2015, switch to inspector on TODO
+#RUN yum -y install \
+# openstack-ironic-discoverd \
+# && yum clean all
{% endif %}
+
+{% elif install_type == 'source' %}
+
+RUN echo '{{ install_type }} not yet available for {{ base_distro }}' \
+ && /bin/false
+
{% endif %}
COPY start.sh /
-COPY config-external.sh /opt/kolla/
CMD ["/start.sh"]
diff --git a/docker/ironic/ironic-discoverd/config-external.sh b/docker/ironic/ironic-discoverd/config-external.sh
deleted file mode 100644
index a3f82b8f3..000000000
--- a/docker/ironic/ironic-discoverd/config-external.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-SOURCE="/opt/kolla/ironic-discoverd/discoverd.conf"
-TARGET="/etc/ironic-discoverd/discoverd.conf"
-OWNER="ironic"
-
-if [[ -f "$SOURCE" ]]; then
- cp $SOURCE $TARGET
- chown ${OWNER}: $TARGET
- chmod 0644 $TARGET
-fi
diff --git a/docker/ironic/ironic-discoverd/start.sh b/docker/ironic/ironic-discoverd/start.sh
index 093dc517a..e6b7c5bb5 100755
--- a/docker/ironic/ironic-discoverd/start.sh
+++ b/docker/ironic/ironic-discoverd/start.sh
@@ -1,10 +1,6 @@
#!/bin/bash
set -o errexit
-CMD="/usr/bin/ironic-discoverd"
-ARGS=""
-
source /opt/kolla/kolla-common.sh
-set_configs
-exec $CMD $ARGS
+exec $CMD
diff --git a/docker/ironic/ironic-pxe/Dockerfile.j2 b/docker/ironic/ironic-pxe/Dockerfile.j2
new file mode 100644
index 000000000..d4484d1db
--- /dev/null
+++ b/docker/ironic/ironic-pxe/Dockerfile.j2
@@ -0,0 +1,35 @@
+FROM {{ namespace }}/{{ base_distro }}-{{ install_type }}-base:{{ tag }}
+MAINTAINER Kolla Project (https://launchpad.net/kolla)
+
+{% if install_type == 'binary' %}
+ {% if base_distro in ['centos', 'fedora', 'oraclelinux', 'rhel'] %}
+
+RUN yum -y install tftp-server syslinux-tftpboot \
+ && yum clean all
+
+# PXE configuration
+RUN mkdir -p /tftpboot \
+ && cp /var/lib/tftpboot/chain.c32 /tftpboot \
+ && echo 're ^(/tftpboot/) /tftpboot/\2' > /tftpboot/map-file \
+ && echo 're ^/tftpboot/ /tftpboot/' >> /tftpboot/map-file \
+ && echo 're ^(^/) /tftpboot/\1' >> /tftpboot/map-file \
+ && echo 're ^([^/]) /tftpboot/\1' >> /tftpboot/map-file
+
+ {% elif base_distro in ['ubuntu', 'debian'] %}
+RUN echo '{{ install_type }} not yet available for {{ base_distro }}' \
+ && /bin/false
+
+ {% endif %}
+
+{% elif install_type == 'source' %}
+
+RUN echo '{{ install_type }} not yet available for {{ base_distro }}' \
+ && /bin/false
+
+{% endif %}
+
+COPY start.sh /
+
+CMD ["/start.sh"]
+
+{{ include_footer }}
diff --git a/docker/ironic/ironic-pxe/start.sh b/docker/ironic/ironic-pxe/start.sh
new file mode 100755
index 000000000..e6b7c5bb5
--- /dev/null
+++ b/docker/ironic/ironic-pxe/start.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -o errexit
+
+source /opt/kolla/kolla-common.sh
+
+exec $CMD
diff --git a/etc/kolla/config/discoverd.conf b/etc/kolla/config/discoverd.conf
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/etc/kolla/config/discoverd.conf
diff --git a/etc/kolla/config/ironic.conf b/etc/kolla/config/ironic.conf
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/etc/kolla/config/ironic.conf
diff --git a/etc/kolla/config/ironic/discoverd.conf b/etc/kolla/config/ironic/discoverd.conf
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/etc/kolla/config/ironic/discoverd.conf
diff --git a/etc/kolla/config/ironic/ironic-api.conf b/etc/kolla/config/ironic/ironic-api.conf
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/etc/kolla/config/ironic/ironic-api.conf
diff --git a/etc/kolla/config/ironic/ironic-conductor.conf b/etc/kolla/config/ironic/ironic-conductor.conf
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/etc/kolla/config/ironic/ironic-conductor.conf
diff --git a/etc/kolla/passwords.yml b/etc/kolla/passwords.yml
index b50ddd3dd..04a30e797 100644
--- a/etc/kolla/passwords.yml
+++ b/etc/kolla/passwords.yml
@@ -53,6 +53,9 @@ heat_domain_admin_password: "password"
murano_database_password: "password"
murano_keystone_password: "password"
+ironic_database_password: "password"
+ironic_keystone_password: "password"
+
####################
# RabbitMQ options
diff --git a/tests/test_build.py b/tests/test_build.py
index a58327a51..8feb98d00 100644
--- a/tests/test_build.py
+++ b/tests/test_build.py
@@ -39,7 +39,9 @@ class BuildTest(base.BaseTestCase):
# these are images that are known to not build properly
excluded_images = ["gnocchi-base",
- "murano-base"]
+ "murano-base",
+ "ironic-pxe",
+ "ironic-discoverd"]
failures = 0
for image, result in bad_results.iteritems():