From 5304c0a48951283c0f04cd8df88bcb84a5e724ae Mon Sep 17 00:00:00 2001 From: Mark Goddard Date: Fri, 1 Sep 2017 18:09:02 +0000 Subject: [PATCH] Add a data store for ironic inspector introspection data In environments without Swift we are currently unable to store hardware introspection data. The inspection_store container runs an nginx server that supports a restricted Swift-like HTTP API using WebDAV that supports upload and retrieval of introspection data. --- ansible/group_vars/all/inspector | 11 +++++ ansible/inspection-store.yml | 16 ++++++++ ansible/kolla-openstack.yml | 7 ++++ ansible/overcloud-extras.yml | 1 + ansible/roles/inspection-store/README.md | 37 +++++++++++++++++ .../roles/inspection-store/defaults/main.yml | 37 +++++++++++++++++ .../roles/inspection-store/handlers/main.yml | 15 +++++++ .../roles/inspection-store/tasks/config.yml | 17 ++++++++ .../roles/inspection-store/tasks/deploy.yml | 3 ++ .../roles/inspection-store/tasks/destroy.yml | 29 ++++++++++++++ ansible/roles/inspection-store/tasks/main.yml | 2 + ansible/roles/inspection-store/tasks/pull.yml | 10 +++++ .../inspection-store/tasks/reconfigure.yml | 2 + .../roles/inspection-store/tasks/start.yml | 15 +++++++ .../roles/inspection-store/tasks/upgrade.yml | 3 ++ .../inspection-store/templates/nginx.conf | 40 +++++++++++++++++++ .../roles/kolla-openstack/defaults/main.yml | 7 ++++ .../templates/ironic-inspector.conf.j2 | 13 ++++++ etc/kayobe/inspector.yml | 11 +++++ 19 files changed, 276 insertions(+) create mode 100644 ansible/inspection-store.yml create mode 100644 ansible/roles/inspection-store/README.md create mode 100644 ansible/roles/inspection-store/defaults/main.yml create mode 100644 ansible/roles/inspection-store/handlers/main.yml create mode 100644 ansible/roles/inspection-store/tasks/config.yml create mode 100644 ansible/roles/inspection-store/tasks/deploy.yml create mode 100644 ansible/roles/inspection-store/tasks/destroy.yml create mode 100644 ansible/roles/inspection-store/tasks/main.yml create mode 100644 ansible/roles/inspection-store/tasks/pull.yml create mode 100644 ansible/roles/inspection-store/tasks/reconfigure.yml create mode 100644 ansible/roles/inspection-store/tasks/start.yml create mode 100644 ansible/roles/inspection-store/tasks/upgrade.yml create mode 100644 ansible/roles/inspection-store/templates/nginx.conf diff --git a/ansible/group_vars/all/inspector b/ansible/group_vars/all/inspector index 6c04a3c05..55e63e8be 100644 --- a/ansible/group_vars/all/inspector +++ b/ansible/group_vars/all/inspector @@ -316,3 +316,14 @@ inspector_rules: "{{ inspector_rules_default + inspector_rules_extra }}" # Ansible group containing switch hosts to which the workaround should be # applied. inspector_dell_switch_lldp_workaround_group: + +############################################################################### +# Inspection store configuration. +# The inspection store provides a Swift-like service for storing inspection +# data which may be useful in environments without Swift. + +# Whether the inspection data store is enabled. +inspector_store_enabled: "{{ not kolla_enable_swift | bool }}" + +# Port on which the inspection data store should listen. +inspector_store_port: 8080 diff --git a/ansible/inspection-store.yml b/ansible/inspection-store.yml new file mode 100644 index 000000000..84e19c388 --- /dev/null +++ b/ansible/inspection-store.yml @@ -0,0 +1,16 @@ +--- +# Deploy/pull/reconfigure/upgrade inspection data store. +# +# Follows kolla-ansible service deployment patterns. +# +# Variables: +# action: One of deploy, destroy, pull, reconfigure, upgrade + +- name: Ensure inspection store is deployed + hosts: controllers[0] + roles: + - role: inspection-store + inspection_store_enabled: "{{ inspector_store_enabled }}" + inspection_store_port: "{{ inspector_store_port }}" + # FIXME: Use kayobe_config_path? + inspection_store_config_path: "/etc/kayobe/inspection-store" diff --git a/ansible/kolla-openstack.yml b/ansible/kolla-openstack.yml index 0b596b6a9..485e4ce72 100644 --- a/ansible/kolla-openstack.yml +++ b/ansible/kolla-openstack.yml @@ -161,6 +161,13 @@ kolla_inspector_enable_discovery: "{{ inspector_enable_discovery }}" kolla_inspector_discovery_enroll_node_driver: "{{ inspector_discovery_enroll_node_driver }}" kolla_inspector_extra_kernel_options: "{{ inspector_extra_kernel_options }}" + # Ironic inspector swift store configuration. Currently only supports the + # 'fake' inspection store. + kolla_inspector_enable_swift: "{{ inspector_store_enabled }}" + kolla_inspector_swift_auth: + auth_type: token_endpoint + url: "http://{% raw %}{{ api_interface_address }}{% endraw %}:{{ inspector_store_port }}" + token: fake-token # Ironic inspector's dnsmasq configuration. kolla_inspector_dhcp_pool_start: "{{ inspection_net_name | net_inspection_allocation_pool_start }}" kolla_inspector_dhcp_pool_end: "{{ inspection_net_name | net_inspection_allocation_pool_end }}" diff --git a/ansible/overcloud-extras.yml b/ansible/overcloud-extras.yml index eba51d530..bc2dadd9c 100644 --- a/ansible/overcloud-extras.yml +++ b/ansible/overcloud-extras.yml @@ -8,4 +8,5 @@ # action: One of deploy, destroy, pull, reconfigure, upgrade - include: docker-registry.yml +- include: inspection-store.yml - include: opensm.yml diff --git a/ansible/roles/inspection-store/README.md b/ansible/roles/inspection-store/README.md new file mode 100644 index 000000000..67c40dda3 --- /dev/null +++ b/ansible/roles/inspection-store/README.md @@ -0,0 +1,37 @@ +Inspection Store +================ + +Ironic inspector can make use of Swift to store introspection data. Not all +OpenStack deployments feature Swift, so it may be useful to provide a minimal +HTTP interface that emulates Swift for storing ironic inspector's introspection +data. This role deploys such an interface using nginx. Note that no +authentication mechanism is provided. + +Requirements +------------ + +Docker engine should be running on the target system. + +Role Variables +-------------- + +Dependencies +------------ + +The `docker-py` python package is required on the target system. + +Example Playbook +---------------- + +The following playbook deploys an inspection store. + + --- + - hosts: all + + roles: + - role: inspection-store + +Author Information +------------------ + +- Mark Goddard () diff --git a/ansible/roles/inspection-store/defaults/main.yml b/ansible/roles/inspection-store/defaults/main.yml new file mode 100644 index 000000000..e89ed9082 --- /dev/null +++ b/ansible/roles/inspection-store/defaults/main.yml @@ -0,0 +1,37 @@ +--- +# Roughly follows kolla-ansible's service deployment patterns. + +# Whether an inspection store is enabled. +inspection_store_enabled: true + +# Service deployment definition. +inspection_store_services: + inspection_store: + container_name: inspection_store + enabled: "{{ inspection_store_enabled }}" + image: "{{ inspection_store_image_full }}" + ports: + - "{{ inspection_store_port }}:80" + volumes: + - "/etc/localtime:/etc/localtime:ro" + - "{{ inspection_store_config_path }}/nginx.conf:/etc/nginx/nginx.conf:ro" + - "inspection_store:/data" + +# The port on which the inspection store server should listen. +inspection_store_port: 8080 + +# Path in which to store inspection store server configuration. +inspection_store_config_path: "/etc/inspection-store" + +#################### +# Inspection Store +#################### +# NOTE: Namespace 'library' causes image task to always be changed and +# container to never update to new images. +inspection_store_namespace: "" +inspection_store_image: "{{ inspection_store ~ '/' if inspection_store | default else '' }}{{ inspection_store_namespace ~ '/' if inspection_store_namespace else '' }}nginx" +inspection_store_tag: "latest" +inspection_store_image_full: "{{ inspection_store_image }}:{{ inspection_store_tag }}" + +inspection_store_restart_policy: "unless-stopped" +inspection_store_restart_retries: 10 diff --git a/ansible/roles/inspection-store/handlers/main.yml b/ansible/roles/inspection-store/handlers/main.yml new file mode 100644 index 000000000..6f52517ea --- /dev/null +++ b/ansible/roles/inspection-store/handlers/main.yml @@ -0,0 +1,15 @@ +--- +- name: Restart inspection store container + docker_container: + name: "{{ item.value.container_name }}" + state: started + restart: True + with_dict: "{{ inspection_store_services }}" + when: item.value.enabled + +- name: Ensure inspection store data directory exists + command: > + docker exec {{ inspection_store_services.inspection_store.container_name }} + bash -c "mkdir -p /data/ironic-inspector && + chown nginx:nginx /data/ironic-inspector" + when: inspection_store_services.inspection_store.enabled diff --git a/ansible/roles/inspection-store/tasks/config.yml b/ansible/roles/inspection-store/tasks/config.yml new file mode 100644 index 000000000..b854b3ee2 --- /dev/null +++ b/ansible/roles/inspection-store/tasks/config.yml @@ -0,0 +1,17 @@ +--- +- name: Ensure inspection store configuration path exists + file: + path: "{{ inspection_store_config_path }}" + state: directory + owner: "{{ ansible_env.USER }}" + group: "{{ ansible_env.USER }}" + mode: 0750 + become: True + +- name: Ensure inspection store server is configured + template: + src: nginx.conf + dest: "{{ inspection_store_config_path }}/nginx.conf" + notify: + - Restart inspection store container + - Ensure inspection store data directory exists diff --git a/ansible/roles/inspection-store/tasks/deploy.yml b/ansible/roles/inspection-store/tasks/deploy.yml new file mode 100644 index 000000000..65966076b --- /dev/null +++ b/ansible/roles/inspection-store/tasks/deploy.yml @@ -0,0 +1,3 @@ +--- +- include: config.yml +- include: start.yml diff --git a/ansible/roles/inspection-store/tasks/destroy.yml b/ansible/roles/inspection-store/tasks/destroy.yml new file mode 100644 index 000000000..15f37fd4a --- /dev/null +++ b/ansible/roles/inspection-store/tasks/destroy.yml @@ -0,0 +1,29 @@ +--- +- name: Ensure inspection store container is stopped + docker_container: + name: "{{ item.value.container_name }}" + state: "absent" + with_dict: "{{ inspection_store_services }}" + +- name: Check whether inspection store volumes are present + command: docker volume inspect {{ volume }} + changed_when: False + with_subelements: + - "{{ inspection_store_services }}" + - volumes + when: "'/' not in volume" + failed_when: + - volume_result.rc != 0 + - "'No such volume' not in volume_result.stderr" + vars: + volume: "{{ item.1.split(':')[0] }}" + register: volume_result + +- name: Ensure inspection store volumes are absent + command: docker volume rm {{ volume }} + with_items: "{{ volume_result.results }}" + when: + - not item | skipped + - item.rc == 0 + vars: + volume: "{{ item.item.1.split(':')[0] }}" diff --git a/ansible/roles/inspection-store/tasks/main.yml b/ansible/roles/inspection-store/tasks/main.yml new file mode 100644 index 000000000..b017e8b4a --- /dev/null +++ b/ansible/roles/inspection-store/tasks/main.yml @@ -0,0 +1,2 @@ +--- +- include: "{{ action }}.yml" diff --git a/ansible/roles/inspection-store/tasks/pull.yml b/ansible/roles/inspection-store/tasks/pull.yml new file mode 100644 index 000000000..5c0fa23e7 --- /dev/null +++ b/ansible/roles/inspection-store/tasks/pull.yml @@ -0,0 +1,10 @@ +--- +- name: Pulling inspection store container image + docker_image: + name: "{{ item.value.image }}" + repository: "{{ item.value.image }}" + state: present + with_dict: "{{ inspection_store_services }}" + when: + - item.value.enabled + - action != 'destroy' diff --git a/ansible/roles/inspection-store/tasks/reconfigure.yml b/ansible/roles/inspection-store/tasks/reconfigure.yml new file mode 100644 index 000000000..e078ef131 --- /dev/null +++ b/ansible/roles/inspection-store/tasks/reconfigure.yml @@ -0,0 +1,2 @@ +--- +- include: deploy.yml diff --git a/ansible/roles/inspection-store/tasks/start.yml b/ansible/roles/inspection-store/tasks/start.yml new file mode 100644 index 000000000..9f4889b4b --- /dev/null +++ b/ansible/roles/inspection-store/tasks/start.yml @@ -0,0 +1,15 @@ +--- +- name: Ensure inspection store container is running + docker_container: + image: "{{ item.value.image }}" + name: "{{ item.value.container_name }}" + ports: "{{ item.value.ports | default(omit) }}" + privileged: "{{ item.value.privileged | default(omit) }}" + read_only: "{{ item.value.read_only | default(omit) }}" + restart_policy: "{{ inspection_store_restart_policy }}" + restart_retries: "{{ inspection_store_restart_retries }}" + state: "{{ item.value.enabled | ternary('started', 'absent') }}" + volumes: "{{ item.value.volumes }}" + with_dict: "{{ inspection_store_services }}" + notify: + - Ensure inspection store data directory exists diff --git a/ansible/roles/inspection-store/tasks/upgrade.yml b/ansible/roles/inspection-store/tasks/upgrade.yml new file mode 100644 index 000000000..8459b03ca --- /dev/null +++ b/ansible/roles/inspection-store/tasks/upgrade.yml @@ -0,0 +1,3 @@ +--- +- include: pull.yml +- include: deploy.yml diff --git a/ansible/roles/inspection-store/templates/nginx.conf b/ansible/roles/inspection-store/templates/nginx.conf new file mode 100644 index 000000000..41d958dd5 --- /dev/null +++ b/ansible/roles/inspection-store/templates/nginx.conf @@ -0,0 +1,40 @@ +user nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + server { + listen 80; + root /data; + location /ironic-inspector { + return 200 ""; + } + location /ironic-inspector/ { + dav_methods PUT DELETE; + } + } +} diff --git a/ansible/roles/kolla-openstack/defaults/main.yml b/ansible/roles/kolla-openstack/defaults/main.yml index 5213ae165..fddb868d4 100644 --- a/ansible/roles/kolla-openstack/defaults/main.yml +++ b/ansible/roles/kolla-openstack/defaults/main.yml @@ -163,6 +163,13 @@ kolla_inspector_ipa_kernel_path: # Mutually exclusive with kolla_inspector_ipa_ramdisk_upstream_url. kolla_inspector_ipa_ramdisk_path: +# Whether to enable the Swift introspection data store. +kolla_inspector_enable_swift: + +# Dict of authentication parameters for accessing the Swift introspection data +# store. +kolla_inspector_swift_auth: {} + # Free form extra configuration to append to ironic-inspector.conf. kolla_extra_inspector: diff --git a/ansible/roles/kolla-openstack/templates/ironic-inspector.conf.j2 b/ansible/roles/kolla-openstack/templates/ironic-inspector.conf.j2 index c312e8b6f..372143a0b 100644 --- a/ansible/roles/kolla-openstack/templates/ironic-inspector.conf.j2 +++ b/ansible/roles/kolla-openstack/templates/ironic-inspector.conf.j2 @@ -27,7 +27,20 @@ always_store_ramdisk_logs = True {% if kolla_inspector_enable_discovery %} # Enable discovery when nodes do not exist in Ironic. node_not_found_hook = enroll +{% endif %} +{% if kolla_inspector_enable_swift %} +store_data = swift +{% endif %} + +{% if kolla_inspector_enable_swift %} +[swift] +{% for key, value in kolla_inspector_swift_auth.items() %} +{{ key }} = {{ value }} +{% endfor %} +{% endif %} + +{% if kolla_inspector_enable_discovery %} [discovery] # The driver with which to enroll newly discovered nodes in Ironic. enroll_node_driver = {{ kolla_inspector_discovery_enroll_node_driver }} diff --git a/etc/kayobe/inspector.yml b/etc/kayobe/inspector.yml index 3bbb5ac7e..12ab7e5aa 100644 --- a/etc/kayobe/inspector.yml +++ b/etc/kayobe/inspector.yml @@ -109,6 +109,17 @@ # applied. #inspector_dell_switch_lldp_workaround_group: +############################################################################### +# Inspection store configuration. +# The inspection store provides a Swift-like service for storing inspection +# data which may be useful in environments without Swift. + +# Whether the inspection data store is enabled. +#inspector_store_enabled: + +# Port on which the inspection data store should listen. +#inspector_store_port: + ############################################################################### # Dummy variable to allow Ansible to accept this file. workaround_ansible_issue_8743: yes