added or updated multiple methods for disk or scsi controller handling.
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/141d235b Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/141d235b Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/141d235b Branch: refs/heads/trunk Commit: 141d235b51da29b3cc414fb7d8a4147ae5b50774 Parents: b4a7e98 Author: mitch <[email protected]> Authored: Mon Aug 27 15:41:33 2018 -0400 Committer: mitch <[email protected]> Committed: Mon Aug 27 15:41:33 2018 -0400 ---------------------------------------------------------------------- libcloud/common/nttcis.py | 45 ++++++++++++++ libcloud/compute/drivers/nttcis.py | 106 ++++++++++++++++++++++++++++---- tests/lib_edit_test.py | 82 ++++++++++++++++++++++-- tests/lib_list_test.py | 11 +++- 4 files changed, 225 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/141d235b/libcloud/common/nttcis.py ---------------------------------------------------------------------- diff --git a/libcloud/common/nttcis.py b/libcloud/common/nttcis.py index 6e2375c..191309f 100644 --- a/libcloud/common/nttcis.py +++ b/libcloud/common/nttcis.py @@ -808,6 +808,40 @@ class NttCisServerDisk(object): % (self.id, self.size_gb)) +class NttCisScsiController(object): + """ + A class that represents the disk on a server + """ + def __init__(self, id: str=None, adapter_type: str=None, bus_number: str=None, state: str=None): + """ + Instantiate a new :class:`DimensionDataServerDisk` + + :param id: The id of the controller + :type id: ``str`` + + :param adapter_type: The 'brand' of adapter + :type adapter_type: ``str`` + + :param bus_number: The bus number occupied on the virtual hardware + :type bus_nubmer: ``str`` + + :param state: Curent state (i.e. NORMAL) + :type speed: ``str`` + + :param state: State of the disk (i.e. PENDING) + :type state: ``str`` + """ + self.id = id + self.adapter_type = adapter_type + self.bus_number = bus_number + self.state = state + + def __repr__(self): + return (('<NttCisScsiController: ' + 'id=%s, adapter_type=%s, bus_number=%s, state=%s') + % (self.id, self.adapter_type, self.bus_number, self.state)) + + class NttCisServerVMWareTools(object): """ A class that represents the VMWareTools for a node @@ -1336,6 +1370,13 @@ class NttCisBackupDetails(object): % (self.asset_id)) +class NttCisDataCenter(object): + """ + Class that represents a Cloud Infrastructure Datacenter + """ + + + class NttCisBackupClient(object): """ An object that represents a backup client @@ -1593,6 +1634,10 @@ class NttCisTagKey(object): % (self.name)) +class NttCisFactory(object): + pass + + class NttCisIpAddressList(object): """ NttCis IP Address list http://git-wip-us.apache.org/repos/asf/libcloud/blob/141d235b/libcloud/compute/drivers/nttcis.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/nttcis.py b/libcloud/compute/drivers/nttcis.py index 8512f4e..4866e76 100644 --- a/libcloud/compute/drivers/nttcis.py +++ b/libcloud/compute/drivers/nttcis.py @@ -30,6 +30,7 @@ from libcloud.common.nttcis import NttCisNetworkDomain from libcloud.common.nttcis import NttCisVlan from libcloud.common.nttcis import NttCisServerCpuSpecification from libcloud.common.nttcis import NttCisServerDisk +from libcloud.common.nttcis import NttCisScsiController from libcloud.common.nttcis import NttCisServerVMWareTools from libcloud.common.nttcis import NttCisPublicIpBlock from libcloud.common.nttcis import NttCisFirewallRule @@ -879,6 +880,25 @@ class NttCisNodeDriver(NodeDriver): ).object ) + + def ex_get_datacneter(self, ex_id): + """ + List locations (datacenters) available for instantiating servers and + networks. + + :keyword ex_id: Filters the location list to this id + :type ex_id: ``str`` + + :return: List of locations + :rtype: ``list`` of :class:`NodeLocation` + """ + params = {} + if ex_id is not None: + params['id'] = ex_id + + return self.connection.request_with_orgId_api_2('infrastructure/datacenter', params=params) + + def list_snapshot_windows(self, location: str, plan: str) -> list: """ List snapshot windows in a given location @@ -2474,12 +2494,51 @@ class NttCisNodeDriver(NodeDriver): response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] - def ex_add_storage_to_node(self, node, amount, - speed='STANDARD', scsi_id=None): + def ex_add_scsi_controller_to_node(self, server_id: str, adapter_type: str, bus_number: str=None) -> bool: + """ + Added 8/27/18: Adds a SCSI Controller by node id + :param server_id: server id + :param adapter_type: the type of SCSI Adapter, i.e., LSI_LOGIC_PARALLEL + :param bus_number: optional number of server's bus + :return: whether addition is in progress or 'OK' otherwise false """ + + update_node = ET.Element('addScsiController', {'xmlns': TYPES_URN}) + ET.SubElement(update_node, 'serverId').text = server_id + ET.SubElement(update_node, 'adapterType').text = adapter_type + if bus_number is not None: + ET.SubElement(update_node, 'busNumber').text = bus_number + + result = self.connection.request_with_orgId_api_2( + 'server/addScsiController', + method='POST', + data=ET.tostring(update_node)).object + response_code = findtext(result, 'responseCode', TYPES_URN) + return response_code in ['IN_PROGRESS', 'OK'] + + def ex_remove_scsi_controller(self, controller_id: str) -> bool: + """ + Added 8/27/18: Adds a SCSI Controller by node id + :param controller_id: Scsi controller's id + :return: whether addition is in progress or 'OK' otherwise false + """ + update_node = ET.Element('removeScsiController', {'xmlns': TYPES_URN}) + update_node.set('id', controller_id) + result = self.connection.request_with_orgId_api_2( + 'server/removeScsiController', + method='POST', + data=ET.tostring(update_node)).object + response_code = findtext(result, 'responseCode', TYPES_URN) + return response_code in ['IN_PROGRESS', 'OK'] + + def ex_add_storage_to_node(self, amount, node=None, + speed='STANDARD', controller_id=None, scsi_id=None): + """ + Updated 8/23/18 Add storage to the node + One of node or controller_id must be selected - :param node: The server to add storage to + :param node: The server to add storage to (required if controller_id is not used :type node: :class:`Node` :param amount: The amount of storage to add, in GB @@ -2488,14 +2547,26 @@ class NttCisNodeDriver(NodeDriver): :param speed: The disk speed type :type speed: ``str`` + :param conrollter_id: The disk may be added using the cotnroller id (required if node object is not used) + :type controller_id: ``str`` + :param scsi_id: The target SCSI ID (optional) :type scsi_id: ``int`` :rtype: ``bool`` """ + + if (node is None and controller_id is None) or (node is not None and controller_id is not None): + raise RuntimeError("Either a node or a controller id must be specified") + update_node = ET.Element('addDisk', {'xmlns': TYPES_URN}) - update_node.set('id', node.id) + if node is not None: + ET.SubElement(update_node, 'serverId').text = node.id + elif controller_id is not None: + scsi_node = ET.Element('scsiController') + ET.SubElement(scsi_node, 'controllerId').text = controller_id + update_node.insert(1, scsi_node) ET.SubElement(update_node, 'sizeGb').text = str(amount) ET.SubElement(update_node, 'speed').text = speed.upper() if scsi_id is not None: @@ -2546,7 +2617,7 @@ class NttCisNodeDriver(NodeDriver): response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] - def ex_change_storage_speed(self, node, disk_id, speed): + def ex_change_storage_speed(self, disk_id, speed, iops=None): """ Change the speed (disk tier) of a disk @@ -2561,14 +2632,17 @@ class NttCisNodeDriver(NodeDriver): :rtype: ``bool`` """ - create_node = ET.Element('ChangeDiskSpeed', {'xmlns': SERVER_NS}) + create_node = ET.Element('changeDiskSpeed', {'xmlns': TYPES_URN}) + create_node.set('id', disk_id) ET.SubElement(create_node, 'speed').text = speed - result = self.connection.request_with_orgId_api_1( - 'server/%s/disk/%s/changeSpeed' % - (node.id, disk_id), + if iops is not None: + ET.SubElement(create_node, 'iops').text = str(iops) + #result = self.connection.request_with_orgId_api_1( + result = self.connection.request_with_orgId_api_2( + 'server/changeDiskSpeed', method='POST', data=ET.tostring(create_node)).object - response_code = findtext(result, 'result', GENERAL_NS) + response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_change_storage_size(self, node, disk_id, size): @@ -4573,9 +4647,14 @@ class NttCisNodeDriver(NodeDriver): version_status=version_status, api_version=api_version) + def _to_scsi_controllers(self, elements): + return NttCisScsiController(id=elements.get('id'), + adapter_type=elements.get('adapterType'), + bus_number=elements.get('busNumber'), + state=elements.get('state') + ) + def _to_disks(self, object): - for child in object.iter(): - print(child.tag, child.attrib) disk_elements = object.findall(fixxpath('disk', TYPES_URN)) return [self._to_disk(el) for el in disk_elements] @@ -4629,8 +4708,10 @@ class NttCisNodeDriver(NodeDriver): has_scsi = element.find(fixxpath('scsiController', TYPES_URN)) is not None has_sata = element.find(fixxpath('sataController', TYPES_URN)) is not None has_ide = element.find(fixxpath('ideController')) is not None + scsi_controllers = [] disks = [] if has_scsi: + scsi_controllers.append(self._to_scsi_controllers(element.find(fixxpath('scsiController', TYPES_URN)))) for scsi in element.findall(fixxpath('scsiController', TYPES_URN)): disks.extend(self._to_disks(scsi)) if has_sata: @@ -4685,6 +4766,7 @@ class NttCisNodeDriver(NodeDriver): 'OS_type': operation_system.get('family'), 'OS_displayName': operation_system.get('displayName'), 'status': status, + 'scsi_controller': scsi_controllers, 'disks': disks, 'vmWareTools': vmware_tools } http://git-wip-us.apache.org/repos/asf/libcloud/blob/141d235b/tests/lib_edit_test.py ---------------------------------------------------------------------- diff --git a/tests/lib_edit_test.py b/tests/lib_edit_test.py index 222ce6e..c86d3ce 100644 --- a/tests/lib_edit_test.py +++ b/tests/lib_edit_test.py @@ -90,14 +90,88 @@ def test_reconfigure_node(compute_driver): assert result is True -def test_add_disk(compute_driver): +def test_add_disk_by_node(compute_driver): + """ + Speeds can be specified based on DataCenter + :param compute_driver: libcloud.DriverType.COMPUTE.NTTCIS + :return: NA + """ + node = compute_driver.ex_get_node_by_id('803e5e00-b22a-450a-8827-066ff15ec977') + shut_result = compute_driver.ex_shutdown_graceful(node) + assert shut_result is True + compute_driver.ex_wait_for_state('stopped', compute_driver.ex_get_node_by_id, 2, 45, node.id) + result = compute_driver.ex_add_storage_to_node(20, node) + assert result is True + compute_driver.ex_wait_for_state('stopped', compute_driver.ex_get_node_by_id, 2, 180, node.id) + result = compute_driver.ex_start_node(node) + assert result is True + + +def test_add_disk_by_controller_id(compute_driver): + node = compute_driver.ex_get_node_by_id('803e5e00-b22a-450a-8827-066ff15ec977') + shut_result = compute_driver.ex_shutdown_graceful(node) + assert shut_result is True + compute_driver.ex_wait_for_state('stopped', compute_driver.ex_get_node_by_id, 2, 45, node.id) + result = compute_driver.ex_add_storage_to_node(20, controller_id=node.extra['scsi_controller'][0].id) + assert result is True + compute_driver.ex_wait_for_state('stopped', compute_driver.ex_get_node_by_id, 2, 180, node.id) + result = compute_driver.ex_start_node(node) + assert result is True + + +def test_changing_diskspeed(compute_driver): + node = compute_driver.ex_get_node_by_id('803e5e00-b22a-450a-8827-066ff15ec977') + shut_result = compute_driver.ex_shutdown_graceful(node) + assert shut_result is True + compute_driver.ex_wait_for_state('stopped', compute_driver.ex_get_node_by_id, 2, 45, node.id) + disk_id = 'f8a01c24-4768-46be-af75-9fe877f8c588' + result = compute_driver.ex_change_storage_speed(disk_id, 'HIGHPERFORMANCE') + assert result is True + compute_driver.ex_wait_for_state('stopped', compute_driver.ex_get_node_by_id, 2, 240, node.id) + result = compute_driver.ex_start_node(node) + assert result is True + + +def test_changing_diskspeed_iops(compute_driver): node = compute_driver.ex_get_node_by_id('803e5e00-b22a-450a-8827-066ff15ec977') - print(node) + shut_result = compute_driver.ex_shutdown_graceful(node) + assert shut_result is True + compute_driver.ex_wait_for_state('stopped', compute_driver.ex_get_node_by_id, 2, 45, node.id) + disk_id = 'f8a01c24-4768-46be-af75-9fe877f8c588' + result = compute_driver.ex_change_storage_speed(disk_id, 'PROVISIONEDIOPS', iops=60) + assert result is True + compute_driver.ex_wait_for_state('stopped', compute_driver.ex_get_node_by_id, 2, 240, node.id) + result = compute_driver.ex_start_node(node) + assert result is True -def test_remove_disk(compute_driver): +def test_add_scsi_controller(compute_driver): node = compute_driver.ex_get_node_by_id('803e5e00-b22a-450a-8827-066ff15ec977') - print(node) + shut_result = compute_driver.ex_shutdown_graceful(node) + assert shut_result is True + compute_driver.ex_wait_for_state('stopped', compute_driver.ex_get_node_by_id, 2, 45, node.id) + adapter_type = 'VMWARE_PARAVIRTUAL' + result = compute_driver.ex_add_scsi_controller_to_node(node.id, adapter_type) + assert result is True + compute_driver.ex_wait_for_state('stopped', compute_driver.ex_get_node_by_id, 2, 240, node.id) + result = compute_driver.ex_start_node(node) + assert result is True + + +def test_remove_scsi_controller(compute_driver): + node = compute_driver.ex_get_node_by_id('803e5e00-b22a-450a-8827-066ff15ec977') + shut_result = compute_driver.ex_shutdown_graceful(node) + assert shut_result is True + compute_driver.ex_wait_for_state('stopped', compute_driver.ex_get_node_by_id, 2, 45, node.id) + result = compute_driver.ex_remove_scsi_controller('f1126751-c6d5-4d64-893c-8902b8481f90') + assert result is True + compute_driver.ex_wait_for_state('stopped', compute_driver.ex_get_node_by_id, 2, 240, node.id) + result = compute_driver.ex_start_node(node) + assert result is True + + +def test_update_vmware_tools(compute_driver): + pass def test_list_locations(compute_driver): http://git-wip-us.apache.org/repos/asf/libcloud/blob/141d235b/tests/lib_list_test.py ---------------------------------------------------------------------- diff --git a/tests/lib_list_test.py b/tests/lib_list_test.py index fec88dc..f664068 100644 --- a/tests/lib_list_test.py +++ b/tests/lib_list_test.py @@ -6,9 +6,10 @@ from libcloud import loadbalancer def test_list_node_all(compute_driver): nodes = compute_driver.list_nodes() for node in nodes: - print(node.extra['networkDomainId'], node.extra['datacenterId'], node.uuid, node.state, node.name, node.extra['cpu'], - [disk for disk in node.extra['disks']], node.extra['memoryMb'], node.extra['OS_displayName'], - node.private_ips, node.extra['ipv6'], node.extra['window']) + print(node.extra['networkDomainId'], node.extra['datacenterId'], node.uuid, node.state, node.name, node.extra['cpu'], + node.extra['scsi_controller'], node.extra['disks'], node.extra['memoryMb'], + node.extra['OS_displayName'], node.private_ips, node.extra['ipv6'], node.extra['window']) + assert isinstance(nodes, list) and len(nodes) > 0 @@ -153,6 +154,10 @@ def test_list_vlan(compute_driver): assert vlan.name == 'sdk_vlan1' +def test_list_datacenter_object_creation(compute_driver): + datacenter = compute_driver.ex_get_datacenter('EU6') + + def test_list_firewall_rules(compute_driver): rules = compute_driver.ex_list_firewall_rules('6aafcf08-cb0b-432c-9c64-7371265db086') print()
