Ejemplo n.º 1
0
    def get_device_info(self):
        device_info = {}
        device_info['network_os'] = 'iosxr'
        install_meta = collections.OrderedDict()
        install_meta.update([
            ('boot-variables', {
                'xpath': 'install/boot-variables',
                'tag': True
            }),
            ('boot-variable', {
                'xpath': 'install/boot-variables/boot-variable',
                'tag': True,
                'lead': True
            }),
            ('software', {
                'xpath': 'install/software',
                'tag': True
            }),
            ('alias-devices', {
                'xpath': 'install/software/alias-devices',
                'tag': True
            }),
            ('alias-device', {
                'xpath': 'install/software/alias-devices/alias-device',
                'tag': True
            }),
            ('m:device-name', {
                'xpath':
                'install/software/alias-devices/alias-device/device-name',
                'value': 'disk0:'
            }),
        ])

        install_filter = build_xml('install', install_meta, opcode='filter')
        try:
            reply = self.get(install_filter)
            resp = remove_namespaces(
                re.sub(r'<\?xml version="1.0" encoding="UTF-8"\?>', '', reply))
            ele_boot_variable = etree_find(resp, 'boot-variable/boot-variable')
            if ele_boot_variable is not None:
                device_info['network_os_image'] = re.split(
                    '[:|,]', ele_boot_variable.text)[1]
            ele_package_name = etree_find(reply, 'package-name')
            if ele_package_name is not None:
                device_info['network_os_package'] = ele_package_name.text
                device_info['network_os_version'] = re.split(
                    '-', ele_package_name.text)[-1]

            hostname_filter = build_xml('host-names', opcode='filter')
            reply = self.get(hostname_filter)
            resp = remove_namespaces(
                re.sub(r'<\?xml version="1.0" encoding="UTF-8"\?>', '', reply))
            hostname_ele = etree_find(resp.strip(), 'host-name')
            device_info[
                'network_os_hostname'] = hostname_ele.text if hostname_ele is not None else None
        except Exception as exc:
            self._connection.queue_message(
                'vvvv', 'Fail to retrieve device info %s' % exc)
        return device_info
Ejemplo n.º 2
0
 def edit_config(self,
                 config=None,
                 format='xml',
                 target='candidate',
                 default_operation=None,
                 test_option=None,
                 error_option=None,
                 remove_ns=False):
     if config is None:
         raise ValueError('config value must be provided')
     try:
         resp = self.m.edit_config(config,
                                   format=format,
                                   target=target,
                                   default_operation=default_operation,
                                   test_option=test_option,
                                   error_option=error_option)
         if remove_ns:
             response = remove_namespaces(resp)
         else:
             response = resp.data_xml if hasattr(resp,
                                                 'data_xml') else resp.xml
         return response
     except RPCError as exc:
         raise Exception(to_xml(exc.xml))
Ejemplo n.º 3
0
def main():
    """entry point for module execution
    """
    argument_spec = dict(
        rpc=dict(type="str", required=True),
        xmlns=dict(type="str"),
        content=dict(),
        display=dict(choices=['json', 'pretty', 'xml'])
    )

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

    rpc = module.params['rpc']
    xmlns = module.params['xmlns']
    content = module.params['content']
    display = module.params['display']

    if rpc is None:
        module.fail_json(msg='argument `rpc` must not be None')

    rpc = rpc.strip()
    if len(rpc) == 0:
        module.fail_json(msg='argument `rpc` must not be empty')

    if rpc in ['close-session']:
        # explicit close-session is not allowed, as this would make the next
        # NETCONF operation to the same host fail
        module.fail_json(msg='unsupported operation `%s`' % rpc)

    if display == 'json' and not HAS_JXMLEASE:
        module.fail_json(msg='jxmlease is required to display response in json format'
                             'but does not appear to be installed. '
                             'It can be installed using `pip install jxmlease`')

    xml_req = get_xml_request(module, rpc, xmlns, content)
    response = dispatch(module, xml_req)

    xml_resp = tostring(response)
    output = None

    if display == 'xml':
        output = remove_namespaces(xml_resp)
    elif display == 'json':
        try:
            output = jxmlease.parse(xml_resp)
        except Exception:
            raise ValueError(xml_resp)
    elif display == 'pretty':
        output = tostring(response, pretty_print=True)

    result = {
        'stdout': xml_resp,
        'output': output
    }

    module.exit_json(**result)
Ejemplo n.º 4
0
def main():
    """entry point for module execution
    """
    argument_spec = dict(
        rpc=dict(type="str", required=True),
        xmlns=dict(type="str"),
        content=dict(),
        display=dict(choices=["json", "pretty", "xml"]),
    )

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

    rpc = module.params["rpc"]
    xmlns = module.params["xmlns"]
    content = module.params["content"]
    display = module.params["display"]

    if rpc is None:
        module.fail_json(msg="argument `rpc` must not be None")

    rpc = rpc.strip()
    if len(rpc) == 0:
        module.fail_json(msg="argument `rpc` must not be empty")

    if rpc in ["close-session"]:
        # explicit close-session is not allowed, as this would make the next
        # NETCONF operation to the same host fail
        module.fail_json(msg="unsupported operation `%s`" % rpc)

    if display == "json" and not HAS_JXMLEASE:
        module.fail_json(
            msg="jxmlease is required to display response in json format"
            "but does not appear to be installed. "
            "It can be installed using `pip install jxmlease`"
        )

    xml_req = get_xml_request(module, rpc, xmlns, content)
    response = dispatch(module, xml_req)

    xml_resp = tostring(response)
    output = None

    if display == "xml":
        output = remove_namespaces(xml_resp)
    elif display == "json":
        try:
            output = jxmlease.parse(xml_resp)
        except Exception:
            raise ValueError(xml_resp)
    elif display == "pretty":
        output = tostring(response, pretty_print=True)

    result = {"stdout": xml_resp, "output": output}

    module.exit_json(**result)
Ejemplo n.º 5
0
 def discard_changes(self, remove_ns=False):
     try:
         resp = self.m.discard_changes()
         if remove_ns:
             response = remove_namespaces(resp)
         else:
             response = resp.data_xml if hasattr(resp,
                                                 'data_xml') else resp.xml
         return response
     except RPCError as exc:
         raise Exception(to_xml(exc.xml))
Ejemplo n.º 6
0
 def validate(self, source="candidate", remove_ns=False):
     try:
         resp = self.m.validate(source=source)
         if remove_ns:
             response = remove_namespaces(resp)
         else:
             response = resp.data_xml if hasattr(resp,
                                                 'data_xml') else resp.xml
         return response
     except RPCError as exc:
         raise Exception(to_xml(exc.xml))
Ejemplo n.º 7
0
 def get_config(self, source=None, filter=None, remove_ns=False):
     if isinstance(filter, list):
         filter = tuple(filter)
     try:
         resp = self.m.get_config(source=source, filter=filter)
         if remove_ns:
             response = remove_namespaces(resp)
         else:
             response = resp.data_xml if hasattr(resp,
                                                 'data_xml') else resp.xml
         return response
     except RPCError as exc:
         raise Exception(to_xml(exc.xml))
Ejemplo n.º 8
0
 def commit(
     self, confirmed=False, timeout=None, persist=None, remove_ns=False
 ):
     try:
         resp = self.m.commit(
             confirmed=confirmed, timeout=timeout, persist=persist
         )
         if remove_ns:
             response = remove_namespaces(resp)
         else:
             response = (
                 resp.data_xml if hasattr(resp, "data_xml") else resp.xml
             )
         return response
     except RPCError as exc:
         raise Exception(to_xml(exc.xml))
Ejemplo n.º 9
0
 def commit(
     self,
     confirmed=False,
     timeout=None,
     persist=None,
     remove_ns=False,
 ):
     timeout = to_text(timeout, errors="surrogate_or_strict")
     try:
         resp = self.m.commit(
             confirmed=confirmed,
             timeout=timeout,
             persist=persist,
         )
         if remove_ns:
             response = remove_namespaces(resp)
         else:
             response = resp.data_xml if hasattr(resp,
                                                 "data_xml") else resp.xml
         return response
     except RPCError as exc:
         raise Exception(to_xml(exc.xml))
Ejemplo n.º 10
0
def main():
    """entry point for module execution"""
    argument_spec = dict(
        source=dict(choices=["running", "candidate", "startup"]),
        filter=dict(type="raw"),
        display=dict(choices=["json", "native", "pretty", "xml"]),
        lock=dict(
            default="never", choices=["never", "always", "if-supported"]
        ),
    )

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

    capabilities = get_capabilities(module)
    operations = capabilities["device_operations"]

    source = module.params["source"]
    filter, tipe = ensure_xml_or_str(module.params["filter"], "filter")
    if tipe == "xml":
        filter_type = "subtree"
    elif tipe == "str":
        filter_type = "xpath"
    else:
        filter_type = tipe

    lock = module.params["lock"]
    display = module.params["display"]

    if source == "candidate" and not operations.get("supports_commit", False):
        module.fail_json(
            msg="candidate source is not supported on this device"
        )

    if source == "startup" and not operations.get("supports_startup", False):
        module.fail_json(msg="startup source is not supported on this device")

    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
        )

    # If source is None, NETCONF <get> operation is issued, reading config/state data
    # from the running datastore. The python expression "(source or 'running')" results
    # in the value of source (if not None) or the value 'running' (if source is None).

    if lock == "never":
        execute_lock = False
    elif (source or "running") 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"
            % (source or "running")
        )
        execute_lock = lock == "always"

    if display == "json" and not HAS_JXMLEASE:
        module.fail_json(
            msg="jxmlease is required to display response in json format"
            "but does not appear to be installed. "
            "It can be installed using `pip install jxmlease`"
        )

    filter_spec = (filter_type, filter) if filter_type else None

    if source is not None:
        response = get_config(module, source, filter_spec, execute_lock)
    else:
        response = get(module, filter_spec, execute_lock)

    xml_resp = to_text(tostring(response))
    output = None

    if display == "xml":
        output = remove_namespaces(xml_resp)
    elif display == "json":
        try:
            output = jxmlease.parse(xml_resp)
        except Exception:
            raise ValueError(xml_resp)

    elif display == "pretty":
        output = to_text(tostring(response, pretty_print=True))
    elif display == "native":
        output = xml_to_native(tostring(response), "display")

    result = {"stdout": xml_resp, "output": output}

    module.exit_json(**result)
Ejemplo n.º 11
0
    def get_device_info(self):
        device_info = {}
        device_info["network_os"] = "iosxr"
        install_meta = collections.OrderedDict()
        install_meta.update([
            ("prepare", {
                "xpath": "install/prepare",
                "tag": True
            }),
            (
                "prepared-boot-image",
                {
                    "xpath": "install/prepare/prepared-boot-image",
                    "tag": True,
                },
            ),
            ("version", {
                "xpath": "install/version",
                "tag": True
            }),
            ("label", {
                "xpath": "install/version/label",
                "tag": True
            }),
            (
                "hardware-info",
                {
                    "xpath": "install/version/hardware-info",
                    "tag": True
                },
            ),
            ("package", {
                "xpath": "install/version/package",
                "tag": True
            }),
        ], )
        install_filter = build_xml(
            "install",
            install_meta,
            opcode="filter",
            namespace="install",
        )
        try:
            reply = self.get(install_filter)
            resp = remove_namespaces(
                re.sub(r'<\?xml version="1.0" encoding="UTF-8"\?>', "",
                       reply), )
            ele_package_name = etree_find(resp.strip(), "name")
            if ele_package_name is not None:
                device_info["network_os_package"] = ele_package_name.text
            ele_label = etree_find(resp.strip(), "label")
            if ele_label is not None:
                device_info["network_os_version"] = ele_label.text

            model_search_strs = [
                r"^[Cc]isco (.+) \(\) processor",
                r"^[Cc]isco (.+) \(revision",
                r"^[Cc]isco (\S+ \S+).+bytes of .*memory",
            ]
            ele_hardware_info = etree_find(resp.strip(), "hardware-info")
            if ele_hardware_info is not None:
                for item in model_search_strs:
                    match = re.search(item, ele_hardware_info.text, re.M)
                    if match:
                        device_info["network_os_model"] = match.group(1)
                        break
        except Exception as exc:
            error_msg = to_text(exc, errors="surrogate_or_strict").strip()
            if "bad-namespace" in error_msg:
                device_info = self.get_device_info_old_version()
            else:
                self._connection.queue_message(
                    "vvvv",
                    "Fail to retrieve device info %s" % exc,
                )
        try:
            hostname_filter = build_xml(
                "host-names",
                opcode="filter",
                namespace="host-names",
            )
            reply = self.get(hostname_filter)
            resp = remove_namespaces(
                re.sub(r'<\?xml version="1.0" encoding="UTF-8"\?>', "",
                       reply), )
            hostname_ele = etree_find(resp.strip(), "host-name")
            device_info["network_os_hostname"] = (
                hostname_ele.text if hostname_ele is not None else None)
        except Exception as exc:
            self._connection.queue_message(
                "vvvv",
                "Fail to retrieve device info %s" % exc,
            )
        return device_info
Ejemplo n.º 12
0
    def get_device_info_old_version(self):
        device_info = {}
        device_info["network_os"] = "iosxr"
        install_meta = collections.OrderedDict()
        install_meta.update([
            (
                "boot-variables",
                {
                    "xpath": "install/boot-variables",
                    "tag": True
                },
            ),
            (
                "boot-variable",
                {
                    "xpath": "install/boot-variables/boot-variable",
                    "tag": True,
                    "lead": True,
                },
            ),
            ("software", {
                "xpath": "install/software",
                "tag": True
            }),
            (
                "alias-devices",
                {
                    "xpath": "install/software/alias-devices",
                    "tag": True
                },
            ),
            (
                "alias-device",
                {
                    "xpath": "install/software/alias-devices/alias-device",
                    "tag": True,
                },
            ),
            (
                "m:device-name",
                {
                    "xpath":
                    "install/software/alias-devices/alias-device/device-name",
                    "value": "disk0:",
                },
            ),
        ], )

        install_filter = build_xml(
            "install",
            install_meta,
            opcode="filter",
            namespace="install_old",
        )
        try:
            reply = self.get(install_filter)
            resp = remove_namespaces(
                re.sub(r'<\?xml version="1.0" encoding="UTF-8"\?>', "",
                       reply), )
            ele_boot_variable = etree_find(resp, "boot-variable/boot-variable")
            if ele_boot_variable is not None:
                device_info["network_os_image"] = re.split(
                    "[:|,]",
                    ele_boot_variable.text,
                )[1]
            ele_package_name = etree_find(reply, "package-name")
            if ele_package_name is not None:
                device_info["network_os_package"] = ele_package_name.text
                device_info["network_os_version"] = re.split(
                    "-",
                    ele_package_name.text,
                )[-1]
        except Exception as exc:
            self._connection.queue_message(
                "vvvv",
                "Fail to retrieve device info %s" % exc,
            )
        return device_info
Ejemplo n.º 13
0
def main():
    """entry point for module execution
    """
    argument_spec = dict(
        source=dict(choices=['running', 'candidate', 'startup']),
        filter=dict(),
        display=dict(choices=['json', 'pretty', 'xml']),
        lock=dict(default='never', choices=['never', 'always',
                                            'if-supported']))

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

    capabilities = get_capabilities(module)
    operations = capabilities['device_operations']

    source = module.params['source']
    filter = module.params['filter']
    filter_type = get_filter_type(filter)
    lock = module.params['lock']
    display = module.params['display']

    if source == 'candidate' and not operations.get('supports_commit', False):
        module.fail_json(
            msg='candidate source is not supported on this device')

    if source == 'startup' and not operations.get('supports_startup', False):
        module.fail_json(msg='startup source is not supported on this device')

    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)

    # If source is None, NETCONF <get> operation is issued, reading config/state data
    # from the running datastore. The python expression "(source or 'running')" results
    # in the value of source (if not None) or the value 'running' (if source is None).

    if lock == 'never':
        execute_lock = False
    elif (source or 'running') 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" %
            (source or 'running'))
        execute_lock = (lock == 'always')

    if display == 'json' and not HAS_JXMLEASE:
        module.fail_json(
            msg='jxmlease is required to display response in json format'
            'but does not appear to be installed. '
            'It can be installed using `pip install jxmlease`')

    filter_spec = (filter_type, filter) if filter_type else None

    if source is not None:
        response = get_config(module, source, filter_spec, execute_lock)
    else:
        response = get(module, filter_spec, execute_lock)

    xml_resp = to_text(tostring(response))
    output = None

    if display == 'xml':
        output = remove_namespaces(xml_resp)
    elif display == 'json':
        try:
            output = jxmlease.parse(xml_resp)
        except Exception:
            raise ValueError(xml_resp)
    elif display == 'pretty':
        output = to_text(tostring(response, pretty_print=True))

    result = {'stdout': xml_resp, 'output': output}

    module.exit_json(**result)