|
|
@ -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
|
|
|
|
|
|
|
|
clone_snapshot: true
|
|
|
|
|
|
|
|
clone_name: test-container-overlayfs-clone-snapshot
|
|
|
|
|
|
|
|
archive: true
|
|
|
|
|
|
|
|
archive_compression: gzip
|
|
|
|
|
|
|
|
register: clone_container_info
|
|
|
|
|
|
|
|
|
|
|
|
- name: Clone a container
|
|
|
|
- name: debug info on container "test-container"
|
|
|
|
lxc_container:
|
|
|
|
debug: var=clone_container_info
|
|
|
|
name: test-container-overlayfs
|
|
|
|
|
|
|
|
clone_name: test-container-clone
|
|
|
|
|
|
|
|
state: clone
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- name: Clone a container using snapshot.
|
|
|
|
- name: Clone a container using snapshot
|
|
|
|
lxc_container:
|
|
|
|
lxc_container:
|
|
|
|
name: test-container-overlayfs
|
|
|
|
name: test-container-overlayfs-clone-snapshot
|
|
|
|
clone_name: test-container-overlayfs-clone
|
|
|
|
|
|
|
|
backing_store: overlayfs
|
|
|
|
backing_store: overlayfs
|
|
|
|
|
|
|
|
clone_name: test-container-overlayfs-clone-snapshot2
|
|
|
|
clone_snapshot: true
|
|
|
|
clone_snapshot: true
|
|
|
|
state: clone
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- 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,8 +752,6 @@ class LxcContainerManagement(object):
|
|
|
|
state.
|
|
|
|
state.
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
self.check_count(count=count, method='clone')
|
|
|
|
|
|
|
|
if self._container_exists(container_name=self.container_name):
|
|
|
|
|
|
|
|
# Ensure that the state of the original container is stopped
|
|
|
|
# Ensure that the state of the original container is stopped
|
|
|
|
container_state = self._get_state()
|
|
|
|
container_state = self._get_state()
|
|
|
|
if container_state != 'stopped':
|
|
|
|
if container_state != 'stopped':
|
|
|
@ -773,6 +772,11 @@ class LxcContainerManagement(object):
|
|
|
|
# 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:
|
|
|
@ -792,25 +796,7 @@ class LxcContainerManagement(object):
|
|
|
|
self.container.start()
|
|
|
|
self.container.start()
|
|
|
|
self.container.freeze()
|
|
|
|
self.container.freeze()
|
|
|
|
|
|
|
|
|
|
|
|
# Change the container name context to the new cloned container
|
|
|
|
return True
|
|
|
|
# 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:
|
|
|
|
|
|
|
|
self._create()
|
|
|
|
|
|
|
|
count += 1
|
|
|
|
|
|
|
|
self._clone(count)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|