Exemple #1
0
def main():
    """ main entry point for module execution
    """
    backup_spec = dict(
        filename=dict(),
        dir_path=dict(type='path')
    )
    argument_spec = dict(
        content=dict(aliases=['xml']),
        target=dict(choices=['auto', 'candidate', 'running'], default='auto', aliases=['datastore']),
        source_datastore=dict(aliases=['source']),
        format=dict(choices=['xml', 'text'], default='xml'),
        lock=dict(choices=['never', 'always', 'if-supported'], default='always'),
        default_operation=dict(choices=['merge', 'replace', 'none']),
        confirm=dict(type='int', default=0),
        confirm_commit=dict(type='bool', default=False),
        error_option=dict(choices=['stop-on-error', 'continue-on-error', 'rollback-on-error'], default='stop-on-error'),
        backup=dict(type='bool', default=False),
        backup_options=dict(type='dict', options=backup_spec),
        save=dict(type='bool', default=False),
        delete=dict(type='bool', default=False),
        commit=dict(type='bool', default=True),
        validate=dict(type='bool', default=False),
    )

    # deprecated options
    netconf_top_spec = {
        'src': dict(type='path', removed_in_version=2.11),
        'host': dict(removed_in_version=2.11),
        'port': dict(removed_in_version=2.11, type='int', default=830),
        'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME']), removed_in_version=2.11, no_log=True),
        'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), removed_in_version=2.11, no_log=True),
        'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), removed_in_version=2.11, type='path'),
        'hostkey_verify': dict(removed_in_version=2.11, type='bool', default=True),
        'look_for_keys': dict(removed_in_version=2.11, type='bool', default=True),
        'timeout': dict(removed_in_version=2.11, type='int', default=10),
    }
    argument_spec.update(netconf_top_spec)

    mutually_exclusive = [('content', 'src', 'source', 'delete', 'confirm_commit')]
    required_one_of = [('content', 'src', 'source', 'delete', 'confirm_commit')]

    module = AnsibleModule(argument_spec=argument_spec,
                           required_one_of=required_one_of,
                           mutually_exclusive=mutually_exclusive,
                           supports_check_mode=True)

    if module.params['src']:
        module.deprecate(msg="argument 'src' has been deprecated. Use file lookup plugin instead to read file contents.",
                         version="2.11")

    config = module.params['content'] or module.params['src']
    target = module.params['target']
    lock = module.params['lock']
    source = module.params['source_datastore']
    delete = module.params['delete']
    confirm_commit = module.params['confirm_commit']
    confirm = module.params['confirm']
    validate = module.params['validate']
    save = module.params['save']

    conn = Connection(module._socket_path)
    capabilities = get_capabilities(module)
    operations = capabilities['device_operations']

    supports_commit = operations.get('supports_commit', False)
    supports_writable_running = operations.get('supports_writable_running', False)
    supports_startup = operations.get('supports_startup', False)

    # identify target datastore
    if target == 'candidate' and not supports_commit:
        module.fail_json(msg=':candidate is not supported by this netconf server')
    elif target == 'running' and not supports_writable_running:
        module.fail_json(msg=':writable-running is not supported by this netconf server')
    elif target == 'auto':
        if supports_commit:
            target = 'candidate'
        elif supports_writable_running:
            target = 'running'
        else:
            module.fail_json(msg='neither :candidate nor :writable-running are supported by this netconf server')

    # Netconf server capability validation against input options
    if save and not supports_startup:
        module.fail_json(msg='cannot copy <%s/> to <startup/>, while :startup is not supported' % target)

    if confirm_commit and not operations.get('supports_confirm_commit', False):
        module.fail_json(msg='confirm commit is not supported by Netconf server')

    if (confirm > 0) and not operations.get('supports_confirm_commit', False):
        module.fail_json(msg='confirm commit is not supported by this netconf server, given confirm timeout: %d' % confirm)

    if validate and not operations.get('supports_validate', False):
        module.fail_json(msg='validate is not supported by this netconf server')

    if lock == 'never':
        execute_lock = False
    elif target in operations.get('lock_datastore', []):
        # lock is requested (always/if-support) and supported => lets do it
        execute_lock = True
    else:
        # lock is requested (always/if-supported) but not supported => issue warning
        module.warn("lock operation on '%s' source is not supported on this device" % target)
        execute_lock = (lock == 'always')

    result = {'changed': False, 'server_capabilities': capabilities.get('server_capabilities', [])}
    before = None
    after = None
    locked = False
    try:
        if module.params['backup']:
            response = get_config(module, target, lock=execute_lock)
            before = to_text(response, errors='surrogate_then_replace').strip()
            result['__backup__'] = before.strip()
        if validate:
            conn.validate(target)
        if source:
            if not module.check_mode:
                conn.copy(source, target)
            result['changed'] = True
        elif delete:
            if not module.check_mode:
                conn.delete(target)
            result['changed'] = True
        elif confirm_commit:
            if not module.check_mode:
                conn.commit()
            result['changed'] = True
        elif config:
            if module.check_mode and not supports_commit:
                module.warn("check mode not supported as Netconf server doesn't support candidate capability")
                result['changed'] = True
                module.exit_json(**result)

            if execute_lock:
                conn.lock(target=target)
                locked = True
            if before is None:
                before = to_text(conn.get_config(source=target), errors='surrogate_then_replace').strip()

            kwargs = {
                'config': config,
                'target': target,
                'default_operation': module.params['default_operation'],
                'error_option': module.params['error_option'],
                'format': module.params['format'],
            }

            conn.edit_config(**kwargs)

            if supports_commit and module.params['commit']:
                after = to_text(conn.get_config(source='candidate'), errors='surrogate_then_replace').strip()
                if not module.check_mode:
                    confirm_timeout = confirm if confirm > 0 else None
                    confirmed_commit = True if confirm_timeout else False
                    conn.commit(confirmed=confirmed_commit, timeout=confirm_timeout)
                else:
                    conn.discard_changes()

            if after is None:
                after = to_text(conn.get_config(source='running'), errors='surrogate_then_replace').strip()

            sanitized_before = sanitize_xml(before)
            sanitized_after = sanitize_xml(after)
            if sanitized_before != sanitized_after:
                result['changed'] = True

            if result['changed']:
                if save and not module.check_mode:
                    conn.copy_config(target, 'startup')
                if module._diff:
                    result['diff'] = {'before': sanitized_before, 'after': sanitized_after}

    except ConnectionError as e:
        module.fail_json(msg=to_text(e, errors='surrogate_then_replace').strip())
    finally:
        if locked:
            conn.unlock(target=target)

    module.exit_json(**result)
def main():
    """ main entry point for module execution
    """
    backup_spec = dict(filename=dict(), dir_path=dict(type="path"))
    argument_spec = dict(
        content=dict(aliases=["xml"]),
        target=dict(
            choices=["auto", "candidate", "running"],
            default="auto",
            aliases=["datastore"],
        ),
        source_datastore=dict(aliases=["source"]),
        format=dict(choices=["xml", "text"], default="xml"),
        lock=dict(
            choices=["never", "always", "if-supported"], default="always"
        ),
        default_operation=dict(choices=["merge", "replace", "none"]),
        confirm=dict(type="int", default=0),
        confirm_commit=dict(type="bool", default=False),
        error_option=dict(
            choices=[
                "stop-on-error",
                "continue-on-error",
                "rollback-on-error",
            ],
            default="stop-on-error",
        ),
        backup=dict(type="bool", default=False),
        backup_options=dict(type="dict", options=backup_spec),
        save=dict(type="bool", default=False),
        delete=dict(type="bool", default=False),
        commit=dict(type="bool", default=True),
        validate=dict(type="bool", default=False),
        get_filter=dict(),
    )

    # deprecated options
    netconf_top_spec = {
        "src": dict(
            type="path",
            removed_at_date="2020-12-01",
            removed_from_collection="ansible.netcommon",
        ),
        "host": dict(
            removed_at_date="2020-12-01",
            removed_from_collection="ansible.netcommon",
        ),
        "port": dict(
            removed_at_date="2020-12-01",
            removed_from_collection="ansible.netcommon",
            type="int",
            default=830,
        ),
        "username": dict(
            fallback=(env_fallback, ["ANSIBLE_NET_USERNAME"]),
            removed_at_date="2020-12-01",
            removed_from_collection="ansible.netcommon",
            no_log=True,
        ),
        "password": dict(
            fallback=(env_fallback, ["ANSIBLE_NET_PASSWORD"]),
            removed_at_date="2020-12-01",
            removed_from_collection="ansible.netcommon",
            no_log=True,
        ),
        "ssh_keyfile": dict(
            fallback=(env_fallback, ["ANSIBLE_NET_SSH_KEYFILE"]),
            removed_at_date="2020-12-01",
            removed_from_collection="ansible.netcommon",
            type="path",
        ),
        "hostkey_verify": dict(
            removed_at_date="2020-12-01",
            removed_from_collection="ansible.netcommon",
            type="bool",
            default=True,
        ),
        "look_for_keys": dict(
            removed_at_date="2020-12-01",
            removed_from_collection="ansible.netcommon",
            type="bool",
            default=True,
        ),
        "timeout": dict(
            removed_at_date="2020-12-01",
            removed_from_collection="ansible.netcommon",
            type="int",
            default=10,
        ),
    }
    argument_spec.update(netconf_top_spec)

    mutually_exclusive = [
        ("content", "src", "source_datastore", "delete", "confirm_commit")
    ]
    required_one_of = [
        ("content", "src", "source_datastore", "delete", "confirm_commit")
    ]

    module = AnsibleModule(
        argument_spec=argument_spec,
        required_one_of=required_one_of,
        mutually_exclusive=mutually_exclusive,
        supports_check_mode=True,
    )

    config = module.params["content"] or module.params["src"]
    target = module.params["target"]
    lock = module.params["lock"]
    source = module.params["source_datastore"]
    delete = module.params["delete"]
    confirm_commit = module.params["confirm_commit"]
    confirm = module.params["confirm"]
    validate = module.params["validate"]
    save = module.params["save"]
    filter = module.params["get_filter"]
    format = module.params["format"]
    filter_type = get_filter_type(filter)

    conn = Connection(module._socket_path)
    capabilities = get_capabilities(module)
    operations = capabilities["device_operations"]

    supports_commit = operations.get("supports_commit", False)
    supports_writable_running = operations.get(
        "supports_writable_running", False
    )
    supports_startup = operations.get("supports_startup", False)

    # identify target datastore
    if target == "candidate" and not supports_commit:
        module.fail_json(
            msg=":candidate is not supported by this netconf server"
        )
    elif target == "running" and not supports_writable_running:
        module.fail_json(
            msg=":writable-running is not supported by this netconf server"
        )
    elif target == "auto":
        if supports_commit:
            target = "candidate"
        elif supports_writable_running:
            target = "running"
        else:
            module.fail_json(
                msg="neither :candidate nor :writable-running are supported by this netconf server"
            )

    # Netconf server capability validation against input options
    if save and not supports_startup:
        module.fail_json(
            msg="cannot copy <%s/> to <startup/>, while :startup is not supported"
            % target
        )

    if confirm_commit and not operations.get("supports_confirm_commit", False):
        module.fail_json(
            msg="confirm commit is not supported by Netconf server"
        )

    if (confirm > 0) and not operations.get("supports_confirm_commit", False):
        module.fail_json(
            msg="confirm commit is not supported by this netconf server, given confirm timeout: %d"
            % confirm
        )

    if validate and not operations.get("supports_validate", False):
        module.fail_json(
            msg="validate is not supported by this netconf server"
        )

    if filter_type == "xpath" and not operations.get("supports_xpath", False):
        module.fail_json(
            msg="filter value '%s' of type xpath is not supported on this device"
            % filter
        )

    filter_spec = (filter_type, filter) if filter_type else None

    if lock == "never":
        execute_lock = False
    elif target in operations.get("lock_datastore", []):
        # lock is requested (always/if-support) and supported => lets do it
        execute_lock = True
    else:
        # lock is requested (always/if-supported) but not supported => issue warning
        module.warn(
            "lock operation on '%s' source is not supported on this device"
            % target
        )
        execute_lock = lock == "always"

    result = {
        "changed": False,
        "server_capabilities": capabilities.get("server_capabilities", []),
    }
    before = None
    after = None
    locked = False
    try:
        if module.params["backup"]:
            response = get_config(
                module, target, filter_spec, lock=execute_lock
            )
            before = to_text(
                tostring(response), errors="surrogate_then_replace"
            ).strip()
            result["__backup__"] = before.strip()
        if validate:
            conn.validate(target)
        if source:
            if not module.check_mode:
                conn.copy(source, target)
            result["changed"] = True
        elif delete:
            if not module.check_mode:
                conn.delete(target)
            result["changed"] = True
        elif confirm_commit:
            if not module.check_mode:
                conn.commit()
            result["changed"] = True
        elif config:
            if module.check_mode and not supports_commit:
                module.warn(
                    "check mode not supported as Netconf server doesn't support candidate capability"
                )
                result["changed"] = True
                module.exit_json(**result)

            if execute_lock:
                conn.lock(target=target)
                locked = True
            if before is None:
                before = to_text(
                    conn.get_config(source=target, filter=filter_spec),
                    errors="surrogate_then_replace",
                ).strip()

            validate_config(module, config, format)
            kwargs = {
                "config": config,
                "target": target,
                "default_operation": module.params["default_operation"],
                "error_option": module.params["error_option"],
                "format": format,
            }

            conn.edit_config(**kwargs)

            if supports_commit and module.params["commit"]:
                after = to_text(
                    conn.get_config(source="candidate", filter=filter_spec),
                    errors="surrogate_then_replace",
                ).strip()
                if not module.check_mode:
                    confirm_timeout = confirm if confirm > 0 else None
                    confirmed_commit = True if confirm_timeout else False
                    conn.commit(
                        confirmed=confirmed_commit, timeout=confirm_timeout
                    )
                else:
                    conn.discard_changes()

            if after is None:
                after = to_text(
                    conn.get_config(source="running", filter=filter_spec),
                    errors="surrogate_then_replace",
                ).strip()

            sanitized_before = sanitize_xml(before)
            sanitized_after = sanitize_xml(after)
            if sanitized_before != sanitized_after:
                result["changed"] = True

            if result["changed"]:
                if save and not module.check_mode:
                    conn.copy_config(target, "startup")
                if module._diff:
                    result["diff"] = {
                        "before": sanitized_before,
                        "after": sanitized_after,
                    }

    except ConnectionError as e:
        module.fail_json(
            msg=to_text(e, errors="surrogate_then_replace").strip()
        )
    finally:
        if locked:
            conn.unlock(target=target)

    module.exit_json(**result)
def main():
    """ main entry point for module execution
    """
    backup_spec = dict(filename=dict(), dir_path=dict(type="path"))
    argument_spec = dict(
        content=dict(aliases=["xml"], type="raw"),
        target=dict(
            choices=["auto", "candidate", "running"],
            default="auto",
            aliases=["datastore"],
        ),
        source_datastore=dict(aliases=["source"]),
        format=dict(choices=["xml", "text", "json"]),
        lock=dict(
            choices=["never", "always", "if-supported"], default="always"
        ),
        default_operation=dict(choices=["merge", "replace", "none"]),
        confirm=dict(type="int", default=0),
        confirm_commit=dict(type="bool", default=False),
        error_option=dict(
            choices=[
                "stop-on-error",
                "continue-on-error",
                "rollback-on-error",
            ],
            default="stop-on-error",
        ),
        backup=dict(type="bool", default=False),
        backup_options=dict(type="dict", options=backup_spec),
        save=dict(type="bool", default=False),
        delete=dict(type="bool", default=False),
        commit=dict(type="bool", default=True),
        validate=dict(type="bool", default=False),
        get_filter=dict(type="raw"),
    )

    mutually_exclusive = [
        ("content", "source_datastore", "delete", "confirm_commit")
    ]
    required_one_of = [
        ("content", "source_datastore", "delete", "confirm_commit")
    ]

    module = AnsibleModule(
        argument_spec=argument_spec,
        required_one_of=required_one_of,
        mutually_exclusive=mutually_exclusive,
        supports_check_mode=True,
    )

    config = module.params["content"]
    target = module.params["target"]
    lock = module.params["lock"]
    source = module.params["source_datastore"]
    delete = module.params["delete"]
    confirm_commit = module.params["confirm_commit"]
    confirm = module.params["confirm"]
    validate = module.params["validate"]
    save = module.params["save"]
    filter = module.params["get_filter"]
    format = module.params["format"]

    try:
        filter_data, filter_type = validate_and_normalize_data(filter)
    except Exception as exc:
        module.fail_json(msg=to_text(exc))

    if filter_type == "xml":
        filter_type = "subtree"
    elif filter_type == "json":
        try:
            filter = dict_to_xml(filter_data)
        except Exception as exc:
            module.fail_json(msg=to_text(exc))
        filter_type = "subtree"
    elif filter_type == "xpath":
        pass
    elif filter_type is None:
        if filter_data is not None:
            # to maintain backward compatibility for ansible 2.9 which
            # defaults to "subtree" filter type
            filter_type = "subtree"
            module.warn(
                "The data format of get_filter option value couldn't be identified, hence set to 'subtree'"
            )
        else:
            pass
    else:
        module.fail_json(
            msg="Invalid filter type detected %s for get_filter value %s"
            % (filter_type, filter)
        )

    conn = Connection(module._socket_path)
    capabilities = get_capabilities(module)
    operations = capabilities["device_operations"]

    supports_commit = operations.get("supports_commit", False)
    supports_writable_running = operations.get(
        "supports_writable_running", False
    )
    supports_startup = operations.get("supports_startup", False)

    # identify target datastore
    if target == "candidate" and not supports_commit:
        module.fail_json(
            msg=":candidate is not supported by this netconf server"
        )
    elif target == "running" and not supports_writable_running:
        module.fail_json(
            msg=":writable-running is not supported by this netconf server"
        )
    elif target == "auto":
        if supports_commit:
            target = "candidate"
        elif supports_writable_running:
            target = "running"
        else:
            module.fail_json(
                msg="neither :candidate nor :writable-running are supported by this netconf server"
            )

    # Netconf server capability validation against input options
    if save and not supports_startup:
        module.fail_json(
            msg="cannot copy <%s/> to <startup/>, while :startup is not supported"
            % target
        )

    if confirm_commit and not operations.get("supports_confirm_commit", False):
        module.fail_json(
            msg="confirm commit is not supported by Netconf server"
        )

    if (confirm > 0) and not operations.get("supports_confirm_commit", False):
        module.fail_json(
            msg="confirm commit is not supported by this netconf server, given confirm timeout: %d"
            % confirm
        )

    if validate and not operations.get("supports_validate", False):
        module.fail_json(
            msg="validate is not supported by this netconf server"
        )

    if filter_type == "xpath" and not operations.get("supports_xpath", False):
        module.fail_json(
            msg="filter value '%s' of type xpath is not supported on this device"
            % filter
        )

    filter_spec = (filter_type, filter) if filter_type else None

    if lock == "never":
        execute_lock = False
    elif target in operations.get("lock_datastore", []):
        # lock is requested (always/if-support) and supported => lets do it
        execute_lock = True
    else:
        # lock is requested (always/if-supported) but not supported => issue warning
        module.warn(
            "lock operation on '%s' source is not supported on this device"
            % target
        )
        execute_lock = lock == "always"

    result = {
        "changed": False,
        "server_capabilities": capabilities.get("server_capabilities", []),
    }
    before = None
    after = None
    locked = False
    try:
        if module.params["backup"]:
            response = get_config(
                module, target, filter_spec, lock=execute_lock
            )
            before = to_text(
                tostring(response), errors="surrogate_then_replace"
            ).strip()
            result["__backup__"] = before.strip()
        if validate:
            conn.validate(target)
        if source:
            if not module.check_mode:
                conn.copy(source, target)
            result["changed"] = True
        elif delete:
            if not module.check_mode:
                conn.delete(target)
            result["changed"] = True
        elif confirm_commit:
            if not module.check_mode:
                conn.commit()
            result["changed"] = True
        elif config:
            if module.check_mode and not supports_commit:
                module.warn(
                    "check mode not supported as Netconf server doesn't support candidate capability"
                )
                result["changed"] = True
                module.exit_json(**result)

            if execute_lock:
                conn.lock(target=target)
                locked = True
            if before is None:
                before = to_text(
                    conn.get_config(source=target, filter=filter_spec),
                    errors="surrogate_then_replace",
                ).strip()

            if format != "text":
                # check for format of type json/xml/xpath
                try:
                    config_obj, config_format = validate_and_normalize_data(
                        config, format
                    )
                except Exception as exc:
                    module.fail_json(msg=to_text(exc))

                if config_format == "json":
                    try:
                        config = dict_to_xml(config_obj)
                    except Exception as exc:
                        module.fail_json(msg=to_text(exc))
                    format = "xml"
                elif config_format is None:
                    format = "xml"
                    module.warn(
                        "The data format of content option value couldn't be identified, hence set to 'xml'"
                    )
                else:
                    format = config_format

            validate_config(module, config, format)

            kwargs = {
                "config": config,
                "target": target,
                "default_operation": module.params["default_operation"],
                "error_option": module.params["error_option"],
                "format": format,
            }

            conn.edit_config(**kwargs)

            if supports_commit and module.params["commit"]:
                after = to_text(
                    conn.get_config(source="candidate", filter=filter_spec),
                    errors="surrogate_then_replace",
                ).strip()
                if not module.check_mode:
                    confirm_timeout = confirm if confirm > 0 else None
                    confirmed_commit = True if confirm_timeout else False
                    conn.commit(
                        confirmed=confirmed_commit, timeout=confirm_timeout
                    )
                else:
                    conn.discard_changes()

            if after is None:
                after = to_text(
                    conn.get_config(source="running", filter=filter_spec),
                    errors="surrogate_then_replace",
                ).strip()

            sanitized_before = sanitize_xml(before)
            sanitized_after = sanitize_xml(after)
            if sanitized_before != sanitized_after:
                result["changed"] = True

            if result["changed"]:
                if save and not module.check_mode:
                    conn.copy_config(target, "startup")
                if module._diff:
                    result["diff"] = {
                        "before": sanitized_before,
                        "after": sanitized_after,
                    }

    except ConnectionError as e:
        module.fail_json(
            msg=to_text(e, errors="surrogate_then_replace").strip()
        )
    finally:
        if locked:
            conn.unlock(target=target)

    module.exit_json(**result)
Exemple #4
0
class RmModule(RmModuleRender):  # pylint: disable=R0902
    """ rm
    """
    def __init__(self, *_args, **kwargs):
        self._empty_fact_val = kwargs.get('empty_fact_val', [])
        self._facts_module = kwargs.get('facts_module', None)
        self._gather_subset = kwargs.get('gather_subset', ['!all', '!min'])
        self._module = kwargs.get('module', None)
        self._resource = kwargs.get('resource', None)
        self._tmplt = kwargs.get('tmplt', None)

        self._connection = None
        self.state = self._module.params['state']

        self.before = self.gather_current()
        self.changed = False
        self.commands = []
        self.warnings = []

        self.have = deepcopy(self.before)
        self.want = remove_empties(
            self._module.params).get('config', self._empty_fact_val)

        self._get_connection()
        super(RmModule, self).__init__(tmplt=self._tmplt)

    def gather_current(self):
        if self.state == 'rendered':
            return self._empty_fact_val
        return deepcopy(self.get_facts(self._empty_fact_val))

    @property
    def result(self):
        """ result
        """
        if self.state == 'gathered':
            before = self.before
            after = self._empty_fact_val
        elif self.state == 'rendered':
            before = self._empty_fact_val
            after = self.want
        else:
            before = self.before
            after = self.get_facts(self._empty_fact_val)
        result = {'after': after,
                  'changed': self.changed,
                  'commands': self.commands,
                  'before': before,
                  'warnings': self.warnings}
        return result

    def addcmd(self, data, tmplt, negate=False):
        """ addcmd
        """
        command = self.render(data, tmplt, negate)
        if command:
            self.commands.append(command)

    def addcmd_first_found(self, data, tmplts, negate=False):
        """ addcmd first found
        """
        for pname in tmplts:
            before = len(self.commands)
            self.addcmd(data, pname, negate)
            if len(self.commands) != before:
                break

    def get_facts(self, empty_val=None):
        """ Get the 'facts' (the current configuration)

        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        if empty_val is None:
            empty_val = []
        facts, _warnings = self._facts_module.get_facts(
            resource_facts_type=[self._resource])

        facts = facts['ansible_network_resources'].get(self._resource)
        if not facts:
            return empty_val
        return facts

    def _get_connection(self):
        if self.state != 'rendered':
            if self._connection:
                return self._connection
            # pylint: disable=W0212
            self._connection = Connection(self._module._socket_path)
            # pylint: enable=W0212
            return self._connection
        return None

    def compare(self, parsers, want=None, have=None):
        """ compare
        """
        if want is None:
            want = self.want
        if have is None:
            have = self.have
        for parser in to_list(parsers):
            compval = self.get_parser(parser).get('compval')
            if not compval:
                compval = parser
            inw = get_from_dict(want, compval)
            inh = get_from_dict(have, compval)
            if inw is not None and inw != inh:
                if isinstance(inw, bool):
                    self.addcmd(want, parser, not inw)
                else:
                    self.addcmd(want, parser, False)
            elif inw is None and inh is not None:
                if isinstance(inh, bool):
                    self.addcmd(have, parser, inh)
                else:
                    self.addcmd(have, parser, True)

    def run_commands(self):
        """ run_commands
        """
        if self.commands:
            if not self._module.check_mode:
                if self.state != 'rendered':
                    response = self._connection.edit_config(self.commands)
                    self.warnings.extend([r for r in response['response'] if r])
                    self.changed = True