Best Python code snippet using fMBT_python
ixia_nto.py
Source:ixia_nto.py
...72 handle = open(self.logFile, 'a') if self.logFile else sys.stdout73 handle.write(message)74 if handle is not sys.stdout:75 handle.close()76 def _callServer(self, HTTPMethod, URL, argsAPI=None, decode=True):77 """ Call server method HTTPMethod with error handling78 and returns the response. """79 response = None80 if self.debug:81 self._log("Sending a message to the server with parameters:\n")82 self._log(" HTTPMethod=%s\n" % HTTPMethod)83 self._log(" URL=%s\n" % URL)84 self._log(" argsAPI=%s\n" % argsAPI)85 argsAPI = json.dumps(argsAPI)86 response = self.connection.urlopen(HTTPMethod, URL, body=argsAPI, headers=self.token_headers)87 if self.debug:88 self._log("Response:\n")89 self._log(" Status=%s\n" % response.status)90 self._log(" Reason=%s\n" % response.reason)91 self._log(" Headers=%s\n" % response.headers)92 self._log(" Data=%s\n" % response.data)93 self._log(" decode=%s\n" % decode)94 data = response.data95 if decode:96 data = json.loads(data.decode('ascii'))97 self._validate_response_data(data)98 return data99 def _validate_response_data(self, data):100 if isinstance(data, dict):101 code = data.get("code")102 if code:103 descr = data.get("description", "Error occured")104 if code in [400, 403, 404, 500, 501, 503, 504]:105 raise NtoException("Status code {}, {}".format(code, descr))106 elif code == 401:107 raise NtoAuthException("Status code {}, {}".format(code, descr))108 return data109 def setDebug(self, debug=False):110 """ Turn on/off debug messages """111 self.debug = debug112 ###################################################113 # Actions114 ###################################################115 def authenticate(self):116 """ authenticate :117 Athenticate with the NTO using username and password.118 119 Sample usage:120 >>> nto.authenticate()121 """122 response = self.connection.urlopen('GET', '/api/auth', headers=self.password_headers)123 if self.debug:124 self._log("Status=%s" % response.status)125 self._log("Reason=%s" % response.reason)126 self._log("Headers=%s" % response.headers)127 self._log("Data=%s" % response.data)128 self.token_headers = {'Authentication': response.headers['x-auth-token'], 'Content-type': 'application/json'}129 def addAggregationSwitch(self):130 """ addAggregationSwitch :131 Adds a new Aggregation Switch to a Switch Cluster.132 133 Sample usage:134 """135 return self._callServer('POST', '/api/actions/add_aggregation_switch', None)136 def certificateManagement(self, argsAPI):137 """ certificateManagement :138 Allows Syslog and TLS/HTTPS certificates to be uploaded and deleted. Basic139 information can also be viewed for certificates installed on the system.140 141 Sample usage:142 >>> nto.certificateManagement({'action': 'VIEW', 'certificate_use': 'DEFAULT_TLS_HTTPS'})143 {u'authentication': [{u'valid_from': u'May 28, 2015 10:06:25 AM GMT', u'sha1_fingerprint': u'D3:75:74:30:D7:D8:50:FE:73:2F:10:E3:62:59:1B:EF:83:24:44:58', u'signature_algorithm': u'SHA256WITHRSA', u'valid_to': u'May 25, 2025 10:06:25 AM GMT', u'version': u'3', u'signature': u'12:B5:F1:75:7B:26:86:B2:C7:CE:A8:CE:74:CC:E8:82:8A:A3:45:45:AB:D3:DF:35:96:6A:50:61:F7:70:32:51:0A:03:5E:D1:14:1E:19:8E:ED:1A:E0:71:6E:CD:79:3C:67:70:F1:66:73:6C:1E:4F:97:97:94:79:25:D9:16:9C:B5:C7:E1:84:2A:A4:D6:FE:74:E7:E1:B5:B7:E0:32:0F:12:EA:A0:9C:62:75:D8:70:63:1B:C2:04:67:B9:33:5B:FE:9F:73:20:8B:AF:92:EA:6E:1A:61:B7:79:2A:AF:9E:50:EF:7D:7D:CE:DD:55:BD:20:E3:D7:C3:49:EB:A1:7D:B7:C8:89:43:19:13:59:4D:B6:2F:B9:22:8C:06:5C:4D:BB:8C:03:5B:45:B2:6D:DC:B5:4A:80:9A:14:32:2B:44:9D:CF:83:D8:E8:81:B8:77:94:2D:71:D0:54:ED:47:53:45:06:28:39:86:7D:EF:9D:3D:DC:BD:06:E0:BC:EF:62:AA:85:02:20:D7:E6:61:4E:12:81:04:9E:42:AA:40:18:4F:1B:3D:41:62:9B:E4:36:A9:F8:39:5F:60:2B:C1:83:5D:CF:FE:9F:3B:C0:FD:62:A7:D6:47:9E:C4:73:02:CA:C6:86:F5:7B:52:5B:E8:58:3B:23:57:3F:EE:2C:09:E2', u'serial_number': u'1165506059 (4578360b)', u'md5_fingerprint': u'57:7E:03:2E:2B:67:AA:E7:75:44:AA:21:5C:8F:BE:A1', u'subject': u'CN=Ixia, OU=Ixia, O=Ixia, L=Calabasas, ST=California, C=US', u'issuer': u'CN=Ixia, OU=Ixia, O=Ixia, L=Calabasas, ST=California, C=US'}]}144 """145 return self._callServer('POST', '/api/actions/certificates', argsAPI)146 def changeRole(self):147 """ changeRole :148 This command changes role between supervisor and independent.149 150 Sample usage:151 >>> nto.changeRole()152 """153 argsAPI = {}154 return self._callServer('POST', '/api/actions/change_role', argsAPI)155 def changePortSpeed(self, argsAPI):156 """ changePortSpeed :157 Changes the speed configuration of port.158 Sample usage:159 >>> nto.changePortSpeed({'port_list': [64], 'qsfp28_port_mode': 'MODE_QSFP'})160 '{}'161 """162 return self._callServer('POST', '/api/actions/change_speed_configuration', argsAPI, False)163 def clearAggregationSwitch(self):164 """ clearAggregationSwitch :165 Clears the configuration of an aggregation switch.166 167 Sample usage:168 """169 return self._callServer('POST', '/api/actions/clear_aggregation_switch', None)170 def changeQsfp28PortMode(self, argsAPI):171 """ changeQsfp28PortMode :172 Changes the QSFP mode of a QSFP28 port.173 174 Sample usage:175 """176 return self._callServer('POST', '/api/actions/change_qsfp28_port_mode', argsAPI, False)177 def changePortAggregationMode(self, argsAPI):178 """ changePortAggregationMode :179 Agregates four 10G ports into one 40G port and backward.180 181 Sample usage:182 """183 return self._callServer('POST', '/api/actions/change_port_aggregation_mode', argsAPI, False)184 def clearConfig(self):185 """ clearConfig :186 Clear the configuration by deleting all filters, regular users, groups,187 filter templates, filter template collections, port groups, and custom188 icons and by setting all ports to default values.189 Sample usage:190 >>> nto.clearConfig()191 {u'message': u'Configuration cleared.'}192 """193 argsAPI = {}194 return self._callServer('POST', '/api/actions/clear_config', argsAPI)195 def clearFiltersAndPorts(self):196 """ clearFiltersAndPorts :197 This command deletes all filters and port groups and sets all ports to198 default values.199 Sample usage:200 >>> nto.clearFiltersAndPorts()201 {u'message': u'Filters and ports cleared.'}202 """203 argsAPI = {}204 return self._callServer('POST', '/api/actions/clear_filters_and_ports', argsAPI)205 def clearSystem(self):206 """ clearSystem :207 This command clears the system and restores it to a default state, including208 resetting the admin account to default values. The license currently209 installed will not be removed.210 211 Sample usage:212 >>> nto.clearSystem()213 {u'message': u'System restored to default state.'}214 """215 argsAPI = {}216 return self._callServer('POST', '/api/actions/clear_system', argsAPI)217 def enableFipsServerEncryption(self):218 """ enableFipsServerEncryption :219 This commands causes FIPS encryption to be enabled on the server.220 221 Sample usage:222 *** TO BE TESTED ***223 >>> nto.enableFipsServerEncryption()224 """225 argsAPI = {}226 return self._callServer('POST', '/api/actions/enable_fips_server_encryption', argsAPI)227 def exportConfig(self, argsAPI):228 """ exportConfig :229 Return configuration settings from an NTO to a file.230 Sample usage:231 nto.exportConfig({'boundary' : 'INCLUDE', 'description' : 'SNMP Config', 'export_type' : 'CUSTOM', 'file_name' : '/Users/fmota/Desktop/snmp+user.ata', 'user': None, 'system' : 'snmp_config'})232 """233 file_name = ''234 if 'file_name' in argsAPI:235 file_name = argsAPI['file_name']236 file = self._callServer('POST', '/api/actions/export', argsAPI, False)237 f = open(file_name, 'wb')238 f.write(file)239 f.close()240 def exportKeyGenLicense(self, argsAPI):241 """ exportKeyGenLicense :242 Export the KeyGen license details to a json file that can be used243 on the migration portal to obtain a new style license for an NTO244 or an union.245 246 Sample usage:247 >>> nto.exportKeyGenLicense({'file_name': 'mylicense'})248 """249 file_name = ''250 if 'file_name' in argsAPI:251 file_name = argsAPI['file_name']252 file = self._callServer('POST', '/api/actions/export_keygen_license_to_json', argsAPI, False)253 f = open(file_name, 'wb')254 f.write(file)255 f.close()256 def fipsServerEncryptionStatus(self):257 """ fipsServerEncryptionStatus :258 This commands causes FIPS encryption to be enabled on the server.259 Sample usage:260 *** TO BE TESTED ***261 >>> nto.fipsServerEncryptionStatus()262 """263 argsAPI = {}264 return self._callServer('POST', '/api/actions/fips_server_encryption_status', argsAPI)265 def factoryReset(self):266 """ factoryReset :267 This command clears the system and restores it to a factory default268 state, including resetting the admin account to default values. The269 license currently installed will also be removed.270 271 Sample usage:272 >>> nto.factoryReset()273 """274 argsAPI = {}275 return self._callServer('POST', '/api/actions/factory_reset', argsAPI)276 def generateCsr(self, argsAPI):277 """ generateCsr :278 Allows Syslog and TLS/HTTPS certificates to be uploaded and deleted. Basic279 information can also be viewed for certificates installed on the system.280 281 Sample usage:282 >>> nto.generateCsr({'csr_use' : 'SYSLOG', 'tls_cert_request_info' : {'city' : 'Austin', 'common_name' : 'Test API', 'country' : 'US', 'organization' : 'Ixia', 'organization_unit' : 'NVS', 'state' : 'TX', 'subject_alt_name' : 'Anue'}})283 {u'csr': u'-----BEGIN CERTIFICATE REQUEST-----MIIC5zCCAc8CAQAwWzELMAkGA1UECBMCVFgxDzANBgNVBAcTBkF1c3RpbjELMAkGA1UEBhMCVVMxDDAKBgNVBAsTA05WUzENMAsGA1UEChMESXhpYTERMA8GA1UEAxMIVGVzdCBBUEkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4RNOnSPTRamGkAwj/otEgzAFYIEXlpsO4OS16P49l3c0n5ShDs0uo2pd4a0Qe4Wvh/KX4L1oZbxS/2YNJgNlLiRkHo5K62ZYYskfNGXPBYfkkRDLk76SrhgHyoGSEy8h6OdeE2QpfgsD/XLQVoFQ3dVemSwo76bE3Vap333fJmvtNJNgItkKqKBW3zF1doSWJwEHDwwhG9/KSfFBHf/qE51LRj2iybZQE4ijZGHv0I7CtSF20166sH75EhsoK8/vs1RT6LpyuEM9JKoRzmvE1ufk3nHtlvF3UniUluUCubXfldaEROIeBvYfoWZGGuyzAN01ZbxZ+/K2ENokpVKPbAgMBAAGgRzBFBgkqhkiG9w0BCQ4xODA2MA8GA1UdEQQIMAaCBEFudWUwDgYDVR0PAQH/BAQDAgUgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQAfVnwTv1t56YWU2W5+Fjlc9nuTL7eAoKqkioTJ1CuAINLybbHYUVXVfpBahfjj7g6ZmiWZ383SK7ImuPfHE7kt/eRDna+/+HUQ22799HQmyLcxCkYZVSH8gWkTNbUIhgh4AFMwt83zWu324P+qNkh5u0sckPTfNzry3Mxz2QzmM5sP+oU8/RCt04iYzz5KSu+tzHWJ9FOGLQqQ73Ausz0smTDFBlVLs8VCifHVc2QmSbIofHVPUOUEjWo+FFb6WK6/7NjgE4DM9rVDV7eW9WXZgos6WnXRVMIpedeibh31iM/sc63F0tQHXt696kfO19LBc6FLMKLCvVtkGfSnq5u9-----END CERTIFICATE REQUEST-----'}284 """285 return self._callServer('POST', '/api/actions/generate_csr', argsAPI)286 def getAvailableFilterCriteria(self, argsAPI):287 """ getAvailableFilterCriteria :288 Return a list of filter criteria which can be used given an already289 present set of filter criteria.290 291 Sample usage:292 >>> nto.getAvailableFilterCriteria({'filter_object_type': 'FILTER'})293 []294 """295 return self._callServer('POST', '/api/actions/get_available_filter_criteria', argsAPI)296 def getLoginInfo(self):297 """ getLoginInfo :298 Return info helpful for login.299 Sample usage:300 """301 return self._callServer('POST', '/api/actions/get_login_info', None)302 def getFabricPorts(self, argsAPI):303 """ getFabricPorts :304 Return fabric ports information for one or more members. This305 information can be used as input to the update_fabric_ports action.306 307 Sample usage:308 >>> nto.getFabricPorts()309 """310 return self._callServer('POST', '/api/actions/get_fabric_ports', argsAPI)311 def getMemoryMeters(self):312 """ getMemoryMeters :313 Return the filter memory meters showing memory allocation and percentage used.314 315 Sample usage:316 >>> nto.getMemoryMeters()317 [{u'unit_name': u'LC1', u'memory_meters': [{u'custom_memory_slice_count': 0, u'meters': [{u'alloc_pcnt': 89, u'avail_pcnt': 100, u'meter_name': u'FILTER_ETHERTYPE_VLAN_L3_L4'}, {u'alloc_pcnt': 89, u'avail_pcnt': 100, u'meter_name': u'FILTER_L2_L3_L4'}], u'memory_type': u'DYNAMIC_FILTER_NON_IP'}, {u'custom_memory_slice_count': 0, u'meters': [{u'alloc_pcnt': 50, u'avail_pcnt': 100, u'meter_name': u'DYNAMIC_SIP_IPV4'}, {u'alloc_pcnt': 50, u'avail_pcnt': 100, u'meter_name': u'DYNAMIC_DIP'}], u'memory_type': u'DYNAMIC_FILTER_IP'}, {u'custom_memory_slice_count': 0, u'meters': [{u'alloc_pcnt': 100, u'avail_pcnt': 100, u'meter_name': u'NETWORK_PORT_L2_L3_IPV4'}], u'memory_type': u'NETWORK_PORT_FILTER'}, {u'custom_memory_slice_count': 0, u'meters': [{u'alloc_pcnt': 100, u'avail_pcnt': 100, u'meter_name': u'TOOL_PORT_L2_L3_IPV4'}], u'memory_type': u'TOOL_PORT_FILTER'}]}, ...318 """319 argsAPI = {}320 return self._callServer('POST', '/api/actions/get_memory_meters', argsAPI)321 def getTranceiverInfo(self):322 """ getTranceiverInfo :323 Return the tranceivor information.324 325 Sample usage:326 >>> nto.getTranceiverInfo()327 [{u'line_card_number': 1, u'line_card_tranceiver_info': u"<h1>Demo sample</h1><br/><br/><br/><table border='2'><tr><td bgcolor='#6495ED'><font size='+1' color='black'><b>Port: P1-01 (demo)</b></font><br/><br/><table border='1'><tr><th bgcolor='silver'>Hardware Info</th><th bgcolor='silver'>Vendor Name</th><th bgcolor='silver'>OUI</th><th bgcolor='silver'>Part Number</th><th bgcolor='silver'>Revision</th><th bgcolor='silver'>Serial Number</th><th bgcolor='silver'>Date Code</th><th bgcolor='silver'>Lot Code</th></tr><tr><th bgcolor='white'>SFP</th><th bgcolor='white'>ANUE SYSTEMS</th><th bgcolor='white'>009065</th><th bgcolor='white'>200-06-0003</th><th bgcolor=328 """329 argsAPI = {}330 return self._callServer('POST', '/api/actions/get_tranceiver_info', argsAPI)331 def getObjectType(self, argsAPI):332 """ getObjectType :333 Return the object type for an internal id.334 Sample usage:335 >>> nto.getObjectType({'id':238})336 {u'object_type': u'PORT'}337 """338 return self._callServer('POST', '/api/actions/get_object_type', argsAPI)339 def getProperties(self, argsAPI):340 """ getProperties :341 Return a list of the properties that are available for a particular type of object.342 Sample usage:343 >>> nto.getProperties({'object_type' : 'monitor'})344 {u'properties': [u'actions', u'created', u'description', u'history', u'id', u'mod_count', u'name', u'trigger']}345 """346 return self._callServer('POST', '/api/actions/get_props', argsAPI)347 def getPropertyValues(self, argsAPI):348 """ getPropertyValues :349 Return a list of the properties that are available for a particular type of object.350 Sample usage:351 >>> nto.getPropertyValues({'object_type': 'port', 'prop_name': 'force_link_up'})352 {u'value': [u'DISABLED', u'ENABLED', u'MIXED', u'NOT_SUPPORTED']}353 """354 return self._callServer('POST', '/api/actions/get_values', argsAPI)355 def importConfig(self, argsAPI):356 """ import_cfg :357 Copy configuration settings from a file to an NTO.358 Sample usage:359 >>> nto.importConfig({'boundary': 'INCLUDE', 'import_type': 'CUSTOM', 'file_name': '/Users/fmota/Desktop/snmp+user.ata', 'system' : 'snmp_config'})360 '{"message": "Configuration imported from /Users/fmota/Desktop/snmp+user.ata."}'361 """362 file_name = ''363 if 'file_name' in argsAPI:364 file_name = argsAPI['file_name']365 del argsAPI['file_name']366 boundary = "-----WebKitFormBoundary" + str(int(time.time())) + str(os.getpid())367 buffer = bytearray()368 # Set param369 buffer.extend(b'--' + bytearray(boundary, 'ascii') + b'\r\n')370 buffer.extend(b'Content-Disposition: form-data; name="param"\r\n')371 buffer.extend(b'Content-Type: application/json\r\n')372 buffer.extend(b'\r\n')373 buffer.extend(bytearray(json.dumps(argsAPI), 'ascii'))374 buffer.extend(b'\r\n')375 # Set creative contents part.376 buffer.extend(b'--' + bytearray(boundary, 'ascii') + b'\r\n')377 buffer.extend(378 b'Content-Disposition: form-data; name="file"; filename=' + bytearray(file_name, 'ascii') + b'\r\n')379 buffer.extend(b'Content-Type: application/octet-stream\r\n')380 buffer.extend(b'\r\n')381 # TODO: catch errors with opening file.382 buffer.extend(open(file_name, 'rb').read())383 buffer.extend(b'\r\n')384 buffer.extend(b'--' + bytearray(boundary, 'ascii') + b'--\r\n')385 buffer.extend(b'\r\n')386 hdrs = {'Authentication': self.token, 'Content-type': 'multipart/form-data; boundary=' + boundary}387 response = self.connection.urlopen('POST', '/api/actions/import', body=buffer, headers=hdrs)388 # self._log (response.status, response.reason)389 data = response.data390 return data391 def installLicense(self, argsAPI):392 """ installLicense :393 This command installs a license file on a NTO, a union, or a member.394 395 Sample usage:396 >>> nto.installLicense({'file_name': '/Users/fmota/Desktop/IxiaLicenseA_17_Fred_20150826_1.txt'})397 '{"message": "License installed from /Users/fmota/Desktop/IxiaLicenseA_17_Fred_20150826_1.txt."}'398 """399 file_name = ''400 if 'file_name' in argsAPI:401 file_name = argsAPI['file_name']402 del argsAPI['file_name']403 boundary = "-----WebKitFormBoundary" + str(int(time.time())) + str(os.getpid())404 buffer = bytearray()405 # Set param406 if len(argsAPI.keys()) > 0:407 buffer.extend(b'--' + bytearray(boundary, 'ascii') + b'\r\n')408 buffer.extend(b'Content-Disposition: form-data; name="param"\r\n')409 buffer.extend(b'Content-Type: application/json\r\n')410 buffer.extend(b'\r\n')411 # buffer.extend(json.dumps({'action_target' : target}))412 buffer.extend(json.dumps(argsAPI))413 buffer.extend(b'\r\n')414 # Set creative contents part.415 buffer.extend(b'--' + bytearray(boundary, 'ascii') + b'\r\n')416 buffer.extend(417 b'Content-Disposition: form-data; name="file"; filename=' + bytearray(file_name, 'ascii') + b'\r\n')418 buffer.extend(b'Content-Type: application/octet-stream\r\n')419 buffer.extend(b'\r\n')420 # TODO: catch errors with opening file.421 buffer.extend(open(file_name, 'rb').read())422 buffer.extend(b'\r\n')423 buffer.extend(b'--' + bytearray(boundary, 'ascii') + b'--\r\n')424 buffer.extend(b'\r\n')425 hdrs = {'Authentication': self.token, 'Content-type': 'multipart/form-data; boundary=' + boundary}426 response = self.connection.urlopen('POST', '/api/actions/install_license', body=buffer, headers=hdrs)427 # self._log (response.status, response.reason)428 data = response.data429 return data430 def installLicense_old(self, argsAPI):431 """ installLicense :432 This command installs a license file on a NTO, a union, or a member.433 Sample usage:434 >>> nto.installLicense({'file_name': '/Users/fmota/Desktop/IxiaLicenseA_17_Fred_20150826_1.txt'})435 '{"message": "License installed from /Users/fmota/Desktop/IxiaLicenseA_17_Fred_20150826_1.txt."}'436 """437 file_name = ''438 if 'file_name' in argsAPI:439 file_name = argsAPI['file_name']440 del argsAPI['file_name']441 boundary = "-----WebKitFormBoundary" + str(int(time.time())) + str(os.getpid())442 parts = []443 # Set param444 if len(argsAPI.keys()) > 0:445 parts.append('--' + boundary)446 parts.append('Content-Disposition: form-data; name="param"')447 parts.append('Content-Type: application/json')448 parts.append('')449 # parts.append(json.dumps({'action_target' : target}))450 parts.append(json.dumps(argsAPI))451 # Set creative contents part.452 parts.append('--' + boundary)453 parts.append('Content-Disposition: form-data; name="file"; filename=' + file_name)454 parts.append('Content-Type: application/octet-stream')455 parts.append('')456 # TODO: catch errors with opening file.457 parts.append(open(file_name, 'r').read())458 parts.append('--' + boundary + '--')459 parts.append('')460 content = '\r\n'.join(parts)461 hdrs = {'Authentication': self.token, 'Content-type': 'multipart/form-data; boundary=' + boundary}462 response = self.connection.urlopen('POST', '/api/actions/install_license', body=content, headers=hdrs)463 # self._log (response.status, response.reason)464 data = response.data465 return data466 def installSoftware(self, argsAPI):467 """ installSoftware :468 This command installs a software upgrade file on an NTO. When installing469 software on a supervisor in a union, all members in the union will be470 upgraded to the same software level automatically.471 472 Sample usage:473 >>> nto.installSoftware({'file_name': '/Users/fmota/Desktop/NVOS-4.3.1.1-52xx-141844-20150722-174244.zip'})474 '{"message": "Software installation complete. The system will be restarted. Visit the 5288 launch page in your browser to obtain the updated client software."}'475 """476 file_name = ''477 if 'file_name' in argsAPI:478 file_name = argsAPI['file_name']479 boundary = "-----WebKitFormBoundary" + str(int(time.time())) + str(os.getpid())480 buffer = bytearray()481 # Set creative contents part.482 buffer.extend(b'--' + bytearray(boundary, 'ascii') + b'\r\n')483 buffer.extend(484 b'Content-Disposition: form-data; name="file"; filename=' + bytearray(file_name, 'ascii') + b'\r\n')485 buffer.extend(b'Content-Type: application/octet-stream\r\n')486 buffer.extend(b'\r\n')487 # TODO: catch errors with opening file.488 buffer.extend(open(file_name, 'rb').read())489 buffer.extend(b'\r\n')490 buffer.extend(b'--' + bytearray(boundary, 'ascii') + b'--\r\n')491 buffer.extend(b'\r\n')492 hdrs = {'Authentication': self.token, 'Content-type': 'multipart/form-data; boundary=' + boundary}493 response = self.connection.urlopen('POST', '/api/actions/install_software', body=buffer, headers=hdrs)494 # self._log (response.status, response.reason)495 data = response.data496 return data497 def powerDown(self, argsAPI={}):498 """ powerDown :499 This command safely shuts down an NTO, a union or a member.500 Sample usage:501 >>> nto.powerDown()502 {u'message': u'System shutdown requested.'}503 """504 return self._callServer('POST', '/api/actions/power_down', argsAPI)505 def pullConfigFromHaPeer(self):506 """ pullConfigFromHaPeer :507 Pulls the configuration from the HA peer machine.508 Sample usage:509 *** TO BE TESTED ***510 >>> nto.pullConfigFromHaPeer()511 """512 argsAPI = {}513 return self._callServer('POST', '/api/actions/pull_config_from_ha_peer', argsAPI)514 def pushConfigToHaPeer(self):515 """ pushConfigToHaPeer :516 Pushes the local configuration to the HA peer machine.517 Sample usage:518 *** TO BE TESTED ***519 >>> nto.pushConfigToHaPeer()520 """521 argsAPI = {}522 return self._callServer('POST', '/api/actions/push_config_to_ha_peer', argsAPI)523 def removeLicense(self):524 """ removeLicense :525 This command will remove the license and power down the NTO.526 527 Sample usage:528 >>> nto.removeLicense()529 """530 argsAPI = {}531 return self._callServer('POST', '/api/actions/remove_license', argsAPI)532 def removeLineCard(self, argsAPI):533 """ removeLineCard :534 This command will remove the line card based on the given line card id.535 Sample usage:536 >>> nto.removeLineCard({'line_card_id': 1})537 {u'message': u'System restart requested.'}538 """539 return self._callServer('POST', '/api/actions/remove_line_card', argsAPI)540 def restart(self, argsAPI={}):541 """ restart :542 This command safely restarts an NTO, a union, or a member.543 Sample usage:544 >>> nto.restart()545 {u'message': u'System restart requested.'}546 """547 return self._callServer('POST', '/api/actions/restart', argsAPI)548 def revertSoftware(self):549 """ revertSoftware :550 This command revert software to it's previous version.551 552 Sample usage:553 >>> nto.revertSoftware()554 {u'message': u'Software revert requested. The system will be restarted. Visit the 7300 launch page in your browser to obtain the reverted client software.'}555 """556 argsAPI = {}557 return self._callServer('POST', '/api/actions/revert_software', argsAPI)558 def saveLogs(self, argsAPI):559 """ saveLogs :560 Save the current system log files for subsequent delivery to Anue Support.561 Sample usage:562 >>> nto.saveLogs({'file_name': '/Users/fmota/Desktop/NTO-log.zip'})563 """564 file_name = ''565 if 'file_name' in argsAPI:566 file_name = argsAPI['file_name']567 file = self._callServer('POST', '/api/actions/save_logs', argsAPI, False)568 f = open(file_name, 'wb')569 f.write(file)570 f.close()571 def setHaSyncPort(self):572 """ setHaSyncPort :573 Set the HA sync port.574 575 Sample usage:576 *** TO BE TESTED ***577 >>> nto.setHaSyncPort()578 """579 argsAPI = {}580 return self._callServer('POST', '/api/actions/set_ha_sync_port', argsAPI)581 def setIpConfig(self, argsAPI):582 """ setIpConfig :583 Changes the IP configuration of a system.584 Sample usage:585 >>> nto.setIPConfig({'ipv4_address': '192.168.2.149', 'ipv4_enabled': True, 'ipv4_gateway': '192.168.2.2', 'ipv4_netmask': '255.255.255.0', 'ipv6_address': 'fe80::5daa:83ed:42f8:6c08%11', 'ipv6_enabled': False, 'ipv6_prefix_length': 64})586 {u'message': u'The new IP configuration has been submitted.'}587 """588 return self._callServer('POST', '/api/actions/set_ip_config', argsAPI)589 def swapPortLicenses(self, argsAPI):590 """ swapPortLicenses :591 Swaps port licenses.592 593 Sample usage:594 """595 return self._callServer('POST', '/api/actions/swap_port_licenses', argsAPI, False)596 def modifyFabricPorts(self, argsAPI):597 """ modifyFabricPorts :598 Changes the fabric ports configuration for the specified member switch.599 600 Sample usage:601 """602 return self._callServer('POST', '/api/actions/update_fabric_ports', argsAPI)603 ###################################################604 # Capture Resources605 ###################################################606 def getAllCaptures(self):607 """ getAllCaptures :608 Fetch a list containing the summaries for all the captures in the system.609 Sample usage:610 >>> nto.getAllCaptures()611 [{u'id': 546, u'name': u'L4-CAP'}]612 """613 return self._callServer('GET', '/api/capture_resources')614 def getCapture(self, resource):615 """ getCapture :616 Fetch the properties of a capture object.617 Sample usage:618 >>> nto.getCapture('177')619 {u'trailer_stripping_mode': u'USE_LOCAL_TIME', u'capture_count_unit': u'PACKETS', u'id': 177, u'has_dropped_packets': False, u'max_buffer_capacity': 14680063, u'modify_access_settings': {u'policy': u'ALLOW_ALL', u'groups': []}, u'connect_disconnect_access_settings': {u'policy': u'ALLOW_ALL', u'groups': []}, u'status': u'IDLE_WITH_DATA', u'fill_to_trigger_position': False, u'description': None, u'trigger_position': 25, u'resource_status': u'READY', u'license_status': u'NOT_PRESENT', u'trailer_stripping_enabled': False, u'buffer_size': 200, u'trigger_criteria': {u'logical_operation': u'AND'}, u'name': u'L1-CAP', u'buffer_type': u'LINEAR', u'capture_source': 307, u'lineboard_id': 175, u'default_name': u'L1-CAP', u'trigger_mode': u'MANUAL', u'mod_count': 3, u'history': [{u'type': u'MODIFY', u'time': 1442009546427, u'caused_by': u'admin', u'details': None, u'props': [u'CAPTURE_SOURCE', u'BUFFER_SIZE']}]}620 """621 return self._callServer('GET', '/api/capture_resources/' + resource)622 def deleteCaptureFile(self, resource, argsAPI):623 """ deleteCaptureFile :624 Deletes a capture file from a capture resource.625 Sample usage:626 >>> nto.deleteFileCapture('546', {'file_name': 'File 1.pcap'})627 ''628 """629 return self._callServer('DELETE', '/api/capture_resources/' + resource + '/delete_file ', argsAPI, False)630 def disableCapture(self, resource):631 """ disableCapture :632 Disables a capture resource by disconnecting the attached filter.633 Sample usage:634 >>> nto.disableCapture('L1-CAP')635 ''636 """637 argsAPI = {}638 return self._callServer('PUT', '/api/capture_resources/' + resource + '/disable', argsAPI, False)639 def downloadCaptureFile(self, resource, argsAPI, local_file_name=None):640 """ downloadCaptureFile :641 Downloads a capture file of capture resource.642 Sample usage:643 >>> nto.downloadFileCapture('L1-CAP', {'file_name': 'Suspicious Netflow export.pcap'})644 """645 file_name = ''646 if 'file_name' in argsAPI:647 file_name = argsAPI['file_name']648 file = self._callServer('POST', '/api/capture_resources/' + resource + '/download_file', argsAPI, False)649 if local_file_name is None:650 local_file_name = file_name651 f = open(local_file_name, 'wb')652 f.write(file)653 f.close()654 def enableCapture(self, resource, argsAPI):655 """ enableCapture :656 Enables a capture by attaching a filter to it.657 Sample usage:658 >>> nto.enableCapture('546', {'filter_id': '524'})659 ''660 """661 return self._callServer('PUT', '/api/capture_resources/' + resource + '/enable', argsAPI, False)662 def ftpTransferCapture(self, resource, argsAPI):663 """ ftpTransferCapture :664 Transfers via FTP a capture file or the buffer of a capture resource.665 Sample usage:666 >>> nto.ftpTransferCapture('317', {'address': '10.218.6.43', 'file_name': '150604_085131.pcap', 'password': '****', 'range_type': 'ALL_PACKETS', 'remote_file_name': 'fred-api.pcap', 'user': 'fredmota', 'port': 21})667 '{\n "id": 2,\n "progress": 0,\n "state": "PENDING"\n}'668 """669 return self._callServer('POST', '/api/capture_resources/' + resource + '/ftp_file', argsAPI, False)670 def getTriggerPacketCapture(self, resource):671 """ getTriggerPacketCapture :672 Gets the number of the packet that triggered the capture.673 Sample usage:674 >>> nto1.getTriggerPacketCapture('546')675 {u'triggerPacketNumber': 1025}676 """677 return self._callServer('GET', '/api/capture_resources/' + resource + '/trigger_packet')678 def listCaptureFiles(self, resource):679 """ listCaptureFiles :680 Fetch a list containing the summaries for all the captures in the system.681 Sample usage:682 >>> nto.listFilesCapture('546')683 [{u'access_settings': {u'policy': u'REQUIRE_MEMBER', u'groups': [u'group1', u'group2']}, u'description': u'Capture file description', u'capture_date': 1440119146145, u'name': u'File 2.pcap', u'packet_count': 32, u'duration': 12, u'size': 262144, u'access_policy_id': u'7300-demodemo'}]684 """685 argsAPI = {}686 return self._callServer('GET', '/api/capture_resources/' + resource + '/files', argsAPI)687 def scpTransferCapture(self, resource, argsAPI):688 """ scpTransferCapture :689 Transfers via SCP a capture file or the buffer of a capture resource.690 Sample usage:691 >>> nto.scpTransferCapture('317', {'address': '10.218.30.1', 'file_name': '150604_085131.pcap', 'password': 'Anue', 'port': 22, 'range_type': 'ALL_PACKETS', 'remote_file_name': 'fred-api.pcap', 'user': 'support'})692 '{\n "id": 3,\n "progress": 0,\n "state": "PENDING"\n}'693 """694 return self._callServer('POST', '/api/capture_resources/' + resource + '/scp_file', argsAPI, False)695 def saveBufferCapture(self, resource, argsAPI):696 """ saveBufferCapture :697 Saves the buffer of a capture resource to a new capture file.698 Sample usage:699 >>> nto.saveBufferCapture('L1-CAP', {'file_name': 'wep_api_test.pcap', 'description': 'Web API Saved File', 'range' : '1-10', 'range_type': 'RANGE'})700 {u'progress': 0, u'state': u'PENDING', u'id': 1}701 """702 return self._callServer('POST', '/api/capture_resources/' + resource + '/save_buffer', argsAPI)703 def searchCapture(self, argsAPI):704 """ searchCapture :705 Search for a specific capture in the system by certain properties.706 Sample usage:707 >>> nto.searchCapture({'status': 'IDLE_WITH_DATA'})708 [{u'id': 177, u'name': u'L1-CAP'}]709 """710 return self._callServer('POST', '/api/capture_resources/search', argsAPI)711 def startCapture(self, resource):712 """ startCapture :713 Starts a capture resource to capture packets via the attached filter.714 Sample usage:715 >>> nto.startCapture('L1-CAP')716 ''717 """718 argsAPI = {}719 return self._callServer('PUT', '/api/capture_resources/' + resource + '/start', argsAPI, False)720 def stopCapture(self, resource):721 """ stopCapture :722 Stops a capture resource to capture packets via the attached filter.723 Sample usage:724 >>> nto.stopCapture('L1-CAP')725 ''726 """727 argsAPI = {}728 return self._callServer('PUT', '/api/capture_resources/' + resource + '/stop', argsAPI, False)729 def modifyCapture(self, resource, argsAPI):730 """ modifyCapture :731 Update the properties of an existing capture resource.732 Sample usage:733 >>> nto.modifyCapture('L1-CAP', {'buffer_size': 100})734 ''735 """736 return self._callServer('PUT', '/api/capture_resources/' + resource, argsAPI, False)737 ###################################################738 # ATIP Resources739 ###################################################740 def getAllAtips(self):741 """ getAllAtips :742 Fetch a list containing the summaries for all the ATIP resources in the system.743 Sample usage:744 >>> nto.getAllAtips()745 [{u'id': 179, u'name': u'L2-ATIP'}]746 """747 return self._callServer('GET', '/api/atip_resources')748 def getAtip(self, resource):749 """ getCapture :750 Fetch the properties of an ATIP resource.751 Sample usage:752 >>> nto.getAtip('L2-ATIP')753 {u'fill_to_trigger_position': False, u'description': None, u'capture_source': 304, u'lineboard_id': 173, u'default_name': u'L2-ATIP', u'resource_status': u'READY', u'name': u'L2-ATIP', u'mod_count': 5, u'license_status': u'VALID', u'modify_access_settings': {u'policy': u'REQUIRE_ADMIN', u'groups': []}, u'id': 179, u'connect_disconnect_access_settings': {u'policy': u'REQUIRE_ADMIN', u'groups': []}, u'history': [{u'type': u'MODIFY', u'time': 1442009546622, u'caused_by': u'admin', u'details': None, u'props': [u'NETFLOW_ENABLED']}]}754 """755 return self._callServer('GET', '/api/atip_resources/' + resource)756 def disableAtip(self, resource):757 """ disableAtip :758 Disables an ATIP by disconnecting the attached filter.759 Sample usage:760 >>> nto.disableAtip('319')761 ''762 """763 argsAPI = {}764 return self._callServer('PUT', '/api/atip_resources/' + resource + '/disable', argsAPI, False)765 def enableAtip(self, resource, argsAPI):766 """ enableAtip :767 Enables a capture by attaching a filter to it.768 Sample usage:769 >>> nto.enableAtip('319', {'filter_id': 'F1'})770 ''771 """772 return self._callServer('PUT', '/api/atip_resources/' + resource + '/enable', argsAPI, False)773 def searchAtip(self, argsAPI):774 """ searchAtip :775 Search for a specific ATIP resource in the system by certain properties.776 Sample usage:777 >>> nto.searchAtip({'resource_status': 'READY'})778 [{u'id': 179, u'name': u'L2-ATIP'}]779 """780 return self._callServer('POST', '/api/atip_resources/search', argsAPI)781 def modifyAtip(self, resource, argsAPI):782 """ modifyAtip:783 Update the properties of an existing ATIP resource.784 Sample usage:785 >>> nto.modifyAtip('L2-ATIP', {'description': 'ATIP at slot #2'})786 ''787 """788 return self._callServer('PUT', '/api/atip_resources/' + resource, argsAPI, False)789 ###################################################790 # Authentication791 ###################################################792 def logout(self):793 """ logout :794 This call is used to invalidate any token returned from other calls to the web API.795 796 Sample usage:797 >>> nto.logout()798 'User "admin" has logged out.'799 """800 argsAPI = {}801 return self._callServer('GET', '/api/auth/logout', argsAPI, False)802 ###################################################803 # Bypass connectors804 ###################################################805 def createBypass(self, argsAPI):806 """ createBypass :807 Create a new Inline Bypass Connector in the system.808 Sample usage:809 """810 return self._callServer('POST', '/api/bypass_connectors', argsAPI)811 def getBypass(self, bypass_id):812 """ getBypass :813 Fetch the properties of an Inline Bypass Connector.814 Sample usage:815 """816 return self._callServer('GET', '/api/bypass_connectors/' + bypass_id)817 def getAllBypasses(self):818 """ getAllBypasses :819 Fetch a list containing the summaries for all the Inline Bypass Connectors in the system.820 Sample usage:821 """822 return self._callServer('GET', '/api/bypass_connectors')823 def searchBypass(self, argsAPI):824 """ searchBypass :825 Search for a specific Inline Bypass Connector in the system by certain properties.826 Sample usage:827 """828 return self._callServer('POST', '/api/bypass_connectors/search', argsAPI)829 def modifyBypass(self, bypass_id, argsAPI):830 """ modifyBypass:831 Update the properties of an existing Inline Bypass Connector.832 Sample usage:833 >>> nto.modifyAtip('L2-ATIP', {'description': 'ATIP at slot #2'})834 ''835 """836 return self._callServer('PUT', '/api/bypass_connectors/' + bypass_id, argsAPI, False)837 ####################################838 # Control Tower Evolution839 ####################################840 # CTE Cluster841 def getCteCluster(self):842 """ getCteCluster :843 Retrieve the properties of the CTE cluster.844 Sample usage:845 """846 return self._callServer('GET', '/api/cte_cluster')847 def getCteResources(self):848 """ getCteCluster :849 Retrieve the properties of the CTE cluster.850 Sample usage:851 """852 return self._callServer('GET', '/api/cte_ae_resources')853 # def getCteCluster(self, argsAPI):854 # """ getCteCluster :855 # Retrieve the properties of the CTE cluster.856 #857 # Sample usage:858 # """859 # return self._callServer('POST', '/api/cte_cluster', argsAPI)860 # CTE Connections861 def createCteConnection(self, argsAPI):862 """ createCteConnection :863 Create a new CTE connection in the system.864 Sample usage:865 """866 return self._callServer('POST', '/api/cte_connections', argsAPI)867 def deleteCteConnection(self, cte_id):868 """ deleteCteConnection :869 Remove a CTE connection.870 Sample usage:871 """872 return self._callServer('DELETE', '/api/cte_connections/' + cte_id, None, False)873 def getCteConnection(self, cte_id):874 """ getCteConnection :875 Fetch the properties of a CTE connection.876 Sample usage:877 """878 return self._callServer('GET', '/api/cte_connections/' + cte_id)879 def getAllCteConnections(self):880 """ getAllCteConnections :881 Fetch a list containing the summaries for all the CTE connections.882 883 Sample usage:884 """885 return self._callServer('GET', '/api/cte_connections')886 def searchCteConnection(self, argsAPI):887 """ searchCteConnection :888 Search a specific CTE connection by certain properties.889 Sample usage:890 """891 return self._callServer('POST', '/api/cte_connections/search', argsAPI)892 def modifyCteConnection(self, cte_id, argsAPI):893 """ modifyCteConnection :894 Update the properties of an existing CTE connection.895 Sample usage:896 """897 return self._callServer('PUT', '/api/cte_connections/' + cte_id, argsAPI, False)898 # CTE Filters899 def createCteFilter(self, argsAPI):900 """ createCteFilter :901 Create a new CTE filter in the system.902 Sample usage:903 """904 return self._callServer('POST', '/api/cte_filters', argsAPI)905 def deleteCteFilter(self, cte_filter_id):906 """ deleteCteFilter :907 Remove a CTE filter.908 Sample usage:909 """910 return self._callServer('DELETE', '/api/cte_filters/' + cte_filter_id, None, False)911 def getCteFilter(self, cte_filter_id):912 """ getCteFilter :913 Fetch the properties of a CTE filter.914 Sample usage:915 """916 return self._callServer('GET', '/api/cte_filters/' + cte_filter_id)917 def getAllCteFilters(self):918 """ getAllCteFilters :919 Fetch a list containing the summaries for all the CTE filters.920 Sample usage:921 """922 return self._callServer('GET', '/api/cte_filters')923 def searchCteFilter(self, argsAPI):924 """ searchCteFilter :925 Search a specific CTE filter by certain properties.926 927 Sample usage:928 """929 return self._callServer('POST', '/api/cte_filters/search', argsAPI)930 def modifyCteFilter(self, cte_filter_id, argsAPI):931 """ modifyCteFilter :932 Update the properties of an existing CTE connection.933 Sample usage:934 """935 return self._callServer('PUT', '/api/cte_filters/' + cte_filter_id, argsAPI, False)936 # CTE Members937 def getCteMember(self, cte_member_id):938 """ getCteMember :939 Fetch the properties of a CTE member.940 Sample usage:941 """942 return self._callServer('GET', '/api/cte_members/' + cte_member_id)943 def getAllCteMembers(self):944 """ getAllCteMembers :945 Fetch a list containing the summaries for all the CTE members.946 Sample usage:947 """948 return self._callServer('GET', '/api/cte_members')949 def searchCteMember(self, argsAPI):950 """ searchCteMember :951 Search a specific CTE member by certain properties.952 Sample usage:953 """954 return self._callServer('POST', '/api/cte_members/search', argsAPI)955 # CTE Operations956 def clearCteConfig(self):957 """ clearCteConfig :958 Create a CTE topology.959 960 Sample usage:961 """962 argsAPI = {}963 return self._callServer('POST', '/api/cte_operations/cte_clear_config', argsAPI, False)964 def clearCteFiltersAndPort(self):965 """ clearCteFiltersAndPort :966 This command deletes all filters and port groups and sets all ports to default values..967 968 Sample usage:969 """970 argsAPI = {}971 return self._callServer('POST', '/api/cte_operations/cte_clear_filters_and_ports', argsAPI, False)972 def createCteTopology(self, argsAPI):973 """ createCteTopology :974 Create a CTE topology.975 Sample usage:976 """977 return self._callServer('POST', '/api/cte_operations/create_topology', argsAPI)978 def disbandCteTopology(self, argsAPI):979 """ disbandCteTopology :980 Disband the CTE topology. The local device and all other members981 that can be notified will be forced out of the topology. Manual982 disband on unreachable devices is required to recover them.983 Sample usage:984 """985 return self._callServer('POST', '/api/cte_operations/disband_topology', argsAPI)986 def exportCteTopology(self, argsAPI):987 """ exportCteTopology :988 Export topology configuration to a file.989 990 Sample usage:991 """992 return self._callServer('POST', '/api/cte_operations/export', argsAPI)993 def forceRemoveFromCteTopology(self, argsAPI):994 """ forceRemoveFromCteTopology :995 Given a failed member of a CTE topology by its IPv4 address, force996 remove it from the topology.997 Sample usage:998 """999 return self._callServer('POST', '/api/cte_operations/force_remove', argsAPI)1000 def importCteTopology(self, argsAPI):1001 """ importCteTopology :1002 Import topology configuration from a file.1003 Sample usage:1004 """1005 return self._callServer('POST', '/api/cte_operations/import', argsAPI)1006 def joinCteTopology(self, argsAPI):1007 """ joinCteTopology :1008 Join the current stack to a CTE topology.1009 Sample usage:1010 """1011 return self._callServer('POST', '/api/cte_operations/join_topology', argsAPI)1012 def leaveCteTopology(self, argsAPI):1013 """ leaveCteTopology :1014 Given a member of a CTE topology by its IPv4 address, this action will1015 disconnect it from the topology.1016 Sample usage:1017 """1018 return self._callServer('POST', '/api/cte_operations/leave_topology', argsAPI)1019 # CTE Port Groups1020 def getCtePortGroup(self, cte_port_group_id):1021 """ getCtePortGroup :1022 Fetch the properties of a CTE port group.1023 Sample usage:1024 """1025 return self._callServer('GET', '/api/cte_port_groups/' + cte_port_group_id)1026 def getAllCtePortGroups(self):1027 """ getAllCtePortGroups :1028 Fetch a list containing the summaries for all the CTE port groups.1029 Sample usage:1030 """1031 return self._callServer('GET', '/api/cte_port_groups')1032 def searchCtePortGroup(self, argsAPI):1033 """ searchCtePortGroup :1034 Search a specific CTE port group by certain properties.1035 Sample usage:1036 """1037 return self._callServer('POST', '/api/cte_port_groups/search', argsAPI)1038 # CTE Ports1039 def getCtePort(self, cte_port_id):1040 """ getCtePort :1041 Fetch the properties of a CTE port.1042 Sample usage:1043 """1044 return self._callServer('GET', '/api/cte_ports/' + cte_port_id)1045 def getAllCtePorts(self):1046 """ getAllCtePorts :1047 Fetch a list containing the summaries for all the CTE ports.1048 Sample usage:1049 """1050 return self._callServer('GET', '/api/cte_ports')1051 def searchCtePortGroup(self, argsAPI):1052 """ searchCtePortGroup :1053 Search a specific CTE port by certain properties.1054 Sample usage:1055 """1056 return self._callServer('POST', '/api/cte_ports/search', argsAPI)1057 def modifyCtePort(self, cte_port_id, argsAPI):1058 """ modifyCtePortGroup :1059 Change the properties of a specific CTE port.1060 Sample usage:1061 """1062 return self._callServer('PUT', '/api/cte_ports/' + cte_port_id, argsAPI, False)1063 ####################################1064 # CTE Remote Systems (deprecated)1065 ####################################1066 def getAllCtes(self):1067 """ getAllCtes :1068 Fetch a list containing the summaries for all the CTE remote1069 systems available on this device.1070 Sample usage:1071 """1072 return self._callServer('GET', '/api/cte_remote_system')1073 def getCte(self, cte_id):1074 """ getCte :1075 Fetch the properties of a CTE remote system available on the local device.1076 1077 Sample usage:1078 """1079 return self._callServer('GET', '/api/cte_remote_system/' + cte_id)1080 def connectCte(self, argsAPI):1081 """ connectCte :1082 Make a new CTE remote system available on the local device.1083 1084 Sample usage:1085 """1086 return self._callServer('POST', '/api/cte_remote_system', argsAPI)1087 def disconnectCte(self, cte_id):1088 """ disconnectCte :1089 Remove a CTE remote system from the local device.1090 1091 Sample usage:1092 """1093 argsAPI = {}1094 return self._callServer('DELETE', '/api/cte_remote_system/' + cte_id, argsAPI, False)1095 def searchCte(self, argsAPI):1096 """ searchCte :1097 Search by certain properties for a specific CTE remote systems available on this device.1098 1099 Sample usage:1100 """1101 return self._callServer('POST', '/api/cte_remote_system/search', argsAPI)1102 def modifyCte(self, cte_id, argsAPI):1103 """ modifyCte :1104 Update the connection details of a CTE remote system available on the local device.1105 1106 Sample usage:1107 """1108 return self._callServer('PUT', '/api/cte_remote_system/' + cte_id, argsAPI, False)1109 ####################################1110 # Custom Icons1111 ####################################1112 def getAllIcons(self):1113 """ getAllIcons :1114 Fetch a list containing summaries for all custom icons in the system.1115 Sample usage:1116 >>> nto.getAllIcons()1117 [{u'id': 71, u'name': u'JuniperLogoLarge'}, {u'id': 70, u'name': u'Tektronix'}, {u'id': 69, u'name': u'JDSU'}, {u'id': 68, u'name': u'Cisco'}, {u'id': 75, u'name': u'A Big Bomb!'}]1118 """1119 return self._callServer('GET', '/api/custom_icons')1120 def getIcon(self, icon):1121 """ getIcon :1122 Fetch the properties of a custom icon which is specified by its custom_icon_id_or_name.1123 Samle usage:1124 >>> nto.getIcon('75')1125 {u'description': u'A bomb!', u'created': {u'type': u'CREATE', u'caused_by': u'admin', u'details': None, u'time': 1440623340772}, u'name': u'A Big Bomb!', u'mod_count': 2, u'id': 75, u'history': [{u'type': u'MODIFY', u'time': 1440623518301, u'caused_by': u'admin', u'details': None, u'props': [u'NAME']}]}1126 """1127 return self._callServer('GET', '/api/custom_icons/' + icon)1128 def createIcon(self, argsAPI):1129 """ createIcon :1130 Create a new custom icon.1131 1132 Sample usage:1133 >>> nto.createIcon({'description': 'A bomb!', 'file_name': '/Users/fmota/Desktop/bomb.jpeg', 'name' : 'Bomb'})1134 {u'id': u'75'}1135 """1136 description = ''1137 if 'description' in argsAPI:1138 description = argsAPI['description']1139 file_name = ''1140 if 'file_name' in argsAPI:1141 file_name = argsAPI['file_name']1142 name = ''1143 if 'name' in argsAPI:1144 name = argsAPI['name']1145 boundary = "-----WebKitFormBoundary" + str(int(time.time())) + str(os.getpid())1146 buffer = bytearray()1147 # Set name1148 buffer.extend(b'--' + bytearray(boundary, 'ascii') + b'\r\n')1149 buffer.extend(b'Content-Disposition: form-data; name="name"\r\n')1150 buffer.extend(b'Content-Type: text/plain\r\n')1151 buffer.extend(b'\r\n')1152 buffer.extend(bytearray(name, 'ascii'))1153 buffer.extend(b'\r\n')1154 # Set Description1155 buffer.extend(b'--' + bytearray(boundary, 'ascii') + b'\r\n')1156 buffer.extend(b'Content-Disposition: form-data; name="description"\r\n')1157 buffer.extend(b'Content-Type: text/plain\r\n')1158 buffer.extend(b'\r\n')1159 buffer.extend(bytearray(description, 'ascii'))1160 buffer.extend(b'\r\n')1161 # Set creative contents part.1162 buffer.extend(b'--' + bytearray(boundary, 'ascii') + b'\r\n')1163 buffer.extend(1164 b'Content-Disposition: form-data; name="file"; filename=' + bytearray(file_name, 'ascii') + b'\r\n')1165 buffer.extend(b'Content-Type: application/octet-stream\r\n')1166 buffer.extend(b'\r\n')1167 # TODO: catch errors with opening file.1168 buffer.extend(open(file_name, 'rb').read())1169 buffer.extend(b'\r\n')1170 buffer.extend(b'--' + bytearray(boundary, 'ascii') + b'--\r\n')1171 hdrs = {'Authentication': self.token, 'Content-type': 'multipart/form-data; boundary=' + boundary}1172 response = self.connection.urlopen('POST', '/api/custom_icons', body=buffer, headers=hdrs)1173 # self._log (response.status, response.reason)1174 data = response.data1175 data = json.loads(data.decode('ascii'))1176 return data1177 def modifyIcon(self, icon_id, argsAPI):1178 """ modifyIcon :1179 Update properties of a custom icon.1180 Sample usage:1181 >>> nto.modifyIcon('75', {'name' : 'A Big Bomb!'})1182 ''1183 """1184 return self._callServer('PUT', '/api/custom_icons/' + icon_id, argsAPI, False)1185 def searchIcon(self, argsAPI):1186 """ searchFilterTemplateCollections :1187 Search for a specific custom icon in the system by certain properties.1188 Sample usage:1189 >>> nto.searchIcon({'name' : 'A Big Bomb!'})1190 [{u'id': 75, u'name': u'A Big Bomb!'}]1191 """1192 return self._callServer('POST', '/api/custom_icons/search', argsAPI)1193 def deleteIcon(self, icon_id):1194 """ deleteIcon :1195 Remove a custom icon from the system.1196 The custom icon is specified by a custom_icon_id_or_name.1197 Sample usage:1198 >>>.deleteIcon('75')1199 ''1200 """1201 return self._callServer('DELETE', '/api/custom_icons/' + icon_id, None, False)1202 ####################################1203 # Filter Template Collections1204 ####################################1205 def getAllFilterTemplateCollections(self):1206 """ getAllFilterTemplateCollections :1207 Fetch a list containing summaries for all the filter template collections in the system.1208 Sample usage:1209 >>> nto.getAllFilterTemplateCollections()1210 [{u'id': 467, u'name': u'NET_TROUBLESHOOTING'}, {u'id': 57, u'name': u'Public'}]1211 """1212 return self._callServer('GET', '/api/filter_template_collections')1213 def getFilterTemplateCollection(self, filter_template_collection):1214 """ getFilterTemplateCollection :1215 Fetch the properties of a filter template collection object which is specified by its1216 filter_template_collection_id_or_name.1217 Sample usage:1218 >>> nto.getFilterTemplateCollection('467')1219 {u'description': None, u'created': {u'type': u'CREATE', u'caused_by': u'admin', u'details': None, u'time': 1429303086082}, u'name': u'NET_TROUBLESHOOTING', u'mod_count': 2, u'id': 467, u'history': []}1220 """1221 return self._callServer('GET', '/api/filter_template_collections/' + filter_template_collection)1222 def createFilterTemplateCollection(self, argsAPI):1223 """ createFilterTemplateCollection :1224 Create a new filter template collection.1225 Sample usage:1226 >>> nto.createFilterTemplateCollection({'description': 'My filter collection', 'name': 'Private Filter Collection'})1227 {u'id': u'50'}1228 """1229 return self._callServer('POST', '/api/filter_template_collections', argsAPI)1230 def modifyFilterTemplateCollection(self, filter_template_collection_id, argsAPI):1231 """ modifyFilterTemplateCollection :1232 Update properties of a filter template collection.1233 Sample usage:1234 >>> nto.modifyFilterTemplateCollection('50', {'description': 'My private filter collection'})1235 ''1236 """1237 return self._callServer('PUT', '/api/filter_template_collections/' + filter_template_collection_id, argsAPI,1238 False)1239 def searchFilterTemplateCollections(self, argsAPI):1240 """ searchFilterTemplateCollections :1241 Search for a specific filter template collection in the system by certain properties.1242 Sample usage:1243 >>> nto.searchFilterTemplateCollections({'name': 'Private Filter Collection'})1244 [{u'id': 50, u'name': u'Private Filter Collection'}]1245 """1246 return self._callServer('POST', '/api/filter_template_collections/search', argsAPI)1247 def deleteFilterTemplateCollection(self, filter_template_collection_id):1248 """ deleteFilterTemplate :1249 Remove a filter template collection from the system. The filter is specified by a1250 filter_template_collection_id_or_name.1251 Sample usage:1252 >>> nto.deleteFilterTemplateCollection('50')1253 ''1254 """1255 return self._callServer('DELETE', '/api/filter_template_collections/' + filter_template_collection_id, None,1256 False)1257 ####################################1258 # Filter Templates1259 ####################################1260 def getAllFilterTemplates(self):1261 """ getAllFilterTemplates :1262 Fetch a list containing summaries for all the filter templates in the system.1263 Sample usage:1264 >>> nto.getAllFilterTemplates()1265 [{u'id': 468, u'name': u'Too Much Overhead'}, {u'id': 469, u'name': u'Syn Attack'}, {u'id': 470, u'name': u'ARP Storm'}, {u'id': 51, u'name': u'VLAN Gold'}]1266 """1267 return self._callServer('GET', '/api/filter_templates')1268 def getFilterTemplate(self, filter_template):1269 """ getFilterTemplate :1270 Fetch the properties of a filter templates object which is specified by its filter_template_id.1271 Sample usage:1272 >>> nto.getFilterTemplate('468')1273 {u'description': u'Use for base line tools. Checks ICMP and SNMP traffic.', u'created': {u'type': u'CREATE', u'caused_by': u'admin', u'details': None, u'time': 1429303123112}, u'collection': u'NET_TROUBLESHOOTING', u'name': u'Too Much Overhead', u'mod_count': 5, u'criteria': {u'logical_operation': u'AND', u'ip_protocol': {u'value': u'1'}, u'layer4_src_or_dst_port': {u'port': u'161-162'}}, u'id': 468, u'history': []}1274 """1275 return self._callServer('GET', '/api/filter_templates/' + filter_template)1276 def createFilterTemplate(self, argsAPI):1277 """ createFilterTemplate :1278 Create a new filter template.1279 Sample usage:1280 >>> nto.createFilterTemplate({'collection': 'Public', 'name': 'Virtual Traffic', 'criteria': {'vlan': {'vlan_id': '100'}, 'logical_operation': 'AND'}})1281 {u'id': u'52'}1282 """1283 return self._callServer('POST', '/api/filter_templates', argsAPI)1284 def modifyFilterTemplate(self, filter_template_id, argsAPI):1285 """ modifyFilterTemplate :1286 Update properties of a filter template.1287 Sample usage:1288 >>> nto.modifyFilterTemplate('52', {'criteria': {'vlan': {'vlan_id': '200'}, 'logical_operation': 'AND'}})1289 ''1290 """1291 return self._callServer('PUT', '/api/filter_templates/' + filter_template_id, argsAPI, False)1292 def searchFilterTemplates(self, argsAPI):1293 """ searchFilterTemplates :1294 Search for a specific filter template in the system by certain properties.1295 Sample usage:1296 >>> nto.searchFilterTemplates({'collection': 'Public'})1297 [{u'id': 51, u'name': u'VLAN Gold'}, {u'id': 52, u'name': u'Virtual Traffic'}]1298 """1299 return self._callServer('POST', '/api/filter_templates/search', argsAPI)1300 def deleteFilterTemplate(self, filter_template_id):1301 """ deleteFilterTemplate :1302 Remove a filter template from the system. The filter template is specified by a filter_template_id.1303 Sample usage:1304 >>> nto.deleteFilterTemplate('52')1305 ''1306 """1307 return self._callServer('DELETE', '/api/filter_templates/' + filter_template_id, None, False)1308 ####################################1309 # Filters1310 ####################################1311 def getAllFilters(self):1312 """ getAllFilters :1313 Fetch a list containing summaries for all the filters in the system.1314 Sample usage:1315 >>> nto.getAllFilters()1316 [{u'id': 460, u'name': u'TCP, UDP, HTTP'}, {u'id': 461, u'name': u'Voice VLANs'}, {u'id': 462, u'name': u'ARP Storm'}, {u'id': 463, u'name': u'Syn Attack'}, {u'id': 464, u'name': u'DENY HTTPS'}, {u'id': 465, u'name': u'Too Much Overhead'}, {u'id': 466, u'name': u'F4'}]1317 """1318 return self._callServer('GET', '/api/filters')1319 def getFilter(self, filter):1320 """ getFilter :1321 Fetch the properties of a filter object which is specified by its filter_id_or_name.1322 Sample usage:1323 >>> nto.getFilter('461')1324 {u'dynamic_filter_type': u'TWO_STAGE', u'connect_in_access_settings': {u'policy': u'INHERITED'}, u'dest_port_list': [], u'match_count_unit': u'PACKETS', u'description': None, u'resource_access_settings': {u'policy': u'INHERITED'}, u'created': None, u'modify_access_settings': {u'policy': u'INHERITED'}, u'default_name': u'F3', u'dest_port_group_list': [], u'name': u'Voice VLANs', u'mod_count': 6, u'snmp_tag': None, u'mode': u'PASS_BY_CRITERIA', u'criteria': {u'vlan': {u'priority': None, u'vlan_id': u'1000'}, u'logical_operation': u'AND'}, u'keywords': [], u'source_port_group_list': [], u'source_port_list': [410, 428], u'connect_out_access_settings': {u'policy': u'INHERITED'}, u'id': 461, u'history': [{u'type': u'MODIFY', u'time': 1442251734144, u'caused_by': u'internal', u'details': None, u'props': [u'SOURCE_PORT_LIST', u'DEST_PORT_LIST']}]}1325 """1326 return self._callServer('GET', '/api/filters/' + filter)1327 def createFilter(self, argsAPI, allowTemporayDataLoss=False):1328 """ createFilter :1329 Create a new filter.1330 Sample usage:1331 >>> nto.createFilter({'source_port_list': ['218', '220'], 'dest_port_list': ['219'], 'mode': 'PASS_ALL'})1332 {u'id': u'466'}1333 """1334 return self._callServer('POST', '/api/filters?allowTemporayDataLoss=' + str(allowTemporayDataLoss), argsAPI)1335 def modifyFilter(self, filter_id, argsAPI, allowTemporayDataLoss=False):1336 """ modifyFilter :1337 Update properties of a filter.1338 Sample usage:1339 >>> nto.modifyFilter('F4', {'mode' : 'PASS_BY_CRITERIA', 'criteria' : {'logical_operation': 'AND', 'ipv4_session_flow': {'session_sets': [{'a_sessions': ['10.0.0.0/24:1', '12.0.0.0/24:1'], 'b_sessions': ['14.0.0.0/24:1', '16.0.0.0/24:1']}], 'flow_type': 'UNI'}}})1340 ''1341 """1342 return self._callServer('PUT',1343 '/api/filters/' + filter_id + '?allowTemporayDataLoss=' + str(allowTemporayDataLoss),1344 argsAPI, False)1345 def searchFilters(self, argsAPI):1346 """ searchFilters :1347 Search for a specific port group in the system by certain properties.1348 Sample usage:1349 >>> nto.searchFilters({'mode' : 'PASS_BY_CRITERIA'})1350 [{u'id': 463, u'name': u'Syn Attack'}, {u'id': 465, u'name': u'Too Much Overhead'}, {u'id': 466, u'name': u'F8'}, {u'id': 55, u'name': u'F4'}, {u'id': 460, u'name': u'TCP, UDP, HTTP'}, {u'id': 462, u'name': u'ARP Storm'}, {u'id': 461, u'name': u'Voice VLANs'}]1351 """1352 return self._callServer('POST', '/api/filters/search', argsAPI)1353 def deleteFilter(self, filter_id):1354 """ deleteFilter :1355 Remove a filter from the system. The filter is specified by a filter_id_or_name.1356 Sample usage:1357 >>> nto.deleteFilter('F4')1358 ''1359 """1360 return self._callServer('DELETE', '/api/filters/' + filter_id, None, False)1361 def getFilterProperty(self, filter, property):1362 """ getFilterProperty :1363 Fetch a property of a filter object which is specified by its1364 port_id_or_name.1365 1366 Sample usage:1367 >>> nto.getFilterProperty('F1', 'keywords')1368 [u'TIME']1369 """1370 return self._callServer('GET', '/api/filters/' + filter + '?properties=' + property)[property]1371 ####################################1372 # Groups1373 ####################################1374 def getAllGroups(self):1375 """ getAllGroups :1376 Fetch a list containing the summaries for all the user groups in the system.1377 Sample usage:1378 >>> nto.getAllGroups()1379 [{u'id': 369, u'name': u'Security Mgmt'}, {u'id': 367, u'name': u'Network Mgmt'}, {u'id': 368, u'name': u'Security Engineering'}, {u'id': 365, u'name': u'group2'}, {u'id': 366, u'name': u'Network Operations'}, {u'id': 364, u'name': u'group1'}]1380 """1381 return self._callServer('GET', '/api/groups')1382 def getGroup(self, group):1383 """ getGroup :1384 Fetch the properties of an user group object which is specified by its1385 group_id_or_name.1386 Sample usage:1387 >>> nto.getGroup('369')1388 {u'owners': [], u'auto_created': False, u'description': None, u'name': u'Security Mgmt', u'created': {u'type': u'CREATE', u'caused_by': u'admin', u'details': None, u'time': 1256831414761}, u'accessible_ports': [], u'mod_count': 2, u'members': [u'bbrother', u'securityguy'], u'accessible_filters': [], u'id': 369, u'history': [{u'type': u'MODIFY', u'time': 1316645263611, u'caused_by': u'internal', u'details': None, u'props': [u'ACCESSIBLE_PORTS']}]}1389 """1390 return self._callServer('GET', '/api/groups/' + group)1391 def createGroup(self, argsAPI):1392 """ createGroup :1393 Create a new user group.1394 Sample usage:1395 >>> nto.createGroup({'name' : 'Automation', 'members': ['bbrother', 'jfixit']})1396 {u'id': u'477'}1397 """1398 return self._callServer('POST', '/api/groups', argsAPI)1399 def modifyGroup(self, group_id, argsAPI):1400 """ modifyGroup :1401 Update the properties of an existing user group.1402 Sample usage:1403 >>> nto.modifyGroup('Automation', {'members': ['jfixit']})1404 ''1405 """1406 return self._callServer('PUT', '/api/groups/' + group_id, argsAPI, False)1407 def deleteGroup(self, group_id):1408 """ deleteGroup :1409 Remove a user from the system. The user is specified by a group_id_or_name.1410 Sample usage:1411 >>> nto.deleteGroup('477')1412 ''1413 """1414 return self._callServer('DELETE', '/api/groups/' + group_id, None, False)1415 def searchGroups(self, argsAPI):1416 """ searchGroups :1417 Search for a specific user group in the system by certain properties.1418 Sample usage:1419 >>> nto.searchGroups({'members': ['netopsguy']})1420 [{u'id': 367, u'name': u'Network Mgmt'}]1421 """1422 return self._callServer('POST', '/api/groups/search', argsAPI)1423 ###################################################1424 # Heartbeats1425 ###################################################1426 def createHeartbeat(self, argsAPI):1427 """ createHeartbeat :1428 Create a new tool heartbeat in the system.1429 Sample usage:1430 """1431 return self._callServer('POST', '/api/heartbeats', argsAPI)1432 def deleteHeartbeat(self, heartbeat_id):1433 """ deleteHeartbeat :1434 Remove an existing tool heartbeat from the system.1435 Sample usage:1436 """1437 return self._callServer('DELETE', '/api/heartbeats/' + heartbeat_id, None, False)1438 def getHeartbeat(self, heartbeat_id):1439 """ getHeartbeat :1440 Fetch the properties of a tool heartbeat object.1441 Sample usage:1442 """1443 return self._callServer('GET', '/api/heartbeats/' + bypass_id)1444 def getAllHeartbeats(self):1445 """ getAllHeartbeats :1446 Fetch a list containing the summaries for all the tool heartbeats in the system.1447 Sample usage:1448 """1449 return self._callServer('GET', '/api/heartbeats')1450 def searchHeartbeat(self, argsAPI):1451 """ searchHeartbeat :1452 Search for a specific tool heartbeat in the system by certain properties.1453 Sample usage:1454 """1455 return self._callServer('POST', '/api/heartbeats/search', argsAPI)1456 def modifyHeartbeat(self, heartbeat_id, argsAPI):1457 """ modifyHeartbeat:1458 Update the properties of an existing tool heartbeat.1459 Sample usage:1460 """1461 return self._callServer('PUT', '/api/heartbeats/' + heartbeat_id, argsAPI, False)1462 ###################################################1463 # Inline service chains1464 ###################################################1465 def createInline(self, argsAPI):1466 """ createInline :1467 Create a new inline service chain in the system.1468 Sample usage:1469 """1470 return self._callServer('POST', '/api/inline_service_chains', argsAPI)1471 def deleteInline(self, inline_id):1472 """ deleteInline :1473 Remove an existing inline service chain from the system.1474 1475 Sample usage:1476 """1477 return self._callServer('DELETE', '/api/inline_service_chains/' + inline_id, None, False)1478 def getInline(self, inline_id):1479 """ getInline :1480 Fetch the properties of a inline service chain object.1481 Sample usage:1482 """1483 return self._callServer('GET', '/api/inline_service_chains/' + inline_id)1484 def getAllInlines(self):1485 """ getAllInlines :1486 Fetch a list containing the summaries for all the inline service chains in the system.1487 Sample usage:1488 """1489 return self._callServer('GET', '/api/inline_service_chains')1490 def searchInline(self, argsAPI):1491 """ searchInline :1492 Search for a specific inline service chain in the system by certain properties.1493 Sample usage:1494 """1495 return self._callServer('POST', '/api/inline_service_chains/search', argsAPI)1496 def modifyInline(self, inline_id, argsAPI):1497 """ modifyInline:1498 Update the properties of an existing inline service chain.1499 Sample usage:1500 """1501 return self._callServer('PUT', '/api/inline_service_chains/' + inline_id, argsAPI, False)1502 ###################################################1503 # Line Boards1504 ###################################################1505 def getAllLineBoards(self):1506 """ getAllLineBoards :1507 Fetch a list containing the summaries for all the line boards in the system.1508 Sample usage:1509 >>> nto.getAllLineBoards()1510 [{u'id': 471, u'name': u'LC6'}, {u'id': 476, u'name': u'LC1'}, {u'id': 474, u'name': u'LC5'}, {u'id': 475, u'name': u'LC3'}, {u'id': 472, u'name': u'LC2'}, {u'id': 473, u'name': u'LC4'}]1511 """1512 return self._callServer('GET', '/api/line_boards')1513 def getLineBoard(self, line_board):1514 """ getLineBoard :1515 Fetch the properties of a line board.1516 Sample usage:1517 >>> nto.getLineBoard('LC6')1518 {u'name': u'LC6', u'qsfp_card_mode': u'MODE_QSFP', u'default_name': u'LC6', u'mod_count': 9, u'modify_access_settings': {u'policy': u'ALLOW_ALL', u'groups': []}, u'id': 471}1519 """1520 return self._callServer('GET', '/api/line_boards/' + line_board)1521 def searchLineBoard(self, argsAPI):1522 """ searchLineBoard :1523 Search for a specific capture in the system by certain properties.1524 Sample usage:1525 >>> nto.searchLineBoard({'name': 'LC6'})1526 [{u'id': 471, u'name': u'LC6'}]1527 """1528 return self._callServer('POST', '/api/line_boards/search', argsAPI)1529 def switchModeLineBoard(self, line_board):1530 """ switchModeLineBoard :1531 Switches the card mode to QSFP if in SFP mode and to SFP if in QSFP mode.1532 Sample usage:1533 >>> nto.switchModeLineBoard('LC6')1534 ''1535 """1536 argsAPI = {}1537 return self._callServer('PUT', '/api/line_boards/' + line_board + '/switch_mode', argsAPI, False)1538 def modifyLineBoard(self, line_board, argsAPI):1539 """ modifyLineBoard :1540 Update the properties of an existing line board.1541 Sample usage:1542 >>> nto.modifyLineBoard('LC6', {'name' : 'Test LC'})1543 ''1544 """1545 return self._callServer('PUT', '/api/line_boards/' + line_board, argsAPI, False)1546 ###################################################1547 # Monitors1548 ###################################################1549 def getAllMonitors(self):1550 """ getAllMonitors :1551 Fetch a list containing the summaries for all the monitors in the system.1552 Sample usage:1553 >>> nto.getAllMonitors()1554 [{u'id': 572, u'name': u'Low Traffic'}]1555 """1556 return self._callServer('GET', '/api/monitors')1557 def getMonitor(self, monitor):1558 """ getMonitor :1559 Fetch the properties of a monitor object which is specified by its1560 monitor_id_or_name.1561 Sample usage:1562 >>> nto.getMonitor('572')1563 {u'description': None, u'created': {u'type': u'CREATE', u'caused_by': u'admin', u'details': None, u'time': 1442432114344}, u'actions': [{u'min_interval': {u'value': 15, u'unit': u'SEC'}, u'type': u'TRAP', u'enabled': True}], u'name': u'Low Traffic', u'mod_count': 0, u'trigger': {u'stat': u'NP_CURRENT_RX_UTILIZATION', u'window_size': 1, u'window_count': 1, u'down_threshold_enabled': True, u'up_threshold': 99, u'up_threshold_enabled': False, u'down_threshold': 10, u'type': u'PERCENT_STAT', u'ports': [58]}, u'id': 572, u'history': []}1564 """1565 return self._callServer('GET', '/api/monitors/' + monitor)1566 def createMonitor(self, argsAPI):1567 """ createMonitor :1568 Create a new monitor.1569 Sample usage:1570 >>> nto.createMonitor({'actions': [{'min_interval': {'value': 15, 'unit': 'SEC'}, 'type': 'TRAP', 'enabled': True}], 'name': 'Drop Packets', 'trigger': {'stat': 'TP_TOTAL_DROP_COUNT_PACKETS', 'window_size': 1, 'min_change': 10, 'window_count': 1, 'type': 'COUNT_STAT', 'ports': [59]}})1571 '{"id": "574"}'1572 """1573 return self._callServer('POST', '/api/monitors', argsAPI, False)1574 def modifyMonitor(self, monitor_id, argsAPI):1575 """ modifyMonitor :1576 Update properties of a monitor.1577 Sample usage:1578 >>> nto.modifyMonitor('574', {'trigger': {'stat': 'TP_TOTAL_DROP_COUNT_PACKETS', 'window_size': 1, 'min_change': 20, 'window_count': 1, 'type': 'COUNT_STAT', 'ports': [59]}})1579 ''1580 """1581 return self._callServer('PUT', '/api/monitors/' + monitor_id, argsAPI, False)1582 def searchMonitors(self, argsAPI):1583 """ searchMonitors :1584 Search for a specific port group in the system by certain properties.1585 Sample usage:1586 >>> nto.searchMonitors({'name': 'Drop Packets'})1587 [{u'id': 574, u'name': u'Drop Packets'}]1588 """1589 return self._callServer('POST', '/api/monitors/search', argsAPI)1590 def deleteMonitor(self, monitor_id):1591 """ deleteMonitor :1592 Remove a monitor from the system. The monitor is specified by a monitor_id_or_name.1593 Sample usage:1594 >>> nto.deleteMonitor('572')1595 ''1596 """1597 return self._callServer('DELETE', '/api/monitors/' + monitor_id, None, False)1598 ###################################################1599 # Neighbors1600 ###################################################1601 def getAllNeighbors(self, port_id_list=[]):1602 """ getAllNeighbors :1603 Fetch a list containing summaries for all the neigbors the system learned by snooping on LLDP messages1604 Sample usage:1605 >>> nto.getAllNeighbors()1606 1607 """1608 # TODO TEST we got HTTP/200 with JSON back1609 # TODO TEST we got 'message' key back1610 return self._callServer('POST', '/api/actions/get_neighbors', {'port_id_list': port_id_list})['message']1611 ###################################################1612 # Port Groups1613 ###################################################1614 def getAllPortGroups(self):1615 """ getAllPortGroups :1616 Fetch a list containing the summaries for all the port groups in the system.1617 Sample usage:1618 >>> nto.getAllPortGroups()1619 [{u'id': 202, u'name': u'PGF27'}, {u'id': 203, u'name': u'PGF31'}, {u'id': 204, u'name': u'PGF30'}, {u'id': 205, u'name': u'PGF29'}, {u'id': 206, u'name': u'PGF28'}, {u'id': 251, u'name': u'PGF1'}, {u'id': 252, u'name': u'PGF2'}, {u'id': 253, u'name': u'PGF3'}, {u'id': 254, u'name': u'PGF4'}, {u'id': 255, u'name': u'PGF5'}, {u'id': 288, u'name': u'PGF6'}, {u'id': 289, u'name': u'PGF7'}, {u'id': 290, u'name': u'PGF8'}, {u'id': 291, u'name': u'PGF9'}, {u'id': 292, u'name': u'PGF10'}, {u'id': 325, u'name': u'PGF11'}, {u'id': 326, u'name': u'PGF12'}, {u'id': 327, u'name': u'PGF13'}, {u'id': 328, u'name': u'PGF14'}, {u'id': 329, u'name': u'PGF15'}, {u'id': 362, u'name': u'PGF16'}, {u'id': 363, u'name': u'PGF17'}, {u'id': 364, u'name': u'PGF18'}, {u'id': 365, u'name': u'PGF19'}, {u'id': 366, u'name': u'PGF20'}, {u'id': 399, u'name': u'PGF21'}, {u'id': 400, u'name': u'PGF22'}, {u'id': 401, u'name': u'PGF23'}, {u'id': 402, u'name': u'PGF24'}, {u'id': 403, u'name': u'PGF25'}, {u'id': 404, u'name': u'PG1'}]1620 """1621 return self._callServer('GET', '/api/port_groups')1622 def getPortGroup(self, port_group):1623 """ getPortGroup :1624 Fetch the properties of a port group object which is specified by its1625 port_group_id_or_name.1626 Sample usage:1627 >>> nto.getPortGroup('404')1628 {u'trim_settings': None, u'supports_timestamp': False, u'dedup_settings': None, u'vntag_strip_settings': None, u'vxlan_strip_settings': None, u'failover_mode': u'REBALANCE', u'keywords': [], u'supports_dedup': False, u'id': 404, u'fabric_path_strip_settings': None, u'supports_vntag_strip': False, u'has_dropped_packets': False, u'filtering_direction': u'INGRESS', u'supports_trailer_strip': False, u'icon_type': u'INTERCONNECT', u'last_filter_order_event': None, u'supports_mpls_strip': False, u'enabled_status': u'ENABLED', u'supports_burst_buffer': False, u'custom_icon_id': None, u'trailer_strip_settings': None, u'mpls_strip_settings': None, u'type': u'INTERCONNECT', u'tx_light_status': u'ON', u'filter_criteria': {u'logical_operation': u'AND'}, u'supports_std_vlan_strip': True, u'pause_frames_status': u'IGNORE', u'dest_filter_list': [], u'description': None, u'snmp_tag': None, u'l2gre_strip_settings': None, u'gtp_strip_settings': None, u'burst_buffer_settings': None, u'force_link_up': u'NOT_SUPPORTED', u'supports_trim': False, u'supports_gtp_strip': False, u'port_list': [58], u'supports_vxlan_strip': False, u'name': u'PG1', u'supports_l2gre_strip': False, u'supports_fabric_path_strip': False, u'link_status': {u'speed': 0, u'link_up': False}, u'interconnect_info': {u'addr': u'0.0.0.0', u'port_group': None}, u'created': {u'type': u'CREATE', u'caused_by': u'admin', u'details': None, u'time': 1442434236579}, u'default_name': u'PG1', u'supports_erspan_strip': False, u'mod_count': 1, u'timestamp_settings': None, u'erspan_strip_settings': None, u'mode': u'NETWORK', u'source_filter_list': [], u'filter_mode': u'PASS_ALL', u'std_vlan_strip_settings': {u'ingress_count': 0, u'egress_count': 0, u'enabled': False, u'strip_mode': None}, u'history': [{u'type': u'MODIFY', u'time': 1442434236579, u'caused_by': u'admin', u'details': None, u'props': [u'PORT_LIST']}]}1629 """1630 return self._callServer('GET', '/api/port_groups/' + port_group)1631 def createPortGroup(self, argsAPI):1632 """ createPortGroup :1633 Create a new port group.1634 Sample usage:1635 >>> nto.createPortGroup({'mode': 'NETWORK', 'type': 'INTERCONNECT', 'port_list': [59,60]})1636 {u'id': u'405'}1637 """1638 return self._callServer('POST', '/api/port_groups', argsAPI)1639 def modifyPortGroup(self, port_group_id, argsAPI):1640 """ modifyPortGroup :1641 Update properties of a port group.1642 Sample usage:1643 >>> nto.modifyPortGroup('PG2', {'port_list': [59,60,61,62]})1644 ''1645 """1646 return self._callServer('PUT', '/api/port_groups/' + port_group_id, argsAPI, False)1647 def searchPortGroups(self, argsAPI):1648 """ searchPortGroups :1649 Search for a specific port group in the system by certain properties.1650 Sample usage:1651 >>> nto.searchPortGroups({'enabled_status' : 'DISABLED'})1652 [{u'id': 404, u'name': u'PG1'}]1653 """1654 return self._callServer('POST', '/api/port_groups/search', argsAPI)1655 def deletePortGroup(self, port_group_id):1656 """ deletePortGroup :1657 Remove a port group from the system. The port group is specified by a port_group_id_or_name.1658 Sample usage:1659 >>> nto.deletePortGroup('PG2')1660 ''1661 """1662 return self._callServer('DELETE', '/api/port_groups/' + port_group_id, None, False)1663 def disablePortGroup(self, port_group_id):1664 """ disablePortGroup :1665 Disables a port group by disabling all the contained ports.1666 1667 Sample usage:1668 """1669 return self._callServer('PUT', '/api/port_groups/' + port_group_id + '/disable', None, False)1670 def enablePortGroup(self, port_group_id):1671 """ enablePortGroup :1672 Enables a port group by enabling all the contained ports.1673 1674 Sample usage:1675 """1676 return self._callServer('PUT', '/api/port_groups/' + port_group_id + '/enable', None, False)1677 def getPortGroupProperty(self, port_group, property):1678 """ getPortGroupProperty :1679 Fetch a property of a port group object which is specified by its1680 port_id_or_name.1681 1682 Sample usage:1683 >>> nto.getPortGroupProperty('PG1', 'keywords')1684 [u'TIME']1685 """1686 return self._callServer('GET', '/api/port_groups/' + port_group + '?properties=' + property)[property]1687 ###################################################1688 # Ports1689 ###################################################1690 def getAllPorts(self):1691 """ getAllPorts :1692 Fetch a list containing summaries for all the ports in the system.1693 Sample usage:1694 >>> nto.getAllPorts()1695 [{u'id': 58, u'name': u'P1-01'}, {u'id': 59, u'name': u'P1-02'}, {u'id': 60, u'name': u'P1-03'}, {u'id': 61, u'name': u'P1-04'}, {u'id': 62, u'name': u'P1-05'}, {u'id': 63, u'name': u'P1-06'}, {u'id': 64, u'name': u'P1-07'}, {u'id': 65, u'name': u'P1-08'}, {u'id': 66, u'name': u'P1-09'}, {u'id': 67, u'name': u'P1-10'}, {u'id': 68, u'name': u'P1-11'}, {u'id': 69, u'name': u'P1-12'}, {u'id': 70, u'name': u'P1-13'}, {u'id': 71, u'name': u'P1-14'}, {u'id': 72, u'name': u'P1-15'}, {u'id': 73, u'name': u'P1-16'}]1696 """1697 return self._callServer('GET', '/api/ports')1698 def getPort(self, port):1699 """ getPort :1700 Fetch the properties of a port object which is specified by its1701 port_id_or_name.1702 Sample usage:1703 >>> nto.getPort('58')1704 {u'trim_settings': None, u'supports_timestamp': False, u'dedup_settings': None, u'filter_criteria': {u'logical_operation': u'AND'}, u'vntag_strip_settings': None, u'std_port_tagging_settings': {u'enabled': False, u'vlan_id': 101}, u'link_up_down_trap_enabled': True, u'filter_match_count_unit': u'PACKETS', u'gtp_fd_settings': None, u'keywords': [u'LC1'], u'tunnel_termination_settings': {u'ip_version': 4, u'dest_ip_addr': None, u'enabled': False, u'empty_erspan_header': False, u'tunnel_protocol': None}, u'supports_dedup': False, u'id': 58, u'fabric_path_strip_settings': None, u'supports_vxlan_strip': False, u'port_group_id': None, u'mpls_strip_settings': None, u'max_licensed_speed': u'40G', u'supports_vntag_strip': False, u'has_dropped_packets': False, u'filtering_direction': u'INGRESS', u'supports_trailer_strip': False, u'tunnel_mac': None, u'supports_tunnel_termination': False, u'supports_mpls_strip': False, u'copper_link_polling': False, u'last_filter_order_event': None, u'vxlan_strip_settings': None, u'supports_burst_buffer': False, u'custom_icon_id': None, u'trailer_strip_settings': None, u'media_type': u'QSFP_PLUS_40G', u'expiration_time': 1449727199651, u'modify_access_settings': {u'policy': u'ALLOW_ALL', u'groups': []}, u'type': u'QSFP_PLUS', u'link_settings': u'40G_FULL', u'tx_light_status': u'ON', u'connect_in_access_settings': {u'policy': u'ALLOW_ALL', u'groups': []}, u'supports_std_vlan_strip': True, u'dest_filter_list': [], u'description': None, u'snmp_tag': None, u'l2gre_strip_settings': None, u'gtp_strip_settings': None, u'burst_buffer_settings': None, u'force_link_up': u'NOT_SUPPORTED', u'supports_trim': False, u'supports_gtp_strip': False, u'license_status': u'VALID', u'resource_access_settings': {u'policy': u'ALLOW_ALL', u'groups': []}, u'supports_std_port_tagging': True, u'remote_fabric_port': None, u'connect_out_access_settings': {u'policy': u'ALLOW_ALL', u'groups': []}, u'name': u'P1-01', u'supports_l2gre_strip': False, u'supports_fabric_path_strip': False, u'ignore_pause_frames': True, u'link_status': {u'duplex': u'UNKNOWN', u'pause': u'UNKNOWN', u'speed': u'N/A', u'link_up': False}, u'icon_type': u'QSFP_PLUS', u'default_name': u'P1-01', u'enabled': False, u'supports_erspan_strip': False, u'mod_count': 21, u'timestamp_settings': None, u'erspan_strip_settings': None, u'mode': u'NETWORK', u'supports_gtp_flow_distribution': False, u'source_filter_list': [], u'filter_mode': u'PASS_ALL', u'std_vlan_strip_settings': {u'ingress_count': 0, u'egress_count': 0, u'enabled': False, u'strip_mode': None}, u'history': []}1705 """1706 return self._callServer('GET', '/api/ports/' + port)1707 def modifyPort(self, port_id, argsAPI):1708 """ modifyPort :1709 Update the properties of a port.1710 Sample usage:1711 >>> nto.modifyPort('58', {'mode': 'TOOL'})1712 ''1713 """1714 return self._callServer('PUT', '/api/ports/' + port_id, argsAPI, False)1715 def searchPorts(self, argsAPI):1716 """ searchPorts :1717 Search for a specific port in the system by certain properties.1718 Sample usage:1719 >>> nto.searchPorts({'mode': 'TOOL'})1720 [{u'id': 58, u'name': u'P1-01'}]1721 """1722 return self._callServer('POST', '/api/ports/search', argsAPI)1723 def getPortProperties(self, port, properties):1724 """ getPortProperties :1725 Fetch one or more properties of a port object which is specified by its1726 port_id_or_name.1727 1728 Sample usage:1729 >>> nto.getPortProperties('PB07', 'enabled,link_status')1730 {u'enabled': True, u'link_status': {u'duplex': u'FULL', u'pause': u'DISABLED', u'speed': u'10G', u'link_up': True}}1731 """1732 return self._callServer('GET', '/api/ports/' + port + '?properties=' + properties)1733 def getPortProperty(self, port, property):1734 """ getPortProperty :1735 Fetch a property of a port object which is specified by its1736 port_id_or_name.1737 Sample usage:1738 >>> nto.getPortProperty('PB07', 'enabled')1739 {u'enabled': True}1740 """1741 return self._callServer('GET', '/api/ports/' + port + '?properties=' + property)[property]1742 ###################################################1743 # Recirculated AFM resources1744 ###################################################1745 def disableAfm(self, afm_id, argsAPI):1746 """ disableAfm :1747 Disables an recirculated AFM by disconnecting the attached port, port group or filter.1748 Sample usage:1749 >>> nto.disableAfm('96', {'object_id': '53'})1750 ''1751 """1752 return self._callServer('PUT', '/api/recirculated_afm_resources/' + afm_id + '/disable', argsAPI, False)1753 def enableAfm(self, afm_id, argsAPI):1754 """ enableAfm :1755 Enables an recirculated AFM by attaching a port, port group or filter to it.1756 Sample usage:1757 >>> nto.enableAfm('96', {'allocated_bandwidth': 10, 'object_id': '53', 'port_mode': 'NETWORK'})1758 ''1759 """1760 return self._callServer('PUT', '/api/recirculated_afm_resources/' + afm_id + '/enable', argsAPI, False)1761 def getBandwidthDetailsAfm(self, afm_id):1762 """ getBandwidthDetailsAfm :1763 Gets the bandwidth details for the Recirculated AFM resource.1764 Sample usage:1765 >>> nto.getBandwidthDetailsAfm('96')1766 {u'allocated_bandwidth': 20, u'total_bandwidth': 160, u'available_bandwidth': 140, u'bandwidth_increment': 10}1767 """1768 return self._callServer('PUT', '/api/recirculated_afm_resources/' + afm_id + '/get_bandwidth_details', {})1769 def getAfm(self, afm_id):1770 """ getAfm :1771 Fetch the properties of a recirculated AFM object.1772 Sample usage:1773 >>> nto.getAfm('96')1774 {u'description': u'AFM Resources', u'lane_config_list': [{u'allocated_bandwidth': 10, u'attachment_id': u'52', u'attachment_type': u'PORT'}, {u'allocated_bandwidth': 10, u'attachment_id': u'53', u'attachment_type': u'PORT'}], u'capture_source': None, u'lineboard_id': None, u'default_name': u'L1-AFM', u'resource_status': u'READY', u'name': u'L1-AFM', u'mod_count': 20, u'license_status': u'NOT_PRESENT', u'capture_port_group': None, u'modify_access_settings': {u'policy': u'ALLOW_ALL', u'groups': []}, u'id': 96, u'connect_disconnect_access_settings': {u'policy': u'ALLOW_ALL', u'groups': []}, u'history': [{u'type': u'MODIFY', u'time': 1497393506254, u'caused_by': u'admin', u'details': None, u'props': [u'DESCRIPTION']}]}1775 >>> nto.getAfm('L1-AFM')1776 {u'description': u'AFM Resources', u'lane_config_list': [{u'allocated_bandwidth': 10, u'attachment_id': u'52', u'attachment_type': u'PORT'}, {u'allocated_bandwidth': 10, u'attachment_id': u'53', u'attachment_type': u'PORT'}], u'capture_source': None, u'lineboard_id': None, u'default_name': u'L1-AFM', u'resource_status': u'READY', u'name': u'L1-AFM', u'mod_count': 20, u'license_status': u'NOT_PRESENT', u'capture_port_group': None, u'modify_access_settings': {u'policy': u'ALLOW_ALL', u'groups': []}, u'id': 96, u'connect_disconnect_access_settings': {u'policy': u'ALLOW_ALL', u'groups': []}, u'history': [{u'type': u'MODIFY', u'time': 1497393506254, u'caused_by': u'admin', u'details': None, u'props': [u'DESCRIPTION']}]}1777 """1778 return self._callServer('GET', '/api/recirculated_afm_resources/' + afm_id)1779 def getAllAfms(self):1780 """ getAllAfms :1781 Fetch a list containing the summaries for all the recirculated AFM resources in the system.1782 Sample usage:1783 >>> nto.getAllAfms()1784 [{u'id': 96, u'name': u'L1-AFM'}]1785 """1786 return self._callServer('GET', '/api/recirculated_afm_resources')1787 def searchAfm(self, argsAPI):1788 """ searchAfm :1789 Search for a specific recirculated AFM resource in the system by certain properties.1790 Sample usage:1791 >>> nto.searchAfm({'description': 'AFM Resources'})1792 [{u'id': 96, u'name': u'L1-AFM'}]1793 """1794 return self._callServer('POST', '/api/recirculated_afm_resources/search', argsAPI)1795 def modifyAfm(self, afm_id, argsAPI):1796 """ modifyAfm:1797 Update the properties of an existing recirculated AFM resource.1798 Sample usage:1799 >>> nto.modifyAfm('96', {'description': 'Shared AFM Resources'})1800 ''1801 """1802 return self._callServer('PUT', '/api/recirculated_afm_resources/' + afm_id, argsAPI, False)1803 ####################################1804 # Statistics1805 ####################################1806 def getStats(self, argsAPI):1807 """ getStats :1808 Retrieve a stats snapshot containing the specified objects.1809 Sample usage:1810 >>> nto.getStats({'stat_name': ['np_peak_gtp_v2_deleted_sessions_time', 'np_total_rx_count_valid_packets'], 'port_group': '91'})1811 {u'stats_snapshot': [{u'np_peak_gtp_v2_deleted_sessions_time': 1441391232493, u'reset_by': u'null', u'reset_time': 1441390286194, u'default_name': u'PG1', u'stats_time': 1441391232493, u'np_total_rx_count_valid_packets': 0, u'type': u'Port Group', u'id': u'91'}]}1812 """1813 return self._callServer('POST', '/api/stats', argsAPI)1814 def resetStats(self, argsAPI):1815 """ resetStats :1816 Reset the stats for a set of specific NTO ports, port groups, and/or filters.1817 Sample usage:1818 >>> nto.resetStats({'PORT': [59], 'PORT_GROUP': [405]})1819 {}1820 """1821 return self._callServer('POST', '/api/stats/reset', argsAPI)1822 def getManagementStats(self):1823 """ getManagementStats :1824 Returns the statistics for active management port.1825 1826 Sample usage:1827 """1828 return self._callServer('POST', '/api/stats/mgmt_port', None)1829 def resetDrops(self, argsAPI):1830 """ resetDrops :1831 Reset the overflow drop counts for a set of specific NTO tool ports and/or output port groups.1832 Sample usage:1833 >>> nto.resetDrops({'PORT': [58]})1834 {u'reset_drops_attempt_count': 134, u'reset_drops_success_count': 118}1835 """1836 return self._callServer('POST', '/api/stats/reset_drops', argsAPI)1837 ####################################1838 # System1839 ####################################1840 def getSpecificSystem(self, system_id):1841 """ getSpecificSystem :1842 Retrieve the properties of the system specified.1843 1844 Sample usage:1845 >>> nto.getSystem()1846 {u'mgmt_port2_link_status': {u'duplex': u'FULL', u'active_port': False, u'speed': u'1G', u'link_up': True}, u'union_mode': u'INDEPENDENT', u'timestamp_config': {u'time_source': u'LOCAL'}, u'fan_failure_count': 0, u'web_api_config': {u'enabled': True, u'port': 9000, u'token_timeout': {u'value': 10, u'unit': u'MIN'}}, u'session_timeout_interval': 0,1847 <snip>1848 """1849 return self._callServer('GET', '/api/system/' + system_id)1850 def getSystem(self):1851 """ getSystem :1852 Retrieve the properties of the system.1853 Sample usage:1854 >>> nto.getSystem()1855 {u'mgmt_port2_link_status': {u'duplex': u'FULL', u'active_port': False, u'speed': u'1G', u'link_up': True}, u'union_mode': u'INDEPENDENT', u'timestamp_config': {u'time_source': u'LOCAL'}, u'fan_failure_count': 0, u'web_api_config': {u'enabled': True, u'port': 9000, u'token_timeout': {u'value': 10, u'unit': u'MIN'}}, u'session_timeout_interval': 0,1856 <snip>1857 """1858 return self._callServer('GET', '/api/system')1859 def getSystemProperties(self, properties):1860 """ getSystemProperties :1861 Fetch one or more systen properties.1862 Sample usage:1863 >>> nto.getSystemProperties('snmp_config,dns_config')1864 {u'dns_config': {u'suffix1': None, u'suffix2': None, u'primary_server': None, u'alt_server': None}, u'snmp_config': {u'trap_recipients': [{u'remote_user': None, u'traps': [u'COLD_START', u'WARM_START', u'LINK_UP_DOWN', u'TEST_NOTIFICATION'], u'retry_count': 1, u'host': {u'value': u'155.174.7.97'}, u'version': u'V2', u'community_string': u'V2/155.174.7.97:162', u'timeout': 5, u'port': 162}], u'refresh_time': 1, u'gets_enabled': True, u'traps_enabled': True, u'get_access': [{u'version': u'V2', u'community_string': u'AnueComm4ATSro', u'local_user': None}]}}1865 """1866 return self._callServer('GET', '/api/system?properties=' + properties)1867 def getSystemProperty(self, property):1868 """ getSystemProperty :1869 Fetch a systen property.1870 1871 Sample usage:1872 >>> nto.getSystemProperty('snmp_config')1873 {u'trap_recipients': [{u'remote_user': None, u'traps': [u'COLD_START', u'WARM_START', u'LINK_UP_DOWN', u'TEST_NOTIFICATION'], u'retry_count': 1, u'host': {u'value': u'155.174.7.97'}, u'version': u'V2', u'community_string': u'V2/155.174.7.97:162', u'timeout': 5, u'port': 162}], u'refresh_time': 1, u'gets_enabled': True, u'traps_enabled': True, u'get_access': [{u'version': u'V2', u'community_string': u'AnueComm4ATSro', u'local_user': None}]}1874 """1875 return self._callServer('GET', '/api/system?properties=' + property)[property]1876 def modifySystem(self, argsAPI):1877 """ modifySystem :1878 Update the system properties.1879 Sample usage:1880 >>> nto.modifySystem({'system_info': {u'location': 'Austin', u'name': 'The Big Box'}})1881 ''1882 """1883 return self._callServer('PUT', '/api/system', argsAPI, False)1884 def modifySpecificSystem(self, system_id, argsAPI):1885 """ modifySpecificSystem :1886 Update the properties of the system specified.1887 1888 Sample usage:1889 >>> nto.modifySystem({'system_info': {u'location': 'Austin', u'name': 'The Big Box'}})1890 ''1891 """1892 return self._callServer('PUT', '/api/system/' + system_id, argsAPI, False)1893 ####################################1894 # Users1895 ####################################1896 def getAllUsers(self):1897 """ getAllUsers :1898 Fetch a list containing the summaries for all the users in the system, or1899 if a user ID is specified, fetch the properties of that user object.1900 Sample usage:1901 >>> nto.getAllUsers()1902 [{u'id': 56, u'name': u'admin'}, {u'id': 52, u'name': u'tcl'}]1903 """1904 return self._callServer('GET', '/api/users')1905 def getUser(self, user):1906 """ getUser :1907 Fetch a list containing the summaries for all the users in the system, or1908 if a user ID is specified, fetch the properties of that user object.1909 Sample usage:1910 >>> nto.getUser('tcl')1911 {u'login_id': u'tcl', u'session_type': None, u'created': {u'type': u'CREATE', u'caused_by': u'admin', u'details': None, u'time': 1442436968401}, u'is_sysadm': True, u'phone': u'867-53009', u'email': u'tcl@nto.com', u'mod_count': 0, u'is_logged_in': False, u'full_name': u'tcl', u'authentication_mode': u'LOCAL', u'id': 52, u'history': []}1912 """1913 return self._callServer('GET', '/api/users/' + user)1914 def changePasswordUser(self, user_id, argsAPI):1915 """ changePasswordUser :1916 Change the user password.1917 Sample usage:1918 >>> nto.changePasswordUser('tcl1', {'new_password' : 'tcl1', 'old_password' : 'fredMota@123'})1919 ''1920 """1921 return self._callServer('PUT', '/api/users/' + user_id + '/change_password', argsAPI, False)1922 def createUser(self, argsAPI):1923 """ createUser :1924 Create a new user.1925 Sample usage:1926 >>> nto.createUser({'login_id': 'oper', 'is_sysadm': False, 'password': 'oper'})1927 {u'id': u'54'}1928 """1929 return self._callServer('POST', '/api/users', argsAPI)1930 def modifyUser(self, user_id, argsAPI):1931 """ modifyUser :1932 Update the properties of an existing user.1933 Sample usage:1934 >>> nto.modifyUser('oper', {'password': '***'})1935 ''1936 """1937 return self._callServer('PUT', '/api/users/' + user_id, argsAPI, False)1938 def deleteUser(self, user_id):1939 """ deleteUser :1940 Remove a user from the system. The user is specified by an user_id.1941 Sample usage:1942 >>> nto.deleteUser('54')1943 ''1944 """1945 return self._callServer('DELETE', '/api/users/' + user_id, None, False)1946 def searchUsers(self, argsAPI):1947 """ searchUsers :1948 Search a specific user from the system by certain properties.1949 Sample usage:1950 >>> nto.searchUsers({'is_sysadm': False})1951 [{u'id': 54, u'name': u'oper'}]1952 """1953 return self._callServer('POST', '/api/users/search', argsAPI)1954 ####################################1955 # Search1956 ####################################1957 def search(self, entity_type, argsAPI):1958 """ search :1959 Search an entity.1960 Sample usage:1961 >>> nto.search('port_groups', {'mode': 'NETWORK'})1962 [{u'id': 94, u'name': u'GSC Network Ports PB09-PB16'}, {u'id': 92, u'name': u'GSC Network Ports PB01-PB08'}, {u'id': 91, u'name': u'GSC Network Ports PA01-PA08'}, {u'id': 95, u'name': u'GSC Network Ports PA09-PA16'}]1963 """...
classes.py
Source:classes.py
...15 '''Client connection to a PDS Registry Server.'''16 def __init__(self, url):17 '''Initialize a registry client with the ``url`` to the server.'''18 self.url = url19 def _callServer(self, path='', params=None, json=None, method='GET'):20 ''''''21 url = self.url + path + (u'?' + urlencode(params) if params else u'')22 request = Request(url, data=None, headers=_standardHeaders)23 request.get_method = lambda: method24 if json:25 assert method != 'GET'26 request.add_data(json)27 request.add_header(u'Content-type', 'application/json')28 request.add_header(u'Content-length', unicode(len(json)))29 with closing(urlopen(request)) as f:30 return anyjson.deserialize(f.read()) if method == 'GET' else None31 def _createSlots(self, s):32 '''Create a set of Slots from the given post-JSON-quantized sequence ``s``.'''33 return set([Slot(i['name'], i['values'], i.get('slotType', None)) for i in s])34 def _createSpecificationLinks(self, serviceBindingGUID, s):35 '''Create a set of SpecificationLinks from the ginve post-JSON-quantized sequence ``s`` that36 belong to the ServiceBinding with GUID ``serviceBindingGUID``.'''37 return set([SpecificationLink(38 guid=d['guid'],39 lid=d.get('lid', None),40 serviceBinding=serviceBindingGUID,41 specificationObject=d['specificationObject'],42 home=d.get('home', None),43 slots=self._createSlots(d.get('slots', [])),44 name=d['name'],45 status=d.get('status', None),46 description=d.get('description', None),47 versionName=d.get('versionName', None),48 usageDescription=d.get('usageDescription', None),49 usageParameters=d.get('usageParameters', [])50 ) for d in s])51 def _createServiceBindings(self, serviceGUID, s):52 '''Create a set of ServiceBindings from the given post-JSON-quantized sequence ``s`` that53 belong to the Service with GUID ``serviceGUID``.'''54 return set([ServiceBinding(55 guid=d['guid'],56 lid=d.get('lid', None),57 service=serviceGUID,58 home=d.get('home', None),59 slots=self._createSlots(d.get('slots', [])),60 name=d['name'],61 status=d.get('status', None),62 description=d.get('description', None),63 versionName=d.get('versionName', None),64 accessURI=d['accessURI'],65 specificationLinks=self._createSpecificationLinks(d['guid'], d.get('specificationLinks', [])),66 targetBinding=d.get('targetBinding', None)67 ) for d in s])68 def _createExtrinsic(self, d):69 '''Create an extrinsic from a post-JSON-quantized dictionary ``d``.'''70 return ExtrinsicObject(71 contentVersion=d.get('contentVersion', None),72 description=d.get('description', None),73 guid=d['guid'],74 home=d['home'],75 lid=d['lid'],76 mimeType=d.get('mimeType', None),77 name=d['name'],78 objectType=d.get('objectType', None),79 slots=self._createSlots(d.get('slots', [])),80 status=d.get('status', None),81 versionName=d.get('versionName', None),82 )83 def _createService(self, d):84 '''Create a service from a post-JSON-quantized dictionary ``d``.'''85 if 'objectType' not in d: raise ValueError('No "objectType"')86 if d['objectType'] != 'Service': raise ValueError('Expected a "Service" but got "%s"' % d['objectType'])87 serviceGUID = d['guid']88 return Service(89 guid=serviceGUID,90 lid=d['lid'],91 home=d['home'],92 slots=self._createSlots(d.get('slots', [])),93 name=d['name'],94 status=d.get('status', None),95 description=d.get('description', None),96 versionName=d.get('versionName', None),97 serviceBindings=self._createServiceBindings(serviceGUID, d.get('serviceBindings', []))98 )99 def _createAssociation(self, d):100 '''Create an Association from a post-JSON-quantized dictionary ``d``.'''101 if 'objectType' not in d: raise ValueError('No "objectType"')102 if d['objectType'] != 'Association': raise ValueError('Expected an "Assocation" but got "%s"' % d['objectType'])103 associationGUID = d['guid']104 return Association(105 guid=associationGUID,106 lid=d['lid'],107 home=d['home'],108 slots=self._createSlots(d.get('slots', [])),109 name=d['name'],110 status=d.get('status', None),111 description=d.get('description', None),112 versionName=d.get('versionName', None),113 source=d.get('sourceObject', None),114 target=d.get('targetObject', None),115 associationType=d.get('associationType', None)116 )117 def _mapSlots(self, slots):118 '''Map a set of Slots into a structure acceptable to JSON.119 '''120 return [dict(name=i.name, slotType=i.slotType, values=i.values) for i in slots]121 def _mapSpecificationLinks(self, links):122 '''Map a set of SpecificationLinks into a structure acceptable to JSON'''123 return [{124 'description': i.description,125 'guid': i.guid,126 'home': i.home,127 'lid': i.lid,128 'name': i.name,129 'objectType': i.objectType,130 'serviceBinding': i.serviceBinding,131 'slots': self._mapSlots(i.slots),132 'specificationObject': i.specificationObject,133 'usageDescription': i.usageDescription,134 'usageParameters': i.usageParameters,135 'versionName': i.versionName,136 } for i in links]137 def _mapServiceBindings(self, bindings):138 '''Map a set of ServiceBindings into a structure acceptable to JSON'''139 return [{140 'accessURI': i.accessURI,141 'description': i.description,142 'guid': i.guid,143 'home': i.home,144 'lid': i.lid,145 'name': i.name,146 'objectType': i.objectType,147 'service': i.service,148 'slots': self._mapSlots(i.slots),149 'specificationLinks': self._mapSpecificationLinks(i.specificationLinks),150 'versionName': i.versionName,151 } for i in bindings]152 def _serializeExtrinsic(self, extrinsic):153 '''Serialize an ExtrinsicObject into JSON.'''154 return anyjson.serialize({155 'contentVersion': extrinsic.contentVersion,156 'description': extrinsic.description,157 'guid': extrinsic.guid,158 'home': extrinsic.home,159 'lid': extrinsic.lid,160 'mimeType': extrinsic.mimeType,161 'name': extrinsic.name,162 'objectType': extrinsic.objectType,163 'slots': self._mapSlots(extrinsic.slots),164 'versionName': extrinsic.versionName,165 })166 def _serializeService(self, service):167 '''Serialize a Service into JSON.'''168 return anyjson.serialize({169 'description': service.description,170 'guid': service.guid,171 'home': service.home,172 'lid': service.lid,173 'name': service.name,174 'objectType': service.objectType,175 'serviceBindings': self._mapServiceBindings(service.serviceBindings),176 'slots': self._mapSlots(service.slots),177 'versionName': service.versionName,178 })179 def _serializeAssociation(self, association):180 '''Serialize an Association into JSON.'''181 return anyjson.serialize({182 'associationType': association.associationType,183 'description': association.description,184 'guid': association.guid,185 'home': association.home,186 'lid': association.lid,187 'name': association.name,188 'objectType': association.objectType,189 'slots': self._mapSlots(association.slots),190 'sourceObject': association.source,191 'targetObject': association.target,192 'versionName': association.versionName,193 })194 def getServices(self, start=0, rows=20):195 '''Retrieve services registered with the registry service, starting at index ``start`` in the196 services list and retrieving no more than ``rows`` worth.197 198 >>> import pds.registry.net.tests.base199 >>> rs = PDSRegistryClient('testscheme:/rs')200 >>> services = rs.getServices()201 >>> len(services)202 3203 >>> services[0].guid, services[1].guid, services[2].guid204 (u'urn:sk:radio:lush:2.1', u'urn:sk:services:insults:0', u'urn:uuid:0f142be7-e4ab-4495-8a03-aa926ffcc5d3')205 >>> services = rs.getServices(1, 1)206 >>> len(services)207 1208 >>> services[0].guid209 u'urn:sk:services:insults:0'210 '''211 answer = self._callServer('/services', dict(start=start+1, rows=rows)) # Why is it one-based indexing? Lame.212 return [self._createService(i) for i in answer.get('results', [])]213 def getExtrinsics(self, start=0, rows=20):214 '''Retrieve extrinsics registered with the registry service, starting at index ``start`` in the215 services list and retrieving no more than ``rows`` worth.216 217 >>> import pds.registry.net.tests.base218 >>> rs = PDSRegistryClient('testscheme:/rs')219 >>> extrinsics = rs.getExtrinsics()220 >>> len(extrinsics)221 3222 >>> extrinsics[0].guid, extrinsics[1].guid, extrinsics[2].guid223 (u'egg-1.0', u'spam-1.0', u'bacon-1.0')224 >>> extrinsics = rs.getExtrinsics(1, 1)225 >>> len(extrinsics)226 1227 >>> extrinsics[0].guid228 u'spam-1.0'229 '''230 answer = self._callServer('/extrinsics', dict(start=start+1, rows=rows)) # Why is it one-based indexing? Lame.231 return [self._createExtrinsic(i) for i in answer.get('results', [])]232 def getAssociations(self, start=0, rows=20):233 '''Retrieve associations registered with the registry service, starting at index ``start`` in234 the associations list and retrieving no more than ``rows`` worth.235 >>> import pds.registry.net.tests.base236 >>> rs = PDSRegistryClient('testscheme:/rs')237 >>> associations = rs.getAssociations()238 >>> len(associations)239 3240 >>> associations[0].guid, associations[1].guid, associations[2].guid241 (u'urn:anatomyid:ass', u'urn:anatomyid:but', u'urn:anatomyid:boo')242 >>> associations = rs.getAssociations(1, 1)243 >>> len(associations)244 1245 >>> associations[0].guid246 u'urn:anatomyid:but'247 '''248 answer = self._callServer('/associations', dict(start=start+1, rows=rows)) # Why is it one-based indexing? Lame.249 return [self._createAssociation(i) for i in answer.get('results', [])]250 def getExtrinsicByLidvid(self, lidvid):251 '''Retrieve an extrinsic given a ``lidvid``, which is a string of the form ``LOGICAL-ID::VERSION-NAME``.252 >>> rs = PDSRegistryClient('testscheme:/rs')253 >>> extrinsic = rs.getExtrinsicByLidvid('bacon::1.0')254 >>> extrinsic.lid, extrinsic.versionName255 (u'bacon', u'1.0')256 '''257 lid, vid = lidvid.split('::')258 answer = self._callServer('/extrinsics', dict(lid=lid, versionName=vid))259 if answer.get('numFound', 0) == 0:260 return None261 return self._createExtrinsic(answer['results'][0])262 def getService(self, guid):263 '''Retrieve a service with a known ``guid``, or None if ``guid`` is not found.264 265 >>> import pds.registry.net.tests.base266 >>> rs = PDSRegistryClient('testscheme:/rs')267 >>> lush = rs.getService('urn:sk:radio:lush')268 >>> lush.guid, lush.home, lush.lid269 (u'urn:sk:radio:lush:2.1', u'http://localhost:8080/registry-service', u'urn:uuid:0b2aebc3-dde7-4453-901d-9b3f9660dfc2')270 >>> lush.versionName, lush.objectType271 (u'1.0', 'Service')272 >>> lush.name ,lush.description273 (u'Lush Radio Service', u'Provides live streams for tuning the Lush radio station at Soma FM.')274 >>> len(lush.slots)275 2276 >>> slots = list(lush.slots); slots.sort(); [(i.name, i.values) for i in slots]277 [(u'genres', [u'chillout', u'vocal trance', u'chillout dreams']), (u'max-bpm', [u'90'])]278 >>> len(lush.serviceBindings)279 2280 >>> bindings = list(lush.serviceBindings); bindings.sort(); binding = bindings[1]281 >>> binding.accessURI, binding.name, binding.description282 (u'http://somafm.com/play/lush/mp3', u'128k MP3 Lush Stream', u'The main Lush stream (and hence the most popular).')283 >>> binding.guid, binding.objectType284 (u'urn:uuid:c400fc6e-c9a5-428c-adbf-6cd8f2237cc3', 'ServiceBinding')285 >>> len(binding.slots)286 1287 >>> slot = iter(binding.slots).next()288 >>> slot.name, slot.values289 (u'comment', [u'Gah, MP3 is 20 years old. Use AAC+!'])290 >>> len(binding.specificationLinks)291 1292 >>> sl = iter(binding.specificationLinks).next()293 >>> sl.name, sl.description, sl.specificationObject294 (u'RSTP', u'Real Time Streaming Protocol', u'urn:ietf:rfc:2326')295 >>> sl.objectType, sl.guid296 ('SpecificationLink', u'urn:uuid:5de615ab-242d-463d-b0dc-1f6efeaae0ee')297 >>> unknown = rs.getService('urn:this:does:not:exist')298 >>> unknown is None299 True300 '''301 try:302 answer = self._callServer('/services/%s' % guid)303 if 'Service' != answer.get('objectType', None): return None304 return self._createService(answer)305 except HTTPError, ex:306 if ex.code == httplib.NOT_FOUND:307 return None308 else:309 raise ex310 def getAssociation(self, guid):311 '''Retrieve an association with a known ``guid``, or None if ``guid`` is not found.312 313 >>> import pds.registry.net.tests.base314 >>> rs = PDSRegistryClient('testscheme:/rs')315 >>> ass = rs.getAssociation('urn:anatomyid:ass')316 >>> ass.guid, ass.lid, ass.name317 (u'urn:anatomyid:ass', u'ass1', u'ass')318 >>> ass.status, ass.description, ass.versionName319 (u'Probed', u'This is the rear association', u'1.0')320 >>> ass.source, ass.target321 (u'urn:uuid:8007636f-adcd-416e-a75b-e954814bd953', u'urn:uuid:2cdad332-f667-4e8b-814a-4b67624c4e2a')322 >>> ass.associationType, ass.objectType323 (u'urn:registry:AssociationType:HasRear', 'Association')324 >>> len(ass.slots)325 1326 >>> slot = ass.slots.pop()327 >>> slot.name, slot.values328 (u'targetObjectType', [u'ExtrinsicObject'])329 '''330 try:331 answer = self._callServer('/associations/%s' % guid)332 if 'Association' != answer.get('objectType', None): return None333 return self._createAssociation(answer)334 except HTTPError, ex:335 if ex.code == httplib.NOT_FOUND:336 return None337 else:338 raise ex339 def getExtrinsicByLID(self, lid, earliest=False):340 '''Retrieve an extrinsic by its logical identifier, ``lid``; by default the latest version341 is returned, if found. To get the earliest version, set ``earliest`` to True.342 343 >>> import pds.registry.net.tests.base344 >>> rs = PDSRegistryClient('testscheme:/rs')345 >>> ext = rs.getExtrinsicByLID('egg')346 >>> ext.guid, ext.home, ext.lid347 (u'egg-1.0', u'http://localhost:5634/registry', u'egg')348 >>> ext.versionName, ext.objectType349 (u'1.0', u'Product')350 >>> ext.name, ext.description351 (u'Egg v1.0', u'You usually have egg with bacon or with spam.')352 >>> ext.contentVersion, ext.mimeType353 (u'88.88', u'x-application/albumin')354 >>> len(ext.slots)355 2356 >>> slots = list(ext.slots); slots.sort(); [(i.name, i.values) for i in slots]357 [(u'preparation', [u'scrambled', u'poached']), (u'seasoning', [u'salt', u'pepper', u'hot sauce'])]358 >>> ext2 = rs.getExtrinsicByLID('egg', earliest=True)359 >>> ext == ext2360 True361 >>> unknown = rs.getExtrinsicByLID('non-exisitent')362 >>> unknown is None363 True364 '''365 try:366 # Registry Service is bizarrely inconsistent. Retrieving an extrinsic by guid, or by lid/earliest,367 # or by lid/latest, gives back a JSON dict that represents the extrinsic. However, retrieving just368 # by lid (without /earliest or /latest) returns a JSON dict with 'start' set to null, "numFound" set369 # to null, and a one-item sequence "results" that contains the extrinsic.370 if earliest:371 answer = self._callServer(u'/extrinsics/logicals/{}/earliest'.format(lid))372 else:373 answer = self._callServer(u'/extrinsics/logicals/{}'.format(lid))374 answer = answer['results'][0]375 return self._createExtrinsic(answer)376 except HTTPError, ex:377 if ex.code == httplib.NOT_FOUND:378 return None379 else:380 raise ex381 def getExtrinsic(self, guid):382 '''Retrieve an extrinsic with a known ``guid``, or None if ``guid`` is not found.383 384 >>> import pds.registry.net.tests.base385 >>> rs = PDSRegistryClient('testscheme:/rs')386 >>> ext = rs.getExtrinsic('egg-1.0')387 >>> ext.guid, ext.home, ext.lid388 (u'egg-1.0', u'http://localhost:5634/registry', u'egg')389 >>> ext.versionName, ext.objectType390 (u'1.0', u'Product')391 >>> ext.name, ext.description392 (u'Egg v1.0', u'You usually have egg with bacon or with spam.')393 >>> ext.contentVersion, ext.mimeType394 (u'88.88', u'x-application/albumin')395 >>> len(ext.slots)396 2397 >>> slots = list(ext.slots); slots.sort(); [(i.name, i.values) for i in slots]398 [(u'preparation', [u'scrambled', u'poached']), (u'seasoning', [u'salt', u'pepper', u'hot sauce'])]399 >>> unknown = rs.getExtrinsic('non-exisitent-1.0')400 >>> unknown is None401 True402 '''403 try:404 answer = self._callServer('/extrinsics/%s' % guid)405 return self._createExtrinsic(answer)406 except HTTPError, ex:407 if ex.code == httplib.NOT_FOUND:408 return None409 else:410 raise ex411 def putService(self, service):412 '''Send Service ``service`` into the Registry.413 414 >>> import pds.registry.net.tests.base415 >>> from pds.registry.model.classes import Service416 >>> rs = PDSRegistryClient('testscheme:/rs')417 >>> service = Service(u'urn:services:new-service', u'urn:services:new-service', u'testscheme:/rs', set(), u'New Service')418 >>> rs.putService(service)419 >>> service = Service(u'urn:sk:radio:lush', u'urn:sk:radio:lush', u'testscheme:/rs', set(), u'Lush Radio Service')420 >>> rs.putService(service)421 '''422 # If it doesn't exist, POST to the /services path, but if it does exist, PUT to423 # the existing /services/guid path. FIXME: Yes, there is a race here.424 json = self._serializeService(service)425 existing = self.getService(service.guid)426 if existing:427 self._callServer('/services/%s' % service.guid, params=None, json=json, method='PUT')428 else:429 self._callServer('/services', params=None, json=json, method='POST')430 def putExtrinsic(self, extrinsic):431 '''Send ExtrinsicObject ``extrinsic`` into the Registry.432 433 >>> import pds.registry.net.tests.base434 >>> from pds.registry.model.classes import ExtrinsicObject435 >>> rs = PDSRegistryClient('testscheme:/rs')436 >>> ext = ExtrinsicObject(u'egg-1.0', u'egg', u'testscheme:/rs', set(), u'New Egg', u'Approved', u'Freshly laid', u'1.0',437 ... u'79.99', u'x-application/breakfast')438 >>> rs.putExtrinsic(ext)439 >>> ext = ExtrinsicObject(u'spam-1.0', u'spam', u'testscheme:/rs', set(), u'Spam')440 >>> rs.putExtrinsic(ext)441 '''442 # If the extrinsic doesn't exist, POST it to /extrinsics; but if it does exist, POST443 # it to the existing /extrinsics/logicals/lid path. FIXME: Yes, there is a race here.444 json = self._serializeExtrinsic(extrinsic)445 existing = self.getExtrinsicByLID(extrinsic.lid)446 if existing:447 self._callServer(u'/extrinsics/logicals/{}'.format(extrinsic.lid), params=None, json=json, method='POST')448 else:449 self._callServer(u'/extrinsics', params=None, json=json, method='POST')450 def putAssociation(self, association):451 '''Send the Association object ``association`` into the Registry.452 >>> import pds.registry.net.tests.base453 >>> from pds.registry.model.classes import Association454 >>> rs = PDSRegistryClient('testscheme:/rs')455 >>> ass = Association(u'ass-1', u'ass', u'testscheme:/rs', set(), u'ass', u'Probed', u'Assoc', u'1.0', u'rec', u'anu', 'urn:con')456 >>> rs.putAssociation(ass)457 >>> ass = Association(u'urn:anatomyid:ass', 'ass')458 >>> rs.putAssociation(ass)459 '''460 # If the association doesn't exist, POST it to /associations; but if it does exist, PUT461 # it to the existing /associations/guid path. FIXME: Yes, there is a race here.462 json = self._serializeAssociation(association)463 existing = self.getAssociation(association.guid)464 if existing:465 self._callServer('/associations/%s' % association.guid, params=None, json=json, method='PUT')466 else:467 self._callServer('/associations', params=None, json=json, method='POST')468 def deleteService(self, serviceGUID):469 '''Delete the service with UUID ``serviceGUID`` from the Registry.470 471 >>> import pds.registry.net.tests.base472 >>> rs = PDSRegistryClient('testscheme:/rs')473 >>> rs.deleteService('urn:sk:radio:lush')474 '''475 self._callServer('/services/%s' % serviceGUID, params=None, json=None, method='DELETE')476 def deleteExtrinsic(self, extrinsicGUID):477 '''Delete the extrinsic with UUID ``extrinsicGUID`` from the Registry.478 479 >>> import pds.registry.net.tests.base480 >>> rs = PDSRegistryClient('testscheme:/rs')481 >>> rs.deleteExtrinsic('egg-1.0')482 '''483 self._callServer('/extrinsics/%s' % extrinsicGUID, params=None, json=None, method='DELETE')484 def deleteAssocation(self, associationGUID):485 '''Delete the association with the UUID ``associationGUID`` from the Registry.486 >>> import pds.registry.net.tests.base487 >>> rs = PDSRegistryClient('testscheme:/rs')488 >>> rs.deleteAssocation('urn:anatomyid:ass')489 '''490 self._callServer('/associations/%s' % associationGUID, params=None, json=None, method='DELETE')491# Demonstration with actual PDS Registry Service:492def main():493 c = PDSRegistryClient('http://localhost:8080/registry')494 serviceSlots = set([Slot('bpm', ['140'], 'int'), Slot('genre', ['goa', 'psy'], 'enum')])495 bindingSlots = set([Slot('strength', ['strong'])])496 linkSlots = set([Slot('broken', ['true'], 'bool'), Slot('with-icon', ['false', 'maybe'], 'huh?')])497 service = Service('urn:sk:global:guid:1', 'urn:sk:logical:1', 'http://localhost:8080/registry-service', serviceSlots, 'T.H.E. SERVICE', 'submitted', 'It is indeed THE service.', 'One Point Oh Point One')498 binding = ServiceBinding('urn:sk:global:guid:1:1', 'http://endpoint.com/', service.guid, service.home, bindingSlots, 'T.H.E. BINDING', 'submitted', 'It is quite the binding.', 'Two Point Oh Point Oh', 'http://endpoint.com/')499 link = SpecificationLink('urn:sk:global:guid:1:1:1', 'urn:sk:logical:link:1', binding.guid, 'urn:ietf:rfc:1136', service.home, linkSlots, 'T.H.E. Specification', 'submitted', 'Woo woo', 'Three', 'Use it wisely', ['or', 'not'])500 binding.specificationLinks.add(link)501 service.serviceBindings.add(binding)502 c.putService(service)503 c.deleteService(service.guid)504if __name__ == '__main__':...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!