Optimize reconfigure action for glance

Partically-implements: blueprint better-reconfigure
Change-Id: I89e30e8b87f24a621c521d915842a4af0042d6fe
This commit is contained in:
Jeffrey Zhang 2016-09-25 20:13:54 +08:00
parent c3073f216f
commit d37da2cfa9
12 changed files with 207 additions and 154 deletions

View File

@ -33,6 +33,7 @@ options:
required: True required: True
type: str type: str
choices: choices:
- compare_container
- compare_image - compare_image
- create_volume - create_volume
- get_container_env - get_container_env
@ -40,6 +41,7 @@ options:
- pull_image - pull_image
- remove_container - remove_container
- remove_volume - remove_volume
- recreate_or_restart_container
- restart_container - restart_container
- start_container - start_container
- stop_container - stop_container
@ -267,6 +269,12 @@ class DockerWorker(object):
return None return None
return self.dc.inspect_container(self.params.get('name')) return self.dc.inspect_container(self.params.get('name'))
def compare_container(self):
container = self.check_container()
if not container or self.check_container_differs():
self.changed = True
return self.changed
def check_container_differs(self): def check_container_differs(self):
container_info = self.get_container_info() container_info = self.get_container_info()
return ( return (
@ -554,6 +562,21 @@ class DockerWorker(object):
options = self.build_container_options() options = self.build_container_options()
self.dc.create_container(**options) self.dc.create_container(**options)
def recreate_or_restart_container(self):
self.changed = True
container = self.check_container()
# get config_strategy from env
environment = self.params.get('environment')
config_strategy = environment.get('KOLLA_CONFIG_STRATEGY')
if not container:
self.start_container()
elif container and config_strategy == 'COPY_ONCE':
self.remove_container()
self.start_container()
elif container and config_strategy == 'COPY_ALWAYS':
self.restart_container()
def start_container(self): def start_container(self):
if not self.check_image(): if not self.check_image():
self.pull_image() self.pull_image()
@ -651,16 +674,14 @@ class DockerWorker(object):
def generate_module(): def generate_module():
argument_spec = dict( argument_spec = dict(
common_options=dict(required=False, type='dict', default=dict()), common_options=dict(required=False, type='dict', default=dict()),
action=dict(required=True, type='str', choices=['compare_image', action=dict(required=True, type='str',
'create_volume', choices=['compare_container', 'compare_image',
'get_container_env', 'create_volume', 'get_container_env',
'get_container_state', 'get_container_state', 'pull_image',
'pull_image', 'recreate_or_restart_container',
'remove_container', 'remove_container', 'remove_volume',
'remove_volume', 'restart_container', 'start_container',
'restart_container', 'stop_container']),
'start_container',
'stop_container']),
api_version=dict(required=False, type='str', default='auto'), api_version=dict(required=False, type='str', default='auto'),
auth_email=dict(required=False, type='str'), auth_email=dict(required=False, type='str'),
auth_password=dict(required=False, type='str'), auth_password=dict(required=False, type='str'),

View File

@ -1,8 +1,26 @@
--- ---
project_name: "glance" project_name: "glance"
glance_service_groups:
- { name: glance_api, service: glance-api, group: glance-api } glance_services:
- { name: glance_registry, service: glance-registry, group: glance-registry } glance-api:
container_name: glance_api
group: glance-api
enabled: true
image: "{{ glance_api_image_full }}"
volumes:
- "{{ node_config_directory }}/glance-api/:{{ container_config_directory }}/:ro"
- "/etc/localtime:/etc/localtime:ro"
- "glance:/var/lib/glance/"
- "kolla_logs:/var/log/kolla/"
glance-registry:
container_name: glance_registry
group: glance-registry
enabled: true
image: "{{ glance_registry_image_full }}"
volumes:
- "{{ node_config_directory }}/glance-registry/:{{ container_config_directory }}/:ro"
- "/etc/localtime:/etc/localtime:ro"
- "kolla_logs:/var/log/kolla/"
#################### ####################

View File

@ -0,0 +1,46 @@
---
- name: Restart glance-api container
vars:
service_name: "glance-api"
service: "{{ glance_services[service_name] }}"
config_json: "{{ glance_config_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}"
glance_conf: "{{ glance_confs.results|selectattr('item.key', 'equalto', service_name)|first }}"
policy_json: "{{ glance_policy_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}"
glance_api_container: "{{ check_glance_containers.results|selectattr('item.key', 'equalto', service_name)|first }}"
kolla_docker:
action: "recreate_or_restart_container"
common_options: "{{ docker_common_options }}"
name: "{{ service.container_name }}"
image: "{{ service.image }}"
volumes: "{{ service.volumes }}"
when:
- inventory_hostname in groups[service.group]
- service.enabled | bool
- config_json.changed | bool
or glance_conf.changed | bool
or policy_json.changed | bool
or glance_api_container.changed | bool
- name: Restart glance-registry container
vars:
service_name: "glance-registry"
service: "{{ glance_services[service_name] }}"
config_json: "{{ glance_config_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}"
glance_conf: "{{ glance_confs.results|selectattr('item.key', 'equalto', service_name)|first }}"
policy_json: "{{ glance_policy_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}"
glance_registry_container: "{{ check_glance_containers.results|selectattr('item.key', 'equalto', service_name)|first }}"
kolla_docker:
action: "recreate_or_restart_container"
common_options: "{{ docker_common_options }}"
name: "{{ service.container_name }}"
image: "{{ service.image }}"
volumes: "{{ service.volumes }}"
when:
- inventory_hostname in groups[service.group]
- service.enabled | bool
- config_json.changed | bool
or glance_conf.changed | bool
or policy_json.changed | bool
or glance_registry_container.changed | bool

View File

@ -1,5 +1,7 @@
--- ---
- name: Running Glance bootstrap container - name: Running Glance bootstrap container
vars:
glance_api: "{{ glance_services['glance-api'] }}"
kolla_docker: kolla_docker:
action: "start_container" action: "start_container"
common_options: "{{ docker_common_options }}" common_options: "{{ docker_common_options }}"
@ -7,15 +9,11 @@
environment: environment:
KOLLA_BOOTSTRAP: KOLLA_BOOTSTRAP:
KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}" KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
image: "{{ glance_api_image_full }}" image: "{{ glance_api.image }}"
labels: labels:
BOOTSTRAP: BOOTSTRAP:
name: "bootstrap_glance" name: "bootstrap_glance"
restart_policy: "never" restart_policy: "never"
volumes: volumes: "{{ glance_api.volumes }}"
- "{{ node_config_directory }}/glance-api/:{{ container_config_directory }}/:ro"
- "/etc/localtime:/etc/localtime:ro"
- "glance:/var/lib/glance/"
- "kolla_logs:/var/log/kolla/"
run_once: True run_once: True
delegate_to: "{{ groups['glance-api'][0] }}" delegate_to: "{{ groups[glance_api.group][0] }}"

View File

@ -1,34 +1,46 @@
--- ---
- name: Ensuring config directories exist - name: Ensuring config directories exist
file: file:
path: "{{ node_config_directory }}/{{ item.service }}" path: "{{ node_config_directory }}/{{ item.key }}"
state: "directory" state: "directory"
recurse: yes recurse: yes
when: inventory_hostname in groups[item.group] when: inventory_hostname in groups[item.value.group]
with_items: "{{ glance_service_groups }}" with_dict: "{{ glance_services }}"
- name: Copying over config.json files for services - name: Copying over config.json files for services
template: template:
src: "{{ item.service }}.json.j2" src: "{{ item.key }}.json.j2"
dest: "{{ node_config_directory }}/{{ item.service }}/config.json" dest: "{{ node_config_directory }}/{{ item.key }}/config.json"
when: inventory_hostname in groups[item.group] register: glance_config_jsons
with_items: "{{ glance_service_groups }}" when:
- item.value.enabled | bool
- inventory_hostname in groups[item.value.group]
with_dict: "{{ glance_services }}"
notify:
- Restart glance-api container
- Restart glance-registry container
- name: Copying over glance-*.conf - name: Copying over glance-*.conf
merge_configs: merge_configs:
vars: vars:
service_name: "{{ item.service }}" service_name: "{{ item.key }}"
sources: sources:
- "{{ role_path }}/templates/{{ item.service }}.conf.j2" - "{{ role_path }}/templates/{{ item.key }}.conf.j2"
- "{{ node_custom_config }}/global.conf" - "{{ node_custom_config }}/global.conf"
- "{{ node_custom_config }}/database.conf" - "{{ node_custom_config }}/database.conf"
- "{{ node_custom_config }}/messaging.conf" - "{{ node_custom_config }}/messaging.conf"
- "{{ node_custom_config }}/glance.conf" - "{{ node_custom_config }}/glance.conf"
- "{{ node_custom_config }}/glance/{{ item.service }}.conf" - "{{ node_custom_config }}/glance/{{ item.key }}.conf"
- "{{ node_custom_config }}/glance/{{ inventory_hostname }}/{{ item.service }}.conf" - "{{ node_custom_config }}/glance/{{ inventory_hostname }}/{{ item.key }}.conf"
dest: "{{ node_config_directory }}/{{ item.service }}/{{ item.service }}.conf" dest: "{{ node_config_directory }}/{{ item.key }}/{{ item.key }}.conf"
when: inventory_hostname in groups[item.group] register: glance_confs
with_items: "{{ glance_service_groups }}" when:
- item.value.enabled | bool
- inventory_hostname in groups[item.value.group]
with_dict: "{{ glance_services }}"
notify:
- Restart glance-api container
- Restart glance-registry container
- name: Check if policies shall be overwritten - name: Check if policies shall be overwritten
local_action: stat path="{{ node_custom_config }}/glance/policy.json" local_action: stat path="{{ node_custom_config }}/glance/policy.json"
@ -37,8 +49,28 @@
- name: Copying over existing policy.json - name: Copying over existing policy.json
template: template:
src: "{{ node_custom_config }}/glance/policy.json" src: "{{ node_custom_config }}/glance/policy.json"
dest: "{{ node_config_directory }}/{{ item.service }}/policy.json" dest: "{{ node_config_directory }}/{{ item.key }}/policy.json"
register: glance_policy_jsons
when: when:
- inventory_hostname in groups[item.group]
- glance_policy.stat.exists - glance_policy.stat.exists
with_items: "{{ glance_service_groups }}" - inventory_hostname in groups[item.value.group]
with_dict: "{{ glance_services }}"
notify:
- Restart glance-api container
- Restart glance-registry container
- name: Check glance containers
kolla_docker:
action: "compare_container"
common_options: "{{ docker_common_options }}"
name: "{{ item.value.container_name }}"
image: "{{ item.value.image }}"
volumes: "{{ item.value.volumes }}"
register: check_glance_containers
when:
- inventory_hostname in groups[item.value.group]
- item.value.enabled | bool
with_dict: "{{ glance_services }}"
notify:
- Restart glance-api container
- Restart glance-registry container

View File

@ -22,9 +22,8 @@
- include: bootstrap.yml - include: bootstrap.yml
when: inventory_hostname in groups['glance-api'] when: inventory_hostname in groups['glance-api']
- include: start.yml - name: Flush handlers
when: inventory_hostname in groups['glance-api'] or meta: flush_handlers
inventory_hostname in groups['glance-registry']
- include: check.yml - include: check.yml
when: inventory_hostname in groups['glance-api'] or when: inventory_hostname in groups['glance-api'] or

View File

@ -1,9 +1,7 @@
--- ---
- name: Get container facts - name: Get container facts
kolla_container_facts: kolla_container_facts:
name: name: "{{ glance_services.keys() }}"
- glance_api
- glance_registry
register: container_facts register: container_facts
- name: Checking free port for Glance API - name: Checking free port for Glance API
@ -13,7 +11,7 @@
connect_timeout: 1 connect_timeout: 1
state: stopped state: stopped
when: when:
- inventory_hostname in groups['glance-api'] - inventory_hostname in groups[glance_services['glance-api']['group']]
- container_facts['glance_api'] is not defined - container_facts['glance_api'] is not defined
- name: Checking free port for Glance Registry - name: Checking free port for Glance Registry
@ -23,5 +21,5 @@
connect_timeout: 1 connect_timeout: 1
state: stopped state: stopped
when: when:
- inventory_hostname in groups['glance-registry'] - inventory_hostname in groups[glance_services['glance-api']['group']]
- container_facts['glance_registry'] is not defined - container_facts['glance_registry'] is not defined

View File

@ -1,14 +1,10 @@
--- ---
- name: Pulling glance-api image - name: Pulling glance images
kolla_docker: kolla_docker:
action: "pull_image" action: "pull_image"
common_options: "{{ docker_common_options }}" common_options: "{{ docker_common_options }}"
image: "{{ glance_api_image_full }}" image: "{{ item.value.image }}"
when: inventory_hostname in groups['glance-api'] when:
- inventory_hostname in groups[item.value.group]
- name: Pulling glance-registry image - item.value.enabled | bool
kolla_docker: with_dict: "{{ glance_services }}"
action: "pull_image"
common_options: "{{ docker_common_options }}"
image: "{{ glance_registry_image_full }}"
when: inventory_hostname in groups['glance-registry']

View File

@ -1,63 +0,0 @@
---
- name: Ensuring the containers up
kolla_docker:
name: "{{ item.name }}"
action: "get_container_state"
register: container_state
failed_when: container_state.Running == false
when: inventory_hostname in groups[item.group]
with_items: "{{ glance_service_groups }}"
- include: config.yml
- name: Check the configs
command: docker exec {{ item.name }} /usr/local/bin/kolla_set_configs --check
changed_when: false
failed_when: false
register: check_results
when: inventory_hostname in groups[item.group]
with_items: "{{ glance_service_groups }}"
# NOTE(jeffrey4l): when config_strategy == 'COPY_ALWAYS'
# and container env['KOLLA_CONFIG_STRATEGY'] == 'COPY_ONCE',
# just remove the container and start again
- name: Containers config strategy
kolla_docker:
name: "{{ item.name }}"
action: "get_container_env"
register: container_envs
when: inventory_hostname in groups[item.group]
with_items: "{{ glance_service_groups }}"
- name: Remove the containers
kolla_docker:
name: "{{ item[0]['name'] }}"
action: "remove_container"
register: remove_containers
when:
- inventory_hostname in groups[item[0]['group']]
- config_strategy == "COPY_ONCE" or item[1]['KOLLA_CONFIG_STRATEGY'] == 'COPY_ONCE'
- item[2]['rc'] == 1
with_together:
- "{{ glance_service_groups }}"
- "{{ container_envs.results }}"
- "{{ check_results.results }}"
- include: bootstrap_service.yml
- include: start.yml
when: remove_containers.changed
- name: Restart containers
kolla_docker:
name: "{{ item[0]['name'] }}"
action: "restart_container"
when:
- inventory_hostname in groups[item[0]['group']]
- config_strategy == 'COPY_ALWAYS'
- item[1]['KOLLA_CONFIG_STRATEGY'] != 'COPY_ONCE'
- item[2]['rc'] == 1
with_together:
- "{{ glance_service_groups }}"
- "{{ container_envs.results }}"
- "{{ check_results.results }}"

View File

@ -0,0 +1 @@
deploy.yml

View File

@ -1,25 +0,0 @@
---
- name: Starting glance-registry container
kolla_docker:
action: "start_container"
common_options: "{{ docker_common_options }}"
image: "{{ glance_registry_image_full }}"
name: "glance_registry"
volumes:
- "{{ node_config_directory }}/glance-registry/:{{ container_config_directory }}/:ro"
- "/etc/localtime:/etc/localtime:ro"
- "kolla_logs:/var/log/kolla/"
when: inventory_hostname in groups['glance-registry']
- name: Starting glance-api container
kolla_docker:
action: "start_container"
common_options: "{{ docker_common_options }}"
image: "{{ glance_api_image_full }}"
name: "glance_api"
volumes:
- "{{ node_config_directory }}/glance-api/:{{ container_config_directory }}/:ro"
- "/etc/localtime:/etc/localtime:ro"
- "glance:/var/lib/glance/"
- "kolla_logs:/var/log/kolla/"
when: inventory_hostname in groups['glance-api']

View File

@ -3,4 +3,5 @@
- include: bootstrap_service.yml - include: bootstrap_service.yml
- include: start.yml - name: Flush handlers
meta: flush_handlers

View File

@ -43,16 +43,13 @@ class ModuleArgsTest(base.BaseTestCase):
argument_spec = dict( argument_spec = dict(
common_options=dict(required=False, type='dict', default=dict()), common_options=dict(required=False, type='dict', default=dict()),
action=dict( action=dict(
required=True, type='str', choices=['compare_image', required=True, type='str',
'create_volume', choices=['compare_container', 'compare_image', 'create_volume',
'get_container_env', 'get_container_env', 'get_container_state',
'get_container_state', 'pull_image', 'recreate_or_restart_container',
'pull_image', 'remove_container', 'remove_volume',
'remove_container', 'restart_container', 'start_container',
'remove_volume', 'stop_container']),
'restart_container',
'start_container',
'stop_container']),
api_version=dict(required=False, type='str', default='auto'), api_version=dict(required=False, type='str', default='auto'),
auth_email=dict(required=False, type='str'), auth_email=dict(required=False, type='str'),
auth_password=dict(required=False, type='str'), auth_password=dict(required=False, type='str'),
@ -372,6 +369,40 @@ class TestContainer(base.BaseTestCase):
self.dw.module.fail_json.assert_called_once_with( self.dw.module.fail_json.assert_called_once_with(
msg="No such container: fake_container") msg="No such container: fake_container")
def test_recreate_or_restart_container_not_container(self):
self.dw = get_DockerWorker({
'environment': dict(KOLLA_CONFIG_STRATEGY='COPY_ALWAYS')})
self.dw.check_container = mock.Mock(return_value=None)
self.dw.start_container = mock.Mock()
self.dw.recreate_or_restart_container()
self.dw.start_container.assert_called_once_with()
def test_recreate_or_restart_container_container_copy_always(self):
self.dw = get_DockerWorker({
'environment': dict(KOLLA_CONFIG_STRATEGY='COPY_ALWAYS')})
self.dw.check_container = mock.Mock(
return_value=self.fake_data['containers'][0])
self.dw.restart_container = mock.Mock()
self.dw.recreate_or_restart_container()
self.dw.restart_container.assert_called_once_with()
def test_recreate_or_restart_container_container_copy_once(self):
self.dw = get_DockerWorker({
'environment': dict(KOLLA_CONFIG_STRATEGY='COPY_ONCE')})
self.dw.check_container = mock.Mock(
return_value=self.fake_data['containers'][0])
self.dw.start_container = mock.Mock()
self.dw.remove_container = mock.Mock()
self.dw.recreate_or_restart_container()
self.dw.remove_container.assert_called_once_with()
self.dw.start_container.assert_called_once_with()
class TestImage(base.BaseTestCase): class TestImage(base.BaseTestCase):