def run_commands(cmds, site):
# Filter Nornir to only use site user specified
    nr_filtered = nr.filter(site=site)
# Use credentials user supplied so they do not have to be stored in inventory files
    nr_filtered.inventory.defaults.username = user
    nr_filtered.inventory.defaults.password = p
    nr_filtered.inventory.defaults.connection_options['netmiko'] = ConnectionOptions(extras={"secret":f"{p}"})
# Filter Nornir inventory for list of hosts
    host_list = nr_filtered.inventory.hosts
# Populate dictionary 'dict1' with a key for each hostname
    for i in host_list:
        dict1[i] = []
# Filter Nornir inventory for dictionary of host info
    ip_dict = nr_filtered.inventory.get_hosts_dict()
# Append the host IP address to the dictionary 'dict1'
    for i in host_list:
        ip = ip_dict[i]['hostname']
        dict1[i].append(ip)
# Run each command and append output to 'dict1' in the hosts' list
    for cmd in cmds:
        result = nr_filtered.run(task=netmiko_send_command,command_string=cmd)
        for dv_name in result.keys():
            value = str(result[dv_name][0].result)
            value = value.rstrip()
            dict1[dv_name].append(value)
    return dict1
예제 #2
0
    def reset_access_device(self):
        nr = cnaas_nms.confpush.nornir_helper.cnaas_init()
        nr_filtered = nr.filter(name=self.testdata['init_access_new_hostname'])
        nr_filtered.inventory.hosts[self.testdata['init_access_new_hostname']].\
            connection_options["napalm"] = ConnectionOptions(extras={"timeout": 5})

        data_dir = pkg_resources.resource_filename(__name__, 'data')
        with open(os.path.join(data_dir, 'access_reset.j2'),
                  'r') as f_reset_config:
            print(self.testdata['init_access_new_hostname'])
            config = f_reset_config.read()
            print(config)
            nrresult = nr_filtered.run(
                task=networking.napalm_configure,
                name="Reset config",
                replace=False,
                configuration=config,
                dry_run=False  # TODO: temp for testing
            )
            print_result(nrresult)

        reset_interfacedb(self.testdata['init_access_new_hostname'])

        with sqla_session() as session:
            dev: Device = session.query(Device).filter(
                Device.hostname ==
                self.testdata['init_access_new_hostname']).one()
            dev.management_ip = None
            dev.hostname = self.testdata['init_access_old_hostname']
            dev.state = DeviceState.DISCOVERED
            dev.device_type = DeviceType.UNKNOWN
예제 #3
0
def adapt_user_password(host):
    host.username = creds[f"{host}"]["username"]
    host.password = creds[f"{host}"]["password"]
    host.connection_options["napalm"] = ConnectionOptions(
     extras={
         "optional_args": {
             "secret":"admin"
            }
        }
    )
예제 #4
0
def push_base_management_access(task, device_variables, job_id):
    set_thread_data(job_id)
    logger = get_logger()
    logger.debug("Push basetemplate for host: {}".format(task.host.name))

    with open('/etc/cnaas-nms/repository.yml', 'r') as db_file:
        repo_config = yaml.safe_load(db_file)
        local_repo_path = repo_config['templates_local']

    mapfile = os.path.join(local_repo_path, task.host.platform, 'mapping.yml')
    if not os.path.isfile(mapfile):
        raise RepoStructureException(
            "File {} not found in template repo".format(mapfile))
    with open(mapfile, 'r') as f:
        mapping = yaml.safe_load(f)
        template = mapping['ACCESS']['entrypoint']

    settings, settings_origin = get_settings(task.host.name, DeviceType.ACCESS)

    # Add all environment variables starting with TEMPLATE_SECRET_ to
    # the list of configuration variables. The idea is to store secret
    # configuration outside of the templates repository.
    template_secrets = {}
    for env in os.environ:
        if env.startswith('TEMPLATE_SECRET_'):
            template_secrets[env] = os.environ[env]

    # Merge dicts, this will overwrite interface list from settings
    template_vars = {**settings, **device_variables, **template_secrets}

    r = task.run(task=text.template_file,
                 name="Generate initial device config",
                 template=template,
                 path=f"{local_repo_path}/{task.host.platform}",
                 **template_vars)

    #TODO: Handle template not found, variables not defined

    task.host["config"] = r.result
    # Use extra low timeout for this since we expect to loose connectivity after changing IP
    task.host.connection_options["napalm"] = ConnectionOptions(
        extras={"timeout": 30})

    try:
        task.run(task=networking.napalm_configure,
                 name="Push base management config",
                 replace=True,
                 configuration=task.host["config"],
                 dry_run=False)
    except Exception:
        task.run(task=networking.napalm_get, getters=["facts"])
        if not task.results[-1].failed:
            raise InitError(
                "Device {} did not commit new base management config".format(
                    task.host.name))
예제 #5
0
def adapt_host_data(host):

    # This function receives a Host object for manipulation
    # host.username = host["username"]
    # host.password = host["password"]
    host.connection_options["napalm"] = ConnectionOptions(
        extras={
            "optional_args": {
                'secret': host.password
        }
        }
    )
def _get_connection_options(data: Dict[str, Any]) -> Dict[str, ConnectionOptions]:
    cp = {}
    for cn, c in data.items():
        cp[cn] = ConnectionOptions(
            hostname=c.get('hostname'),
            port=c.get('port'),
            username=c.get('username'),
            password=c.get('password'),
            platform=c.get('platform'),
            extras=c.get('extras'),
        )
    return cp
예제 #7
0
def enable_fast_cli(nr: Nornir) -> None:
    """
    Enable `fast_cli` option in netmiko. This option is only appropriate
    for Cisco IOS devices.

    Args:
        nr: a Nornir object.
    """
    conn_options = ConnectionOptions(extras={"fast_cli": True})
    for host in nr.inventory.hosts.values():
        if host.platform == "ios":
            host.connection_options["netmiko"] = conn_options
예제 #8
0
def _get_connection_options(data: Dict[str, Any]) -> ConnectionOptions:
    cp = {}
    for cn, c in data.items():
        cp[cn] = ConnectionOptions(
            hostname=c.get("hostname"),
            port=c.get("port"),
            username=c.get("username"),
            password=c.get("password"),
            platform=c.get("platform"),
            extras=c.get("extras"),
        )
    return cp
예제 #9
0
def _validate_connection_options(ctx, param, value):
    if value is not None:
        try:
            value = {
                connection_plugin: ConnectionOptions(**connection_params)
                for connection_plugin, connection_params in _json_loads(
                    [value])[0].items()
            }
            return value
        except (TypeError, AttributeError):
            ctx.fail(
                click.BadParameter(f"'--connection_options' / '-co': {value}",
                                   ).format_message(), )
예제 #10
0
def get_interfaces_status(nr):
    ssh = True
    r = ''
    main.session_log(nr)
    try:
        r = nr.run(task=networking.netmiko_send_command,
                   name=f'Issue show interfaces status por SSH en {nr.host}',
                   command_string='show interfaces status',
                   use_textfsm=True
                   ).result

    except NornirSubTaskError:
        print('Al parecer, SSH no funca asi que cerrando conexion....')
        ssh = False
        try:
            nr.host.close_connections()
        except ValueError:
            print('... y abriendo un telnet rico...')
            pass

    if not ssh:

        nr.host.connection_options['netmiko'] = ConnectionOptions(
            extras={"device_type": 'cisco_ios_telnet'}
        )

        host_info = main.get_device_info(nr)

        nr.host.connection_options['netmiko'] = ConnectionOptions(
            extras={"device_type": 'cisco_ios_telnet', "session_log": main.session_log(nr)}
        )

        r = nr.run(task=networking.netmiko_send_command,
                   name=f'Hace un show interfaces status por TELNET en {nr.host}',
                   command_string='show interfaces status',
                   use_textfsm=True
                   ).result

    main.process_data_trunk(r, nr)
예제 #11
0
def transform_slog(host):
    """
    Create ConnectionOptions > Extras in the transform function.

    This pattern presupposes, however, that there is nothing else
    in existing inventory inside extras that needs retained.

    The five primary attributes would still get recursively retrieved
    including inside of connection options.
    """

    # Dynamically set the session_log to be unique per host
    filename = f"{host}-output.txt"
    host.connection_options["netmiko"] = ConnectionOptions(
        extras={"session_log": filename})
    netmiko_params = host.get_connection_parameters("netmiko")
    print(netmiko_params)
예제 #12
0
def _get_connection_options(data: Dict[str, Any]) -> ConnectionOptions:
    """
    Get connection option information for a given host/group

    Arguments:
        data: dictionary of connection options for host/group

    """
    connection_options = {}
    for connection_name, connection_data in data.items():
        connection_options[connection_name] = ConnectionOptions(
            hostname=connection_data.get("hostname"),
            port=connection_data.get("port"),
            username=connection_data.get("username"),
            password=connection_data.get("password"),
            platform=connection_data.get("platform"),
            extras=connection_data.get("extras"),
        )
    return connection_options
def _set_host(data: Dict[str, Any], name: str, groups, host, defaults) -> Host:
    connection_option = {}
    for key, value in data.get("connection_options", {}).items():
        connection_option[key] = ConnectionOptions(
            hostname=value.get("hostname"),
            port=value.get("port"),
            username=value.get("username"),
            password=value.get("password"),
            platform=value.get("platform"),
            extras=value.get("extras"),
        )
    return Host(
        name=name,
        hostname=host["hostname"],
        username=host["username"],
        password=host["password"],
        platform=host["platform"],
        data=data,
        groups=groups,
        defaults=defaults,
        connection_options=connection_option,
    )
예제 #14
0
def push_base_management_access(task, device_variables):
    logger.debug("Push basetemplate for host: {}".format(task.host.name))

    with open('/etc/cnaas-nms/repository.yml', 'r') as db_file:
        repo_config = yaml.safe_load(db_file)
        local_repo_path = repo_config['templates_local']

    mapfile = os.path.join(local_repo_path, task.host.platform, 'mapping.yml')
    if not os.path.isfile(mapfile):
        raise RepoStructureException(
            "File {} not found in template repo".format(mapfile))
    with open(mapfile, 'r') as f:
        mapping = yaml.safe_load(f)
        template = mapping['ACCESS']['entrypoint']

    settings, settings_origin = get_settings(task.host.name, DeviceType.ACCESS)
    # Merge dicts
    template_vars = {**device_variables, **settings}

    r = task.run(task=text.template_file,
                 name="Generate initial device config",
                 template=template,
                 path=f"{local_repo_path}/{task.host.platform}",
                 **template_vars)

    #TODO: Handle template not found, variables not defined

    task.host["config"] = r.result
    # Use extra low timeout for this since we expect to loose connectivity after changing IP
    task.host.connection_options["napalm"] = ConnectionOptions(
        extras={"timeout": 5})

    task.run(
        task=networking.napalm_configure,
        name="Push base management config",
        replace=True,
        configuration=task.host["config"],
        dry_run=False  # TODO: temp for testing
    )
예제 #15
0
def create_connection_options(username: str, password: str,
                              secret: str) -> dict:
    """Helper function to create or connection options.

    Args:
        username (str): Username to use to connect to device.
        password (str): Password to use to connect to device.
        secret (str): Secret or enable password to use to elevate perissions on the device.

    Returns:
        dict: Nornir ConnectionOptions object
    """
    napalm_options = ConnectionOptions(
        username=username,
        password=password,
        extras={"optional_args": {
            "conn_timeout": 500,
            "secret": secret
        }})

    connection_options = {"napalm": napalm_options}

    return connection_options
def host_credentials(host, username, password):
    host.username = username
    host.password = password
    host.connection_options['netmiko'] = ConnectionOptions(
        extras={'secret': password})
예제 #17
0
from nornir import InitNornir
from nornir.plugins.tasks.data import load_yaml
from nornir.plugins.functions.text import print_result
from nornir.core.inventory import ConnectionOptions

def load_data(task):
    data = task.run(
           task=load_yaml,
           file=f'{task.host["site"]}.yaml'
    )

    task.host["asn"] = data.result["asn"]
    task.host["networks"] = data.result["networks"]


nr = InitNornir()
nr.inventory.defaults.connection_options = ConnectionOptions(extras={"secret": "cisco"})
r = nr.run(task=load_data)
print_result(r)
예제 #18
0
def nornir_initialize(args: Namespace) -> Nornir:
    """
    Given the parsed argument Namespace object, initialize a Nornir inventory/execution object and return it.
    :param args: A parsed/instantiated argpase.Namespace object with our command line arguments
    :return:
    """

    log_file = pathlib.Path(pathlib.Path(args.logging_dir) / "stockpiler.log")

    # A directory in the path doesn't exist, this can happen with the default logging path of `/var/log/stockpiler/`
    if not log_file.parent.exists():
        try:
            log_file.parent.mkdir(parents=True)
        except PermissionError:
            sys_user = getpass.getuser()
            print(
                "\nERROR: Unable to create parent log directories!"
                f"\nYou may have to manually do this with 'sudo mkdir -p {str(log_file.parent)};"
                f"sudo chown {sys_user}:{sys_user} {str(log_file.parent)}'\n"
            )
            sys.exit(1)

    # Ensure the logfile is able to be written to.
    try:
        log_file.touch()
    except PermissionError:
        print(
            f"\nERROR: Unable to access the log file at {str(log_file)}"
            f" please check permissions on the file/directory!\n"
        )
        sys.exit(1)

    logging_config = {
        "level": args.log_level,
        "file": str(log_file),
        "loggers": ["nornir", "paramiko", "netmiko", "stockpiler"],
    }
    if args.config_file:
        config_file = args.config_file
    else:
        with importlib.resources.path(package="stockpiler", resource="nornir_conf.yaml") as p:
            config_file = str(p)

    # See if an SSH config file is specified in args or in the config file, order of precedence is:
    #   First In the inventory: Device -> Group -> Defaults
    #   Then: Args -> Config File -> Packaged SSH Config File
    if args.ssh_config_file:
        ssh_config_file = args.ssh_config_file
    else:
        cf_path = pathlib.Path(config_file)
        if not cf_path.is_file():
            raise ValueError(f"The provided configuration file {str(cf_path)} is not found.")
        with cf_path.open() as cf:
            try:
                cf_yaml = safe_load(cf)
            except (ConstructorError, ValueError) as e:
                raise ValueError(f"Unable to parse the provided config file {str(cf_path)} to YAML: {str(e)}")
        cf_ssh_config_file = cf_yaml.get("ssh", {}).get("config_file", None)
        if cf_ssh_config_file is not None:
            ssh_config_file = cf_ssh_config_file
        else:
            with importlib.resources.path(package="stockpiler", resource="ssh_config") as p:
                ssh_config_file = str(p)

    # Initialize our nornir object/inventory
    logger.info("Reading config file and initializing inventory...")
    norns = InitNornir(config_file=config_file, logging=logging_config, ssh={"config_file": ssh_config_file})

    # Check if we need to gather credentials or not:
    if not args.credential_from_inventory:
        # Gather credentials:
        username, password, enable = gather_credentials(
            credential_prompt=args.credential_prompt, credential_file=args.credential_file
        )

        # Set these into the inventory:
        norns.inventory.defaults.username = username
        norns.inventory.defaults.password = password

        # If there is no Enable, set it to the same as the password.
        norns.inventory.defaults.connection_options["netmiko"] = ConnectionOptions(
            extras={"secret": enable or password}
        )

    return norns
예제 #19
0
def add_conn_options(host):
    host.username = config('username')
    host.password = config('password')
    host.connection_options["netmiko"] = ConnectionOptions(
        extras={'secret': config('secret')})
예제 #20
0
    def load(self):
        """Load inventory by fetching devices from netbox."""
        if self.filter_parameters:
            devices: List[pynetbox.modules.dcim.
                          Devices] = self.session.dcim.devices.filter(
                              **self.filter_parameters)
        else:
            devices: List[pynetbox.modules.dcim.
                          Devices] = self.session.dcim.devices.all()

        # fetch all platforms from Netbox and build mapping:   platform:  napalm_driver
        platforms = self.session.dcim.platforms.all()
        platforms_mapping = {
            platform.slug: platform.napalm_driver
            for platform in platforms if platform.napalm_driver
        }

        hosts = Hosts()
        groups = Groups()
        defaults = Defaults()

        for dev in devices:
            # Netbox allows devices to be unnamed, but the Nornir model does not allow this
            # If a device is unnamed we will set the name to the id of the device in netbox
            dev_name = dev.name or dev.id
            host = NetworkImporterHost(name=dev_name,
                                       connection_options=ConnectionOptions())

            # Only add virtual chassis master as inventory element
            if dev.virtual_chassis and dev.virtual_chassis.master:
                if dev.id != dev.virtual_chassis.master.id:
                    continue
                host.data["virtual_chassis"] = True

            else:
                host.data["virtual_chassis"] = False

            # If supported_platforms is provided
            # skip all devices that do not match the list of supported platforms
            # TODO need to see if we can filter when doing the query directly
            if self.supported_platforms:
                if not dev.platform:
                    continue

                if dev.platform.slug not in self.supported_platforms:
                    continue

            # Add value for IP address
            if self.settings.use_primary_ip and dev.primary_ip:
                host.hostname = dev.primary_ip.address.split("/")[0]
            elif self.settings.use_primary_ip and not dev.primary_ip:
                host.is_reachable = False
                host.not_reachable_reason = "primary ip not defined in Netbox"
            elif not self.settings.use_primary_ip and self.settings.fqdn:
                host.hostname = f"{dev.name}.{self.settings.fqdn}"
            elif not self.settings.use_primary_ip:
                host.hostname = dev.name
            else:
                host.hostname = dev_name

            host.site_name = dev.site.slug

            host.data["serial"] = dev.serial
            host.data["vendor"] = dev.device_type.manufacturer.slug
            host.data["asset_tag"] = dev.asset_tag
            host.data["custom_fields"] = dev.custom_fields
            host.data["site_id"] = dev.site.id
            host.data["device_id"] = dev.id
            host.data["role"] = dev.device_role.slug
            host.data["model"] = dev.device_type.slug

            # Attempt to add 'platform' based of value in 'slug'
            if dev.platform and dev.platform.slug in platforms_mapping:
                host.connection_options = {
                    "napalm":
                    ConnectionOptions(
                        platform=platforms_mapping[dev.platform.slug])
                }

            if dev.platform:
                host.platform = dev.platform.slug
            else:
                host.platform = None

            host.groups = ParentGroups([self.global_group])

            if dev.site.slug not in groups.keys():
                groups[dev.site.slug] = {}

            if dev.device_role.slug not in groups.keys():
                groups[dev.device_role.slug] = {}

            if host.hostname and host.platform:
                host.is_reachable = True

            # Assign temporary dict to outer dict

            hosts[dev_name] = host

        return Inventory(hosts=hosts, groups=groups, defaults=defaults)
예제 #21
0
def nornir_initialize(args: Namespace) -> Nornir:
    """
    Given the parsed argument Namespace object, initialize a Nornir inventory/execution object and return it.
    :param args: A parsed/instantiated argpase.Namespace object with our command line arguments
    :return:
    """

    log_file = pathlib.Path(pathlib.Path(args.logging_dir) / "stockpiler.log")
    pathlib.Path(log_file).touch()

    logging_config = {
        "level": args.log_level,
        "file": str(log_file),
        "loggers": ["nornir", "paramiko", "netmiko", "stockpiler"],
    }
    if args.config_file:
        config_file = args.config_file
    else:
        with importlib.resources.path(package="stockpiler",
                                      resource="nornir_conf.yaml") as p:
            config_file = str(p)

    # See if an SSH config file is specified in args or in the config file, order of precedence is:
    #   First In the inventory: Device -> Group -> Defaults
    #   Then: Args -> Config File -> Packaged SSH Config File
    if args.ssh_config_file:
        ssh_config_file = args.ssh_config_file
    else:
        cf_path = pathlib.Path(config_file)
        if not cf_path.is_file():
            raise ValueError(
                f"The provided configuration file {str(cf_path)} is not found."
            )
        with cf_path.open() as cf:
            try:
                cf_yaml = safe_load(cf)
            except (ConstructorError, ValueError) as e:
                raise ValueError(
                    f"Unable to parse the provided config file {str(cf_path)} to YAML: {str(e)}"
                )
        cf_ssh_config_file = cf_yaml.get("ssh", {}).get("config_file", None)
        if cf_ssh_config_file is not None:
            ssh_config_file = cf_ssh_config_file
        else:
            with importlib.resources.path(package="stockpiler",
                                          resource="ssh_config") as p:
                ssh_config_file = str(p)

    # Initialize our nornir object/inventory
    logger.info("Reading config file and initializing inventory...")
    norns = InitNornir(config_file=config_file,
                       logging=logging_config,
                       ssh={"config_file": ssh_config_file})

    # Gather credentials:
    username, password, enable = gather_credentials(
        prompt_for_credentials=args.prompt_for_credentials)

    # Set these into the inventory:
    norns.inventory.defaults.username = username
    norns.inventory.defaults.password = password

    # If there is no Enable, set it to the same as the password.
    norns.inventory.defaults.connection_options["netmiko"] = ConnectionOptions(
        extras={"secret": enable or password})

    return norns
예제 #22
0
if applyfilter.lower() in ('p'):
    p1 = p.run(task=netboxinfo)

elif applyfilter.lower() in ('pr'):
    p2 = pr.run(task=netboxinfo)

elif applyfilter.lower() in ('prs'):
    p3 = prs.run(task=netboxinfo)

# Enter Credentials and calling Getpass function above.

print("")
print_title('Enter your credentials below... \n')
nornir_set_creds(nr)
secret = input("Enter Enable Secret: ")
nr.inventory.defaults.connection_options['netmiko'] = ConnectionOptions(
    extras={'secret': secret})

# Yes or no question, if no the application quits directly, if yes then proceeds.


def yes_or_no(question):
    answer = input(question + "(y/n): ").lower().strip()
    print("")
    while not (answer == "y" or answer == "yes" or \
               answer == "n" or answer == "no"):
        print("Input yes or no")
        answer = input(question + "(y/n):").lower().strip()
        print("")
    if answer[0] == "y":
        return True
    else:
def adapt_host_data(host, username, password):
    host.username = username
    host.password = password
    host.connection_options['netmiko'] = ConnectionOptions(
        extras={'secret': password})
예제 #24
0
from nornir.plugins.tasks.networking import netmiko_send_command
from nornir.core.inventory import ConnectionOptions
from nornir.plugins.functions.text import print_result


#Transform function from Nornir
def adapt_user_password(host):
    host.username = "******"
    host.password = "******"


#Load config.yaml
nr = InitNornir(config_file="config.yaml")

nr.inventory.defaults.connection_options['netmiko'] = ConnectionOptions(
    extras={"optional_args": {
        "secret": "ENABLESECRET"
    }})
nr.inventory.defaults.connection_options['napalm'] = ConnectionOptions(
    extras={"optional_args": {
        "secret": "ENABLESECRET"
    }})

#Example sw10.domain.com
hosts = nr.filter(name="NETBOXFILTER")

urllib3.disable_warnings()

session = requests.Session()
session.verify = False
# load PynetBox
netbox = pynetbox.api('NETBOXURL', token='NETBOXTOKEN')
예제 #25
0
    def __init__(
        self,
        username: Optional[str] = None,
        password: Optional[str] = None,
        enable: Optional[bool] = None,
        supported_platforms: Optional[List[str]] = None,
        netmiko_extras: Optional[Dict] = None,
        napalm_extras: Optional[Dict] = None,
        limit: Optional[str] = None,
        settings: Optional[Dict] = None,
    ):
        """Initialize class and store all top level arguments locally."""
        self.username = username
        self.password = password
        self.enable = enable
        self.supported_platforms = supported_platforms
        self.limit = limit
        self.netmiko_extras = netmiko_extras
        self.napalm_extras = napalm_extras

        self.settings = settings

        # Define Global Group with Netmiko and Napalm Credentials if provided
        self.global_group = Group(name="global",
                                  connection_options={
                                      "netmiko": ConnectionOptions(),
                                      "napalm": ConnectionOptions()
                                  })

        if self.netmiko_extras:
            self.global_group.connection_options[
                "netmiko"].extras = self.netmiko_extras

        if self.napalm_extras:
            self.global_group.connection_options[
                "napalm"].extras = self.napalm_extras

        # Pull the login and password from the NI config object if available
        if self.username:
            self.global_group.username = self.username

        if self.password:
            self.global_group.password = self.password
            if self.enable:
                if not self.global_group.connection_options["netmiko"].extras:
                    self.global_group.connection_options[
                        "netmiko"].extras = dict()
                elif "secret" not in self.global_group.connection_options[
                        "netmiko"].extras:
                    self.global_group.connection_options["netmiko"].extras[
                        "secret"] = self.password

                if not self.global_group.connection_options["napalm"].extras:
                    self.global_group.connection_options["napalm"].extras = {
                        "optional_args": {
                            "secret": self.password
                        }
                    }
                elif isinstance(
                        dict,
                        self.global_group.connection_options["napalm"].extras):
                    if "optional_args" not in self.global_group.connection_options[
                            "napalm"].extras:
                        self.global_group.connection_options["napalm"].extras[
                            "optional_args"] = {
                                "secret": self.password
                            }
                    elif isinstance(
                            dict,
                            self.global_group.connection_options["napalm"].
                            extras["optional_args"]):
                        self.global_group.connection_options["napalm"].extras[
                            "optional_args"]["secret"] = self.password
예제 #26
0
    def load(self) -> Inventory:
        defaults = Defaults(
            connection_options={
                "napalm": ConnectionOptions(extras={
                    "optional_args": {
                        # args to eAPI HttpsEapiConnection for EOS
                        "enforce_verification": True,
                        "context": ssl_context
                    }
                })
            }
        )
        insecure_device_states = [
            DeviceState.INIT,
            DeviceState.DHCP_BOOT,
            DeviceState.PRE_CONFIGURED,
            DeviceState.DISCOVERED
        ]
        insecure_connection_options = {
            "napalm": ConnectionOptions(extras={
                "optional_args": {"enforce_verification": False}
            })
        }

        groups = Groups()
        for device_type in list(DeviceType.__members__):
            group_name = 'T_'+device_type
            groups[group_name] = Group(name=group_name, defaults=defaults)
        for device_state in list(DeviceState.__members__):
            username, password = self._get_credentials(device_state)
            group_name = 'S_'+device_state
            groups[group_name] = Group(
                name=group_name, username=username, password=password, defaults=defaults)
        for group_name in get_groups():
            groups[group_name] = Group(name=group_name, defaults=defaults)

        hosts = Hosts()
        with cnaas_nms.db.session.sqla_session() as session:
            instance: Device
            for instance in session.query(Device):
                hostname = self._get_management_ip(instance.management_ip,
                                                   instance.dhcp_ip)
                port = None
                if instance.port and isinstance(instance.port, int):
                    port = instance.port
                host_groups = [
                    'T_' + instance.device_type.name,
                    'S_' + instance.state.name
                ]
                for member_group in get_groups(instance.hostname):
                    host_groups.append(member_group)

                if instance.state in insecure_device_states:
                    host_connection_options = insecure_connection_options
                else:
                    host_connection_options = None
                hosts[instance.hostname] = Host(
                    name=instance.hostname,
                    hostname=hostname,
                    platform=instance.platform,
                    groups=ParentGroups(groups[g] for g in host_groups),
                    port=port,
                    data={
                        'synchronized': instance.synchronized,
                        'managed': (True if instance.state == DeviceState.MANAGED else False)
                    },
                    connection_options=host_connection_options,
                    defaults=defaults
                )

        return Inventory(hosts=hosts, groups=groups, defaults=defaults)