예제 #1
0
def add_vlan(
    group_dev: str = typer.Argument(...),
    pvid: str = typer.Argument(...),
    ip: str = typer.Argument(None),
    mask: str = typer.Argument("255.255.255.0"),
    name: str = None, description: str = None,
    interface: str = None,
    vrid: str = None,
    vrrp_ip: str = None,
    vrrp_pri: int = None,
    default: bool = typer.Option(False, "-d", is_flag=True, help="Use default central account",
                                 callback=cli.default_callback),
    debug: bool = typer.Option(False, "--debug", envvar="ARUBACLI_DEBUG", help="Enable Additional Debug Logging",
                               callback=cli.debug_callback),
    account: str = typer.Option("central_info",
                                envvar="ARUBACLI_ACCOUNT",
                                help="The Aruba Central Account to use (must be defined in the config)",
                                callback=cli.account_name_callback),
) -> None:
    caasapi = caas.CaasAPI(central=cli.central)
    cmds = []
    cmds += [f"vlan {pvid}", "!"]
    if name:
        cmds += [f"vlan-name {name}", "!", f"vlan {name} {pvid}", "!"]
    if ip:
        _fallback_desc = f"VLAN{pvid}-SVI"
        cmds += [f"interface vlan {pvid}", f"description {description or name or _fallback_desc}", f"ip address {ip} {mask}", "!"]
    if vrid:
        cmds += [f"vrrp {vrid}", f"ip address {vrrp_ip}", f"vlan {pvid}"]
        if vrrp_pri:
            cmds += [f"priority {vrrp_pri}"]
        cmds += ["no shutdown", "!"]

    resp = cli.central.request(caasapi.send_commands, group_dev, cmds)
    caas.eval_caas_response(resp)
예제 #2
0
def bulk_edit(
    input_file: Path = typer.Argument(config.bulk_edit_file, ),
    default: bool = typer.Option(False,
                                 "-d",
                                 is_flag=True,
                                 help="Use default central account",
                                 callback=cli.default_callback),
    debug: bool = typer.Option(False,
                               "--debug",
                               envvar="ARUBACLI_DEBUG",
                               help="Enable Additional Debug Logging",
                               callback=cli.debug_callback),
    account: str = typer.Option(
        "central_info",
        envvar="ARUBACLI_ACCOUNT",
        help="The Aruba Central Account to use (must be defined in the config)",
        callback=cli.account_name_callback),
) -> None:
    caasapi = caas.CaasAPI(central=cli.central)
    cmds = caasapi.build_cmds(file=input_file)
    # TODO log cli
    if cmds:
        typer.secho("Commands:", fg="bright_green")
        typer.echo("\n".join(cmds))
        if typer.confirm("Send Commands"):
            for dev in caasapi.data:
                group_dev = f"{caasapi.data[dev]['_common'].get('group')}/{dev}"
                resp = cli.central.request(caasapi.send_commands, group_dev,
                                           cmds)
                caas.eval_caas_response(resp)
        else:
            raise typer.Abort()
예제 #3
0
def _build_pre_config(node: str, dev_type: SendConfigDevIdens, cfg_file: Path, var_file: Path = None) -> PreConfig:
    """Build Configuration from raw config or jinja2 template/variable file.

    Args:
        node (str): The name of the central node (group name or device MAC for gw)
        dev_type (str): Type of device being pre-provisioned.  One of 'gw' or 'ap'.
        cfg_file (Path): Path of the config file.
        var_file (Path, optional): Path of the variable file. Defaults to None.

    Raises:
        typer.Exit: If config is j2 template but no variable file is found.
        typer.Exit: If result of config generation yields no commands

    Returns:
        PreConfig: PreConfig object
    """
    if not cfg_file.exists():
        print(f":warning: [cyan]{node}[/] {cfg_file} not found.  Unable to generate config.")
        raise typer.Exit(1)

    br = cli.central.BatchRequest
    caasapi = caas.CaasAPI(central=cli.central)
    config_out = utils.generate_template(cfg_file, var_file=var_file)
    commands = utils.validate_config(config_out)

    if dev_type == "gw":
        return PreConfig(name=node, config=config_out, request=br(caasapi.send_commands, node, cli_cmds=commands))
    elif dev_type == "ap":
        return PreConfig(name=node, config=config_out, request=br(cli.central.replace_ap_config, node, clis=commands))
예제 #4
0
def send_cmds(
    kw1: constants.SendCmdArgs = typer.Argument(
        ...,
    ),
    nodes: str = typer.Argument(
        None,
        autocompletion=cache.send_cmds_completion,
        metavar=iden.group_or_dev_or_site,
        # callback=cli.send_cmds_node_callback,
        # is_eager=True,
    ),
    kw2: str = typer.Argument(
        None,
        autocompletion=cache.send_cmds_completion,
        # callback=cli.send_cmds_node_callback,
    ),
    commands: List[str] = typer.Argument(None, callback=cli.send_cmds_node_callback),
    cmd_file: Path = typer.Option(None, help="Path to file containing commands (1 per line) to be sent to device", exists=True),
    # dev_file: Path = typer.Option(None, help="Path to file containing iden for devices to send commands to", exists=True),
    # group: bool = typer.Option(None, help="Send commands to all gateways in a group", autocompletion=cli.cache.group_completion),
    # site: bool = typer.Option(None, help="Send commands to all gateways in a site", autocompletion=cli.cache.site_completion),
    all: bool = typer.Option(False, "-A", help="Send command(s) to all gateways (device level update) when group is provided"),
    yes: bool = typer.Option(False, "-Y", help="Bypass confirmation prompts - Assume Yes"),
    yes_: bool = typer.Option(False, "-y", hidden=True),
    default: bool = typer.Option(False, "-d", is_flag=True, help="Use default central account",
                                 callback=cli.default_callback),
    debug: bool = typer.Option(False, "--debug", envvar="ARUBACLI_DEBUG", help="Enable Additional Debug Logging",
                               callback=cli.debug_callback),
    account: str = typer.Option("central_info",
                                envvar="ARUBACLI_ACCOUNT",
                                help="The Aruba Central Account to use (must be defined in the config)",
                                callback=cli.account_name_callback),
) -> None:
    console = Console(emoji=False)
    yes = yes if yes else yes_
    commands = commands or []
    if kw1 == "group":
        if all:
            g = cache.get_group_identifier(nodes)
            nodes = [cache.CentralObject(d) for d in cache.devices if d["type"] == "gw" and d["group"] == g.name]
            action = f"all devices in {g.name} group."
        else:
            nodes = cache.get_group_identifier(nodes)
            action = f"group level gateway config for {nodes.name} group."
    elif kw1 == "site":
        s = cache.get_group_identifier(nodes)
        nodes = [cache.CentralObject(d) for d in cache.devices if d["type"] == "gw" and d["site"] == s.name]
        action = f"all devices in site: {s.name}"
    elif kw1 == "file":
        dev_file = Path(nodes)
        file_data = config.get_file_data(dev_file, text_ok=True)
        if not file_data:
            print(f"No data parsed from file {dev_file.name}.")
            raise typer.Exit(1)

        if isinstance(file_data, list):
            nodes = [cache.get_identifier(d.strip(), ["dev", "group", "site"], device_type="gw") for d in file_data]
        else:
            devices = file_data.get("devices", file_data.get("gateways"))
            if devices:
                nodes = [cache.get_identifier(d.strip(), ["dev", "group", "site"], device_type="gw") for d in file_data["devices"]]
            elif "groups" in file_data:
                nodes = [cache.CentralObject(d) for d in cache.devices if d["type"] == "gw" and d["group"] in file_data["groups"]]
            elif "sites" in file_data:
                nodes = [cache.CentralObject(d) for d in cache.devices if d["type"] == "gw" and d["site"] in file_data["sites"]]
            else:
                print(f"Expected 'gateways', 'groups', or 'sites' key in {dev_file.name}.")
                raise typer.Exit(1)

            if "cmds" in file_data or "commands" in file_data:
                if commands:
                    print("Providing commands on the command line and in the import file is a strange thing to do.")
                    raise typer.Exit(1)
                commands = file_data.get("cmds", file_data.get("commands"))
    elif kw1 == "device":
        if not isinstance(nodes, str):
            print(f"nodes is of type {type(nodes)} this is unexpected.")

        nodes = [cache.get_identifier(nodes, ["dev"], "gw")]

    if cmd_file:
        if commands:
            print("Providing commands on the command line and in the import file is a strange thing to do.")
            raise typer.Exit(1)
        else:
            commands = [line.rstrip() for line in cmd_file.read_text().splitlines()]

    if not commands:
        print("Error No commands provided")
        raise typer.Exit(1)

    if yes or typer.confirm("\nProceed?", abort=True):
        caasapi = caas.CaasAPI(central=cli.central)
        _reqs = [
            cli.central.BatchRequest(
                caasapi.send_commands,
                n.name if not n.is_dev else n.mac,
                cli_cmds=commands
            )
            for n in utils.listify(nodes)
        ]
        batch_res = cli.central.batch_request(_reqs)
        cli.display_results(batch_res, cleaner=cleaner.parse_caas_response)
예제 #5
0
def caas_batch(
    key: str = typer.Argument(None,),
    file: Path = typer.Option(config.stored_tasks_file, exists=True,),
    command: str = typer.Option(None,),
    default: bool = typer.Option(False, "-d", is_flag=True, help="Use default central account",
                                 callback=cli.default_callback),
    debug: bool = typer.Option(False, "--debug", envvar="ARUBACLI_DEBUG", help="Enable Additional Debug Logging",
                               callback=cli.debug_callback),
    account: str = typer.Option("central_info",
                                envvar="ARUBACLI_ACCOUNT",
                                help="The Aruba Central Account to use (must be defined in the config)",
                                callback=cli.account_name_callback),
) -> None:
    """cencli caas batch add-vlan add-vlan-99"""
    caasapi = caas.CaasAPI(central=cli.central)
    if file == config.stored_tasks_file and not key:
        print("[bright_red]ERROR:[/] key is required when using the default import file")
        raise typer.Exit(1)

    data = config.get_file_data(file)
    if hasattr(data, "dict"):  # csv
        data = data.dict
        data = {k: data[k] for k in data if data.get("key", "") == key}
    else:
        data = data.get(key)

    if not data:
        print(f"[bright_red]ERROR:[/] [cyan]{key}[/] not found in [cyan]{file}[/].  No Data to Process")
        raise typer.Exit(1)
    else:
        args = data.get("arguments", [])
        kwargs = data.get("options", {})
        cmds = data.get("cmds", [])

        if not args:
            print("[bright_red]ERROR:[/] import data requires an argument specifying the group / device")
            raise typer.Exit(1)

        if command:
            command = command.replace('-', '_')
            _msg1 = typer.style(
                f"Proceed with {command}:",
                fg="cyan"
            )
            _msg2 = f"{', '.join(args)} {', '.join([f'{k}={v}' for k, v in kwargs.items()])}"
            confirm_msg = typer.style(f"{_msg1} {_msg2}?", fg="bright_green")

            if command in globals():
                fn = globals()[command]
                if typer.confirm(confirm_msg):
                    fn(*args, **kwargs)  # type: ignore # NoQA
                else:
                    raise typer.Abort()
            else:
                typer.echo(f"{command} doesn't appear to be valid")

        elif cmds:
            print(f"\nSending the following to [cyan]{utils.unlistify(args)}[/]")
            if kwargs:
                print("\n  With the following options:")
                _ = [print(f"    {k} : {v}") for k, v in kwargs.items()]
                print(f"  [bold]cli cmds:[/]")
            _ = [print(f"    [cyan]{c}[/]") for c in cmds]
            if typer.confirm("Proceed:"):
                kwargs = {**kwargs, **{"cli_cmds": cmds}}
                resp = cli.central.request(caasapi.send_commands, *args, **kwargs)
                caas.eval_caas_response(resp)
예제 #6
0
def config_(
    group_dev: str = typer.Argument(
        ...,
        metavar="GROUP|DEVICE",
        help="Group or device to update.",
        autocompletion=cli.cache.group_dev_ap_gw_completion
    ),
    # TODO simplify structure can just remove device arg
    # device: str = typer.Argument(
    #     None,
    #     autocompletion=cli.cache.dev_ap_gw_completion
    #     # TODO dev type gw or ap only
    #     # autocompletion=lambda incomplete: [
    #     #    c for c in cli.cache.dev_completion(incomplete, dev_type="gw") if c.lower().startswith(incomplete.lower())
    #     # ]
    # ),
    # TODO collect multi-line input as option to paste in config
    cli_file: Path = typer.Argument(..., help="File containing desired config/template in CLI format.", exists=True, autocompletion=lambda incomplete: tuple()),
    var_file: Path = typer.Argument(None, help="File containing variables for j2 config template.", exists=True, autocompletion=lambda incomplete: tuple()),
    # TODO --vars PATH  help="File containing variables to convert jinja2 template."
    yes: bool = typer.Option(False, "-Y", help="Bypass confirmation prompts - Assume Yes"),
    yes_: bool = typer.Option(False, "-y", hidden=True),
    do_gw: bool = typer.Option(None, "--gw", help="Show group level config for gateways."),
    do_ap: bool = typer.Option(None, "--ap", help="Show group level config for APs."),
    debug: bool = typer.Option(False, "--debug", envvar="ARUBACLI_DEBUG", help="Enable Additional Debug Logging",),
    default: bool = typer.Option(False, "-d", is_flag=True, help="Use default central account", show_default=False,),
    account: str = typer.Option("central_info",
                                envvar="ARUBACLI_ACCOUNT",
                                help="The Aruba Central Account to use (must be defined in the config)",),
) -> None:
    yes = yes_ if yes_ else yes
    group_dev: CentralObject = cli.cache.get_identifier(group_dev, qry_funcs=["group", "dev"], device_type=["ap", "gw"])
    config_out = utils.generate_template(cli_file, var_file=var_file)
    cli_cmds = utils.validate_config(config_out)

    # TODO render.py module with helper function to return styled rule/line
    console = Console(record=True, emoji=False)
    console.begin_capture()
    console.rule("Configuration to be sent")
    console.print("\n".join([f"[green]{line}[/green]" for line in cli_cmds]))
    console.rule()
    console.print(f"\nUpdating {'group' if group_dev.is_group else group_dev.generic_type.upper()} [cyan]{group_dev.name}")
    _msg = console.end_capture()

    if group_dev.is_group:
        device = None
        if not do_ap and not do_gw:
            print("Invalid Input, --gw or --ap option must be supplied for group level config.")
            raise typer.Exit(1)
    else:  # group_dev is a device iden
        device = group_dev

    if do_gw or (device and device.generic_type == "gw"):
        if device and device.generic_type != "gw":
            print(f"Invalid input: --gw option conflicts with {device.name} which is an {device.generic_type}")
            raise typer.Exit(1)
        use_caas = True
        caasapi = caas.CaasAPI(central=cli.central)  # XXX Burried import
        node_iden = group_dev.name if group_dev.is_group else group_dev.mac
    elif do_ap or (device and device.generic_type == "ap"):
        if device and device.generic_type != "ap":
            print(f"Invalid input: --ap option conflicts with {device.name} which is a {device.generic_type}")
            raise typer.Exit(1)
        use_caas = False
        node_iden = group_dev.name if group_dev.is_group else group_dev.serial

    typer.echo(_msg)
    if yes or typer.confirm("Proceed?", abort=True):
        if use_caas:
            resp = cli.central.request(caasapi.send_commands, node_iden, cli_cmds)
            cli.display_results(resp, cleaner=cleaner.parse_caas_response)
        else:
            # FIXME this is OK for group level ap config , for AP this method is not valid
            if group_dev.is_dev:
                print("Not Implemented yet for AP device level updates")
                raise typer.Exit(1)
            resp = cli.central.request(cli.central.replace_ap_config, node_iden, cli_cmds)
            cli.display_results(resp, tablefmt="action")