Merge pull request #491 from cloudnull/devel-updated-lxc-clone
Updated lxc module to remove the clone state
This commit is contained in:
commit
bd477e5a31
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