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:
Kevin Carter 2015-05-13 21:20:05 -05:00
parent 9800126a6e
commit fd0c21df27

View file

@ -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