Split config parameter to config, devices, profiles, source et al

This commit is contained in:
Hiroaki Nakamura 2016-06-28 22:52:40 +09:00 committed by Matt Clay
parent 776a748eb4
commit a0bf88f60a

View file

@ -32,26 +32,43 @@ options:
description: description:
- Name of a container. - Name of a container.
required: true required: true
architecture:
description:
- The archiecture for the container (e.g. "x86_64" or "i686").
See https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1
required: false
config: config:
description: description:
- A config dictionary for creating a container. - The config for the container (e.g. '{"limits.cpu": "2"}').
See https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1 See https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1
- Required when the container is not created yet and the state is - If the container already exists and its "config" value in metadata
not absent. obtained from
- If the container already exists and its metadata obtained from
GET /1.0/containers/<name> GET /1.0/containers/<name>
https://github.com/lxc/lxd/blob/master/doc/rest-api.md#10containersname https://github.com/lxc/lxd/blob/master/doc/rest-api.md#10containersname
are different, they this module tries to apply the configurations. are different, they this module tries to apply the configurations.
The following keys in config will be compared and applied. - The key starts with 'volatile.' are ignored for this comparison.
- architecture
- config
- The key starts with 'volatile.' are ignored for comparison.
- devices
- ephemeral
- profiles
- Not all config values are supported to apply the existing container. - Not all config values are supported to apply the existing container.
Maybe you need to delete and recreate a container. Maybe you need to delete and recreate a container.
required: false required: false
devices:
description:
- The devices for the container
(e.g. '{ "rootfs": { "path": "/dev/kvm", "type": "unix-char" }').
See https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1
required: false
ephemeral:
description:
- Whether or not the container is ephemeral (e.g. true or false).
See https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1
required: false
source:
description:
- The source for the container
(e.g. '{ "type": "image", "mode": "pull",
"server": "https://images.linuxcontainers.org", "protocol": "lxd",
"alias": "ubuntu/xenial/amd64" }').
See https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1
required: false
state: state:
choices: choices:
- started - started
@ -113,14 +130,13 @@ EXAMPLES = """
lxd_container: lxd_container:
name: mycontainer name: mycontainer
state: started state: started
config: source:
source: type: image
type: image mode: pull
mode: pull server: https://images.linuxcontainers.org
server: https://images.linuxcontainers.org protocol: lxd
protocol: lxd alias: "ubuntu/xenial/amd64"
alias: "ubuntu/xenial/amd64" profiles: ["default"]
profiles: ["default"]
- name: Install python in the created container "mycontainer" - name: Install python in the created container "mycontainer"
command: lxc exec mycontainer -- apt install -y python command: lxc exec mycontainer -- apt install -y python
- name: Copy /etc/hosts in the created container "mycontainer" to localhost with name "mycontainer-hosts" - name: Copy /etc/hosts in the created container "mycontainer" to localhost with name "mycontainer-hosts"
@ -144,14 +160,13 @@ EXAMPLES = """
lxd_container: lxd_container:
name: mycontainer name: mycontainer
state: stopped state: stopped
config: source:
source: type: image
type: image mode: pull
mode: pull server: https://images.linuxcontainers.org
server: https://images.linuxcontainers.org protocol: lxd
protocol: lxd alias: "ubuntu/xenial/amd64"
alias: "ubuntu/xenial/amd64" profiles: ["default"]
profiles: ["default"]
- hosts: localhost - hosts: localhost
connection: local connection: local
@ -160,14 +175,13 @@ EXAMPLES = """
lxd_container: lxd_container:
name: mycontainer name: mycontainer
state: restarted state: restarted
config: source:
source: type: image
type: image mode: pull
mode: pull server: https://images.linuxcontainers.org
server: https://images.linuxcontainers.org protocol: lxd
protocol: lxd alias: "ubuntu/xenial/amd64"
alias: "ubuntu/xenial/amd64" profiles: ["default"]
profiles: ["default"]
""" """
RETURN=""" RETURN="""
@ -257,7 +271,13 @@ class LxdContainerManagement(object):
""" """
self.module = module self.module = module
self.container_name = self.module.params['name'] self.container_name = self.module.params['name']
self.config = self.module.params.get('config', None)
self.container_config = {}
for attr in ['architecture', 'config', 'devices', 'ephemeral', 'profiles', 'source']:
param_val = self.module.params.get(attr, None)
if param_val is not None:
self.container_config[attr] = param_val
self.state = self.module.params['state'] self.state = self.module.params['state']
self.timeout = self.module.params['timeout'] self.timeout = self.module.params['timeout']
self.wait_for_ipv4_addresses = self.module.params['wait_for_ipv4_addresses'] self.wait_for_ipv4_addresses = self.module.params['wait_for_ipv4_addresses']
@ -296,13 +316,12 @@ class LxdContainerManagement(object):
def _operate_and_wait(self, method, path, body_json=None): def _operate_and_wait(self, method, path, body_json=None):
resp_json = self._send_request(method, path, body_json=body_json) resp_json = self._send_request(method, path, body_json=body_json)
if resp_json['type'] == 'async': if resp_json['type'] == 'async':
path = '{0}/wait?timeout={1}'.format(resp_json['operation'], self.timeout) url = '{0}/wait?timeout={1}'.format(resp_json['operation'], self.timeout)
resp_json = self._send_request('GET', path) resp_json = self._send_request('GET', url)
if resp_json['metadata']['status'] != 'Success': if resp_json['metadata']['status'] != 'Success':
url = self._path_to_url(path)
self.module.fail_json( self.module.fail_json(
msg='error response for waiting opearation', msg='error response for waiting opearation',
request={'method': method, 'url': url, 'json': body_json, 'timeout': self.timeout}, request={'method': method, 'url': url, 'timeout': self.timeout},
response={'json': resp_json}, response={'json': resp_json},
logs=self.logs logs=self.logs
) )
@ -333,10 +352,10 @@ class LxdContainerManagement(object):
return self._operate_and_wait('PUT', '/1.0/containers/{0}/state'.format(self.container_name), body_json=body_json) return self._operate_and_wait('PUT', '/1.0/containers/{0}/state'.format(self.container_name), body_json=body_json)
def _create_container(self): def _create_container(self):
config = self.config.copy() config = self.container_config.copy()
config['name'] = self.container_name config['name'] = self.container_name
self._operate_and_wait('POST', '/1.0/containers', config) self._operate_and_wait('POST', '/1.0/containers', config)
self.actions.append('creat') self.actions.append('create')
def _start_container(self): def _start_container(self):
self._change_state('start') self._change_state('start')
@ -453,13 +472,13 @@ class LxdContainerManagement(object):
self._freeze_container() self._freeze_container()
def _needs_to_change_config(self, key): def _needs_to_change_config(self, key):
if key not in self.config: if key not in self.container_config:
return False return False
if key == 'config': if key == 'config':
old_configs = dict((k, v) for k, v in self.old_container_json['metadata'][key].items() if not k.startswith('volatile.')) old_configs = dict((k, v) for k, v in self.old_container_json['metadata'][key].items() if not k.startswith('volatile.'))
else: else:
old_configs = self.old_container_json['metadata'][key] old_configs = self.old_container_json['metadata'][key]
return self.config[key] != old_configs return self.container_config[key] != old_configs
def _needs_to_apply_configs(self): def _needs_to_apply_configs(self):
return ( return (
@ -479,16 +498,16 @@ class LxdContainerManagement(object):
'profiles': old_metadata['profiles'] 'profiles': old_metadata['profiles']
} }
if self._needs_to_change_config('architecture'): if self._needs_to_change_config('architecture'):
body_json['architecture'] = self.config['architecture'] body_json['architecture'] = self.container_config['architecture']
if self._needs_to_change_config('config'): if self._needs_to_change_config('config'):
for k, v in self.config['config'].items(): for k, v in self.container_config['config'].items():
body_json['config'][k] = v body_json['config'][k] = v
if self._needs_to_change_config('ephemeral'): if self._needs_to_change_config('ephemeral'):
body_json['ephemeral'] = self.config['ephemeral'] body_json['ephemeral'] = self.container_config['ephemeral']
if self._needs_to_change_config('devices'): if self._needs_to_change_config('devices'):
body_json['devices'] = self.config['devices'] body_json['devices'] = self.container_config['devices']
if self._needs_to_change_config('profiles'): if self._needs_to_change_config('profiles'):
body_json['profiles'] = self.config['profiles'] body_json['profiles'] = self.container_config['profiles']
self._operate_and_wait('PUT', '/1.0/containers/{0}'.format(self.container_name), body_json=body_json) self._operate_and_wait('PUT', '/1.0/containers/{0}'.format(self.container_name), body_json=body_json)
self.actions.append('apply_configs') self.actions.append('apply_configs')
@ -522,9 +541,24 @@ def main():
type='str', type='str',
required=True required=True
), ),
architecture=dict(
type='str',
),
config=dict( config=dict(
type='dict', type='dict',
), ),
devices=dict(
type='dict',
),
ephemeral=dict(
type='bool',
),
profiles=dict(
type='list',
),
source=dict(
type='dict',
),
state=dict( state=dict(
choices=LXD_ANSIBLE_STATES.keys(), choices=LXD_ANSIBLE_STATES.keys(),
default='started' default='started'