Updated lxc module to remove the clone state
The clone state was removed in favor of making the module more declarative. This change was done in response to review in PR #328 from @bcoca. In the commit new examples were created on how this feature works.
This commit is contained in:
parent
8178854c2a
commit
7a22f84ca4
1 changed files with 125 additions and 104 deletions
|
@ -156,12 +156,12 @@ options:
|
||||||
- restarted
|
- restarted
|
||||||
- absent
|
- absent
|
||||||
- frozen
|
- frozen
|
||||||
- clone
|
|
||||||
description:
|
description:
|
||||||
- Define the state of a container. If you use clone the container
|
- Define the state of a container. If you clone a container using
|
||||||
will be stopped while the clone operation is happening and upon
|
`clone_name` the newly cloned container created in a stopped state.
|
||||||
completion of the clone the original container state will be
|
The running container will be stopped while the clone operation is
|
||||||
restored.
|
happening and upon completion of the clone the original container
|
||||||
|
state will be restored.
|
||||||
required: false
|
required: false
|
||||||
default: started
|
default: started
|
||||||
container_config:
|
container_config:
|
||||||
|
@ -225,6 +225,7 @@ EXAMPLES = """
|
||||||
- name: Create filesystem container
|
- name: Create filesystem container
|
||||||
lxc_container:
|
lxc_container:
|
||||||
name: test-container-config
|
name: test-container-config
|
||||||
|
backing_store: dir
|
||||||
container_log: true
|
container_log: true
|
||||||
template: ubuntu
|
template: ubuntu
|
||||||
state: started
|
state: started
|
||||||
|
@ -238,7 +239,7 @@ EXAMPLES = """
|
||||||
# Create an lvm container, run a complex command in it, add additional
|
# Create an lvm container, run a complex command in it, add additional
|
||||||
# configuration to it, create an archive of it, and finally leave the container
|
# configuration to it, create an archive of it, and finally leave the container
|
||||||
# in a frozen state. The container archive will be compressed using bzip2
|
# in a frozen state. The container archive will be compressed using bzip2
|
||||||
- name: Create an lvm container
|
- name: Create a frozen lvm container
|
||||||
lxc_container:
|
lxc_container:
|
||||||
name: test-container-lvm
|
name: test-container-lvm
|
||||||
container_log: true
|
container_log: true
|
||||||
|
@ -263,14 +264,6 @@ EXAMPLES = """
|
||||||
- name: Debug info on container "test-container-lvm"
|
- name: Debug info on container "test-container-lvm"
|
||||||
debug: var=lvm_container_info
|
debug: var=lvm_container_info
|
||||||
|
|
||||||
- name: Get information on a given container.
|
|
||||||
lxc_container:
|
|
||||||
name: test-container-config
|
|
||||||
register: config_container_info
|
|
||||||
|
|
||||||
- name: debug info on container "test-container"
|
|
||||||
debug: var=config_container_info
|
|
||||||
|
|
||||||
- name: Run a command in a container and ensure its in a "stopped" state.
|
- name: Run a command in a container and ensure its in a "stopped" state.
|
||||||
lxc_container:
|
lxc_container:
|
||||||
name: test-container-started
|
name: test-container-started
|
||||||
|
@ -285,19 +278,19 @@ EXAMPLES = """
|
||||||
container_command: |
|
container_command: |
|
||||||
echo 'hello world.' | tee /opt/frozen
|
echo 'hello world.' | tee /opt/frozen
|
||||||
|
|
||||||
- name: Start a container.
|
- name: Start a container
|
||||||
lxc_container:
|
lxc_container:
|
||||||
name: test-container-stopped
|
name: test-container-stopped
|
||||||
state: started
|
state: started
|
||||||
|
|
||||||
- name: Run a command in a container and then restart it.
|
- name: Run a command in a container and then restart it
|
||||||
lxc_container:
|
lxc_container:
|
||||||
name: test-container-started
|
name: test-container-started
|
||||||
state: restarted
|
state: restarted
|
||||||
container_command: |
|
container_command: |
|
||||||
echo 'hello world.' | tee /opt/restarted
|
echo 'hello world.' | tee /opt/restarted
|
||||||
|
|
||||||
- name: Run a complex command within a "running" container.
|
- name: Run a complex command within a "running" container
|
||||||
lxc_container:
|
lxc_container:
|
||||||
name: test-container-started
|
name: test-container-started
|
||||||
container_command: |
|
container_command: |
|
||||||
|
@ -317,7 +310,10 @@ EXAMPLES = """
|
||||||
archive: true
|
archive: true
|
||||||
archive_path: /opt/archives
|
archive_path: /opt/archives
|
||||||
|
|
||||||
- name: Create an overlayfs container
|
# Create a container using overlayfs, create an archive of it, create a
|
||||||
|
# snapshot clone of the container and and finally leave the container
|
||||||
|
# in a frozen state. The container archive will be compressed using gzip.
|
||||||
|
- name: Create an overlayfs container archive and clone it
|
||||||
lxc_container:
|
lxc_container:
|
||||||
name: test-container-overlayfs
|
name: test-container-overlayfs
|
||||||
container_log: true
|
container_log: true
|
||||||
|
@ -325,40 +321,42 @@ EXAMPLES = """
|
||||||
state: started
|
state: started
|
||||||
backing_store: overlayfs
|
backing_store: overlayfs
|
||||||
template_options: --release trusty
|
template_options: --release trusty
|
||||||
|
|
||||||
- name: Clone a container
|
|
||||||
lxc_container:
|
|
||||||
name: test-container-overlayfs
|
|
||||||
clone_name: test-container-clone
|
|
||||||
state: clone
|
|
||||||
|
|
||||||
- name: Clone a container using snapshot.
|
|
||||||
lxc_container:
|
|
||||||
name: test-container-overlayfs
|
|
||||||
clone_name: test-container-overlayfs-clone
|
|
||||||
backing_store: overlayfs
|
|
||||||
clone_snapshot: true
|
clone_snapshot: true
|
||||||
state: clone
|
clone_name: test-container-overlayfs-clone-snapshot
|
||||||
|
archive: true
|
||||||
|
archive_compression: gzip
|
||||||
|
register: clone_container_info
|
||||||
|
|
||||||
|
- name: debug info on container "test-container"
|
||||||
|
debug: var=clone_container_info
|
||||||
|
|
||||||
|
- name: Clone a container using snapshot
|
||||||
|
lxc_container:
|
||||||
|
name: test-container-overlayfs-clone-snapshot
|
||||||
|
backing_store: overlayfs
|
||||||
|
clone_name: test-container-overlayfs-clone-snapshot2
|
||||||
|
clone_snapshot: true
|
||||||
|
|
||||||
- name: Create a new container and clone it
|
- name: Create a new container and clone it
|
||||||
lxc_container:
|
lxc_container:
|
||||||
name: test-container-new-overlayfs
|
name: test-container-new-archive
|
||||||
clone_name: test-container-new-overlayfs-clone
|
backing_store: dir
|
||||||
backing_store: overlayfs
|
clone_name: test-container-new-archive-clone
|
||||||
clone_snapshot: true
|
|
||||||
state: clone
|
|
||||||
|
|
||||||
- name: Create a new container, clone it, and archive
|
- name: Archive and clone a container then destroy it
|
||||||
lxc_container:
|
lxc_container:
|
||||||
name: test-container-new-overlayfs
|
name: test-container-new-archive
|
||||||
clone_name: test-container-new-overlayfs-clone
|
state: absent
|
||||||
backing_store: overlayfs
|
clone_name: test-container-new-archive-destroyed-clone
|
||||||
clone_snapshot: true
|
|
||||||
state: clone
|
|
||||||
archive: true
|
archive: true
|
||||||
archive_compression: gzip
|
archive_compression: gzip
|
||||||
|
|
||||||
- name: Destroy a container.
|
- name: Start a cloned container.
|
||||||
|
lxc_container:
|
||||||
|
name: test-container-new-archive-destroyed-clone
|
||||||
|
state: started
|
||||||
|
|
||||||
|
- name: Destroy a container
|
||||||
lxc_container:
|
lxc_container:
|
||||||
name: "{{ item }}"
|
name: "{{ item }}"
|
||||||
state: absent
|
state: absent
|
||||||
|
@ -369,8 +367,12 @@ EXAMPLES = """
|
||||||
- test-container-lvm
|
- test-container-lvm
|
||||||
- test-container-config
|
- test-container-config
|
||||||
- test-container-overlayfs
|
- test-container-overlayfs
|
||||||
- test-container-clone
|
|
||||||
- test-container-overlayfs-clone
|
- test-container-overlayfs-clone
|
||||||
|
- test-container-overlayfs-clone-snapshot
|
||||||
|
- test-container-overlayfs-clone-snapshot2
|
||||||
|
- test-container-new-archive
|
||||||
|
- test-container-new-archive-clone
|
||||||
|
- test-container-new-archive-destroyed-clone
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -518,18 +520,16 @@ def create_script(command):
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
# Ensure the script is executable.
|
# Ensure the script is executable.
|
||||||
os.chmod(script_file, 0755)
|
os.chmod(script_file, 1755)
|
||||||
|
|
||||||
# Get temporary directory.
|
# Get temporary directory.
|
||||||
tempdir = tempfile.gettempdir()
|
tempdir = tempfile.gettempdir()
|
||||||
|
|
||||||
# Output log file.
|
# Output log file.
|
||||||
stdout = path.join(tempdir, 'lxc-attach-script.log')
|
stdout_file = open(path.join(tempdir, 'lxc-attach-script.log'), 'ab')
|
||||||
stdout_file = open(stdout, 'ab')
|
|
||||||
|
|
||||||
# Error log file.
|
# Error log file.
|
||||||
stderr = path.join(tempdir, 'lxc-attach-script.err')
|
stderr_file = open(path.join(tempdir, 'lxc-attach-script.err'), 'ab')
|
||||||
stderr_file = open(stderr, 'ab')
|
|
||||||
|
|
||||||
# Execute the script command.
|
# Execute the script command.
|
||||||
try:
|
try:
|
||||||
|
@ -561,6 +561,7 @@ class LxcContainerManagement(object):
|
||||||
self.container_name = self.module.params['name']
|
self.container_name = self.module.params['name']
|
||||||
self.container = self.get_container_bind()
|
self.container = self.get_container_bind()
|
||||||
self.archive_info = None
|
self.archive_info = None
|
||||||
|
self.clone_info = None
|
||||||
|
|
||||||
def get_container_bind(self):
|
def get_container_bind(self):
|
||||||
return lxc.Container(name=self.container_name)
|
return lxc.Container(name=self.container_name)
|
||||||
|
@ -735,7 +736,7 @@ class LxcContainerManagement(object):
|
||||||
self._container_startup()
|
self._container_startup()
|
||||||
self.container.freeze()
|
self.container.freeze()
|
||||||
|
|
||||||
def _clone(self, count=0):
|
def _container_create_clone(self):
|
||||||
"""Clone a new LXC container from an existing container.
|
"""Clone a new LXC container from an existing container.
|
||||||
|
|
||||||
This method will clone an existing container to a new container using
|
This method will clone an existing container to a new container using
|
||||||
|
@ -751,66 +752,51 @@ class LxcContainerManagement(object):
|
||||||
state.
|
state.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.check_count(count=count, method='clone')
|
# Ensure that the state of the original container is stopped
|
||||||
if self._container_exists(container_name=self.container_name):
|
container_state = self._get_state()
|
||||||
# Ensure that the state of the original container is stopped
|
if container_state != 'stopped':
|
||||||
container_state = self._get_state()
|
self.state_change = True
|
||||||
if container_state != 'stopped':
|
self.container.stop()
|
||||||
self.state_change = True
|
|
||||||
self.container.stop()
|
|
||||||
|
|
||||||
build_command = [
|
build_command = [
|
||||||
self.module.get_bin_path('lxc-clone', True),
|
self.module.get_bin_path('lxc-clone', True),
|
||||||
]
|
]
|
||||||
|
|
||||||
build_command = self._add_variables(
|
build_command = self._add_variables(
|
||||||
variables_dict=self._get_vars(
|
variables_dict=self._get_vars(
|
||||||
variables=LXC_COMMAND_MAP['clone']['variables']
|
variables=LXC_COMMAND_MAP['clone']['variables']
|
||||||
),
|
),
|
||||||
build_command=build_command
|
build_command=build_command
|
||||||
)
|
)
|
||||||
|
|
||||||
# Load logging for the instance when creating it.
|
# Load logging for the instance when creating it.
|
||||||
if self.module.params.get('clone_snapshot') in BOOLEANS_TRUE:
|
if self.module.params.get('clone_snapshot') in BOOLEANS_TRUE:
|
||||||
build_command.append('--snapshot')
|
build_command.append('--snapshot')
|
||||||
|
# Check for backing_store == overlayfs if so force the use of snapshot
|
||||||
|
# If overlay fs is used and snapshot is unset the clone command will
|
||||||
|
# fail with an unsupported type.
|
||||||
|
elif self.module.params.get('backing_store') == 'overlayfs':
|
||||||
|
build_command.append('--snapshot')
|
||||||
|
|
||||||
rc, return_data, err = self._run_command(build_command)
|
rc, return_data, err = self._run_command(build_command)
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
message = "Failed executing lxc-clone."
|
message = "Failed executing lxc-clone."
|
||||||
self.failure(
|
self.failure(
|
||||||
err=err, rc=rc, msg=message, command=' '.join(
|
err=err, rc=rc, msg=message, command=' '.join(
|
||||||
build_command
|
build_command
|
||||||
)
|
|
||||||
)
|
)
|
||||||
else:
|
)
|
||||||
self.state_change = True
|
|
||||||
# Restore the original state of the origin container if it was
|
|
||||||
# not in a stopped state.
|
|
||||||
if container_state == 'running':
|
|
||||||
self.container.start()
|
|
||||||
elif container_state == 'frozen':
|
|
||||||
self.container.start()
|
|
||||||
self.container.freeze()
|
|
||||||
|
|
||||||
# Change the container name context to the new cloned container
|
|
||||||
# This enforces that the state of the new cloned container will be
|
|
||||||
# "stopped".
|
|
||||||
self.state = 'stopped'
|
|
||||||
self.container_name = self.module.params['clone_name']
|
|
||||||
self.container = self.get_container_bind()
|
|
||||||
|
|
||||||
# Return data
|
|
||||||
self._execute_command()
|
|
||||||
|
|
||||||
# Perform any configuration updates
|
|
||||||
self._config()
|
|
||||||
|
|
||||||
# Check if the container needs to have an archive created.
|
|
||||||
self._check_archive()
|
|
||||||
else:
|
else:
|
||||||
self._create()
|
self.state_change = True
|
||||||
count += 1
|
# Restore the original state of the origin container if it was
|
||||||
self._clone(count)
|
# not in a stopped state.
|
||||||
|
if container_state == 'running':
|
||||||
|
self.container.start()
|
||||||
|
elif container_state == 'frozen':
|
||||||
|
self.container.start()
|
||||||
|
self.container.freeze()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def _create(self):
|
def _create(self):
|
||||||
"""Create a new LXC container.
|
"""Create a new LXC container.
|
||||||
|
@ -965,6 +951,23 @@ class LxcContainerManagement(object):
|
||||||
'archive': self._container_create_tar()
|
'archive': self._container_create_tar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _check_clone(self):
|
||||||
|
"""Create a compressed archive of a container.
|
||||||
|
|
||||||
|
This will store archive_info in as self.archive_info
|
||||||
|
"""
|
||||||
|
|
||||||
|
clone_name = self.module.params.get('clone_name')
|
||||||
|
if clone_name:
|
||||||
|
if not self._container_exists(container_name=clone_name):
|
||||||
|
self.clone_info = {
|
||||||
|
'cloned': self._container_create_clone()
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
self.clone_info = {
|
||||||
|
'cloned': False
|
||||||
|
}
|
||||||
|
|
||||||
def _destroyed(self, timeout=60):
|
def _destroyed(self, timeout=60):
|
||||||
"""Ensure a container is destroyed.
|
"""Ensure a container is destroyed.
|
||||||
|
|
||||||
|
@ -979,6 +982,9 @@ class LxcContainerManagement(object):
|
||||||
# Check if the container needs to have an archive created.
|
# Check if the container needs to have an archive created.
|
||||||
self._check_archive()
|
self._check_archive()
|
||||||
|
|
||||||
|
# Check if the container is to be cloned
|
||||||
|
self._check_clone()
|
||||||
|
|
||||||
if self._get_state() != 'stopped':
|
if self._get_state() != 'stopped':
|
||||||
self.state_change = True
|
self.state_change = True
|
||||||
self.container.stop()
|
self.container.stop()
|
||||||
|
@ -1028,6 +1034,9 @@ class LxcContainerManagement(object):
|
||||||
|
|
||||||
# Check if the container needs to have an archive created.
|
# Check if the container needs to have an archive created.
|
||||||
self._check_archive()
|
self._check_archive()
|
||||||
|
|
||||||
|
# Check if the container is to be cloned
|
||||||
|
self._check_clone()
|
||||||
else:
|
else:
|
||||||
self._create()
|
self._create()
|
||||||
count += 1
|
count += 1
|
||||||
|
@ -1055,6 +1064,9 @@ class LxcContainerManagement(object):
|
||||||
|
|
||||||
# Check if the container needs to have an archive created.
|
# Check if the container needs to have an archive created.
|
||||||
self._check_archive()
|
self._check_archive()
|
||||||
|
|
||||||
|
# Check if the container is to be cloned
|
||||||
|
self._check_clone()
|
||||||
else:
|
else:
|
||||||
self._create()
|
self._create()
|
||||||
count += 1
|
count += 1
|
||||||
|
@ -1082,6 +1094,9 @@ class LxcContainerManagement(object):
|
||||||
|
|
||||||
# Check if the container needs to have an archive created.
|
# Check if the container needs to have an archive created.
|
||||||
self._check_archive()
|
self._check_archive()
|
||||||
|
|
||||||
|
# Check if the container is to be cloned
|
||||||
|
self._check_clone()
|
||||||
else:
|
else:
|
||||||
self._create()
|
self._create()
|
||||||
count += 1
|
count += 1
|
||||||
|
@ -1122,6 +1137,9 @@ class LxcContainerManagement(object):
|
||||||
|
|
||||||
# Check if the container needs to have an archive created.
|
# Check if the container needs to have an archive created.
|
||||||
self._check_archive()
|
self._check_archive()
|
||||||
|
|
||||||
|
# Check if the container is to be cloned
|
||||||
|
self._check_clone()
|
||||||
else:
|
else:
|
||||||
self._create()
|
self._create()
|
||||||
count += 1
|
count += 1
|
||||||
|
@ -1581,6 +1599,9 @@ class LxcContainerManagement(object):
|
||||||
if self.archive_info:
|
if self.archive_info:
|
||||||
outcome.update(self.archive_info)
|
outcome.update(self.archive_info)
|
||||||
|
|
||||||
|
if self.clone_info:
|
||||||
|
outcome.update(self.clone_info)
|
||||||
|
|
||||||
self.module.exit_json(
|
self.module.exit_json(
|
||||||
changed=self.state_change,
|
changed=self.state_change,
|
||||||
lxc_container=outcome
|
lxc_container=outcome
|
||||||
|
|
Loading…
Reference in a new issue