From 109ea5ae3fa3438e3da443b7ae86f915e610685d Mon Sep 17 00:00:00 2001 From: Ian Sutton Date: Thu, 20 Feb 2020 15:10:47 -0600 Subject: [PATCH 01/12] bring in convert/refresh funcs --- SoftLayer/CLI/block/convert.py | 17 +++++++++++++++++ SoftLayer/CLI/block/refresh.py | 18 ++++++++++++++++++ SoftLayer/CLI/file/convert.py | 17 +++++++++++++++++ SoftLayer/CLI/file/refresh.py | 18 ++++++++++++++++++ SoftLayer/CLI/routes.py | 4 ++++ SoftLayer/managers/block.py | 17 +++++++++++++++++ SoftLayer/managers/file.py | 17 +++++++++++++++++ docs/cli/block.rst | 7 +++++++ 8 files changed, 115 insertions(+) create mode 100644 SoftLayer/CLI/block/convert.py create mode 100644 SoftLayer/CLI/block/refresh.py create mode 100644 SoftLayer/CLI/file/convert.py create mode 100644 SoftLayer/CLI/file/refresh.py diff --git a/SoftLayer/CLI/block/convert.py b/SoftLayer/CLI/block/convert.py new file mode 100644 index 000000000..795d3d27c --- /dev/null +++ b/SoftLayer/CLI/block/convert.py @@ -0,0 +1,17 @@ +"""Convert a dependent duplicate volume to an indepdent volume.""" +# :license: MIT, see LICENSE for more details. + +import click +import SoftLayer +from SoftLayer.CLI import environment + + +@click.command() +@click.argument('volume_id') +@environment.pass_env +def cli(env, volume_id): + """Convert a dependent duplicate volume to an indepdent volume.""" + block_manager = SoftLayer.BlockStorageManager(env.client) + resp = block_manager.convert_dep_dupe(volume_id) + + click.echo(resp) diff --git a/SoftLayer/CLI/block/refresh.py b/SoftLayer/CLI/block/refresh.py new file mode 100644 index 000000000..66a2f3c22 --- /dev/null +++ b/SoftLayer/CLI/block/refresh.py @@ -0,0 +1,18 @@ +"""Refresh a dependent duplicate volume with a snapshot from its parent.""" +# :license: MIT, see LICENSE for more details. + +import click +import SoftLayer +from SoftLayer.CLI import environment + + +@click.command() +@click.argument('volume_id') +@click.argument('snapshot_id') +@environment.pass_env +def cli(env, volume_id, snapshot_id): + """"Refresh a dependent duplicate volume with a snapshot from its parent.""" + block_manager = SoftLayer.BlockStorageManager(env.client) + resp = block_manager.refresh_dep_dupe(volume_id, snapshot_id) + + click.echo(resp) diff --git a/SoftLayer/CLI/file/convert.py b/SoftLayer/CLI/file/convert.py new file mode 100644 index 000000000..7c01d8c53 --- /dev/null +++ b/SoftLayer/CLI/file/convert.py @@ -0,0 +1,17 @@ +"""Convert a dependent duplicate volume to an indepdent volume.""" +# :license: MIT, see LICENSE for more details. + +import click +import SoftLayer +from SoftLayer.CLI import environment + + +@click.command() +@click.argument('volume_id') +@environment.pass_env +def cli(env, volume_id): + """Convert a dependent duplicate volume to an indepdent volume.""" + file_manager = SoftLayer.FileStorageManager(env.client) + resp = file_manager.convert_dep_dupe(volume_id) + + click.echo(resp) diff --git a/SoftLayer/CLI/file/refresh.py b/SoftLayer/CLI/file/refresh.py new file mode 100644 index 000000000..c566dac91 --- /dev/null +++ b/SoftLayer/CLI/file/refresh.py @@ -0,0 +1,18 @@ +"""Refresh a dependent duplicate volume with a snapshot from its parent.""" +# :license: MIT, see LICENSE for more details. + +import click +import SoftLayer +from SoftLayer.CLI import environment + + +@click.command() +@click.argument('volume_id') +@click.argument('snapshot_id') +@environment.pass_env +def cli(env, volume_id, snapshot_id): + """"Refresh a dependent duplicate volume with a snapshot from its parent.""" + file_manager = SoftLayer.FileStorageManager(env.client) + resp = file_manager.refresh_dep_dupe(volume_id, snapshot_id) + + click.echo(resp) diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py index 27bfb0b23..b908be4f5 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -106,6 +106,8 @@ ('block:volume-order', 'SoftLayer.CLI.block.order:cli'), ('block:volume-set-lun-id', 'SoftLayer.CLI.block.lun:cli'), ('block:volume-limits', 'SoftLayer.CLI.block.limit:cli'), + ('block:volume-refresh', 'SoftLayer.CLI.block.refresh:cli'), + ('block:volume-convert', 'SoftLayer.CLI.block.convert:cli'), ('event-log', 'SoftLayer.CLI.event_log'), ('event-log:get', 'SoftLayer.CLI.event_log.get:cli'), @@ -137,6 +139,8 @@ ('file:volume-modify', 'SoftLayer.CLI.file.modify:cli'), ('file:volume-order', 'SoftLayer.CLI.file.order:cli'), ('file:volume-limits', 'SoftLayer.CLI.file.limit:cli'), + ('file:volume-refresh', 'SoftLayer.CLI.file.refresh:cli'), + ('file:volume-convert', 'SoftLayer.CLI.file.convert:cli'), ('firewall', 'SoftLayer.CLI.firewall'), ('firewall:add', 'SoftLayer.CLI.firewall.add:cli'), diff --git a/SoftLayer/managers/block.py b/SoftLayer/managers/block.py index 25e6839f2..8b379513f 100644 --- a/SoftLayer/managers/block.py +++ b/SoftLayer/managers/block.py @@ -616,3 +616,20 @@ def create_or_update_lun_id(self, volume_id, lun_id): """ return self.client.call('Network_Storage', 'createOrUpdateLunId', lun_id, id=volume_id) + + def refresh_dep_dupe(self, volume_id, snapshot_id): + """"Refresh a dependent duplicate volume with a snapshot from its parent. + + :param integer volume_id: The id of the volume + :param integer snapshot_id: The id of the snapshot + """ + return self.client.call('Network_Storage', 'refreshDependentDuplicate', + snapshot_id, id=volume_id) + + def convert_dep_dupe(self, volume_id): + """Convert a dependent duplicate volume to an indepdent volume. + + :param integer volume_id: The id of the volume. + """ + return self.client.call('Network_Storage', 'convertCloneDependentToIndependent', + id=volume_id) diff --git a/SoftLayer/managers/file.py b/SoftLayer/managers/file.py index 0a5214e67..2876daf98 100644 --- a/SoftLayer/managers/file.py +++ b/SoftLayer/managers/file.py @@ -527,3 +527,20 @@ def failback_from_replicant(self, volume_id): """ return self.client.call('Network_Storage', 'failbackFromReplicant', id=volume_id) + + def refresh_dep_dupe(self, volume_id, snapshot_id): + """"Refresh a dependent duplicate volume with a snapshot from its parent. + + :param integer volume_id: The id of the volume + :param integer snapshot_id: The id of the snapshot + """ + return self.client.call('Network_Storage', 'refreshDependentDuplicate', + snapshot_id, id=volume_id) + + def convert_dep_dupe(self, volume_id): + """Convert a dependent duplicate volume to an indepdent volume. + + :param integer volume_id: The id of the volume. + """ + return self.client.call('Network_Storage', 'convertCloneDependentToIndependent', + id=volume_id) diff --git a/docs/cli/block.rst b/docs/cli/block.rst index 851d7d84c..860872ce7 100644 --- a/docs/cli/block.rst +++ b/docs/cli/block.rst @@ -111,6 +111,13 @@ Block Commands :prog: block volume-limits :show-nested: +.. click:: SoftLayer.CLI.block.refresh:cli + :prog block volume-refresh + :show-nested: + +.. click:: SoftLayer.CLI.block.convert:cli + :prog block volume-convert + :show-nested: .. click:: SoftLayer.CLI.block.subnets.list:cli :prog: block subnets-list From 4007d758b43dbf7c1562200bd69210c9a690e236 Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Thu, 20 Feb 2020 18:02:41 -0400 Subject: [PATCH 02/12] Fix the block and file storage detail. --- SoftLayer/CLI/block/detail.py | 15 ++++++++++- SoftLayer/CLI/file/detail.py | 15 ++++++++++- tests/CLI/modules/block_tests.py | 43 ++++++++++++++++++++++++++++++++ tests/CLI/modules/file_tests.py | 43 ++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 2 deletions(-) diff --git a/SoftLayer/CLI/block/detail.py b/SoftLayer/CLI/block/detail.py index 6b1b7288c..73e93298f 100644 --- a/SoftLayer/CLI/block/detail.py +++ b/SoftLayer/CLI/block/detail.py @@ -5,16 +5,29 @@ import SoftLayer from SoftLayer.CLI import environment from SoftLayer.CLI import formatting +from SoftLayer.CLI import helpers from SoftLayer import utils +def get_block_volume_id(volume_id, block_manager): + storage_list = block_manager.list_block_volumes() + for storage in storage_list: + if volume_id == storage['username']: + volume_id = storage['id'] + break + + return volume_id + + @click.command() @click.argument('volume_id') @environment.pass_env def cli(env, volume_id): """Display details for a specified volume.""" block_manager = SoftLayer.BlockStorageManager(env.client) - block_volume = block_manager.get_block_volume_details(volume_id) + volume_id = get_block_volume_id(volume_id, block_manager) + block_volume_id = helpers.resolve_id(block_manager.resolve_ids, volume_id, 'Block Volume') + block_volume = block_manager.get_block_volume_details(block_volume_id) block_volume = utils.NestedDict(block_volume) table = formatting.KeyValueTable(['Name', 'Value']) diff --git a/SoftLayer/CLI/file/detail.py b/SoftLayer/CLI/file/detail.py index 02bb5c17a..25af366f2 100644 --- a/SoftLayer/CLI/file/detail.py +++ b/SoftLayer/CLI/file/detail.py @@ -5,16 +5,29 @@ import SoftLayer from SoftLayer.CLI import environment from SoftLayer.CLI import formatting +from SoftLayer.CLI import helpers from SoftLayer import utils +def get_file_volume_id(volume_id, file_manager): + storage_list = file_manager.list_file_volumes() + for storage in storage_list: + if volume_id == storage['username']: + volume_id = storage['id'] + break + + return volume_id + + @click.command() @click.argument('volume_id') @environment.pass_env def cli(env, volume_id): """Display details for a specified volume.""" file_manager = SoftLayer.FileStorageManager(env.client) - file_volume = file_manager.get_file_volume_details(volume_id) + volume_id = get_file_volume_id(volume_id, file_manager) + file_volume_id = helpers.resolve_id(file_manager.resolve_ids, volume_id, 'File Storage') + file_volume = file_manager.get_file_volume_details(file_volume_id) file_volume = utils.NestedDict(file_volume) table = formatting.KeyValueTable(['Name', 'Value']) diff --git a/tests/CLI/modules/block_tests.py b/tests/CLI/modules/block_tests.py index e59288981..42e574c48 100644 --- a/tests/CLI/modules/block_tests.py +++ b/tests/CLI/modules/block_tests.py @@ -98,6 +98,49 @@ def test_volume_detail(self): ] }, json.loads(result.output)) + def test_volume_detail_name_identifier(self): + result = self.run_command(['block', 'volume-detail', 'username']) + + self.assert_no_fail(result) + isinstance(json.loads(result.output)['IOPs'], float) + self.assertEqual({ + 'Username': 'username', + 'LUN Id': '2', + 'Endurance Tier': 'READHEAVY_TIER', + 'IOPs': 1000, + 'Snapshot Capacity (GB)': '10', + 'Snapshot Used (Bytes)': 1024, + 'Capacity (GB)': '20GB', + 'Target IP': '10.1.2.3', + 'Data Center': 'dal05', + 'Type': 'ENDURANCE', + 'ID': 100, + '# of Active Transactions': '1', + 'Ongoing Transaction': 'This is a buffer time in which the customer may cancel the server', + 'Replicant Count': '1', + 'Replication Status': 'Replicant Volume Provisioning ' + 'has completed.', + 'Replicant Volumes': [[ + {'Replicant ID': 'Volume Name', '1784': 'TEST_REP_1'}, + {'Replicant ID': 'Target IP', '1784': '10.3.174.79'}, + {'Replicant ID': 'Data Center', '1784': 'wdc01'}, + {'Replicant ID': 'Schedule', '1784': 'REPLICATION_HOURLY'}, + ], [ + {'Replicant ID': 'Volume Name', '1785': 'TEST_REP_2'}, + {'Replicant ID': 'Target IP', '1785': '10.3.177.84'}, + {'Replicant ID': 'Data Center', '1785': 'dal01'}, + {'Replicant ID': 'Schedule', '1785': 'REPLICATION_DAILY'}, + ]], + 'Original Volume Properties': [ + {'Property': 'Original Volume Size', + 'Value': '20'}, + {'Property': 'Original Volume Name', + 'Value': 'test-original-volume-name'}, + {'Property': 'Original Snapshot Name', + 'Value': 'test-original-snapshot-name'} + ] + }, json.loads(result.output)) + def test_volume_list(self): result = self.run_command(['block', 'volume-list']) diff --git a/tests/CLI/modules/file_tests.py b/tests/CLI/modules/file_tests.py index e1d8628cb..e5e3ca556 100644 --- a/tests/CLI/modules/file_tests.py +++ b/tests/CLI/modules/file_tests.py @@ -163,6 +163,49 @@ def test_volume_detail(self): ] }, json.loads(result.output)) + def test_volume_detail_name_identifier(self): + result = self.run_command(['file', 'volume-detail', 'user']) + + self.assert_no_fail(result) + self.assertEqual({ + 'Username': 'username', + 'Used Space': '0B', + 'Endurance Tier': 'READHEAVY_TIER', + 'IOPs': 1000, + 'Mount Address': '127.0.0.1:/TEST', + 'Snapshot Capacity (GB)': '10', + 'Snapshot Used (Bytes)': 1024, + 'Capacity (GB)': '20GB', + 'Target IP': '10.1.2.3', + 'Data Center': 'dal05', + 'Type': 'ENDURANCE', + 'ID': 100, + '# of Active Transactions': '1', + 'Ongoing Transaction': 'This is a buffer time in which the customer may cancel the server', + 'Replicant Count': '1', + 'Replication Status': 'Replicant Volume Provisioning ' + 'has completed.', + 'Replicant Volumes': [[ + {'Replicant ID': 'Volume Name', '1784': 'TEST_REP_1'}, + {'Replicant ID': 'Target IP', '1784': '10.3.174.79'}, + {'Replicant ID': 'Data Center', '1784': 'wdc01'}, + {'Replicant ID': 'Schedule', '1784': 'REPLICATION_HOURLY'}, + ], [ + {'Replicant ID': 'Volume Name', '1785': 'TEST_REP_2'}, + {'Replicant ID': 'Target IP', '1785': '10.3.177.84'}, + {'Replicant ID': 'Data Center', '1785': 'dal01'}, + {'Replicant ID': 'Schedule', '1785': 'REPLICATION_DAILY'}, + ]], + 'Original Volume Properties': [ + {'Property': 'Original Volume Size', + 'Value': '20'}, + {'Property': 'Original Volume Name', + 'Value': 'test-original-volume-name'}, + {'Property': 'Original Snapshot Name', + 'Value': 'test-original-snapshot-name'} + ] + }, json.loads(result.output)) + def test_volume_order_performance_iops_not_given(self): result = self.run_command(['file', 'volume-order', '--storage-type=performance', '--size=20', From b07e0ecd2ebb109ef3babb3df4b19edfb6706a3c Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Thu, 20 Feb 2020 18:18:33 -0400 Subject: [PATCH 03/12] Add docstring for block and file new method. --- SoftLayer/CLI/block/detail.py | 6 ++++++ SoftLayer/CLI/file/detail.py | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/SoftLayer/CLI/block/detail.py b/SoftLayer/CLI/block/detail.py index 73e93298f..02ce0c82f 100644 --- a/SoftLayer/CLI/block/detail.py +++ b/SoftLayer/CLI/block/detail.py @@ -10,6 +10,12 @@ def get_block_volume_id(volume_id, block_manager): + """Returns the volume id. + + :param volume_id: ID of volume. + :param block_manager: Block Storage Manager. + :return: Returns the volume id. + """ storage_list = block_manager.list_block_volumes() for storage in storage_list: if volume_id == storage['username']: diff --git a/SoftLayer/CLI/file/detail.py b/SoftLayer/CLI/file/detail.py index 25af366f2..ad0393916 100644 --- a/SoftLayer/CLI/file/detail.py +++ b/SoftLayer/CLI/file/detail.py @@ -10,6 +10,12 @@ def get_file_volume_id(volume_id, file_manager): + """Returns the volume id. + + :param volume_id: ID of volume. + :param block_manager: Block Storage Manager. + :return: Returns the volume id. + """ storage_list = file_manager.list_file_volumes() for storage in storage_list: if volume_id == storage['username']: From dab368eb153110bc0eace325f4a2c701d5fd02a2 Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Wed, 26 Feb 2020 16:01:42 -0600 Subject: [PATCH 04/12] #1233 refactored the file/block managers to reduce duplicated code --- .../fixtures/SoftLayer_Location_Datacenter.py | 12 + SoftLayer/managers/block.py | 451 +----------------- SoftLayer/managers/file.py | 381 +-------------- SoftLayer/managers/storage.py | 415 ++++++++++++++++ SoftLayer/managers/storage_utils.py | 17 +- tests/managers/block_tests.py | 125 ++--- tests/managers/file_tests.py | 106 ++-- 7 files changed, 585 insertions(+), 922 deletions(-) create mode 100644 SoftLayer/fixtures/SoftLayer_Location_Datacenter.py create mode 100644 SoftLayer/managers/storage.py diff --git a/SoftLayer/fixtures/SoftLayer_Location_Datacenter.py b/SoftLayer/fixtures/SoftLayer_Location_Datacenter.py new file mode 100644 index 000000000..510fa18e7 --- /dev/null +++ b/SoftLayer/fixtures/SoftLayer_Location_Datacenter.py @@ -0,0 +1,12 @@ +getDatacenters = [ + { + "id": 1441195, + "longName": "Dallas 10", + "name": "dal10" + }, + { + "id": 449494, + "longName": "Dallas 9", + "name": "dal09" + } +] \ No newline at end of file diff --git a/SoftLayer/managers/block.py b/SoftLayer/managers/block.py index 11b998935..4ff3faa86 100644 --- a/SoftLayer/managers/block.py +++ b/SoftLayer/managers/block.py @@ -7,32 +7,27 @@ """ from SoftLayer import exceptions from SoftLayer.managers import storage_utils +from SoftLayer.managers.storage import StorageManager + from SoftLayer import utils # pylint: disable=too-many-public-methods -class BlockStorageManager(utils.IdentifierMixin, object): +class BlockStorageManager(StorageManager): """Manages SoftLayer Block Storage volumes. See product information here: http://www.softlayer.com/block-storage - - :param SoftLayer.API.BaseClient client: the client instance """ - def __init__(self, client): - self.configuration = {} - self.client = client - def list_block_volume_limit(self): """Returns a list of block volume count limit. :return: Returns a list of block volume count limit. """ - return self.client.call('Network_Storage', 'getVolumeCountLimits') + return self.get_volume_count_limits() - def list_block_volumes(self, datacenter=None, username=None, - storage_type=None, **kwargs): + def list_block_volumes(self, datacenter=None, username=None, storage_type=None, **kwargs): """Returns a list of block volumes. :param datacenter: Datacenter short name (e.g.: dal09) @@ -84,35 +79,8 @@ def get_block_volume_details(self, volume_id, **kwargs): :param kwargs: :return: Returns details about the specified volume. """ + return self.get_volume_details(volume_id, **kwargs) - if 'mask' not in kwargs: - items = [ - 'id', - 'username', - 'password', - 'capacityGb', - 'snapshotCapacityGb', - 'parentVolume.snapshotSizeBytes', - 'storageType.keyName', - 'serviceResource.datacenter[name]', - 'serviceResourceBackendIpAddress', - 'storageTierLevel', - 'provisionedIops', - 'lunId', - 'originalVolumeName', - 'originalSnapshotName', - 'originalVolumeSize', - 'activeTransactionCount', - 'activeTransactions.transactionStatus[friendlyName]', - 'replicationPartnerCount', - 'replicationStatus', - 'replicationPartners[id,username,' - 'serviceResourceBackendIpAddress,' - 'serviceResource[datacenter[name]],' - 'replicationSchedule[type[keyname]]]', - ] - kwargs['mask'] = ','.join(items) - return self.client.call('Network_Storage', 'getObject', id=volume_id, **kwargs) def get_block_volume_access_list(self, volume_id, **kwargs): """Returns a list of authorized hosts for a specified volume. @@ -121,17 +89,7 @@ def get_block_volume_access_list(self, volume_id, **kwargs): :param kwargs: :return: Returns a list of authorized hosts for a specified volume. """ - if 'mask' not in kwargs: - items = [ - 'id', - 'allowedVirtualGuests[allowedHost[credential, sourceSubnet]]', - 'allowedHardware[allowedHost[credential]]', - 'allowedSubnets[allowedHost[credential]]', - 'allowedIpAddresses[allowedHost[credential]]', - ] - kwargs['mask'] = ','.join(items) - return self.client.call('Network_Storage', 'getObject', - id=volume_id, **kwargs) + return self.get_volume_access_list(volume_id, **kwargs) def get_block_volume_snapshot_list(self, volume_id, **kwargs): """Returns a list of snapshots for the specified volume. @@ -140,73 +98,8 @@ def get_block_volume_snapshot_list(self, volume_id, **kwargs): :param kwargs: :return: Returns a list of snapshots for the specified volume. """ - if 'mask' not in kwargs: - items = [ - 'id', - 'notes', - 'snapshotSizeBytes', - 'storageType[keyName]', - 'snapshotCreationTimestamp', - 'intervalSchedule', - 'hourlySchedule', - 'dailySchedule', - 'weeklySchedule' - ] + return self.get_volume_snapshot_list(volume_id, **kwargs) - kwargs['mask'] = ','.join(items) - - return self.client.call('Network_Storage', 'getSnapshots', - id=volume_id, **kwargs) - - def authorize_host_to_volume(self, volume_id, - hardware_ids=None, - virtual_guest_ids=None, - ip_address_ids=None, - **kwargs): - """Authorizes hosts to Block Storage Volumes - - :param volume_id: The Block volume to authorize hosts to - :param hardware_ids: A List of SoftLayer_Hardware ids - :param virtual_guest_ids: A List of SoftLayer_Virtual_Guest ids - :param ip_address_ids: A List of SoftLayer_Network_Subnet_IpAddress ids - :return: Returns an array of - SoftLayer_Network_Storage_Allowed_Host objects - which now have access to the given Block volume - """ - host_templates = [] - storage_utils.populate_host_templates(host_templates, - hardware_ids, - virtual_guest_ids, - ip_address_ids, - None) - - return self.client.call('Network_Storage', 'allowAccessFromHostList', - host_templates, id=volume_id, **kwargs) - - def deauthorize_host_to_volume(self, volume_id, - hardware_ids=None, - virtual_guest_ids=None, - ip_address_ids=None, - **kwargs): - """Revokes authorization of hosts to Block Storage Volumes - - :param volume_id: The Block volume to deauthorize hosts to - :param hardware_ids: A List of SoftLayer_Hardware ids - :param virtual_guest_ids: A List of SoftLayer_Virtual_Guest ids - :param ip_address_ids: A List of SoftLayer_Network_Subnet_IpAddress ids - :return: Returns an array of - SoftLayer_Network_Storage_Allowed_Host objects - which have access to the given Block volume - """ - host_templates = [] - storage_utils.populate_host_templates(host_templates, - hardware_ids, - virtual_guest_ids, - ip_address_ids, - None) - - return self.client.call('Network_Storage', 'removeAccessFromHostList', - host_templates, id=volume_id, **kwargs) def assign_subnets_to_acl(self, access_id, subnet_ids): """Assigns subnet records to ACL for the access host. @@ -217,10 +110,7 @@ def assign_subnets_to_acl(self, access_id, subnet_ids): :param list subnet_ids: The ids of the subnets to be assigned :return: Returns int array of assigned subnet ids """ - return self.client.call('Network_Storage_Allowed_Host', - 'assignSubnetsToAcl', - subnet_ids, - id=access_id) + return self.client.call('Network_Storage_Allowed_Host', 'assignSubnetsToAcl', subnet_ids, id=access_id) def remove_subnets_from_acl(self, access_id, subnet_ids): """Removes subnet records from ACL for the access host. @@ -231,10 +121,7 @@ def remove_subnets_from_acl(self, access_id, subnet_ids): :param list subnet_ids: The ids of the subnets to be removed :return: Returns int array of removed subnet ids """ - return self.client.call('Network_Storage_Allowed_Host', - 'removeSubnetsFromAcl', - subnet_ids, - id=access_id) + return self.client.call('Network_Storage_Allowed_Host', 'removeSubnetsFromAcl', subnet_ids, id=access_id) def get_subnets_in_acl(self, access_id): """Returns a list of subnet records for the access host. @@ -244,148 +131,7 @@ def get_subnets_in_acl(self, access_id): :param integer access_id: id of the access host :return: Returns an array of SoftLayer_Network_Subnet objects """ - return self.client.call('Network_Storage_Allowed_Host', - 'getSubnetsInAcl', - id=access_id) - - def get_replication_partners(self, volume_id): - """Acquires list of replicant volumes pertaining to the given volume. - - :param volume_id: The ID of the primary volume to be replicated - :return: Returns an array of SoftLayer_Location objects - """ - return self.client.call('Network_Storage', - 'getReplicationPartners', - id=volume_id) - - def get_replication_locations(self, volume_id): - """Acquires list of the datacenters to which a volume can be replicated. - - :param volume_id: The ID of the primary volume to be replicated - :return: Returns an array of SoftLayer_Network_Storage objects - """ - return self.client.call('Network_Storage', - 'getValidReplicationTargetDatacenterLocations', - id=volume_id) - - def order_replicant_volume(self, volume_id, snapshot_schedule, - location, tier=None, os_type=None): - """Places an order for a replicant block volume. - - :param volume_id: The ID of the primary volume to be replicated - :param snapshot_schedule: The primary volume's snapshot - schedule to use for replication - :param location: The location for the ordered replicant volume - :param tier: The tier (IOPS per GB) of the primary volume - :param os_type: The OS type of the primary volume - :return: Returns a SoftLayer_Container_Product_Order_Receipt - """ - - block_mask = 'billingItem[activeChildren,hourlyFlag],'\ - 'storageTierLevel,osType,staasVersion,'\ - 'hasEncryptionAtRest,snapshotCapacityGb,schedules,'\ - 'intervalSchedule,hourlySchedule,dailySchedule,'\ - 'weeklySchedule,storageType[keyName],provisionedIops' - block_volume = self.get_block_volume_details(volume_id, - mask=block_mask) - - if os_type is None: - if isinstance(utils.lookup(block_volume, 'osType', 'keyName'), - str): - os_type = block_volume['osType']['keyName'] - else: - raise exceptions.SoftLayerError( - "Cannot find primary volume's os-type " - "automatically; must specify manually") - - order = storage_utils.prepare_replicant_order_object( - self, snapshot_schedule, location, tier, block_volume, 'block' - ) - - order['osFormatType'] = {'keyName': os_type} - - return self.client.call('Product_Order', 'placeOrder', order) - - def order_duplicate_volume(self, origin_volume_id, origin_snapshot_id=None, - duplicate_size=None, duplicate_iops=None, - duplicate_tier_level=None, - duplicate_snapshot_size=None, - hourly_billing_flag=False): - """Places an order for a duplicate block volume. - - :param origin_volume_id: The ID of the origin volume to be duplicated - :param origin_snapshot_id: Origin snapshot ID to use for duplication - :param duplicate_size: Size/capacity for the duplicate volume - :param duplicate_iops: The IOPS per GB for the duplicate volume - :param duplicate_tier_level: Tier level for the duplicate volume - :param duplicate_snapshot_size: Snapshot space size for the duplicate - :param hourly_billing_flag: Billing type, monthly (False) - or hourly (True), default to monthly. - :return: Returns a SoftLayer_Container_Product_Order_Receipt - """ - - block_mask = 'id,billingItem[location,hourlyFlag],snapshotCapacityGb,'\ - 'storageType[keyName],capacityGb,originalVolumeSize,'\ - 'provisionedIops,storageTierLevel,osType[keyName],'\ - 'staasVersion,hasEncryptionAtRest' - origin_volume = self.get_block_volume_details(origin_volume_id, - mask=block_mask) - - if isinstance(utils.lookup(origin_volume, 'osType', 'keyName'), str): - os_type = origin_volume['osType']['keyName'] - else: - raise exceptions.SoftLayerError( - "Cannot find origin volume's os-type") - - order = storage_utils.prepare_duplicate_order_object( - self, origin_volume, duplicate_iops, duplicate_tier_level, - duplicate_size, duplicate_snapshot_size, 'block', - hourly_billing_flag - ) - - order['osFormatType'] = {'keyName': os_type} - - if origin_snapshot_id is not None: - order['duplicateOriginSnapshotId'] = origin_snapshot_id - - return self.client.call('Product_Order', 'placeOrder', order) - - def order_modified_volume(self, volume_id, new_size=None, new_iops=None, new_tier_level=None): - """Places an order for modifying an existing block volume. - - :param volume_id: The ID of the volume to be modified - :param new_size: The new size/capacity for the volume - :param new_iops: The new IOPS for the volume - :param new_tier_level: The new tier level for the volume - :return: Returns a SoftLayer_Container_Product_Order_Receipt - """ - - mask_items = [ - 'id', - 'billingItem', - 'storageType[keyName]', - 'capacityGb', - 'provisionedIops', - 'storageTierLevel', - 'staasVersion', - 'hasEncryptionAtRest', - ] - block_mask = ','.join(mask_items) - volume = self.get_block_volume_details(volume_id, mask=block_mask) - - order = storage_utils.prepare_modify_order_object( - self, volume, new_iops, new_tier_level, new_size - ) - - return self.client.call('Product_Order', 'placeOrder', order) - - def delete_snapshot(self, snapshot_id): - """Deletes the specified snapshot object. - - :param snapshot_id: The ID of the snapshot object to delete. - """ - return self.client.call('Network_Storage', 'deleteObject', - id=snapshot_id) + return self.client.call('Network_Storage_Allowed_Host', 'getSubnetsInAcl', id=access_id) def order_block_volume(self, storage_type, location, size, os_type, iops=None, tier_level=None, snapshot_size=None, @@ -415,182 +161,14 @@ def order_block_volume(self, storage_type, location, size, os_type, return self.client.call('Product_Order', 'placeOrder', order) - def create_snapshot(self, volume_id, notes='', **kwargs): - """Creates a snapshot on the given block volume. - - :param integer volume_id: The id of the volume - :param string notes: The notes or "name" to assign the snapshot - :return: Returns the id of the new snapshot - """ - - return self.client.call('Network_Storage', 'createSnapshot', - notes, id=volume_id, **kwargs) - - def order_snapshot_space(self, volume_id, capacity, tier, - upgrade, **kwargs): - """Orders snapshot space for the given block volume. - - :param integer volume_id: The id of the volume - :param integer capacity: The capacity to order, in GB - :param float tier: The tier level of the block volume, in IOPS per GB - :param boolean upgrade: Flag to indicate if this order is an upgrade - :return: Returns a SoftLayer_Container_Product_Order_Receipt - """ - block_mask = 'id,billingItem[location,hourlyFlag],'\ - 'storageType[keyName],storageTierLevel,provisionedIops,'\ - 'staasVersion,hasEncryptionAtRest' - block_volume = self.get_block_volume_details(volume_id, - mask=block_mask, - **kwargs) - - order = storage_utils.prepare_snapshot_order_object( - self, block_volume, capacity, tier, upgrade) - - return self.client.call('Product_Order', 'placeOrder', order) - - def cancel_snapshot_space(self, volume_id, - reason='No longer needed', - immediate=False): - """Cancels snapshot space for a given volume. - - :param integer volume_id: The volume ID - :param string reason: The reason for cancellation - :param boolean immediate_flag: Cancel immediately or on anniversary date - """ - - block_volume = self.get_block_volume_details( - volume_id, - mask='mask[id,billingItem[activeChildren,hourlyFlag]]') - - if 'activeChildren' not in block_volume['billingItem']: - raise exceptions.SoftLayerError( - 'No snapshot space found to cancel') - - children_array = block_volume['billingItem']['activeChildren'] - billing_item_id = None - - for child in children_array: - if child['categoryCode'] == 'storage_snapshot_space': - billing_item_id = child['id'] - break - - if not billing_item_id: - raise exceptions.SoftLayerError( - 'No snapshot space found to cancel') - - if utils.lookup(block_volume, 'billingItem', 'hourlyFlag'): - immediate = True - - return self.client['Billing_Item'].cancelItem( - immediate, - True, - reason, - id=billing_item_id) - - def enable_snapshots(self, volume_id, schedule_type, retention_count, - minute, hour, day_of_week, **kwargs): - """Enables snapshots for a specific block volume at a given schedule - - :param integer volume_id: The id of the volume - :param string schedule_type: 'HOURLY'|'DAILY'|'WEEKLY' - :param integer retention_count: Number of snapshots to be kept - :param integer minute: Minute when to take snapshot - :param integer hour: Hour when to take snapshot - :param string day_of_week: Day when to take snapshot - :return: Returns whether successfully scheduled or not - """ - - return self.client.call('Network_Storage', 'enableSnapshots', - schedule_type, - retention_count, - minute, - hour, - day_of_week, - id=volume_id, - **kwargs) - - def disable_snapshots(self, volume_id, schedule_type): - """Disables snapshots for a specific block volume at a given schedule - - :param integer volume_id: The id of the volume - :param string schedule_type: 'HOURLY'|'DAILY'|'WEEKLY' - :return: Returns whether successfully disabled or not - """ - - return self.client.call('Network_Storage', 'disableSnapshots', - schedule_type, id=volume_id) - - def list_volume_schedules(self, volume_id): - """Lists schedules for a given volume - - :param integer volume_id: The id of the volume - :return: Returns list of schedules assigned to a given volume - """ - volume_detail = self.client.call( - 'Network_Storage', - 'getObject', - id=volume_id, - mask='schedules[type,properties[type]]') - - return utils.lookup(volume_detail, 'schedules') - - def restore_from_snapshot(self, volume_id, snapshot_id): - """Restores a specific volume from a snapshot - - :param integer volume_id: The id of the volume - :param integer snapshot_id: The id of the restore point - :return: Returns whether succesfully restored or not - """ - - return self.client.call('Network_Storage', 'restoreFromSnapshot', - snapshot_id, id=volume_id) - - def cancel_block_volume(self, volume_id, - reason='No longer needed', - immediate=False): + def cancel_block_volume(self, volume_id, reason='No longer needed', immediate=False): """Cancels the given block storage volume. :param integer volume_id: The volume ID :param string reason: The reason for cancellation :param boolean immediate_flag: Cancel immediately or on anniversary date """ - block_volume = self.get_block_volume_details( - volume_id, - mask='mask[id,billingItem[id,hourlyFlag]]') - - if 'billingItem' not in block_volume: - raise exceptions.SoftLayerError("Block Storage was already cancelled") - - billing_item_id = block_volume['billingItem']['id'] - - if utils.lookup(block_volume, 'billingItem', 'hourlyFlag'): - immediate = True - - return self.client['Billing_Item'].cancelItem( - immediate, - True, - reason, - id=billing_item_id) - - def failover_to_replicant(self, volume_id, replicant_id): - """Failover to a volume replicant. - - :param integer volume_id: The id of the volume - :param integer replicant_id: ID of replicant to failover to - :return: Returns whether failover was successful or not - """ - - return self.client.call('Network_Storage', 'failoverToReplicant', - replicant_id, id=volume_id) - - def failback_from_replicant(self, volume_id): - """Failback from a volume replicant. - - :param integer volume_id: The id of the volume - :return: Returns whether failback was successful or not - """ - - return self.client.call('Network_Storage', 'failbackFromReplicant', id=volume_id) + return self.cancel_volume(volume_id, reason, immediate) def set_credential_password(self, access_id, password): """Sets the password for an access host @@ -609,5 +187,4 @@ def create_or_update_lun_id(self, volume_id, lun_id): :param integer lun_id: LUN ID to set on the volume :return: a SoftLayer_Network_Storage_Property object """ - return self.client.call('Network_Storage', 'createOrUpdateLunId', - lun_id, id=volume_id) + return self.client.call('Network_Storage', 'createOrUpdateLunId', lun_id, id=volume_id) diff --git a/SoftLayer/managers/file.py b/SoftLayer/managers/file.py index 95cf85c88..367ce559a 100644 --- a/SoftLayer/managers/file.py +++ b/SoftLayer/managers/file.py @@ -7,27 +7,23 @@ """ from SoftLayer import exceptions from SoftLayer.managers import storage_utils +from SoftLayer.managers.storage import StorageManager from SoftLayer import utils # pylint: disable=too-many-public-methods -class FileStorageManager(utils.IdentifierMixin, object): +class FileStorageManager(StorageManager): """Manages file Storage volumes.""" - def __init__(self, client): - self.configuration = {} - self.client = client - def list_file_volume_limit(self): - """Returns a list of file volume count limit. + """Returns a list of block volume count limit. - :return: Returns a list of file volume count limit. + :return: Returns a list of block volume count limit. """ - return self.client.call('Network_Storage', 'getVolumeCountLimits') + return self.get_volume_count_limits() - def list_file_volumes(self, datacenter=None, username=None, - storage_type=None, **kwargs): + def list_file_volumes(self, datacenter=None, username=None, storage_type=None, **kwargs): """Returns a list of file volumes. :param datacenter: Datacenter short name (e.g.: dal09) @@ -109,8 +105,7 @@ def get_file_volume_details(self, volume_id, **kwargs): 'replicationSchedule[type[keyname]]]', ] kwargs['mask'] = ','.join(items) - return self.client.call('Network_Storage', 'getObject', - id=volume_id, **kwargs) + return self.get_volume_details(volume_id, **kwargs) def get_file_volume_access_list(self, volume_id, **kwargs): """Returns a list of authorized hosts for a specified volume. @@ -119,17 +114,7 @@ def get_file_volume_access_list(self, volume_id, **kwargs): :param kwargs: :return: Returns a list of authorized hosts for a specified volume. """ - if 'mask' not in kwargs: - items = [ - 'id', - 'allowedVirtualGuests[allowedHost[credential, sourceSubnet]]', - 'allowedHardware[allowedHost[credential]]', - 'allowedSubnets[allowedHost[credential]]', - 'allowedIpAddresses[allowedHost[credential]]', - ] - kwargs['mask'] = ','.join(items) - return self.client.call('Network_Storage', 'getObject', - id=volume_id, **kwargs) + return self.get_volume_access_list(volume_id, **kwargs) def get_file_volume_snapshot_list(self, volume_id, **kwargs): """Returns a list of snapshots for the specified volume. @@ -138,195 +123,8 @@ def get_file_volume_snapshot_list(self, volume_id, **kwargs): :param kwargs: :return: Returns a list of snapshots for the specified volume. """ - if 'mask' not in kwargs: - items = [ - 'id', - 'notes', - 'snapshotSizeBytes', - 'storageType[keyName]', - 'snapshotCreationTimestamp', - 'intervalSchedule', - 'hourlySchedule', - 'dailySchedule', - 'weeklySchedule' - ] - kwargs['mask'] = ','.join(items) - - return self.client.call('Network_Storage', 'getSnapshots', - id=volume_id, **kwargs) - - def authorize_host_to_volume(self, volume_id, - hardware_ids=None, - virtual_guest_ids=None, - ip_address_ids=None, - subnet_ids=None, - **kwargs): - """Authorizes hosts to File Storage Volumes - - :param volume_id: The File volume to authorize hosts to - :param hardware_ids: A List of SoftLayer_Hardware ids - :param virtual_guest_ids: A List of SoftLayer_Virtual_Guest ids - :param ip_address_ids: A List of SoftLayer_Network_Subnet_IpAddress ids - :param subnet_ids: A List of SoftLayer_Network_Subnet ids - :return: Returns an array of - SoftLayer_Network_Storage_Allowed_Host objects - which now have access to the given File volume - """ - host_templates = [] - storage_utils.populate_host_templates(host_templates, - hardware_ids, - virtual_guest_ids, - ip_address_ids, - subnet_ids) - - return self.client.call('Network_Storage', 'allowAccessFromHostList', - host_templates, id=volume_id, **kwargs) - - def deauthorize_host_to_volume(self, volume_id, - hardware_ids=None, - virtual_guest_ids=None, - ip_address_ids=None, - subnet_ids=None, - **kwargs): - """Revokes authorization of hosts to File Storage Volumes - - :param volume_id: The File volume to deauthorize hosts to - :param hardware_ids: A List of SoftLayer_Hardware ids - :param virtual_guest_ids: A List of SoftLayer_Virtual_Guest ids - :param ip_address_ids: A List of SoftLayer_Network_Subnet_IpAddress ids - :param subnet_ids: A List of SoftLayer_Network_Subnet ids - :return: Returns an array of - SoftLayer_Network_Storage_Allowed_Host objects - which have access to the given File volume - """ - host_templates = [] - storage_utils.populate_host_templates(host_templates, - hardware_ids, - virtual_guest_ids, - ip_address_ids, - subnet_ids) - - return self.client.call('Network_Storage', 'removeAccessFromHostList', - host_templates, id=volume_id, **kwargs) - - def order_replicant_volume(self, volume_id, snapshot_schedule, - location, tier=None): - """Places an order for a replicant file volume. - - :param volume_id: The ID of the primary volume to be replicated - :param snapshot_schedule: The primary volume's snapshot - schedule to use for replication - :param location: The location for the ordered replicant volume - :param tier: The tier (IOPS per GB) of the primary volume - :return: Returns a SoftLayer_Container_Product_Order_Receipt - """ - - file_mask = 'billingItem[activeChildren,hourlyFlag],'\ - 'storageTierLevel,osType,staasVersion,'\ - 'hasEncryptionAtRest,snapshotCapacityGb,schedules,'\ - 'intervalSchedule,hourlySchedule,dailySchedule,'\ - 'weeklySchedule,storageType[keyName],provisionedIops' - file_volume = self.get_file_volume_details(volume_id, - mask=file_mask) - - order = storage_utils.prepare_replicant_order_object( - self, snapshot_schedule, location, tier, file_volume, 'file' - ) - - return self.client.call('Product_Order', 'placeOrder', order) - - def get_replication_partners(self, volume_id): - """Acquires list of replicant volumes pertaining to the given volume. - - :param volume_id: The ID of the primary volume to be replicated - :return: Returns an array of SoftLayer_Location objects - """ - return self.client.call('Network_Storage', - 'getReplicationPartners', - id=volume_id) - - def get_replication_locations(self, volume_id): - """Acquires list of the datacenters to which a volume can be replicated. - - :param volume_id: The ID of the primary volume to be replicated - :return: Returns an array of SoftLayer_Network_Storage objects - """ - return self.client.call('Network_Storage', - 'getValidReplicationTargetDatacenterLocations', - id=volume_id) - - def order_duplicate_volume(self, origin_volume_id, origin_snapshot_id=None, - duplicate_size=None, duplicate_iops=None, - duplicate_tier_level=None, - duplicate_snapshot_size=None, - hourly_billing_flag=False): - """Places an order for a duplicate file volume. - - :param origin_volume_id: The ID of the origin volume to be duplicated - :param origin_snapshot_id: Origin snapshot ID to use for duplication - :param duplicate_size: Size/capacity for the duplicate volume - :param duplicate_iops: The IOPS per GB for the duplicate volume - :param duplicate_tier_level: Tier level for the duplicate volume - :param duplicate_snapshot_size: Snapshot space size for the duplicate - :param hourly_billing_flag: Billing type, monthly (False) - or hourly (True), default to monthly. - :return: Returns a SoftLayer_Container_Product_Order_Receipt - """ + return self.get_volume_snapshot_list(volume_id, **kwargs) - file_mask = 'id,billingItem[location,hourlyFlag],snapshotCapacityGb,'\ - 'storageType[keyName],capacityGb,originalVolumeSize,'\ - 'provisionedIops,storageTierLevel,'\ - 'staasVersion,hasEncryptionAtRest' - origin_volume = self.get_file_volume_details(origin_volume_id, - mask=file_mask) - - order = storage_utils.prepare_duplicate_order_object( - self, origin_volume, duplicate_iops, duplicate_tier_level, - duplicate_size, duplicate_snapshot_size, 'file', - hourly_billing_flag - ) - - if origin_snapshot_id is not None: - order['duplicateOriginSnapshotId'] = origin_snapshot_id - - return self.client.call('Product_Order', 'placeOrder', order) - - def order_modified_volume(self, volume_id, new_size=None, new_iops=None, new_tier_level=None): - """Places an order for modifying an existing file volume. - - :param volume_id: The ID of the volume to be modified - :param new_size: The new size/capacity for the volume - :param new_iops: The new IOPS for the volume - :param new_tier_level: The new tier level for the volume - :return: Returns a SoftLayer_Container_Product_Order_Receipt - """ - - mask_items = [ - 'id', - 'billingItem', - 'storageType[keyName]', - 'capacityGb', - 'provisionedIops', - 'storageTierLevel', - 'staasVersion', - 'hasEncryptionAtRest', - ] - file_mask = ','.join(mask_items) - volume = self.get_file_volume_details(volume_id, mask=file_mask) - - order = storage_utils.prepare_modify_order_object( - self, volume, new_iops, new_tier_level, new_size - ) - - return self.client.call('Product_Order', 'placeOrder', order) - - def delete_snapshot(self, snapshot_id): - """Deletes the specified snapshot object. - - :param snapshot_id: The ID of the snapshot object to delete. - """ - return self.client.call('Network_Storage', 'deleteObject', - id=snapshot_id) def order_file_volume(self, storage_type, location, size, iops=None, tier_level=None, snapshot_size=None, @@ -353,132 +151,6 @@ def order_file_volume(self, storage_type, location, size, return self.client.call('Product_Order', 'placeOrder', order) - def create_snapshot(self, volume_id, notes='', **kwargs): - """Creates a snapshot on the given file volume. - - :param integer volume_id: The id of the volume - :param string notes: The notes or "name" to assign the snapshot - :return: Returns the id of the new snapshot - """ - - return self.client.call('Network_Storage', 'createSnapshot', - notes, id=volume_id, **kwargs) - - def enable_snapshots(self, volume_id, schedule_type, retention_count, minute, hour, day_of_week, **kwargs): - """Enables snapshots for a specific file volume at a given schedule - - :param integer volume_id: The id of the volume - :param string schedule_type: 'HOURLY'|'DAILY'|'WEEKLY' - :param integer retention_count: The number of snapshots to attempt to retain in this schedule - :param integer minute: The minute of the hour at which HOURLY, DAILY, and WEEKLY snapshots should be taken - :param integer hour: The hour of the day at which DAILY and WEEKLY snapshots should be taken - :param string|integer day_of_week: The day of the week on which WEEKLY snapshots should be taken, - either as a string ('SUNDAY') or integer ('0' is Sunday) - :return: Returns whether successfully scheduled or not - """ - - return self.client.call('Network_Storage', 'enableSnapshots', - schedule_type, - retention_count, - minute, - hour, - day_of_week, - id=volume_id, - **kwargs) - - def disable_snapshots(self, volume_id, schedule_type): - """Disables snapshots for a specific file volume at a given schedule - - :param integer volume_id: The id of the volume - :param string schedule_type: 'HOURLY'|'DAILY'|'WEEKLY' - :return: Returns whether successfully disabled or not - """ - - return self.client.call('Network_Storage', 'disableSnapshots', schedule_type, id=volume_id) - - def list_volume_schedules(self, volume_id): - """Lists schedules for a given volume - - :param integer volume_id: The id of the volume - :return: Returns list of schedules assigned to a given volume - """ - volume_detail = self.client.call( - 'Network_Storage', - 'getObject', - id=volume_id, - mask='schedules[type,properties[type]]') - - return utils.lookup(volume_detail, 'schedules') - - def order_snapshot_space(self, volume_id, capacity, tier, upgrade, **kwargs): - """Orders snapshot space for the given file volume. - - :param integer volume_id: The ID of the volume - :param integer capacity: The capacity to order, in GB - :param float tier: The tier level of the file volume, in IOPS per GB - :param boolean upgrade: Flag to indicate if this order is an upgrade - :return: Returns a SoftLayer_Container_Product_Order_Receipt - """ - file_mask = 'id,billingItem[location,hourlyFlag],'\ - 'storageType[keyName],storageTierLevel,provisionedIops,'\ - 'staasVersion,hasEncryptionAtRest' - file_volume = self.get_file_volume_details(volume_id, - mask=file_mask, - **kwargs) - - order = storage_utils.prepare_snapshot_order_object( - self, file_volume, capacity, tier, upgrade) - - return self.client.call('Product_Order', 'placeOrder', order) - - def cancel_snapshot_space(self, volume_id, reason='No longer needed', immediate=False): - """Cancels snapshot space for a given volume. - - :param integer volume_id: The volume ID - :param string reason: The reason for cancellation - :param boolean immediate: Cancel immediately or on anniversary date - """ - - file_volume = self.get_file_volume_details( - volume_id, - mask='mask[id,billingItem[activeChildren,hourlyFlag]]') - - if 'activeChildren' not in file_volume['billingItem']: - raise exceptions.SoftLayerError( - 'No snapshot space found to cancel') - - children_array = file_volume['billingItem']['activeChildren'] - billing_item_id = None - - for child in children_array: - if child['categoryCode'] == 'storage_snapshot_space': - billing_item_id = child['id'] - break - - if not billing_item_id: - raise exceptions.SoftLayerError( - 'No snapshot space found to cancel') - - if utils.lookup(file_volume, 'billingItem', 'hourlyFlag'): - immediate = True - - return self.client['Billing_Item'].cancelItem( - immediate, - True, - reason, - id=billing_item_id) - - def restore_from_snapshot(self, volume_id, snapshot_id): - """Restores a specific volume from a snapshot - - :param integer volume_id: The ID of the volume - :param integer snapshot_id: The id of the restore point - :return: Returns whether successfully restored or not - """ - - return self.client.call('Network_Storage', 'restoreFromSnapshot', - snapshot_id, id=volume_id) - def cancel_file_volume(self, volume_id, reason='No longer needed', immediate=False): """Cancels the given file storage volume. @@ -486,39 +158,6 @@ def cancel_file_volume(self, volume_id, reason='No longer needed', immediate=Fal :param string reason: The reason for cancellation :param boolean immediate: Cancel immediately or on anniversary date """ - file_volume = self.get_file_volume_details( - volume_id, - mask='mask[id,billingItem[id,hourlyFlag]]') - - if 'billingItem' not in file_volume: - raise exceptions.SoftLayerError('The volume has already been canceled') - billing_item_id = file_volume['billingItem']['id'] - - if utils.lookup(file_volume, 'billingItem', 'hourlyFlag'): - immediate = True - - return self.client['Billing_Item'].cancelItem( - immediate, - True, - reason, - id=billing_item_id) - - def failover_to_replicant(self, volume_id, replicant_id): - """Failover to a volume replicant. - - :param integer volume_id: The ID of the volume - :param integer replicant_id: ID of replicant to failover to - :return: Returns whether failover was successful or not - """ + return self.cancel_volume(volume_id, reason, immediate) - return self.client.call('Network_Storage', 'failoverToReplicant', - replicant_id, id=volume_id) - - def failback_from_replicant(self, volume_id): - """Failback from a volume replicant. - - :param integer volume_id: The ID of the volume - :return: Returns whether failback was successful or not - """ - return self.client.call('Network_Storage', 'failbackFromReplicant', id=volume_id) diff --git a/SoftLayer/managers/storage.py b/SoftLayer/managers/storage.py new file mode 100644 index 000000000..dca50a531 --- /dev/null +++ b/SoftLayer/managers/storage.py @@ -0,0 +1,415 @@ +""" + SoftLayer.storage + ~~~~~~~~~~~~~~~ + Network Storage Manager + + :license: MIT, see LICENSE for more details. +""" +from SoftLayer import exceptions +from SoftLayer.managers import storage_utils +from SoftLayer import utils + +# pylint: disable=too-many-public-methods + + +class StorageManager(utils.IdentifierMixin, object): + """"Base class for File and Block storage managers + + Any shared code between File and Block should ideally go here. + + :param SoftLayer.API.BaseClient client: the client instance + """ + + def __init__(self, client): + self.configuration = {} + self.client = client + + def get_volume_count_limits(self): + """Returns a list of block volume count limit. + + :return: Returns a list of block volume count limit. + """ + return self.client.call('Network_Storage', 'getVolumeCountLimits') + + def get_volume_details(self, volume_id, **kwargs): + """Returns details about the specified volume. + + :param volume_id: ID of volume. + :param kwargs: + :return: Returns details about the specified volume. + """ + + if 'mask' not in kwargs: + items = [ + 'id', + 'username', + 'password', + 'capacityGb', + 'snapshotCapacityGb', + 'parentVolume.snapshotSizeBytes', + 'storageType.keyName', + 'serviceResource.datacenter[name]', + 'serviceResourceBackendIpAddress', + 'storageTierLevel', + 'provisionedIops', + 'lunId', + 'originalVolumeName', + 'originalSnapshotName', + 'originalVolumeSize', + 'activeTransactionCount', + 'activeTransactions.transactionStatus[friendlyName]', + 'replicationPartnerCount', + 'replicationStatus', + 'replicationPartners[id,username,' + 'serviceResourceBackendIpAddress,' + 'serviceResource[datacenter[name]],' + 'replicationSchedule[type[keyname]]]', + ] + kwargs['mask'] = ','.join(items) + return self.client.call('Network_Storage', 'getObject', id=volume_id, **kwargs) + + def get_volume_access_list(self, volume_id, **kwargs): + """Returns a list of authorized hosts for a specified volume. + + :param volume_id: ID of volume. + :param kwargs: + :return: Returns a list of authorized hosts for a specified volume. + """ + if 'mask' not in kwargs: + items = [ + 'id', + 'allowedVirtualGuests[allowedHost[credential, sourceSubnet]]', + 'allowedHardware[allowedHost[credential]]', + 'allowedSubnets[allowedHost[credential]]', + 'allowedIpAddresses[allowedHost[credential]]', + ] + kwargs['mask'] = ','.join(items) + return self.client.call('Network_Storage', 'getObject', id=volume_id, **kwargs) + + def get_volume_snapshot_list(self, volume_id, **kwargs): + """Returns a list of snapshots for the specified volume. + + :param volume_id: ID of volume. + :param kwargs: + :return: Returns a list of snapshots for the specified volume. + """ + if 'mask' not in kwargs: + items = [ + 'id', + 'notes', + 'snapshotSizeBytes', + 'storageType[keyName]', + 'snapshotCreationTimestamp', + 'intervalSchedule', + 'hourlySchedule', + 'dailySchedule', + 'weeklySchedule' + ] + + kwargs['mask'] = ','.join(items) + + return self.client.call('Network_Storage', 'getSnapshots', id=volume_id, **kwargs) + + def authorize_host_to_volume(self, volume_id, hardware_ids=None, virtual_guest_ids=None, + ip_address_ids=None, subnet_ids=None): + """Authorizes hosts to Storage Volumes + + :param volume_id: The File volume to authorize hosts to + :param hardware_ids: A List of SoftLayer_Hardware ids + :param virtual_guest_ids: A List of SoftLayer_Virtual_Guest ids + :param ip_address_ids: A List of SoftLayer_Network_Subnet_IpAddress ids + :param subnet_ids: A List of SoftLayer_Network_Subnet ids. Only use with File volumes. + :return: Returns an array of SoftLayer_Network_Storage_Allowed_Host objects + which now have access to the given volume + """ + host_templates = storage_utils.populate_host_templates(hardware_ids, virtual_guest_ids, + ip_address_ids, subnet_ids) + + return self.client.call('Network_Storage', 'allowAccessFromHostList', host_templates, id=volume_id) + + def deauthorize_host_to_volume(self, volume_id, hardware_ids=None, virtual_guest_ids=None, + ip_address_ids=None, subnet_ids=None): + """Revokes authorization of hosts to File Storage Volumes + + :param volume_id: The File volume to deauthorize hosts to + :param hardware_ids: A List of SoftLayer_Hardware ids + :param virtual_guest_ids: A List of SoftLayer_Virtual_Guest ids + :param ip_address_ids: A List of SoftLayer_Network_Subnet_IpAddress ids + :param subnet_ids: A List of SoftLayer_Network_Subnet ids. Only use with File volumes + :return: Returns an array of SoftLayer_Network_Storage_Allowed_Host objects + which have access to the given File volume + """ + host_templates = storage_utils.populate_host_templates(hardware_ids, virtual_guest_ids, + ip_address_ids, subnet_ids) + + return self.client.call('Network_Storage', 'removeAccessFromHostList', host_templates, id=volume_id) + + def get_replication_partners(self, volume_id): + """Acquires list of replicant volumes pertaining to the given volume. + + :param volume_id: The ID of the primary volume to be replicated + :return: Returns an array of SoftLayer_Location objects + """ + return self.client.call('Network_Storage', 'getReplicationPartners', id=volume_id) + + def get_replication_locations(self, volume_id): + """Acquires list of the datacenters to which a volume can be replicated. + + :param volume_id: The ID of the primary volume to be replicated + :return: Returns an array of SoftLayer_Network_Storage objects + """ + return self.client.call('Network_Storage', 'getValidReplicationTargetDatacenterLocations', id=volume_id) + + def order_replicant_volume(self, volume_id, snapshot_schedule, location, tier=None, os_type=None): + """Places an order for a replicant volume. + + :param volume_id: The ID of the primary volume to be replicated + :param snapshot_schedule: The primary volume's snapshot + schedule to use for replication + :param location: The location for the ordered replicant volume + :param tier: The tier (IOPS per GB) of the primary volume + :param os_type: The OS type of the primary volume + :return: Returns a SoftLayer_Container_Product_Order_Receipt + """ + + block_mask = 'billingItem[activeChildren,hourlyFlag],'\ + 'storageTierLevel,osType,staasVersion,'\ + 'hasEncryptionAtRest,snapshotCapacityGb,schedules,'\ + 'intervalSchedule,hourlySchedule,dailySchedule,'\ + 'weeklySchedule,storageType[keyName],provisionedIops' + block_volume = self.get_volume_details(volume_id, mask=block_mask) + + storage_class = storage_utils.block_or_file(block_volume['storageType']['keyName']) + + order = storage_utils.prepare_replicant_order_object( + self, snapshot_schedule, location, tier, block_volume, storage_class + ) + + if storage_class == 'block': + if os_type is None: + if isinstance(utils.lookup(block_volume, 'osType', 'keyName'), str): + os_type = block_volume['osType']['keyName'] + else: + raise exceptions.SoftLayerError( + "Cannot find primary volume's os-type " + "automatically; must specify manually") + order['osFormatType'] = {'keyName': os_type} + + return self.client.call('Product_Order', 'placeOrder', order) + + def order_duplicate_volume(self, origin_volume_id, origin_snapshot_id=None, + duplicate_size=None, duplicate_iops=None, duplicate_tier_level=None, + duplicate_snapshot_size=None, hourly_billing_flag=False): + """Places an order for a duplicate volume. + + :param origin_volume_id: The ID of the origin volume to be duplicated + :param origin_snapshot_id: Origin snapshot ID to use for duplication + :param duplicate_size: Size/capacity for the duplicate volume + :param duplicate_iops: The IOPS per GB for the duplicate volume + :param duplicate_tier_level: Tier level for the duplicate volume + :param duplicate_snapshot_size: Snapshot space size for the duplicate + :param hourly_billing_flag: Billing type, monthly (False) or hourly (True), default to monthly. + :return: Returns a SoftLayer_Container_Product_Order_Receipt + """ + + block_mask = 'id,billingItem[location,hourlyFlag],snapshotCapacityGb,'\ + 'storageType[keyName],capacityGb,originalVolumeSize,'\ + 'provisionedIops,storageTierLevel,osType[keyName],'\ + 'staasVersion,hasEncryptionAtRest' + origin_volume = self.get_volume_details(origin_volume_id, mask=block_mask) + storage_class = storage_utils.block_or_file(origin_volume['storageType']['keyName']) + + + order = storage_utils.prepare_duplicate_order_object( + self, origin_volume, duplicate_iops, duplicate_tier_level, + duplicate_size, duplicate_snapshot_size, storage_class, hourly_billing_flag + ) + + if storage_class == 'block': + if isinstance(utils.lookup(origin_volume, 'osType', 'keyName'), str): + os_type = origin_volume['osType']['keyName'] + else: + raise exceptions.SoftLayerError("Cannot find origin volume's os-type") + + order['osFormatType'] = {'keyName': os_type} + + if origin_snapshot_id is not None: + order['duplicateOriginSnapshotId'] = origin_snapshot_id + + return self.client.call('Product_Order', 'placeOrder', order) + + + def order_modified_volume(self, volume_id, new_size=None, new_iops=None, new_tier_level=None): + """Places an order for modifying an existing block volume. + + :param volume_id: The ID of the volume to be modified + :param new_size: The new size/capacity for the volume + :param new_iops: The new IOPS for the volume + :param new_tier_level: The new tier level for the volume + :return: Returns a SoftLayer_Container_Product_Order_Receipt + """ + + mask_items = [ + 'id', + 'billingItem', + 'storageType[keyName]', + 'capacityGb', + 'provisionedIops', + 'storageTierLevel', + 'staasVersion', + 'hasEncryptionAtRest', + ] + block_mask = ','.join(mask_items) + volume = self.get_volume_details(volume_id, mask=block_mask) + + order = storage_utils.prepare_modify_order_object( + self, volume, new_iops, new_tier_level, new_size + ) + + return self.client.call('Product_Order', 'placeOrder', order) + + + def delete_snapshot(self, snapshot_id): + """Deletes the specified snapshot object. + + :param snapshot_id: The ID of the snapshot object to delete. + """ + return self.client.call('Network_Storage', 'deleteObject', id=snapshot_id) + + def create_snapshot(self, volume_id, notes='', **kwargs): + """Creates a snapshot on the given block volume. + + :param integer volume_id: The id of the volume + :param string notes: The notes or "name" to assign the snapshot + :return: Returns the id of the new snapshot + """ + return self.client.call('Network_Storage', 'createSnapshot', notes, id=volume_id, **kwargs) + + def order_snapshot_space(self, volume_id, capacity, tier, upgrade, **kwargs): + """Orders snapshot space for the given block volume. + + :param integer volume_id: The id of the volume + :param integer capacity: The capacity to order, in GB + :param float tier: The tier level of the block volume, in IOPS per GB + :param boolean upgrade: Flag to indicate if this order is an upgrade + :return: Returns a SoftLayer_Container_Product_Order_Receipt + """ + object_mask = 'id,billingItem[location,hourlyFlag],'\ + 'storageType[keyName],storageTierLevel,provisionedIops,'\ + 'staasVersion,hasEncryptionAtRest' + volume = self.get_volume_details(volume_id, mask=object_mask, **kwargs) + + order = storage_utils.prepare_snapshot_order_object(self, volume, capacity, tier, upgrade) + + return self.client.call('Product_Order', 'placeOrder', order) + + def cancel_snapshot_space(self, volume_id, reason='No longer needed', immediate=False): + """Cancels snapshot space for a given volume. + + :param integer volume_id: The volume ID + :param string reason: The reason for cancellation + :param boolean immediate_flag: Cancel immediately or on anniversary date + """ + + object_mask = 'mask[id,billingItem[activeChildren,hourlyFlag]]' + volume = self.get_volume_details(volume_id, mask=object_mask) + + if 'activeChildren' not in volume['billingItem']: + raise exceptions.SoftLayerError('No snapshot space found to cancel') + + children_array = volume['billingItem']['activeChildren'] + billing_item_id = None + + for child in children_array: + if child['categoryCode'] == 'storage_snapshot_space': + billing_item_id = child['id'] + break + + if not billing_item_id: + raise exceptions.SoftLayerError('No snapshot space found to cancel') + + if utils.lookup(volume, 'billingItem', 'hourlyFlag'): + immediate = True + + return self.client.call('SoftLayer_Billing_Item', 'cancelItem', immediate, True, reason, id=billing_item_id) + + def enable_snapshots(self, volume_id, schedule_type, retention_count, minute, hour, day_of_week, **kwargs): + """Enables snapshots for a specific block volume at a given schedule + + :param integer volume_id: The id of the volume + :param string schedule_type: 'HOURLY'|'DAILY'|'WEEKLY' + :param integer retention_count: Number of snapshots to be kept + :param integer minute: Minute when to take snapshot + :param integer hour: Hour when to take snapshot + :param string day_of_week: Day when to take snapshot + :return: Returns whether successfully scheduled or not + """ + return self.client.call('Network_Storage', 'enableSnapshots', schedule_type, retention_count, + minute, hour, day_of_week, id=volume_id, **kwargs) + + def disable_snapshots(self, volume_id, schedule_type): + """Disables snapshots for a specific block volume at a given schedule + + :param integer volume_id: The id of the volume + :param string schedule_type: 'HOURLY'|'DAILY'|'WEEKLY' + :return: Returns whether successfully disabled or not + """ + return self.client.call('Network_Storage', 'disableSnapshots', schedule_type, id=volume_id) + + def list_volume_schedules(self, volume_id): + """Lists schedules for a given volume + + :param integer volume_id: The id of the volume + :return: Returns list of schedules assigned to a given volume + """ + object_mask = 'schedules[type,properties[type]]' + volume_detail = self.client.call('Network_Storage', 'getObject', id=volume_id, mask=object_mask) + + return utils.lookup(volume_detail, 'schedules') + + def restore_from_snapshot(self, volume_id, snapshot_id): + """Restores a specific volume from a snapshot + + :param integer volume_id: The id of the volume + :param integer snapshot_id: The id of the restore point + :return: Returns whether succesfully restored or not + """ + return self.client.call('Network_Storage', 'restoreFromSnapshot', snapshot_id, id=volume_id) + + def failover_to_replicant(self, volume_id, replicant_id): + """Failover to a volume replicant. + + :param integer volume_id: The id of the volume + :param integer replicant_id: ID of replicant to failover to + :return: Returns whether failover was successful or not + """ + return self.client.call('Network_Storage', 'failoverToReplicant', replicant_id, id=volume_id) + + def failback_from_replicant(self, volume_id): + """Failback from a volume replicant. + + :param integer volume_id: The id of the volume + :return: Returns whether failback was successful or not + """ + + return self.client.call('Network_Storage', 'failbackFromReplicant', id=volume_id) + + def cancel_volume(self, volume_id, reason='No longer needed', immediate=False): + """Cancels the given block storage volume. + + :param integer volume_id: The volume ID + :param string reason: The reason for cancellation + :param boolean immediate_flag: Cancel immediately or on anniversary date + """ + object_mask = 'mask[id,billingItem[id,hourlyFlag]]' + volume = self.get_volume_details(volume_id, mask=object_mask) + + if 'billingItem' not in volume: + raise exceptions.SoftLayerError("Block Storage was already cancelled") + + billing_item_id = volume['billingItem']['id'] + + if utils.lookup(volume, 'billingItem', 'hourlyFlag'): + immediate = True + + return self.client.call('SoftLayer_Billing_Item', 'cancelItem', immediate, True, reason, id=billing_item_id) diff --git a/SoftLayer/managers/storage_utils.py b/SoftLayer/managers/storage_utils.py index 80ec60368..97a8c14e2 100644 --- a/SoftLayer/managers/storage_utils.py +++ b/SoftLayer/managers/storage_utils.py @@ -19,19 +19,19 @@ } -def populate_host_templates(host_templates, - hardware_ids=None, +def populate_host_templates(hardware_ids=None, virtual_guest_ids=None, ip_address_ids=None, subnet_ids=None): - """Populate the given host_templates array with the IDs provided + """Returns a populated array with the IDs provided - :param host_templates: The array to which host templates will be added :param hardware_ids: A List of SoftLayer_Hardware ids :param virtual_guest_ids: A List of SoftLayer_Virtual_Guest ids :param ip_address_ids: A List of SoftLayer_Network_Subnet_IpAddress ids :param subnet_ids: A List of SoftLayer_Network_Subnet ids + :return: array of objects formatted for allowAccessFromHostList """ + host_templates = [] if hardware_ids is not None: for hardware_id in hardware_ids: host_templates.append({ @@ -59,6 +59,7 @@ def populate_host_templates(host_templates, 'objectType': 'SoftLayer_Network_Subnet', 'id': subnet_id }) + return host_templates def get_package(manager, category_code): @@ -984,6 +985,13 @@ def prepare_modify_order_object(manager, volume, new_iops, new_tier, new_size): return modify_order +def block_or_file(storage_type_keyname): + """returns either 'block' or 'file' + + :param storage_type_keyname: the Network_Storage['storageType']['keyName'] + :returns: 'block' or 'file' + """ + return 'block' if 'BLOCK_STORAGE' in storage_type_keyname else 'file' def _has_category(categories, category_code): return any( @@ -1014,3 +1022,4 @@ def _find_price_id(prices, category, restriction_type=None, restriction_value=No continue return {'id': price['id']} + diff --git a/tests/managers/block_tests.py b/tests/managers/block_tests.py index acb0dc6f6..400ba0e19 100644 --- a/tests/managers/block_tests.py +++ b/tests/managers/block_tests.py @@ -8,7 +8,11 @@ import copy import SoftLayer from SoftLayer import exceptions -from SoftLayer import fixtures +from SoftLayer.fixtures import SoftLayer_Account +from SoftLayer.fixtures import SoftLayer_Product_Package +from SoftLayer.fixtures import SoftLayer_Product_Order +from SoftLayer.fixtures import SoftLayer_Network_Storage +from SoftLayer.fixtures import SoftLayer_Network_Storage_Allowed_Host from SoftLayer import testing @@ -83,7 +87,7 @@ def test_cancel_block_volume_billing_item_found(self): def test_get_block_volume_details(self): result = self.block.get_block_volume_details(100) - self.assertEqual(fixtures.SoftLayer_Network_Storage.getObject, result) + self.assertEqual(SoftLayer_Network_Storage.getObject, result) expected_mask = 'id,' \ 'username,' \ @@ -119,7 +123,7 @@ def test_get_block_volume_details(self): def test_list_block_volumes(self): result = self.block.list_block_volumes() - self.assertEqual(fixtures.SoftLayer_Account.getIscsiNetworkStorage, + self.assertEqual(SoftLayer_Account.getIscsiNetworkStorage, result) expected_filter = { @@ -157,7 +161,7 @@ def test_list_block_volumes_with_additional_filters(self): storage_type="Endurance", username="username") - self.assertEqual(fixtures.SoftLayer_Account.getIscsiNetworkStorage, + self.assertEqual(SoftLayer_Account.getIscsiNetworkStorage, result) expected_filter = { @@ -197,7 +201,7 @@ def test_list_block_volumes_with_additional_filters(self): def test_get_block_volume_access_list(self): result = self.block.get_block_volume_access_list(100) - self.assertEqual(fixtures.SoftLayer_Network_Storage.getObject, result) + self.assertEqual(SoftLayer_Network_Storage.getObject, result) self.assert_called_with( 'SoftLayer_Network_Storage', @@ -207,7 +211,7 @@ def test_get_block_volume_access_list(self): def test_get_block_volume_snapshot_list(self): result = self.block.get_block_volume_snapshot_list(100) - self.assertEqual(fixtures.SoftLayer_Network_Storage.getSnapshots, + self.assertEqual(SoftLayer_Network_Storage.getSnapshots, result) self.assert_called_with( @@ -218,7 +222,7 @@ def test_get_block_volume_snapshot_list(self): def test_delete_snapshot(self): result = self.block.delete_snapshot(100) - self.assertEqual(fixtures.SoftLayer_Network_Storage.deleteObject, + self.assertEqual(SoftLayer_Network_Storage.deleteObject, result) self.assert_called_with( @@ -331,7 +335,7 @@ def test_replicant_failover(self): result = self.block.failover_to_replicant(1234, 5678) self.assertEqual( - fixtures.SoftLayer_Network_Storage.failoverToReplicant, result) + SoftLayer_Network_Storage.failoverToReplicant, result) self.assert_called_with( 'SoftLayer_Network_Storage', 'failoverToReplicant', @@ -343,7 +347,7 @@ def test_replicant_failback(self): result = self.block.failback_from_replicant(1234) self.assertEqual( - fixtures.SoftLayer_Network_Storage.failbackFromReplicant, result) + SoftLayer_Network_Storage.failbackFromReplicant, result) self.assert_called_with( 'SoftLayer_Network_Storage', 'failbackFromReplicant', @@ -373,9 +377,9 @@ def test_order_block_volume_performance(self): mock.return_value = [{'id': 449494, 'name': 'dal09'}] mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -389,7 +393,7 @@ def test_order_block_volume_performance(self): service_offering='storage_as_a_service' ) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -418,9 +422,9 @@ def test_order_block_volume_endurance(self): mock.return_value = [{'id': 449494, 'name': 'dal09'}] mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME + mock_volume = SoftLayer_Network_Storage.STAAS_TEST_VOLUME mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -433,7 +437,7 @@ def test_order_block_volume_endurance(self): service_offering='storage_as_a_service' ) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -463,7 +467,7 @@ def test_authorize_host_to_volume(self): virtual_guest_ids=[200], ip_address_ids=[300]) - self.assertEqual(fixtures.SoftLayer_Network_Storage. + self.assertEqual(SoftLayer_Network_Storage. allowAccessFromHostList, result) self.assert_called_with( @@ -478,7 +482,7 @@ def test_deauthorize_host_to_volume(self): virtual_guest_ids=[200], ip_address_ids=[300]) - self.assertEqual(fixtures.SoftLayer_Network_Storage. + self.assertEqual(SoftLayer_Network_Storage. removeAccessFromHostList, result) self.assert_called_with( @@ -491,7 +495,7 @@ def test_assign_subnets_to_acl(self): 12345, subnet_ids=[12345678]) - self.assertEqual(fixtures.SoftLayer_Network_Storage_Allowed_Host. + self.assertEqual(SoftLayer_Network_Storage_Allowed_Host. assignSubnetsToAcl, result) self.assert_called_with( @@ -504,7 +508,7 @@ def test_remove_subnets_from_acl(self): 12345, subnet_ids=[12345678]) - self.assertEqual(fixtures.SoftLayer_Network_Storage_Allowed_Host. + self.assertEqual(SoftLayer_Network_Storage_Allowed_Host. removeSubnetsFromAcl, result) self.assert_called_with( @@ -515,7 +519,7 @@ def test_remove_subnets_from_acl(self): def test_get_subnets_in_acl(self): result = self.block.get_subnets_in_acl(12345) - self.assertEqual(fixtures.SoftLayer_Network_Storage_Allowed_Host. + self.assertEqual(SoftLayer_Network_Storage_Allowed_Host. getSubnetsInAcl, result) self.assert_called_with( @@ -526,7 +530,7 @@ def test_get_subnets_in_acl(self): def test_create_snapshot(self): result = self.block.create_snapshot(123, 'hello world') - self.assertEqual(fixtures.SoftLayer_Network_Storage.createSnapshot, + self.assertEqual(SoftLayer_Network_Storage.createSnapshot, result) self.assert_called_with( @@ -538,7 +542,7 @@ def test_snapshot_restore(self): result = self.block.restore_from_snapshot(12345678, 87654321) self.assertEqual( - fixtures.SoftLayer_Network_Storage.restoreFromSnapshot, + SoftLayer_Network_Storage.restoreFromSnapshot, result) self.assert_called_with( 'SoftLayer_Network_Storage', @@ -549,7 +553,7 @@ def test_enable_snapshots(self): result = self.block.enable_snapshots(12345678, 'WEEKLY', 10, 47, 16, 'FRIDAY') - self.assertEqual(fixtures.SoftLayer_Network_Storage.enableSnapshots, + self.assertEqual(SoftLayer_Network_Storage.enableSnapshots, result) self.assert_called_with( @@ -560,7 +564,7 @@ def test_enable_snapshots(self): def test_disable_snapshots(self): result = self.block.disable_snapshots(12345678, 'HOURLY') - self.assertEqual(fixtures.SoftLayer_Network_Storage.disableSnapshots, + self.assertEqual(SoftLayer_Network_Storage.disableSnapshots, result) self.assert_called_with( 'SoftLayer_Network_Storage', @@ -571,7 +575,7 @@ def test_list_volume_schedules(self): result = self.block.list_volume_schedules(12345678) self.assertEqual( - fixtures.SoftLayer_Network_Storage.listVolumeSchedules, + SoftLayer_Network_Storage.listVolumeSchedules, result) expected_mask = 'schedules[type,properties[type]]' @@ -585,16 +589,16 @@ def test_list_volume_schedules(self): def test_order_block_snapshot_space_upgrade(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'ENDURANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume result = self.block.order_snapshot_space(102, 20, None, True) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -615,15 +619,15 @@ def test_order_block_snapshot_space_upgrade(self): def test_order_block_snapshot_space(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME + mock_volume = SoftLayer_Network_Storage.STAAS_TEST_VOLUME mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume result = self.block.order_snapshot_space(102, 10, None, False) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -643,7 +647,10 @@ def test_order_block_snapshot_space(self): ) def test_order_block_replicant_os_type_not_found(self): - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_package = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock_package.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) del mock_volume['osType'] mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -665,9 +672,9 @@ def test_order_block_replicant_performance_os_type_given(self): mock.return_value = [{'id': 449494, 'name': 'dal09'}] mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -679,7 +686,7 @@ def test_order_block_replicant_performance_os_type_given(self): os_type='XEN' ) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -712,15 +719,15 @@ def test_order_block_replicant_endurance(self): mock.return_value = [{'id': 449494, 'name': 'dal09'}] mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME + mock_volume = SoftLayer_Network_Storage.STAAS_TEST_VOLUME mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume result = self.block.order_replicant_volume(102, 'WEEKLY', 'dal09') - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -749,9 +756,9 @@ def test_order_block_replicant_endurance(self): def test_order_block_duplicate_origin_os_type_not_found(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) del mock_volume['osType'] mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -767,9 +774,9 @@ def test_order_block_duplicate_origin_os_type_not_found(self): def test_order_block_duplicate_performance_no_duplicate_snapshot(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -778,7 +785,7 @@ def test_order_block_duplicate_performance_no_duplicate_snapshot(self): 102, duplicate_snapshot_size=0) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -804,9 +811,9 @@ def test_order_block_duplicate_performance_no_duplicate_snapshot(self): def test_order_block_duplicate_performance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -820,7 +827,7 @@ def test_order_block_duplicate_performance(self): duplicate_snapshot_size=10 ) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -848,9 +855,9 @@ def test_order_block_duplicate_performance(self): def test_order_block_duplicate_endurance_no_duplicate_snapshot(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME + mock_volume = SoftLayer_Network_Storage.STAAS_TEST_VOLUME mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -858,7 +865,7 @@ def test_order_block_duplicate_endurance_no_duplicate_snapshot(self): 102, duplicate_snapshot_size=0) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -883,9 +890,9 @@ def test_order_block_duplicate_endurance_no_duplicate_snapshot(self): def test_order_block_duplicate_endurance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME + mock_volume = SoftLayer_Network_Storage.STAAS_TEST_VOLUME mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -898,7 +905,7 @@ def test_order_block_duplicate_endurance(self): duplicate_snapshot_size=10 ) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -925,16 +932,16 @@ def test_order_block_duplicate_endurance(self): def test_order_block_modified_performance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume result = self.block.order_modified_volume(102, new_size=1000, new_iops=2000, new_tier_level=None) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', 'placeOrder', @@ -948,15 +955,15 @@ def test_order_block_modified_performance(self): def test_order_block_modified_endurance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME + mock_volume = SoftLayer_Network_Storage.STAAS_TEST_VOLUME mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume result = self.block.order_modified_volume(102, new_size=1000, new_iops=None, new_tier_level=4) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', 'placeOrder', @@ -976,4 +983,4 @@ def test_setCredentialPassword(self): def test_list_block_volume_limit(self): result = self.block.list_block_volume_limit() - self.assertEqual(fixtures.SoftLayer_Network_Storage.getVolumeCountLimits, result) + self.assertEqual(SoftLayer_Network_Storage.getVolumeCountLimits, result) diff --git a/tests/managers/file_tests.py b/tests/managers/file_tests.py index d6ca66c68..640c2d9f8 100644 --- a/tests/managers/file_tests.py +++ b/tests/managers/file_tests.py @@ -8,7 +8,11 @@ import copy import SoftLayer from SoftLayer import exceptions -from SoftLayer import fixtures +from SoftLayer.fixtures import SoftLayer_Account +from SoftLayer.fixtures import SoftLayer_Product_Package +from SoftLayer.fixtures import SoftLayer_Product_Order +from SoftLayer.fixtures import SoftLayer_Network_Storage +from SoftLayer.fixtures import SoftLayer_Network_Storage_Allowed_Host from SoftLayer import testing @@ -49,7 +53,7 @@ def test_authorize_host_to_volume(self): ip_address_ids=[300], subnet_ids=[400]) - self.assertEqual(fixtures.SoftLayer_Network_Storage. + self.assertEqual(SoftLayer_Network_Storage. allowAccessFromHostList, result) self.assert_called_with( @@ -65,7 +69,7 @@ def test_deauthorize_host_to_volume(self): ip_address_ids=[300], subnet_ids=[400]) - self.assertEqual(fixtures.SoftLayer_Network_Storage. + self.assertEqual(SoftLayer_Network_Storage. removeAccessFromHostList, result) self.assert_called_with( @@ -84,7 +88,7 @@ def test_enable_snapshots(self): result = self.file.enable_snapshots(12345678, 'WEEKLY', 10, 47, 16, 'FRIDAY') - self.assertEqual(fixtures.SoftLayer_Network_Storage.enableSnapshots, + self.assertEqual(SoftLayer_Network_Storage.enableSnapshots, result) self.assert_called_with( @@ -95,7 +99,7 @@ def test_enable_snapshots(self): def test_disable_snapshots(self): result = self.file.disable_snapshots(12345678, 'HOURLY') - self.assertEqual(fixtures.SoftLayer_Network_Storage.disableSnapshots, + self.assertEqual(SoftLayer_Network_Storage.disableSnapshots, result) self.assert_called_with( 'SoftLayer_Network_Storage', @@ -106,7 +110,7 @@ def test_snapshot_restore(self): result = self.file.restore_from_snapshot(12345678, 87654321) self.assertEqual( - fixtures.SoftLayer_Network_Storage.restoreFromSnapshot, + SoftLayer_Network_Storage.restoreFromSnapshot, result) self.assert_called_with( 'SoftLayer_Network_Storage', @@ -116,7 +120,7 @@ def test_snapshot_restore(self): def test_get_file_volume_details(self): result = self.file.get_file_volume_details(100) - self.assertEqual(fixtures.SoftLayer_Network_Storage.getObject, result) + self.assertEqual(SoftLayer_Network_Storage.getObject, result) expected_mask = 'id,'\ 'username,'\ @@ -153,7 +157,7 @@ def test_get_file_volume_details(self): def test_get_file_volume_snapshot_list(self): result = self.file.get_file_volume_snapshot_list(100) - self.assertEqual(fixtures.SoftLayer_Network_Storage.getSnapshots, + self.assertEqual(SoftLayer_Network_Storage.getSnapshots, result) self.assert_called_with( @@ -164,7 +168,7 @@ def test_get_file_volume_snapshot_list(self): def test_create_snapshot(self): result = self.file.create_snapshot(123, 'hello world') - self.assertEqual(fixtures.SoftLayer_Network_Storage.createSnapshot, + self.assertEqual(SoftLayer_Network_Storage.createSnapshot, result) self.assert_called_with( @@ -277,7 +281,7 @@ def test_replicant_failover(self): result = self.file.failover_to_replicant(1234, 5678) self.assertEqual( - fixtures.SoftLayer_Network_Storage.failoverToReplicant, result) + SoftLayer_Network_Storage.failoverToReplicant, result) self.assert_called_with( 'SoftLayer_Network_Storage', 'failoverToReplicant', @@ -289,7 +293,7 @@ def test_replicant_failback(self): result = self.file.failback_from_replicant(1234) self.assertEqual( - fixtures.SoftLayer_Network_Storage.failbackFromReplicant, result) + SoftLayer_Network_Storage.failbackFromReplicant, result) self.assert_called_with( 'SoftLayer_Network_Storage', 'failbackFromReplicant', @@ -317,7 +321,7 @@ def test_get_replication_locations(self): def test_delete_snapshot(self): result = self.file.delete_snapshot(100) - self.assertEqual(fixtures.SoftLayer_Network_Storage.deleteObject, + self.assertEqual(SoftLayer_Network_Storage.deleteObject, result) self.assert_called_with( @@ -328,7 +332,7 @@ def test_delete_snapshot(self): def test_list_file_volumes(self): result = self.file.list_file_volumes() - self.assertEqual(fixtures.SoftLayer_Account.getNasNetworkStorage, + self.assertEqual(SoftLayer_Account.getNasNetworkStorage, result) expected_filter = { @@ -366,7 +370,7 @@ def test_list_file_volumes_with_additional_filters(self): storage_type="Endurance", username="username") - self.assertEqual(fixtures.SoftLayer_Account.getNasNetworkStorage, + self.assertEqual(SoftLayer_Account.getNasNetworkStorage, result) expected_filter = { @@ -408,9 +412,9 @@ def test_order_file_volume_performance(self): mock.return_value = [{'id': 449494, 'name': 'dal09'}] mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -423,7 +427,7 @@ def test_order_file_volume_performance(self): service_offering='storage_as_a_service' ) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -451,9 +455,9 @@ def test_order_file_volume_endurance(self): mock.return_value = [{'id': 449494, 'name': 'dal09'}] mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -466,7 +470,7 @@ def test_order_file_volume_endurance(self): service_offering='storage_as_a_service' ) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -490,16 +494,16 @@ def test_order_file_volume_endurance(self): def test_order_file_snapshot_space_upgrade(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume result = self.file.order_snapshot_space(102, 20, None, True) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -520,16 +524,16 @@ def test_order_file_snapshot_space_upgrade(self): def test_order_file_snapshot_space(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume result = self.file.order_snapshot_space(102, 10, None, False) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -553,16 +557,16 @@ def test_order_file_replicant_performance(self): mock.return_value = [{'id': 449494, 'name': 'dal09'}] mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume result = self.file.order_replicant_volume(102, 'WEEKLY', 'dal09') - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -594,16 +598,16 @@ def test_order_file_replicant_endurance(self): mock.return_value = [{'id': 449494, 'name': 'dal09'}] mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume result = self.file.order_replicant_volume(102, 'WEEKLY', 'dal09') - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -631,9 +635,9 @@ def test_order_file_replicant_endurance(self): def test_order_file_duplicate_performance_no_duplicate_snapshot(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -642,7 +646,7 @@ def test_order_file_duplicate_performance_no_duplicate_snapshot(self): 102, duplicate_snapshot_size=0) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -667,8 +671,8 @@ def test_order_file_duplicate_performance_no_duplicate_snapshot(self): def test_order_file_duplicate_performance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -682,7 +686,7 @@ def test_order_file_duplicate_performance(self): duplicate_snapshot_size=10 ) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -709,9 +713,9 @@ def test_order_file_duplicate_performance(self): def test_order_file_duplicate_endurance_no_duplicate_snapshot(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -720,7 +724,7 @@ def test_order_file_duplicate_endurance_no_duplicate_snapshot(self): 102, duplicate_snapshot_size=0) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -744,9 +748,9 @@ def test_order_file_duplicate_endurance_no_duplicate_snapshot(self): def test_order_file_duplicate_endurance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -760,7 +764,7 @@ def test_order_file_duplicate_endurance(self): duplicate_snapshot_size=10 ) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', @@ -786,16 +790,16 @@ def test_order_file_duplicate_endurance(self): def test_order_file_modified_performance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume result = self.file.order_modified_volume(102, new_size=1000, new_iops=2000, new_tier_level=None) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', 'placeOrder', @@ -809,16 +813,16 @@ def test_order_file_modified_performance(self): def test_order_file_modified_endurance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume result = self.file.order_modified_volume(102, new_size=1000, new_iops=None, new_tier_level=4) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', 'placeOrder', @@ -831,4 +835,4 @@ def test_order_file_modified_endurance(self): def test_list_file_volume_limit(self): result = self.file.list_file_volume_limit() - self.assertEqual(fixtures.SoftLayer_Network_Storage.getVolumeCountLimits, result) + self.assertEqual(SoftLayer_Network_Storage.getVolumeCountLimits, result) From ef96801cc6c55bc2253ce27b6968b49350f67861 Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Wed, 26 Feb 2020 16:19:06 -0600 Subject: [PATCH 05/12] style and tox fixes --- .../fixtures/SoftLayer_Location_Datacenter.py | 2 +- SoftLayer/managers/block.py | 6 +----- SoftLayer/managers/file.py | 6 +----- SoftLayer/managers/storage.py | 13 +++++-------- SoftLayer/managers/storage_utils.py | 3 ++- tests/managers/block_tests.py | 4 ++-- tests/managers/file_tests.py | 5 ++--- tests/managers/storage_utils_tests.py | 16 +++------------- 8 files changed, 17 insertions(+), 38 deletions(-) diff --git a/SoftLayer/fixtures/SoftLayer_Location_Datacenter.py b/SoftLayer/fixtures/SoftLayer_Location_Datacenter.py index 510fa18e7..e9aa9b48e 100644 --- a/SoftLayer/fixtures/SoftLayer_Location_Datacenter.py +++ b/SoftLayer/fixtures/SoftLayer_Location_Datacenter.py @@ -9,4 +9,4 @@ "longName": "Dallas 9", "name": "dal09" } -] \ No newline at end of file +] diff --git a/SoftLayer/managers/block.py b/SoftLayer/managers/block.py index 4ff3faa86..45091c002 100644 --- a/SoftLayer/managers/block.py +++ b/SoftLayer/managers/block.py @@ -5,10 +5,8 @@ :license: MIT, see LICENSE for more details. """ -from SoftLayer import exceptions -from SoftLayer.managers import storage_utils from SoftLayer.managers.storage import StorageManager - +from SoftLayer.managers import storage_utils from SoftLayer import utils # pylint: disable=too-many-public-methods @@ -81,7 +79,6 @@ def get_block_volume_details(self, volume_id, **kwargs): """ return self.get_volume_details(volume_id, **kwargs) - def get_block_volume_access_list(self, volume_id, **kwargs): """Returns a list of authorized hosts for a specified volume. @@ -100,7 +97,6 @@ def get_block_volume_snapshot_list(self, volume_id, **kwargs): """ return self.get_volume_snapshot_list(volume_id, **kwargs) - def assign_subnets_to_acl(self, access_id, subnet_ids): """Assigns subnet records to ACL for the access host. diff --git a/SoftLayer/managers/file.py b/SoftLayer/managers/file.py index 367ce559a..b594209d4 100644 --- a/SoftLayer/managers/file.py +++ b/SoftLayer/managers/file.py @@ -5,9 +5,8 @@ :license: MIT, see LICENSE for more details. """ -from SoftLayer import exceptions -from SoftLayer.managers import storage_utils from SoftLayer.managers.storage import StorageManager +from SoftLayer.managers import storage_utils from SoftLayer import utils # pylint: disable=too-many-public-methods @@ -125,7 +124,6 @@ def get_file_volume_snapshot_list(self, volume_id, **kwargs): """ return self.get_volume_snapshot_list(volume_id, **kwargs) - def order_file_volume(self, storage_type, location, size, iops=None, tier_level=None, snapshot_size=None, service_offering='storage_as_a_service', @@ -159,5 +157,3 @@ def cancel_file_volume(self, volume_id, reason='No longer needed', immediate=Fal :param boolean immediate: Cancel immediately or on anniversary date """ return self.cancel_volume(volume_id, reason, immediate) - - diff --git a/SoftLayer/managers/storage.py b/SoftLayer/managers/storage.py index dca50a531..7d4f74562 100644 --- a/SoftLayer/managers/storage.py +++ b/SoftLayer/managers/storage.py @@ -139,8 +139,8 @@ def deauthorize_host_to_volume(self, volume_id, hardware_ids=None, virtual_guest :return: Returns an array of SoftLayer_Network_Storage_Allowed_Host objects which have access to the given File volume """ - host_templates = storage_utils.populate_host_templates(hardware_ids, virtual_guest_ids, - ip_address_ids, subnet_ids) + host_templates = storage_utils.populate_host_templates(hardware_ids, virtual_guest_ids, + ip_address_ids, subnet_ids) return self.client.call('Network_Storage', 'removeAccessFromHostList', host_templates, id=volume_id) @@ -182,8 +182,8 @@ def order_replicant_volume(self, volume_id, snapshot_schedule, location, tier=No storage_class = storage_utils.block_or_file(block_volume['storageType']['keyName']) order = storage_utils.prepare_replicant_order_object( - self, snapshot_schedule, location, tier, block_volume, storage_class - ) + self, snapshot_schedule, location, tier, block_volume, storage_class + ) if storage_class == 'block': if os_type is None: @@ -219,7 +219,6 @@ def order_duplicate_volume(self, origin_volume_id, origin_snapshot_id=None, origin_volume = self.get_volume_details(origin_volume_id, mask=block_mask) storage_class = storage_utils.block_or_file(origin_volume['storageType']['keyName']) - order = storage_utils.prepare_duplicate_order_object( self, origin_volume, duplicate_iops, duplicate_tier_level, duplicate_size, duplicate_snapshot_size, storage_class, hourly_billing_flag @@ -238,7 +237,6 @@ def order_duplicate_volume(self, origin_volume_id, origin_snapshot_id=None, return self.client.call('Product_Order', 'placeOrder', order) - def order_modified_volume(self, volume_id, new_size=None, new_iops=None, new_tier_level=None): """Places an order for modifying an existing block volume. @@ -268,7 +266,6 @@ def order_modified_volume(self, volume_id, new_size=None, new_iops=None, new_tie return self.client.call('Product_Order', 'placeOrder', order) - def delete_snapshot(self, snapshot_id): """Deletes the specified snapshot object. @@ -297,7 +294,7 @@ def order_snapshot_space(self, volume_id, capacity, tier, upgrade, **kwargs): object_mask = 'id,billingItem[location,hourlyFlag],'\ 'storageType[keyName],storageTierLevel,provisionedIops,'\ 'staasVersion,hasEncryptionAtRest' - volume = self.get_volume_details(volume_id, mask=object_mask, **kwargs) + volume = self.get_volume_details(volume_id, mask=object_mask, **kwargs) order = storage_utils.prepare_snapshot_order_object(self, volume, capacity, tier, upgrade) diff --git a/SoftLayer/managers/storage_utils.py b/SoftLayer/managers/storage_utils.py index 97a8c14e2..021fc713f 100644 --- a/SoftLayer/managers/storage_utils.py +++ b/SoftLayer/managers/storage_utils.py @@ -985,6 +985,7 @@ def prepare_modify_order_object(manager, volume, new_iops, new_tier, new_size): return modify_order + def block_or_file(storage_type_keyname): """returns either 'block' or 'file' @@ -993,6 +994,7 @@ def block_or_file(storage_type_keyname): """ return 'block' if 'BLOCK_STORAGE' in storage_type_keyname else 'file' + def _has_category(categories, category_code): return any( True @@ -1022,4 +1024,3 @@ def _find_price_id(prices, category, restriction_type=None, restriction_value=No continue return {'id': price['id']} - diff --git a/tests/managers/block_tests.py b/tests/managers/block_tests.py index 400ba0e19..633cd21c0 100644 --- a/tests/managers/block_tests.py +++ b/tests/managers/block_tests.py @@ -9,10 +9,10 @@ import SoftLayer from SoftLayer import exceptions from SoftLayer.fixtures import SoftLayer_Account -from SoftLayer.fixtures import SoftLayer_Product_Package -from SoftLayer.fixtures import SoftLayer_Product_Order from SoftLayer.fixtures import SoftLayer_Network_Storage from SoftLayer.fixtures import SoftLayer_Network_Storage_Allowed_Host +from SoftLayer.fixtures import SoftLayer_Product_Order +from SoftLayer.fixtures import SoftLayer_Product_Package from SoftLayer import testing diff --git a/tests/managers/file_tests.py b/tests/managers/file_tests.py index 640c2d9f8..8a2db96df 100644 --- a/tests/managers/file_tests.py +++ b/tests/managers/file_tests.py @@ -9,10 +9,9 @@ import SoftLayer from SoftLayer import exceptions from SoftLayer.fixtures import SoftLayer_Account -from SoftLayer.fixtures import SoftLayer_Product_Package -from SoftLayer.fixtures import SoftLayer_Product_Order from SoftLayer.fixtures import SoftLayer_Network_Storage -from SoftLayer.fixtures import SoftLayer_Network_Storage_Allowed_Host +from SoftLayer.fixtures import SoftLayer_Product_Order +from SoftLayer.fixtures import SoftLayer_Product_Package from SoftLayer import testing diff --git a/tests/managers/storage_utils_tests.py b/tests/managers/storage_utils_tests.py index f6934edaf..976f3749a 100644 --- a/tests/managers/storage_utils_tests.py +++ b/tests/managers/storage_utils_tests.py @@ -23,30 +23,20 @@ def set_up(self): # Tests for populate_host_templates() # --------------------------------------------------------------------- def test_populate_host_templates_no_ids_given(self): - host_templates = [] - - storage_utils.populate_host_templates(host_templates) - + host_templates = storage_utils.populate_host_templates() self.assertEqual([], host_templates) def test_populate_host_templates_empty_arrays_given(self): - host_templates = [] - - storage_utils.populate_host_templates( - host_templates, + host_templates = storage_utils.populate_host_templates( hardware_ids=[], virtual_guest_ids=[], ip_address_ids=[], subnet_ids=[] ) - self.assertEqual([], host_templates) def test_populate_host_templates(self): - host_templates = [] - - storage_utils.populate_host_templates( - host_templates, + host_templates = storage_utils.populate_host_templates( hardware_ids=[1111], virtual_guest_ids=[2222], ip_address_ids=[3333], From 1c812ded1233e9fa8230da510ad913442d4a2606 Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Wed, 26 Feb 2020 16:29:28 -0600 Subject: [PATCH 06/12] resolved merge conflicts with master --- SoftLayer/managers/storage.py | 9 ++++++--- tests/managers/block_tests.py | 6 +++--- tests/managers/file_tests.py | 6 +++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/SoftLayer/managers/storage.py b/SoftLayer/managers/storage.py index 7d4f74562..c9768730a 100644 --- a/SoftLayer/managers/storage.py +++ b/SoftLayer/managers/storage.py @@ -197,9 +197,9 @@ def order_replicant_volume(self, volume_id, snapshot_schedule, location, tier=No return self.client.call('Product_Order', 'placeOrder', order) - def order_duplicate_volume(self, origin_volume_id, origin_snapshot_id=None, - duplicate_size=None, duplicate_iops=None, duplicate_tier_level=None, - duplicate_snapshot_size=None, hourly_billing_flag=False): + def order_duplicate_volume(self, origin_volume_id, origin_snapshot_id=None, duplicate_size=None, + duplicate_iops=None, duplicate_tier_level=None, duplicate_snapshot_size=None, + hourly_billing_flag=False, dependent_duplicate=False): """Places an order for a duplicate volume. :param origin_volume_id: The ID of the origin volume to be duplicated @@ -234,6 +234,9 @@ def order_duplicate_volume(self, origin_volume_id, origin_snapshot_id=None, if origin_snapshot_id is not None: order['duplicateOriginSnapshotId'] = origin_snapshot_id + if dependent_duplicate: + # if isDependentDuplicateFlag is set to ANYTHING, it is considered dependent. + order['isDependentDuplicateFlag'] = 1 return self.client.call('Product_Order', 'placeOrder', order) diff --git a/tests/managers/block_tests.py b/tests/managers/block_tests.py index 911a5f766..30a767aaf 100644 --- a/tests/managers/block_tests.py +++ b/tests/managers/block_tests.py @@ -855,9 +855,9 @@ def test_order_block_duplicate_performance(self): def test_order_block_duplicate_depdupe(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -872,7 +872,7 @@ def test_order_block_duplicate_depdupe(self): dependent_duplicate=True ) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', diff --git a/tests/managers/file_tests.py b/tests/managers/file_tests.py index 2011ff327..bdfe9aafd 100644 --- a/tests/managers/file_tests.py +++ b/tests/managers/file_tests.py @@ -747,9 +747,9 @@ def test_order_file_duplicate_endurance_no_duplicate_snapshot(self): def test_order_file_duplicate_depdupe(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + mock.return_value = [SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = copy.deepcopy(fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME) + mock_volume = copy.deepcopy(SoftLayer_Network_Storage.STAAS_TEST_VOLUME) mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -764,7 +764,7 @@ def test_order_file_duplicate_depdupe(self): dependent_duplicate=True ) - self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + self.assertEqual(SoftLayer_Product_Order.placeOrder, result) self.assert_called_with( 'SoftLayer_Product_Order', From 63219ac10af22c0f6f6eded39a3683487983cf06 Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Wed, 26 Feb 2020 16:51:07 -0600 Subject: [PATCH 07/12] Merged in #1232 and added it to the refactor --- SoftLayer/CLI/block/detail.py | 17 ---------- SoftLayer/CLI/file/detail.py | 17 ---------- SoftLayer/managers/block.py | 7 ++++ SoftLayer/managers/file.py | 7 ++++ SoftLayer/managers/storage.py | 4 +++ tests/CLI/modules/block_tests.py | 56 +++++++++----------------------- tests/CLI/modules/file_tests.py | 56 +++++++++----------------------- 7 files changed, 50 insertions(+), 114 deletions(-) diff --git a/SoftLayer/CLI/block/detail.py b/SoftLayer/CLI/block/detail.py index 02ce0c82f..2e7b115e7 100644 --- a/SoftLayer/CLI/block/detail.py +++ b/SoftLayer/CLI/block/detail.py @@ -9,29 +9,12 @@ from SoftLayer import utils -def get_block_volume_id(volume_id, block_manager): - """Returns the volume id. - - :param volume_id: ID of volume. - :param block_manager: Block Storage Manager. - :return: Returns the volume id. - """ - storage_list = block_manager.list_block_volumes() - for storage in storage_list: - if volume_id == storage['username']: - volume_id = storage['id'] - break - - return volume_id - - @click.command() @click.argument('volume_id') @environment.pass_env def cli(env, volume_id): """Display details for a specified volume.""" block_manager = SoftLayer.BlockStorageManager(env.client) - volume_id = get_block_volume_id(volume_id, block_manager) block_volume_id = helpers.resolve_id(block_manager.resolve_ids, volume_id, 'Block Volume') block_volume = block_manager.get_block_volume_details(block_volume_id) block_volume = utils.NestedDict(block_volume) diff --git a/SoftLayer/CLI/file/detail.py b/SoftLayer/CLI/file/detail.py index ad0393916..cea86e351 100644 --- a/SoftLayer/CLI/file/detail.py +++ b/SoftLayer/CLI/file/detail.py @@ -9,29 +9,12 @@ from SoftLayer import utils -def get_file_volume_id(volume_id, file_manager): - """Returns the volume id. - - :param volume_id: ID of volume. - :param block_manager: Block Storage Manager. - :return: Returns the volume id. - """ - storage_list = file_manager.list_file_volumes() - for storage in storage_list: - if volume_id == storage['username']: - volume_id = storage['id'] - break - - return volume_id - - @click.command() @click.argument('volume_id') @environment.pass_env def cli(env, volume_id): """Display details for a specified volume.""" file_manager = SoftLayer.FileStorageManager(env.client) - volume_id = get_file_volume_id(volume_id, file_manager) file_volume_id = helpers.resolve_id(file_manager.resolve_ids, volume_id, 'File Storage') file_volume = file_manager.get_file_volume_details(file_volume_id) file_volume = utils.NestedDict(file_volume) diff --git a/SoftLayer/managers/block.py b/SoftLayer/managers/block.py index 45091c002..eec22a4bb 100644 --- a/SoftLayer/managers/block.py +++ b/SoftLayer/managers/block.py @@ -184,3 +184,10 @@ def create_or_update_lun_id(self, volume_id, lun_id): :return: a SoftLayer_Network_Storage_Property object """ return self.client.call('Network_Storage', 'createOrUpdateLunId', lun_id, id=volume_id) + + def _get_ids_from_username(self, username): + object_mask = "mask[id]" + results = self.list_block_volumes(username=username, mask=object_mask) + if results: + return [result['id'] for result in results] + diff --git a/SoftLayer/managers/file.py b/SoftLayer/managers/file.py index b594209d4..458ffa9aa 100644 --- a/SoftLayer/managers/file.py +++ b/SoftLayer/managers/file.py @@ -157,3 +157,10 @@ def cancel_file_volume(self, volume_id, reason='No longer needed', immediate=Fal :param boolean immediate: Cancel immediately or on anniversary date """ return self.cancel_volume(volume_id, reason, immediate) + + def _get_ids_from_username(self, username): + object_mask = "mask[id]" + results = self.list_file_volumes(username=username, mask=object_mask) + if results: + return [result['id'] for result in results] + diff --git a/SoftLayer/managers/storage.py b/SoftLayer/managers/storage.py index c9768730a..7c927362c 100644 --- a/SoftLayer/managers/storage.py +++ b/SoftLayer/managers/storage.py @@ -23,6 +23,10 @@ class StorageManager(utils.IdentifierMixin, object): def __init__(self, client): self.configuration = {} self.client = client + self.resolvers = [self._get_ids_from_username] + + def _get_ids_from_username(self, username): + raise exceptions.SoftLayerError("Not Implemented.") def get_volume_count_limits(self): """Returns a list of block volume count limit. diff --git a/tests/CLI/modules/block_tests.py b/tests/CLI/modules/block_tests.py index 42e574c48..9e5774400 100644 --- a/tests/CLI/modules/block_tests.py +++ b/tests/CLI/modules/block_tests.py @@ -60,6 +60,7 @@ def test_volume_detail(self): self.assert_no_fail(result) isinstance(json.loads(result.output)['IOPs'], float) + self.assert_called_with('SoftLayer_Network_Storage', 'getObject', identifier=1234) self.assertEqual({ 'Username': 'username', 'LUN Id': '2', @@ -99,47 +100,22 @@ def test_volume_detail(self): }, json.loads(result.output)) def test_volume_detail_name_identifier(self): - result = self.run_command(['block', 'volume-detail', 'username']) - + result = self.run_command(['block', 'volume-detail', 'SL-12345']) + expected_filter = { + 'iscsiNetworkStorage': { + 'serviceResource': { + 'type': { + 'type': {'operation': '!~ ISCSI'} + } + }, + 'storageType': { + 'keyName': {'operation': '*= BLOCK_STORAGE'} + }, + 'username': {'operation': '_= SL-12345'}}} + + self.assert_called_with('SoftLayer_Account', 'getIscsiNetworkStorage', filter=expected_filter) + self.assert_called_with('SoftLayer_Network_Storage', 'getObject', identifier=100) self.assert_no_fail(result) - isinstance(json.loads(result.output)['IOPs'], float) - self.assertEqual({ - 'Username': 'username', - 'LUN Id': '2', - 'Endurance Tier': 'READHEAVY_TIER', - 'IOPs': 1000, - 'Snapshot Capacity (GB)': '10', - 'Snapshot Used (Bytes)': 1024, - 'Capacity (GB)': '20GB', - 'Target IP': '10.1.2.3', - 'Data Center': 'dal05', - 'Type': 'ENDURANCE', - 'ID': 100, - '# of Active Transactions': '1', - 'Ongoing Transaction': 'This is a buffer time in which the customer may cancel the server', - 'Replicant Count': '1', - 'Replication Status': 'Replicant Volume Provisioning ' - 'has completed.', - 'Replicant Volumes': [[ - {'Replicant ID': 'Volume Name', '1784': 'TEST_REP_1'}, - {'Replicant ID': 'Target IP', '1784': '10.3.174.79'}, - {'Replicant ID': 'Data Center', '1784': 'wdc01'}, - {'Replicant ID': 'Schedule', '1784': 'REPLICATION_HOURLY'}, - ], [ - {'Replicant ID': 'Volume Name', '1785': 'TEST_REP_2'}, - {'Replicant ID': 'Target IP', '1785': '10.3.177.84'}, - {'Replicant ID': 'Data Center', '1785': 'dal01'}, - {'Replicant ID': 'Schedule', '1785': 'REPLICATION_DAILY'}, - ]], - 'Original Volume Properties': [ - {'Property': 'Original Volume Size', - 'Value': '20'}, - {'Property': 'Original Volume Name', - 'Value': 'test-original-volume-name'}, - {'Property': 'Original Snapshot Name', - 'Value': 'test-original-snapshot-name'} - ] - }, json.loads(result.output)) def test_volume_list(self): result = self.run_command(['block', 'volume-list']) diff --git a/tests/CLI/modules/file_tests.py b/tests/CLI/modules/file_tests.py index e5e3ca556..b37fb0c3f 100644 --- a/tests/CLI/modules/file_tests.py +++ b/tests/CLI/modules/file_tests.py @@ -164,47 +164,23 @@ def test_volume_detail(self): }, json.loads(result.output)) def test_volume_detail_name_identifier(self): - result = self.run_command(['file', 'volume-detail', 'user']) - + result = self.run_command(['file', 'volume-detail', 'SL-12345']) + expected_filter = { + 'nasNetworkStorage': { + 'serviceResource': { + 'type': { + 'type': {'operation': '!~ NAS'} + } + }, + 'storageType': { + 'keyName': {'operation': '*= FILE_STORAGE'} + }, + 'username': {'operation': '_= SL-12345'}}} + + self.assert_called_with('SoftLayer_Account', 'getNasNetworkStorage', filter=expected_filter) + self.assert_called_with('SoftLayer_Network_Storage', 'getObject', identifier=1) self.assert_no_fail(result) - self.assertEqual({ - 'Username': 'username', - 'Used Space': '0B', - 'Endurance Tier': 'READHEAVY_TIER', - 'IOPs': 1000, - 'Mount Address': '127.0.0.1:/TEST', - 'Snapshot Capacity (GB)': '10', - 'Snapshot Used (Bytes)': 1024, - 'Capacity (GB)': '20GB', - 'Target IP': '10.1.2.3', - 'Data Center': 'dal05', - 'Type': 'ENDURANCE', - 'ID': 100, - '# of Active Transactions': '1', - 'Ongoing Transaction': 'This is a buffer time in which the customer may cancel the server', - 'Replicant Count': '1', - 'Replication Status': 'Replicant Volume Provisioning ' - 'has completed.', - 'Replicant Volumes': [[ - {'Replicant ID': 'Volume Name', '1784': 'TEST_REP_1'}, - {'Replicant ID': 'Target IP', '1784': '10.3.174.79'}, - {'Replicant ID': 'Data Center', '1784': 'wdc01'}, - {'Replicant ID': 'Schedule', '1784': 'REPLICATION_HOURLY'}, - ], [ - {'Replicant ID': 'Volume Name', '1785': 'TEST_REP_2'}, - {'Replicant ID': 'Target IP', '1785': '10.3.177.84'}, - {'Replicant ID': 'Data Center', '1785': 'dal01'}, - {'Replicant ID': 'Schedule', '1785': 'REPLICATION_DAILY'}, - ]], - 'Original Volume Properties': [ - {'Property': 'Original Volume Size', - 'Value': '20'}, - {'Property': 'Original Volume Name', - 'Value': 'test-original-volume-name'}, - {'Property': 'Original Snapshot Name', - 'Value': 'test-original-snapshot-name'} - ] - }, json.loads(result.output)) + def test_volume_order_performance_iops_not_given(self): result = self.run_command(['file', 'volume-order', From 77dc9368c0b13d0478a9e252e698ef83dcf5a3d1 Mon Sep 17 00:00:00 2001 From: allmightyspiff Date: Wed, 26 Feb 2020 16:57:12 -0600 Subject: [PATCH 08/12] tox and style fixes --- SoftLayer/managers/block.py | 2 +- SoftLayer/managers/file.py | 2 +- SoftLayer/managers/storage.py | 3 --- tests/CLI/modules/block_tests.py | 4 ++-- tests/CLI/modules/file_tests.py | 5 ++--- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/SoftLayer/managers/block.py b/SoftLayer/managers/block.py index eec22a4bb..4d129d07c 100644 --- a/SoftLayer/managers/block.py +++ b/SoftLayer/managers/block.py @@ -190,4 +190,4 @@ def _get_ids_from_username(self, username): results = self.list_block_volumes(username=username, mask=object_mask) if results: return [result['id'] for result in results] - + return [] diff --git a/SoftLayer/managers/file.py b/SoftLayer/managers/file.py index 458ffa9aa..ce1b951c8 100644 --- a/SoftLayer/managers/file.py +++ b/SoftLayer/managers/file.py @@ -163,4 +163,4 @@ def _get_ids_from_username(self, username): results = self.list_file_volumes(username=username, mask=object_mask) if results: return [result['id'] for result in results] - + return [] diff --git a/SoftLayer/managers/storage.py b/SoftLayer/managers/storage.py index 7c927362c..2d45bd0db 100644 --- a/SoftLayer/managers/storage.py +++ b/SoftLayer/managers/storage.py @@ -25,9 +25,6 @@ def __init__(self, client): self.client = client self.resolvers = [self._get_ids_from_username] - def _get_ids_from_username(self, username): - raise exceptions.SoftLayerError("Not Implemented.") - def get_volume_count_limits(self): """Returns a list of block volume count limit. diff --git a/tests/CLI/modules/block_tests.py b/tests/CLI/modules/block_tests.py index 9e5774400..f8408dcdd 100644 --- a/tests/CLI/modules/block_tests.py +++ b/tests/CLI/modules/block_tests.py @@ -107,10 +107,10 @@ def test_volume_detail_name_identifier(self): 'type': { 'type': {'operation': '!~ ISCSI'} } - }, + }, 'storageType': { 'keyName': {'operation': '*= BLOCK_STORAGE'} - }, + }, 'username': {'operation': '_= SL-12345'}}} self.assert_called_with('SoftLayer_Account', 'getIscsiNetworkStorage', filter=expected_filter) diff --git a/tests/CLI/modules/file_tests.py b/tests/CLI/modules/file_tests.py index b37fb0c3f..20e065940 100644 --- a/tests/CLI/modules/file_tests.py +++ b/tests/CLI/modules/file_tests.py @@ -171,17 +171,16 @@ def test_volume_detail_name_identifier(self): 'type': { 'type': {'operation': '!~ NAS'} } - }, + }, 'storageType': { 'keyName': {'operation': '*= FILE_STORAGE'} - }, + }, 'username': {'operation': '_= SL-12345'}}} self.assert_called_with('SoftLayer_Account', 'getNasNetworkStorage', filter=expected_filter) self.assert_called_with('SoftLayer_Network_Storage', 'getObject', identifier=1) self.assert_no_fail(result) - def test_volume_order_performance_iops_not_given(self): result = self.run_command(['file', 'volume-order', '--storage-type=performance', '--size=20', From c64c058d9488c35f4d95e1ad9b5628d496334c70 Mon Sep 17 00:00:00 2001 From: Christopher Gallo Date: Thu, 27 Feb 2020 14:31:41 -0600 Subject: [PATCH 09/12] a few minor unit test fixes --- tests/CLI/modules/block_tests.py | 4 +++- tests/managers/block_tests.py | 12 ++++++++++++ tests/managers/file_tests.py | 12 ++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/CLI/modules/block_tests.py b/tests/CLI/modules/block_tests.py index f8408dcdd..0dd7eac57 100644 --- a/tests/CLI/modules/block_tests.py +++ b/tests/CLI/modules/block_tests.py @@ -111,7 +111,9 @@ def test_volume_detail_name_identifier(self): 'storageType': { 'keyName': {'operation': '*= BLOCK_STORAGE'} }, - 'username': {'operation': '_= SL-12345'}}} + 'username': {'operation': '_= SL-12345'} + } + } self.assert_called_with('SoftLayer_Account', 'getIscsiNetworkStorage', filter=expected_filter) self.assert_called_with('SoftLayer_Network_Storage', 'getObject', identifier=100) diff --git a/tests/managers/block_tests.py b/tests/managers/block_tests.py index 30a767aaf..7febbfcf3 100644 --- a/tests/managers/block_tests.py +++ b/tests/managers/block_tests.py @@ -1030,3 +1030,15 @@ def test_setCredentialPassword(self): def test_list_block_volume_limit(self): result = self.block.list_block_volume_limit() self.assertEqual(SoftLayer_Network_Storage.getVolumeCountLimits, result) + + def test_get_ids_from_username(self): + result = self.block._get_ids_from_username("test") + self.assert_called_with('SoftLayer_Account', 'getIscsiNetworkStorage') + self.assertEqual([100], result) + + def test_get_ids_from_username_empty(self): + mock = self.set_mock('SoftLayer_Account', 'getIscsiNetworkStorage') + mock.return_value = [] + result = self.block._get_ids_from_username("test") + self.assert_called_with('SoftLayer_Account', 'getIscsiNetworkStorage') + self.assertEqual([], result) diff --git a/tests/managers/file_tests.py b/tests/managers/file_tests.py index bdfe9aafd..dbd181228 100644 --- a/tests/managers/file_tests.py +++ b/tests/managers/file_tests.py @@ -879,3 +879,15 @@ def test_order_file_modified_endurance(self): def test_list_file_volume_limit(self): result = self.file.list_file_volume_limit() self.assertEqual(SoftLayer_Network_Storage.getVolumeCountLimits, result) + + def test_get_ids_from_username(self): + result = self.file._get_ids_from_username("test") + self.assert_called_with('SoftLayer_Account', 'getNasNetworkStorage') + self.assertEqual([1], result) + + def test_get_ids_from_username_empty(self): + mock = self.set_mock('SoftLayer_Account', 'getNasNetworkStorage') + mock.return_value = [] + result = self.file._get_ids_from_username("test") + self.assert_called_with('SoftLayer_Account', 'getNasNetworkStorage') + self.assertEqual([], result) From 030bb5a91bede9df4e9ebdeca90c8e11b33243c7 Mon Sep 17 00:00:00 2001 From: Ian Sutton Date: Fri, 28 Feb 2020 09:09:03 -0600 Subject: [PATCH 10/12] minor --- SoftLayer/managers/block.py | 6 ++---- docs/cli/file.rst | 8 ++++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/SoftLayer/managers/block.py b/SoftLayer/managers/block.py index 8b379513f..d3c1918fe 100644 --- a/SoftLayer/managers/block.py +++ b/SoftLayer/managers/block.py @@ -623,13 +623,11 @@ def refresh_dep_dupe(self, volume_id, snapshot_id): :param integer volume_id: The id of the volume :param integer snapshot_id: The id of the snapshot """ - return self.client.call('Network_Storage', 'refreshDependentDuplicate', - snapshot_id, id=volume_id) + return self.client.call('Network_Storage', 'refreshDependentDuplicate', snapshot_id, id=volume_id) def convert_dep_dupe(self, volume_id): """Convert a dependent duplicate volume to an indepdent volume. :param integer volume_id: The id of the volume. """ - return self.client.call('Network_Storage', 'convertCloneDependentToIndependent', - id=volume_id) + return self.client.call('Network_Storage', 'convertCloneDependentToIndependent', id=volume_id) diff --git a/docs/cli/file.rst b/docs/cli/file.rst index ad01b0337..13cf92a61 100644 --- a/docs/cli/file.rst +++ b/docs/cli/file.rst @@ -99,6 +99,14 @@ File Commands :prog: file volume-limits :show-nested: +.. click:: SoftLayer.CLI.file.refresh:cli + :prog file volume-refresh + :show-nested: + +.. click:: SoftLayer.CLI.file.convert:cli + :prog file volume-convert + :show-nested: + .. click:: SoftLayer.CLI.file.snapshot.schedule_list:cli :prog: file snapshot-schedule-list :show-nested: From 73b1315e2d4f732fb0ee0cc526aedca6526a0f81 Mon Sep 17 00:00:00 2001 From: Ian Sutton Date: Fri, 28 Feb 2020 10:58:50 -0600 Subject: [PATCH 11/12] UTs, and merge in coalesced storage branch --- .../fixtures/SoftLayer_Network_Storage.py | 9 +++++++++ SoftLayer/managers/storage.py | 15 ++++++++++++++ tests/CLI/modules/block_tests.py | 10 ++++++++++ tests/CLI/modules/file_tests.py | 10 ++++++++++ tests/managers/block_tests.py | 20 +++++++++++++++++++ tests/managers/file_tests.py | 20 +++++++++++++++++++ 6 files changed, 84 insertions(+) diff --git a/SoftLayer/fixtures/SoftLayer_Network_Storage.py b/SoftLayer/fixtures/SoftLayer_Network_Storage.py index 3c8d335e9..611e88005 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_Storage.py +++ b/SoftLayer/fixtures/SoftLayer_Network_Storage.py @@ -157,6 +157,7 @@ 'storageTierLevel': 'READHEAVY_TIER', 'storageType': {'keyName': 'ENDURANCE_STORAGE'}, 'username': 'username', + 'dependentDuplicate': 1, } getSnapshots = [{ @@ -232,3 +233,11 @@ 'maximumAvailableCount': 300, 'provisionedCount': 100 } + +refreshDependentDuplicate = { + 'dependentDuplicate': 1 +} + +convertCloneDependentToIndependent = { + 'dependentDuplicate': 1 +} diff --git a/SoftLayer/managers/storage.py b/SoftLayer/managers/storage.py index 2d45bd0db..a17322361 100644 --- a/SoftLayer/managers/storage.py +++ b/SoftLayer/managers/storage.py @@ -414,3 +414,18 @@ def cancel_volume(self, volume_id, reason='No longer needed', immediate=False): immediate = True return self.client.call('SoftLayer_Billing_Item', 'cancelItem', immediate, True, reason, id=billing_item_id) + + def refresh_dep_dupe(self, volume_id, snapshot_id): + """"Refresh a dependent duplicate volume with a snapshot from its parent. + + :param integer volume_id: The id of the volume + :param integer snapshot_id: The id of the snapshot + """ + return self.client.call('Network_Storage', 'refreshDependentDuplicate', snapshot_id, id=volume_id) + + def convert_dep_dupe(self, volume_id): + """Convert a dependent duplicate volume to an indepdent volume. + + :param integer volume_id: The id of the volume. + """ + return self.client.call('Network_Storage', 'convertCloneDependentToIndependent', id=volume_id) diff --git a/tests/CLI/modules/block_tests.py b/tests/CLI/modules/block_tests.py index 0dd7eac57..b39face10 100644 --- a/tests/CLI/modules/block_tests.py +++ b/tests/CLI/modules/block_tests.py @@ -716,3 +716,13 @@ def test_volume_limit(self, list_mock): result = self.run_command(['block', 'volume-limits']) self.assert_no_fail(result) + + def test_dep_dupe_refresh(self): + result = self.run_command(['block', 'volume-refresh', '102', '103']) + + self.assert_no_fail(result) + + def test_dep_dupe_convert(self): + result = self.run_command(['block', 'volume-convert', '102']) + + self.assert_no_fail(result) diff --git a/tests/CLI/modules/file_tests.py b/tests/CLI/modules/file_tests.py index 20e065940..1d64f54ae 100644 --- a/tests/CLI/modules/file_tests.py +++ b/tests/CLI/modules/file_tests.py @@ -695,3 +695,13 @@ def test_volume_limit(self, list_mock): }] result = self.run_command(['file', 'volume-limits']) self.assert_no_fail(result) + + def test_dep_dupe_refresh(self): + result = self.run_command(['file', 'volume-refresh', '102', '103']) + + self.assert_no_fail(result) + + def test_dep_dupe_convert(self): + result = self.run_command(['file', 'volume-convert', '102']) + + self.assert_no_fail(result) diff --git a/tests/managers/block_tests.py b/tests/managers/block_tests.py index 7febbfcf3..c9731a04d 100644 --- a/tests/managers/block_tests.py +++ b/tests/managers/block_tests.py @@ -1042,3 +1042,23 @@ def test_get_ids_from_username_empty(self): result = self.block._get_ids_from_username("test") self.assert_called_with('SoftLayer_Account', 'getIscsiNetworkStorage') self.assertEqual([], result) + + def test_refresh_block_depdupe(self): + result = self.block.refresh_dep_dupe(123, snapshot_id=321) + self.assertEqual(SoftLayer_Network_Storage.refreshDependentDuplicate, result) + + self.assert_called_with( + 'SoftLayer_Network_Storage', + 'refreshDependentDuplicate', + identifier=123 + ) + + def test_convert_block_depdupe(self): + result = self.block.convert_dep_dupe(123) + self.assertEqual(SoftLayer_Network_Storage.convertCloneDependentToIndependent, result) + + self.assert_called_with( + 'SoftLayer_Network_Storage', + 'convertCloneDependentToIndependent', + identifier=123 + ) diff --git a/tests/managers/file_tests.py b/tests/managers/file_tests.py index dbd181228..6df2b8721 100644 --- a/tests/managers/file_tests.py +++ b/tests/managers/file_tests.py @@ -891,3 +891,23 @@ def test_get_ids_from_username_empty(self): result = self.file._get_ids_from_username("test") self.assert_called_with('SoftLayer_Account', 'getNasNetworkStorage') self.assertEqual([], result) + + def test_refresh_file_depdupe(self): + result = self.file.refresh_dep_dupe(123, snapshot_id=321) + self.assertEqual(SoftLayer_Network_Storage.refreshDependentDuplicate, result) + + self.assert_called_with( + 'SoftLayer_Network_Storage', + 'refreshDependentDuplicate', + identifier=123 + ) + + def test_convert_file_depdupe(self): + result = self.file.convert_dep_dupe(123) + self.assertEqual(SoftLayer_Network_Storage.convertCloneDependentToIndependent, result) + + self.assert_called_with( + 'SoftLayer_Network_Storage', + 'convertCloneDependentToIndependent', + identifier=123 + ) From 833700ccbfc932f8c554bdf94399a1589d967d92 Mon Sep 17 00:00:00 2001 From: Ian Sutton Date: Fri, 28 Feb 2020 16:17:13 -0600 Subject: [PATCH 12/12] spelling --- SoftLayer/CLI/block/convert.py | 4 ++-- SoftLayer/CLI/file/convert.py | 4 ++-- SoftLayer/managers/storage.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SoftLayer/CLI/block/convert.py b/SoftLayer/CLI/block/convert.py index 795d3d27c..a48d8926c 100644 --- a/SoftLayer/CLI/block/convert.py +++ b/SoftLayer/CLI/block/convert.py @@ -1,4 +1,4 @@ -"""Convert a dependent duplicate volume to an indepdent volume.""" +"""Convert a dependent duplicate volume to an independent volume.""" # :license: MIT, see LICENSE for more details. import click @@ -10,7 +10,7 @@ @click.argument('volume_id') @environment.pass_env def cli(env, volume_id): - """Convert a dependent duplicate volume to an indepdent volume.""" + """Convert a dependent duplicate volume to an independent volume.""" block_manager = SoftLayer.BlockStorageManager(env.client) resp = block_manager.convert_dep_dupe(volume_id) diff --git a/SoftLayer/CLI/file/convert.py b/SoftLayer/CLI/file/convert.py index 7c01d8c53..8558ef009 100644 --- a/SoftLayer/CLI/file/convert.py +++ b/SoftLayer/CLI/file/convert.py @@ -1,4 +1,4 @@ -"""Convert a dependent duplicate volume to an indepdent volume.""" +"""Convert a dependent duplicate volume to an independent volume.""" # :license: MIT, see LICENSE for more details. import click @@ -10,7 +10,7 @@ @click.argument('volume_id') @environment.pass_env def cli(env, volume_id): - """Convert a dependent duplicate volume to an indepdent volume.""" + """Convert a dependent duplicate volume to an independent volume.""" file_manager = SoftLayer.FileStorageManager(env.client) resp = file_manager.convert_dep_dupe(volume_id) diff --git a/SoftLayer/managers/storage.py b/SoftLayer/managers/storage.py index a17322361..9a8015d58 100644 --- a/SoftLayer/managers/storage.py +++ b/SoftLayer/managers/storage.py @@ -424,7 +424,7 @@ def refresh_dep_dupe(self, volume_id, snapshot_id): return self.client.call('Network_Storage', 'refreshDependentDuplicate', snapshot_id, id=volume_id) def convert_dep_dupe(self, volume_id): - """Convert a dependent duplicate volume to an indepdent volume. + """Convert a dependent duplicate volume to an independent volume. :param integer volume_id: The id of the volume. """