mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
lxd_container: support lxd instance types (#3661)
* lxd_container: support lxd instance types Update the lxd_container module to enable the new LXD API endpoint, which supports different types of instances, such as containers and virtual machines. The type attributes can be set explicitly to create containers or virtual machines. * lxd_container: rename references from containers to instances * lxd_container: add an example of creating vms * lxd_container: update doc * lxd_container: fix pylint * resolve converstation * remove type from config * remove outdated validation related to the instance api * correct diff * changing last bits * add missing dot
This commit is contained in:
parent
fef02c0fba
commit
58eb94fff3
2 changed files with 150 additions and 100 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- lxd_container - adds ``type`` option which also allows to operate on virtual machines and not just containers (https://github.com/ansible-collections/community.general/pull/3661).
|
|
@ -11,29 +11,28 @@ __metaclass__ = type
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
---
|
---
|
||||||
module: lxd_container
|
module: lxd_container
|
||||||
short_description: Manage LXD Containers
|
short_description: Manage LXD instances
|
||||||
description:
|
description:
|
||||||
- Management of LXD containers
|
- Management of LXD containers and virtual machines.
|
||||||
author: "Hiroaki Nakamura (@hnakamur)"
|
author: "Hiroaki Nakamura (@hnakamur)"
|
||||||
options:
|
options:
|
||||||
name:
|
name:
|
||||||
description:
|
description:
|
||||||
- Name of a container.
|
- Name of an instance.
|
||||||
type: str
|
type: str
|
||||||
required: true
|
required: true
|
||||||
architecture:
|
architecture:
|
||||||
description:
|
description:
|
||||||
- 'The architecture for the container (for example C(x86_64) or C(i686)).
|
- 'The architecture for the instance (for example C(x86_64) or C(i686)).
|
||||||
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1).'
|
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1).'
|
||||||
type: str
|
type: str
|
||||||
required: false
|
required: false
|
||||||
config:
|
config:
|
||||||
description:
|
description:
|
||||||
- 'The config for the container (for example C({"limits.cpu": "2"})).
|
- 'The config for the instance (for example C({"limits.cpu": "2"})).
|
||||||
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1).'
|
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1).'
|
||||||
- If the container already exists and its "config" values in metadata
|
- If the instance already exists and its "config" values in metadata
|
||||||
obtained from GET /1.0/containers/<name>
|
obtained from the LXD API U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#instances-containers-and-virtual-machines)
|
||||||
U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#10containersname)
|
|
||||||
are different, this module tries to apply the configurations.
|
are different, this module tries to apply the configurations.
|
||||||
- The keys starting with C(volatile.) are ignored for this comparison when I(ignore_volatile_options=true).
|
- The keys starting with C(volatile.) are ignored for this comparison when I(ignore_volatile_options=true).
|
||||||
type: dict
|
type: dict
|
||||||
|
@ -50,25 +49,25 @@ options:
|
||||||
version_added: 3.7.0
|
version_added: 3.7.0
|
||||||
profiles:
|
profiles:
|
||||||
description:
|
description:
|
||||||
- Profile to be used by the container.
|
- Profile to be used by the instance.
|
||||||
type: list
|
type: list
|
||||||
elements: str
|
elements: str
|
||||||
devices:
|
devices:
|
||||||
description:
|
description:
|
||||||
- 'The devices for the container
|
- 'The devices for the instance
|
||||||
(for example C({ "rootfs": { "path": "/dev/kvm", "type": "unix-char" }})).
|
(for example C({ "rootfs": { "path": "/dev/kvm", "type": "unix-char" }})).
|
||||||
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1).'
|
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1).'
|
||||||
type: dict
|
type: dict
|
||||||
required: false
|
required: false
|
||||||
ephemeral:
|
ephemeral:
|
||||||
description:
|
description:
|
||||||
- Whether or not the container is ephemeral (for example C(true) or C(false)).
|
- Whether or not the instance is ephemeral (for example C(true) or C(false)).
|
||||||
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1).
|
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1).
|
||||||
required: false
|
required: false
|
||||||
type: bool
|
type: bool
|
||||||
source:
|
source:
|
||||||
description:
|
description:
|
||||||
- 'The source for the container
|
- 'The source for the instance
|
||||||
(e.g. { "type": "image",
|
(e.g. { "type": "image",
|
||||||
"mode": "pull",
|
"mode": "pull",
|
||||||
"server": "https://images.linuxcontainers.org",
|
"server": "https://images.linuxcontainers.org",
|
||||||
|
@ -86,39 +85,49 @@ options:
|
||||||
- absent
|
- absent
|
||||||
- frozen
|
- frozen
|
||||||
description:
|
description:
|
||||||
- Define the state of a container.
|
- Define the state of an instance.
|
||||||
required: false
|
required: false
|
||||||
default: started
|
default: started
|
||||||
type: str
|
type: str
|
||||||
target:
|
target:
|
||||||
description:
|
description:
|
||||||
- For cluster deployments. Will attempt to create a container on a target node.
|
- For cluster deployments. Will attempt to create an instance on a target node.
|
||||||
If container exists elsewhere in a cluster, then container will not be replaced or moved.
|
If the instance exists elsewhere in a cluster, then it will not be replaced or moved.
|
||||||
The name should respond to same name of the node you see in C(lxc cluster list).
|
The name should respond to same name of the node you see in C(lxc cluster list).
|
||||||
type: str
|
type: str
|
||||||
required: false
|
required: false
|
||||||
version_added: 1.0.0
|
version_added: 1.0.0
|
||||||
timeout:
|
timeout:
|
||||||
description:
|
description:
|
||||||
- A timeout for changing the state of the container.
|
- A timeout for changing the state of the instance.
|
||||||
- This is also used as a timeout for waiting until IPv4 addresses
|
- This is also used as a timeout for waiting until IPv4 addresses
|
||||||
are set to the all network interfaces in the container after
|
are set to the all network interfaces in the instance after
|
||||||
starting or restarting.
|
starting or restarting.
|
||||||
required: false
|
required: false
|
||||||
default: 30
|
default: 30
|
||||||
type: int
|
type: int
|
||||||
|
type:
|
||||||
|
description:
|
||||||
|
- Instance type can be either C(virtual-machine) or C(container).
|
||||||
|
required: false
|
||||||
|
default: container
|
||||||
|
choices:
|
||||||
|
- container
|
||||||
|
- virtual-machine
|
||||||
|
type: str
|
||||||
|
version_added: 4.1.0
|
||||||
wait_for_ipv4_addresses:
|
wait_for_ipv4_addresses:
|
||||||
description:
|
description:
|
||||||
- If this is true, the C(lxd_container) waits until IPv4 addresses
|
- If this is true, the C(lxd_container) waits until IPv4 addresses
|
||||||
are set to the all network interfaces in the container after
|
are set to the all network interfaces in the instance after
|
||||||
starting or restarting.
|
starting or restarting.
|
||||||
required: false
|
required: false
|
||||||
default: false
|
default: false
|
||||||
type: bool
|
type: bool
|
||||||
force_stop:
|
force_stop:
|
||||||
description:
|
description:
|
||||||
- If this is true, the C(lxd_container) forces to stop the container
|
- If this is true, the C(lxd_container) forces to stop the instance
|
||||||
when it stops or restarts the container.
|
when it stops or restarts the instance.
|
||||||
required: false
|
required: false
|
||||||
default: false
|
default: false
|
||||||
type: bool
|
type: bool
|
||||||
|
@ -160,18 +169,18 @@ options:
|
||||||
required: false
|
required: false
|
||||||
type: str
|
type: str
|
||||||
notes:
|
notes:
|
||||||
- Containers must have a unique name. If you attempt to create a container
|
- Instances can be a container or a virtual machine, both of them must have unique name. If you attempt to create an instance
|
||||||
with a name that already existed in the users namespace the module will
|
with a name that already existed in the users namespace the module will
|
||||||
simply return as "unchanged".
|
simply return as "unchanged".
|
||||||
- There are two ways to run commands in containers, using the command
|
- There are two ways to run commands inside a container or virtual machine, using the command
|
||||||
module or using the ansible lxd connection plugin bundled in Ansible >=
|
module or using the ansible lxd connection plugin bundled in Ansible >=
|
||||||
2.1, the later requires python to be installed in the container which can
|
2.1, the later requires python to be installed in the instance which can
|
||||||
be done with the command module.
|
be done with the command module.
|
||||||
- You can copy a file from the host to the container
|
- You can copy a file from the host to the instance
|
||||||
with the Ansible M(ansible.builtin.copy) and M(ansible.builtin.template) module and the `lxd` connection plugin.
|
with the Ansible M(ansible.builtin.copy) and M(ansible.builtin.template) module and the `lxd` connection plugin.
|
||||||
See the example below.
|
See the example below.
|
||||||
- You can copy a file in the created container to the localhost
|
- You can copy a file in the created instance to the localhost
|
||||||
with `command=lxc file pull container_name/dir/filename filename`.
|
with `command=lxc file pull instance_name/dir/filename filename`.
|
||||||
See the first example below.
|
See the first example below.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
@ -240,6 +249,7 @@ EXAMPLES = '''
|
||||||
community.general.lxd_container:
|
community.general.lxd_container:
|
||||||
name: mycontainer
|
name: mycontainer
|
||||||
state: absent
|
state: absent
|
||||||
|
type: container
|
||||||
|
|
||||||
# An example for restarting a container
|
# An example for restarting a container
|
||||||
- hosts: localhost
|
- hosts: localhost
|
||||||
|
@ -249,6 +259,7 @@ EXAMPLES = '''
|
||||||
community.general.lxd_container:
|
community.general.lxd_container:
|
||||||
name: mycontainer
|
name: mycontainer
|
||||||
state: restarted
|
state: restarted
|
||||||
|
type: container
|
||||||
|
|
||||||
# An example for restarting a container using https to connect to the LXD server
|
# An example for restarting a container using https to connect to the LXD server
|
||||||
- hosts: localhost
|
- hosts: localhost
|
||||||
|
@ -306,16 +317,36 @@ EXAMPLES = '''
|
||||||
mode: pull
|
mode: pull
|
||||||
alias: ubuntu/xenial/amd64
|
alias: ubuntu/xenial/amd64
|
||||||
target: node02
|
target: node02
|
||||||
|
|
||||||
|
# An example for creating a virtual machine
|
||||||
|
- hosts: localhost
|
||||||
|
connection: local
|
||||||
|
tasks:
|
||||||
|
- name: Create container on another node
|
||||||
|
community.general.lxd_container:
|
||||||
|
name: new-vm-1
|
||||||
|
type: virtual-machine
|
||||||
|
state: started
|
||||||
|
ignore_volatile_options: true
|
||||||
|
wait_for_ipv4_addresses: true
|
||||||
|
profiles: ["default"]
|
||||||
|
source:
|
||||||
|
protocol: simplestreams
|
||||||
|
type: image
|
||||||
|
mode: pull
|
||||||
|
server: https://images.linuxcontainers.org
|
||||||
|
alias: debian/11
|
||||||
|
timeout: 600
|
||||||
'''
|
'''
|
||||||
|
|
||||||
RETURN = '''
|
RETURN = '''
|
||||||
addresses:
|
addresses:
|
||||||
description: Mapping from the network device name to a list of IPv4 addresses in the container
|
description: Mapping from the network device name to a list of IPv4 addresses in the instance.
|
||||||
returned: when state is started or restarted
|
returned: when state is started or restarted
|
||||||
type: dict
|
type: dict
|
||||||
sample: {"eth0": ["10.155.92.191"]}
|
sample: {"eth0": ["10.155.92.191"]}
|
||||||
old_state:
|
old_state:
|
||||||
description: The old state of the container
|
description: The old state of the instance.
|
||||||
returned: when state is started or restarted
|
returned: when state is started or restarted
|
||||||
type: str
|
type: str
|
||||||
sample: "stopped"
|
sample: "stopped"
|
||||||
|
@ -325,7 +356,7 @@ logs:
|
||||||
type: list
|
type: list
|
||||||
sample: "(too long to be placed here)"
|
sample: "(too long to be placed here)"
|
||||||
actions:
|
actions:
|
||||||
description: List of actions performed for the container.
|
description: List of actions performed for the instance.
|
||||||
returned: success
|
returned: success
|
||||||
type: list
|
type: list
|
||||||
sample: '["create", "start"]'
|
sample: '["create", "start"]'
|
||||||
|
@ -384,6 +415,15 @@ class LXDContainerManagement(object):
|
||||||
self.addresses = None
|
self.addresses = None
|
||||||
self.target = self.module.params['target']
|
self.target = self.module.params['target']
|
||||||
|
|
||||||
|
self.type = self.module.params['type']
|
||||||
|
|
||||||
|
# LXD Rest API provides additional endpoints for creating containers and virtual-machines.
|
||||||
|
self.api_endpoint = None
|
||||||
|
if self.type == 'container':
|
||||||
|
self.api_endpoint = '/1.0/containers'
|
||||||
|
elif self.type == 'virtual-machine':
|
||||||
|
self.api_endpoint = '/1.0/virtual-machines'
|
||||||
|
|
||||||
self.key_file = self.module.params.get('client_key')
|
self.key_file = self.module.params.get('client_key')
|
||||||
if self.key_file is None:
|
if self.key_file is None:
|
||||||
self.key_file = '{0}/.config/lxc/client.key'.format(os.environ['HOME'])
|
self.key_file = '{0}/.config/lxc/client.key'.format(os.environ['HOME'])
|
||||||
|
@ -419,20 +459,20 @@ class LXDContainerManagement(object):
|
||||||
if param_val is not None:
|
if param_val is not None:
|
||||||
self.config[attr] = param_val
|
self.config[attr] = param_val
|
||||||
|
|
||||||
def _get_container_json(self):
|
def _get_instance_json(self):
|
||||||
return self.client.do(
|
return self.client.do(
|
||||||
'GET', '/1.0/containers/{0}'.format(self.name),
|
'GET', '{0}/{1}'.format(self.api_endpoint, self.name),
|
||||||
ok_error_codes=[404]
|
ok_error_codes=[404]
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_container_state_json(self):
|
def _get_instance_state_json(self):
|
||||||
return self.client.do(
|
return self.client.do(
|
||||||
'GET', '/1.0/containers/{0}/state'.format(self.name),
|
'GET', '{0}/{1}/state'.format(self.api_endpoint, self.name),
|
||||||
ok_error_codes=[404]
|
ok_error_codes=[404]
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _container_json_to_module_state(resp_json):
|
def _instance_json_to_module_state(resp_json):
|
||||||
if resp_json['type'] == 'error':
|
if resp_json['type'] == 'error':
|
||||||
return 'absent'
|
return 'absent'
|
||||||
return ANSIBLE_LXD_STATES[resp_json['metadata']['status']]
|
return ANSIBLE_LXD_STATES[resp_json['metadata']['status']]
|
||||||
|
@ -441,45 +481,45 @@ class LXDContainerManagement(object):
|
||||||
body_json = {'action': action, 'timeout': self.timeout}
|
body_json = {'action': action, 'timeout': self.timeout}
|
||||||
if force_stop:
|
if force_stop:
|
||||||
body_json['force'] = True
|
body_json['force'] = True
|
||||||
return self.client.do('PUT', '/1.0/containers/{0}/state'.format(self.name), body_json=body_json)
|
return self.client.do('PUT', '{0}/{1}/state'.format(self.api_endpoint, self.name), body_json=body_json)
|
||||||
|
|
||||||
def _create_container(self):
|
def _create_instance(self):
|
||||||
config = self.config.copy()
|
config = self.config.copy()
|
||||||
config['name'] = self.name
|
config['name'] = self.name
|
||||||
if self.target:
|
if self.target:
|
||||||
self.client.do('POST', '/1.0/containers?' + urlencode(dict(target=self.target)), config)
|
self.client.do('POST', '{0}?{1}'.format(self.api_endpoint, urlencode(dict(target=self.target))), config)
|
||||||
else:
|
else:
|
||||||
self.client.do('POST', '/1.0/containers', config)
|
self.client.do('POST', self.api_endpoint, config)
|
||||||
self.actions.append('create')
|
self.actions.append('create')
|
||||||
|
|
||||||
def _start_container(self):
|
def _start_instance(self):
|
||||||
self._change_state('start')
|
self._change_state('start')
|
||||||
self.actions.append('start')
|
self.actions.append('start')
|
||||||
|
|
||||||
def _stop_container(self):
|
def _stop_instance(self):
|
||||||
self._change_state('stop', self.force_stop)
|
self._change_state('stop', self.force_stop)
|
||||||
self.actions.append('stop')
|
self.actions.append('stop')
|
||||||
|
|
||||||
def _restart_container(self):
|
def _restart_instance(self):
|
||||||
self._change_state('restart', self.force_stop)
|
self._change_state('restart', self.force_stop)
|
||||||
self.actions.append('restart')
|
self.actions.append('restart')
|
||||||
|
|
||||||
def _delete_container(self):
|
def _delete_instance(self):
|
||||||
self.client.do('DELETE', '/1.0/containers/{0}'.format(self.name))
|
self.client.do('DELETE', '{0}/{1}'.format(self.api_endpoint, self.name))
|
||||||
self.actions.append('delete')
|
self.actions.append('delete')
|
||||||
|
|
||||||
def _freeze_container(self):
|
def _freeze_instance(self):
|
||||||
self._change_state('freeze')
|
self._change_state('freeze')
|
||||||
self.actions.append('freeze')
|
self.actions.append('freeze')
|
||||||
|
|
||||||
def _unfreeze_container(self):
|
def _unfreeze_instance(self):
|
||||||
self._change_state('unfreeze')
|
self._change_state('unfreeze')
|
||||||
self.actions.append('unfreez')
|
self.actions.append('unfreez')
|
||||||
|
|
||||||
def _container_ipv4_addresses(self, ignore_devices=None):
|
def _instance_ipv4_addresses(self, ignore_devices=None):
|
||||||
ignore_devices = ['lo'] if ignore_devices is None else ignore_devices
|
ignore_devices = ['lo'] if ignore_devices is None else ignore_devices
|
||||||
|
|
||||||
resp_json = self._get_container_state_json()
|
resp_json = self._get_instance_state_json()
|
||||||
network = resp_json['metadata']['network'] or {}
|
network = resp_json['metadata']['network'] or {}
|
||||||
network = dict((k, v) for k, v in network.items() if k not in ignore_devices) or {}
|
network = dict((k, v) for k, v in network.items() if k not in ignore_devices) or {}
|
||||||
addresses = dict((k, [a['address'] for a in v['addresses'] if a['family'] == 'inet']) for k, v in network.items()) or {}
|
addresses = dict((k, [a['address'] for a in v['addresses'] if a['family'] == 'inet']) for k, v in network.items()) or {}
|
||||||
|
@ -494,7 +534,7 @@ class LXDContainerManagement(object):
|
||||||
due = datetime.datetime.now() + datetime.timedelta(seconds=self.timeout)
|
due = datetime.datetime.now() + datetime.timedelta(seconds=self.timeout)
|
||||||
while datetime.datetime.now() < due:
|
while datetime.datetime.now() < due:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
addresses = self._container_ipv4_addresses()
|
addresses = self._instance_ipv4_addresses()
|
||||||
if self._has_all_ipv4_addresses(addresses):
|
if self._has_all_ipv4_addresses(addresses):
|
||||||
self.addresses = addresses
|
self.addresses = addresses
|
||||||
return
|
return
|
||||||
|
@ -504,72 +544,72 @@ class LXDContainerManagement(object):
|
||||||
|
|
||||||
def _started(self):
|
def _started(self):
|
||||||
if self.old_state == 'absent':
|
if self.old_state == 'absent':
|
||||||
self._create_container()
|
self._create_instance()
|
||||||
self._start_container()
|
self._start_instance()
|
||||||
else:
|
else:
|
||||||
if self.old_state == 'frozen':
|
if self.old_state == 'frozen':
|
||||||
self._unfreeze_container()
|
self._unfreeze_instance()
|
||||||
elif self.old_state == 'stopped':
|
elif self.old_state == 'stopped':
|
||||||
self._start_container()
|
self._start_instance()
|
||||||
if self._needs_to_apply_container_configs():
|
if self._needs_to_apply_instance_configs():
|
||||||
self._apply_container_configs()
|
self._apply_instance_configs()
|
||||||
if self.wait_for_ipv4_addresses:
|
if self.wait_for_ipv4_addresses:
|
||||||
self._get_addresses()
|
self._get_addresses()
|
||||||
|
|
||||||
def _stopped(self):
|
def _stopped(self):
|
||||||
if self.old_state == 'absent':
|
if self.old_state == 'absent':
|
||||||
self._create_container()
|
self._create_instance()
|
||||||
else:
|
else:
|
||||||
if self.old_state == 'stopped':
|
if self.old_state == 'stopped':
|
||||||
if self._needs_to_apply_container_configs():
|
if self._needs_to_apply_instance_configs():
|
||||||
self._start_container()
|
self._start_instance()
|
||||||
self._apply_container_configs()
|
self._apply_instance_configs()
|
||||||
self._stop_container()
|
self._stop_instance()
|
||||||
else:
|
else:
|
||||||
if self.old_state == 'frozen':
|
if self.old_state == 'frozen':
|
||||||
self._unfreeze_container()
|
self._unfreeze_instance()
|
||||||
if self._needs_to_apply_container_configs():
|
if self._needs_to_apply_instance_configs():
|
||||||
self._apply_container_configs()
|
self._apply_instance_configs()
|
||||||
self._stop_container()
|
self._stop_instance()
|
||||||
|
|
||||||
def _restarted(self):
|
def _restarted(self):
|
||||||
if self.old_state == 'absent':
|
if self.old_state == 'absent':
|
||||||
self._create_container()
|
self._create_instance()
|
||||||
self._start_container()
|
self._start_instance()
|
||||||
else:
|
else:
|
||||||
if self.old_state == 'frozen':
|
if self.old_state == 'frozen':
|
||||||
self._unfreeze_container()
|
self._unfreeze_instance()
|
||||||
if self._needs_to_apply_container_configs():
|
if self._needs_to_apply_instance_configs():
|
||||||
self._apply_container_configs()
|
self._apply_instance_configs()
|
||||||
self._restart_container()
|
self._restart_instance()
|
||||||
if self.wait_for_ipv4_addresses:
|
if self.wait_for_ipv4_addresses:
|
||||||
self._get_addresses()
|
self._get_addresses()
|
||||||
|
|
||||||
def _destroyed(self):
|
def _destroyed(self):
|
||||||
if self.old_state != 'absent':
|
if self.old_state != 'absent':
|
||||||
if self.old_state == 'frozen':
|
if self.old_state == 'frozen':
|
||||||
self._unfreeze_container()
|
self._unfreeze_instance()
|
||||||
if self.old_state != 'stopped':
|
if self.old_state != 'stopped':
|
||||||
self._stop_container()
|
self._stop_instance()
|
||||||
self._delete_container()
|
self._delete_instance()
|
||||||
|
|
||||||
def _frozen(self):
|
def _frozen(self):
|
||||||
if self.old_state == 'absent':
|
if self.old_state == 'absent':
|
||||||
self._create_container()
|
self._create_instance()
|
||||||
self._start_container()
|
self._start_instance()
|
||||||
self._freeze_container()
|
self._freeze_instance()
|
||||||
else:
|
else:
|
||||||
if self.old_state == 'stopped':
|
if self.old_state == 'stopped':
|
||||||
self._start_container()
|
self._start_instance()
|
||||||
if self._needs_to_apply_container_configs():
|
if self._needs_to_apply_instance_configs():
|
||||||
self._apply_container_configs()
|
self._apply_instance_configs()
|
||||||
self._freeze_container()
|
self._freeze_instance()
|
||||||
|
|
||||||
def _needs_to_change_container_config(self, key):
|
def _needs_to_change_instance_config(self, key):
|
||||||
if key not in self.config:
|
if key not in self.config:
|
||||||
return False
|
return False
|
||||||
if key == 'config' and self.ignore_volatile_options: # the old behavior is to ignore configurations by keyword "volatile"
|
if key == 'config' and self.ignore_volatile_options: # the old behavior is to ignore configurations by keyword "volatile"
|
||||||
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_instance_json['metadata'][key].items() if not k.startswith('volatile.'))
|
||||||
for k, v in self.config['config'].items():
|
for k, v in self.config['config'].items():
|
||||||
if k not in old_configs:
|
if k not in old_configs:
|
||||||
return True
|
return True
|
||||||
|
@ -577,7 +617,7 @@ class LXDContainerManagement(object):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
elif key == 'config': # next default behavior
|
elif key == 'config': # next default behavior
|
||||||
old_configs = dict((k, v) for k, v in self.old_container_json['metadata'][key].items())
|
old_configs = dict((k, v) for k, v in self.old_instance_json['metadata'][key].items())
|
||||||
for k, v in self.config['config'].items():
|
for k, v in self.config['config'].items():
|
||||||
if k not in old_configs:
|
if k not in old_configs:
|
||||||
return True
|
return True
|
||||||
|
@ -585,39 +625,41 @@ class LXDContainerManagement(object):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
old_configs = self.old_container_json['metadata'][key]
|
old_configs = self.old_instance_json['metadata'][key]
|
||||||
return self.config[key] != old_configs
|
return self.config[key] != old_configs
|
||||||
|
|
||||||
def _needs_to_apply_container_configs(self):
|
def _needs_to_apply_instance_configs(self):
|
||||||
return (
|
return (
|
||||||
self._needs_to_change_container_config('architecture') or
|
self._needs_to_change_instance_config('architecture') or
|
||||||
self._needs_to_change_container_config('config') or
|
self._needs_to_change_instance_config('config') or
|
||||||
self._needs_to_change_container_config('ephemeral') or
|
self._needs_to_change_instance_config('ephemeral') or
|
||||||
self._needs_to_change_container_config('devices') or
|
self._needs_to_change_instance_config('devices') or
|
||||||
self._needs_to_change_container_config('profiles')
|
self._needs_to_change_instance_config('profiles')
|
||||||
)
|
)
|
||||||
|
|
||||||
def _apply_container_configs(self):
|
def _apply_instance_configs(self):
|
||||||
old_metadata = self.old_container_json['metadata']
|
old_metadata = self.old_instance_json['metadata']
|
||||||
body_json = {
|
body_json = {
|
||||||
'architecture': old_metadata['architecture'],
|
'architecture': old_metadata['architecture'],
|
||||||
'config': old_metadata['config'],
|
'config': old_metadata['config'],
|
||||||
'devices': old_metadata['devices'],
|
'devices': old_metadata['devices'],
|
||||||
'profiles': old_metadata['profiles']
|
'profiles': old_metadata['profiles']
|
||||||
}
|
}
|
||||||
if self._needs_to_change_container_config('architecture'):
|
|
||||||
|
if self._needs_to_change_instance_config('architecture'):
|
||||||
body_json['architecture'] = self.config['architecture']
|
body_json['architecture'] = self.config['architecture']
|
||||||
if self._needs_to_change_container_config('config'):
|
if self._needs_to_change_instance_config('config'):
|
||||||
for k, v in self.config['config'].items():
|
for k, v in self.config['config'].items():
|
||||||
body_json['config'][k] = v
|
body_json['config'][k] = v
|
||||||
if self._needs_to_change_container_config('ephemeral'):
|
if self._needs_to_change_instance_config('ephemeral'):
|
||||||
body_json['ephemeral'] = self.config['ephemeral']
|
body_json['ephemeral'] = self.config['ephemeral']
|
||||||
if self._needs_to_change_container_config('devices'):
|
if self._needs_to_change_instance_config('devices'):
|
||||||
body_json['devices'] = self.config['devices']
|
body_json['devices'] = self.config['devices']
|
||||||
if self._needs_to_change_container_config('profiles'):
|
if self._needs_to_change_instance_config('profiles'):
|
||||||
body_json['profiles'] = self.config['profiles']
|
body_json['profiles'] = self.config['profiles']
|
||||||
self.client.do('PUT', '/1.0/containers/{0}'.format(self.name), body_json=body_json)
|
|
||||||
self.actions.append('apply_container_configs')
|
self.client.do('PUT', '{0}/{1}'.format(self.api_endpoint, self.name), body_json=body_json)
|
||||||
|
self.actions.append('apply_instance_configs')
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Run the main method."""
|
"""Run the main method."""
|
||||||
|
@ -627,8 +669,8 @@ class LXDContainerManagement(object):
|
||||||
self.client.authenticate(self.trust_password)
|
self.client.authenticate(self.trust_password)
|
||||||
self.ignore_volatile_options = self.module.params.get('ignore_volatile_options')
|
self.ignore_volatile_options = self.module.params.get('ignore_volatile_options')
|
||||||
|
|
||||||
self.old_container_json = self._get_container_json()
|
self.old_instance_json = self._get_instance_json()
|
||||||
self.old_state = self._container_json_to_module_state(self.old_container_json)
|
self.old_state = self._instance_json_to_module_state(self.old_instance_json)
|
||||||
action = getattr(self, LXD_ANSIBLE_STATES[self.state])
|
action = getattr(self, LXD_ANSIBLE_STATES[self.state])
|
||||||
action()
|
action()
|
||||||
|
|
||||||
|
@ -698,6 +740,11 @@ def main():
|
||||||
type='int',
|
type='int',
|
||||||
default=30
|
default=30
|
||||||
),
|
),
|
||||||
|
type=dict(
|
||||||
|
type='str',
|
||||||
|
default='container',
|
||||||
|
choices=['container', 'virtual-machine'],
|
||||||
|
),
|
||||||
wait_for_ipv4_addresses=dict(
|
wait_for_ipv4_addresses=dict(
|
||||||
type='bool',
|
type='bool',
|
||||||
default=False
|
default=False
|
||||||
|
@ -736,6 +783,7 @@ def main():
|
||||||
'This will change in the future. Please test your scripts'
|
'This will change in the future. Please test your scripts'
|
||||||
'by "ignore_volatile_options: false". To keep the old behavior, set that option explicitly to "true"',
|
'by "ignore_volatile_options: false". To keep the old behavior, set that option explicitly to "true"',
|
||||||
version='6.0.0', collection_name='community.general')
|
version='6.0.0', collection_name='community.general')
|
||||||
|
|
||||||
lxd_manage = LXDContainerManagement(module=module)
|
lxd_manage = LXDContainerManagement(module=module)
|
||||||
lxd_manage.run()
|
lxd_manage.run()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue