PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/states/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/states/lxd_container.py |
""" Manage LXD containers. .. versionadded:: 2019.2.0 .. note: - :ref:`pylxd` version 2 is required to let this work, currently only available via pip. To install on Ubuntu: $ apt-get install libssl-dev python-pip $ pip install -U pylxd - you need lxd installed on the minion for the init() and version() methods. - for the config_get() and config_get() methods you need to have lxd-client installed. .. _pylxd: https://github.com/lxc/pylxd/blob/master/doc/source/installation.rst :maintainer: René Jochum <rene@jochums.at> :maturity: new :depends: python-pylxd :platform: Linux """ from salt.exceptions import CommandExecutionError, SaltInvocationError __docformat__ = "restructuredtext en" __virtualname__ = "lxd_container" # Keep in sync with: https://github.com/lxc/lxd/blob/master/shared/status.go CONTAINER_STATUS_RUNNING = 103 CONTAINER_STATUS_FROZEN = 110 CONTAINER_STATUS_STOPPED = 102 def __virtual__(): """ Only load if the lxd module is available in __salt__ """ if "lxd.version" in __salt__: return __virtualname__ return (False, "lxd module could not be loaded") def present( name, running=None, source=None, profiles=None, config=None, devices=None, architecture="x86_64", ephemeral=False, restart_on_change=False, remote_addr=None, cert=None, key=None, verify_cert=True, ): """ Create the named container if it does not exist name The name of the container to be created running : None * If ``True``, ensure that the container is running * If ``False``, ensure that the container is stopped * If ``None``, do nothing with regards to the running state of the container source : None Can be either a string containing an image alias: .. code-block:: none "xenial/amd64" or an dict with type "image" with alias: .. code-block:: python {"type": "image", "alias": "xenial/amd64"} or image with "fingerprint": .. code-block:: python {"type": "image", "fingerprint": "SHA-256"} or image with "properties": .. code-block:: python {"type": "image", "properties": { "os": "ubuntu", "release": "14.04", "architecture": "x86_64" }} or none: .. code-block:: python {"type": "none"} or copy: .. code-block:: python {"type": "copy", "source": "my-old-container"} profiles : ['default'] List of profiles to apply on this container config : A config dict or None (None = unset). Can also be a list: .. code-block:: python [{'key': 'boot.autostart', 'value': 1}, {'key': 'security.privileged', 'value': '1'}] devices : A device dict or None (None = unset). architecture : 'x86_64' Can be one of the following: * unknown * i686 * x86_64 * armv7l * aarch64 * ppc * ppc64 * ppc64le * s390x ephemeral : False Destroy this container after stop? restart_on_change : False Restart the container when we detect changes on the config or its devices? remote_addr : An URL to a remote Server, you also have to give cert and key if you provide remote_addr! Examples: https://myserver.lan:8443 /var/lib/mysocket.sock cert : PEM Formatted SSL Zertifikate. Examples: ~/.config/lxc/client.crt key : PEM Formatted SSL Key. Examples: ~/.config/lxc/client.key verify_cert : True Wherever to verify the cert, this is by default True but in the most cases you want to set it off as LXD normally uses self-signed certificates. """ if profiles is None: profiles = ["default"] if source is None: source = {} ret = { "name": name, "running": running, "profiles": profiles, "source": source, "config": config, "devices": devices, "architecture": architecture, "ephemeral": ephemeral, "restart_on_change": restart_on_change, "remote_addr": remote_addr, "cert": cert, "key": key, "verify_cert": verify_cert, "changes": {}, } container = None try: container = __salt__["lxd.container_get"]( name, remote_addr, cert, key, verify_cert, _raw=True ) except CommandExecutionError as e: return _error(ret, str(e)) except SaltInvocationError as e: # Profile not found pass if container is None: if __opts__["test"]: # Test is on, just return that we would create the container msg = f'Would create the container "{name}"' ret["changes"] = {"created": msg} if running is True: msg = msg + " and start it." ret["changes"]["started"] = 'Would start the container "{}"'.format( name ) ret["changes"] = {"created": msg} return _unchanged(ret, msg) # create the container try: __salt__["lxd.container_create"]( name, source, profiles, config, devices, architecture, ephemeral, True, # Wait remote_addr, cert, key, verify_cert, ) except CommandExecutionError as e: return _error(ret, str(e)) msg = f'Created the container "{name}"' ret["changes"] = {"created": msg} if running is True: try: __salt__["lxd.container_start"]( name, remote_addr, cert, key, verify_cert ) except CommandExecutionError as e: return _error(ret, str(e)) msg = msg + " and started it." ret["changes"] = {"started": f'Started the container "{name}"'} return _success(ret, msg) # Container exists, lets check for differences new_profiles = set(map(str, profiles)) old_profiles = set(map(str, container.profiles)) container_changed = False profile_changes = [] # Removed profiles for k in old_profiles.difference(new_profiles): if not __opts__["test"]: profile_changes.append(f'Removed profile "{k}"') old_profiles.discard(k) else: profile_changes.append(f'Would remove profile "{k}"') # Added profiles for k in new_profiles.difference(old_profiles): if not __opts__["test"]: profile_changes.append(f'Added profile "{k}"') old_profiles.add(k) else: profile_changes.append(f'Would add profile "{k}"') if profile_changes: container_changed = True ret["changes"]["profiles"] = profile_changes container.profiles = list(old_profiles) # Config and devices changes config, devices = __salt__["lxd.normalize_input_values"](config, devices) changes = __salt__["lxd.sync_config_devices"]( container, config, devices, __opts__["test"] ) if changes: container_changed = True ret["changes"].update(changes) is_running = container.status_code == CONTAINER_STATUS_RUNNING if not __opts__["test"]: try: __salt__["lxd.pylxd_save_object"](container) except CommandExecutionError as e: return _error(ret, str(e)) if running != is_running: if running is True: if __opts__["test"]: changes["running"] = "Would start the container" return _unchanged( ret, f'Container "{name}" would get changed and started.', ) else: container.start(wait=True) changes["running"] = "Started the container" elif running is False: if __opts__["test"]: changes["stopped"] = "Would stopped the container" return _unchanged( ret, f'Container "{name}" would get changed and stopped.', ) else: container.stop(wait=True) changes["stopped"] = "Stopped the container" if ( (running is True or running is None) and is_running and restart_on_change and container_changed ): if __opts__["test"]: changes["restarted"] = "Would restart the container" return _unchanged(ret, f'Would restart the container "{name}"') else: container.restart(wait=True) changes["restarted"] = f'Container "{name}" has been restarted' return _success(ret, f'Container "{name}" has been restarted') if not container_changed: return _success(ret, "No changes") if __opts__["test"]: return _unchanged(ret, f'Container "{name}" would get changed.') return _success(ret, "{} changes".format(len(ret["changes"].keys()))) def absent(name, stop=False, remote_addr=None, cert=None, key=None, verify_cert=True): """ Ensure a LXD container is not present, destroying it if present name : The name of the container to destroy stop : stop before destroying default: false remote_addr : An URL to a remote Server, you also have to give cert and key if you provide remote_addr! Examples: https://myserver.lan:8443 /var/lib/mysocket.sock cert : PEM Formatted SSL Zertifikate. Examples: ~/.config/lxc/client.crt key : PEM Formatted SSL Key. Examples: ~/.config/lxc/client.key verify_cert : True Wherever to verify the cert, this is by default True but in the most cases you want to set it off as LXD normally uses self-signed certificates. """ ret = { "name": name, "stop": stop, "remote_addr": remote_addr, "cert": cert, "key": key, "verify_cert": verify_cert, "changes": {}, } try: container = __salt__["lxd.container_get"]( name, remote_addr, cert, key, verify_cert, _raw=True ) except CommandExecutionError as e: return _error(ret, str(e)) except SaltInvocationError as e: # Container not found return _success(ret, f'Container "{name}" not found.') if __opts__["test"]: ret["changes"] = {"removed": f'Container "{name}" would get deleted.'} return _unchanged(ret, ret["changes"]["removed"]) if stop and container.status_code == CONTAINER_STATUS_RUNNING: container.stop(wait=True) container.delete(wait=True) ret["changes"]["deleted"] = f'Container "{name}" has been deleted.' return _success(ret, ret["changes"]["deleted"]) def running( name, restart=False, remote_addr=None, cert=None, key=None, verify_cert=True ): """ Ensure a LXD container is running and restart it if restart is True name : The name of the container to start/restart. restart : restart the container if it is already started. remote_addr : An URL to a remote Server, you also have to give cert and key if you provide remote_addr! Examples: https://myserver.lan:8443 /var/lib/mysocket.sock cert : PEM Formatted SSL Zertifikate. Examples: ~/.config/lxc/client.crt key : PEM Formatted SSL Key. Examples: ~/.config/lxc/client.key verify_cert : True Wherever to verify the cert, this is by default True but in the most cases you want to set it off as LXD normally uses self-signed certificates. """ ret = { "name": name, "restart": restart, "remote_addr": remote_addr, "cert": cert, "key": key, "verify_cert": verify_cert, "changes": {}, } try: container = __salt__["lxd.container_get"]( name, remote_addr, cert, key, verify_cert, _raw=True ) except CommandExecutionError as e: return _error(ret, str(e)) except SaltInvocationError as e: # Container not found return _error(ret, f'Container "{name}" not found') is_running = container.status_code == CONTAINER_STATUS_RUNNING if is_running: if not restart: return _success(ret, f'The container "{name}" is already running') else: if __opts__["test"]: ret["changes"]["restarted"] = 'Would restart the container "{}"'.format( name ) return _unchanged(ret, ret["changes"]["restarted"]) else: container.restart(wait=True) ret["changes"]["restarted"] = 'Restarted the container "{}"'.format( name ) return _success(ret, ret["changes"]["restarted"]) if __opts__["test"]: ret["changes"]["started"] = f'Would start the container "{name}"' return _unchanged(ret, ret["changes"]["started"]) container.start(wait=True) ret["changes"]["started"] = f'Started the container "{name}"' return _success(ret, ret["changes"]["started"]) def frozen(name, start=True, remote_addr=None, cert=None, key=None, verify_cert=True): """ Ensure a LXD container is frozen, start and freeze it if start is true name : The name of the container to freeze start : start and freeze it remote_addr : An URL to a remote Server, you also have to give cert and key if you provide remote_addr! Examples: https://myserver.lan:8443 /var/lib/mysocket.sock cert : PEM Formatted SSL Zertifikate. Examples: ~/.config/lxc/client.crt key : PEM Formatted SSL Key. Examples: ~/.config/lxc/client.key verify_cert : True Wherever to verify the cert, this is by default True but in the most cases you want to set it off as LXD normally uses self-signed certificates. """ ret = { "name": name, "start": start, "remote_addr": remote_addr, "cert": cert, "key": key, "verify_cert": verify_cert, "changes": {}, } try: container = __salt__["lxd.container_get"]( name, remote_addr, cert, key, verify_cert, _raw=True ) except CommandExecutionError as e: return _error(ret, str(e)) except SaltInvocationError as e: # Container not found return _error(ret, f'Container "{name}" not found') if container.status_code == CONTAINER_STATUS_FROZEN: return _success(ret, f'Container "{name}" is alredy frozen') is_running = container.status_code == CONTAINER_STATUS_RUNNING if not is_running and not start: return _error( ret, 'Container "{}" is not running and start is False, cannot freeze it'.format( name ), ) elif not is_running and start: if __opts__["test"]: ret["changes"][ "started" ] = f'Would start the container "{name}" and freeze it after' return _unchanged(ret, ret["changes"]["started"]) else: container.start(wait=True) ret["changes"]["started"] = f'Start the container "{name}"' if __opts__["test"]: ret["changes"]["frozen"] = f'Would freeze the container "{name}"' return _unchanged(ret, ret["changes"]["frozen"]) container.freeze(wait=True) ret["changes"]["frozen"] = f'Froze the container "{name}"' return _success(ret, ret["changes"]["frozen"]) def stopped(name, kill=False, remote_addr=None, cert=None, key=None, verify_cert=True): """ Ensure a LXD container is stopped, kill it if kill is true else stop it name : The name of the container to stop kill : kill if true remote_addr : An URL to a remote Server, you also have to give cert and key if you provide remote_addr! Examples: https://myserver.lan:8443 /var/lib/mysocket.sock cert : PEM Formatted SSL Zertifikate. Examples: ~/.config/lxc/client.crt key : PEM Formatted SSL Key. Examples: ~/.config/lxc/client.key verify_cert : True Wherever to verify the cert, this is by default True but in the most cases you want to set it off as LXD normally uses self-signed certificates. """ ret = { "name": name, "kill": kill, "remote_addr": remote_addr, "cert": cert, "key": key, "verify_cert": verify_cert, "changes": {}, } try: container = __salt__["lxd.container_get"]( name, remote_addr, cert, key, verify_cert, _raw=True ) except CommandExecutionError as e: return _error(ret, str(e)) except SaltInvocationError as e: # Container not found return _error(ret, f'Container "{name}" not found') if container.status_code == CONTAINER_STATUS_STOPPED: return _success(ret, f'Container "{name}" is already stopped') if __opts__["test"]: ret["changes"]["stopped"] = f'Would stop the container "{name}"' return _unchanged(ret, ret["changes"]["stopped"]) container.stop(force=kill, wait=True) ret["changes"]["stopped"] = f'Stopped the container "{name}"' return _success(ret, ret["changes"]["stopped"]) def migrated( name, remote_addr, cert, key, verify_cert, src_remote_addr, stop_and_start=False, src_cert=None, src_key=None, src_verify_cert=None, ): """Ensure a container is migrated to another host If the container is running, it either must be shut down first (use stop_and_start=True) or criu must be installed on the source and destination machines. For this operation both certs need to be authenticated, use :mod:`lxd.authenticate <salt.states.lxd.authenticate` to authenticate your cert(s). name : The container to migrate remote_addr : An URL to the destination remote Server Examples: https://myserver.lan:8443 /var/lib/mysocket.sock cert : PEM Formatted SSL Zertifikate. Examples: ~/.config/lxc/client.crt key : PEM Formatted SSL Key. Examples: ~/.config/lxc/client.key verify_cert : True Wherever to verify the cert, this is by default True but in the most cases you want to set it off as LXD normally uses self-signed certificates. src_remote_addr : An URL to the source remote Server Examples: https://myserver.lan:8443 /var/lib/mysocket.sock stop_and_start: Stop before migrating and start after src_cert : PEM Formatted SSL Zertifikate, if None we copy "cert" Examples: ~/.config/lxc/client.crt src_key : PEM Formatted SSL Key, if None we copy "key" Examples: ~/.config/lxc/client.key src_verify_cert : Wherever to verify the cert, if None we copy "verify_cert" """ ret = { "name": name, "remote_addr": remote_addr, "cert": cert, "key": key, "verify_cert": verify_cert, "src_remote_addr": src_remote_addr, "src_and_start": stop_and_start, "src_cert": src_cert, "src_key": src_key, "changes": {}, } dest_container = None try: dest_container = __salt__["lxd.container_get"]( name, remote_addr, cert, key, verify_cert, _raw=True ) except CommandExecutionError as e: return _error(ret, str(e)) except SaltInvocationError as e: # Destination container not found pass if dest_container is not None: return _success(ret, f'Container "{name}" exists on the destination') if src_verify_cert is None: src_verify_cert = verify_cert try: __salt__["lxd.container_get"]( name, src_remote_addr, src_cert, src_key, src_verify_cert, _raw=True ) except CommandExecutionError as e: return _error(ret, str(e)) except SaltInvocationError as e: # Container not found return _error(ret, f'Source Container "{name}" not found') if __opts__["test"]: ret["changes"]["migrated"] = ( 'Would migrate the container "{}" from "{}" to "{}"'.format( name, src_remote_addr, remote_addr ) ) return _unchanged(ret, ret["changes"]["migrated"]) try: __salt__["lxd.container_migrate"]( name, stop_and_start, remote_addr, cert, key, verify_cert, src_remote_addr, src_cert, src_key, src_verify_cert, ) except CommandExecutionError as e: return _error(ret, str(e)) ret["changes"]["migrated"] = 'Migrated the container "{}" from "{}" to "{}"'.format( name, src_remote_addr, remote_addr ) return _success(ret, ret["changes"]["migrated"]) def _success(ret, success_msg): ret["result"] = True ret["comment"] = success_msg if "changes" not in ret: ret["changes"] = {} return ret def _unchanged(ret, msg): ret["result"] = None ret["comment"] = msg if "changes" not in ret: ret["changes"] = {} return ret def _error(ret, err_msg): ret["result"] = False ret["comment"] = err_msg if "changes" not in ret: ret["changes"] = {} return ret