Graphiant-SDK-Python

Prev Next

Getting Started

Python SDK for Graphiant NaaS.

Docs: https://github.com/Graphiant-Inc/graphiant-sdk-python/tree/main/docs

Source code: https://github.com/Graphiant-Inc/graphiant-sdk-python

Package: https://pypi.org/project/graphiant-sdk/

Topology

Installing Graphiant SDK Python Package

To Install Graphiant SDK Python package, Please refer to https://github.com/Graphiant-Inc/graphiant-sdk-python/blob/main/README.md

Creating Graphiant Portal Client

Import graphiant_sdk python package and define GraphiantPortalClient object.

import graphiant_sdk
from graphiant_sdk.exceptions import (ApiException, BadRequestException,
                                      UnauthorizedException, ForbiddenException,
                                      NotFoundException, ServiceException)
import time
from libs.logger import setup_logger

LOG = setup_logger()


class GraphiantPortalClient():
    def __init__(self, base_url=None, username=None, password=None):
        self.config = graphiant_sdk.Configuration(host=base_url,
                                                  username=username, password=password)
        self.api_client = graphiant_sdk.ApiClient(self.config)
        self.api = graphiant_sdk.DefaultApi(self.api_client)
        self.bearer_token = None

    def set_bearer_token(self):
        v1_auth_login_post_request = graphiant_sdk.V1AuthLoginPostRequest(username=self.config.username,
                                                                          password=self.config.password)
        v1_auth_login_post_response = None
        try:
            v1_auth_login_post_response = self.api.v1_auth_login_post(
                v1_auth_login_post_request=v1_auth_login_post_request)
        except BadRequestException as e:
            LOG.error(f"v1_auth_login_post: Got BadRequestException. Please verify payload is correct. {e}")
        except (UnauthorizedException, ServiceException) as e:
            LOG.error(f"v1_auth_login_post: Got Exception. Please verify crendentials are correct. {e}")
        LOG.debug(f"GraphiantPortalClient Bearer token : {v1_auth_login_post_response.token}")
        self.bearer_token = f'Bearer {v1_auth_login_post_response.token}'

Instantiate GraphiantPortalClient object

self.gsdk = GraphiantPortalClient(base_url=base_url, username=username, password=password)
self.gsdk.set_bearer_token()

Using Graphiant Portal Client

Once Graphiant portal client object is instated and bearer token is retrieved, user can perform CRUD operations using Graphiant APIs.

Refer API Documentation here: https://github.com/Graphiant-Inc/graphiant-sdk-python/blob/main/docs/DefaultApi.md

Getting Device Summary

E.g. Request to retrieve edges summary

edges_summary_response = self.api.v1_edges_summary_get(authorization=self.bearer_token)

v1_edges_summary_get returns  object of type V1EdgesSummaryGet200Response

https://github.com/Graphiant-Inc/graphiant-sdk-python/blob/main/docs/V1EdgesSummaryGet200Response.md

        device_name = 'edge-1-sdktest'
        edge_summary = None
        edges_summary_response = self.api.v1_edges_summary_get(authorization=self.bearer_token)
        for device_summary in edges_summary_response.edges_summary:
            if device_summary.hostname == device_name:
                edge_summary = device_summary
                break
        if edge_summary:
            LOG.info(f'{device_name} edge summary is  {edge_summary.to_str()}')
2025-06-18 11:32:43,374 - Graphiant_playbook - INFO - edge-1-sdktest edge summary is  {'assignedOn': None,
 'deviceId': 30000051803,
 'discoveredLocation': 'Tower Hamlets, Greater London, United Kingdom',
 'enterpriseId': 10000000288,
 'enterpriseName': None,
 'firstAppearedOn': {'nanos': 314421000, 'seconds': 1750202765},
 'hostname': 'edge-1-sdktest',
 'ipDetected': '62.89.143.70',
 'isHardware': None,
 'isNew': True,
 'isRequested': None,
 'lastBootedAt': {'nanos': 537864000, 'seconds': 1750202669},
 'location': {'addressLine1': '',
              'addressLine2': '',
              'city': 'tower hamlets',
              'country': 'united kingdom',
              'countryCode': '',
              'latitude': None,
              'longitude': None,
              'notes': None,
              'provinceCode': '',
              'state': 'greater london',
              'stateCode': ''},
 'model': 'QEMU-Q35',
 'overrideRegion': 'us-west-2 (San Jose)',
 'parentEnterpriseName': None,
 'portalStatus': 'Ready',
 'region': 'eu-west-1 (London)',
 'role': 'cpe',
 'serialNum': '5020cf30-fcee-4f02-93af-8a5ba61f1f0b',
 'site': 'San Jose-sdktest',
 'siteId': 4716,
 'stale': None,
 'status': 'active',
 'swName': '25.6.1',
 'swVersion': '2506.202506021956',
 'ttConnCount': 2,
 'upgradeSummary': None}

Updating Device configuration

Prerequisite before configuration push to device

Before updating a device (edge/gateway/core) configuration, it is required to make sure that the device’s Portal Sync status is in InSync state (a.k.a Ready state).   It is also required to make sure that device has connectivity to the Graphiant portal via Graphiant tunnel terminators. These two pieces of information can be found from v1/edges/summary API

    def get_edges_summary(self, device_id=None):
        """
        Get all edges summary from GCS.

        Args:
            device_id (int, optional): The device ID to filter edges.
            If not provided, returns all edges.

        Returns:
            edges_summary: Optional[List[V1EdgesHardwareAssignedGet200ResponseEdgesSummaryInner]]: 
                A list of all edges summary info if no device_id is provided,
            (or)
            edge_info: V1EdgesHardwareAssignedGet200ResponseEdgesSummaryInner
                 A single edge's summary information if a device_id is provided.
        """
        response = self.api.v1_edges_summary_get(authorization=self.bearer_token)
        if device_id:
            for edge_info in response.edges_summary:
                if edge_info.device_id == device_id:
                    return edge_info
        return response.edges_summary
    def verify_device_portal_status(self, device_id: int):
        """
        Verifies device portal sync Ready status (InSync) and
         also verifies device connections to tunnel terminators status.
        """
        edge_summary = self.get_edges_summary(device_id=device_id)
        if edge_summary.portal_status == "Ready":
            if edge_summary.tt_conn_count and edge_summary.tt_conn_count == 2:
                return
            else:
                LOG.info(f"verify_device_portal_status: {device_id} tunnel terminitor conn count: "
                         f"{edge_summary.tt_conn_count} Expected: tt_conn_count=2. Retrying..")
                assert False, (f"verify_device_portal_status: {device_id} tunnel terminitor conn count: "
                               f"{edge_summary.tt_conn_count} Expected: tt_conn_count=2. Retry")

        else:
            LOG.info(f"verify_device_portal_status: {device_id} Portal Status: "
                     f"{edge_summary.portal_status} Expected: Ready. Retrying..")
            assert False, (f"verify_device_portal_status: {device_id} Portal Status: "
                           f"{edge_summary.portal_status} Expected: Ready. Retrying..")

Configuring interface and subinterfaces of an edge device

Device configuration push is achieved using  API PUT v1/devices/<deviceid>/config. The corresponding method in the Graphiant python sdk is v1_devices_device_id_config_put which has parameter v1_devices_device_id_config_put_request: V1DevicesDeviceIdConfigPutRequest to pass the config request payload to configure edge/gateway V1DevicesDeviceIdConfigPutRequestEdge or core V1DevicesDeviceIdConfigPutRequestCore devices.

Refer V1DevicesDeviceIdConfigPutRequestEdge and V1DevicesDeviceIdConfigPutRequest model documentation

https://github.com/Graphiant-Inc/graphiant-sdk-python/blob/main/docs/V1DevicesDeviceIdConfigPutRequestEdge.md

E.g Request to configure edge’s circuit, interface and add a subinterface

  1. Create payload object V1DevicesDeviceIdConfigPutRequest for config push.

# V1DevicesDeviceIdConfigPutRequestEdgeCircuitsValue can be in dict instead of creating object explicitly.

circuits = {
    "c-gigabitethernet5-0-0": {
        "name": "c-gigabitethernet5-0-0",
        "description": "c-gigabitethernet5-0-0",
        "linkUpSpeedMbps": 50,
        "linkDownSpeedMbps": 100,
        "connectionType": "internet_dia",
        "label": "internet_dia_4",
        "qosProfile": "gold25",
        "qosProfileType": "balanced",
        "diaEnabled": false,
        "lastResort": false,
        "patAddresses": {},
        "staticRoutes": {}
    }
}

# V1DevicesDeviceIdConfigPutRequestEdgeInterfacesValue can be in dict instead of creating object explicitly. Object will be created when assigned. 

interfaces =  {"GigabitEthernet5/0/0": {"interface": {"adminStatus": true, "maxTransmissionUnit": 1500, "circuit": "c-gigabitethernet5-0-0", "description": "wan_1", "alias": "primary_wan", "ipv4": {"dhcp": {"dhcpClient": true}}, "ipv6": {"dhcp": {"dhcpClient": true}}}}, "GigabitEthernet8/0/0": {"interface": {"subinterfaces": {"18": {"interface": {"lan": "lan-7-test", "vlan": 18, "description": "lan-7", "alias": "non_production", "adminStatus": true, "ipv4": {"address": {"address": "10.2.7.1/24"}}, "ipv6": {"address": {"address": "2001:10:2:7::1/64"}}}}}}}}

# Edge configuration payload V1DevicesDeviceIdConfigPutRequestEdge 
device_config_put_request_edge = V1DevicesDeviceIdConfigPutRequestEdge(circuits=circuits,
                                                                       interfaces=interfaces)
                                                                      
# Payload V1DevicesDeviceIdConfigPutRequest for v1_devices_device_id_config_put method.
device_config_put_request = V1DevicesDeviceIdConfigPutRequest(edge=device_config_put_request_edge)

                                               

                                             

  1. Push the configuration to the device after verifying device portal sync status and device-portal connections

        try:
            # Verify device portal status and connection status.
            self.verify_device_portal_status(device_id=device_id)

            # Push the configuration (V1DevicesDeviceIdConfigPutRequest)
            LOG.info(f"put_device_config : config to be pushed for {device_id}: \n{device_config_put_request}")
            response = self.api.v1_devices_device_id_config_put(
                authorization=self.bearer_token, device_id=device_id,
                v1_devices_device_id_config_put_request=device_config_put_request)
            return response
            
        except ForbiddenException as e:
            LOG.error(f"put_device_config : Got ForbiddenException while config push to {device_id}. "
                      f"User {self.config.username} does not have permissions to perform the requested operation "
                      f"(v1_devices_device_id_config_put).")
        except ApiException as e:
            LOG.warning(f"put_device_config : Exception while config push {e}")

  1. Value of device_config_put_request: V1DevicesDeviceIdConfigPutRequest in the log file. NOTE: Dict value is automatically translated to corresponding objects. Optionally you create objects and build the payload.

2025-06-17 17:00:29,868 - Graphiant_playbook - INFO - put_device_config : config to be pushed for 30000051803:
configuration_metadata=None core=None description=None edge=V1DevicesDeviceIdConfigPutRequestEdge(bgp_enabled=None, bgp_instance=None, circuits={'c-gigabitethernet5-0-0': V1DevicesDeviceIdConfigPutRequestEdgeCircuitsValue(bgp_aggregations=None, bgp_multipath=None, bgp_neighbors=None, bgp_redistribution=None, carrier=None, circuit_type=None, connection_type='internet_dia', description='c-gigabitethernet5-0-0', dia_enabled=False, drop_mechanism=None, label='internet_dia_4', last_resort=False, link_down_speed_mbps=100, link_up_speed_mbps=50, loopback=None, name='c-gigabitethernet5-0-0', pat_addresses=V1DevicesDeviceIdConfigPutRequestEdgeCircuitsValuePatAddresses(addresses=None), qos_profile='gold25', qos_profile_type='balanced', static_routes={})}, dhcp_server_enabled=None, dns=None, interfaces={'GigabitEthernet5/0/0': V1DevicesDeviceIdConfigPutRequestEdgeInterfacesValue(interface=V1DevicesDeviceIdConfigPutRequestEdgeInterfacesValueInterface(admin_status=True, alias='primary_wan', circuit='c-gigabitethernet5-0-0', description='wan_1', ipsec=None, ipv4=V1DevicesDeviceIdConfigPutRequestCoreInterfacesValueInterfaceGwGw(address=None, dhcp=V1DevicesDeviceIdConfigPutRequestCoreInterfacesValueInterfaceGwGwDhcp(dhcp_client=True, dhcp_relay=None), vrrp=None), ipv6=V1DevicesDeviceIdConfigPutRequestCoreInterfacesValueInterfaceGwGw(address=None, dhcp=V1DevicesDeviceIdConfigPutRequestCoreInterfacesValueInterfaceGwGwDhcp(dhcp_client=True, dhcp_relay=None), vrrp=None), lan=None, lldp_enabled=None, loopback=None, max_transmission_unit=1500, security_zone=None, subinterfaces=None, tcp_mss=None, tcp_mss_v4=None, tcp_mss_v6=None, v4_tcp_mss=None, v6_tcp_mss=None)), 'GigabitEthernet8/0/0': V1DevicesDeviceIdConfigPutRequestEdgeInterfacesValue(interface=V1DevicesDeviceIdConfigPutRequestEdgeInterfacesValueInterface(admin_status=None, alias=None, circuit=None, description=None, ipsec=None, ipv4=None, ipv6=None, lan=None, lldp_enabled=None, loopback=None, max_transmission_unit=None, security_zone=None, subinterfaces={'18': V1DevicesDeviceIdConfigPutRequestEdgeInterfacesValueInterfaceSubinterfacesValue(interface=V1DevicesDeviceIdConfigPutRequestEdgeInterfacesValueInterfaceSubinterfacesValueInterface(admin_status=True, alias='non_production', circuit=None, description='lan-7', ipv4=V1DevicesDeviceIdConfigPutRequestCoreInterfacesValueInterfaceGwGw(address=V1GlobalConfigPatchRequestSnmpsValueConfigEngineEndpointsValueEngineEndpointAddressesValue(address='10.2.7.1/24'), dhcp=None, vrrp=None), ipv6=V1DevicesDeviceIdConfigPutRequestCoreInterfacesValueInterfaceGwGw(address=V1GlobalConfigPatchRequestSnmpsValueConfigEngineEndpointsValueEngineEndpointAddressesValue(address='2001:10:2:7::1/64'), dhcp=None, vrrp=None), lan='lan-7-test', lldp_enabled=None, max_transmission_unit=None, security_zone=None, tcp_mss=None, tcp_mss_v4=None, tcp_mss_v6=None, v4_tcp_mss=None, v6_tcp_mss=None, vlan=18, vrrp=None))}, tcp_mss=None, tcp_mss_v4=None, tcp_mss_v6=None, v4_tcp_mss=None, v6_tcp_mss=None))}, ipfix_enabled=None, ipfix_exporters=None, lldp_enabled=None, local_route_tag=None, local_web_server_password=None, location=None, maintenance_mode=None, name=None, nat_policy=None, ospfv2_enabled=None, ospfv3_enabled=None, prefix_sets=None, region=None, region_name=None, route_policies=None, segments=None, site=None, site_to_site_vpn=None, snmp=None, snmp_global_object=None, static_routes_enabled=None, traffic_policy=None, vrrp_enabled=None) local_web_server_password=None replace=None

The response (V1DevicesDeviceIdConfigPut202Response) of the request (V1DevicesDeviceIdConfigPutRequest) will contain job_id which can be used to monitor the success and progress of the device update configuration.