Ejemplo n.º 1
0
def netmiko_file_transfer(task, source_file, dest_file, **kwargs):
    """
    Execute Netmiko file_transfer method

    Arguments:
        source_file(str): Source file.
        dest_file(str): Destination file.
        kwargs (dict, optional): Additional arguments to pass to file_transfer

    Returns:
        :obj:`brigade.core.task.Result`:
          * result (``bool``): file exists and MD5 is valid
          * changed (``bool``): the destination file was changed

    """
    net_connect = task.host.get_connection("netmiko")
    kwargs.setdefault("direction", "put")
    scp_result = file_transfer(net_connect,
                               source_file=source_file,
                               dest_file=dest_file,
                               **kwargs)
    if kwargs.get("disable_md5") is True:
        file_valid = scp_result["file_exists"]
    else:
        file_valid = scp_result["file_exists"] and scp_result["file_verified"]
    return Result(host=task.host,
                  result=file_valid,
                  changed=scp_result["file_transferred"])
Ejemplo n.º 2
0
def remote_command(task, command):
    """
    Executes a command locally

    Arguments:
        command (``str``): command to execute

    Returns:
        :obj:`brigade.core.task.Result`:
          * result (``str``): stderr or stdout
          * stdout (``str``): stdout
          * stderr (``srr``): stderr

    Raises:
        :obj:`brigade.core.exceptions.CommandError`: when there is a command error
    """
    client = task.host.get_connection("paramiko")

    chan = client.get_transport().open_session()
    chan.exec_command(command)

    exit_status_code = chan.recv_exit_status()

    with chan.makefile() as f:
        stdout = f.read().decode()
    with chan.makefile_stderr() as f:
        stderr = f.read().decode()

    if exit_status_code:
        raise CommandError(command, exit_status_code, stdout, stderr)

    result = stderr if stderr else stdout
    return Result(result=result, host=task.host, stderr=stderr, stdout=stdout)
Ejemplo n.º 3
0
def napalm_configure(task,
                     dry_run=None,
                     filename=None,
                     configuration=None,
                     replace=False):
    """
    Loads configuration into a network devices using napalm

    Arguments:
        dry_run (bool): Whether to apply changes or not
        configuration (str): configuration to load into the device
        filename (str): filename containing the configuration to load into the device
        replace (bool): whether to replace or merge the configuration

    Returns:
        :obj:`brigade.core.task.Result`:
          * changed (``bool``): whether if the task is changing the system or not
          * diff (``string``): change in the system
    """
    device = task.host.get_connection("napalm")

    if replace:
        device.load_replace_candidate(filename=filename, config=configuration)
    else:
        device.load_merge_candidate(filename=filename, config=configuration)
    diff = device.compare_config()

    dry_run = task.is_dry_run(dry_run)
    if not dry_run and diff:
        device.commit_config()
    else:
        device.discard_config()
    return Result(host=task.host, diff=diff, changed=len(diff) > 0)
Ejemplo n.º 4
0
def parse_data(task):

    data = {}
    data["failed"] = False
    data["changed"] = False

    if "dev1.group_1" == task.host.name:
        data["values"] = [1, 2, 3]
        data["changed"] = True

    elif "dev2.group_1" == task.host.name:
        data["values"] = [4, 5, 6]

    elif "dev3.group_2" == task.host.name:
        data["values"] = [7, 8, 9]

    elif "dev4.group_2" == task.host.name:
        data["values"] = [10, 11, 12]
        data["changed"] = False
        data["failed"] = True

    if data["failed"]:
        raise Exception("Unknown Error -> Contact your system administrator")

    return Result(host=task.host, changed=data["changed"], result=data["values"])
Ejemplo n.º 5
0
def command(task, command):
    """
    Executes a command locally

    Arguments:
        command (``str``): command to execute

    Returns:
        :obj:`brigade.core.task.Result`:
          * result (``str``): stderr or stdout
          * stdout (``str``): stdout
          * stderr (``srr``): stderr
    Raises:
        :obj:`brigade.core.exceptions.CommandError`: when there is a command error
    """
    cmd = subprocess.Popen(
        shlex.split(command),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        shell=False,
    )

    stdout, stderr = cmd.communicate()
    stdout = stdout.decode()
    stderr = stderr.decode()

    if cmd.poll():
        raise CommandError(command, cmd.returncode, stdout, stderr)

    result = stderr if stderr else stdout
    return Result(result=result, host=task.host, stderr=stderr, stdout=stdout)
Ejemplo n.º 6
0
def napalm_cli(task, commands):
    """
    Run commands on remote devices using napalm

    Arguments:
        commands (``list``): List of commands to execute

    Returns:
        :obj:`brigade.core.task.Result`:
          * result (``dict``): dictionary with the result of the commands
    """
    device = task.host.get_connection("napalm")
    result = device.cli(commands)
    return Result(host=task.host, result=result)
Ejemplo n.º 7
0
def load_yaml(task, file):
    """
    Loads a yaml file.

    Arguments:
        file (str): path to the file containing the yaml file to load

    Returns:
        :obj:`brigade.core.task.Result`:
          * result (``dict``): dictionary with the contents of the file
    """
    with open(file, "r") as f:
        data = yaml.load(f.read())

    return Result(host=task.host, result=data)
Ejemplo n.º 8
0
def tcp_ping(task, ports, timeout=2, host=None):
    """
    Tests connection to a tcp port and tries to establish a three way
    handshake. To be used for network discovery or testing.

    Arguments:
        ports (list of int): tcp port to ping
        timeout (int, optional): defaults to 0.5
        host (string, optional): defaults to ``brigade_ip``


    Returns:
        :obj:`brigade.core.task.Result`:
          * result (``dict``): Contains port numbers as keys with True/False as values
    """

    if isinstance(ports, int):
        ports = [ports]

    if isinstance(ports, list):
        if not all(isinstance(port, int) for port in ports):
            raise ValueError("Invalid value for 'ports'")

    else:
        raise ValueError("Invalid value for 'ports'")

    host = host or task.host.host

    result = {}
    for port in ports:
        s = socket.socket()
        s.settimeout(timeout)
        try:
            status = s.connect_ex((host, port))
            if status == 0:
                connection = True
            else:
                connection = False
        except (socket.gaierror, socket.timeout, socket.error):
            connection = False
        finally:
            s.close()
        result[port] = connection

    return Result(host=task.host, result=result)
Ejemplo n.º 9
0
def napalm_validate(task, src=None, validation_source=None):
    """
    Gather information with napalm and validate it:

        http://napalm.readthedocs.io/en/develop/validate/index.html

    Arguments:
        src: file to use as validation source
        validation_source (list): instead of a file data needed to validate device's state

    Returns:
      :obj:`brigade.core.task.Result`:
        * result (``dict``): dictionary with the result of the validation
        * complies (``bool``): Whether the device complies or not
    """
    device = task.host.get_connection("napalm")
    r = device.compliance_report(validation_file=src,
                                 validation_source=validation_source)
    return Result(host=task.host, result=r)
Ejemplo n.º 10
0
def netmiko_send_command(task, command_string, use_timing=False, **kwargs):
    """
    Execute Netmiko send_command method (or send_command_timing)

    Arguments:
        command_string(str): Command to execute on the remote network device.
        use_timing(bool, optional): Set to True to switch to send_command_timing method.
        kwargs (dict, optional): Additional arguments to pass to send_command method.

    Returns:
        :obj:`brigade.core.task.Result`:
          * result (``dict``): dictionary with the result of the show command.
    """
    net_connect = task.host.get_connection("netmiko")
    if use_timing:
        result = net_connect.send_command_timing(command_string, **kwargs)
    else:
        result = net_connect.send_command(command_string, **kwargs)
    return Result(host=task.host, result=result)
Ejemplo n.º 11
0
def template_string(task, template, jinja_filters=None, **kwargs):
    """
    Renders a string with jinja2. All the host data is available in the tempalte

    Arguments:
        template (string): template string
        jinja_filters (dict): jinja filters to enable. Defaults to brigade.config.jinja_filters
        **kwargs: additional data to pass to the template

    Returns:
        :obj:`brigade.core.task.Result`:
            * result (``string``): rendered string
    """
    jinja_filters = jinja_filters or {} or task.brigade.config.jinja_filters
    merged = merge_two_dicts(task.host, kwargs)
    text = jinja_helper.render_from_string(template=template,
                                           host=task.host,
                                           jinja_filters=jinja_filters,
                                           **merged)
    return Result(host=task.host, result=text)
Ejemplo n.º 12
0
def http_method(task=None,
                method="get",
                url="",
                raise_for_status=True,
                **kwargs):
    """
    This is a convenience task that uses `requests <http://docs.python-requests.org/en/master/>`_ to
    interact with an HTTP server.

    Arguments:
        method (string): HTTP method to call
        url (string): URL to connect to
        raise_for_status (bool): Whether to call `raise_for_status
            <http://docs.python-requests.org/en/master/api/#requests.Response.raise_for_status>`_
            method automatically or not. For quick reference, raise_for_status will consider an
            error if the return code is any of 4xx or 5xx
        **kwargs: Keyword arguments will be passed to the `request
            <http://docs.python-requests.org/en/master/api/#requests.request>`_
            method

    Returns:
        :obj:`brigade.core.task.Result`:
          * result (``string/dict``): Body of the response. Either text or a dict if the
            response was a json object
          * reponse (object): Original `Response
            <http://docs.python-requests.org/en/master/api/#requests.Response>`_
    """
    r = requests.request(method, url, **kwargs)

    if raise_for_status:
        r.raise_for_status()

    try:
        content_type = r.headers["Content-type"]
    except KeyError:
        content_type = "text"

    result = r.json() if "application/json" == content_type else r.text

    return Result(host=task.host if task else None, response=r, result=result)
Ejemplo n.º 13
0
def write_file(task, filename, content, append=False, dry_run=None):
    """
    Write contents to a file (locally)

    Arguments:
        dry_run (bool): Whether to apply changes or not
        filename (``str``): file you want to write into
        conteint (``str``): content you want to write
        append (``bool``): whether you want to replace the contents or append to it

    Returns:
        * changed (``bool``):
        * diff (``str``): unified diff
    """
    diff = _generate_diff(filename, content, append)

    if not task.is_dry_run(dry_run):
        mode = "a+" if append else "w+"
        with open(filename, mode=mode) as f:
            f.write(content)

    return Result(host=task.host, diff=diff, changed=bool(diff))
Ejemplo n.º 14
0
def napalm_get(task, getters):
    """
    Gather information from network devices using napalm

    Arguments:
        getters (list of str): getters to use


    Returns:
        :obj:`brigade.core.task.Result`:
          * result (``dict``): dictionary with the result of the getter
    """
    device = task.host.get_connection("napalm")

    if isinstance(getters, str):
        getters = [getters]

    result = {}
    for g in getters:
        getter = g if g.startswith("get_") else "get_{}".format(g)
        method = getattr(device, getter)
        result[g] = method()
    return Result(host=task.host, result=result)
Ejemplo n.º 15
0
def load_data(task):
    data = {"os": "Linux", "services": ["http", "smtp", "dns"]}
    return Result(host=task.host, result=data)
Ejemplo n.º 16
0
def echo_task(task, msg="Brigade"):
    return Result(
        host=task.host,
        result="Hello from {}".format(msg),
        output="Hello from {}".format(msg),
    )