Skip to content

Snapshots Basics

This section provides examples and guidance on how to manage and operate snapshots in IP Fabric using the Python SDK. To understand more about snapshots in IP Fabric, please refer to the Discovery Snapshot documentation.

Retrieving Snapshot IDs and Metadata

Before operating on snapshots, you may want to retrieve information about available snapshots. Here we offer examples of how to access snapshot IDs and metadata:

import json
from ipfabric import IPFClient
from pprint import pprint

# Initialize the IPFClient
ipf = IPFClient(unloaded=False)  # Default is False

# Show current SDK client snapshot ID
print("Current Snapshot ID:", ipf.snapshot_id)

# Show if unloaded 
print("Unloaded snapshots retrieved:", str(ipf.unloaded))

# Get all snapshot IDs
snapshot_ids = list(ipf.snapshots)
print("Snapshot IDs:", snapshot_ids)

# Get snapshot IDs excluding special IDs (like $last, $prev)
actual_snapshot_ids = [snap_id for snap_id in ipf.snapshots.keys() if not snap_id.startswith('$')]
print("Actual Snapshot IDs:", actual_snapshot_ids)

# Pretty print snapshot metadata
print("\nSnapshot Metadata:")
pprint(dict(ipf.snapshots.items()), width=100, depth=2)

# Retrieve loaded snapshot IDs
print("Loaded Snapshot IDs:\n", list(ipf.loaded_snapshots))

# Retrieve unloaded snapshot IDs (calling `ipf.unloaded_snapshots` will automatically load them)
print("Unloaded Snapshot IDs:\n", list(ipf.unloaded_snapshots))

# Retrieve running snapshot ID
print("Running Snapshot ID:\n", ipf.running_snapshot)

# Retrieve loading snapshot ID
print("Loading Snapshot ID:\n", ipf.loading_snapshot)

# Update list of snapshots:
ipf.update()

# Print specific metadata for each snapshot
print("\nDetailed Snapshot Information:")
for snap_id, snapshot in ipf.snapshots.items():
    print(f"\nSnapshot: {snap_id}")
    print(f"  Name: {snapshot.name}")
    print(f"  Start time: {snapshot.start}")
    print(f"  End time: {snapshot.end}")
    print(f"  Status: {snapshot.status}")
    print(f"  Locked: {snapshot.locked}")
    print(f"  Device count: {snapshot.total_dev_count}")
    print(f"  Version: {snapshot.version}")

# Print all data for the initialized snapshot:
pprint(ipf.snapshot.model_dump())

Initializing the IPFClient with Snapshots

You can initialize the IPFClient with specific snapshot IDs. The snapshot ID can be set to $last (the last snapshot is selected by default) or $prev to retrieve the previous snapshot, or you can directly specify any loaded snapshot with its snapshot ID. In this sense, the $prev is considered a representative snapshot id for the previous snapshot.

After initializing the client with a specific snapshot, all tables and methods will operate on the data from that snapshot unless a specific snapshot ID is passed into a method.

from ipfabric import IPFClient

# Initialize client with the previous to the most recent snapshot
ipf = IPFClient(snapshot_id="$prev")

print(ipf.snapshot_id)  # Should return the snapshot ID of the previous snapshot

# Changing the SDK IPFClient's snapshot
ipf.snapshot_id = "$last"

print(ipf.snapshot_id)  # Should return the snapshot ID of the last snapshot
# All methods will now use this ID for returning data

Loading and Unloading Snapshots

All operations available in the UI are available in SDK and loading and unloading snapshots is no exception.

Loading and Unloading Snapshots
from ipfabric import IPFClient

# Initialize the IPFClient
ipf = IPFClient(unloaded=True)
print("Unloaded snapshots retrieved:", str(ipf.unloaded))

# List all unloaded snapshot IDs
print("Unloaded Snapshot IDs:\n", list(ipf.unloaded_snapshots))

# Load a specific unloaded snapshot and update SDK
success = ipf.snapshots['<snapshot_id>'].load(ipf)
print(success)  # Should return True if the snapshot is successfully loaded
ipf.update()

# Unload the most recent snapshot and update SDK
success = ipf.loaded_snapshots['$last'].unload(ipf)
print(success)  # Should return True if the snapshot is successfully unloaded
ipf.update()

Locking and Unlocking Snapshots

You can also lock or unlock snapshots as needed. By locking a snapshot, you prevent it from being modified, deleted or unloaded. For more information on locking and unlocking snapshots, please refer to the Locking Snapshots

Locking and Unlocking Snapshots
from ipfabric import IPFClient
from pprint import pprint

# Initialize the IPFClient
ipf = IPFClient()

# Lock a snapshot
ipf.snapshots['<snapshot_id>'].lock()

# To verify if the operation is completed we can use following code to check all running jobs
running_jobs = ipf.jobs.all_jobs.all(filters = { "isDone": ["eq", False] })
pprint(running_jobs)

# Unlock a snapshot
ipf.snapshots['<snapshot_id>'].unlock()

Creating Snapshots

In ipfabric>=6.9.9 the ability to create snapshots has been added to the SDK. This allows you to create snapshots using the default values or by specifying custom values. The create_snapshot method returns the snapshot ID of the newly created snapshot and the information about the Job that was scheduled.

If a discovery process is already running no snapshot ID is provided until the newly created job starts. The job can be queried by the newly implemented get_job_by_scheduled_time method of the Jobs object.

Creating Snapshots
from ipfabric import IPFClient
from pprint import pprint
from time import sleep

ipf = IPFClient()

snapshot = ipf.create_snapshot(
    fail_if_running_snapshot=False,  # Default is True and will fail if a snapshot is running.
    snapshot_name="New Snapshot via SDK",  # Default is `''`
    snapshot_note="This is a new snapshot created via the SDK",  # Default is `''`
    # The following are also available and default to `None` which will use the default values in Discovery Settings:
    networks=None,  # {include: List[<IP Network>], exclude: List[<IP Network>]}
                    # There must be 1 or more include networks; `['0.0.0.0/0']` will include all networks.
                    # To disable on-prem discovery and to only discover Vendor API (AWS, Azure, Google) networks, set include to `['0.0.0.0/32']`.
    seeds=None,  # List of IP addresses or subnets (/24 or smaller); Empty list will remove all seeds
    credentials=None,  # List of saved or custom credentials; Empty list will remove all credentials
                       # At least one credential is required for on-prem discovery.
    privileges=None,  # List of saved or custom privileges; Empty list will remove all privileges
    disabled_assurance_jobs=None,  # List[Literal["graphCache", "historicalData", "intentVerification"]]
    # To disable Vendor API's set `vendorApi=[]`; Vendor API validation has not been included yet.
)
pprint(snapshot.model_dump())

"""
{'error': False,
 'job': {'downloadFile': None,
         'finishedAt': None,
         'id': '2065349813',
         'isDone': False,
         'name': 'discoveryNew',
         'scheduledAt': 1727717798377,
         'snapshot': None,
         'startedAt': None,
         'status': 'scheduled',
         'username': 'justin.jeffery'},
 'message': 'Please wait till current running snapshot finishes to get the new '
            'snapshot ID.',
 'params': {'snapshotName': 'New Snapshot via SDK',
            'snapshotNote': 'This is a new snapshot created via the SDK'},
 'snapshot_running': True,
 'success': True}
"""

if snapshot.snapshot_id:
    print(f"New snapshot ID: {snapshot.snapshot_id}")
else:
    print(f"New snapshot will be created with the next job scheduled at: {snapshot.job_scheduled_at}")
    """New snapshot will be created with the next job scheduled at: 1727717798377"""
while not snapshot.snapshot_id:
    sleep(30)
    job = ipf.jobs.get_job_by_scheduled_time(snapshot.job_scheduled_at)
    if job.snapshot:
        snapshot.job = job
        print(f"New snapshot ID: {job.snapshot}")

pprint(job.model_dump())
"""
{'downloadFile': None,
 'finishedAt': None,
 'id': '2065349813',
 'isDone': False,
 'name': 'discoveryNew',
 'scheduledAt': 1727717798377,
 'snapshot': '90027d66-4299-4e10-b009-2f0505793d69',
 'startedAt': 1727717915672,
 'status': 'running',
 'username': 'justin.jeffery'}
"""

Managing Devices in Snapshots

The IP Fabric Python SDK provides several methods to manage devices within snapshots. These methods allow you to add new devices, rediscover existing devices, and delete devices from the snapshot.

Adding Devices

Adding Devices by IP

To add new devices to a snapshot by IP address or subnet:

from ipfabric import IPFClient

# Initialize the IPFClient
ipf = IPFClient()

ipf.snapshot.add_ip_devices(
    ip=['1.1.1.1', '10.0.0.0/31'],  # Also accepts ipaddress.IPv4* objects
    wait_for_discovery=True,
    wait_for_assurance=True,
    timeout=60,
    retry=5
)

Adding and Refreshing Devices

To add new devices, retry timed-out devices, and refresh vendor API devices:

from ipfabric import IPFClient

# Initialize the IPFClient
ipf = IPFClient()

ipf.snapshot.add_devices(
    ip=['1.1.1.1', '10.0.0.0/31'],  # Also accepts ipaddress.IPv4* objects
    refresh_vendor_api=True,  # Default True
    retry_timed_out=True,  # Default True
    wait_for_discovery=True,
    wait_for_assurance=True,
    timeout=60,
    retry=5
)

Rediscovering Devices

To rediscover devices in the snapshot based on their serial numbers:

from ipfabric import IPFClient

# Initialize the IPFClient
ipf = IPFClient()

ipf.snapshot.rediscover_devices(
    devices=['a2dff68', ipf.devices.all[0], 'BADSN'],
    wait_for_discovery=True,
    wait_for_assurance=True,
    timeout=60,
    retry=5,
    skip_invalid_devices=True  # Default behavior may vary
)

Deleting Devices

To delete devices from the snapshot based on their serial numbers:

from ipfabric import IPFClient

# Initialize the IPFClient
ipf = IPFClient()

ipf.snapshot.delete_devices(
    devices=[ipf.devices.all[-1], 'BADSN'],
    wait_for_discovery=True,
    wait_for_assurance=True,
    timeout=60,
    retry=5,
    skip_invalid_devices=True  # Default behavior may vary
)

Parameters Explanation

  • ip: List of IP addresses or subnets to add. Can be strings or ipaddress.IPv4* objects.
  • devices: List of device identifiers (serial numbers or device objects) to rediscover or delete.
  • refresh_vendor_api: Boolean to indicate whether to refresh vendor API devices.
  • retry_timed_out: Boolean to indicate whether to retry timed-out devices.
  • wait_for_discovery: Boolean to wait for the discovery process to complete.
  • wait_for_assurance: Boolean to wait for the assurance process to complete.
  • timeout: Maximum time (in seconds) to wait for discovery and assurance processes. (default is 60 seconds)
  • retry: Number of retry attempts for discovery and assurance processes. (default is 5 attempts)
  • skip_invalid_devices: Boolean to skip invalid devices during rediscovery or deletion.

Notes

  • The skip_invalid_devices parameter’s default behavior may vary. Consult the latest documentation for the current default setting.
  • When using ipf.devices.all[index], ensure that the devices have been loaded and the index is valid.
  • The wait_for_discovery and wait_for_assurance parameters allow you to control whether the method should wait for these processes to complete before returning.
  • Adjust the timeout and retry parameters based on your network size and complexity to ensure operations have sufficient time to complete.

These methods provide powerful tools for managing devices within your IP Fabric snapshots. Use them carefully, especially when deleting devices, to maintain the integrity of your network inventory.