7 |
10 | dnac.DnacError = class DnacError(exceptions.Exception) | ||
13 | | DnacError is an exception class for any errors specific to setting up and maintaining a connection with a Cisco DNA 14 | Center cluster. 15 | 16 | Attributes: 17 | None | |
19 | |
26 | Methods defined here: 27 |
31 | Data descriptors defined here: 32 |
36 | Data and other attributes inherited from exceptions.Exception: 37 |
40 | Methods inherited from exceptions.BaseException: 41 |
64 | Data descriptors inherited from exceptions.BaseException: 65 |
|
10 | dnac.basicauth | index /cygdrive/c/Users/rsayle/PycharmProjects/DNAC-Python-Wrapper/dnac/basicauth.py |
15 |
18 | Classes | ||||||||||
21 | |
30 |
|
10 | dnac.ctype | index /cygdrive/c/Users/rsayle/PycharmProjects/DNAC-Python-Wrapper/dnac/ctype.py |
# globals
14 |15 |
18 | Classes | ||||||||||
21 | |
30 |
|
79 |
82 | Data | ||
85 | | JSON = 'application/json' 86 | XML = 'application/xml' |
10 | dnac.deployment | index /cygdrive/c/Users/rsayle/PycharmProjects/DNAC-Python-Wrapper/dnac/deployment.py |
15 |
18 | Classes | ||||||||||
21 | |
30 |
|
131 |
134 | Data | ||
137 | | ACCEPTED = 202 138 | DEPLOYMENT_RESOURCE_PATH = {'1.2.10': '/api/v1/template-programmer/template/deploy/status', '1.2.8': '/api/v1/template-programmer/template/deploy/status', '1.3.0.2': '/api/v1/template-programmer/template/deploy/status', '1.3.0.3': '/api/v1/template-programmer/template/deploy/status', '1.3.1.3': '/api/v1/template-programmer/template/deploy/status', '1.3.1.4': '/dna/intent/api/v1/template-programmer/template/deploy/status/'} 139 | ERROR_MSGS = {400: '400 - API request syntax is malformed', 401: '401 - API request has missing or invalid credentials', 403: '403 - API request is unauthorized', 404: '404 - API requested resource does not exist', 409: '409 - API requested resource is in a conflicted state', 415: '415 - API request body is in an unsupported format', 417: '417 - The server cannot meet the requirements of the Expect request-header field', 500: '500 - Server could not fulfill the API request', 501: '501 - Server has not implemented the requested function', 503: '503 - Server is unavailable', ...} 140 | MODULE = 'deployment.py' 141 | NO_STATUS = '' 142 | REQUEST_NOT_ACCEPTED = 'API request is not ACCEPTED' 143 | STATUS_KEY = 'status' 144 | SUPPORTED_DNAC_VERSIONS = ['1.2.8', '1.2.10', '1.3.0.2', '1.3.0.3', '1.3.1.3', '1.3.1.4'] 145 | UNSUPPORTED_DNAC_VERSION = 'Unsupported Cisco DNA Center version' |
10 | dnac.dnac_config | index /cygdrive/c/Users/rsayle/PycharmProjects/DNAC-Python-Wrapper/dnac/dnac_config.py |
Configuration parameters for a Dnac object.
14 |15 |
18 | Data | ||
21 | | DNAC_CONTENT_TYPE = 'application/json' 22 | DNAC_IP = '' 23 | DNAC_NAME = 'denlab-en-dnac.cisco.com' 24 | DNAC_PASSWD = 'C!sco123' 25 | DNAC_PORT = '443' 26 | DNAC_USER = 'admin' 27 | DNAC_VERSION = '1.3.1.4' |
10 | dnac.timestamp | index /cygdrive/c/Users/rsayle/PycharmProjects/DNAC-Python-Wrapper/dnac/timestamp.py |
15 |
18 | Modules | ||||||
21 | |
|
23 |
26 | Classes | ||||||||||
29 | |
38 |
|
98 |
101 | Data | ||
104 | | GET_CURRENT_TIME = 0 105 | MODULE = 'timestamp.py' 106 | NO_TIME = -1 |
7 | % if bool(dnac.name): 8 | Connected to DNA Center cluster: {{dnac.name}} 9 | % elif bool(dnac.ip): 10 | Connected to DNA Center cluster: {{dnac.ip}} 11 | % else: 12 | Cannot connect to DNA Center cluster. Please set the FQDN or cluster IP in dnac_config. 13 | %end 14 |
15 | Add archive version for {{host}} 16 |
17 | Select the configuration files to add:
18 |
7 | % if bool(dnac.name): 8 | Connected to DNA Center cluster: {{dnac.name}} 9 | % elif bool(dnac.ip): 10 | Connected to DNA Center cluster: {{dnac.ip}} 11 | % else: 12 | Cannot connect to DNA Center cluster. Please set the FQDN or cluster IP in dnac_config. 13 | %end 14 |
15 | Successfully added a new archive version for {{host}} 16 |
17 |
20 | -------------------------------------------------------------------------------- /examples/config_archiver/views/change_settings.tpl: -------------------------------------------------------------------------------- 1 | % current = archive_settings.settings 2 | 3 |7 | % if bool(dnac.name): 8 | Connected to DNA Center cluster: {{dnac.name}} 9 | % elif bool(dnac.ip): 10 | Connected to DNA Center cluster: {{dnac.ip}} 11 | % else: 12 | Cannot connect to DNA Center cluster. Please set the FQDN or cluster IP in dnac_config. 13 | %end 14 |
15 |
22 | -------------------------------------------------------------------------------- /examples/config_archiver/views/config_archiver.tpl: -------------------------------------------------------------------------------- 1 | 2 |4 | % if bool(dnac.name): 5 | Connected to DNA Center cluster: {{dnac.name}} 6 | % elif bool(dnac.ip): 7 | Connected to DNA Center cluster: {{dnac.ip}} 8 | % else: 9 | Cannot connect to DNA Center cluster. Please set the FQDN or cluster IP in dnac_config. 10 | %end 11 |
12 |
15 | 18 | | 19 |20 | 23 | | 24 |25 | 28 | | 29 |
6 | % if bool(dnac.name): 7 | Connected to DNA Center cluster: {{dnac.name}} 8 | % elif bool(dnac.ip): 9 | Connected to DNA Center cluster: {{dnac.ip}} 10 | % else: 11 | Cannot connect to DNA Center cluster. Please set the FQDN or cluster IP in dnac_config. 12 | %end 13 |
14 | % if not bool(hosts): 15 | All devices already have archives. 16 |
17 |
20 | % else: 21 | 29 | 32 | 33 | % end 34 | -------------------------------------------------------------------------------- /examples/config_archiver/views/create_new_device_archive.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 |7 | % if bool(dnac.name): 8 | Connected to DNA Center cluster: {{dnac.name}} 9 | % elif bool(dnac.ip): 10 | Connected to DNA Center cluster: {{dnac.ip}} 11 | % else: 12 | Cannot connect to DNA Center cluster. Please set the FQDN or cluster IP in dnac_config. 13 | %end 14 |
15 | Create archive for {{host}} 16 |
17 | Select the configuration files to add:
18 |
5 | % for version in deleted_versions:
6 | {{version}}
7 | % end
8 |
9 |
12 | 13 | -------------------------------------------------------------------------------- /examples/config_archiver/views/delete_config.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | Successfully deleted selected config file. 4 |5 |
9 | 10 | -------------------------------------------------------------------------------- /examples/config_archiver/views/delete_device_archive_versions.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 |17 | % if bool(dnac.name): 18 | Connected to DNA Center cluster: {{dnac.name}} 19 | % elif bool(dnac.ip): 20 | Connected to DNA Center cluster: {{dnac.ip}} 21 | % else: 22 | Cannot connect to DNA Center cluster. Please set the FQDN or cluster IP in dnac_config. 23 | %end 24 |
25 | Configuration archive for {{host}} 26 |
Version | 29 |30 | |
---|
5 | % if bool(dnac.name): 6 | Connected to DNA Center cluster: {{dnac.name}} 7 | % elif bool(dnac.ip): 8 | Connected to DNA Center cluster: {{dnac.ip}} 9 | % else: 10 | Cannot connect to DNA Center cluster. Please set the FQDN or cluster IP in dnac_config. 11 | %end 12 |
13 |
23 |24 |
27 | 28 | -------------------------------------------------------------------------------- /examples/config_archiver/views/manage_archive_configs.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 |17 | % if bool(dnac.name): 18 | Connected to DNA Center cluster: {{dnac.name}} 19 | % elif bool(dnac.ip): 20 | Connected to DNA Center cluster: {{dnac.ip}} 21 | % else: 22 | Cannot connect to DNA Center cluster. Please set the FQDN or cluster IP in dnac_config. 23 | %end 24 |
25 | Configuration archive for {{host}} 26 |
Version | 29 |30 | | 31 | |
---|
7 | % if bool(dnac.name): 8 | Connected to DNA Center cluster: {{dnac.name}} 9 | % elif bool(dnac.ip): 10 | Connected to DNA Center cluster: {{dnac.ip}} 11 | % else: 12 | Cannot connect to DNA Center cluster. Please set the FQDN or cluster IP in dnac_config. 13 | %end 14 |
15 |
18 | Timeout 19 | | 20 |21 | {{current['timeout']}} 22 | | 23 |
26 | Number of Days 27 | | 28 |29 | {{current['noOfDays']}} 30 | | 31 |
34 | Number of Versions 35 | | 36 |37 | {{current['noOfVersion']}} 38 | | 39 |
44 | 49 | | 50 |51 | 56 | | 57 |
4 |
5 | {{config}}:
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/examples/device_finder/device_finder.py:
--------------------------------------------------------------------------------
1 | from dnac import Dnac
2 | from dnac.site import Site, STUB_SITE
3 | from dnac.networkdevice import NetworkDevice, STUB_DEVICE
4 | from dnac.dnacapi import DnacApiError
5 | from bottle import Bottle, run, template, request
6 | import sys
7 | import json
8 |
9 | MODULE = 'device_finder.py'
10 |
11 | NO_CLUSTER_NAME_NOR_IP = "Cluster has no name nor IP address"
12 | HTTPS = 'https://'
13 | INVENTORY_URI = '/dna/provision/devices/inventory?devices-view=inventoryView&selectedSite='
14 | DEVICE360_URI = '/dna/assurance/home#networkDevice/'
15 |
16 | clusters = []
17 | finder = Bottle()
18 |
19 |
20 | def get_cluster(cluster_id):
21 | """
22 | Retrieves the cluster by a cluster identifier.
23 | :param cluster_id: Identifies a cluster by its name or IP address.
24 | type: str
25 | required: yes
26 | default: None
27 | :return: Dnac object
28 | """
29 | for cluster in clusters:
30 | if cluster_id == cluster.name or cluster_id == cluster.ip:
31 | return cluster
32 | else:
33 | Exception('%s: get_cluster: Could not find cluster %s' % (MODULE, cluster_id))
34 |
35 |
36 | def get_cluster_id(cluster):
37 | if cluster.name != "":
38 | return cluster.name
39 | elif cluster.ip != "":
40 | return cluster.ip
41 | else:
42 | raise Exception("%s: %s" % (MODULE, NO_CLUSTER_NAME_NOR_IP))
43 |
44 |
45 | @finder.route('/', method='GET')
46 | @finder.route('/index', method='GET')
47 | @finder.route('/select_device', method='POST')
48 | def select_device():
49 | return template('select_device', clusters=clusters, method='GET')
50 |
51 |
52 | def get_site(device, cluster):
53 | details = device.get_device_detail_by_name(device.devices['id'])
54 | location = details['location']
55 | if location in cluster.api.keys():
56 | location_id = cluster.api[location].id
57 | else:
58 | site = Site(cluster, location)
59 | location_id = site.id
60 | return location_id
61 |
62 |
63 | @finder.route('/find_device_by_name', method='POST')
64 | def find_device_by_name():
65 | name = request.forms.get('name')
66 | device = None
67 | target_cluster = None
68 | cluster_id = None
69 | inventory_url = ''
70 | device360_url = ''
71 | for cluster in clusters:
72 | # if the device has been cached, return it
73 | if name in cluster.api.keys():
74 | device = cluster.api[name]
75 | target_cluster = cluster
76 | cluster_id = get_cluster_id(cluster)
77 | break
78 | # otherwise, try finding it in the current cluster
79 | else:
80 | try:
81 | # an exception will be thrown if it's not in the cluster
82 | result = cluster.api[STUB_DEVICE].get_device_by_name(name)
83 | # otherwise, it does exist in the physical cluster; cache it in the cluster and return it
84 | device = NetworkDevice(cluster, result['hostname'])
85 | target_cluster = cluster
86 | cluster_id = get_cluster_id(cluster)
87 | break
88 | except DnacApiError:
89 | # device not found; try the next cluster
90 | continue
91 | # if the device was found, get the associated site info in case the user wants to cross-launch into inventory
92 | if bool(device):
93 | details = device.get_device_detail_by_name(name)
94 | location = details['location']
95 | if location in target_cluster.api.keys():
96 | site = target_cluster.api[location]
97 | else:
98 | site = Site(target_cluster, location)
99 | inventory_url = '%s%s%s%s' % (HTTPS, cluster_id, INVENTORY_URI, site.id)
100 | device360_url = '%s%s%s%s' % (HTTPS, cluster_id, DEVICE360_URI, device.get_id_by_device_name(name))
101 | return template('results', target=name, cluster=cluster_id, device=device, inventory_url=inventory_url,
102 | device360_url=device360_url, method='GET')
103 |
104 |
105 | @finder.route('/find_device_by_ip', method='POST')
106 | def find_device_by_ip():
107 | ip = request.forms.get('ip')
108 | device = None
109 | target_cluster = None
110 | cluster_id = None
111 | inventory_url = ''
112 | device360_url = ''
113 | for cluster in clusters:
114 | # if the device has been cached, return it
115 | if ip in cluster.api.keys():
116 | device = cluster.api[ip]
117 | target_cluster = cluster
118 | cluster_id = get_cluster_id(cluster)
119 | break
120 | # otherwise, try finding it in the current cluster
121 | else:
122 | try:
123 | # an exception will be thrown if it's not in the cluster
124 | result = cluster.api[STUB_DEVICE].get_device_by_ip(ip)
125 | # otherwise, it does exist in the physical cluster; cache it in the cluster and return it
126 | device = NetworkDevice(cluster, result['managementIpAddress'])
127 | target_cluster = cluster
128 | cluster_id = get_cluster_id(cluster)
129 | break
130 | except DnacApiError:
131 | # device not found; try the next cluster
132 | continue
133 | # if the device was found, get the associated site info in case the user wants to cross-launch into inventory
134 | if bool(device):
135 | device_by_ip = device.get_device_by_ip(ip)
136 | details = device.get_device_detail_by_name(device_by_ip['hostname'])
137 | location = details['location']
138 | if location in target_cluster.api.keys():
139 | site = target_cluster.api[location]
140 | else:
141 | site = Site(target_cluster, location)
142 | inventory_url = '%s%s%s%s' % (HTTPS, cluster_id, INVENTORY_URI, site.id)
143 | device360_url = '%s%s%s%s' % (HTTPS, cluster_id, DEVICE360_URI, device.devices['id'])
144 | return template('results', target=ip, cluster=cluster_id, device=device, inventory_url=inventory_url,
145 | device360_url=device360_url, method='GET')
146 |
147 |
148 | ##### Main Program #####################################################################################################
149 |
150 | if __name__ == '__main__':
151 | """
152 | usage: device_finder 4 |
8 |
11 | 14 | | 15 |16 | 19 | | 20 |
26 |
29 |12 |
24 |
27 | 34 | | 35 |36 | 43 | | 44 |
4 | % for result in results:
5 | {{result}}
6 | % end
7 |
8 |
5 |
8 | Source Cluster 9 | 18 | |
19 |
20 | Target Cluster 21 | 30 | |
31 |
34 |
4 |
36 | 41 | -------------------------------------------------------------------------------- /examples/networkdevice_example.py: -------------------------------------------------------------------------------- 1 | 2 | from dnac import Dnac 3 | from dnac.networkdevice import NetworkDevice 4 | 5 | MODULE = 'networkdevice_example.py' 6 | 7 | print('%s: setting up Cisco DNA Center and its API...' % MODULE) 8 | dnac = Dnac() 9 | ndapi = NetworkDevice(dnac, 'devices') 10 | 11 | print('%s: getting all devices...' % MODULE) 12 | # The handle 'ndapi' could be used here, but the point of this example is 13 | # demonstrate how to get it directly from the Dnac.api{} using the API's name. 14 | devices = dnac.api['devices'].get_all_devices() 15 | 16 | print('%s: found the following devices:' % MODULE) 17 | for device in devices: 18 | print('hostname: %s\tserial: %s\tIP: %s' % 19 | (device['hostname'], device['serialNumber'], 20 | device['managementIpAddress'])) 21 | print() 22 | -------------------------------------------------------------------------------- /examples/site_hierarchy_replicator/dnac_clusters.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "denlab-en-dnac.cisco.com", 4 | "ip": "", 5 | "version": "1.3.1.4", 6 | "port": 443, 7 | "user": "admin", 8 | "passwd": "C!sco123", 9 | "content_type": "application/json" 10 | }, 11 | { 12 | "name": "", 13 | "ip": "173.36.255.155", 14 | "version": "1.3.1.4", 15 | "port": 443, 16 | "user": "admin", 17 | "passwd": "c!sco123", 18 | "content_type": "application/json" 19 | } 20 | ] 21 | -------------------------------------------------------------------------------- /examples/site_hierarchy_replicator/site_hierarchy_replicator.py: -------------------------------------------------------------------------------- 1 | from dnac import Dnac 2 | from dnac.site import Site, STUB_SITE, AREA, BUILDING, FLOOR 3 | from dnac.site_hierarchy import SiteHierarchy, SITE_HIERARCHY_NAME 4 | from bottle import Bottle, run, template, request 5 | import sys 6 | import json 7 | 8 | MODULE = 'site_hierarchy_replicator.py' 9 | 10 | clusters = [] 11 | replicator = Bottle() 12 | 13 | 14 | def get_cluster(cluster_id): 15 | """ 16 | Retrieves the cluster by a cluster identifier. 17 | :param cluster_id: Identifies a cluster by its name or IP address. 18 | type: str 19 | required: yes 20 | default: None 21 | :return: Dnac object 22 | """ 23 | for cluster in clusters: 24 | if cluster_id == cluster.name or cluster_id == cluster.ip: 25 | return cluster 26 | else: 27 | Exception('%s: get_cluster: Could not find cluster %s' % (MODULE, cluster_id)) 28 | 29 | 30 | def get_source_and_target(request): 31 | """ 32 | Retrieves the source and target cluster names passed from a Bottle template in the request forms. Also removes 33 | the source and target from the request's FormsDict so that further processing can be performed on the request's 34 | list of projects or templates. 35 | :param request: The request object returned from a Bottle template's posting. 36 | type: Bottle request object 37 | required: yes 38 | default: none 39 | :return: 40 | source: The source cluster's name 41 | type: str 42 | target: The target cluster's name 43 | type: str 44 | source_cluster: The source cluster's Dnac representation 45 | type: Dnac object 46 | target_cluster: The target cluster's Dnac representation 47 | type: Dnac object 48 | """ 49 | source = request.forms.get('source') 50 | source_cluster = get_cluster(source) 51 | request.forms.pop('source') 52 | target = request.forms.get('target') 53 | target_cluster = get_cluster(target) 54 | request.forms.pop('target') 55 | return source, target, source_cluster, target_cluster 56 | 57 | 58 | @replicator.route('/', method='GET') 59 | @replicator.route('/index', method='GET') 60 | @replicator.route('/select_clusters', method='POST') 61 | def select_clusters(): 62 | """ 63 | Passes the list of all clusters loaded during project initialization to the home page. 64 | :return: Bottle template 65 | """ 66 | return template('select_clusters', clusters=clusters, method='GET') 67 | 68 | 69 | def get_site_hierarchy(cluster): 70 | """ 71 | Retrieves the cluster's SiteHierarchy object. 72 | :param cluster: The Dnac cluster whose SiteHierarchy is required. 73 | type: Dnac object 74 | required: yes 75 | default: none 76 | :return: SiteHierarchy object 77 | """ 78 | if bool(cluster.name): 79 | cluster_id = cluster.name 80 | elif bool(cluster.ip): 81 | cluster_id = cluster.ip 82 | else: 83 | raise Exception('%s: get_site_hierarchy: Dnac cluster has no name nor IP address' % MODULE) 84 | site_hierarchy_name = '%s%s' % (cluster_id, SITE_HIERARCHY_NAME) 85 | if site_hierarchy_name in cluster.api.keys(): 86 | return cluster.api[site_hierarchy_name] 87 | else: 88 | return SiteHierarchy(cluster, timeout=60) 89 | 90 | 91 | @replicator.route('/select_sites', method='POST') 92 | def select_sites(): 93 | """ 94 | Loads the source and target site hierarchies in a web page that allows a user to select the sites from the source 95 | cluster that should be replicated to the target cluster. 96 | :return: Bottle template 97 | """ 98 | source, target, source_cluster, target_cluster = get_source_and_target(request) 99 | if source == target: 100 | raise Exception( 101 | '%s: select_sites: Source and target DNAC clusters cannot be the same' % MODULE 102 | ) 103 | source_hierarchy = get_site_hierarchy(source_cluster) 104 | source_hierarchy.load_sites() 105 | target_hierarchy = get_site_hierarchy(target_cluster) 106 | target_hierarchy.load_sites() 107 | return template('select_sites', source=source, target=target, 108 | source_hierarchy=source_hierarchy, target_hierarchy=target_hierarchy) 109 | 110 | 111 | @replicator.route('/replicate_sites', method='POST') 112 | def replicate_sites(): 113 | """ 114 | Iterates through the sites chosen for replication and copies them from the source to the target cluster. 115 | :return: Bottle template 116 | """ 117 | source, target, source_cluster, target_cluster = get_source_and_target(request) 118 | if source == target: 119 | raise Exception( 120 | '%s: replicate_sites: Source and target DNAC clusters cannot be the same' % MODULE 121 | ) 122 | results = [] 123 | for site in request.forms: 124 | results = copy_site(site, source, target, source_cluster, target_cluster, results) 125 | return template('replicate_sites', source=source, target=target, results=results) 126 | 127 | 128 | def copy_site(site, source, target, source_cluster, target_cluster, results): 129 | """ 130 | Takes the site information from the source cluster and copies it over to the target cluster. 131 | :param site: The site being copied. 132 | type: str 133 | required: yes 134 | default: none 135 | :param source: The source cluster's identifier, i.e. it's name or IP address. 136 | type: str 137 | required: yes 138 | default: none 139 | :param target: The target cluster's identifier, i.e. it's name or IP address. 140 | type: str 141 | required: yest 142 | default: none 143 | :param source_cluster: The source cluster's Dnac object. 144 | type: Dnac object 145 | required: yes 146 | default: none 147 | :param target_cluster: The target cluster's Dnac object. 148 | type: Dnac object 149 | required: yes 150 | default: none 151 | :param results: The list of site replication results. 152 | type: list 153 | required: yes 154 | default: none 155 | :return: The results list with the addition of the result from calling this function appended to it. 156 | """ 157 | if site not in source_cluster.api.keys(): 158 | results.append( 159 | 'Site %s could not be found in source cluster %s. Skipping...' % (site, source) 160 | ) 161 | source_site = source_cluster.api[site] 162 | # don't add the site if it's parent doesn't exist in the target 163 | if source_site.parent_name not in target_cluster.api.keys(): 164 | results.append('Parent site %s does not exist for site %s. Skipping...' % (source_site.parent_name, site)) 165 | return results 166 | # check the location type and add the site accordingly using the source_site's location values 167 | try: 168 | if source_site.location['type'] == AREA: 169 | target_cluster.api['STUB_SITE'].add_site( 170 | AREA, source_site.name, source_site.parent_name 171 | ) 172 | elif source_site.location['type'] == BUILDING: 173 | target_cluster.api['STUB_SITE'].add_site( 174 | BUILDING, source_site.name, source_site.parent_name, address=source_site.address, 175 | latitude=source_site.latitude, longitude=source_site.longitude 176 | ) 177 | elif source_site.location['type'] == FLOOR: 178 | target_cluster.api['STUB_SITE'].add_site( 179 | FLOOR, source_site.name, source_site.parent_name, rf_model=source_site.rf_model, 180 | width=source_site.width, length=source_site.length, height=source_site.height 181 | ) 182 | else: 183 | results.append( 184 | '%s: copy_site: Unidentifiable site type for site %s: %s. Skipping...' % 185 | (MODULE, site, source_site.location['type']) 186 | ) 187 | results.append('Successfully added site %s to target cluster %s' % (site, target)) 188 | # have the target_cluster refresh its SiteHierarchy 189 | except Exception as error: 190 | results.append('Failed to add site %s to target cluster %s: %s' % (site, target, error)) 191 | return results 192 | 193 | 194 | # Main Program ######################################################################################################## 195 | 196 | 197 | if __name__ == '__main__': 198 | """ 199 | usage: site_heirarchy_replicator
4 | % for result in results:
5 | {{result}}
6 | % end
7 |
8 |
5 |
8 | Source Cluster 9 | 18 | |
19 |
20 | Target Cluster 21 | 30 | |
31 |
34 |
4 |
36 | 41 | -------------------------------------------------------------------------------- /examples/template_example.py: -------------------------------------------------------------------------------- 1 | 2 | from dnac import Dnac 3 | from dnac.template import Template, TARGET_BY_ID 4 | 5 | MODULE = 'template_example.py' 6 | 7 | print('%s: preparing to deploy a template...' % MODULE) 8 | 9 | dnac = Dnac() 10 | 11 | template = Template(dnac, 'Set VLAN') 12 | 13 | print('%s: setting the target device...' % MODULE) 14 | 15 | dnac.api['Set VLAN'].targetId = '84e4b133-2668-4705-8163-5694c84e78fb' 16 | dnac.api['Set VLAN'].targetType = TARGET_BY_ID 17 | 18 | print('%s: setting the template\'s parameters...' % MODULE) 19 | 20 | dnac.api['Set VLAN'].set_param('interface', 'g1/0/8') 21 | dnac.api['Set VLAN'].set_param('description', 'Provisioned by %s' % MODULE) 22 | dnac.api['Set VLAN'].set_param('vlan', 10) 23 | 24 | print('%s: deploying the template...' % MODULE) 25 | 26 | dnac.api['Set VLAN'].deploy_sync() 27 | 28 | print('%s: deploy results: %s' % (MODULE, dnac.api['Set VLAN'].deployment.results)) 29 | 30 | print() 31 | -------------------------------------------------------------------------------- /examples/template_replicator/dnac_clusters.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "denlab-en-dnac.cisco.com", 4 | "ip": "", 5 | "version": "1.3.1.4", 6 | "port": 443, 7 | "user": "admin", 8 | "passwd": "C!sco123", 9 | "content_type": "application/json" 10 | }, 11 | { 12 | "name": "", 13 | "ip": "173.36.255.155", 14 | "version": "1.3.1.4", 15 | "port": 443, 16 | "user": "admin", 17 | "passwd": "c!sco123", 18 | "content_type": "application/json" 19 | } 20 | ] 21 | -------------------------------------------------------------------------------- /examples/template_replicator/views/replicate_projects.tpl: -------------------------------------------------------------------------------- 1 | 2 |
4 | % for result in results:
5 | {{result}}
6 | % end
7 |
8 |
4 | % for result in results:
5 | {{result}}
6 | % end
7 |
8 |
4 | % for result in results:
5 | {{result}}
6 | % end
7 |
8 |
5 |
8 | Source Cluster 9 | 18 | |
19 |
20 | Target Cluster 21 | 30 | |
31 |
34 |
4 |
38 | 43 | -------------------------------------------------------------------------------- /examples/template_replicator/views/select_templates.tpl: -------------------------------------------------------------------------------- 1 | % NO_TEMPLATES = [] 2 | % NO_PROJECTS = {} 3 | 4 |
6 | % for missing in missing_target_projects:
7 | {{missing}}
8 | % end
9 |
10 | % if projects != NO_PROJECTS: 11 |
54 | % end 55 |