1# Licensed to the Apache Software Foundation (ASF) under one or more 2# contributor license agreements. See the NOTICE file distributed with 3# this work for additional information regarding copyright ownership. 4# The ASF licenses this file to You under the Apache License, Version 2.0 5# (the "License"); you may not use this file except in compliance with 6# the License. You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15""" 16Dimension Data Common Components 17""" 18from base64 import b64encode 19from time import sleep 20# TODO: use disutils.version when Travis CI fixed the pylint issue with version 21# from distutils.version import LooseVersion 22from libcloud.utils.py3 import httplib 23from libcloud.utils.py3 import b 24from libcloud.common.base import ConnectionUserAndKey, XmlResponse, RawResponse 25from libcloud.compute.base import Node 26from libcloud.utils.py3 import basestring 27from libcloud.utils.xml import findtext 28from libcloud.compute.types import LibcloudError, InvalidCredsError 29 30# Roadmap / TODO: 31# 32# 1.0 - Copied from OpSource API, named provider details. 33 34# setup a few variables to represent all of the DimensionData cloud namespaces 35NAMESPACE_BASE = "http://oec.api.opsource.net/schemas" 36ORGANIZATION_NS = NAMESPACE_BASE + "/organization" 37SERVER_NS = NAMESPACE_BASE + "/server" 38NETWORK_NS = NAMESPACE_BASE + "/network" 39DIRECTORY_NS = NAMESPACE_BASE + "/directory" 40GENERAL_NS = NAMESPACE_BASE + "/general" 41BACKUP_NS = NAMESPACE_BASE + "/backup" 42 43# API 2.0 Namespaces and URNs 44TYPES_URN = "urn:didata.com:api:cloud:types" 45 46# API end-points 47API_ENDPOINTS = { 48 'dd-na': { 49 'name': 'North America (NA)', 50 'host': 'api-na.dimensiondata.com', 51 'vendor': 'DimensionData' 52 }, 53 'dd-eu': { 54 'name': 'Europe (EU)', 55 'host': 'api-eu.dimensiondata.com', 56 'vendor': 'DimensionData' 57 }, 58 'dd-au': { 59 'name': 'Australia (AU)', 60 'host': 'api-au.dimensiondata.com', 61 'vendor': 'DimensionData' 62 }, 63 'dd-au-gov': { 64 'name': 'Australia Canberra ACT (AU)', 65 'host': 'api-canberra.dimensiondata.com', 66 'vendor': 'DimensionData' 67 }, 68 'dd-af': { 69 'name': 'Africa (AF)', 70 'host': 'api-mea.dimensiondata.com', 71 'vendor': 'DimensionData' 72 }, 73 'dd-ap': { 74 'name': 'Asia Pacific (AP)', 75 'host': 'api-ap.dimensiondata.com', 76 'vendor': 'DimensionData' 77 }, 78 'dd-latam': { 79 'name': 'South America (LATAM)', 80 'host': 'api-latam.dimensiondata.com', 81 'vendor': 'DimensionData' 82 }, 83 'dd-canada': { 84 'name': 'Canada (CA)', 85 'host': 'api-canada.dimensiondata.com', 86 'vendor': 'DimensionData' 87 }, 88 'is-na': { 89 'name': 'North America (NA)', 90 'host': 'usapi.cloud.is.co.za', 91 'vendor': 'InternetSolutions' 92 }, 93 'is-eu': { 94 'name': 'Europe (EU)', 95 'host': 'euapi.cloud.is.co.za', 96 'vendor': 'InternetSolutions' 97 }, 98 'is-au': { 99 'name': 'Australia (AU)', 100 'host': 'auapi.cloud.is.co.za', 101 'vendor': 'InternetSolutions' 102 }, 103 'is-af': { 104 'name': 'Africa (AF)', 105 'host': 'meaapi.cloud.is.co.za', 106 'vendor': 'InternetSolutions' 107 }, 108 'is-ap': { 109 'name': 'Asia Pacific (AP)', 110 'host': 'apapi.cloud.is.co.za', 111 'vendor': 'InternetSolutions' 112 }, 113 'is-latam': { 114 'name': 'South America (LATAM)', 115 'host': 'latamapi.cloud.is.co.za', 116 'vendor': 'InternetSolutions' 117 }, 118 'is-canada': { 119 'name': 'Canada (CA)', 120 'host': 'canadaapi.cloud.is.co.za', 121 'vendor': 'InternetSolutions' 122 }, 123 'ntta-na': { 124 'name': 'North America (NA)', 125 'host': 'cloudapi.nttamerica.com', 126 'vendor': 'NTTNorthAmerica' 127 }, 128 'ntta-eu': { 129 'name': 'Europe (EU)', 130 'host': 'eucloudapi.nttamerica.com', 131 'vendor': 'NTTNorthAmerica' 132 }, 133 'ntta-au': { 134 'name': 'Australia (AU)', 135 'host': 'aucloudapi.nttamerica.com', 136 'vendor': 'NTTNorthAmerica' 137 }, 138 'ntta-af': { 139 'name': 'Africa (AF)', 140 'host': 'sacloudapi.nttamerica.com', 141 'vendor': 'NTTNorthAmerica' 142 }, 143 'ntta-ap': { 144 'name': 'Asia Pacific (AP)', 145 'host': 'hkcloudapi.nttamerica.com', 146 'vendor': 'NTTNorthAmerica' 147 }, 148 'cisco-na': { 149 'name': 'North America (NA)', 150 'host': 'iaas-api-na.cisco-ccs.com', 151 'vendor': 'Cisco' 152 }, 153 'cisco-eu': { 154 'name': 'Europe (EU)', 155 'host': 'iaas-api-eu.cisco-ccs.com', 156 'vendor': 'Cisco' 157 }, 158 'cisco-au': { 159 'name': 'Australia (AU)', 160 'host': 'iaas-api-au.cisco-ccs.com', 161 'vendor': 'Cisco' 162 }, 163 'cisco-af': { 164 'name': 'Africa (AF)', 165 'host': 'iaas-api-mea.cisco-ccs.com', 166 'vendor': 'Cisco' 167 }, 168 'cisco-ap': { 169 'name': 'Asia Pacific (AP)', 170 'host': 'iaas-api-ap.cisco-ccs.com', 171 'vendor': 'Cisco' 172 }, 173 'cisco-latam': { 174 'name': 'South America (LATAM)', 175 'host': 'iaas-api-sa.cisco-ccs.com', 176 'vendor': 'Cisco' 177 }, 178 'cisco-canada': { 179 'name': 'Canada (CA)', 180 'host': 'iaas-api-ca.cisco-ccs.com', 181 'vendor': 'Cisco' 182 }, 183 'med1-il': { 184 'name': 'Israel (IL)', 185 'host': 'api.cloud.med-1.com', 186 'vendor': 'Med-1' 187 }, 188 'med1-na': { 189 'name': 'North America (NA)', 190 'host': 'api-na.cloud.med-1.com', 191 'vendor': 'Med-1' 192 }, 193 'med1-eu': { 194 'name': 'Europe (EU)', 195 'host': 'api-eu.cloud.med-1.com', 196 'vendor': 'Med-1' 197 }, 198 'med1-au': { 199 'name': 'Australia (AU)', 200 'host': 'api-au.cloud.med-1.com', 201 'vendor': 'Med-1' 202 }, 203 'med1-af': { 204 'name': 'Africa (AF)', 205 'host': 'api-af.cloud.med-1.com', 206 'vendor': 'Med-1' 207 }, 208 'med1-ap': { 209 'name': 'Asia Pacific (AP)', 210 'host': 'api-ap.cloud.med-1.com', 211 'vendor': 'Med-1' 212 }, 213 'med1-latam': { 214 'name': 'South America (LATAM)', 215 'host': 'api-sa.cloud.med-1.com', 216 'vendor': 'Med-1' 217 }, 218 'med1-canada': { 219 'name': 'Canada (CA)', 220 'host': 'api-ca.cloud.med-1.com', 221 'vendor': 'Med-1' 222 }, 223 'indosat-id': { 224 'name': 'Indonesia (ID)', 225 'host': 'iaas-api.indosat.com', 226 'vendor': 'Indosat' 227 }, 228 'indosat-na': { 229 'name': 'North America (NA)', 230 'host': 'iaas-usapi.indosat.com', 231 'vendor': 'Indosat' 232 }, 233 'indosat-eu': { 234 'name': 'Europe (EU)', 235 'host': 'iaas-euapi.indosat.com', 236 'vendor': 'Indosat' 237 }, 238 'indosat-au': { 239 'name': 'Australia (AU)', 240 'host': 'iaas-auapi.indosat.com', 241 'vendor': 'Indosat' 242 }, 243 'indosat-af': { 244 'name': 'Africa (AF)', 245 'host': 'iaas-afapi.indosat.com', 246 'vendor': 'Indosat' 247 }, 248 'bsnl-in': { 249 'name': 'India (IN)', 250 'host': 'api.bsnlcloud.com', 251 'vendor': 'BSNL' 252 }, 253 'bsnl-na': { 254 'name': 'North America (NA)', 255 'host': 'usapi.bsnlcloud.com', 256 'vendor': 'BSNL' 257 }, 258 'bsnl-eu': { 259 'name': 'Europe (EU)', 260 'host': 'euapi.bsnlcloud.com', 261 'vendor': 'BSNL' 262 }, 263 'bsnl-au': { 264 'name': 'Australia (AU)', 265 'host': 'auapi.bsnlcloud.com', 266 'vendor': 'BSNL' 267 }, 268 'bsnl-af': { 269 'name': 'Africa (AF)', 270 'host': 'afapi.bsnlcloud.com', 271 'vendor': 'BSNL' 272 } 273} 274 275# Default API end-point for the base connection class. 276DEFAULT_REGION = 'dd-na' 277 278BAD_CODE_XML_ELEMENTS = ( 279 ('responseCode', SERVER_NS), 280 ('responseCode', TYPES_URN), 281 ('result', GENERAL_NS) 282) 283 284BAD_MESSAGE_XML_ELEMENTS = ( 285 ('message', SERVER_NS), 286 ('message', TYPES_URN), 287 ('resultDetail', GENERAL_NS) 288) 289 290 291def dd_object_to_id(obj, obj_type, id_value='id'): 292 """ 293 Takes in a DD object or string and prints out it's id 294 This is a helper method, as many of our functions can take either an object 295 or a string, and we need an easy way of converting them 296 297 :param obj: The object to get the id for 298 :type obj: ``object`` 299 300 :param func: The function to call, e.g. ex_get_vlan. Note: This 301 function needs to return an object which has ``status`` 302 attribute. 303 :type func: ``function`` 304 305 :rtype: ``str`` 306 """ 307 if isinstance(obj, obj_type): 308 return getattr(obj, id_value) 309 elif isinstance(obj, (basestring)): 310 return obj 311 else: 312 raise TypeError( 313 "Invalid type %s looking for basestring or %s" 314 % (type(obj).__name__, obj_type.__name__) 315 ) 316 317 318# TODO: use disutils.version when Travis CI fixed the pylint issue with version 319# This is a temporary workaround. 320def LooseVersion(version): 321 return float(version) 322 323 324class NetworkDomainServicePlan(object): 325 ESSENTIALS = "ESSENTIALS" 326 ADVANCED = "ADVANCED" 327 328 329class DimensionDataRawResponse(RawResponse): 330 pass 331 332 333class DimensionDataResponse(XmlResponse): 334 def parse_error(self): 335 if self.status == httplib.UNAUTHORIZED: 336 raise InvalidCredsError(self.body) 337 elif self.status == httplib.FORBIDDEN: 338 raise InvalidCredsError(self.body) 339 340 body = self.parse_body() 341 342 if self.status == httplib.BAD_REQUEST: 343 for response_code in BAD_CODE_XML_ELEMENTS: 344 code = findtext(body, response_code[0], response_code[1]) 345 if code is not None: 346 break 347 for message in BAD_MESSAGE_XML_ELEMENTS: 348 message = findtext(body, message[0], message[1]) 349 if message is not None: 350 break 351 raise DimensionDataAPIException(code=code, 352 msg=message, 353 driver=self.connection.driver) 354 if self.status is not httplib.OK: 355 raise DimensionDataAPIException(code=self.status, 356 msg=body, 357 driver=self.connection.driver) 358 359 return self.body 360 361 362class DimensionDataAPIException(LibcloudError): 363 def __init__(self, code, msg, driver): 364 self.code = code 365 self.msg = msg 366 self.driver = driver 367 368 def __str__(self): 369 return "%s: %s" % (self.code, self.msg) 370 371 def __repr__(self): 372 return ("<DimensionDataAPIException: code='%s', msg='%s'>" % 373 (self.code, self.msg)) 374 375 376class DimensionDataConnection(ConnectionUserAndKey): 377 """ 378 Connection class for the DimensionData driver 379 """ 380 381 api_path_version_1 = '/oec' 382 api_path_version_2 = '/caas' 383 api_version_1 = 0.9 384 385 # Earliest version supported 386 oldest_api_version = '2.2' 387 388 # Latest version supported 389 latest_api_version = '2.4' 390 391 # Default api version 392 active_api_version = '2.4' 393 394 _orgId = None 395 responseCls = DimensionDataResponse 396 rawResponseCls = DimensionDataRawResponse 397 398 allow_insecure = False 399 400 def __init__(self, user_id, key, secure=True, host=None, port=None, 401 url=None, timeout=None, proxy_url=None, 402 api_version=None, **conn_kwargs): 403 super(DimensionDataConnection, self).__init__( 404 user_id=user_id, 405 key=key, 406 secure=secure, 407 host=host, port=port, 408 url=url, timeout=timeout, 409 proxy_url=proxy_url) 410 411 if conn_kwargs['region']: 412 self.host = conn_kwargs['region']['host'] 413 414 if api_version: 415 if LooseVersion(api_version) < LooseVersion( 416 self.oldest_api_version): 417 msg = 'API Version specified is too old. No longer ' \ 418 'supported. Please upgrade to the latest version {}' \ 419 .format(self.active_api_version) 420 421 raise DimensionDataAPIException(code=None, 422 msg=msg, 423 driver=self.driver) 424 elif LooseVersion(api_version) > LooseVersion( 425 self.latest_api_version): 426 msg = 'Unsupported API Version. The version specified is ' \ 427 'not release yet. Please use the latest supported ' \ 428 'version {}' \ 429 .format(self.active_api_version) 430 431 raise DimensionDataAPIException(code=None, 432 msg=msg, 433 driver=self.driver) 434 435 else: 436 # Overwrite default version using the version user specified 437 self.active_api_version = api_version 438 439 def add_default_headers(self, headers): 440 headers['Authorization'] = \ 441 ('Basic %s' % b64encode(b('%s:%s' % (self.user_id, 442 self.key))).decode('utf-8')) 443 headers['Content-Type'] = 'application/xml' 444 return headers 445 446 def request_api_1(self, action, params=None, data='', 447 headers=None, method='GET'): 448 action = "%s/%s/%s" % (self.api_path_version_1, 449 self.api_version_1, action) 450 451 return super(DimensionDataConnection, self).request( 452 action=action, 453 params=params, data=data, 454 method=method, headers=headers) 455 456 def request_api_2(self, path, action, params=None, data='', 457 headers=None, method='GET'): 458 action = "%s/%s/%s/%s" % (self.api_path_version_2, 459 self.active_api_version, path, action) 460 461 return super(DimensionDataConnection, self).request( 462 action=action, 463 params=params, data=data, 464 method=method, headers=headers) 465 466 def raw_request_with_orgId_api_1(self, action, params=None, data='', 467 headers=None, method='GET'): 468 action = "%s/%s" % (self.get_resource_path_api_1(), action) 469 return super(DimensionDataConnection, self).request( 470 action=action, 471 params=params, data=data, 472 method=method, headers=headers, raw=True) 473 474 def request_with_orgId_api_1(self, action, params=None, data='', 475 headers=None, method='GET'): 476 action = "%s/%s" % (self.get_resource_path_api_1(), action) 477 478 return super(DimensionDataConnection, self).request( 479 action=action, 480 params=params, data=data, 481 method=method, headers=headers) 482 483 def request_with_orgId_api_2(self, action, params=None, data='', 484 headers=None, method='GET'): 485 action = "%s/%s" % (self.get_resource_path_api_2(), action) 486 487 return super(DimensionDataConnection, self).request( 488 action=action, 489 params=params, data=data, 490 method=method, headers=headers) 491 492 def paginated_request_with_orgId_api_2(self, action, params=None, data='', 493 headers=None, method='GET', 494 page_size=250): 495 """ 496 A paginated request to the MCP2.0 API 497 This essentially calls out to request_with_orgId_api_2 for each page 498 and yields the response to make a generator 499 This generator can be looped through to grab all the pages. 500 501 :param action: The resource to access (i.e. 'network/vlan') 502 :type action: ``str`` 503 504 :param params: Parameters to give to the action 505 :type params: ``dict`` or ``None`` 506 507 :param data: The data payload to be added to the request 508 :type data: ``str`` 509 510 :param headers: Additional header to be added to the request 511 :type headers: ``str`` or ``dict`` or ``None`` 512 513 :param method: HTTP Method for the request (i.e. 'GET', 'POST') 514 :type method: ``str`` 515 516 :param page_size: The size of each page to be returned 517 Note: Max page size in MCP2.0 is currently 250 518 :type page_size: ``int`` 519 """ 520 if params is None: 521 params = {} 522 params['pageSize'] = page_size 523 524 resp = self.request_with_orgId_api_2(action, params, 525 data, headers, 526 method).object 527 yield resp 528 if len(resp) <= 0: 529 return 530 531 pcount = resp.get('pageCount') # pylint: disable=no-member 532 psize = resp.get('pageSize') # pylint: disable=no-member 533 pnumber = resp.get('pageNumber') # pylint: disable=no-member 534 535 while int(pcount) >= int(psize): 536 params['pageNumber'] = int(pnumber) + 1 537 resp = self.request_with_orgId_api_2(action, params, 538 data, headers, 539 method).object 540 pcount = resp.get('pageCount') # pylint: disable=no-member 541 psize = resp.get('pageSize') # pylint: disable=no-member 542 pnumber = resp.get('pageNumber') # pylint: disable=no-member 543 yield resp 544 545 def get_resource_path_api_1(self): 546 """ 547 This method returns a resource path which is necessary for referencing 548 resources that require a full path instead of just an ID, such as 549 networks, and customer snapshots. 550 """ 551 return ("%s/%s/%s" % (self.api_path_version_1, self.api_version_1, 552 self._get_orgId())) 553 554 def get_resource_path_api_2(self): 555 """ 556 This method returns a resource path which is necessary for referencing 557 resources that require a full path instead of just an ID, such as 558 networks, and customer snapshots. 559 """ 560 return ("%s/%s/%s" % (self.api_path_version_2, self.active_api_version, 561 self._get_orgId())) 562 563 def wait_for_state(self, state, func, poll_interval=2, timeout=60, *args, 564 **kwargs): 565 """ 566 Wait for the function which returns a instance with field status/state 567 to match. 568 569 Keep polling func until one of the desired states is matched 570 571 :param state: Either the desired state (`str`) or a `list` of states 572 :type state: ``str`` or ``list`` 573 574 :param func: The function to call, e.g. ex_get_vlan. Note: This 575 function needs to return an object which has ``status`` 576 attribute. 577 :type func: ``function`` 578 579 :param poll_interval: The number of seconds to wait between checks 580 :type poll_interval: `int` 581 582 :param timeout: The total number of seconds to wait to reach a state 583 :type timeout: `int` 584 585 :param args: The arguments for func 586 :type args: Positional arguments 587 588 :param kwargs: The arguments for func 589 :type kwargs: Keyword arguments 590 591 :return: Result from the calling function. 592 """ 593 cnt = 0 594 result = None 595 object_state = None 596 while cnt < timeout / poll_interval: 597 result = func(*args, **kwargs) 598 if isinstance(result, Node): 599 object_state = result.state 600 else: 601 object_state = result.status 602 603 if object_state is state or str(object_state) in state: 604 return result 605 606 sleep(poll_interval) 607 cnt += 1 608 609 msg = 'Status check for object %s timed out' % (result) 610 raise DimensionDataAPIException(code=object_state, 611 msg=msg, 612 driver=self.driver) 613 614 def _get_orgId(self): 615 """ 616 Send the /myaccount API request to DimensionData cloud and parse the 617 'orgId' from the XML response object. We need the orgId to use most 618 of the other API functions 619 """ 620 if self._orgId is None: 621 body = self.request_api_1('myaccount').object 622 self._orgId = findtext(body, 'orgId', DIRECTORY_NS) 623 return self._orgId 624 625 def get_account_details(self): 626 """ 627 Get the details of this account 628 629 :rtype: :class:`DimensionDataAccountDetails` 630 """ 631 body = self.request_api_1('myaccount').object 632 return DimensionDataAccountDetails( 633 user_name=findtext(body, 'userName', DIRECTORY_NS), 634 full_name=findtext(body, 'fullName', DIRECTORY_NS), 635 first_name=findtext(body, 'firstName', DIRECTORY_NS), 636 last_name=findtext(body, 'lastName', DIRECTORY_NS), 637 email=findtext(body, 'emailAddress', DIRECTORY_NS)) 638 639 640class DimensionDataAccountDetails(object): 641 """ 642 Dimension Data account class details 643 """ 644 def __init__(self, user_name, full_name, first_name, last_name, email): 645 self.user_name = user_name 646 self.full_name = full_name 647 self.first_name = first_name 648 self.last_name = last_name 649 self.email = email 650 651 652class DimensionDataStatus(object): 653 """ 654 DimensionData API pending operation status class 655 action, request_time, user_name, number_of_steps, update_time, 656 step.name, step.number, step.percent_complete, failure_reason, 657 """ 658 def __init__(self, action=None, request_time=None, user_name=None, 659 number_of_steps=None, update_time=None, step_name=None, 660 step_number=None, step_percent_complete=None, 661 failure_reason=None): 662 self.action = action 663 self.request_time = request_time 664 self.user_name = user_name 665 self.number_of_steps = number_of_steps 666 self.update_time = update_time 667 self.step_name = step_name 668 self.step_number = step_number 669 self.step_percent_complete = step_percent_complete 670 self.failure_reason = failure_reason 671 672 def __repr__(self): 673 return (('<DimensionDataStatus: action=%s, request_time=%s, ' 674 'user_name=%s, number_of_steps=%s, update_time=%s, ' 675 'step_name=%s, step_number=%s, ' 676 'step_percent_complete=%s, failure_reason=%s>') 677 % (self.action, self.request_time, self.user_name, 678 self.number_of_steps, self.update_time, self.step_name, 679 self.step_number, self.step_percent_complete, 680 self.failure_reason)) 681 682 683class DimensionDataNetwork(object): 684 """ 685 DimensionData network with location. 686 """ 687 688 def __init__(self, id, name, description, location, private_net, 689 multicast, status): 690 self.id = str(id) 691 self.name = name 692 self.description = description 693 self.location = location 694 self.private_net = private_net 695 self.multicast = multicast 696 self.status = status 697 698 def __repr__(self): 699 return (('<DimensionDataNetwork: id=%s, name=%s, description=%s, ' 700 'location=%s, private_net=%s, multicast=%s>') 701 % (self.id, self.name, self.description, self.location, 702 self.private_net, self.multicast)) 703 704 705class DimensionDataNetworkDomain(object): 706 """ 707 DimensionData network domain with location. 708 """ 709 710 def __init__(self, id, name, description, location, status, plan): 711 self.id = str(id) 712 self.name = name 713 self.description = description 714 self.location = location 715 self.status = status 716 self.plan = plan 717 718 def __repr__(self): 719 return (('<DimensionDataNetworkDomain: id=%s, name=%s, ' 720 'description=%s, location=%s, status=%s, plan=%s>') 721 % (self.id, self.name, self.description, self.location, 722 self.status, self.plan)) 723 724 725class DimensionDataPublicIpBlock(object): 726 """ 727 DimensionData Public IP Block with location. 728 """ 729 730 def __init__(self, id, base_ip, size, location, network_domain, 731 status): 732 self.id = str(id) 733 self.base_ip = base_ip 734 self.size = size 735 self.location = location 736 self.network_domain = network_domain 737 self.status = status 738 739 def __repr__(self): 740 return (('<DimensionDataNetworkDomain: id=%s, base_ip=%s, ' 741 'size=%s, location=%s, status=%s>') 742 % (self.id, self.base_ip, self.size, self.location, 743 self.status)) 744 745 746class DimensionDataServerCpuSpecification(object): 747 """ 748 A class that represents the specification of the CPU(s) for a 749 node 750 """ 751 def __init__(self, cpu_count, cores_per_socket, performance): 752 """ 753 Instantiate a new :class:`DimensionDataServerCpuSpecification` 754 755 :param cpu_count: The number of CPUs 756 :type cpu_count: ``int`` 757 758 :param cores_per_socket: The number of cores per socket, the 759 recommendation is 1 760 :type cores_per_socket: ``int`` 761 762 :param performance: The performance type, e.g. HIGHPERFORMANCE 763 :type performance: ``str`` 764 """ 765 self.cpu_count = cpu_count 766 self.cores_per_socket = cores_per_socket 767 self.performance = performance 768 769 def __repr__(self): 770 return (('<DimensionDataServerCpuSpecification: ' 771 'cpu_count=%s, cores_per_socket=%s, ' 772 'performance=%s>') 773 % (self.cpu_count, self.cores_per_socket, self.performance)) 774 775 776class DimensionDataServerDisk(object): 777 """ 778 A class that represents the disk on a server 779 """ 780 def __init__(self, id=None, scsi_id=None, size_gb=None, speed=None, 781 state=None): 782 """ 783 Instantiate a new :class:`DimensionDataServerDisk` 784 785 :param id: The id of the disk 786 :type id: ``str`` 787 788 :param scsi_id: Representation for scsi 789 :type scsi_id: ``int`` 790 791 :param size_gb: Size of the disk 792 :type size_gb: ``int`` 793 794 :param speed: Speed of the disk (i.e. STANDARD) 795 :type speed: ``str`` 796 797 :param state: State of the disk (i.e. PENDING) 798 :type state: ``str`` 799 """ 800 self.id = id 801 self.scsi_id = scsi_id 802 self.size_gb = size_gb 803 self.speed = speed 804 self.state = state 805 806 def __repr__(self): 807 return (('<DimensionDataServerDisk: ' 808 'id=%s, size_gb=%s') 809 % (self.id, self.size_gb)) 810 811 812class DimensionDataServerVMWareTools(object): 813 """ 814 A class that represents the VMWareTools for a node 815 """ 816 def __init__(self, status, version_status, api_version): 817 """ 818 Instantiate a new :class:`DimensionDataServerVMWareTools` object 819 820 :param status: The status of VMWare Tools 821 :type status: ``str`` 822 823 :param version_status: The status for the version of VMWare Tools 824 (i.e NEEDS_UPGRADE) 825 :type version_status: ``str`` 826 827 :param api_version: The API version of VMWare Tools 828 :type api_version: ``str`` 829 """ 830 self.status = status 831 self.version_status = version_status 832 self.api_version = api_version 833 834 def __repr__(self): 835 return (('<DimensionDataServerVMWareTools ' 836 'status=%s, version_status=%s, ' 837 'api_version=%s>') 838 % (self.status, self.version_status, self.api_version)) 839 840 841class DimensionDataFirewallRule(object): 842 """ 843 DimensionData Firewall Rule for a network domain 844 """ 845 846 def __init__(self, id, name, action, location, network_domain, 847 status, ip_version, protocol, source, destination, 848 enabled): 849 self.id = str(id) 850 self.name = name 851 self.action = action 852 self.location = location 853 self.network_domain = network_domain 854 self.status = status 855 self.ip_version = ip_version 856 self.protocol = protocol 857 self.source = source 858 self.destination = destination 859 self.enabled = enabled 860 861 def __repr__(self): 862 return (('<DimensionDataFirewallRule: id=%s, name=%s, ' 863 'action=%s, location=%s, network_domain=%s, ' 864 'status=%s, ip_version=%s, protocol=%s, source=%s, ' 865 'destination=%s, enabled=%s>') 866 % (self.id, self.name, self.action, self.location, 867 self.network_domain, self.status, self.ip_version, 868 self.protocol, self.source, self.destination, 869 self.enabled)) 870 871 872class DimensionDataFirewallAddress(object): 873 """ 874 The source or destination model in a firewall rule 875 """ 876 def __init__(self, any_ip, ip_address, ip_prefix_size, 877 port_begin, port_end, address_list_id, 878 port_list_id): 879 self.any_ip = any_ip 880 self.ip_address = ip_address 881 self.ip_prefix_size = ip_prefix_size 882 self.port_list_id = port_list_id 883 self.port_begin = port_begin 884 self.port_end = port_end 885 self.address_list_id = address_list_id 886 self.port_list_id = port_list_id 887 888 def __repr__(self): 889 return ( 890 '<DimensionDataFirewallAddress: any_ip=%s, ip_address=%s, ' 891 'ip_prefix_size=%s, port_begin=%s, port_end=%s, ' 892 'address_list_id=%s, port_list_id=%s>' 893 % (self.any_ip, self.ip_address, self.ip_prefix_size, 894 self.port_begin, self.port_end, self.address_list_id, 895 self.port_list_id)) 896 897 898class DimensionDataNatRule(object): 899 """ 900 An IP NAT rule in a network domain 901 """ 902 def __init__(self, id, network_domain, internal_ip, external_ip, status): 903 self.id = id 904 self.network_domain = network_domain 905 self.internal_ip = internal_ip 906 self.external_ip = external_ip 907 self.status = status 908 909 def __repr__(self): 910 return (('<DimensionDataNatRule: id=%s, status=%s>') 911 % (self.id, self.status)) 912 913 914class DimensionDataAntiAffinityRule(object): 915 """ 916 Anti-Affinity rule for DimensionData 917 918 An Anti-Affinity rule ensures that servers in the rule will 919 not reside on the same VMware ESX host. 920 """ 921 def __init__(self, id, node_list): 922 """ 923 Instantiate a new :class:`DimensionDataAntiAffinityRule` 924 925 :param id: The ID of the Anti-Affinity rule 926 :type id: ``str`` 927 928 :param node_list: List of node ids that belong in this rule 929 :type node_list: ``list`` of ``str`` 930 """ 931 self.id = id 932 self.node_list = node_list 933 934 def __repr__(self): 935 return (('<DimensionDataAntiAffinityRule: id=%s>') 936 % (self.id)) 937 938 939class DimensionDataVlan(object): 940 """ 941 DimensionData VLAN. 942 """ 943 944 def __init__(self, id, name, description, location, network_domain, 945 status, private_ipv4_range_address, private_ipv4_range_size, 946 ipv6_range_address, ipv6_range_size, ipv4_gateway, 947 ipv6_gateway): 948 """ 949 Initialize an instance of ``DimensionDataVlan`` 950 951 :param id: The ID of the VLAN 952 :type id: ``str`` 953 954 :param name: The name of the VLAN 955 :type name: ``str`` 956 957 :param description: Plan text description of the VLAN 958 :type description: ``str`` 959 960 :param location: The location (data center) of the VLAN 961 :type location: ``NodeLocation`` 962 963 :param network_domain: The Network Domain that owns this VLAN 964 :type network_domain: :class:`DimensionDataNetworkDomain` 965 966 :param status: The status of the VLAN 967 :type status: :class:`DimensionDataStatus` 968 969 :param private_ipv4_range_address: The host address of the VLAN 970 IP space 971 :type private_ipv4_range_address: ``str`` 972 973 :param private_ipv4_range_size: The size (e.g. '24') of the VLAN 974 as a CIDR range size 975 :type private_ipv4_range_size: ``int`` 976 977 :param ipv6_range_address: The host address of the VLAN 978 IP space 979 :type ipv6_range_address: ``str`` 980 981 :param ipv6_range_size: The size (e.g. '32') of the VLAN 982 as a CIDR range size 983 :type ipv6_range_size: ``int`` 984 985 :param ipv4_gateway: The IPv4 default gateway address 986 :type ipv4_gateway: ``str`` 987 988 :param ipv6_gateway: The IPv6 default gateway address 989 :type ipv6_gateway: ``str`` 990 """ 991 self.id = str(id) 992 self.name = name 993 self.location = location 994 self.description = description 995 self.network_domain = network_domain 996 self.status = status 997 self.private_ipv4_range_address = private_ipv4_range_address 998 self.private_ipv4_range_size = private_ipv4_range_size 999 self.ipv6_range_address = ipv6_range_address 1000 self.ipv6_range_size = ipv6_range_size 1001 self.ipv4_gateway = ipv4_gateway 1002 self.ipv6_gateway = ipv6_gateway 1003 1004 def __repr__(self): 1005 return (('<DimensionDataVlan: id=%s, name=%s, ' 1006 'description=%s, location=%s, status=%s>') 1007 % (self.id, self.name, self.description, 1008 self.location, self.status)) 1009 1010 1011class DimensionDataPool(object): 1012 """ 1013 DimensionData VIP Pool. 1014 """ 1015 1016 def __init__(self, id, name, description, status, load_balance_method, 1017 health_monitor_id, service_down_action, slow_ramp_time): 1018 """ 1019 Initialize an instance of ``DimensionDataPool`` 1020 1021 :param id: The ID of the pool 1022 :type id: ``str`` 1023 1024 :param name: The name of the pool 1025 :type name: ``str`` 1026 1027 :param description: Plan text description of the pool 1028 :type description: ``str`` 1029 1030 :param status: The status of the pool 1031 :type status: :class:`DimensionDataStatus` 1032 1033 :param load_balance_method: The load balancer method 1034 :type load_balance_method: ``str`` 1035 1036 :param health_monitor_id: The ID of the health monitor 1037 :type health_monitor_id: ``str`` 1038 1039 :param service_down_action: Action to take when pool is down 1040 :type service_down_action: ``str`` 1041 1042 :param slow_ramp_time: The ramp-up time for service recovery 1043 :type slow_ramp_time: ``int`` 1044 """ 1045 self.id = str(id) 1046 self.name = name 1047 self.description = description 1048 self.status = status 1049 self.load_balance_method = load_balance_method 1050 self.health_monitor_id = health_monitor_id 1051 self.service_down_action = service_down_action 1052 self.slow_ramp_time = slow_ramp_time 1053 1054 def __repr__(self): 1055 return (('<DimensionDataPool: id=%s, name=%s, ' 1056 'description=%s, status=%s>') 1057 % (self.id, self.name, self.description, 1058 self.status)) 1059 1060 1061class DimensionDataPoolMember(object): 1062 """ 1063 DimensionData VIP Pool Member. 1064 """ 1065 1066 def __init__(self, id, name, status, ip, port, node_id): 1067 """ 1068 Initialize an instance of ``DimensionDataPoolMember`` 1069 1070 :param id: The ID of the pool member 1071 :type id: ``str`` 1072 1073 :param name: The name of the pool member 1074 :type name: ``str`` 1075 1076 :param status: The status of the pool 1077 :type status: :class:`DimensionDataStatus` 1078 1079 :param ip: The IP of the pool member 1080 :type ip: ``str`` 1081 1082 :param port: The port of the pool member 1083 :type port: ``int`` 1084 1085 :param node_id: The ID of the associated node 1086 :type node_id: ``str`` 1087 """ 1088 self.id = str(id) 1089 self.name = name 1090 self.status = status 1091 self.ip = ip 1092 self.port = port 1093 self.node_id = node_id 1094 1095 def __repr__(self): 1096 return (('<DimensionDataPoolMember: id=%s, name=%s, ' 1097 'ip=%s, status=%s, port=%s, node_id=%s>') 1098 % (self.id, self.name, 1099 self.ip, self.status, self.port, 1100 self.node_id)) 1101 1102 1103class DimensionDataVIPNode(object): 1104 def __init__(self, id, name, status, ip, connection_limit='10000', 1105 connection_rate_limit='10000'): 1106 """ 1107 Initialize an instance of :class:`DimensionDataVIPNode` 1108 1109 :param id: The ID of the node 1110 :type id: ``str`` 1111 1112 :param name: The name of the node 1113 :type name: ``str`` 1114 1115 :param status: The status of the node 1116 :type status: :class:`DimensionDataStatus` 1117 1118 :param ip: The IP of the node 1119 :type ip: ``str`` 1120 1121 :param connection_limit: The total connection limit for the node 1122 :type connection_limit: ``int`` 1123 1124 :param connection_rate_limit: The rate limit for the node 1125 :type connection_rate_limit: ``int`` 1126 """ 1127 self.id = str(id) 1128 self.name = name 1129 self.status = status 1130 self.ip = ip 1131 self.connection_limit = connection_limit 1132 self.connection_rate_limit = connection_rate_limit 1133 1134 def __repr__(self): 1135 return (('<DimensionDataVIPNode: id=%s, name=%s, ' 1136 'status=%s, ip=%s>') 1137 % (self.id, self.name, 1138 self.status, self.ip)) 1139 1140 1141class DimensionDataVirtualListener(object): 1142 """ 1143 DimensionData Virtual Listener. 1144 """ 1145 1146 def __init__(self, id, name, status, ip): 1147 """ 1148 Initialize an instance of :class:`DimensionDataVirtualListener` 1149 1150 :param id: The ID of the listener 1151 :type id: ``str`` 1152 1153 :param name: The name of the listener 1154 :type name: ``str`` 1155 1156 :param status: The status of the listener 1157 :type status: :class:`DimensionDataStatus` 1158 1159 :param ip: The IP of the listener 1160 :type ip: ``str`` 1161 """ 1162 self.id = str(id) 1163 self.name = name 1164 self.status = status 1165 self.ip = ip 1166 1167 def __repr__(self): 1168 return (('<DimensionDataVirtualListener: id=%s, name=%s, ' 1169 'status=%s, ip=%s>') 1170 % (self.id, self.name, 1171 self.status, self.ip)) 1172 1173 1174class DimensionDataDefaultHealthMonitor(object): 1175 """ 1176 A default health monitor for a VIP (node, pool or listener) 1177 """ 1178 def __init__(self, id, name, node_compatible, pool_compatible): 1179 """ 1180 Initialize an instance of :class:`DimensionDataDefaultHealthMonitor` 1181 1182 :param id: The ID of the monitor 1183 :type id: ``str`` 1184 1185 :param name: The name of the monitor 1186 :type name: ``str`` 1187 1188 :param node_compatible: Is a monitor capable of monitoring nodes 1189 :type node_compatible: ``bool`` 1190 1191 :param pool_compatible: Is a monitor capable of monitoring pools 1192 :type pool_compatible: ``bool`` 1193 """ 1194 self.id = id 1195 self.name = name 1196 self.node_compatible = node_compatible 1197 self.pool_compatible = pool_compatible 1198 1199 def __repr__(self): 1200 return (('<DimensionDataDefaultHealthMonitor: id=%s, name=%s>') 1201 % (self.id, self.name)) 1202 1203 1204class DimensionDataPersistenceProfile(object): 1205 """ 1206 Each Persistence Profile declares the combination of Virtual Listener 1207 type and protocol with which it is 1208 compatible and whether or not it is compatible as a 1209 Fallback Persistence Profile. 1210 """ 1211 def __init__(self, id, name, compatible_listeners, fallback_compatible): 1212 """ 1213 Initialize an instance of :class:`DimensionDataPersistenceProfile` 1214 1215 :param id: The ID of the profile 1216 :type id: ``str`` 1217 1218 :param name: The name of the profile 1219 :type name: ``str`` 1220 1221 :param compatible_listeners: List of compatible Virtual Listener types 1222 :type compatible_listeners: ``list`` of 1223 :class:`DimensionDataVirtualListenerCompatibility` 1224 1225 :param fallback_compatible: Is capable as a fallback profile 1226 :type fallback_compatible: ``bool`` 1227 """ 1228 self.id = id 1229 self.name = name 1230 self.compatible_listeners = compatible_listeners 1231 self.fallback_compatible = fallback_compatible 1232 1233 def __repr__(self): 1234 return (('<DimensionDataPersistenceProfile: id=%s, name=%s>') 1235 % (self.id, self.name)) 1236 1237 1238class DimensionDataDefaultiRule(object): 1239 """ 1240 A default iRule for a network domain, can be applied to a listener 1241 """ 1242 def __init__(self, id, name, compatible_listeners): 1243 """ 1244 Initialize an instance of :class:`DimensionDataDefaultiRule` 1245 1246 :param id: The ID of the iRule 1247 :type id: ``str`` 1248 1249 :param name: The name of the iRule 1250 :type name: ``str`` 1251 1252 :param compatible_listeners: List of compatible Virtual Listener types 1253 :type compatible_listeners: ``list`` of 1254 :class:`DimensionDataVirtualListenerCompatibility` 1255 """ 1256 self.id = id 1257 self.name = name 1258 self.compatible_listeners = compatible_listeners 1259 1260 def __repr__(self): 1261 return (('<DimensionDataDefaultiRule: id=%s, name=%s>') 1262 % (self.id, self.name)) 1263 1264 1265class DimensionDataVirtualListenerCompatibility(object): 1266 """ 1267 A compatibility preference for a persistence profile or iRule 1268 specifies which virtual listener types this profile or iRule can be 1269 applied to. 1270 """ 1271 def __init__(self, type, protocol): 1272 self.type = type 1273 self.protocol = protocol 1274 1275 def __repr__(self): 1276 return (('<DimensionDataVirtualListenerCompatibility: ' 1277 'type=%s, protocol=%s>') 1278 % (self.type, self.protocol)) 1279 1280 1281class DimensionDataBackupDetails(object): 1282 """ 1283 Dimension Data Backup Details represents information about 1284 a targets backups configuration 1285 """ 1286 1287 def __init__(self, asset_id, service_plan, status, clients=None): 1288 """ 1289 Initialize an instance of :class:`DimensionDataBackupDetails` 1290 1291 :param asset_id: Asset identification for backups 1292 :type asset_id: ``str`` 1293 1294 :param service_plan: The service plan for backups. i.e (Essentials) 1295 :type service_plan: ``str`` 1296 1297 :param status: The overall status this backup target. 1298 i.e. (unregistered) 1299 :type status: ``str`` 1300 1301 :param clients: Backup clients attached to this target 1302 :type clients: ``list`` of :class:`DimensionDataBackupClient` 1303 """ 1304 self.asset_id = asset_id 1305 self.service_plan = service_plan 1306 self.status = status 1307 self.clients = clients 1308 1309 def __repr__(self): 1310 return (('<DimensionDataBackupDetails: id=%s>') 1311 % (self.asset_id)) 1312 1313 1314class DimensionDataBackupClient(object): 1315 """ 1316 An object that represents a backup client 1317 """ 1318 def __init__(self, id, type, status, 1319 schedule_policy, storage_policy, download_url, 1320 alert=None, running_job=None): 1321 """ 1322 Initialize an instance of :class:`DimensionDataBackupClient` 1323 1324 :param id: Unique ID for the client 1325 :type id: ``str`` 1326 1327 :param type: The type of client that this client is 1328 :type type: :class:`DimensionDataBackupClientType` 1329 1330 :param status: The states of this particular backup client. 1331 i.e. (Unregistered) 1332 :type status: ``str`` 1333 1334 :param schedule_policy: The schedule policy for this client 1335 NOTE: Dimension Data only sends back the name 1336 of the schedule policy, no further details 1337 :type schedule_policy: ``str`` 1338 1339 :param storage_policy: The storage policy for this client 1340 NOTE: Dimension Data only sends back the name 1341 of the storage policy, no further details 1342 :type storage_policy: ``str`` 1343 1344 :param download_url: The download url for this client 1345 :type download_url: ``str`` 1346 1347 :param alert: The alert configured for this backup client (optional) 1348 :type alert: :class:`DimensionDataBackupClientAlert` 1349 1350 :param alert: The running job for the client (optional) 1351 :type alert: :class:`DimensionDataBackupClientRunningJob` 1352 """ 1353 self.id = id 1354 self.type = type 1355 self.status = status 1356 self.schedule_policy = schedule_policy 1357 self.storage_policy = storage_policy 1358 self.download_url = download_url 1359 self.alert = alert 1360 self.running_job = running_job 1361 1362 def __repr__(self): 1363 return (('<DimensionDataBackupClient: id=%s>') 1364 % (self.id)) 1365 1366 1367class DimensionDataBackupClientAlert(object): 1368 """ 1369 An alert for a backup client 1370 """ 1371 def __init__(self, trigger, notify_list=[]): 1372 """ 1373 Initialize an instance of :class:`DimensionDataBackupClientAlert` 1374 1375 :param trigger: Trigger type for the client i.e. ON_FAILURE 1376 :type trigger: ``str`` 1377 1378 :param notify_list: List of email addresses that are notified 1379 when the alert is fired 1380 :type notify_list: ``list`` of ``str`` 1381 """ 1382 self.trigger = trigger 1383 self.notify_list = notify_list 1384 1385 def __repr__(self): 1386 return (('<DimensionDataBackupClientAlert: trigger=%s>') 1387 % (self.trigger)) 1388 1389 1390class DimensionDataBackupClientRunningJob(object): 1391 """ 1392 A running job for a given backup client 1393 """ 1394 def __init__(self, id, status, percentage=0): 1395 """ 1396 Initialize an instance of :class:`DimensionDataBackupClientRunningJob` 1397 1398 :param id: The unqiue ID of the job 1399 :type id: ``str`` 1400 1401 :param status: The status of the job i.e. Waiting 1402 :type status: ``str`` 1403 1404 :param percentage: The percentage completion of the job 1405 :type percentage: ``int`` 1406 """ 1407 self.id = id 1408 self.percentage = percentage 1409 self.status = status 1410 1411 def __repr__(self): 1412 return (('<DimensionDataBackupClientRunningJob: id=%s>') 1413 % (self.id)) 1414 1415 1416class DimensionDataBackupClientType(object): 1417 """ 1418 A client type object for backups 1419 """ 1420 def __init__(self, type, is_file_system, description): 1421 """ 1422 Initialize an instance of :class:`DimensionDataBackupClientType` 1423 1424 :param type: The type of client i.e. (FA.Linux, MySQL, ect.) 1425 :type type: ``str`` 1426 1427 :param is_file_system: The name of the iRule 1428 :type is_file_system: ``bool`` 1429 1430 :param description: Description of the client 1431 :type description: ``str`` 1432 """ 1433 self.type = type 1434 self.is_file_system = is_file_system 1435 self.description = description 1436 1437 def __repr__(self): 1438 return (('<DimensionDataBackupClientType: type=%s>') 1439 % (self.type)) 1440 1441 1442class DimensionDataBackupStoragePolicy(object): 1443 """ 1444 A representation of a storage policy 1445 """ 1446 def __init__(self, name, retention_period, secondary_location): 1447 """ 1448 Initialize an instance of :class:`DimensionDataBackupStoragePolicy` 1449 1450 :param name: The name of the storage policy i.e. 14 Day Storage Policy 1451 :type name: ``str`` 1452 1453 :param retention_period: How long to keep the backup in days 1454 :type retention_period: ``int`` 1455 1456 :param secondary_location: The secondary location i.e. Primary 1457 :type secondary_location: ``str`` 1458 """ 1459 self.name = name 1460 self.retention_period = retention_period 1461 self.secondary_location = secondary_location 1462 1463 def __repr__(self): 1464 return (('<DimensionDataBackupStoragePolicy: name=%s>') 1465 % (self.name)) 1466 1467 1468class DimensionDataBackupSchedulePolicy(object): 1469 """ 1470 A representation of a schedule policy 1471 """ 1472 def __init__(self, name, description): 1473 """ 1474 Initialize an instance of :class:`DimensionDataBackupSchedulePolicy` 1475 1476 :param name: The name of the policy i.e 12AM - 6AM 1477 :type name: ``str`` 1478 1479 :param description: Short summary of the details of the policy 1480 :type description: ``str`` 1481 """ 1482 self.name = name 1483 self.description = description 1484 1485 def __repr__(self): 1486 return (('<DimensionDataBackupSchedulePolicy: name=%s>') 1487 % (self.name)) 1488 1489 1490class DimensionDataTag(object): 1491 """ 1492 A representation of a Tag in Dimension Data 1493 A Tag first must have a Tag Key, then an asset is tag with 1494 a key and an option value. Tags can be queried later to filter assets 1495 and also show up on usage report if so desired. 1496 """ 1497 def __init__(self, asset_type, asset_id, asset_name, 1498 datacenter, key, value): 1499 """ 1500 Initialize an instance of :class:`DimensionDataTag` 1501 1502 :param asset_type: The type of asset. Current asset types: 1503 SERVER, VLAN, NETWORK_DOMAIN, CUSTOMER_IMAGE, 1504 PUBLIC_IP_BLOCK, ACCOUNT 1505 :type asset_type: ``str`` 1506 1507 :param asset_id: The GUID of the asset that is tagged 1508 :type asset_id: ``str`` 1509 1510 :param asset_name: The name of the asset that is tagged 1511 :type asset_name: ``str`` 1512 1513 :param datacenter: The short datacenter name of the tagged asset 1514 :type datacenter: ``str`` 1515 1516 :param key: The tagged key 1517 :type key: :class:`DimensionDataTagKey` 1518 1519 :param value: The tagged value 1520 :type value: ``None`` or ``str`` 1521 """ 1522 self.asset_type = asset_type 1523 self.asset_id = asset_id 1524 self.asset_name = asset_name 1525 self.datacenter = datacenter 1526 self.key = key 1527 self.value = value 1528 1529 def __repr__(self): 1530 return (('<DimensionDataTag: asset_name=%s, tag_name=%s, value=%s>') 1531 % (self.asset_name, self.key.name, self.value)) 1532 1533 1534class DimensionDataTagKey(object): 1535 """ 1536 A representation of a Tag Key in Dimension Data 1537 A tag key is required to tag an asset 1538 """ 1539 def __init__(self, id, name, description, 1540 value_required, display_on_report): 1541 """ 1542 Initialize an instance of :class:`DimensionDataTagKey` 1543 1544 :param id: GUID of the tag key 1545 :type id: ``str`` 1546 1547 :param name: Name of the tag key 1548 :type name: ``str`` 1549 1550 :param description: Description of the tag key 1551 :type description: ``str`` 1552 1553 :param value_required: If a value is required for this tag key 1554 :type value_required: ``bool`` 1555 1556 :param display_on_report: If this tag key should be displayed on 1557 usage reports 1558 :type display_on_report: ``bool`` 1559 """ 1560 self.id = id 1561 self.name = name 1562 self.description = description 1563 self.value_required = value_required 1564 self.display_on_report = display_on_report 1565 1566 def __repr__(self): 1567 return (('<DimensionDataTagKey: name=%s>') 1568 % (self.name)) 1569 1570 1571class DimensionDataIpAddressList(object): 1572 """ 1573 DimensionData IP Address list 1574 """ 1575 1576 def __init__(self, id, name, description, ip_version, 1577 ip_address_collection, 1578 state, create_time, child_ip_address_lists=None): 1579 """" 1580 Initialize an instance of :class:`DimensionDataIpAddressList` 1581 1582 :param id: GUID of the IP Address List key 1583 :type id: ``str`` 1584 1585 :param name: Name of the IP Address List 1586 :type name: ``str`` 1587 1588 :param description: Description of the IP Address List 1589 :type description: ``str`` 1590 1591 :param ip_version: IP version. E.g. IPV4, IPV6 1592 :type ip_version: ``str`` 1593 1594 :param ip_address_collection: Collection of DimensionDataIpAddress 1595 :type ip_address_collection: ``List`` 1596 1597 :param state: IP Address list state 1598 :type state: ``str`` 1599 1600 :param create_time: IP Address List created time 1601 :type create_time: ``date time`` 1602 1603 :param child_ip_address_lists: List of IP address list to be included 1604 :type child_ip_address_lists: List \ 1605 of :class:'DimensionDataIpAddressList' 1606 """ 1607 self.id = id 1608 self.name = name 1609 self.description = description 1610 self.ip_version = ip_version 1611 self.ip_address_collection = ip_address_collection 1612 self.state = state 1613 self.create_time = create_time 1614 self.child_ip_address_lists = child_ip_address_lists 1615 1616 def __repr__(self): 1617 return ('<DimensionDataIpAddressList: id=%s, name=%s, description=%s, ' 1618 'ip_version=%s, ip_address_collection=%s, state=%s, ' 1619 'create_time=%s, child_ip_address_lists=%s>' 1620 % (self.id, self.name, self.description, self.ip_version, 1621 self.ip_address_collection, self.state, self.create_time, 1622 self.child_ip_address_lists)) 1623 1624 1625class DimensionDataChildIpAddressList(object): 1626 """ 1627 DimensionData Child IP Address list 1628 """ 1629 1630 def __init__(self, id, name): 1631 """" 1632 Initialize an instance of :class:`DimensionDataChildIpAddressList` 1633 1634 :param id: GUID of the IP Address List key 1635 :type id: ``str`` 1636 1637 :param name: Name of the IP Address List 1638 :type name: ``str`` 1639 1640 """ 1641 self.id = id 1642 self.name = name 1643 1644 def __repr__(self): 1645 return ('<DimensionDataChildIpAddressList: id=%s, name=%s>' 1646 % (self.id, self.name)) 1647 1648 1649class DimensionDataIpAddress(object): 1650 """ 1651 A representation of IP Address in Dimension Data 1652 """ 1653 1654 def __init__(self, begin, end=None, prefix_size=None): 1655 """ 1656 Initialize an instance of :class:`DimensionDataIpAddress` 1657 1658 :param begin: IP Address Begin 1659 :type begin: ``str`` 1660 1661 :param end: IP Address end 1662 :type end: ``str`` 1663 1664 :param prefixSize: IP Address prefix size 1665 :type prefixSize: ``int`` 1666 """ 1667 self.begin = begin 1668 self.end = end 1669 self.prefix_size = prefix_size 1670 1671 def __repr__(self): 1672 return ('<DimensionDataIpAddress: begin=%s, end=%s, prefix_size=%s>' 1673 % (self.begin, self.end, self.prefix_size)) 1674 1675 1676class DimensionDataPortList(object): 1677 """ 1678 DimensionData Port list 1679 """ 1680 1681 def __init__(self, id, name, description, port_collection, 1682 child_portlist_list, 1683 state, create_time): 1684 """" 1685 Initialize an instance of :class:`DimensionDataPortList` 1686 1687 :param id: GUID of the Port List key 1688 :type id: ``str`` 1689 1690 :param name: Name of the Port List 1691 :type name: ``str`` 1692 1693 :param description: Description of the Port List 1694 :type description: ``str`` 1695 1696 :param port_collection: Collection of DimensionDataPort 1697 :type port_collection: ``List`` 1698 1699 :param child_portlist_list: Collection of DimensionDataChildPort 1700 :type child_portlist_list: ``List`` 1701 1702 :param state: Port list state 1703 :type state: ``str`` 1704 1705 :param create_time: Port List created time 1706 :type create_time: ``date time`` 1707 """ 1708 self.id = id 1709 self.name = name 1710 self.description = description 1711 self.port_collection = port_collection 1712 self.child_portlist_list = child_portlist_list 1713 self.state = state 1714 self.create_time = create_time 1715 1716 def __repr__(self): 1717 return ( 1718 "<DimensionDataPortList: id=%s, name=%s, description=%s, " 1719 "port_collection=%s, child_portlist_list=%s, state=%s, " 1720 "create_time=%s>" 1721 % (self.id, self.name, self.description, 1722 self.port_collection, self.child_portlist_list, self.state, 1723 self.create_time)) 1724 1725 1726class DimensionDataChildPortList(object): 1727 """ 1728 DimensionData Child Port list 1729 """ 1730 1731 def __init__(self, id, name): 1732 """" 1733 Initialize an instance of :class:`DimensionDataChildIpAddressList` 1734 1735 :param id: GUID of the child port list key 1736 :type id: ``str`` 1737 1738 :param name: Name of the child port List 1739 :type name: ``str`` 1740 1741 """ 1742 self.id = id 1743 self.name = name 1744 1745 def __repr__(self): 1746 return ('<DimensionDataChildPortList: id=%s, name=%s>' 1747 % (self.id, self.name)) 1748 1749 1750class DimensionDataPort(object): 1751 """ 1752 A representation of Port in Dimension Data 1753 """ 1754 1755 def __init__(self, begin, end=None): 1756 """ 1757 Initialize an instance of :class:`DimensionDataPort` 1758 1759 :param begin: Port Number Begin 1760 :type begin: ``str`` 1761 1762 :param end: Port Number end 1763 :type end: ``str`` 1764 """ 1765 self.begin = begin 1766 self.end = end 1767 1768 def __repr__(self): 1769 return ('<DimensionDataPort: begin=%s, end=%s>' 1770 % (self.begin, self.end)) 1771 1772 1773class DimensionDataNic(object): 1774 """ 1775 A representation of Network Adapter in Dimension Data 1776 """ 1777 1778 def __init__(self, private_ip_v4=None, vlan=None, 1779 network_adapter_name=None): 1780 """ 1781 Initialize an instance of :class:`DimensionDataNic` 1782 1783 :param private_ip_v4: IPv4 1784 :type private_ip_v4: ``str`` 1785 1786 :param vlan: Network VLAN 1787 :type vlan: class: DimensionDataVlan or ``str`` 1788 1789 :param network_adapter_name: Network Adapter Name 1790 :type network_adapter_name: ``str`` 1791 """ 1792 self.private_ip_v4 = private_ip_v4 1793 self.vlan = vlan 1794 self.network_adapter_name = network_adapter_name 1795 1796 def __repr__(self): 1797 return ('<DimensionDataNic: private_ip_v4=%s, vlan=%s,' 1798 'network_adapter_name=%s>' 1799 % (self.private_ip_v4, self.vlan, self.network_adapter_name)) 1800