Esempio n. 1
0
def _run_one(netconf, message_id, operation, netconf_namespace, data, xmlns):
    """run one call by netconf connection"""
    # rpc
    ctx.logger.info("rpc call")
    parent = utils.rpc_gen(message_id, operation, netconf_namespace, data,
                           xmlns)

    # send rpc
    rpc_string = etree.tostring(parent,
                                pretty_print=True,
                                xml_declaration=True,
                                encoding='UTF-8')
    ctx.logger.info("i sent: " + rpc_string)
    response = netconf.send(rpc_string)
    ctx.logger.info("i recieved:" + response)

    response_dict = _parse_response(xmlns, netconf_namespace, response)
    ctx.logger.info("package will be :" + str(response_dict))
    return response_dict
Esempio n. 2
0
def _run_one(
    netconf, message_id, operation, netconf_namespace, data, xmlns
):
    """run one call by netconf connection"""
    # rpc
    ctx.logger.info("rpc call")
    parent = utils.rpc_gen(
        message_id, operation, netconf_namespace, data, xmlns
    )

    # send rpc
    rpc_string = etree.tostring(
        parent, pretty_print=True, xml_declaration=True,
        encoding='UTF-8'
    )
    ctx.logger.info("i sent: " + rpc_string)
    response = netconf.send(rpc_string)
    ctx.logger.info("i recieved:" + response)

    response_dict = _parse_response(
        xmlns, netconf_namespace, response
    )
    ctx.logger.info("package will be :" + str(response_dict))
    return response_dict
Esempio n. 3
0
def run(**kwargs):
    """main entry point for all calls"""

    calls = kwargs.get('calls', [])
    if not calls:
        ctx.logger.info("No calls")
        return

    # credentials
    properties = ctx.node.properties
    ip = properties.get('netconf_auth', {}).get('ip')
    user = properties.get('netconf_auth', {}).get('user')
    password = properties.get('netconf_auth', {}).get('password')
    key_content = properties.get('netconf_auth', {}).get('key_content')
    if not ip or not user or (not password and not key_content):
        raise cfy_exc.NonRecoverableError("please check your credentials")

    # some random initial message id, for have different between calls
    message_id = int((time.time() * 100) % 100 * 1000)

    # xml namespaces and capabilities
    xmlns = properties.get('metadata', {}).get('xmlns', {})
    # override by system namespaces
    xmlns = _merge_ns(xmlns, properties.get('base_xmlns', {}))

    netconf_namespace, xmlns = utils.update_xmlns(xmlns)
    capabilities = properties.get('metadata', {}).get('capabilities')

    # connect
    ctx.logger.info("use %s@%s for login" % (user, ip))
    hello_string = _generate_hello(xmlns, netconf_namespace, capabilities)
    ctx.logger.info("i sent: " + hello_string)
    netconf = netconf_connection.connection()
    capabilities = netconf.connect(ip, user, hello_string, password,
                                   key_content)
    ctx.logger.info("i recieved: " + capabilities)

    if _server_support_1_1(xmlns, netconf_namespace, capabilities):
        ctx.logger.info("i will use version 1.1 of netconf protocol")
        netconf.current_level = netconf_connection.NETCONF_1_1_CAPABILITY

    if 'lock' in kwargs:
        message_id = message_id + 1
        for name in kwargs['lock']:
            _lock(name, True, netconf, message_id, netconf_namespace, xmlns)

    if 'back_database' in kwargs and 'front_database' in kwargs:
        message_id = message_id + 1
        _copy(kwargs['front_database'], kwargs['back_database'], netconf,
              message_id, netconf_namespace, xmlns)

    # recheck before real send
    for call in calls:
        operation = call.get('action')
        if not operation:
            continue
        data = call.get('payload', {})

        # gen xml for check
        parent = utils.rpc_gen(message_id, operation, netconf_namespace, data,
                               xmlns)

        # validate rpc
        validation = call.get('validation', {})
        xpath = validation.get('xpath')
        if xpath:
            ctx.logger.info("We have some validation rules for " + str(xpath))
            rng = validation.get('rng')
            sch = validation.get('sch')
            utils.xml_validate(parent, xmlns, xpath, rng, sch)

    # we can have several calls in one session,
    # like lock, edit-config, unlock
    for call in calls:
        operation = call.get('action')
        if not operation:
            ctx.logger.info("No operations")
            continue
        data = call.get('payload', {})

        message_id = message_id + 1

        if "@" not in operation:
            operation = "_@" + operation

        _update_data(data, operation, netconf_namespace,
                     kwargs.get('back_database'))

        response_dict = _run_one(netconf, message_id, operation,
                                 netconf_namespace, data, xmlns)

        # save results to runtime properties
        save_to = call.get('save_to')
        if save_to:
            ctx.instance.runtime_properties[save_to] = response_dict
            ctx.instance.runtime_properties[save_to + "_ns"] = xmlns

    if 'back_database' in kwargs and 'front_database' in kwargs:
        message_id = message_id + 1
        _copy(kwargs['back_database'], kwargs['front_database'], netconf,
              message_id, netconf_namespace, xmlns)

    if 'lock' in kwargs:
        message_id = message_id + 1
        for name in kwargs['lock']:
            _lock(name, False, netconf, message_id, netconf_namespace, xmlns)

    # goodbye
    ctx.logger.info("connection close")
    message_id = message_id + 1
    goodbye_string = _generate_goodbye(xmlns, netconf_namespace, message_id)
    ctx.logger.info("i sent: " + goodbye_string)

    response = netconf.close(goodbye_string)
    ctx.logger.info("i recieved: " + response)
Esempio n. 4
0
def run(**kwargs):
    """main entry point for all calls"""

    calls = kwargs.get('calls', [])
    if not calls:
        ctx.logger.info("No calls")
        return

    # credentials
    properties = ctx.node.properties
    ip = properties.get('netconf_auth', {}).get('ip')
    user = properties.get('netconf_auth', {}).get('user')
    password = properties.get('netconf_auth', {}).get('password')
    key_content = properties.get('netconf_auth', {}).get('key_content')
    port = properties.get('netconf_auth', {}).get('port', 830)
    if not ip or not user or (not password and not key_content):
        raise cfy_exc.NonRecoverableError(
            "please check your credentials"
        )

    # some random initial message id, for have different between calls
    message_id = int((time.time() * 100) % 100 * 1000)

    # xml namespaces and capabilities
    xmlns = properties.get('metadata', {}).get('xmlns', {})

    # override by system namespaces
    xmlns = _merge_ns(xmlns, properties.get('base_xmlns', {}))

    netconf_namespace, xmlns = utils.update_xmlns(
        xmlns
    )
    capabilities = properties.get('metadata', {}).get('capabilities')

    # connect
    ctx.logger.info("use %s@%s for login" % (user, ip))
    hello_string = _generate_hello(
        xmlns, netconf_namespace, capabilities
    )
    ctx.logger.info("i sent: " + hello_string)
    netconf = netconf_connection.connection()
    capabilities = netconf.connect(
        ip, user, hello_string, password, key_content, port
    )
    ctx.logger.info("i recieved: " + capabilities)

    if _server_support_1_1(xmlns, netconf_namespace, capabilities):
        ctx.logger.info("i will use version 1.1 of netconf protocol")
        netconf.current_level = netconf_connection.NETCONF_1_1_CAPABILITY

    if 'lock' in kwargs:
        message_id = message_id + 1
        for name in kwargs['lock']:
            _lock(
                name, True, netconf, message_id, netconf_namespace,
                xmlns
            )

    if 'back_database' in kwargs and 'front_database' in kwargs:
        message_id = message_id + 1
        _copy(
            kwargs['front_database'], kwargs['back_database'],
            netconf, message_id, netconf_namespace, xmlns
        )

    # recheck before real send
    for call in calls:
        operation = call.get('action')
        if not operation:
            continue
        data = call.get('payload', {})

        # gen xml for check
        parent = utils.rpc_gen(
            message_id, operation, netconf_namespace, data, xmlns
        )

        # try to validate
        validate_xml = call.get('validate_xml', True)

        if validate_xml:

            # validate rpc
            rng, sch, xpath = _gen_relaxng_with_schematron(
                properties.get('metadata', {}).get('dsdl'),
                call.get('action')
            )
        else:
            xpath = None

        if xpath:
            ctx.logger.info(
                "We have some validation rules for '{}'".format(
                    str(xpath)
                )
            )

            utils.xml_validate(
                parent, xmlns, xpath, rng, sch
            )

    # we can have several calls in one session,
    # like lock, edit-config, unlock
    for call in calls:
        operation = call.get('action')
        if not operation:
            ctx.logger.info("No operations")
            continue
        data = call.get('payload', {})

        message_id = message_id + 1

        if "@" not in operation:
            operation = "_@" + operation

        _update_data(
            data, operation, netconf_namespace,
            kwargs.get('back_database')
        )

        response_dict = _run_one(
            netconf, message_id, operation, netconf_namespace, data,
            xmlns
        )

        # save results to runtime properties
        save_to = call.get('save_to')
        if save_to:
            ctx.instance.runtime_properties[save_to] = response_dict
            ctx.instance.runtime_properties[save_to + "_ns"] = xmlns

    if 'back_database' in kwargs and 'front_database' in kwargs:
        message_id = message_id + 1
        _copy(
            kwargs['back_database'], kwargs['front_database'],
            netconf, message_id, netconf_namespace, xmlns
        )

    if 'lock' in kwargs:
        message_id = message_id + 1
        for name in kwargs['lock']:
            _lock(
                name, False, netconf, message_id, netconf_namespace,
                xmlns
            )

    # goodbye
    ctx.logger.info("connection close")
    message_id = message_id + 1
    goodbye_string = _generate_goodbye(
        xmlns, netconf_namespace, message_id
    )
    ctx.logger.info("i sent: " + goodbye_string)

    response = netconf.close(goodbye_string)
    ctx.logger.info("i recieved: " + response)