Example #1
0
def sync_check_hash(task, force=False, job_id=None):
    """
    Start the task which will compare device configuration hashes.

    Args:
        task: Nornir task
        force: Ignore device hash
    """
    set_thread_data(job_id)
    logger = get_logger()
    if force is True:
        return
    with sqla_session() as session:
        stored_hash = Device.get_config_hash(session, task.host.name)
    if stored_hash is None:
        return

    task.host.open_connection("napalm", configuration=task.nornir.config)
    res = task.run(task=napalm_get, getters=["config"])
    task.host.close_connection("napalm")

    running_config = dict(res.result)['config']['running'].encode()
    if running_config is None:
        raise Exception('Failed to get running configuration')
    hash_obj = sha256(running_config)
    running_hash = hash_obj.hexdigest()
    if stored_hash != running_hash:
        raise Exception('Device {} configuration is altered outside of CNaaS!'.format(task.host.name))
Example #2
0
def sync_devices(hostname: Optional[str] = None,
                 device_type: Optional[str] = None,
                 dry_run: bool = True,
                 force: bool = False) -> NornirJobResult:
    """Synchronize devices to their respective templates. If no arguments
    are specified then synchronize all devices that are currently out
    of sync.

    Args:
        hostname: Specify a single host by hostname to synchronize
        device_type: Specify a device type to synchronize

    Returns:
        NornirJobResult
    """
    nr = cnaas_nms.confpush.nornir_helper.cnaas_init()
    if hostname:
        nr_filtered = nr.filter(name=hostname).filter(managed=True)
    elif device_type:
        nr_filtered = nr.filter(F(groups__contains='T_' +
                                  device_type))  # device type
    else:
        nr_filtered = nr.filter(synchronized=False).filter(
            managed=True)  # all unsynchronized devices

    device_list = list(nr_filtered.inventory.hosts.keys())
    logger.info(
        "Device(s) selected for synchronization: {}".format(device_list))

    alterned_devices = []
    for device in device_list:
        stored_config_hash = Device.get_config_hash(device)
        if stored_config_hash is None:
            continue
        current_config_hash = get_running_config_hash(device)
        if current_config_hash is None:
            raise Exception('Failed to get configuration hash')
        if stored_config_hash != current_config_hash:
            logger.info(
                "Device {} configuration is altered outside of CNaaS!".format(
                    device))
            alterned_devices.append(device)
    if alterned_devices != [] and force is False:
        raise Exception(
            'Configuration for {} is altered outside of CNaaS'.format(
                ', '.join(alterned_devices)))

    try:
        nrresult = nr_filtered.run(task=push_sync_device, dry_run=dry_run)
        print_result(nrresult)
    except Exception as e:
        logger.exception("Exception while synchronizing devices: {}".format(
            str(e)))
        return NornirJobResult(nrresult=nrresult)

    failed_hosts = list(nrresult.failed_hosts.keys())

    if not dry_run:
        for key in nrresult.keys():
            if key in failed_hosts:
                continue
            new_config_hash = get_running_config_hash(key)
            if new_config_hash is None:
                raise Exception('Failed to get configuration hash')
            Device.set_config_hash(key, new_config_hash)

        with sqla_session() as session:
            for hostname in device_list:
                if hostname in failed_hosts:
                    logger.error(
                        "Synchronization of device '{}' failed".format(
                            hostname))
                    continue
                dev: Device = session.query(Device).filter(
                    Device.hostname == hostname).one()
                dev.synchronized = True

    if nrresult.failed:
        logger.error("Not all devices were successfully synchronized")

    return NornirJobResult(nrresult=nrresult)