From 195bb3af619606c4dee1e3b995b605f0d19d31f2 Mon Sep 17 00:00:00 2001 From: David Pickle Date: Wed, 5 Jul 2017 19:34:40 -0500 Subject: [PATCH 1/4] Update file/block ordering to support storage_as_a_service package **Includes updates to logic for ordering volumes, replicas, and snapshot space. The storage_as_a_service package is used as a default for new volume orders, but customers can specify older packages for use. The package associated with the existing primary volume is used in replica and snapshot orders. **Also includes a refactoring of a number of the unit tests for File and Block manager functions. --- SoftLayer/CLI/block/order.py | 33 +- SoftLayer/CLI/block/snapshot/order.py | 5 +- SoftLayer/CLI/file/order.py | 33 +- SoftLayer/CLI/file/snapshot/order.py | 5 +- .../fixtures/SoftLayer_Network_Storage.py | 156 +- .../fixtures/SoftLayer_Product_Package.py | 521 ++- SoftLayer/managers/block.py | 114 +- SoftLayer/managers/file.py | 127 +- SoftLayer/managers/storage_utils.py | 596 ++- tests/CLI/modules/block_tests.py | 41 +- tests/CLI/modules/file_tests.py | 41 +- tests/managers/block_tests.py | 979 ++--- tests/managers/file_tests.py | 967 ++--- tests/managers/storage_utils_tests.py | 3612 ++++++++++++++--- 14 files changed, 4673 insertions(+), 2557 deletions(-) diff --git a/SoftLayer/CLI/block/order.py b/SoftLayer/CLI/block/order.py index a5af2a671..cdcaeef0a 100644 --- a/SoftLayer/CLI/block/order.py +++ b/SoftLayer/CLI/block/order.py @@ -48,40 +48,48 @@ help='Optional parameter for ordering snapshot ' 'space along with endurance block storage; specifies ' 'the size (in GB) of snapshot space to order') +@click.option('--service-offering', + help='The service offering package to use for placing ' + 'the order [optional, default is \'storage_as_a_service\'', + type=click.Choice([ + 'storage_as_a_service', + 'enterprise', + 'performance'])) @environment.pass_env def cli(env, storage_type, size, iops, tier, os_type, - location, snapshot_size): + location, snapshot_size, service_offering): """Order a block storage volume.""" block_manager = SoftLayer.BlockStorageManager(env.client) storage_type = storage_type.lower() + if service_offering is None: + service_offering = 'storage_as_a_service' + if storage_type == 'performance': if iops is None: raise exceptions.CLIAbort( 'Option --iops required with Performance') - if iops < 100 or iops > 6000: - raise exceptions.CLIAbort( - 'Option --iops must be between 100 and 6000, inclusive') - if iops % 100 != 0: raise exceptions.CLIAbort( 'Option --iops must be a multiple of 100' ) - if snapshot_size is not None: + if service_offering == 'performance' and snapshot_size is not None: raise exceptions.CLIAbort( - 'Option --snapshot-size not allowed for performance volumes.' - 'Snapshots are only available for endurance storage.' + '--snapshot-size is not available for performance volumes ' + 'ordered with the \'performance\' service offering option' ) try: order = block_manager.order_block_volume( - storage_type='performance_storage_iscsi', + storage_type=storage_type, location=location, size=int(size), iops=iops, - os_type=os_type + os_type=os_type, + snapshot_size=snapshot_size, + service_offering=service_offering ) except ValueError as ex: raise exceptions.ArgumentError(str(ex)) @@ -95,12 +103,13 @@ def cli(env, storage_type, size, iops, tier, os_type, try: order = block_manager.order_block_volume( - storage_type='storage_service_enterprise', + storage_type=storage_type, location=location, size=int(size), tier_level=float(tier), os_type=os_type, - snapshot_size=snapshot_size + snapshot_size=snapshot_size, + service_offering=service_offering ) except ValueError as ex: raise exceptions.ArgumentError(str(ex)) diff --git a/SoftLayer/CLI/block/snapshot/order.py b/SoftLayer/CLI/block/snapshot/order.py index 119c4d86e..c5d798eba 100644 --- a/SoftLayer/CLI/block/snapshot/order.py +++ b/SoftLayer/CLI/block/snapshot/order.py @@ -15,8 +15,9 @@ required=True) @click.option('--tier', help='Endurance Storage Tier (IOPS per GB) of the block' - ' volume for which space is ordered [optional]', - type=click.Choice(['0.25', '2', '4'])) + ' volume for which space is ordered [optional, and only' + ' valid for endurance storage volumes]', + type=click.Choice(['0.25', '2', '4', '10'])) @click.option('--upgrade', type=bool, help='Flag to indicate that the order is an upgrade', diff --git a/SoftLayer/CLI/file/order.py b/SoftLayer/CLI/file/order.py index d13b952b1..8d3e77ad3 100644 --- a/SoftLayer/CLI/file/order.py +++ b/SoftLayer/CLI/file/order.py @@ -36,39 +36,47 @@ help='Optional parameter for ordering snapshot ' 'space along with endurance file storage; specifies ' 'the size (in GB) of snapshot space to order') +@click.option('--service-offering', + help='The service offering package to use for placing ' + 'the order [optional, default is \'storage_as_a_service\'', + type=click.Choice([ + 'storage_as_a_service', + 'enterprise', + 'performance'])) @environment.pass_env def cli(env, storage_type, size, iops, tier, - location, snapshot_size): + location, snapshot_size, service_offering): """Order a file storage volume.""" file_manager = SoftLayer.FileStorageManager(env.client) storage_type = storage_type.lower() + if service_offering is None: + service_offering = 'storage_as_a_service' + if storage_type == 'performance': if iops is None: raise exceptions.CLIAbort( 'Option --iops required with Performance') - if iops < 100 or iops > 6000: - raise exceptions.CLIAbort( - 'Option --iops must be between 100 and 6000, inclusive') - if iops % 100 != 0: raise exceptions.CLIAbort( 'Option --iops must be a multiple of 100' ) - if snapshot_size is not None: + if service_offering == 'performance' and snapshot_size is not None: raise exceptions.CLIAbort( - 'Option --snapshot-size not allowed for performance volumes.' - ' Snapshots are only available for endurance storage.' + '--snapshot-size is not available for performance volumes ' + 'ordered with the \'performance\' service offering option' ) try: order = file_manager.order_file_volume( - storage_type='performance_storage_nfs', + storage_type=storage_type, location=location, size=size, - iops=iops + iops=iops, + snapshot_size=snapshot_size, + service_offering=service_offering ) except ValueError as ex: raise exceptions.ArgumentError(str(ex)) @@ -82,11 +90,12 @@ def cli(env, storage_type, size, iops, tier, try: order = file_manager.order_file_volume( - storage_type='storage_service_enterprise', + storage_type=storage_type, location=location, size=size, tier_level=float(tier), - snapshot_size=snapshot_size + snapshot_size=snapshot_size, + service_offering=service_offering ) except ValueError as ex: raise exceptions.ArgumentError(str(ex)) diff --git a/SoftLayer/CLI/file/snapshot/order.py b/SoftLayer/CLI/file/snapshot/order.py index fbfff517b..9043f8bf0 100644 --- a/SoftLayer/CLI/file/snapshot/order.py +++ b/SoftLayer/CLI/file/snapshot/order.py @@ -15,8 +15,9 @@ required=True) @click.option('--tier', help='Endurance Storage Tier (IOPS per GB) of the file' - ' volume for which space is ordered [optional]', - type=click.Choice(['0.25', '2', '4'])) + ' volume for which space is ordered [optional, and only' + ' valid for endurance storage volumes]', + type=click.Choice(['0.25', '2', '4', '10'])) @click.option('--upgrade', type=bool, help='Flag to indicate that the order is an upgrade', diff --git a/SoftLayer/fixtures/SoftLayer_Network_Storage.py b/SoftLayer/fixtures/SoftLayer_Network_Storage.py index 90c046622..de71ddfd5 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_Storage.py +++ b/SoftLayer/fixtures/SoftLayer_Network_Storage.py @@ -1,4 +1,4 @@ -DUPLICATABLE_VOLUME = { +SAAS_TEST_VOLUME = { 'accountId': 1234, 'activeTransactions': None, 'activeTransactionCount': 0, @@ -9,10 +9,12 @@ 'cancellationDate': '', }], 'cancellationDate': '', + 'categoryCode': 'storage_as_a_service', 'id': 454, 'location': {'id': 449500} }, 'capacityGb': 500, + 'hasEncryptionAtRest': 1, 'id': 102, 'iops': 1000, 'lunId': 2, @@ -21,9 +23,14 @@ 'parentVolume': {'snapshotSizeBytes': 1024}, 'provisionedIops': '1000', 'replicationPartnerCount': 0, + 'schedules': [{ + 'id': 978, + 'type': {'keyname': 'SNAPSHOT_WEEKLY'}, + }], 'serviceResource': {'datacenter': {'id': 449500, 'name': 'dal05'}}, 'serviceResourceBackendIpAddress': '10.1.2.3', 'snapshotCapacityGb': '10', + 'staasVersion': '2', 'storageTierLevel': 'READHEAVY_TIER', 'storageType': {'keyName': 'ENDURANCE_BLOCK_STORAGE'}, 'username': 'duplicatable_volume_username' @@ -31,107 +38,110 @@ getObject = { 'accountId': 1234, - 'billingItem': { - 'id': 449, - 'cancellationDate': '', - 'categoryCode': 'storage_service_enterprise', - 'activeChildren': [{ - 'categoryCode': 'storage_snapshot_space', - 'id': 123, - 'cancellationDate': '', - }], - 'location': {'id': 449500} - }, - 'capacityGb': 20, - 'createDate': '2015:50:15-04:00', - 'guestId': '', - 'hardwareId': '', - 'hostId': '', - 'id': 100, - 'nasType': 'ISCSI', - 'notes': """{'status': 'available'}""", - 'password': '', - 'serviceProviderId': 1, - 'iops': 1000, - 'storageTierLevel': 'READHEAVY_TIER', - 'snapshotCapacityGb': '10', - 'parentVolume': {'snapshotSizeBytes': 1024}, - 'osType': {'keyName': 'LINUX'}, - 'originalSnapshotName': 'test-origin-snapshot-name', - 'originalVolumeName': 'test-origin-volume-name', - 'originalVolumeSize': '20', - 'schedules': [{ - 'id': 978, - 'type': {'keyname': 'SNAPSHOT_WEEKLY'}, - }], - 'serviceResource': {'datacenter': {'id': 449500, 'name': 'dal05'}}, - 'serviceResourceBackendIpAddress': '10.1.2.3', - 'fileNetworkMountAddress': '127.0.0.1:/TEST', - 'serviceResourceName': 'Storage Type 01 Aggregate staaspar0101_pc01', - 'username': 'username', - 'storageType': {'keyName': 'ENDURANCE_STORAGE'}, - 'bytesUsed': 0, - 'activeTransactions': None, 'activeTransactionCount': 0, - 'allowedVirtualGuests': [{ - 'id': 1234, - 'hostname': 'test-server', - 'domain': 'example.com', - 'primaryBackendIpAddress': '10.0.0.1', + 'activeTransactions': None, + 'allowedHardware': [{ 'allowedHost': { - 'name': 'test-server', 'credential': {'username': 'joe', 'password': '12345'}, + 'name': 'test-server', }, - }], - 'lunId': 2, - 'allowedHardware': [{ - 'id': 1234, - 'hostname': 'test-server', 'domain': 'example.com', + 'hostname': 'test-server', + 'id': 1234, 'primaryBackendIpAddress': '10.0.0.2', + }], + 'allowedIpAddresses': [{ 'allowedHost': { - 'name': 'test-server', 'credential': {'username': 'joe', 'password': '12345'}, + 'name': 'test-server', }, + 'id': 1234, + 'ipAddress': '10.0.0.1', + 'note': 'backend ip', }], 'allowedSubnets': [{ - 'id': 1234, - 'networkIdentifier': '10.0.0.1', - 'cidr': '24', - 'note': 'backend subnet', 'allowedHost': { - 'name': 'test-server', 'credential': {'username': 'joe', 'password': '12345'}, + 'name': 'test-server', }, - }], - 'allowedIpAddresses': [{ + 'cidr': '24', 'id': 1234, - 'ipAddress': '10.0.0.1', - 'note': 'backend ip', + 'networkIdentifier': '10.0.0.1', + 'note': 'backend subnet', + }], + 'allowedVirtualGuests': [{ 'allowedHost': { - 'name': 'test-server', 'credential': {'username': 'joe', 'password': '12345'}, + 'name': 'test-server', }, + 'domain': 'example.com', + 'hostname': 'test-server', + 'id': 1234, + 'primaryBackendIpAddress': '10.0.0.1', }], - 'replicationStatus': 'Replicant Volume Provisioning has completed.', + 'billingItem': { + 'activeChildren': [{ + 'cancellationDate': '', + 'categoryCode': 'storage_snapshot_space', + 'id': 123, + }], + 'cancellationDate': '', + 'categoryCode': 'storage_service_enterprise', + 'id': 449, + 'location': {'id': 449500} + }, + 'bytesUsed': 0, + 'capacityGb': 20, + 'createDate': '2015:50:15-04:00', + 'fileNetworkMountAddress': '127.0.0.1:/TEST', + 'guestId': '', + 'hardwareId': '', + 'hasEncryptionAtRest': 0, + 'hostId': '', + 'id': 100, + 'iops': 1000, + 'lunId': 2, + 'nasType': 'ISCSI', + 'notes': """{'status': 'available'}""", + 'originalSnapshotName': 'test-origin-snapshot-name', + 'originalVolumeName': 'test-origin-volume-name', + 'originalVolumeSize': '20', + 'osType': {'keyName': 'LINUX'}, + 'parentVolume': {'snapshotSizeBytes': 1024}, + 'password': '', + 'provisionedIops': '1000', 'replicationPartnerCount': 1, 'replicationPartners': [{ + 'createDate': '2017:50:15-04:00', 'id': 1784, - 'username': 'TEST_REP_1', - 'serviceResourceBackendIpAddress': '10.3.174.79', 'nasType': 'ISCSI_REPLICANT', - 'createDate': '2017:50:15-04:00', - 'serviceResource': {'datacenter': {'name': 'wdc01'}}, 'replicationSchedule': {'type': {'keyname': 'REPLICATION_HOURLY'}}, + 'serviceResource': {'datacenter': {'name': 'wdc01'}}, + 'serviceResourceBackendIpAddress': '10.3.174.79', + 'username': 'TEST_REP_1', }, { + 'createDate': '2017:50:15-04:00', 'id': 1785, - 'username': 'TEST_REP_2', - 'serviceResourceBackendIpAddress': '10.3.177.84', 'nasType': 'ISCSI_REPLICANT', - 'createDate': '2017:50:15-04:00', - 'serviceResource': {'datacenter': {'name': 'dal01'}}, 'replicationSchedule': {'type': {'keyname': 'REPLICATION_DAILY'}}, + 'serviceResource': {'datacenter': {'name': 'dal01'}}, + 'serviceResourceBackendIpAddress': '10.3.177.84', + 'username': 'TEST_REP_2', + }], + 'replicationStatus': 'Replicant Volume Provisioning has completed.', + 'schedules': [{ + 'id': 978, + 'type': {'keyname': 'SNAPSHOT_WEEKLY'}, }], + 'serviceProviderId': 1, + 'serviceResource': {'datacenter': {'id': 449500, 'name': 'dal05'}}, + 'serviceResourceBackendIpAddress': '10.1.2.3', + 'serviceResourceName': 'Storage Type 01 Aggregate staaspar0101_pc01', + 'snapshotCapacityGb': '10', + 'staasVersion': '1', + 'storageTierLevel': 'READHEAVY_TIER', + 'storageType': {'keyName': 'ENDURANCE_STORAGE'}, + 'username': 'username', } getSnapshots = [{ diff --git a/SoftLayer/fixtures/SoftLayer_Product_Package.py b/SoftLayer/fixtures/SoftLayer_Product_Package.py index 237b64a70..c05765d22 100644 --- a/SoftLayer/fixtures/SoftLayer_Product_Package.py +++ b/SoftLayer/fixtures/SoftLayer_Product_Package.py @@ -156,134 +156,515 @@ 'sort': 99}]}] +ENTERPRISE_PACKAGE = { + 'categories': [ + {'categoryCode': 'storage_service_enterprise'} + ], + 'id': 240, + 'name': 'Endurance', + 'items': [ + { + 'capacity': '0', + 'itemCategory': {'categoryCode': 'storage_service_enterprise'}, + 'keyName': 'CODENAME_PRIME_STORAGE_SERVICE', + 'prices': [ + { + 'categories': [ + {'categoryCode': 'storage_service_enterprise'} + ], + 'id': 45058, + 'locationGroupId': '' + } + ] + }, { + 'capacity': '0', + 'itemCategory': {'categoryCode': 'storage_file'}, + 'keyName': 'FILE_STORAGE_2', + 'prices': [ + { + 'categories': [ + {'categoryCode': 'storage_file'} + ], + 'id': 45108, + 'locationGroupId': '' + } + ] + }, { + 'capacity': '0', + 'itemCategory': {'categoryCode': 'storage_block'}, + 'keyName': 'BLOCK_STORAGE_2', + 'prices': [ + { + 'categories': [ + {'categoryCode': 'storage_block'} + ], + 'id': 45098, + 'locationGroupId': '' + } + ] + }, { + 'capacity': '10', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': '10_GB_STORAGE_SPACE', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 46160, + 'locationGroupId': '' + }, { + 'capacityRestrictionMaximum': '300', + 'capacityRestrictionMinimum': '300', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 46170, + 'locationGroupId': '' + } + ] + }, { + 'capacity': '20', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': '20_GB_PERFORMANCE_STORAGE_SPACE', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 45860, + 'locationGroupId': '' + }, { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'performance_storage_replication'} + ], + 'id': 46659, + 'locationGroupId': '' + }, { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'performance_storage_space'} + ], + 'id': 45128, + 'locationGroupId': '' + } + ] + }, { + 'capacity': '1000', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': '1000_GB_PERFORMANCE_STORAGE_SPACE', + 'prices': [ + { + 'capacityRestrictionMaximum': '300', + 'capacityRestrictionMinimum': '300', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'performance_storage_replication'} + ], + 'id': 46789, + 'locationGroupId': '' + }, { + 'capacityRestrictionMaximum': '300', + 'capacityRestrictionMinimum': '300', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'performance_storage_space'} + ], + 'id': 45318, + 'locationGroupId': '' + } + ] + }, { + 'attributes': [ + {'value': '300'} + ], + 'capacity': '300', + 'itemCategory': {'categoryCode': 'storage_tier_level'}, + 'keyName': 'WRITEHEAVY_TIER', + 'prices': [ + { + 'categories': [ + {'categoryCode': 'storage_tier_level'} + ], + 'id': 45088, + 'locationGroupId': '' + } + ] + }, { + 'attributes': [ + {'value': '200'} + ], + 'capacity': '200', + 'itemCategory': {'categoryCode': 'storage_tier_level'}, + 'keyName': 'READHEAVY_TIER', + 'prices': [ + { + 'categories': [ + {'categoryCode': 'storage_tier_level'} + ], + 'id': 45078, + 'locationGroupId': '' + } + ] + } + ] +} + + +PERFORMANCE_PACKAGE = { + 'categories': [ + {'categoryCode': 'performance_storage_iscsi'}, + {'categoryCode': 'performance_storage_nfs'} + ], + 'id': 222, + 'name': 'Performance', + 'items': [ + { + 'capacity': '0', + 'itemCategory': {'categoryCode': 'performance_storage_iscsi'}, + 'keyName': 'BLOCK_STORAGE_PERFORMANCE_ISCSI', + 'prices': [ + { + 'categories': [ + {'categoryCode': 'performance_storage_iscsi'} + ], + 'id': 40672, + 'locationGroupId': '' + } + ] + }, { + 'capacity': '0', + 'itemCategory': {'categoryCode': 'performance_storage_nfs'}, + 'keyName': 'FILE_STORAGE_PERFORMANCE_NFS', + 'prices': [ + { + 'categories': [ + {'categoryCode': 'performance_storage_nfs'} + ], + 'id': 40662, + 'locationGroupId': '' + } + ] + }, { + 'capacity': '20', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': '20_GB_PERFORMANCE_STORAGE_SPACE', + 'prices': [ + { + 'categories': [ + {'categoryCode': 'performance_storage_space'} + ], + 'id': 40682, + 'locationGroupId': '' + } + ] + }, { + 'capacity': '1000', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': '1000_GB_PERFORMANCE_STORAGE_SPACE', + 'prices': [ + { + 'categories': [ + {'categoryCode': 'performance_storage_space'} + ], + 'id': 40742, + 'locationGroupId': '' + } + ] + }, { + 'capacity': '800', + 'itemCategory': {'categoryCode': 'performance_storage_iops'}, + 'keyName': '800_IOPS_4', + 'prices': [ + { + 'capacityRestrictionMaximum': '1000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 41562, + 'locationGroupId': '' + } + ] + }, { + 'capacity': '1000', + 'itemCategory': {'categoryCode': 'performance_storage_iops'}, + 'keyName': '1000_IOPS', + 'prices': [ + { + 'capacityRestrictionMaximum': '20', + 'capacityRestrictionMinimum': '20', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 40882, + 'locationGroupId': '' + } + ] + } + ] +} + + SAAS_PACKAGE = { + 'categories': [ + {'categoryCode': 'storage_as_a_service'} + ], 'id': 759, 'name': 'Storage As A Service (StaaS)', - 'categories': [{'categoryCode': 'storage_as_a_service'}], 'items': [ { 'capacity': '0', 'keyName': '', - 'prices': [{'id': 189433, - 'categories': [{ - 'categoryCode': 'storage_as_a_service'}], - 'locationGroupId': ''}] + 'prices': [ + { + 'id': 189433, + 'categories': [ + {'categoryCode': 'storage_as_a_service'} + ], + 'locationGroupId': '' + } + ] }, { 'capacity': '0', 'keyName': '', - 'prices': [{'categories': [{'categoryCode': 'storage_block'}], - 'id': 189443, - 'locationGroupId': ''}] + 'prices': [ + { + 'categories': [ + {'categoryCode': 'storage_block'} + ], + 'id': 189443, + 'locationGroupId': '' + } + ] }, { 'capacity': '0', 'keyName': '', - 'prices': [{'categories': [{'categoryCode': 'storage_file'}], - 'id': 189453, - 'locationGroupId': ''}] + 'prices': [ + { + 'categories': [ + {'categoryCode': 'storage_file'} + ], + 'id': 189453, + 'locationGroupId': '' + } + ] }, { 'capacity': '0', 'capacityMaximum': '999', 'capacityMinimum': '500', 'itemCategory': {'categoryCode': 'performance_storage_space'}, 'keyName': '500_999_GBS', - 'prices': [{'id': 189993, - 'categories': [{ - 'categoryCode': 'performance_storage_space'}], - 'locationGroupId': ''}] + 'prices': [ + { + 'id': 189993, + 'categories': [ + {'categoryCode': 'performance_storage_space'} + ], + 'locationGroupId': '' + } + ] }, { 'capacity': '0', 'capacityMaximum': '1999', 'capacityMinimum': '1000', 'itemCategory': {'categoryCode': 'performance_storage_space'}, 'keyName': '1000_1999_GBS', - 'prices': [{'id': 190113, - 'categories': [{ - 'categoryCode': 'performance_storage_space'}], - 'locationGroupId': ''}] + 'prices': [ + { + 'id': 190113, + 'categories': [ + {'categoryCode': 'performance_storage_space'} + ], + 'locationGroupId': '' + } + ] }, { 'capacity': '0', 'capacityMaximum': '12000', 'capacityMinimum': '1', 'keyName': 'STORAGE_SPACE_FOR_2_IOPS_PER_GB', - 'prices': [{'id': 193433, - 'categories': [{ - 'categoryCode': 'performance_storage_space'}], - 'locationGroupId': ''}] + 'prices': [ + { + 'id': 193433, + 'categories': [ + {'categoryCode': 'performance_storage_space'} + ], + 'locationGroupId': '' + } + ] }, { 'capacity': '0', 'capacityMaximum': '12000', 'capacityMinimum': '1', 'keyName': 'STORAGE_SPACE_FOR_4_IOPS_PER_GB', - 'prices': [{'id': 194763, - 'categories': [{ - 'categoryCode': 'performance_storage_space'}], - 'locationGroupId': ''}] + 'prices': [ + { + 'id': 194763, + 'categories': [ + {'categoryCode': 'performance_storage_space'} + ], + 'locationGroupId': '' + } + ] }, { 'capacity': '0', 'capacityMaximum': '10000', 'capacityMinimum': '100', 'keyName': '', 'itemCategory': {'categoryCode': 'performance_storage_iops'}, - 'prices': [{'capacityRestrictionMaximum': '999', - 'capacityRestrictionMinimum': '500', - 'capacityRestrictionType': 'STORAGE_SPACE', - 'categories': [{ - 'categoryCode': 'performance_storage_iops'}], - 'id': 190053, - 'locationGroupId': ''}] + 'prices': [ + { + 'capacityRestrictionMaximum': '999', + 'capacityRestrictionMinimum': '500', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 190053, + 'locationGroupId': '' + } + ] }, { 'capacity': '0', 'capacityMaximum': '20000', 'capacityMinimum': '100', 'keyName': '', 'itemCategory': {'categoryCode': 'performance_storage_iops'}, - 'prices': [{'capacityRestrictionMaximum': '1999', - 'capacityRestrictionMinimum': '1000', - 'capacityRestrictionType': 'STORAGE_SPACE', - 'categories': [{ - 'categoryCode': 'performance_storage_iops'}], - 'id': 190173, - 'locationGroupId': ''}] + 'prices': [ + { + 'capacityRestrictionMaximum': '1999', + 'capacityRestrictionMinimum': '1000', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 190173, + 'locationGroupId': '' + } + ] }, { 'capacity': '200', 'itemCategory': {'categoryCode': 'storage_tier_level'}, 'keyName': '', - 'prices': [{'id': 193373, - 'categories': [{ - 'categoryCode': 'storage_tier_level'}], - 'locationGroupId': ''}] + 'prices': [ + { + 'id': 193373, + 'categories': [ + {'categoryCode': 'storage_tier_level'} + ], + 'locationGroupId': '' + } + ] }, { 'capacity': '300', 'itemCategory': {'categoryCode': 'storage_tier_level'}, 'keyName': '', - 'prices': [{'id': 194703, - 'categories': [{ - 'categoryCode': 'storage_tier_level'}], - 'locationGroupId': ''}] + 'prices': [ + { + 'id': 194703, + 'categories': [ + {'categoryCode': 'storage_tier_level'} + ], + 'locationGroupId': '' + } + ] }, { 'capacity': '10', 'keyName': '', - 'prices': [{'capacityRestrictionMaximum': '48000', - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionType': 'IOPS', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space'}], - 'id': 191193, - 'locationGroupId': ''}, - {'capacityRestrictionMaximum': '200', - 'capacityRestrictionMinimum': '200', - 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space'}], - 'id': 193613, - 'locationGroupId': ''}, - {'capacityRestrictionMaximum': '300', - 'capacityRestrictionMinimum': '300', - 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space'}], - 'id': 194943, - 'locationGroupId': ''}] + 'prices': [ + { + 'capacityRestrictionMaximum': '48000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'IOPS', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 191193, + 'locationGroupId': '' + }, { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 193613, + 'locationGroupId': '' + }, { + 'capacityRestrictionMaximum': '300', + 'capacityRestrictionMinimum': '300', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 194943, + 'locationGroupId': ''}] + }, { + 'capacity': '20', + 'keyName': '', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 193853, + 'locationGroupId': '' + } + ] + }, { + 'capacity': '0', + 'itemCategory': { + 'categoryCode': 'performance_storage_replication' + }, + 'keyName': 'REPLICATION_FOR_IOPSBASED_PERFORMANCE', + 'prices': [ + { + 'capacityRestrictionMaximum': '48000', + 'capacityRestrictionMinimum': '1', + 'capacityRestrictionType': 'IOPS', + 'categories': [ + {'categoryCode': 'performance_storage_replication'} + ], + 'id': 192033, + 'locationGroupId': '' + } + ] + }, { + 'capacity': '0', + 'itemCategory': { + 'categoryCode': 'performance_storage_replication' + }, + 'keyName': 'REPLICATION_FOR_TIERBASED_PERFORMANCE', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'performance_storage_replication'} + ], + 'id': 194693, + 'locationGroupId': '' + } + ] } ] } diff --git a/SoftLayer/managers/block.py b/SoftLayer/managers/block.py index 6b2dc9d33..ecf48b33d 100644 --- a/SoftLayer/managers/block.py +++ b/SoftLayer/managers/block.py @@ -56,7 +56,7 @@ def list_block_volumes(self, datacenter=None, username=None, utils.query_filter('*BLOCK_STORAGE*')) if storage_type: _filter['iscsiNetworkStorage']['storageType']['keyName'] = ( - utils.query_filter('%s_BLOCK_STORAGE' % storage_type.upper())) + utils.query_filter('%s_BLOCK_STORAGE*' % storage_type.upper())) if datacenter: _filter['iscsiNetworkStorage']['serviceResource']['datacenter'][ @@ -233,9 +233,10 @@ def order_replicant_volume(self, volume_id, snapshot_schedule, :return: Returns a SoftLayer_Container_Product_Order_Receipt """ - block_mask = 'billingItem[activeChildren],storageTierLevel,'\ - 'osType,snapshotCapacityGb,schedules,'\ - 'hourlySchedule,dailySchedule,weeklySchedule' + block_mask = 'billingItem[activeChildren],storageTierLevel,osType,'\ + 'staasVersion,hasEncryptionAtRest,snapshotCapacityGb,'\ + 'schedules,hourlySchedule,dailySchedule,weeklySchedule,'\ + 'storageType[keyName],provisionedIops' block_volume = self.get_block_volume_details(volume_id, mask=block_mask) @@ -249,8 +250,7 @@ def order_replicant_volume(self, volume_id, snapshot_schedule, "automatically; must specify manually") order = storage_utils.prepare_replicant_order_object( - self, volume_id, snapshot_schedule, location, tier, - block_volume, 'block' + self, snapshot_schedule, location, tier, block_volume, 'block' ) order['osFormatType'] = {'keyName': os_type} @@ -274,7 +274,8 @@ def order_duplicate_volume(self, origin_volume_id, origin_snapshot_id=None, block_mask = 'id,billingItem[location],snapshotCapacityGb,'\ 'storageType[keyName],capacityGb,originalVolumeSize,'\ - 'provisionedIops,storageTierLevel,osType[keyName]' + 'provisionedIops,storageTierLevel,osType[keyName],'\ + 'staasVersion,hasEncryptionAtRest' origin_volume = self.get_block_volume_details(origin_volume_id, mask=block_mask) @@ -305,70 +306,26 @@ def delete_snapshot(self, snapshot_id): id=snapshot_id) def order_block_volume(self, storage_type, location, size, os_type, - iops=None, tier_level=None, snapshot_size=None): + iops=None, tier_level=None, snapshot_size=None, + service_offering='storage_as_a_service'): """Places an order for a block volume. - :param storage_type: "performance_storage_iscsi" (performance) - or "storage_service_enterprise" (endurance) + :param storage_type: 'performance' or 'endurance' :param location: Datacenter in which to order iSCSI volume :param size: Size of the desired volume, in GB :param os_type: OS Type to use for volume alignment, see help for list :param iops: Number of IOPs for a "Performance" order :param tier_level: Tier level to use for an "Endurance" order :param snapshot_size: The size of optional snapshot space, - if snapshot space should also be ordered (None if not ordered) + if snapshot space should also be ordered (None if not ordered) + :param service_offering: Requested offering package to use in the order """ + order = storage_utils.prepare_volume_order_object( + self, storage_type, location, size, iops, tier_level, + snapshot_size, service_offering, 'block' + ) - try: - location_id = storage_utils.get_location_id(self, location) - except ValueError: - raise exceptions.SoftLayerError( - "Invalid datacenter name specified. " - "Please provide the lower case short name (e.g.: dal09)") - - base_type_name = 'SoftLayer_Container_Product_Order_Network_' - package = storage_utils.get_package(self, storage_type) - if storage_type == 'performance_storage_iscsi': - complex_type = base_type_name + 'PerformanceStorage_Iscsi' - prices = [ - storage_utils.find_performance_price( - package, - 'performance_storage_iscsi' - ), - storage_utils.find_performance_space_price(package, size), - storage_utils.find_performance_iops_price(package, size, iops), - ] - elif storage_type == 'storage_service_enterprise': - complex_type = base_type_name + 'Storage_Enterprise' - prices = [ - storage_utils.find_endurance_price(package, 'storage_block'), - storage_utils.find_endurance_price( - package, - 'storage_service_enterprise' - ), - storage_utils.find_endurance_space_price( - package, - size, - tier_level - ), - storage_utils.find_endurance_tier_price(package, tier_level), - ] - if snapshot_size is not None: - prices.append(storage_utils.find_snapshot_space_price( - package, snapshot_size, tier_level)) - else: - raise exceptions.SoftLayerError( - "Block volume storage_type must be either " - "Performance or Endurance") - - order = { - 'complexType': complex_type, - 'packageId': package['id'], - 'osFormatType': {'keyName': os_type}, - 'prices': prices, - 'quantity': 1, - 'location': location_id, - } + order['osFormatType'] = {'keyName': os_type} return self.client.call('Product_Order', 'placeOrder', order) @@ -393,41 +350,16 @@ def order_snapshot_space(self, volume_id, capacity, tier, :param boolean upgrade: Flag to indicate if this order is an upgrade :return: Returns a SoftLayer_Container_Product_Order_Receipt """ - package = storage_utils.get_package(self, 'storage_service_enterprise') - block_mask = 'serviceResource.datacenter[id],'\ - 'storageTierLevel,billingItem' + block_mask = 'id,billingItem[location],storageType[keyName],'\ + 'storageTierLevel,provisionedIops,staasVersion,hasEncryptionAtRest' block_volume = self.get_block_volume_details(volume_id, mask=block_mask, **kwargs) - storage_type = block_volume['billingItem']['categoryCode'] - if storage_type != 'storage_service_enterprise': - raise exceptions.SoftLayerError( - "Block volume storage_type must be Endurance") - - if tier is None: - tier = storage_utils.find_endurance_tier_iops_per_gb(block_volume) - prices = [storage_utils.find_snapshot_space_price( - package, capacity, tier)] + order = storage_utils.prepare_snapshot_order_object( + self, block_volume, capacity, tier, upgrade) - if upgrade: - complex_type = 'SoftLayer_Container_Product_Order_'\ - 'Network_Storage_Enterprise_SnapshotSpace_Upgrade' - else: - complex_type = 'SoftLayer_Container_Product_Order_'\ - 'Network_Storage_Enterprise_SnapshotSpace' - - snapshot_space_order = { - 'complexType': complex_type, - 'packageId': package['id'], - 'prices': prices, - 'quantity': 1, - 'location': block_volume['serviceResource']['datacenter']['id'], - 'volumeId': volume_id, - } - - return self.client.call('Product_Order', 'placeOrder', - snapshot_space_order) + return self.client.call('Product_Order', 'placeOrder', order) def cancel_snapshot_space(self, volume_id, reason='No longer needed', diff --git a/SoftLayer/managers/file.py b/SoftLayer/managers/file.py index 6caf1f5f1..c3919cb9f 100644 --- a/SoftLayer/managers/file.py +++ b/SoftLayer/managers/file.py @@ -51,7 +51,7 @@ def list_file_volumes(self, datacenter=None, username=None, utils.query_filter('*FILE_STORAGE*')) if storage_type: _filter['nasNetworkStorage']['storageType']['keyName'] = ( - utils.query_filter('%s_FILE_STORAGE' % storage_type.upper())) + utils.query_filter('%s_FILE_STORAGE*' % storage_type.upper())) if datacenter: _filter['nasNetworkStorage']['serviceResource']['datacenter'][ @@ -213,14 +213,14 @@ def order_replicant_volume(self, volume_id, snapshot_schedule, """ file_mask = 'billingItem[activeChildren],storageTierLevel,'\ - 'osType,snapshotCapacityGb,schedules,'\ - 'hourlySchedule,dailySchedule,weeklySchedule' + 'staasVersion,hasEncryptionAtRest,snapshotCapacityGb,'\ + 'schedules,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, volume_id, snapshot_schedule, location, tier, - file_volume, 'file' + self, snapshot_schedule, location, tier, file_volume, 'file' ) return self.client.call('Product_Order', 'placeOrder', order) @@ -262,7 +262,8 @@ def order_duplicate_volume(self, origin_volume_id, origin_snapshot_id=None, file_mask = 'id,billingItem[location],snapshotCapacityGb,'\ 'storageType[keyName],capacityGb,originalVolumeSize,'\ - 'provisionedIops,storageTierLevel' + 'provisionedIops,storageTierLevel,'\ + 'staasVersion,hasEncryptionAtRest' origin_volume = self.get_file_volume_details(origin_volume_id, mask=file_mask) @@ -284,73 +285,24 @@ def delete_snapshot(self, snapshot_id): return self.client.call('Network_Storage', 'deleteObject', id=snapshot_id) - def order_file_volume(self, storage_type, location, size, os_type=None, - iops=None, tier_level=None, snapshot_size=None): + def order_file_volume(self, storage_type, location, size, + iops=None, tier_level=None, snapshot_size=None, + service_offering='storage_as_a_service'): """Places an order for a file volume. - :param storage_type: "performance_storage_iscsi" (performance) - or "storage_service_enterprise" (endurance) - :param location: Datacenter in which to order iSCSI volume + :param storage_type: 'performance' or 'endurance' + :param location: Name of the datacenter in which to order the volume :param size: Size of the desired volume, in GB - :param os_type: Not used for file storage orders, leave None :param iops: Number of IOPs for a "Performance" order :param tier_level: Tier level to use for an "Endurance" order :param snapshot_size: The size of optional snapshot space, - if snapshot space should also be ordered (None if not ordered) + if snapshot space should also be ordered (None if not ordered) + :param service_offering: Requested offering package to use in the order """ - if os_type: - raise exceptions.SoftLayerError( - 'OS type is not used on file storage orders') - - try: - location_id = storage_utils.get_location_id(self, location) - except ValueError: - raise exceptions.SoftLayerError( - "Invalid datacenter name specified. " - "Please provide the lower case short name (e.g.: dal09)") - - base_type_name = 'SoftLayer_Container_Product_Order_Network_' - package = storage_utils.get_package(self, storage_type) - if storage_type == 'performance_storage_nfs': - complex_type = base_type_name + 'PerformanceStorage_Nfs' - prices = [ - storage_utils.find_performance_price( - package, - 'performance_storage_nfs' - ), - storage_utils.find_performance_space_price(package, size), - storage_utils.find_performance_iops_price(package, size, iops), - ] - elif storage_type == 'storage_service_enterprise': - complex_type = base_type_name + 'Storage_Enterprise' - prices = [ - storage_utils.find_endurance_price(package, 'storage_file'), - storage_utils.find_endurance_price( - package, - 'storage_service_enterprise' - ), - storage_utils.find_endurance_space_price( - package, - size, - tier_level - ), - storage_utils.find_endurance_tier_price(package, tier_level), - ] - if snapshot_size is not None: - prices.append(storage_utils.find_snapshot_space_price( - package, snapshot_size, tier_level)) - else: - raise exceptions.SoftLayerError( - "File volume storage_type must be either " - "Performance or Endurance") - - order = { - 'complexType': complex_type, - 'packageId': package['id'], - 'prices': prices, - 'quantity': 1, - 'location': location_id, - } + order = storage_utils.prepare_volume_order_object( + self, storage_type, location, size, iops, tier_level, + snapshot_size, service_offering, 'file' + ) return self.client.call('Product_Order', 'placeOrder', order) @@ -413,42 +365,16 @@ def order_snapshot_space(self, volume_id, capacity, tier, :param boolean upgrade: Flag to indicate if this order is an upgrade :return: Returns a SoftLayer_Container_Product_Order_Receipt """ - - package = storage_utils.get_package(self, 'storage_service_enterprise') - file_mask = 'serviceResource.datacenter[id],'\ - 'storageTierLevel,billingItem' + file_mask = 'id,billingItem[location],storageType[keyName],'\ + 'storageTierLevel,provisionedIops,staasVersion,hasEncryptionAtRest' file_volume = self.get_file_volume_details(volume_id, mask=file_mask, **kwargs) - storage_type = file_volume['billingItem']['categoryCode'] - if storage_type != 'storage_service_enterprise': - raise exceptions.SoftLayerError( - "File volume storage_type must be Endurance") - - if tier is None: - tier = storage_utils.find_endurance_tier_iops_per_gb(file_volume) - prices = [storage_utils.find_snapshot_space_price( - package, capacity, tier)] - - if upgrade: - complex_type = 'SoftLayer_Container_Product_Order_'\ - 'Network_Storage_Enterprise_SnapshotSpace_Upgrade' - else: - complex_type = 'SoftLayer_Container_Product_Order_'\ - 'Network_Storage_Enterprise_SnapshotSpace' - - snapshot_space_order = { - 'complexType': complex_type, - 'packageId': package['id'], - 'prices': prices, - 'quantity': 1, - 'location': file_volume['serviceResource']['datacenter']['id'], - 'volumeId': volume_id, - } - - return self.client.call('Product_Order', 'placeOrder', - snapshot_space_order) + 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', @@ -464,13 +390,14 @@ def cancel_snapshot_space(self, volume_id, file_volume = self.get_file_volume_details( volume_id, mask='mask[id,billingItem[activeChildren]]') - children_array = file_volume['billingItem']['activeChildren'] - billing_item_id = None 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'] diff --git a/SoftLayer/managers/storage_utils.py b/SoftLayer/managers/storage_utils.py index 7cb46ab6b..8c6bbc833 100644 --- a/SoftLayer/managers/storage_utils.py +++ b/SoftLayer/managers/storage_utils.py @@ -8,6 +8,8 @@ from SoftLayer import exceptions from SoftLayer import utils +# pylint: disable=too-many-lines + ENDURANCE_TIERS = { 0.25: 100, @@ -102,35 +104,43 @@ def get_location_id(manager, location): raise ValueError('Invalid datacenter name specified.') -def find_endurance_price(package, price_category): +def find_price_by_category(package, price_category): """Find the price in the given package that has the specified category - :param package: The product package of the endurance storage type - :param price_category: The price category to search for + :param package: The AsAService, Enterprise, or Performance product package + :param price_category: The price category code to search for :return: Returns the price for the given category, or an error if not found """ for item in package['items']: for price in item['prices']: - # Only collect prices from valid location groups. if price['locationGroupId'] != '': continue if not _has_category(price['categories'], price_category): continue - return price + return {'id': price['id']} - raise ValueError("Could not find price for endurance storage") + raise ValueError("Could not find price with the category, %s" + % price_category) -def find_endurance_space_price(package, size, tier_level): - """Find the price in the given package with the specified size and tier +def find_ent_space_price(package, category, size, tier_level): + """Find the space price for the given category, size, and tier - :param package: The product package of the endurance storage type + :param package: The Enterprise (Endurance) product package + :param category: The category of space (endurance, replication, snapshot) :param size: The size for which a price is desired :param tier_level: The endurance tier for which a price is desired - :return: Returns the price for the size and tier, or an error if not found + :return: Returns the matching price, or an error if not found """ + if category == 'snapshot': + category_code = 'storage_snapshot_space' + elif category == 'replication': + category_code = 'performance_storage_replication' + else: # category == 'endurance' + category_code = 'performance_storage_space' + for item in package['items']: if int(item['capacity']) != size: continue @@ -140,26 +150,24 @@ def find_endurance_space_price(package, size, tier_level): if price['locationGroupId'] != '': continue - if not _has_category(price['categories'], - 'performance_storage_space'): - continue - level = ENDURANCE_TIERS.get(tier_level) - if level < int(price['capacityRestrictionMinimum']): + if price['capacityRestrictionType'] != 'STORAGE_TIER_LEVEL'\ + or level < int(price['capacityRestrictionMinimum'])\ + or level > int(price['capacityRestrictionMaximum']): continue - if level > int(price['capacityRestrictionMaximum']): + if not _has_category(price['categories'], category_code): continue - return price + return {'id': price['id']} - raise ValueError("Could not find price for disk space") + raise ValueError("Could not find price for %s storage space" % category) -def find_endurance_tier_price(package, tier_level): +def find_ent_endurance_tier_price(package, tier_level): """Find the price in the given package with the specified tier level - :param package: The product package of the endurance storage type + :param package: The Enterprise (Endurance) product package :param tier_level: The endurance tier for which a price is desired :return: Returns the price for the given tier, or an error if not found """ @@ -178,9 +186,9 @@ def find_endurance_tier_price(package, tier_level): if not _has_category(price['categories'], 'storage_tier_level'): continue - return price + return {'id': price['id']} - raise ValueError("Could not find price for tier") + raise ValueError("Could not find price for endurance tier level") def find_endurance_tier_iops_per_gb(volume): @@ -206,32 +214,11 @@ def find_endurance_tier_iops_per_gb(volume): return iops_per_gb -def find_performance_price(package, price_category): - """Find the price in the given package that has the specified category - - :param package: The product package of the performance storage type - :param price_category: The price category to search for - :return: Returns the price for the given category, or an error if not found - """ - for item in package['items']: - for price in item['prices']: - # Only collect prices from valid location groups. - if price['locationGroupId'] != '': - continue - - if not _has_category(price['categories'], price_category): - continue - - return price - - raise ValueError("Could not find price for performance storage") - - -def find_performance_space_price(package, size): +def find_perf_space_price(package, size): """Find the price in the given package with the specified size - :param package: The product package of the performance storage type - :param size: The size for which a price is desired + :param package: The Performance product package + :param size: The storage space size for which a price is desired :return: Returns the price for the given size, or an error if not found """ for item in package['items']: @@ -247,16 +234,16 @@ def find_performance_space_price(package, size): 'performance_storage_space'): continue - return price + return {'id': price['id']} - raise ValueError("Could not find disk space price for the given volume") + raise ValueError("Could not find performance space price for this volume") -def find_performance_iops_price(package, size, iops): +def find_perf_iops_price(package, size, iops): """Find the price in the given package with the specified size and iops - :param package: The product package of the performance storage type - :param size: The size for which a price is desired + :param package: The Performance product package + :param size: The size of storage space for which an IOPS price is desired :param iops: The number of IOPS for which a price is desired :return: Returns the price for the size and IOPS, or an error if not found """ @@ -273,102 +260,14 @@ def find_performance_iops_price(package, size, iops): 'performance_storage_iops'): continue - if size < int(price['capacityRestrictionMinimum']): - continue - - if size > int(price['capacityRestrictionMaximum']): - continue - - return price - - raise ValueError("Could not find price for iops for the given volume") - - -def find_replication_price(package, capacity, tier_level): - """Find the price in the given package for the desired replicant volume - - :param package: The product package of the endurance storage type - :param capacity: The capacity of the primary storage volume - :param tier_level: The tier of the primary storage volume - :return: Returns the price for the given size, or an error if not found - """ - for item in package['items']: - if int(item['capacity']) != capacity: - continue - - for price in item['prices']: - # Only collect prices from valid location groups. - if price['locationGroupId'] != '': - continue - - if not _has_category(price['categories'], - 'performance_storage_replication'): - continue - - level = ENDURANCE_TIERS.get(tier_level) - if level < int(price['capacityRestrictionMinimum']): - continue - - if level > int(price['capacityRestrictionMaximum']): - continue - - return price - - raise ValueError("Could not find price for replicant volume") - - -def find_snapshot_space_price(package, size, tier_level): - """Find the price in the given package for the desired snapshot space size - - :param package: The product package of the endurance storage type - :param size: The snapshot space size for which a price is desired - :param tier_level: The tier of the volume for which space is being ordered - :return: Returns the price for the given size, or an error if not found - """ - for item in package['items']: - if int(item['capacity']) != size: - continue - - for price in item['prices']: - # Only collect prices from valid location groups. - if price['locationGroupId'] != '': - continue - - if not _has_category(price['categories'], - 'storage_snapshot_space'): - continue - - level = ENDURANCE_TIERS.get(tier_level) - if level < int(price['capacityRestrictionMinimum']): - continue - - if level > int(price['capacityRestrictionMaximum']): - continue - - return price - - raise ValueError("Could not find price for snapshot space") - - -def find_saas_price_by_category(package, price_category): - """Find a price in the SaaS package with the specified category - - :param package: The Storage As A Service product package - :param price_category: The price category to search for - :return: Returns a price for the given category, or an error if not found - """ - for item in package['items']: - for price in item['prices']: - if price['locationGroupId'] != '': - continue - - if not _has_category(price['categories'], price_category): + if price['capacityRestrictionType'] != 'STORAGE_SPACE'\ + or size < int(price['capacityRestrictionMinimum'])\ + or size > int(price['capacityRestrictionMaximum']): continue return {'id': price['id']} - raise ValueError("Could not find price with the category, %s" - % price_category) + raise ValueError("Could not find price for iops for the given volume") def find_saas_endurance_space_price(package, size, tier_level): @@ -520,17 +419,17 @@ def find_saas_perform_iops_price(package, size, iops): raise ValueError("Could not find price for iops for the given volume") -def find_saas_snapshot_space_price(package, size, tier_level=None, iops=None): +def find_saas_snapshot_space_price(package, size, tier=None, iops=None): """Find the price in the SaaS package for the desired snapshot space size :param package: The product package of the endurance storage type :param size: The snapshot space size for which a price is desired - :param tier_level: The tier of the volume for which space is being ordered + :param tier: The tier of the volume for which space is being ordered :param iops: The IOPS of the volume for which space is being ordered :return: Returns the price for the given size, or an error if not found """ - if tier_level is not None: - target_value = ENDURANCE_TIERS.get(tier_level) + if tier is not None: + target_value = ENDURANCE_TIERS.get(tier) target_restriction_type = 'STORAGE_TIER_LEVEL' else: target_value = iops @@ -559,6 +458,46 @@ def find_saas_snapshot_space_price(package, size, tier_level=None, iops=None): raise ValueError("Could not find price for snapshot space") +def find_saas_replication_price(package, tier=None, iops=None): + """Find the price in the given package for the desired replicant volume + + :param package: The product package of the endurance storage type + :param tier: The tier of the primary storage volume + :param iops: The IOPS of the primary storage volume + :return: Returns the replication price, or an error if not found + """ + if tier is not None: + target_value = ENDURANCE_TIERS.get(tier) + target_item_keyname = 'REPLICATION_FOR_TIERBASED_PERFORMANCE' + target_restriction_type = 'STORAGE_TIER_LEVEL' + else: + target_value = iops + target_item_keyname = 'REPLICATION_FOR_IOPSBASED_PERFORMANCE' + target_restriction_type = 'IOPS' + + for item in package['items']: + if item['keyName'] != target_item_keyname: + continue + + for price in item['prices']: + # Only collect prices from valid location groups. + if price['locationGroupId'] != '': + continue + + if target_restriction_type != price['capacityRestrictionType']\ + or target_value < int(price['capacityRestrictionMinimum'])\ + or target_value > int(price['capacityRestrictionMaximum']): + continue + + if not _has_category(price['categories'], + 'performance_storage_replication'): + continue + + return {'id': price['id']} + + raise ValueError("Could not find price for replicant volume") + + def find_snapshot_schedule_id(volume, snapshot_schedule_keyname): """Find the snapshot schedule ID for the given volume and keyname @@ -575,12 +514,225 @@ def find_snapshot_schedule_id(volume, snapshot_schedule_keyname): "the given storage volume") -def prepare_replicant_order_object(manager, volume_id, snapshot_schedule, - location, tier, volume, volume_type): +def prepare_snapshot_order_object(manager, volume, capacity, tier, upgrade): + """Prepare the snapshot space order object for the placeOrder() method + + :param manager: The File or Block manager calling this function + :param integer volume: The volume for which snapshot space is ordered + :param integer capacity: The snapshot space size to order, in GB + :param float tier: The tier level of the volume, in IOPS per GB (optional) + :param boolean upgrade: Flag to indicate if this order is an upgrade + :return: Returns the order object for the + Product_Order service's placeOrder() method + """ + # Ensure the storage volume has not been cancelled + if 'billingItem' not in volume: + raise exceptions.SoftLayerError( + 'This volume has been cancelled; unable to order snapshot space') + + # Determine and validate the storage volume's billing item category + billing_item_category_code = volume['billingItem']['categoryCode'] + if billing_item_category_code == 'storage_as_a_service': + order_type_is_saas = True + elif billing_item_category_code == 'storage_service_enterprise': + order_type_is_saas = False + else: + raise exceptions.SoftLayerError( + "Snapshot space cannot be ordered for a primary volume with a " + "billing item category code of '%s'" % billing_item_category_code) + + # Use the volume's billing item category code to get the product package + package = get_package(manager, billing_item_category_code) + + # Find prices based on the volume's type and billing item category + if order_type_is_saas: # 'storage_as_a_service' package + volume_storage_type = volume['storageType']['keyName'] + if 'ENDURANCE' in volume_storage_type: + if tier is None: + tier = find_endurance_tier_iops_per_gb(volume) + prices = [find_saas_snapshot_space_price( + package, capacity, tier=tier)] + elif 'PERFORMANCE' in volume_storage_type: + if not _staas_version_is_v2_or_above(volume): + raise exceptions.SoftLayerError( + "Snapshot space cannot be ordered for this performance " + "volume since it does not support Encryption at Rest.") + iops = int(volume['provisionedIops']) + prices = [find_saas_snapshot_space_price( + package, capacity, iops=iops)] + else: + raise exceptions.SoftLayerError( + "Storage volume does not have a valid storage type " + "(with an appropriate keyName to indicate the " + "volume is a PERFORMANCE or an ENDURANCE volume)") + else: # 'storage_service_enterprise' package + if tier is None: + tier = find_endurance_tier_iops_per_gb(volume) + prices = [find_ent_space_price(package, 'snapshot', capacity, tier)] + + # Currently, these types are valid for snapshot space orders, whether + # the base volume's order container was Enterprise or AsAService + if upgrade: + complex_type = 'SoftLayer_Container_Product_Order_'\ + 'Network_Storage_Enterprise_SnapshotSpace_Upgrade' + else: + complex_type = 'SoftLayer_Container_Product_Order_'\ + 'Network_Storage_Enterprise_SnapshotSpace' + + # Build and return the order object + snapshot_space_order = { + 'complexType': complex_type, + 'packageId': package['id'], + 'prices': prices, + 'quantity': 1, + 'location': volume['billingItem']['location']['id'], + 'volumeId': volume['id'] + } + + return snapshot_space_order + + +def prepare_volume_order_object(manager, storage_type, location, size, + iops, tier, snapshot_size, + service_offering, volume_type): + """Prepare the order object which is submitted to the placeOrder() method + + :param manager: The File or Block manager calling this function + :param storage_type: "performance" or "endurance" + :param location: Requested datacenter location name for the ordered volume + :param size: Desired size of the volume, in GB + :param iops: Number of IOPs for a "Performance" volume order + :param tier: Tier level to use for an "Endurance" volume order + :param snapshot_size: The size of snapshot space for the volume (optional) + :param service_offering: Requested offering package to use for the order + :param volume_type: The type of the volume to order ('file' or 'block') + :return: Returns the order object for the + Product_Order service's placeOrder() method + """ + # Ensure the volume storage type is valid + if storage_type != 'performance' and storage_type != 'endurance': + raise exceptions.SoftLayerError( + "Volume storage type must be either performance or endurance") + + # Find the ID for the requested location + try: + location_id = get_location_id(manager, location) + except ValueError: + raise exceptions.SoftLayerError( + "Invalid datacenter name specified. " + "Please provide the lower case short name (e.g.: dal09)") + + # Determine the category code to use for the order (and product package) + order_type_is_saas, order_category_code = _get_order_type_and_category( + service_offering, + storage_type, + volume_type + ) + + # Get the product package for the given category code + package = get_package(manager, order_category_code) + + # Based on the storage type and product package, build up the complex type + # and array of price codes to include in the order object + base_type_name = 'SoftLayer_Container_Product_Order_Network_' + if order_type_is_saas: + complex_type = base_type_name + 'Storage_AsAService' + if storage_type == 'performance': + prices = [ + find_price_by_category(package, order_category_code), + find_price_by_category(package, 'storage_' + volume_type), + find_saas_perform_space_price(package, size), + find_saas_perform_iops_price(package, size, iops) + ] + if snapshot_size is not None: + prices.append(find_saas_snapshot_space_price( + package, snapshot_size, iops=iops)) + else: # storage_type == 'endurance' + prices = [ + find_price_by_category(package, order_category_code), + find_price_by_category(package, 'storage_' + volume_type), + find_saas_endurance_space_price(package, size, tier), + find_saas_endurance_tier_price(package, tier) + ] + if snapshot_size is not None: + prices.append(find_saas_snapshot_space_price( + package, snapshot_size, tier=tier)) + else: # offering package is enterprise or performance + if storage_type == 'performance': + if volume_type == 'block': + complex_type = base_type_name + 'PerformanceStorage_Iscsi' + else: + complex_type = base_type_name + 'PerformanceStorage_Nfs' + prices = [ + find_price_by_category(package, order_category_code), + find_perf_space_price(package, size), + find_perf_iops_price(package, size, iops), + ] + else: # storage_type == 'endurance' + complex_type = base_type_name + 'Storage_Enterprise' + prices = [ + find_price_by_category(package, order_category_code), + find_price_by_category(package, 'storage_' + volume_type), + find_ent_space_price(package, 'endurance', size, tier), + find_ent_endurance_tier_price(package, tier), + ] + if snapshot_size is not None: + prices.append(find_ent_space_price( + package, 'snapshot', snapshot_size, tier)) + + # Build and return the order object + order = { + 'complexType': complex_type, + 'packageId': package['id'], + 'prices': prices, + 'quantity': 1, + 'location': location_id, + } + + if order_type_is_saas: + order['volumeSize'] = size + if storage_type == 'performance': + order['iops'] = iops + + return order + + +def _get_order_type_and_category(service_offering, storage_type, volume_type): + if service_offering == 'storage_as_a_service': + order_type_is_saas = True + order_category_code = 'storage_as_a_service' + elif service_offering == 'enterprise': + order_type_is_saas = False + if storage_type == 'endurance': + order_category_code = 'storage_service_enterprise' + else: + raise exceptions.SoftLayerError( + "The requested offering package, '%s', is not available for " + "the '%s' storage type." % (service_offering, storage_type)) + elif service_offering == 'performance': + order_type_is_saas = False + if storage_type == 'performance': + if volume_type == 'block': + order_category_code = 'performance_storage_iscsi' + else: + order_category_code = 'performance_storage_nfs' + else: + raise exceptions.SoftLayerError( + "The requested offering package, '%s', is not available for " + "the '%s' storage type." % (service_offering, storage_type)) + else: + raise exceptions.SoftLayerError( + "The requested service offering package is not valid. " + "Please check the available options and try again.") + + return order_type_is_saas, order_category_code + + +def prepare_replicant_order_object(manager, snapshot_schedule, location, + tier, volume, volume_type): """Prepare the order object which is submitted to the placeOrder() method :param manager: The File or Block manager calling this function - :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 @@ -590,23 +742,43 @@ def prepare_replicant_order_object(manager, volume_id, snapshot_schedule, :return: Returns the order object for the Product_Order service's placeOrder() method """ + # Ensure the primary volume and snapshot space are not set for cancellation + if 'billingItem' not in volume\ + or volume['billingItem']['cancellationDate'] != '': + raise exceptions.SoftLayerError( + 'This volume is set for cancellation; ' + 'unable to order replicant volume') + for child in volume['billingItem']['activeChildren']: + if child['categoryCode'] == 'storage_snapshot_space'\ + and child['cancellationDate'] != '': + raise exceptions.SoftLayerError( + 'The snapshot space for this volume is set for ' + 'cancellation; unable to order replicant volume') + + # Find the ID for the requested location try: location_id = get_location_id(manager, location) except ValueError: raise exceptions.SoftLayerError( - "Invalid data center name specified. " + "Invalid datacenter name specified. " "Please provide the lower case short name (e.g.: dal09)") - volume_capacity = int(volume['capacityGb']) - storage_type = volume['billingItem']['categoryCode'] + # Get sizes and properties needed for the order + volume_size = int(volume['capacityGb']) - if storage_type != 'storage_service_enterprise': + billing_item_category_code = volume['billingItem']['categoryCode'] + if billing_item_category_code == 'storage_as_a_service': + order_type_is_saas = True + elif billing_item_category_code == 'storage_service_enterprise': + order_type_is_saas = False + else: raise exceptions.SoftLayerError( - "Primary volume storage_type must be Endurance") + "A replicant volume cannot be ordered for a primary volume with a " + "billing item category code of '%s'" % billing_item_category_code) if 'snapshotCapacityGb' in volume: - volume_snapshot_capacity = int(volume['snapshotCapacityGb']) + snapshot_size = int(volume['snapshotCapacityGb']) else: raise exceptions.SoftLayerError( "Snapshot capacity not found for the given primary volume") @@ -616,42 +788,79 @@ def prepare_replicant_order_object(manager, volume_id, snapshot_schedule, 'SNAPSHOT_' + snapshot_schedule ) - if volume['billingItem']['cancellationDate'] != '': - raise exceptions.SoftLayerError( - 'This volume is set for cancellation; ' - 'unable to order replicant volume') - - for child in volume['billingItem']['activeChildren']: - if child['categoryCode'] == 'storage_snapshot_space'\ - and child['cancellationDate'] != '': + # Use the volume's billing item category code to get the product package + package = get_package(manager, billing_item_category_code) + + # Find prices based on the primary volume's type and billing item category + if order_type_is_saas: # 'storage_as_a_service' package + complex_type = 'SoftLayer_Container_Product_Order_'\ + 'Network_Storage_AsAService' + volume_storage_type = volume['storageType']['keyName'] + if 'ENDURANCE' in volume_storage_type: + volume_is_performance = False + if tier is None: + tier = find_endurance_tier_iops_per_gb(volume) + prices = [ + find_price_by_category(package, billing_item_category_code), + find_price_by_category(package, 'storage_' + volume_type), + find_saas_endurance_space_price(package, volume_size, tier), + find_saas_endurance_tier_price(package, tier), + find_saas_snapshot_space_price( + package, snapshot_size, tier=tier), + find_saas_replication_price(package, tier=tier) + ] + elif 'PERFORMANCE' in volume_storage_type: + if not _staas_version_is_v2_or_above(volume): + raise exceptions.SoftLayerError( + "A replica volume cannot be ordered for this performance " + "volume since it does not support Encryption at Rest.") + volume_is_performance = True + iops = int(volume['provisionedIops']) + prices = [ + find_price_by_category(package, billing_item_category_code), + find_price_by_category(package, 'storage_' + volume_type), + find_saas_perform_space_price(package, volume_size), + find_saas_perform_iops_price(package, volume_size, iops), + find_saas_snapshot_space_price( + package, snapshot_size, iops=iops), + find_saas_replication_price(package, iops=iops) + ] + else: raise exceptions.SoftLayerError( - 'The snapshot space for this volume is set for ' - 'cancellation; unable to order replicant volume') - - if tier is None: - tier = find_endurance_tier_iops_per_gb(volume) - - package = get_package(manager, storage_type) - prices = [ - find_endurance_price(package, 'storage_service_enterprise'), - find_endurance_price(package, 'storage_' + volume_type), - find_endurance_tier_price(package, tier), - find_endurance_space_price(package, volume_capacity, tier), - find_snapshot_space_price(package, volume_snapshot_capacity, tier), - find_replication_price(package, volume_capacity, tier), - ] + "Storage volume does not have a valid storage type " + "(with an appropriate keyName to indicate the " + "volume is a PERFORMANCE or an ENDURANCE volume)") + else: # 'storage_service_enterprise' package + complex_type = 'SoftLayer_Container_Product_Order_'\ + 'Network_Storage_Enterprise' + volume_is_performance = False + if tier is None: + tier = find_endurance_tier_iops_per_gb(volume) + prices = [ + find_price_by_category(package, billing_item_category_code), + find_price_by_category(package, 'storage_' + volume_type), + find_ent_space_price(package, 'endurance', volume_size, tier), + find_ent_endurance_tier_price(package, tier), + find_ent_space_price(package, 'snapshot', snapshot_size, tier), + find_ent_space_price(package, 'replication', volume_size, tier) + ] + # Build and return the order object replicant_order = { - 'complexType': 'SoftLayer_Container_Product_Order_' - 'Network_Storage_Enterprise', + 'complexType': complex_type, 'packageId': package['id'], 'prices': prices, 'quantity': 1, 'location': location_id, - 'originVolumeId': int(volume_id), + 'originVolumeId': volume['id'], 'originVolumeScheduleId': snapshot_schedule_id, } + if order_type_is_saas: + replicant_order['volumeSize'] = volume_size + if volume_is_performance: + replicant_order['iops'] = iops + return replicant_order @@ -693,6 +902,13 @@ def prepare_duplicate_order_object(manager, origin_volume, iops, tier, raise exceptions.SoftLayerError( "Cannot find origin volume's location") + # Ensure the origin volume is STaaS v2 or higher + # and supports Encryption at Rest + if not _staas_version_is_v2_or_above(origin_volume): + raise exceptions.SoftLayerError( + "This volume cannot be duplicated since it " + "does not support Encryption at Rest.") + # If no specific snapshot space was requested for the duplicate, # use the origin snapshot space size if duplicate_snapshot_size is None: @@ -718,8 +934,8 @@ def prepare_duplicate_order_object(manager, origin_volume, iops, tier, origin_volume, iops, duplicate_size) # Set up the price array for the order prices = [ - find_saas_price_by_category(package, 'storage_as_a_service'), - find_saas_price_by_category(package, 'storage_' + volume_type), + find_price_by_category(package, 'storage_as_a_service'), + find_price_by_category(package, 'storage_' + volume_type), find_saas_perform_space_price(package, duplicate_size), find_saas_perform_iops_price(package, duplicate_size, iops), ] @@ -736,21 +952,21 @@ def prepare_duplicate_order_object(manager, origin_volume, iops, tier, tier = _validate_dupl_endurance_tier(origin_volume, tier) # Set up the price array for the order prices = [ - find_saas_price_by_category(package, 'storage_as_a_service'), - find_saas_price_by_category(package, 'storage_' + volume_type), + find_price_by_category(package, 'storage_as_a_service'), + find_price_by_category(package, 'storage_' + volume_type), find_saas_endurance_space_price(package, duplicate_size, tier), find_saas_endurance_tier_price(package, tier), ] # Add the price code for snapshot space as well, unless 0 GB was given if duplicate_snapshot_size > 0: prices.append(find_saas_snapshot_space_price( - package, duplicate_snapshot_size, tier_level=tier)) + package, duplicate_snapshot_size, tier=tier)) else: raise exceptions.SoftLayerError( "Origin volume does not have a valid storage type " "(with an appropriate keyName to indicate the " - "volume is a PERFORMANCE or ENDURANCE volume)") + "volume is a PERFORMANCE or an ENDURANCE volume)") duplicate_order = { 'complexType': 'SoftLayer_Container_Product_Order_' @@ -867,3 +1083,7 @@ def _has_category(categories, category_code): in categories if category['categoryCode'] == category_code ) + + +def _staas_version_is_v2_or_above(volume): + return int(volume['staasVersion']) > 1 and volume['hasEncryptionAtRest'] diff --git a/tests/CLI/modules/block_tests.py b/tests/CLI/modules/block_tests.py index 87641216e..e8b81da5f 100644 --- a/tests/CLI/modules/block_tests.py +++ b/tests/CLI/modules/block_tests.py @@ -129,14 +129,6 @@ def test_volume_order_performance_iops_not_given(self): self.assertEqual(2, result.exit_code) - def test_volume_order_performance_iops_out_of_range(self): - result = self.run_command(['block', 'volume-order', - '--storage-type=performance', '--size=20', - '--iops=80000', '--os-type=linux', - '--location=dal05']) - - self.assertEqual(2, result.exit_code) - def test_volume_order_performance_iops_not_multiple_of_100(self): result = self.run_command(['block', 'volume-order', '--storage-type=performance', '--size=20', @@ -149,7 +141,8 @@ def test_volume_order_performance_snapshot_error(self): result = self.run_command(['block', 'volume-order', '--storage-type=performance', '--size=20', '--iops=100', '--os-type=linux', - '--location=dal05', '--snapshot-size=10']) + '--location=dal05', '--snapshot-size=10', + '--service-offering=performance']) self.assertEqual(2, result.exit_code) @@ -162,20 +155,22 @@ def test_volume_order_performance(self, order_mock): {'description': 'Performance Storage'}, {'description': 'Block Storage'}, {'description': '0.25 IOPS per GB'}, - {'description': '20 GB Storage Space'}] + {'description': '20 GB Storage Space'}, + {'description': '10 GB Storage Space (Snapshot Space)'}] } } result = self.run_command(['block', 'volume-order', '--storage-type=performance', '--size=20', '--iops=100', '--os-type=linux', - '--location=dal05']) + '--location=dal05', '--snapshot-size=10']) self.assert_no_fail(result) self.assertEqual(result.output, 'Order #478 placed successfully!\n' ' > Performance Storage\n > Block Storage\n' - ' > 0.25 IOPS per GB\n > 20 GB Storage Space\n') + ' > 0.25 IOPS per GB\n > 20 GB Storage Space\n' + ' > 10 GB Storage Space (Snapshot Space)\n') def test_volume_order_endurance_tier_not_given(self): result = self.run_command(['block', 'volume-order', @@ -307,6 +302,28 @@ def test_snapshot_restore(self): self.assertEqual(result.output, 'Block volume 12345678 is being' ' restored using snapshot 87654321\n') + @mock.patch('SoftLayer.BlockStorageManager.order_snapshot_space') + def test_snapshot_order_order_not_placed(self, order_mock): + order_mock.return_value = {} + + result = self.run_command(['block', 'snapshot-order', '1234', + '--capacity=10', '--tier=0.25']) + + self.assert_no_fail(result) + self.assertEqual(result.output, + 'Order could not be placed! Please verify ' + 'your options and try again.\n') + + @mock.patch('SoftLayer.BlockStorageManager.order_snapshot_space') + def test_snapshot_order_performance_manager_error(self, order_mock): + order_mock.side_effect = ValueError('failure!') + + result = self.run_command(['block', 'snapshot-order', '1234', + '--capacity=10', '--tier=0.25']) + + self.assertEqual(2, result.exit_code) + self.assertEqual('Argument Error: failure!', result.exception.message) + @mock.patch('SoftLayer.BlockStorageManager.order_snapshot_space') def test_snapshot_order(self, order_mock): order_mock.return_value = { diff --git a/tests/CLI/modules/file_tests.py b/tests/CLI/modules/file_tests.py index 5d53210f9..e68ad658b 100644 --- a/tests/CLI/modules/file_tests.py +++ b/tests/CLI/modules/file_tests.py @@ -161,13 +161,6 @@ def test_volume_order_performance_iops_not_given(self): self.assertEqual(2, result.exit_code) - def test_volume_order_performance_iops_out_of_range(self): - result = self.run_command(['file', 'volume-order', - '--storage-type=performance', '--size=20', - '--iops=80000', '--location=dal05']) - - self.assertEqual(2, result.exit_code) - def test_volume_order_performance_iops_not_multiple_of_100(self): result = self.run_command(['file', 'volume-order', '--storage-type=performance', '--size=20', @@ -179,7 +172,8 @@ def test_volume_order_performance_snapshot_error(self): result = self.run_command(['file', 'volume-order', '--storage-type=performance', '--size=20', '--iops=100', '--location=dal05', - '--snapshot-size=10']) + '--snapshot-size=10', + '--service-offering=performance']) self.assertEqual(2, result.exit_code) @@ -192,19 +186,22 @@ def test_volume_order_performance(self, order_mock): {'description': 'Performance Storage'}, {'description': 'File Storage'}, {'description': '0.25 IOPS per GB'}, - {'description': '20 GB Storage Space'}] + {'description': '20 GB Storage Space'}, + {'description': '10 GB Storage Space (Snapshot Space)'}] } } result = self.run_command(['file', 'volume-order', '--storage-type=performance', '--size=20', - '--iops=100', '--location=dal05']) + '--iops=100', '--location=dal05', + '--snapshot-size=10']) self.assert_no_fail(result) self.assertEqual(result.output, 'Order #478 placed successfully!\n' ' > Performance Storage\n > File Storage\n' - ' > 0.25 IOPS per GB\n > 20 GB Storage Space\n') + ' > 0.25 IOPS per GB\n > 20 GB Storage Space\n' + ' > 10 GB Storage Space (Snapshot Space)\n') def test_volume_order_endurance_tier_not_given(self): result = self.run_command(['file', 'volume-order', @@ -316,6 +313,28 @@ def test_delete_snapshot(self): self.assert_no_fail(result) + @mock.patch('SoftLayer.FileStorageManager.order_snapshot_space') + def test_snapshot_order_order_not_placed(self, order_mock): + order_mock.return_value = {} + + result = self.run_command(['file', 'snapshot-order', '1234', + '--capacity=10', '--tier=0.25']) + + self.assert_no_fail(result) + self.assertEqual(result.output, + 'Order could not be placed! Please verify ' + 'your options and try again.\n') + + @mock.patch('SoftLayer.FileStorageManager.order_snapshot_space') + def test_snapshot_order_performance_manager_error(self, order_mock): + order_mock.side_effect = ValueError('failure!') + + result = self.run_command(['file', 'snapshot-order', '1234', + '--capacity=10', '--tier=0.25']) + + self.assertEqual(2, result.exit_code) + self.assertEqual('Argument Error: failure!', result.exception.message) + @mock.patch('SoftLayer.FileStorageManager.order_snapshot_space') def test_snapshot_order(self, order_mock): order_mock.return_value = { diff --git a/tests/managers/block_tests.py b/tests/managers/block_tests.py index 91909f52c..aeaea906f 100644 --- a/tests/managers/block_tests.py +++ b/tests/managers/block_tests.py @@ -67,10 +67,75 @@ def test_list_block_volumes(self): self.assertEqual(fixtures.SoftLayer_Account.getIscsiNetworkStorage, result) - self.assert_called_with('SoftLayer_Account', 'getIscsiNetworkStorage') + expected_filter = { + 'iscsiNetworkStorage': { + 'storageType': { + 'keyName': {'operation': '*= BLOCK_STORAGE'} + }, + 'serviceResource': { + 'type': { + 'type': {'operation': '!~ ISCSI'} + } + } + } + } - result = self.block.list_block_volumes(datacenter="dal09", storage_type="Endurance", username="username") - self.assert_called_with('SoftLayer_Account', 'getIscsiNetworkStorage') + expected_mask = 'id,'\ + 'username,'\ + 'lunId,'\ + 'capacityGb,'\ + 'bytesUsed,'\ + 'serviceResource.datacenter[name],'\ + 'serviceResourceBackendIpAddress,'\ + 'activeTransactionCount' + + self.assert_called_with( + 'SoftLayer_Account', + 'getIscsiNetworkStorage', + filter=expected_filter, + mask='mask[%s]' % expected_mask + ) + + def test_list_block_volumes_with_additional_filters(self): + result = self.block.list_block_volumes(datacenter="dal09", + storage_type="Endurance", + username="username") + + self.assertEqual(fixtures.SoftLayer_Account.getIscsiNetworkStorage, + result) + + expected_filter = { + 'iscsiNetworkStorage': { + 'storageType': { + 'keyName': {'operation': '^= ENDURANCE_BLOCK_STORAGE'} + }, + 'username': {'operation': u'_= username'}, + 'serviceResource': { + 'datacenter': { + 'name': {'operation': u'_= dal09'} + }, + 'type': { + 'type': {'operation': '!~ ISCSI'} + } + } + } + } + + expected_mask = 'id,'\ + 'username,'\ + 'lunId,'\ + 'capacityGb,'\ + 'bytesUsed,'\ + 'serviceResource.datacenter[name],'\ + 'serviceResourceBackendIpAddress,'\ + 'activeTransactionCount' + + self.assert_called_with( + 'SoftLayer_Account', + 'getIscsiNetworkStorage', + filter=expected_filter, + mask='mask[%s]' % expected_mask + ) def test_get_block_volume_access_list(self): result = self.block.get_block_volume_access_list(100) @@ -104,53 +169,6 @@ def test_delete_snapshot(self): 'deleteObject', identifier=100) - def test_order_block_volume_invalid_location(self): - mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') - mock.return_value = [] - - exception = self.assertRaises( - exceptions.SoftLayerError, - self.block.order_block_volume, - "performance_storage_iscsi", - "dal05", - 100, - "LINUX", - iops=100, - ) - - self.assertEqual(str(exception), "Invalid datacenter name " - "specified. Please provide the " - "lower case short name " - "(e.g.: dal09)") - - def test_order_block_volume_no_package(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [] - - self.assertRaises( - ValueError, - self.block.order_block_volume, - "performance_storage_iscsi", - "dal05", - 100, - "LINUX", - iops=100, - ) - - def test_order_block_volume_too_many_packages(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{}, {}] - - self.assertRaises( - ValueError, - self.block.order_block_volume, - "performance_storage_iscsi", - "dal05", - 100, - "LINUX", - iops=100, - ) - def test_cancel_snapshot_immediately(self): self.block.cancel_snapshot_space(1234, immediate=True) @@ -161,7 +179,7 @@ def test_cancel_snapshot_immediately(self): identifier=123, ) - def test_cancel_snapshot_exception_1(self): + def test_cancel_snapshot_exception_no_billing_item_active_children(self): mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = { 'capacityGb': 20, @@ -175,14 +193,18 @@ def test_cancel_snapshot_exception_1(self): 'cancellationDate': '2016-09-04T22:00:00-07:00' } } - self.assertRaises( + exception = self.assertRaises( exceptions.SoftLayerError, self.block.cancel_snapshot_space, 12345, immediate=True ) + self.assertEqual( + 'No snapshot space found to cancel', + str(exception) + ) - def test_cancel_snapshot_exception_2(self): + def test_cancel_snapshot_exception_snapshot_billing_item_not_found(self): mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = { 'capacityGb': 20, @@ -195,12 +217,16 @@ def test_cancel_snapshot_exception_2(self): 'activeChildren': [] } } - self.assertRaises( + exception = self.assertRaises( exceptions.SoftLayerError, self.block.cancel_snapshot_space, 12345, immediate=True ) + self.assertEqual( + 'No snapshot space found to cancel', + str(exception) + ) def test_replicant_failover(self): result = self.block.failover_to_replicant(1234, 5678, immediate=True) @@ -244,247 +270,94 @@ def test_get_replication_locations(self): identifier=1234, ) - def test_order_block_volume_invalid_storage_type(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{}] - - self.assertRaises( - exceptions.SoftLayerError, - self.block.order_block_volume, - "something_completely_different", - "dal05", - 100, - "LINUX", - iops=100, - ) - def test_order_block_volume_performance(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 449494, 'name': 'dal09'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{ - 'id': 1, - 'name': 'Performance', - 'items': [{ - 'capacity': '1', - 'prices': [{ - 'id': 1, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_iscsi', - }], - }], - }, { - 'capacity': '100', - 'prices': [{ - 'id': 2, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_space', - }], - }], - }, { - 'capacity': '100', - 'prices': [{ - 'id': 3, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_iops', - }], - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionMaximum': '100', - }], - }], - }] + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type_keyname = mock_volume['storageType']['keyName'] + mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' + mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = mock_volume result = self.block.order_block_volume( - "performance_storage_iscsi", - "dal05", - 100, - "LINUX", - iops=100, - ) + 'performance', + 'dal09', + 1000, + 'LINUX', + iops=2000, + service_offering='storage_as_a_service' + ) - self.assertEqual( - result, - { - 'orderDate': '2013-08-01 15:23:45', - 'orderId': 1234, - 'prices': [{ - 'hourlyRecurringFee': '2', - 'id': 1, - 'item': {'description': 'this is a thing', 'id': 1}, - 'laborFee': '2', - 'oneTimeFee': '2', - 'oneTimeFeeTax': '.1', - 'quantity': 1, - 'recurringFee': '2', - 'recurringFeeTax': '.1', - 'setupFee': '1'}], - }, - ) + self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) - def test_order_block_volume_endurance(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{ - 'id': 1, - 'name': 'Performance', - 'items': [{ - 'capacity': '1', - 'prices': [{ - 'id': 1, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_block', - }], - }], - }, { - 'capacity': '1', - 'prices': [{ - 'id': 2, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_service_enterprise', - }], - }], - }, { - 'capacity': '100', - 'prices': [{ - 'id': 3, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_space', - }], - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionMaximum': '100', - }], - }, { - 'capacity': '100', - 'attributes': [{ - 'value': '100', - }], - 'prices': [{ - 'id': 4, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_tier_level', - }], - }], - }], - }] + self.assert_called_with( + 'SoftLayer_Product_Order', + 'placeOrder', + args=({ + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189443}, + {'id': 190113}, + {'id': 190173} + ], + 'volumeSize': 1000, + 'quantity': 1, + 'location': 449494, + 'iops': 2000, + 'osFormatType': {'keyName': 'LINUX'} + },) + ) - result = self.block.order_block_volume( - "storage_service_enterprise", - "dal05", - 100, - "LINUX", - tier_level=0.25, - ) + mock_volume['storageType']['keyName'] = prev_storage_type_keyname - self.assertEqual( - result, - { - 'orderDate': '2013-08-01 15:23:45', - 'orderId': 1234, - 'prices': [{ - 'hourlyRecurringFee': '2', - 'id': 1, - 'item': {'description': 'this is a thing', 'id': 1}, - 'laborFee': '2', - 'oneTimeFee': '2', - 'oneTimeFeeTax': '.1', - 'quantity': 1, - 'recurringFee': '2', - 'recurringFeeTax': '.1', - 'setupFee': '1'}], - }, - ) + def test_order_block_volume_endurance(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 449494, 'name': 'dal09'}] - def test_order_block_volume_endurance_with_snapshot(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{ - 'id': 1, - 'name': 'Endurance', - 'items': [{ - 'capacity': '1', - 'prices': [{ - 'id': 1, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_block', - }], - }], - }, { - 'capacity': '1', - 'prices': [{ - 'id': 2, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_service_enterprise', - }], - }], - }, { - 'capacity': '100', - 'prices': [{ - 'id': 3, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_space', - }], - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionMaximum': '100', - }], - }, { - 'capacity': '100', - 'attributes': [{ - 'value': '100', - }], - 'prices': [{ - 'id': 4, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_tier_level', - }], - }], - }, { - 'capacity': '10', - 'prices': [{ - 'id': 5, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionMaximum': '100', - }], - }], - }] + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = mock_volume result = self.block.order_block_volume( - "storage_service_enterprise", - "dal05", - 100, - "LINUX", - tier_level=0.25, - snapshot_size=10, - ) + 'endurance', + 'dal09', + 1000, + 'LINUX', + tier_level=4, + service_offering='storage_as_a_service' + ) - self.assertEqual( - result, - { - 'orderDate': '2013-08-01 15:23:45', - 'orderId': 1234, - 'prices': [{ - 'hourlyRecurringFee': '2', - 'id': 1, - 'item': {'description': 'this is a thing', 'id': 1}, - 'laborFee': '2', - 'oneTimeFee': '2', - 'oneTimeFeeTax': '.1', - 'quantity': 1, - 'recurringFee': '2', - 'recurringFeeTax': '.1', - 'setupFee': '1'}], - }, - ) + self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + + self.assert_called_with( + 'SoftLayer_Product_Order', + 'placeOrder', + args=({ + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189443}, + {'id': 194763}, + {'id': 194703} + ], + 'volumeSize': 1000, + 'quantity': 1, + 'location': 449494, + 'osFormatType': {'keyName': 'LINUX'} + },) + ) def test_authorize_host_to_volume(self): result = self.block.authorize_host_to_volume( @@ -560,446 +433,180 @@ def test_disable_snapshots(self): 'disableSnapshots', identifier=12345678) - def test_order_snapshot_space_no_package(self): + def test_order_block_snapshot_space_upgrade(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [] - - self.assertRaises( - ValueError, - self.block.order_snapshot_space, - 100, - 5, - None, - False, - ) + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - def test_order_snapshot_space_too_many_packages(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{}, {}] - - self.assertRaises( - ValueError, - self.block.order_snapshot_space, - 100, - 5, - None, - False, - ) + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type_keyname = mock_volume['storageType']['keyName'] + mock_volume['storageType']['keyName'] = 'ENDURANCE_BLOCK_STORAGE' + mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = mock_volume - def test_order_snapshot_space(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{ - 'id': 240, - 'name': 'Endurance', - 'items': [{ - 'capacity': '0', - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '530', - }], - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_block', - }], - }], - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '300', - }], - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionMaximum': '100', - }], - }, { - 'capacity': '5', - 'prices': [{ - 'id': 46130, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '200', - 'capacityRestrictionMaximum': '200', - }], - }], - }] + result = self.block.order_snapshot_space(102, 20, None, True) - result = self.block.order_snapshot_space( - 100, - 5, - None, - False, - ) + self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) - self.assertEqual( - result, - { - 'orderId': 1234, - 'orderDate': '2013-08-01 15:23:45', - 'prices': [{ - 'hourlyRecurringFee': '2', - 'id': 1, - 'item': {'description': 'this is a thing', 'id': 1}, - 'laborFee': '2', - 'oneTimeFee': '2', - 'oneTimeFeeTax': '.1', - 'quantity': 1, - 'recurringFee': '2', - 'recurringFeeTax': '.1', - 'setupFee': '1'}], - }, - ) - result = self.block.order_snapshot_space(100, 5, None, True) + self.assert_called_with( + 'SoftLayer_Product_Order', + 'placeOrder', + args=({ + 'complexType': 'SoftLayer_Container_Product_Order_Network_' + 'Storage_Enterprise_SnapshotSpace_Upgrade', + 'packageId': 759, + 'prices': [ + {'id': 193853} + ], + 'quantity': 1, + 'location': 449500, + 'volumeId': 102 + },) + ) - self.assertEqual( - result, - { - 'orderId': 1234, - 'orderDate': '2013-08-01 15:23:45', - 'prices': [{ - 'hourlyRecurringFee': '2', - 'id': 1, - 'item': {'description': 'this is a thing', 'id': 1}, - 'laborFee': '2', - 'oneTimeFee': '2', - 'oneTimeFeeTax': '.1', - 'quantity': 1, - 'recurringFee': '2', - 'recurringFeeTax': '.1', - 'setupFee': '1'}], - }, - ) + mock_volume['storageType']['keyName'] = prev_storage_type_keyname - def test_order_snapshot_space_invalid_category(self): + def test_order_block_snapshot_space(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{ - 'id': 240, - 'name': 'Endurance', - 'items': [{ - 'capacity': '0', - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '530', - }], - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_block', - }], - }], - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '300', - }], - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionMaximum': '100', - }], - }, { - 'capacity': '5', - 'prices': [{ - 'id': 46130, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '200', - 'capacityRestrictionMaximum': '200', - }], - }], - }] + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - billing_item_mock = self.set_mock('SoftLayer_Network_Storage', - 'getObject') - billing_item_mock.return_value = { - 'billingItem': { - 'categoryCode': 'not_storage_service_enterprise' - } - } + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = mock_volume - exception = self.assertRaises( - exceptions.SoftLayerError, - self.block.order_snapshot_space, - 100, - 5, - None, - False - ) - self.assertEqual(str(exception), "Block volume storage_type must be " - "Endurance") + result = self.block.order_snapshot_space(102, 10, None, False) - def test_order_block_replicant_invalid_location(self): - self.assertRaises( - exceptions.SoftLayerError, - self.block.order_replicant_volume, - 100, - 'WEEKLY', - 'moon_center', - os_type='LINUX', + self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + + self.assert_called_with( + 'SoftLayer_Product_Order', + 'placeOrder', + args=({ + 'complexType': 'SoftLayer_Container_Product_Order_Network_' + 'Storage_Enterprise_SnapshotSpace', + 'packageId': 759, + 'prices': [ + {'id': 193613} + ], + 'quantity': 1, + 'location': 449500, + 'volumeId': 102 + },) ) - def test_order_block_replicant_invalid_storage_type(self): + def test_order_block_replicant_os_type_not_found(self): + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_os_type = mock_volume['osType'] + del mock_volume['osType'] mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = mock_volume - mock.return_value = { - 'capacityGb': 20, - 'billingItem': { - 'categoryCode': 'not_the_storage_you_are_looking_for' - } - } - - self.assertRaises( + exception = self.assertRaises( exceptions.SoftLayerError, self.block.order_replicant_volume, - 100, - 'WEEKLY', - 'dal05', - os_type='LINUX', + 102, 'WEEKLY', 'dal09' ) - def test_order_block_replicant_no_snapshot_space(self): - mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') - - mock.return_value = { - 'capacityGb': 20, - 'billingItem': { - 'categoryCode': 'storage_service_enterprise' - } - } - - self.assertRaises( - exceptions.SoftLayerError, - self.block.order_replicant_volume, - 100, - 'WEEKLY', - 'dal05', - os_type='LINUX', + self.assertEqual( + "Cannot find primary volume's os-type " + "automatically; must specify manually", + str(exception) ) - def test_order_block_replicant_primary_volume_cancelled(self): - mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock_volume['osType'] = prev_os_type - mock.return_value = { - 'capacityGb': 20, - 'snapshotCapacityGb': '10', - 'schedules': [{ - 'id': 7770, - 'type': {'keyname': 'SNAPSHOT_WEEKLY'} - }], - 'billingItem': { - 'categoryCode': 'storage_service_enterprise', - 'cancellationDate': '2016-09-04T22:00:00-07:00' - } - } + def test_order_block_replicant_performance_os_type_given(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 449494, 'name': 'dal09'}] - self.assertRaises( - exceptions.SoftLayerError, - self.block.order_replicant_volume, - 100, - 'WEEKLY', - 'dal05', - os_type='LINUX', - ) + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - def test_order_block_replicant_snapshot_space_cancelled(self): + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type_keyname = mock_volume['storageType']['keyName'] + mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = mock_volume - mock.return_value = { - 'capacityGb': 20, - 'snapshotCapacityGb': '10', - 'schedules': [{ - 'id': 7770, - 'type': {'keyname': 'SNAPSHOT_WEEKLY'} - }], - 'billingItem': { - 'categoryCode': 'storage_service_enterprise', - 'cancellationDate': '', - 'activeChildren': [{ - 'categoryCode': 'storage_snapshot_space', - 'cancellationDate': '2016-09-04T22:00:00-07:00' - }] - } - } - - self.assertRaises( - exceptions.SoftLayerError, - self.block.order_replicant_volume, - 100, + result = self.block.order_replicant_volume( + 102, 'WEEKLY', - 'dal05', - os_type='LINUX', + 'dal09', + os_type='XEN' ) - def test_order_block_replicant_os_type_not_found(self): - mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') - - mock.return_value = {} + self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) - self.assertRaises( - exceptions.SoftLayerError, - self.block.order_replicant_volume, - 100, - 'WEEKLY', - 'dal05', - tier='2', + self.assert_called_with( + 'SoftLayer_Product_Order', + 'placeOrder', + args=({ + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189443}, + {'id': 189993}, + {'id': 190053}, + {'id': 191193}, + {'id': 192033} + ], + 'volumeSize': 500, + 'quantity': 1, + 'location': 449494, + 'iops': 1000, + 'originVolumeId': 102, + 'originVolumeScheduleId': 978, + 'osFormatType': {'keyName': 'XEN'} + },) ) - def test_order_block_replicant(self): + mock_volume['storageType']['keyName'] = prev_storage_type_keyname + + def test_order_block_replicant_endurance(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 449494, 'name': 'dal09'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{ - 'id': 240, - 'name': 'Endurance', - 'items': [{ - 'capacity': '0', - 'attributes': [{ - 'value': '42', - }], - 'prices': [{ - 'locationGroupId': '530', - }], - }, { - 'capacity': '10', - 'attributes': [{ - 'value': '200', - }], - 'prices': [{ - 'locationGroupId': '530', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_service_enterprise', - }], - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_tier_level', - }], - }, { - 'id': 46130, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '200', - 'capacityRestrictionMaximum': '200', - }], - }, { - 'capacity': '20', - 'prices': [{ - 'locationGroupId': '530', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_block', - }], - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_service_enterprise', - }], - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_space', - }], - 'capacityRestrictionMinimum': '742', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_space', - }], - 'capacityRestrictionMinimum': '42', - 'capacityRestrictionMaximum': '42', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_space', - }], - 'capacityRestrictionMinimum': '200', - 'capacityRestrictionMaximum': '200', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_replication', - }], - 'capacityRestrictionMinimum': '742', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_replication', - }], - 'capacityRestrictionMinimum': '42', - 'capacityRestrictionMaximum': '42', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_replication', - }], - 'capacityRestrictionMinimum': '200', - 'capacityRestrictionMaximum': '200', - }], - }], - }] + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - result = self.block.order_replicant_volume( - 100, - 'WEEKLY', - 'dal05', - ) + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = mock_volume - self.assertEqual( - result, - { - 'orderId': 1234, - 'orderDate': '2013-08-01 15:23:45', - 'prices': [{ - 'hourlyRecurringFee': '2', - 'id': 1, - 'item': {'description': 'this is a thing', 'id': 1}, - 'laborFee': '2', - 'oneTimeFee': '2', - 'oneTimeFeeTax': '.1', - 'quantity': 1, - 'recurringFee': '2', - 'recurringFeeTax': '.1', - 'setupFee': '1'}], - }, - ) + result = self.block.order_replicant_volume(102, 'WEEKLY', 'dal09') + + self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + + self.assert_called_with( + 'SoftLayer_Product_Order', + 'placeOrder', + args=({ + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189443}, + {'id': 193433}, + {'id': 193373}, + {'id': 193613}, + {'id': 194693} + ], + 'volumeSize': 500, + 'quantity': 1, + 'location': 449494, + 'originVolumeId': 102, + 'originVolumeScheduleId': 978, + 'osFormatType': {'keyName': 'LINUX'} + },) + ) 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_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_os_type = mock_volume['osType'] del mock_volume['osType'] mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -1020,7 +627,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -1059,7 +666,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -1105,7 +712,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -1139,7 +746,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume diff --git a/tests/managers/file_tests.py b/tests/managers/file_tests.py index ea313b3dc..d81a6e14a 100644 --- a/tests/managers/file_tests.py +++ b/tests/managers/file_tests.py @@ -169,6 +169,55 @@ def test_cancel_snapshot_immediately(self): identifier=123, ) + def test_cancel_snapshot_exception_no_billing_item_active_children(self): + mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = { + 'capacityGb': 20, + 'snapshotCapacityGb': '10', + 'schedules': [{ + 'id': 7770, + 'type': {'keyname': 'SNAPSHOT_WEEKLY'} + }], + 'billingItem': { + 'categoryCode': 'storage_service_enterprise', + 'cancellationDate': '2016-09-04T22:00:00-07:00' + } + } + exception = self.assertRaises( + exceptions.SoftLayerError, + self.file.cancel_snapshot_space, + 12345, + immediate=True + ) + self.assertEqual( + 'No snapshot space found to cancel', + str(exception) + ) + + def test_cancel_snapshot_exception_snapshot_billing_item_not_found(self): + mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = { + 'capacityGb': 20, + 'snapshotCapacityGb': '10', + 'schedules': [{ + 'id': 7770, + 'type': {'keyname': 'SNAPSHOT_WEEKLY'} + }], + 'billingItem': { + 'activeChildren': [] + } + } + exception = self.assertRaises( + exceptions.SoftLayerError, + self.file.cancel_snapshot_space, + 12345, + immediate=True + ) + self.assertEqual( + 'No snapshot space found to cancel', + str(exception) + ) + def test_replicant_failover(self): result = self.file.failover_to_replicant(1234, 5678, immediate=True) @@ -222,719 +271,325 @@ def test_delete_snapshot(self): 'deleteObject', identifier=100) - def test_order_file_volume_invalid_location(self): - mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') - mock.return_value = [] + def test_list_file_volumes(self): + result = self.file.list_file_volumes() - exception = self.assertRaises( - exceptions.SoftLayerError, - self.file.order_file_volume, - "performance_storage_nfs", - "dal05", - 100, - None, - iops=100, - ) + self.assertEqual(fixtures.SoftLayer_Account.getNasNetworkStorage, + result) - self.assertEqual(str(exception), "Invalid datacenter name " - "specified. Please provide the " - "lower case short name " - "(e.g.: dal09)") + expected_filter = { + 'nasNetworkStorage': { + 'storageType': { + 'keyName': {'operation': '*= FILE_STORAGE'} + }, + 'serviceResource': { + 'type': { + 'type': {'operation': '!~ NAS'} + } + } + } + } - def test_order_file_volume_no_package(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [] - - self.assertRaises( - ValueError, - self.file.order_file_volume, - "performance_storage_nfs", - "dal05", - 40, - None, - iops=100, - ) + expected_mask = 'id,'\ + 'username,'\ + 'capacityGb,'\ + 'bytesUsed,'\ + 'serviceResource.datacenter[name],'\ + 'serviceResourceBackendIpAddress,'\ + 'activeTransactionCount,'\ + 'fileNetworkMountAddress' - def test_order_file_volume_too_many_packages(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{}, {}] - - self.assertRaises( - ValueError, - self.file.order_file_volume, - "performance_storage_nfs", - "dal05", - 40, - None, - iops=100, + self.assert_called_with( + 'SoftLayer_Account', + 'getNasNetworkStorage', + filter=expected_filter, + mask='mask[%s]' % expected_mask ) - def test_order_file_volume_invalid_storage_type(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{}] + def test_list_file_volumes_with_additional_filters(self): + result = self.file.list_file_volumes(datacenter="dal09", + storage_type="Endurance", + username="username") - exception = self.assertRaises( - exceptions.SoftLayerError, - self.file.order_file_volume, - "something_completely_different", - "dal05", - 100, - None, - iops=100, - ) - self.assertEqual(str(exception), "File volume storage_type must be " - "either Performance or Endurance") + self.assertEqual(fixtures.SoftLayer_Account.getNasNetworkStorage, + result) - def test_order_file_volume_os_type_provided(self): - exception = self.assertRaises( - exceptions.SoftLayerError, - self.file.order_file_volume, - "performance_storage_nfs", - "dal05", - 100, - "LINUX", - iops=100, + expected_filter = { + 'nasNetworkStorage': { + 'storageType': { + 'keyName': {'operation': '^= ENDURANCE_FILE_STORAGE'} + }, + 'username': {'operation': u'_= username'}, + 'serviceResource': { + 'datacenter': { + 'name': {'operation': u'_= dal09'} + }, + 'type': { + 'type': {'operation': '!~ NAS'} + } + } + } + } + + expected_mask = 'id,'\ + 'username,'\ + 'capacityGb,'\ + 'bytesUsed,'\ + 'serviceResource.datacenter[name],'\ + 'serviceResourceBackendIpAddress,'\ + 'activeTransactionCount,'\ + 'fileNetworkMountAddress' + + self.assert_called_with( + 'SoftLayer_Account', + 'getNasNetworkStorage', + filter=expected_filter, + mask='mask[%s]' % expected_mask ) - self.assertEqual(str(exception), "OS type is not used on file " - "storage orders") def test_order_file_volume_performance(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 449494, 'name': 'dal09'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{ - 'id': 1, - 'name': 'Performance', - 'items': [{ - 'capacity': '1', - 'prices': [{ - 'id': 1, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_nfs', - }], - }], - }, { - 'capacity': '100', - 'prices': [{ - 'id': 2, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_space', - }], - }], - }, { - 'capacity': '100', - 'prices': [{ - 'id': 3, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_iops', - }], - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionMaximum': '100', - }], - }], - }] + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - result = self.file.order_file_volume( - "performance_storage_nfs", - "dal05", - 100, - None, - iops=100, - ) + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type_keyname = mock_volume['storageType']['keyName'] + mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' + mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = mock_volume - self.assertEqual( - result, - { - 'orderDate': '2013-08-01 15:23:45', - 'orderId': 1234, - 'prices': [{ - 'hourlyRecurringFee': '2', - 'id': 1, - 'item': {'description': 'this is a thing', 'id': 1}, - 'laborFee': '2', - 'oneTimeFee': '2', - 'oneTimeFeeTax': '.1', - 'quantity': 1, - 'recurringFee': '2', - 'recurringFeeTax': '.1', - 'setupFee': '1'}], - }, - ) + result = self.file.order_file_volume( + 'performance', + 'dal09', + 1000, + iops=2000, + service_offering='storage_as_a_service' + ) - def test_list_file_volumes(self): - result = self.file.list_file_volumes() + self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) - self.assertEqual(fixtures.SoftLayer_Account.getNasNetworkStorage, - result) + self.assert_called_with( + 'SoftLayer_Product_Order', + 'placeOrder', + args=({ + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189453}, + {'id': 190113}, + {'id': 190173} + ], + 'volumeSize': 1000, + 'quantity': 1, + 'location': 449494, + 'iops': 2000 + },) + ) - self.assert_called_with('SoftLayer_Account', 'getNasNetworkStorage') + mock_volume['storageType']['keyName'] = prev_storage_type_keyname def test_order_file_volume_endurance(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{ - 'id': 1, - 'name': 'Endurance', - 'items': [{ - 'capacity': '1', - 'prices': [{ - 'id': 1, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_file', - }], - }], - }, { - 'capacity': '1', - 'prices': [{ - 'id': 2, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_service_enterprise', - }], - }], - }, { - 'capacity': '100', - 'prices': [{ - 'id': 3, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_space', - }], - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionMaximum': '100', - }], - }, { - 'capacity': '100', - 'attributes': [{ - 'value': '100', - }], - 'prices': [{ - 'id': 4, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_tier_level', - }], - }], - }], - }] - - result = self.file.order_file_volume( - "storage_service_enterprise", - "dal05", - 100, - None, - tier_level=0.25, - ) - - self.assertEqual( - result, - { - 'orderDate': '2013-08-01 15:23:45', - 'orderId': 1234, - 'prices': [{ - 'hourlyRecurringFee': '2', - 'id': 1, - 'item': {'description': 'this is a thing', 'id': 1}, - 'laborFee': '2', - 'oneTimeFee': '2', - 'oneTimeFeeTax': '.1', - 'quantity': 1, - 'recurringFee': '2', - 'recurringFeeTax': '.1', - 'setupFee': '1'}], - }, - ) + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 449494, 'name': 'dal09'}] - def test_order_file_volume_endurance_with_snapshot(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{ - 'id': 1, - 'name': 'Endurance', - 'items': [{ - 'capacity': '1', - 'prices': [{ - 'id': 1, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_file', - }], - }], - }, { - 'capacity': '1', - 'prices': [{ - 'id': 2, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_service_enterprise', - }], - }], - }, { - 'capacity': '100', - 'prices': [{ - 'id': 3, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_space', - }], - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionMaximum': '100', - }], - }, { - 'capacity': '100', - 'attributes': [{ - 'value': '100', - }], - 'prices': [{ - 'id': 4, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_tier_level', - }], - }], - }, { - 'capacity': '10', - 'prices': [{ - 'id': 5, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionMaximum': '100', - }], - }], - }] + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type_keyname = mock_volume['storageType']['keyName'] + mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' + mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = mock_volume result = self.file.order_file_volume( - "storage_service_enterprise", - "dal05", - 100, - None, - tier_level=0.25, - snapshot_size=10, - ) + 'endurance', + 'dal09', + 1000, + tier_level=4, + service_offering='storage_as_a_service' + ) - self.assertEqual( - result, - { - 'orderDate': '2013-08-01 15:23:45', - 'orderId': 1234, - 'prices': [{ - 'hourlyRecurringFee': '2', - 'id': 1, - 'item': {'description': 'this is a thing', 'id': 1}, - 'laborFee': '2', - 'oneTimeFee': '2', - 'oneTimeFeeTax': '.1', - 'quantity': 1, - 'recurringFee': '2', - 'recurringFeeTax': '.1', - 'setupFee': '1'}], - }, - ) + self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) - def test_order_snapshot_space_no_package(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [] - - self.assertRaises( - ValueError, - self.file.order_snapshot_space, - 100, - 5, - None, - False, + self.assert_called_with( + 'SoftLayer_Product_Order', + 'placeOrder', + args=({ + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189453}, + {'id': 194763}, + {'id': 194703} + ], + 'volumeSize': 1000, + 'quantity': 1, + 'location': 449494 + },) ) - def test_order_snapshot_space_too_many_packages(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{}, {}] - - self.assertRaises( - ValueError, - self.file.order_snapshot_space, - 100, - 5, - None, - False, - ) + mock_volume['storageType']['keyName'] = prev_storage_type_keyname - def test_order_snapshot_space_invalid_category(self): + def test_order_file_snapshot_space_upgrade(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{ - 'id': 240, - 'name': 'Endurance', - 'items': [{ - 'capacity': '0', - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '530', - }], - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_file', - }], - }], - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '300', - }], - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionMaximum': '100', - }], - }, { - 'capacity': '5', - 'prices': [{ - 'id': 46130, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '200', - 'capacityRestrictionMaximum': '200', - }], - }], - }] + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - billing_item_mock = self.set_mock('SoftLayer_Network_Storage', - 'getObject') - billing_item_mock.return_value = { - 'billingItem': { - 'categoryCode': 'not_storage_service_enterprise' - } - } + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type_keyname = mock_volume['storageType']['keyName'] + mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' + mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = mock_volume - exception = self.assertRaises( - exceptions.SoftLayerError, - self.file.order_snapshot_space, - 100, - 5, - None, - False, + result = self.file.order_snapshot_space(102, 20, None, True) + + self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + + self.assert_called_with( + 'SoftLayer_Product_Order', + 'placeOrder', + args=({ + 'complexType': 'SoftLayer_Container_Product_Order_Network_' + 'Storage_Enterprise_SnapshotSpace_Upgrade', + 'packageId': 759, + 'prices': [ + {'id': 193853} + ], + 'quantity': 1, + 'location': 449500, + 'volumeId': 102 + },) ) - self.assertEqual(str(exception), "File volume storage_type must be " - "Endurance") - def test_order_snapshot_space(self): + mock_volume['storageType']['keyName'] = prev_storage_type_keyname + + def test_order_file_snapshot_space(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{ - 'id': 240, - 'name': 'Endurance', - 'items': [{ - 'capacity': '0', - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '530', - }], - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_file', - }], - }], - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '300', - }], - }, { - 'capacity': '5', - 'prices': [{ - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionMaximum': '100', - }], - }, { - 'capacity': '5', - 'prices': [{ - 'id': 46130, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '200', - 'capacityRestrictionMaximum': '200', - }], - }], - }] + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - result = self.file.order_snapshot_space( - 100, - 5, - None, - False, - ) + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type_keyname = mock_volume['storageType']['keyName'] + mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' + mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = mock_volume - self.assertEqual( - result, - { - 'orderId': 1234, - 'orderDate': '2013-08-01 15:23:45', - 'prices': [{ - 'hourlyRecurringFee': '2', - 'id': 1, - 'item': {'description': 'this is a thing', 'id': 1}, - 'laborFee': '2', - 'oneTimeFee': '2', - 'oneTimeFeeTax': '.1', - 'quantity': 1, - 'recurringFee': '2', - 'recurringFeeTax': '.1', - 'setupFee': '1'}], - }, - ) + result = self.file.order_snapshot_space(102, 10, None, False) - def test_order_file_replicant_invalid_location(self): - self.assertRaises( - exceptions.SoftLayerError, - self.file.order_replicant_volume, - 100, - 'WEEKLY', - 'moon_center', + self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + + self.assert_called_with( + 'SoftLayer_Product_Order', + 'placeOrder', + args=({ + 'complexType': 'SoftLayer_Container_Product_Order_Network_' + 'Storage_Enterprise_SnapshotSpace', + 'packageId': 759, + 'prices': [ + {'id': 193613} + ], + 'quantity': 1, + 'location': 449500, + 'volumeId': 102 + },) ) - def test_order_file_replicant_invalid_storage_type(self): - mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock_volume['storageType']['keyName'] = prev_storage_type_keyname - mock.return_value = { - 'capacityGb': 20, - 'billingItem': { - 'categoryCode': 'not_the_storage_you_are_looking_for' - } - } + def test_order_file_replicant_performance(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 449494, 'name': 'dal09'}] - self.assertRaises( - exceptions.SoftLayerError, - self.file.order_replicant_volume, - 100, - 'WEEKLY', - 'dal05', - ) + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - def test_order_file_replicant_no_snapshot_space(self): + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type_keyname = mock_volume['storageType']['keyName'] + mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = mock_volume - mock.return_value = { - 'capacityGb': 20, - 'billingItem': { - 'categoryCode': 'storage_service_enterprise' - } - } + result = self.file.order_replicant_volume(102, 'WEEKLY', 'dal09') - self.assertRaises( - exceptions.SoftLayerError, - self.file.order_replicant_volume, - 100, - 'WEEKLY', - 'dal05', + self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) + + self.assert_called_with( + 'SoftLayer_Product_Order', + 'placeOrder', + args=({ + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189453}, + {'id': 189993}, + {'id': 190053}, + {'id': 191193}, + {'id': 192033} + ], + 'volumeSize': 500, + 'quantity': 1, + 'location': 449494, + 'iops': 1000, + 'originVolumeId': 102, + 'originVolumeScheduleId': 978 + },) ) - def test_order_file_replicant_primary_volume_cancelled(self): - mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock_volume['storageType']['keyName'] = prev_storage_type_keyname - mock.return_value = { - 'capacityGb': 20, - 'snapshotCapacityGb': '10', - 'schedules': [{ - 'id': 7770, - 'type': {'keyname': 'SNAPSHOT_WEEKLY'} - }], - 'billingItem': { - 'categoryCode': 'storage_service_enterprise', - 'cancellationDate': '2016-09-04T22:00:00-07:00' - } - } + def test_order_file_replicant_endurance(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 449494, 'name': 'dal09'}] - self.assertRaises( - exceptions.SoftLayerError, - self.file.order_replicant_volume, - 100, - 'WEEKLY', - 'dal05', - ) + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - def test_order_file_replicant_snapshot_space_cancelled(self): + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type_keyname = mock_volume['storageType']['keyName'] + mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = mock_volume - mock.return_value = { - 'capacityGb': 20, - 'snapshotCapacityGb': '10', - 'schedules': [{ - 'id': 7770, - 'type': {'keyname': 'SNAPSHOT_WEEKLY'} - }], - 'billingItem': { - 'categoryCode': 'storage_service_enterprise', - 'cancellationDate': '', - 'activeChildren': [{ - 'categoryCode': 'storage_snapshot_space', - 'cancellationDate': '2016-09-04T22:00:00-07:00' - }] - } - } - - self.assertRaises( - exceptions.SoftLayerError, - self.file.order_replicant_volume, - 100, - 'WEEKLY', - 'dal05', - ) + result = self.file.order_replicant_volume(102, 'WEEKLY', 'dal09') - def test_order_file_replicant(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [{ - 'id': 240, - 'name': 'Endurance', - 'items': [{ - 'capacity': '0', - 'attributes': [{ - 'value': '42', - }], - 'prices': [{ - 'locationGroupId': '530', - }], - }, { - 'capacity': '10', - 'attributes': [{ - 'value': '200', - }], - 'prices': [{ - 'locationGroupId': '530', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_service_enterprise', - }], - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_tier_level', - }], - }, { - 'id': 46130, - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_snapshot_space', - }], - 'capacityRestrictionMinimum': '200', - 'capacityRestrictionMaximum': '200', - }], - }, { - 'capacity': '20', - 'prices': [{ - 'locationGroupId': '530', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_file', - }], - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'storage_service_enterprise', - }], - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_space', - }], - 'capacityRestrictionMinimum': '742', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_space', - }], - 'capacityRestrictionMinimum': '42', - 'capacityRestrictionMaximum': '42', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_space', - }], - 'capacityRestrictionMinimum': '200', - 'capacityRestrictionMaximum': '200', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_replication', - }], - 'capacityRestrictionMinimum': '742', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_replication', - }], - 'capacityRestrictionMinimum': '42', - 'capacityRestrictionMaximum': '42', - }, { - 'locationGroupId': '', - 'categories': [{ - 'categoryCode': 'performance_storage_replication', - }], - 'capacityRestrictionMinimum': '200', - 'capacityRestrictionMaximum': '200', - }], - }], - }] + self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) - result = self.file.order_replicant_volume( - 100, - 'WEEKLY', - 'dal05', - ) + self.assert_called_with( + 'SoftLayer_Product_Order', + 'placeOrder', + args=({ + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189453}, + {'id': 193433}, + {'id': 193373}, + {'id': 193613}, + {'id': 194693} + ], + 'volumeSize': 500, + 'quantity': 1, + 'location': 449494, + 'originVolumeId': 102, + 'originVolumeScheduleId': 978 + },) + ) - self.assertEqual( - result, - { - 'orderId': 1234, - 'orderDate': '2013-08-01 15:23:45', - 'prices': [{ - 'hourlyRecurringFee': '2', - 'id': 1, - 'item': {'description': 'this is a thing', 'id': 1}, - 'laborFee': '2', - 'oneTimeFee': '2', - 'oneTimeFeeTax': '.1', - 'quantity': 1, - 'recurringFee': '2', - 'recurringFeeTax': '.1', - 'setupFee': '1'}], - }, - ) + mock_volume['storageType']['keyName'] = prev_storage_type_keyname 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_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -972,7 +627,7 @@ 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 = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -1017,7 +672,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -1054,7 +709,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') diff --git a/tests/managers/storage_utils_tests.py b/tests/managers/storage_utils_tests.py index b875cceea..cca34fcad 100644 --- a/tests/managers/storage_utils_tests.py +++ b/tests/managers/storage_utils_tests.py @@ -17,13 +17,159 @@ def set_up(self): self.block = SoftLayer.BlockStorageManager(self.client) self.file = SoftLayer.FileStorageManager(self.client) - def test_find_saas_price_by_category_no_items_in_package(self): + # --------------------------------------------------------------------- + # Tests for populate_host_templates() + # --------------------------------------------------------------------- + def test_populate_host_templates_no_ids_given(self): + host_templates = [] + + storage_utils.populate_host_templates(host_templates) + + self.assertEqual([], host_templates) + + def test_populate_host_templates_empty_arrays_given(self): + host_templates = [] + + storage_utils.populate_host_templates( + 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, + hardware_ids=[1111], + virtual_guest_ids=[2222], + ip_address_ids=[3333], + subnet_ids=[4444, 5555] + ) + + expected_result = [ + {'objectType': 'SoftLayer_Hardware', 'id': 1111}, + {'objectType': 'SoftLayer_Virtual_Guest', 'id': 2222}, + {'objectType': 'SoftLayer_Network_Subnet_IpAddress', 'id': 3333}, + {'objectType': 'SoftLayer_Network_Subnet', 'id': 4444}, + {'objectType': 'SoftLayer_Network_Subnet', 'id': 5555} + ] + + self.assertEqual(expected_result, host_templates) + + # --------------------------------------------------------------------- + # Tests for get_package() + # --------------------------------------------------------------------- + def test_get_package_no_packages_found(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [] + + exception = self.assertRaises( + ValueError, + storage_utils.get_package, + self.block, 'storage_as_a_service' + ) + + self.assertEqual( + "No packages were found for storage_as_a_service", + str(exception) + ) + + def test_get_package_more_than_one_package_found(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [ + fixtures.SoftLayer_Product_Package.SAAS_PACKAGE, + fixtures.SoftLayer_Product_Package.ENTERPRISE_PACKAGE + ] + + exception = self.assertRaises( + ValueError, + storage_utils.get_package, + self.block, 'storage_as_a_service' + ) + + self.assertEqual( + "More than one package was found for storage_as_a_service", + str(exception) + ) + + def test_get_package(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + result = storage_utils.get_package(self.block, 'storage_as_a_service') + + self.assertEqual( + fixtures.SoftLayer_Product_Package.SAAS_PACKAGE, + result + ) + + expected_filter = { + 'statusCode': {'operation': '_= ACTIVE'}, + 'categories': { + 'categoryCode': {'operation': '_= storage_as_a_service'} + } + } + + self.assert_called_with( + 'SoftLayer_Product_Package', + 'getAllObjects', + filter=expected_filter, + mask='mask[id,name,items[prices[categories],attributes]]' + ) + + # --------------------------------------------------------------------- + # Tests for get_location_id() + # --------------------------------------------------------------------- + def test_get_location_id_no_datacenters_in_collection(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [] + + exception = self.assertRaises( + ValueError, + storage_utils.get_location_id, + self.block, 'dal09' + ) + + self.assertEqual("Invalid datacenter name specified.", str(exception)) + + def test_get_location_id_no_matching_location_name(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [ + {'id': 1414, 'name': 'hoth01'}, + {'id': 1417, 'name': 'hoth04'} + ] + + exception = self.assertRaises( + ValueError, + storage_utils.get_location_id, + self.block, 'dal09' + ) + + self.assertEqual("Invalid datacenter name specified.", str(exception)) + + def test_get_location_id(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 29, 'name': 'dal09'}] + + result = storage_utils.get_location_id(self.block, 'dal09') + + self.assertEqual(29, result) + + # --------------------------------------------------------------------- + # Tests for find_price_by_category() + # --------------------------------------------------------------------- + def test_find_price_by_category_no_items_in_package(self): package = { 'items': []} exception = self.assertRaises( ValueError, - storage_utils.find_saas_price_by_category, + storage_utils.find_price_by_category, package, 'storage_as_a_service' ) @@ -31,7 +177,7 @@ def test_find_saas_price_by_category_no_items_in_package(self): "Could not find price with the category, " "storage_as_a_service") - def test_find_saas_price_by_category_no_prices_in_items(self): + def test_find_price_by_category_no_prices_in_items(self): package = { 'items': [ {'capacity': '0', @@ -40,7 +186,7 @@ def test_find_saas_price_by_category_no_prices_in_items(self): exception = self.assertRaises( ValueError, - storage_utils.find_saas_price_by_category, + storage_utils.find_price_by_category, package, 'storage_as_a_service' ) @@ -48,7 +194,7 @@ def test_find_saas_price_by_category_no_prices_in_items(self): "Could not find price with the category, " "storage_as_a_service") - def test_find_saas_price_by_category_empty_location_not_found(self): + def test_find_price_by_category_empty_location_not_found(self): package = { 'items': [ {'capacity': '0', @@ -63,7 +209,7 @@ def test_find_saas_price_by_category_empty_location_not_found(self): exception = self.assertRaises( ValueError, - storage_utils.find_saas_price_by_category, + storage_utils.find_price_by_category, package, 'storage_as_a_service' ) @@ -71,7 +217,7 @@ def test_find_saas_price_by_category_empty_location_not_found(self): "Could not find price with the category, " "storage_as_a_service") - def test_find_saas_price_by_category_category_not_found(self): + def test_find_price_by_category_category_not_found(self): package = { 'items': [ {'capacity': '0', @@ -86,7 +232,7 @@ def test_find_saas_price_by_category_category_not_found(self): exception = self.assertRaises( ValueError, - storage_utils.find_saas_price_by_category, + storage_utils.find_price_by_category, package, 'storage_as_a_service' ) @@ -94,7 +240,7 @@ def test_find_saas_price_by_category_category_not_found(self): "Could not find price with the category, " "storage_as_a_service") - def test_find_saas_price_by_category(self): + def test_find_price_by_category(self): package = { 'items': [ {'capacity': '0', @@ -107,1154 +253,3316 @@ def test_find_saas_price_by_category(self): ]} ]} - result = storage_utils.find_saas_price_by_category( + result = storage_utils.find_price_by_category( package, 'storage_as_a_service') self.assertEqual({'id': 189433}, result) - def test_find_saas_endurance_space_price_no_items_in_package(self): + # --------------------------------------------------------------------- + # Tests for find_ent_space_price() + # --------------------------------------------------------------------- + def test_find_ent_space_price_no_items_in_package(self): package = { - 'items': []} + 'items': [] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_space_price, - package, 8000, 0.25 + storage_utils.find_ent_space_price, + package, 'snapshot', 10, 2 ) - self.assertEqual(str(exception), - "Could not find price for endurance storage space") + self.assertEqual( + "Could not find price for snapshot storage space", + str(exception) + ) - def test_find_saas_endurance_space_price_no_matching_keyname(self): + def test_find_ent_space_price_no_matching_capacity(self): package = { 'items': [ - {'capacity': '0', - 'keyName': 'STORAGE_SPACE_FOR_2_IOPS_PER_GB'} - ]} + {'capacity': '-1'} + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_space_price, - package, 8000, 0.25 + storage_utils.find_ent_space_price, + package, 'snapshot', 10, 2 ) - self.assertEqual(str(exception), - "Could not find price for endurance storage space") + self.assertEqual( + "Could not find price for snapshot storage space", + str(exception) + ) - def test_find_saas_endurance_space_price_no_capacity_maximum(self): + def test_find_ent_space_price_no_prices_in_items(self): package = { 'items': [ - {'capacity': '0', - 'capacityMinimum': '1', - 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB'} - ]} + { + 'capacity': '10', + 'prices': [] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_space_price, - package, 8000, 0.25 + storage_utils.find_ent_space_price, + package, 'snapshot', 10, 2 ) - self.assertEqual(str(exception), - "Could not find price for endurance storage space") + self.assertEqual( + "Could not find price for snapshot storage space", + str(exception) + ) - def test_find_saas_endurance_space_price_no_capacity_minimum(self): + def test_find_ent_space_price_empty_location_not_found(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '12000', - 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB'} - ]} + { + 'capacity': '10', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 46160, + 'locationGroupId': '77777777' + } + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_space_price, - package, 8000, 0.25 + storage_utils.find_ent_space_price, + package, 'snapshot', 10, 2 ) - self.assertEqual(str(exception), - "Could not find price for endurance storage space") + self.assertEqual( + "Could not find price for snapshot storage space", + str(exception) + ) - def test_find_saas_endurance_space_price_size_below_capacity(self): + def test_find_ent_space_price_wrong_capacity_restriction(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '12000', - 'capacityMinimum': '1', - 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB'} - ]} + { + 'capacity': '10', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'WRONG_CATEGORY', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 46160, + 'locationGroupId': '' + } + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_space_price, - package, 0, 0.25 + storage_utils.find_ent_space_price, + package, 'snapshot', 10, 2 ) - self.assertEqual(str(exception), - "Could not find price for endurance storage space") + self.assertEqual( + "Could not find price for snapshot storage space", + str(exception) + ) - def test_find_saas_endurance_space_price_size_above_capacity(self): + def test_find_ent_space_price_target_value_below_capacity(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '12000', - 'capacityMinimum': '1', - 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB'} - ]} + { + 'capacity': '10', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 46160, + 'locationGroupId': '' + } + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_space_price, - package, 12001, 0.25 + storage_utils.find_ent_space_price, + package, 'snapshot', 10, 0.25 ) - self.assertEqual(str(exception), - "Could not find price for endurance storage space") + self.assertEqual( + "Could not find price for snapshot storage space", + str(exception) + ) - def test_find_saas_endurance_space_price_no_prices_in_items(self): + def test_find_ent_space_price_target_value_above_capacity(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '12000', - 'capacityMinimum': '1', - 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB', - 'prices': []} - ]} + { + 'capacity': '10', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 46160, + 'locationGroupId': '' + } + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_space_price, - package, 8000, 0.25 + storage_utils.find_ent_space_price, + package, 'snapshot', 10, 4 ) - self.assertEqual(str(exception), - "Could not find price for endurance storage space") + self.assertEqual( + "Could not find price for snapshot storage space", + str(exception) + ) - def test_find_saas_endurance_space_price_empty_location_not_found(self): + def test_find_ent_space_price_category_not_found(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '12000', - 'capacityMinimum': '1', - 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB', - 'prices': [ - {'id': 192103, - 'categories': [ - {'categoryCode': 'performance_storage_space'} - ], - 'locationGroupId': '77777777'} - ]} - ]} + { + 'capacity': '10', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'invalid_category_noooooooo'} + ], + 'id': 46160, + 'locationGroupId': '' + } + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_space_price, - package, 8000, 0.25 + storage_utils.find_ent_space_price, + package, 'snapshot', 10, 2 ) - self.assertEqual(str(exception), - "Could not find price for endurance storage space") + self.assertEqual( + "Could not find price for snapshot storage space", + str(exception) + ) - def test_find_saas_endurance_space_price_category_not_found(self): + def test_find_ent_space_price_with_snapshot_category(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '12000', - 'capacityMinimum': '1', - 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB', - 'prices': [ - {'id': 192103, - 'categories': [ - {'categoryCode': 'invalid_category_noooo'} - ], - 'locationGroupId': ''} - ]} - ]} + { + 'capacity': '10', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 46160, + 'locationGroupId': '' + } + ] + } + ] + } + + result = storage_utils.find_ent_space_price( + package, 'snapshot', 10, 2 + ) + + self.assertEqual({'id': 46160}, result) + + def test_find_ent_space_price_with_replication_category(self): + package = { + 'items': [ + { + 'capacity': '20', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': + 'performance_storage_replication'} + ], + 'id': 46659, + 'locationGroupId': '' + } + ] + } + ] + } + + result = storage_utils.find_ent_space_price( + package, 'replication', 20, 2 + ) + + self.assertEqual({'id': 46659}, result) + + def test_find_ent_space_price_with_endurance_category(self): + package = { + 'items': [ + { + 'capacity': '1000', + 'prices': [ + { + 'capacityRestrictionMaximum': '300', + 'capacityRestrictionMinimum': '300', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'performance_storage_space'} + ], + 'id': 45318, + 'locationGroupId': '' + } + ] + } + ] + } + + result = storage_utils.find_ent_space_price( + package, 'endurance', 1000, 4 + ) + + self.assertEqual({'id': 45318}, result) + + # --------------------------------------------------------------------- + # Tests for find_ent_endurance_tier_price() + # --------------------------------------------------------------------- + def test_find_ent_endurance_tier_price_no_items_in_package(self): + package = { + 'items': [] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_space_price, - package, 8000, 0.25 + storage_utils.find_ent_endurance_tier_price, + package, 2 ) - self.assertEqual(str(exception), - "Could not find price for endurance storage space") + self.assertEqual( + "Could not find price for endurance tier level", + str(exception) + ) - def test_find_saas_endurance_space_price(self): + def test_find_ent_endurance_tier_price_no_attributes_in_items(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '12000', - 'capacityMinimum': '1', - 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB', - 'prices': [ - {'id': 192103, - 'categories': [ - {'categoryCode': 'performance_storage_space'} - ], - 'locationGroupId': ''} - ]} - ]} + {'attributes': []} + ] + } - result = storage_utils.find_saas_endurance_space_price( - package, 8000, 0.25) + exception = self.assertRaises( + ValueError, + storage_utils.find_ent_endurance_tier_price, + package, 2 + ) - self.assertEqual({'id': 192103}, result) + self.assertEqual( + "Could not find price for endurance tier level", + str(exception) + ) - def test_find_saas_endurance_tier_price_no_items_in_package(self): + def test_find_ent_endurance_tier_price_no_matching_attribute_value(self): package = { - 'items': []} + 'items': [ + { + 'attributes': [ + {'value': '-1'} + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_tier_price, + storage_utils.find_ent_endurance_tier_price, package, 2 ) - self.assertEqual(str(exception), - "Could not find price for endurance tier level") + self.assertEqual( + "Could not find price for endurance tier level", + str(exception) + ) - def test_find_saas_endurance_tier_price_no_itemCategory(self): + def test_find_ent_endurance_tier_price_no_prices_in_items(self): package = { 'items': [ - {'capacity': '200'} - ]} + { + 'attributes': [ + {'value': '200'} + ], + 'prices': [] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_tier_price, + storage_utils.find_ent_endurance_tier_price, package, 2 ) - self.assertEqual(str(exception), - "Could not find price for endurance tier level") + self.assertEqual( + "Could not find price for endurance tier level", + str(exception) + ) - def test_find_saas_endurance_tier_price_no_itemCategory_code(self): + def test_find_ent_endurance_tier_price_empty_location_not_found(self): package = { 'items': [ - {'capacity': '200', - 'itemCategory': {}} - ]} + { + 'attributes': [ + {'value': '200'} + ], + 'prices': [ + { + 'categories': [ + {'categoryCode': 'storage_tier_level'} + ], + 'id': 45078, + 'locationGroupId': '77777777' + } + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_tier_price, + storage_utils.find_ent_endurance_tier_price, package, 2 ) - self.assertEqual(str(exception), - "Could not find price for endurance tier level") + self.assertEqual( + "Could not find price for endurance tier level", + str(exception) + ) - def test_find_saas_endurance_tier_price_no_matching_itemCategory(self): + def test_find_ent_endurance_tier_price_category_not_found(self): package = { 'items': [ - {'capacity': '200', - 'itemCategory': {'categoryCode': 'invalid_category_noooo'}} - ]} + { + 'attributes': [ + {'value': '200'} + ], + 'prices': [ + { + 'categories': [ + {'categoryCode': 'invalid_category_noooo'} + ], + 'id': 45078, + 'locationGroupId': '' + } + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_tier_price, + storage_utils.find_ent_endurance_tier_price, package, 2 ) - self.assertEqual(str(exception), - "Could not find price for endurance tier level") + self.assertEqual( + "Could not find price for endurance tier level", + str(exception) + ) - def test_find_saas_endurance_tier_price_no_matching_capacity(self): + def test_find_ent_endurance_tier_price(self): package = { 'items': [ - {'capacity': '200', - 'itemCategory': {'categoryCode': 'storage_tier_level'}} - ]} + { + 'attributes': [ + {'value': '200'} + ], + 'prices': [ + { + 'categories': [ + {'categoryCode': 'storage_tier_level'} + ], + 'id': 45078, + 'locationGroupId': '' + } + ] + } + ] + } + + result = storage_utils.find_ent_endurance_tier_price(package, 2) + + self.assertEqual({'id': 45078}, result) + + # --------------------------------------------------------------------- + # Tests for find_endurance_tier_iops_per_gb() + # --------------------------------------------------------------------- + def test_find_endurance_tier_iops_per_gb_value_is_025(self): + volume = {'storageTierLevel': 'LOW_INTENSITY_TIER'} + result = storage_utils.find_endurance_tier_iops_per_gb(volume) + self.assertEqual(0.25, result) + + def test_find_endurance_tier_iops_per_gb_value_is_2(self): + volume = {'storageTierLevel': 'READHEAVY_TIER'} + result = storage_utils.find_endurance_tier_iops_per_gb(volume) + self.assertEqual(2, result) + + def test_find_endurance_tier_iops_per_gb_value_is_4(self): + volume = {'storageTierLevel': 'WRITEHEAVY_TIER'} + result = storage_utils.find_endurance_tier_iops_per_gb(volume) + self.assertEqual(4, result) + + def test_find_endurance_tier_iops_per_gb_value_is_10(self): + volume = {'storageTierLevel': '10_IOPS_PER_GB'} + result = storage_utils.find_endurance_tier_iops_per_gb(volume) + self.assertEqual(10, result) + + def test_find_endurance_tier_iops_per_gb_value_not_found(self): + volume = {'storageTierLevel': 'INVALID_TIER_OH_NOOOO'} exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_tier_price, - package, 10 + storage_utils.find_endurance_tier_iops_per_gb, + volume ) - self.assertEqual(str(exception), - "Could not find price for endurance tier level") + self.assertEqual( + "Could not find tier IOPS per GB for this volume", + str(exception) + ) - def test_find_saas_endurance_tier_price_no_prices_in_items(self): + # --------------------------------------------------------------------- + # Tests for find_perf_space_price() + # --------------------------------------------------------------------- + def test_find_perf_space_price_no_items_in_package(self): package = { - 'items': [ - {'capacity': '200', - 'itemCategory': {'categoryCode': 'storage_tier_level'}, - 'prices': []} - ]} + 'items': [] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_tier_price, - package, 2 + storage_utils.find_perf_space_price, + package, 1000 ) - self.assertEqual(str(exception), - "Could not find price for endurance tier level") + self.assertEqual( + "Could not find performance space price for this volume", + str(exception) + ) - def test_find_saas_endurance_tier_price_empty_location_not_found(self): + def test_find_perf_space_price_no_matching_capacity(self): package = { 'items': [ - {'capacity': '200', - 'itemCategory': {'categoryCode': 'storage_tier_level'}, - 'prices': [ - {'id': 193373, - 'categories': [ - {'categoryCode': 'storage_tier_level'} - ], - 'locationGroupId': '77777777'} - ]} - ]} + {'capacity': '-1'} + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_tier_price, - package, 2 + storage_utils.find_perf_space_price, + package, 1000 ) - self.assertEqual(str(exception), - "Could not find price for endurance tier level") + self.assertEqual( + "Could not find performance space price for this volume", + str(exception) + ) - def test_find_saas_endurance_tier_price_category_not_found(self): + def test_find_perf_space_price_no_prices_in_items(self): package = { 'items': [ - {'capacity': '200', - 'itemCategory': {'categoryCode': 'storage_tier_level'}, - 'prices': [ - {'id': 193373, - 'categories': [ - {'categoryCode': 'invalid_category_noooo'} - ], - 'locationGroupId': ''} - ]} - ]} + { + 'capacity': '1000', + 'prices': [] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_endurance_tier_price, - package, 2 + storage_utils.find_perf_space_price, + package, 1000 ) - self.assertEqual(str(exception), - "Could not find price for endurance tier level") + self.assertEqual( + "Could not find performance space price for this volume", + str(exception) + ) - def test_find_saas_endurance_tier_price(self): + def test_find_perf_space_price_empty_location_not_found(self): package = { 'items': [ - {'capacity': '200', - 'itemCategory': {'categoryCode': 'storage_tier_level'}, - 'prices': [ - {'id': 193373, - 'categories': [ - {'categoryCode': 'storage_tier_level'} - ], - 'locationGroupId': ''} - ]} - ]} + { + 'capacity': '1000', + 'prices': [ + { + 'categories': [ + {'categoryCode': 'performance_storage_space'} + ], + 'id': 40742, + 'locationGroupId': '77777777' + } + ] + } + ] + } - result = storage_utils.find_saas_endurance_tier_price( - package, 2) + exception = self.assertRaises( + ValueError, + storage_utils.find_perf_space_price, + package, 1000 + ) - self.assertEqual({'id': 193373}, result) + self.assertEqual( + "Could not find performance space price for this volume", + str(exception) + ) - def test_find_saas_perform_space_price_no_items_in_package(self): + def test_find_perf_space_price_category_not_found(self): package = { - 'items': []} + 'items': [ + { + 'capacity': '1000', + 'prices': [ + { + 'categories': [ + {'categoryCode': 'invalid_category_noooo'} + ], + 'id': 40742, + 'locationGroupId': '' + } + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_space_price, - package, 500 + storage_utils.find_perf_space_price, + package, 1000 ) - self.assertEqual(str(exception), - "Could not find price for performance storage space") + self.assertEqual( + "Could not find performance space price for this volume", + str(exception) + ) - def test_find_saas_perform_space_price_no_itemCategory(self): + def test_find_perf_space_price(self): package = { 'items': [ - {'capacity': '0'} - ]} + { + 'capacity': '1000', + 'prices': [ + { + 'categories': [ + {'categoryCode': 'performance_storage_space'} + ], + 'id': 40742, + 'locationGroupId': '' + } + ] + } + ] + } + + result = storage_utils.find_perf_space_price( + package, 1000 + ) + + self.assertEqual({'id': 40742}, result) + + # --------------------------------------------------------------------- + # Tests for find_perf_iops_price() + # --------------------------------------------------------------------- + def test_find_perf_iops_price_no_items_in_package(self): + package = { + 'items': [] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_space_price, - package, 500 + storage_utils.find_perf_iops_price, + package, 500, 800 ) - self.assertEqual(str(exception), - "Could not find price for performance storage space") + self.assertEqual( + "Could not find price for iops for the given volume", + str(exception) + ) - def test_find_saas_perform_space_price_no_itemCategory_code(self): + def test_find_perf_iops_price_no_matching_iops_value(self): package = { 'items': [ - {'capacity': '0', - 'itemCategory': {}} - ]} + {'capacity': '-1'} + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_space_price, - package, 500 + storage_utils.find_perf_iops_price, + package, 500, 800 ) - self.assertEqual(str(exception), - "Could not find price for performance storage space") + self.assertEqual( + "Could not find price for iops for the given volume", + str(exception) + ) - def test_find_saas_perform_space_price_no_matching_itemCategory(self): + def test_find_perf_iops_price_no_prices_in_items(self): package = { 'items': [ - {'capacity': '0', - 'itemCategory': {'categoryCode': 'invalid_category_noooo'}} - ]} + { + 'capacity': '800', + 'keyName': '800_IOPS_4', + 'prices': [] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_space_price, - package, 500 + storage_utils.find_perf_iops_price, + package, 500, 800 ) - self.assertEqual(str(exception), - "Could not find price for performance storage space") + self.assertEqual( + "Could not find price for iops for the given volume", + str(exception) + ) - def test_find_saas_perform_space_price_no_capacity_maximum(self): + def test_find_perf_iops_price_empty_location_not_found(self): package = { 'items': [ - {'capacity': '0', - 'capacityMinimum': '500', - 'itemCategory': {'categoryCode': 'performance_storage_space'}, - 'keyName': '500_999_GBS'} - ]} + { + 'capacity': '800', + 'keyName': '800_IOPS_4', + 'prices': [ + { + 'capacityRestrictionMaximum': '1000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 41562, + 'locationGroupId': '77777777' + } + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_space_price, - package, 500 + storage_utils.find_perf_iops_price, + package, 500, 800 ) - self.assertEqual(str(exception), - "Could not find price for performance storage space") + self.assertEqual( + "Could not find price for iops for the given volume", + str(exception) + ) - def test_find_saas_perform_space_price_no_capacity_minimum(self): + def test_find_perf_iops_price_category_not_found(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '999', - 'itemCategory': {'categoryCode': 'performance_storage_space'}, - 'keyName': '500_999_GBS'} - ]} + { + 'capacity': '800', + 'keyName': '800_IOPS_4', + 'prices': [ + { + 'capacityRestrictionMaximum': '1000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'invalid_category_noooo'} + ], + 'id': 41562, + 'locationGroupId': '' + } + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_space_price, - package, 500 + storage_utils.find_perf_iops_price, + package, 500, 800 ) - self.assertEqual(str(exception), - "Could not find price for performance storage space") + self.assertEqual( + "Could not find price for iops for the given volume", + str(exception) + ) - def test_find_saas_perform_space_price_size_below_capacity(self): + def test_find_perf_iops_price_wrong_capacity_restriction(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '999', - 'capacityMinimum': '500', - 'itemCategory': {'categoryCode': 'performance_storage_space'}, - 'keyName': '500_999_GBS'} - ]} + { + 'capacity': '800', + 'keyName': '800_IOPS_4', + 'prices': [ + { + 'capacityRestrictionMaximum': '1000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'WRONG_TYPE_WOAH', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 41562, + 'locationGroupId': '' + } + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_space_price, - package, 499 + storage_utils.find_perf_iops_price, + package, 500, 800 ) - self.assertEqual(str(exception), - "Could not find price for performance storage space") + self.assertEqual( + "Could not find price for iops for the given volume", + str(exception) + ) - def test_find_saas_perform_space_price_size_above_capacity(self): + def test_find_perf_iops_price_volume_size_below_capacity(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '999', - 'capacityMinimum': '500', - 'itemCategory': {'categoryCode': 'performance_storage_space'}, - 'keyName': '500_999_GBS'} - ]} + { + 'capacity': '800', + 'keyName': '800_IOPS_4', + 'prices': [ + { + 'capacityRestrictionMaximum': '1000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 41562, + 'locationGroupId': '' + } + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_space_price, - package, 1000 + storage_utils.find_perf_iops_price, + package, 80, 800 ) - self.assertEqual(str(exception), - "Could not find price for performance storage space") + self.assertEqual( + "Could not find price for iops for the given volume", + str(exception) + ) - def test_find_saas_perform_space_price_no_matching_keyname(self): + def test_find_perf_iops_price_volume_size_above_capacity(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '999', - 'capacityMinimum': '500', - 'itemCategory': {'categoryCode': 'performance_storage_space'}, - 'keyName': 'NOT_THE_CORRECT_KEYNAME'} - ]} + { + 'capacity': '800', + 'keyName': '800_IOPS_4', + 'prices': [ + { + 'capacityRestrictionMaximum': '1000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 41562, + 'locationGroupId': '' + } + ] + } + ] + } exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_space_price, - package, 500 + storage_utils.find_perf_iops_price, + package, 2000, 800 ) - self.assertEqual(str(exception), - "Could not find price for performance storage space") + self.assertEqual( + "Could not find price for iops for the given volume", + str(exception) + ) - def test_find_saas_perform_space_price_no_prices_in_items(self): + def test_find_perf_iops_price(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '999', - 'capacityMinimum': '500', - 'itemCategory': {'categoryCode': 'performance_storage_space'}, - 'keyName': '500_999_GBS', - 'prices': []} - ]} + { + 'capacity': '800', + 'keyName': '800_IOPS_4', + 'prices': [ + { + 'capacityRestrictionMaximum': '1000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 41562, + 'locationGroupId': '' + } + ] + } + ] + } + + result = storage_utils.find_perf_iops_price( + package, 500, 800 + ) + + self.assertEqual({'id': 41562}, result) + + # --------------------------------------------------------------------- + # Tests for find_saas_endurance_space_price() + # --------------------------------------------------------------------- + def test_find_saas_endurance_space_price_no_items_in_package(self): + package = { + 'items': []} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_space_price, - package, 500 + storage_utils.find_saas_endurance_space_price, + package, 8000, 0.25 ) self.assertEqual(str(exception), - "Could not find price for performance storage space") + "Could not find price for endurance storage space") - def test_find_saas_perform_space_price_empty_location_not_found(self): + def test_find_saas_endurance_space_price_no_matching_keyname(self): package = { 'items': [ {'capacity': '0', - 'capacityMaximum': '999', - 'capacityMinimum': '500', - 'itemCategory': {'categoryCode': 'performance_storage_space'}, - 'keyName': '500_999_GBS', - 'prices': [ - {'id': 189993, - 'categories': [ - {'categoryCode': 'performance_storage_space'} - ], - 'locationGroupId': '77777777'} - ]} + 'keyName': 'STORAGE_SPACE_FOR_2_IOPS_PER_GB'} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_space_price, - package, 500 + storage_utils.find_saas_endurance_space_price, + package, 8000, 0.25 ) self.assertEqual(str(exception), - "Could not find price for performance storage space") + "Could not find price for endurance storage space") - def test_find_saas_perform_space_price_category_not_found(self): + def test_find_saas_endurance_space_price_no_capacity_maximum(self): package = { 'items': [ {'capacity': '0', - 'capacityMaximum': '999', - 'capacityMinimum': '500', - 'itemCategory': {'categoryCode': 'performance_storage_space'}, - 'keyName': '500_999_GBS', - 'prices': [ - {'id': 189993, - 'categories': [ - {'categoryCode': 'invalid_category_noooo'} - ], - 'locationGroupId': ''} - ]} + 'capacityMinimum': '1', + 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB'} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_space_price, - package, 500 + storage_utils.find_saas_endurance_space_price, + package, 8000, 0.25 ) self.assertEqual(str(exception), - "Could not find price for performance storage space") + "Could not find price for endurance storage space") - def test_find_saas_perform_space_price(self): + def test_find_saas_endurance_space_price_no_capacity_minimum(self): package = { 'items': [ {'capacity': '0', - 'capacityMaximum': '999', - 'capacityMinimum': '500', - 'itemCategory': {'categoryCode': 'performance_storage_space'}, - 'keyName': '500_999_GBS', - 'prices': [ - {'id': 189993, - 'categories': [ - {'categoryCode': 'performance_storage_space'} - ], - 'locationGroupId': ''} - ]} + 'capacityMaximum': '12000', + 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB'} ]} - result = storage_utils.find_saas_perform_space_price( - package, 500) - - self.assertEqual({'id': 189993}, result) - - def test_find_saas_perform_iops_price_no_items_in_package(self): - package = { - 'items': []} - exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 500, 1700 + storage_utils.find_saas_endurance_space_price, + package, 8000, 0.25 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance storage space") - def test_find_saas_perform_iops_price_no_itemCategory(self): + def test_find_saas_endurance_space_price_size_below_capacity(self): package = { 'items': [ - {'capacity': '0'} + {'capacity': '0', + 'capacityMaximum': '12000', + 'capacityMinimum': '1', + 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB'} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 500, 1700 + storage_utils.find_saas_endurance_space_price, + package, 0, 0.25 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance storage space") - def test_find_saas_perform_iops_price_no_itemCategory_code(self): + def test_find_saas_endurance_space_price_size_above_capacity(self): package = { 'items': [ {'capacity': '0', - 'itemCategory': {}} + 'capacityMaximum': '12000', + 'capacityMinimum': '1', + 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB'} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 500, 1700 + storage_utils.find_saas_endurance_space_price, + package, 12001, 0.25 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance storage space") - def test_find_saas_perform_iops_price_no_matching_itemCategory(self): + def test_find_saas_endurance_space_price_no_prices_in_items(self): package = { 'items': [ {'capacity': '0', - 'itemCategory': {'categoryCode': 'invalid_category_noooo'}} + 'capacityMaximum': '12000', + 'capacityMinimum': '1', + 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB', + 'prices': []} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 500, 1700 + storage_utils.find_saas_endurance_space_price, + package, 8000, 0.25 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance storage space") - def test_find_saas_perform_iops_price_no_capacity_maximum(self): + def test_find_saas_endurance_space_price_empty_location_not_found(self): package = { 'items': [ {'capacity': '0', - 'capacityMinimum': '100', - 'itemCategory': {'categoryCode': 'performance_storage_iops'}} + 'capacityMaximum': '12000', + 'capacityMinimum': '1', + 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB', + 'prices': [ + {'id': 192103, + 'categories': [ + {'categoryCode': 'performance_storage_space'} + ], + 'locationGroupId': '77777777'} + ]} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 500, 1700 + storage_utils.find_saas_endurance_space_price, + package, 8000, 0.25 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance storage space") - def test_find_saas_perform_iops_price_no_capacity_minimum(self): + def test_find_saas_endurance_space_price_category_not_found(self): package = { 'items': [ {'capacity': '0', - 'capacityMaximum': '10000', - 'itemCategory': {'categoryCode': 'performance_storage_iops'}} + 'capacityMaximum': '12000', + 'capacityMinimum': '1', + 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB', + 'prices': [ + {'id': 192103, + 'categories': [ + {'categoryCode': 'invalid_category_noooo'} + ], + 'locationGroupId': ''} + ]} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 500, 1700 + storage_utils.find_saas_endurance_space_price, + package, 8000, 0.25 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance storage space") - def test_find_saas_perform_iops_price_iops_below_capacity(self): + def test_find_saas_endurance_space_price(self): package = { 'items': [ {'capacity': '0', - 'capacityMaximum': '10000', - 'capacityMinimum': '100', - 'itemCategory': {'categoryCode': 'performance_storage_iops'}} + 'capacityMaximum': '12000', + 'capacityMinimum': '1', + 'keyName': 'STORAGE_SPACE_FOR_0_25_IOPS_PER_GB', + 'prices': [ + {'id': 192103, + 'categories': [ + {'categoryCode': 'performance_storage_space'} + ], + 'locationGroupId': ''} + ]} ]} + result = storage_utils.find_saas_endurance_space_price( + package, 8000, 0.25) + + self.assertEqual({'id': 192103}, result) + + # --------------------------------------------------------------------- + # Tests for find_saas_endurance_tier_price() + # --------------------------------------------------------------------- + def test_find_saas_endurance_tier_price_no_items_in_package(self): + package = { + 'items': []} + exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 500, 99 + storage_utils.find_saas_endurance_tier_price, + package, 2 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance tier level") - def test_find_saas_perform_iops_price_iops_above_capacity(self): + def test_find_saas_endurance_tier_price_no_itemCategory(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '10000', - 'capacityMinimum': '100', - 'itemCategory': {'categoryCode': 'performance_storage_iops'}} + {'capacity': '200'} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 500, 10001 + storage_utils.find_saas_endurance_tier_price, + package, 2 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance tier level") - def test_find_saas_perform_iops_price_no_prices_in_items(self): + def test_find_saas_endurance_tier_price_no_itemCategory_code(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '10000', - 'capacityMinimum': '100', - 'itemCategory': {'categoryCode': 'performance_storage_iops'}, - 'prices': []} + {'capacity': '200', + 'itemCategory': {}} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 500, 1700 + storage_utils.find_saas_endurance_tier_price, + package, 2 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance tier level") - def test_find_saas_perform_iops_price_empty_location_not_found(self): + def test_find_saas_endurance_tier_price_no_matching_itemCategory(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '10000', - 'capacityMinimum': '100', - 'itemCategory': {'categoryCode': 'performance_storage_iops'}, - 'prices': [ - {'capacityRestrictionMaximum': '999', - 'capacityRestrictionMinimum': '500', - 'capacityRestrictionType': 'STORAGE_SPACE', - 'categories': [ - {'categoryCode': 'performance_storage_iops'} - ], - 'id': 190053, - 'locationGroupId': '77777777'} - ]} + {'capacity': '200', + 'itemCategory': {'categoryCode': 'invalid_category_noooo'}} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 500, 1700 + storage_utils.find_saas_endurance_tier_price, + package, 2 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance tier level") - def test_find_saas_perform_iops_price_category_not_found(self): + def test_find_saas_endurance_tier_price_no_matching_capacity(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '10000', - 'capacityMinimum': '100', - 'itemCategory': {'categoryCode': 'performance_storage_iops'}, - 'prices': [ - {'capacityRestrictionMaximum': '999', - 'capacityRestrictionMinimum': '500', - 'capacityRestrictionType': 'STORAGE_SPACE', - 'categories': [ - {'categoryCode': 'invalid_category_noooo'} - ], - 'id': 190053, - 'locationGroupId': ''} - ]} + {'capacity': '200', + 'itemCategory': {'categoryCode': 'storage_tier_level'}} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 500, 1700 + storage_utils.find_saas_endurance_tier_price, + package, 10 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance tier level") - def test_find_saas_perform_iops_price_wrong_capacity_restriction(self): + def test_find_saas_endurance_tier_price_no_prices_in_items(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '10000', - 'capacityMinimum': '100', - 'itemCategory': {'categoryCode': 'performance_storage_iops'}, - 'prices': [ - {'capacityRestrictionMaximum': '999', - 'capacityRestrictionMinimum': '500', - 'capacityRestrictionType': 'NOT_THE_CORRECT_TYPE', - 'categories': [ - {'categoryCode': 'performance_storage_iops'} - ], - 'id': 190053, - 'locationGroupId': ''} - ]} + {'capacity': '200', + 'itemCategory': {'categoryCode': 'storage_tier_level'}, + 'prices': []} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 500, 1700 + storage_utils.find_saas_endurance_tier_price, + package, 2 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance tier level") - def test_find_saas_perform_iops_price_size_below_capacity(self): + def test_find_saas_endurance_tier_price_empty_location_not_found(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '10000', - 'capacityMinimum': '100', - 'itemCategory': {'categoryCode': 'performance_storage_iops'}, + {'capacity': '200', + 'itemCategory': {'categoryCode': 'storage_tier_level'}, 'prices': [ - {'capacityRestrictionMaximum': '999', - 'capacityRestrictionMinimum': '500', - 'capacityRestrictionType': 'STORAGE_SPACE', + {'id': 193373, 'categories': [ - {'categoryCode': 'performance_storage_iops'} + {'categoryCode': 'storage_tier_level'} ], - 'id': 190053, - 'locationGroupId': ''} + 'locationGroupId': '77777777'} ]} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 499, 1700 + storage_utils.find_saas_endurance_tier_price, + package, 2 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance tier level") - def test_find_saas_perform_iops_price_size_above_capacity(self): + def test_find_saas_endurance_tier_price_category_not_found(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '10000', - 'capacityMinimum': '100', - 'itemCategory': {'categoryCode': 'performance_storage_iops'}, + {'capacity': '200', + 'itemCategory': {'categoryCode': 'storage_tier_level'}, 'prices': [ - {'capacityRestrictionMaximum': '999', - 'capacityRestrictionMinimum': '500', - 'capacityRestrictionType': 'STORAGE_SPACE', + {'id': 193373, 'categories': [ - {'categoryCode': 'performance_storage_iops'} + {'categoryCode': 'invalid_category_noooo'} ], - 'id': 190053, 'locationGroupId': ''} ]} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_perform_iops_price, - package, 1000, 1700 + storage_utils.find_saas_endurance_tier_price, + package, 2 ) self.assertEqual(str(exception), - "Could not find price for iops for the given volume") + "Could not find price for endurance tier level") - def test_find_saas_perform_iops_price(self): + def test_find_saas_endurance_tier_price(self): package = { 'items': [ - {'capacity': '0', - 'capacityMaximum': '10000', - 'capacityMinimum': '100', - 'itemCategory': {'categoryCode': 'performance_storage_iops'}, + {'capacity': '200', + 'itemCategory': {'categoryCode': 'storage_tier_level'}, 'prices': [ - {'capacityRestrictionMaximum': '999', - 'capacityRestrictionMinimum': '500', - 'capacityRestrictionType': 'STORAGE_SPACE', + {'id': 193373, 'categories': [ - {'categoryCode': 'performance_storage_iops'} + {'categoryCode': 'storage_tier_level'} ], - 'id': 190053, 'locationGroupId': ''} ]} ]} - result = storage_utils.find_saas_perform_iops_price( - package, 500, 1700) + result = storage_utils.find_saas_endurance_tier_price( + package, 2) - self.assertEqual({'id': 190053}, result) + self.assertEqual({'id': 193373}, result) - def test_find_saas_snapshot_space_price_no_items_in_package(self): + # --------------------------------------------------------------------- + # Tests for find_saas_perform_space_price() + # --------------------------------------------------------------------- + def test_find_saas_perform_space_price_no_items_in_package(self): package = { 'items': []} exception = self.assertRaises( ValueError, - storage_utils.find_saas_snapshot_space_price, - package, 10, iops=2100 + storage_utils.find_saas_perform_space_price, + package, 500 ) self.assertEqual(str(exception), - "Could not find price for snapshot space") + "Could not find price for performance storage space") - def test_find_saas_snapshot_space_price_no_matching_capacity(self): + def test_find_saas_perform_space_price_no_itemCategory(self): package = { 'items': [ - {'capacity': '-1'} + {'capacity': '0'} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_snapshot_space_price, - package, 10, iops=2100 + storage_utils.find_saas_perform_space_price, + package, 500 ) self.assertEqual(str(exception), - "Could not find price for snapshot space") + "Could not find price for performance storage space") - def test_find_saas_snapshot_space_price_no_prices_in_items(self): + def test_find_saas_perform_space_price_no_itemCategory_code(self): package = { 'items': [ - {'capacity': '10', - 'prices': []} + {'capacity': '0', + 'itemCategory': {}} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_snapshot_space_price, - package, 10, iops=2100 + storage_utils.find_saas_perform_space_price, + package, 500 ) self.assertEqual(str(exception), - "Could not find price for snapshot space") + "Could not find price for performance storage space") - def test_find_saas_snapshot_space_price_empty_location_not_found(self): + def test_find_saas_perform_space_price_no_matching_itemCategory(self): package = { 'items': [ - {'capacity': '10', - 'prices': [ - {'capacityRestrictionMaximum': '48000', - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionType': 'IOPS', - 'categories': [ - {'categoryCode': 'storage_snapshot_space'} - ], - 'id': 191193, - 'locationGroupId': '77777777'} - ]} + {'capacity': '0', + 'itemCategory': {'categoryCode': 'invalid_category_noooo'}} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_snapshot_space_price, - package, 10, iops=2100 + storage_utils.find_saas_perform_space_price, + package, 500 ) self.assertEqual(str(exception), - "Could not find price for snapshot space") + "Could not find price for performance storage space") - def test_find_saas_snapshot_space_price_wrong_capacity_restriction(self): + def test_find_saas_perform_space_price_no_capacity_maximum(self): package = { 'items': [ - {'capacity': '10', - 'prices': [ - {'capacityRestrictionMaximum': '48000', - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionType': 'NOT_THE_CORRECT_CATEGORY', - 'categories': [ - {'categoryCode': 'storage_snapshot_space'} - ], - 'id': 191193, - 'locationGroupId': ''} - ]} + {'capacity': '0', + 'capacityMinimum': '500', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': '500_999_GBS'} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_snapshot_space_price, - package, 10, iops=2100 + storage_utils.find_saas_perform_space_price, + package, 500 ) self.assertEqual(str(exception), - "Could not find price for snapshot space") + "Could not find price for performance storage space") - def test_find_saas_snapshot_space_price_target_value_below_capacity(self): + def test_find_saas_perform_space_price_no_capacity_minimum(self): package = { 'items': [ - {'capacity': '10', - 'prices': [ - {'capacityRestrictionMaximum': '48000', - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionType': 'IOPS', - 'categories': [ - {'categoryCode': 'storage_snapshot_space'} - ], - 'id': 191193, - 'locationGroupId': ''} - ]} + {'capacity': '0', + 'capacityMaximum': '999', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': '500_999_GBS'} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_snapshot_space_price, - package, 10, iops=99 + storage_utils.find_saas_perform_space_price, + package, 500 ) self.assertEqual(str(exception), - "Could not find price for snapshot space") + "Could not find price for performance storage space") - def test_find_saas_snapshot_space_price_target_value_above_capacity(self): + def test_find_saas_perform_space_price_size_below_capacity(self): package = { 'items': [ - {'capacity': '10', - 'prices': [ - {'capacityRestrictionMaximum': '48000', - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionType': 'IOPS', - 'categories': [ - {'categoryCode': 'storage_snapshot_space'} - ], - 'id': 191193, - 'locationGroupId': ''} - ]} + {'capacity': '0', + 'capacityMaximum': '999', + 'capacityMinimum': '500', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': '500_999_GBS'} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_snapshot_space_price, - package, 10, iops=48001 + storage_utils.find_saas_perform_space_price, + package, 499 ) self.assertEqual(str(exception), - "Could not find price for snapshot space") + "Could not find price for performance storage space") - def test_find_saas_snapshot_space_price_category_not_found(self): + def test_find_saas_perform_space_price_size_above_capacity(self): package = { 'items': [ - {'capacity': '10', + {'capacity': '0', + 'capacityMaximum': '999', + 'capacityMinimum': '500', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': '500_999_GBS'} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_space_price, + package, 1000 + ) + + self.assertEqual(str(exception), + "Could not find price for performance storage space") + + def test_find_saas_perform_space_price_no_matching_keyname(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMaximum': '999', + 'capacityMinimum': '500', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': 'NOT_THE_CORRECT_KEYNAME'} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_space_price, + package, 500 + ) + + self.assertEqual(str(exception), + "Could not find price for performance storage space") + + def test_find_saas_perform_space_price_no_prices_in_items(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMaximum': '999', + 'capacityMinimum': '500', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': '500_999_GBS', + 'prices': []} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_space_price, + package, 500 + ) + + self.assertEqual(str(exception), + "Could not find price for performance storage space") + + def test_find_saas_perform_space_price_empty_location_not_found(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMaximum': '999', + 'capacityMinimum': '500', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': '500_999_GBS', 'prices': [ - {'capacityRestrictionMaximum': '48000', - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionType': 'IOPS', + {'id': 189993, 'categories': [ - {'categoryCode': 'invalid_category_noooooooo'} + {'categoryCode': 'performance_storage_space'} ], - 'id': 191193, - 'locationGroupId': ''} + 'locationGroupId': '77777777'} ]} ]} exception = self.assertRaises( ValueError, - storage_utils.find_saas_snapshot_space_price, - package, 10, iops=2100 + storage_utils.find_saas_perform_space_price, + package, 500 ) self.assertEqual(str(exception), - "Could not find price for snapshot space") + "Could not find price for performance storage space") - def test_find_saas_snapshot_space_price_with_iops(self): + def test_find_saas_perform_space_price_category_not_found(self): package = { 'items': [ - {'capacity': '10', + {'capacity': '0', + 'capacityMaximum': '999', + 'capacityMinimum': '500', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': '500_999_GBS', 'prices': [ - {'capacityRestrictionMaximum': '48000', - 'capacityRestrictionMinimum': '100', - 'capacityRestrictionType': 'IOPS', + {'id': 189993, 'categories': [ - {'categoryCode': 'storage_snapshot_space'} + {'categoryCode': 'invalid_category_noooo'} ], - 'id': 191193, 'locationGroupId': ''} ]} ]} - result = storage_utils.find_saas_snapshot_space_price( - package, 10, iops=2100) + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_space_price, + package, 500 + ) - self.assertEqual({'id': 191193}, result) + self.assertEqual(str(exception), + "Could not find price for performance storage space") - def test_find_saas_snapshot_space_price_with_tier_level(self): + def test_find_saas_perform_space_price(self): package = { 'items': [ - {'capacity': '10', + {'capacity': '0', + 'capacityMaximum': '999', + 'capacityMinimum': '500', + 'itemCategory': {'categoryCode': 'performance_storage_space'}, + 'keyName': '500_999_GBS', 'prices': [ - {'capacityRestrictionMaximum': '200', - 'capacityRestrictionMinimum': '200', - 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + {'id': 189993, 'categories': [ - {'categoryCode': 'storage_snapshot_space'} + {'categoryCode': 'performance_storage_space'} ], - 'id': 193613, 'locationGroupId': ''} ]} ]} - result = storage_utils.find_saas_snapshot_space_price( - package, 10, tier_level=2) - - self.assertEqual({'id': 193613}, result) + result = storage_utils.find_saas_perform_space_price( + package, 500) - def test_prep_duplicate_order_origin_volume_cancelled(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') - mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + self.assertEqual({'id': 189993}, result) - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME - prev_billing_item = mock_volume['billingItem'] - del mock_volume['billingItem'] + # --------------------------------------------------------------------- + # Tests for find_saas_perform_iops_price() + # --------------------------------------------------------------------- + def test_find_saas_perform_iops_price_no_items_in_package(self): + package = { + 'items': []} exception = self.assertRaises( - exceptions.SoftLayerError, - storage_utils.prepare_duplicate_order_object, - self.block, mock_volume, None, None, None, None, 'block' + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 500, 1700 ) self.assertEqual(str(exception), - "The origin volume has been cancelled; " - "unable to order duplicate volume") + "Could not find price for iops for the given volume") - mock_volume['billingItem'] = prev_billing_item + def test_find_saas_perform_iops_price_no_itemCategory(self): + package = { + 'items': [ + {'capacity': '0'} + ]} - def test_prep_duplicate_order_origin_snapshot_capacity_not_found(self): + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 500, 1700 + ) + + self.assertEqual(str(exception), + "Could not find price for iops for the given volume") + + def test_find_saas_perform_iops_price_no_itemCategory_code(self): + package = { + 'items': [ + {'capacity': '0', + 'itemCategory': {}} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 500, 1700 + ) + + self.assertEqual(str(exception), + "Could not find price for iops for the given volume") + + def test_find_saas_perform_iops_price_no_matching_itemCategory(self): + package = { + 'items': [ + {'capacity': '0', + 'itemCategory': {'categoryCode': 'invalid_category_noooo'}} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 500, 1700 + ) + + self.assertEqual(str(exception), + "Could not find price for iops for the given volume") + + def test_find_saas_perform_iops_price_no_capacity_maximum(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMinimum': '100', + 'itemCategory': {'categoryCode': 'performance_storage_iops'}} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 500, 1700 + ) + + self.assertEqual(str(exception), + "Could not find price for iops for the given volume") + + def test_find_saas_perform_iops_price_no_capacity_minimum(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMaximum': '10000', + 'itemCategory': {'categoryCode': 'performance_storage_iops'}} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 500, 1700 + ) + + self.assertEqual(str(exception), + "Could not find price for iops for the given volume") + + def test_find_saas_perform_iops_price_iops_below_capacity(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMaximum': '10000', + 'capacityMinimum': '100', + 'itemCategory': {'categoryCode': 'performance_storage_iops'}} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 500, 99 + ) + + self.assertEqual(str(exception), + "Could not find price for iops for the given volume") + + def test_find_saas_perform_iops_price_iops_above_capacity(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMaximum': '10000', + 'capacityMinimum': '100', + 'itemCategory': {'categoryCode': 'performance_storage_iops'}} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 500, 10001 + ) + + self.assertEqual(str(exception), + "Could not find price for iops for the given volume") + + def test_find_saas_perform_iops_price_no_prices_in_items(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMaximum': '10000', + 'capacityMinimum': '100', + 'itemCategory': {'categoryCode': 'performance_storage_iops'}, + 'prices': []} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 500, 1700 + ) + + self.assertEqual(str(exception), + "Could not find price for iops for the given volume") + + def test_find_saas_perform_iops_price_empty_location_not_found(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMaximum': '10000', + 'capacityMinimum': '100', + 'itemCategory': {'categoryCode': 'performance_storage_iops'}, + 'prices': [ + {'capacityRestrictionMaximum': '999', + 'capacityRestrictionMinimum': '500', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 190053, + 'locationGroupId': '77777777'} + ]} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 500, 1700 + ) + + self.assertEqual(str(exception), + "Could not find price for iops for the given volume") + + def test_find_saas_perform_iops_price_category_not_found(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMaximum': '10000', + 'capacityMinimum': '100', + 'itemCategory': {'categoryCode': 'performance_storage_iops'}, + 'prices': [ + {'capacityRestrictionMaximum': '999', + 'capacityRestrictionMinimum': '500', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'invalid_category_noooo'} + ], + 'id': 190053, + 'locationGroupId': ''} + ]} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 500, 1700 + ) + + self.assertEqual(str(exception), + "Could not find price for iops for the given volume") + + def test_find_saas_perform_iops_price_wrong_capacity_restriction(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMaximum': '10000', + 'capacityMinimum': '100', + 'itemCategory': {'categoryCode': 'performance_storage_iops'}, + 'prices': [ + {'capacityRestrictionMaximum': '999', + 'capacityRestrictionMinimum': '500', + 'capacityRestrictionType': 'NOT_THE_CORRECT_TYPE', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 190053, + 'locationGroupId': ''} + ]} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 500, 1700 + ) + + self.assertEqual(str(exception), + "Could not find price for iops for the given volume") + + def test_find_saas_perform_iops_price_size_below_capacity(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMaximum': '10000', + 'capacityMinimum': '100', + 'itemCategory': {'categoryCode': 'performance_storage_iops'}, + 'prices': [ + {'capacityRestrictionMaximum': '999', + 'capacityRestrictionMinimum': '500', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 190053, + 'locationGroupId': ''} + ]} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 499, 1700 + ) + + self.assertEqual(str(exception), + "Could not find price for iops for the given volume") + + def test_find_saas_perform_iops_price_size_above_capacity(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMaximum': '10000', + 'capacityMinimum': '100', + 'itemCategory': {'categoryCode': 'performance_storage_iops'}, + 'prices': [ + {'capacityRestrictionMaximum': '999', + 'capacityRestrictionMinimum': '500', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 190053, + 'locationGroupId': ''} + ]} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_perform_iops_price, + package, 1000, 1700 + ) + + self.assertEqual(str(exception), + "Could not find price for iops for the given volume") + + def test_find_saas_perform_iops_price(self): + package = { + 'items': [ + {'capacity': '0', + 'capacityMaximum': '10000', + 'capacityMinimum': '100', + 'itemCategory': {'categoryCode': 'performance_storage_iops'}, + 'prices': [ + {'capacityRestrictionMaximum': '999', + 'capacityRestrictionMinimum': '500', + 'capacityRestrictionType': 'STORAGE_SPACE', + 'categories': [ + {'categoryCode': 'performance_storage_iops'} + ], + 'id': 190053, + 'locationGroupId': ''} + ]} + ]} + + result = storage_utils.find_saas_perform_iops_price( + package, 500, 1700) + + self.assertEqual({'id': 190053}, result) + + # --------------------------------------------------------------------- + # Tests for find_saas_snapshot_space_price() + # --------------------------------------------------------------------- + def test_find_saas_snapshot_space_price_no_items_in_package(self): + package = { + 'items': []} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_snapshot_space_price, + package, 10, iops=2100 + ) + + self.assertEqual(str(exception), + "Could not find price for snapshot space") + + def test_find_saas_snapshot_space_price_no_matching_capacity(self): + package = { + 'items': [ + {'capacity': '-1'} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_snapshot_space_price, + package, 10, iops=2100 + ) + + self.assertEqual(str(exception), + "Could not find price for snapshot space") + + def test_find_saas_snapshot_space_price_no_prices_in_items(self): + package = { + 'items': [ + {'capacity': '10', + 'prices': []} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_snapshot_space_price, + package, 10, iops=2100 + ) + + self.assertEqual(str(exception), + "Could not find price for snapshot space") + + def test_find_saas_snapshot_space_price_empty_location_not_found(self): + package = { + 'items': [ + {'capacity': '10', + 'prices': [ + {'capacityRestrictionMaximum': '48000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'IOPS', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 191193, + 'locationGroupId': '77777777'} + ]} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_snapshot_space_price, + package, 10, iops=2100 + ) + + self.assertEqual(str(exception), + "Could not find price for snapshot space") + + def test_find_saas_snapshot_space_price_wrong_capacity_restriction(self): + package = { + 'items': [ + {'capacity': '10', + 'prices': [ + {'capacityRestrictionMaximum': '48000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'NOT_THE_CORRECT_CATEGORY', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 191193, + 'locationGroupId': ''} + ]} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_snapshot_space_price, + package, 10, iops=2100 + ) + + self.assertEqual(str(exception), + "Could not find price for snapshot space") + + def test_find_saas_snapshot_space_price_target_value_below_capacity(self): + package = { + 'items': [ + {'capacity': '10', + 'prices': [ + {'capacityRestrictionMaximum': '48000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'IOPS', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 191193, + 'locationGroupId': ''} + ]} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_snapshot_space_price, + package, 10, iops=99 + ) + + self.assertEqual(str(exception), + "Could not find price for snapshot space") + + def test_find_saas_snapshot_space_price_target_value_above_capacity(self): + package = { + 'items': [ + {'capacity': '10', + 'prices': [ + {'capacityRestrictionMaximum': '48000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'IOPS', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 191193, + 'locationGroupId': ''} + ]} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_snapshot_space_price, + package, 10, iops=48001 + ) + + self.assertEqual(str(exception), + "Could not find price for snapshot space") + + def test_find_saas_snapshot_space_price_category_not_found(self): + package = { + 'items': [ + {'capacity': '10', + 'prices': [ + {'capacityRestrictionMaximum': '48000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'IOPS', + 'categories': [ + {'categoryCode': 'invalid_category_noooooooo'} + ], + 'id': 191193, + 'locationGroupId': ''} + ]} + ]} + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_snapshot_space_price, + package, 10, iops=2100 + ) + + self.assertEqual(str(exception), + "Could not find price for snapshot space") + + def test_find_saas_snapshot_space_price_with_iops(self): + package = { + 'items': [ + {'capacity': '10', + 'prices': [ + {'capacityRestrictionMaximum': '48000', + 'capacityRestrictionMinimum': '100', + 'capacityRestrictionType': 'IOPS', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 191193, + 'locationGroupId': ''} + ]} + ]} + + result = storage_utils.find_saas_snapshot_space_price( + package, 10, iops=2100) + + self.assertEqual({'id': 191193}, result) + + def test_find_saas_snapshot_space_price_with_tier_level(self): + package = { + 'items': [ + {'capacity': '10', + 'prices': [ + {'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'storage_snapshot_space'} + ], + 'id': 193613, + 'locationGroupId': ''} + ]} + ]} + + result = storage_utils.find_saas_snapshot_space_price( + package, 10, tier=2) + + self.assertEqual({'id': 193613}, result) + + # --------------------------------------------------------------------- + # Tests for find_saas_replication_price () + # --------------------------------------------------------------------- + def test_find_saas_replication_price_no_items_in_package(self): + package = { + 'items': [] + } + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_replication_price, + package, tier=2 + ) + + self.assertEqual( + "Could not find price for replicant volume", + str(exception) + ) + + def test_find_saas_replication_price_no_matching_key_name(self): + package = { + 'items': [ + {'keyName': 'THIS_IS_NOT_THE_ITEM_YOU_ARE_LOOKING_FOR'} + ] + } + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_replication_price, + package, tier=2 + ) + + self.assertEqual( + "Could not find price for replicant volume", + str(exception) + ) + + def test_find_saas_replication_price_no_prices_in_items(self): + package = { + 'items': [ + { + 'keyName': 'REPLICATION_FOR_TIERBASED_PERFORMANCE', + 'prices': [] + } + ] + } + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_replication_price, + package, tier=2 + ) + + self.assertEqual( + "Could not find price for replicant volume", + str(exception) + ) + + def test_find_saas_replication_price_empty_location_not_found(self): + package = { + 'items': [ + { + 'keyName': 'REPLICATION_FOR_TIERBASED_PERFORMANCE', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': + 'performance_storage_replication'} + ], + 'id': 194693, + 'locationGroupId': '77777777' + } + ] + } + ] + } + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_replication_price, + package, tier=2 + ) + + self.assertEqual( + "Could not find price for replicant volume", + str(exception) + ) + + def test_find_saas_replication_price_wrong_capacity_restriction(self): + package = { + 'items': [ + { + 'keyName': 'REPLICATION_FOR_TIERBASED_PERFORMANCE', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'WRONG_TYPE_WOAH', + 'categories': [ + {'categoryCode': + 'performance_storage_replication'} + ], + 'id': 194693, + 'locationGroupId': '' + } + ] + } + ] + } + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_replication_price, + package, tier=2 + ) + + self.assertEqual( + "Could not find price for replicant volume", + str(exception) + ) + + def test_find_saas_replication_price_target_value_below_capacity(self): + package = { + 'items': [ + { + 'keyName': 'REPLICATION_FOR_TIERBASED_PERFORMANCE', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': + 'performance_storage_replication'} + ], + 'id': 194693, + 'locationGroupId': '' + } + ] + } + ] + } + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_replication_price, + package, tier=0.25 + ) + + self.assertEqual( + "Could not find price for replicant volume", + str(exception) + ) + + def test_find_saas_replication_price_target_value_above_capacity(self): + package = { + 'items': [ + { + 'keyName': 'REPLICATION_FOR_TIERBASED_PERFORMANCE', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': + 'performance_storage_replication'} + ], + 'id': 194693, + 'locationGroupId': '' + } + ] + } + ] + } + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_replication_price, + package, tier=4 + ) + + self.assertEqual( + "Could not find price for replicant volume", + str(exception) + ) + + def test_find_saas_replication_price_category_not_found(self): + package = { + 'items': [ + { + 'keyName': 'REPLICATION_FOR_TIERBASED_PERFORMANCE', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': 'invalid_category_oh_noooo'} + ], + 'id': 194693, + 'locationGroupId': '' + } + ] + } + ] + } + + exception = self.assertRaises( + ValueError, + storage_utils.find_saas_replication_price, + package, tier=2 + ) + + self.assertEqual( + "Could not find price for replicant volume", + str(exception) + ) + + def test_find_saas_replication_price_with_tier(self): + package = { + 'items': [ + { + 'keyName': 'REPLICATION_FOR_TIERBASED_PERFORMANCE', + 'prices': [ + { + 'capacityRestrictionMaximum': '200', + 'capacityRestrictionMinimum': '200', + 'capacityRestrictionType': 'STORAGE_TIER_LEVEL', + 'categories': [ + {'categoryCode': + 'performance_storage_replication'} + ], + 'id': 194693, + 'locationGroupId': '' + } + ] + } + ] + } + + result = storage_utils.find_saas_replication_price( + package, tier=2 + ) + + self.assertEqual({'id': 194693}, result) + + def test_find_saas_replication_price_with_iops(self): + package = { + 'items': [ + { + 'keyName': 'REPLICATION_FOR_IOPSBASED_PERFORMANCE', + 'prices': [ + { + 'capacityRestrictionMaximum': '48000', + 'capacityRestrictionMinimum': '1', + 'capacityRestrictionType': 'IOPS', + 'categories': [ + {'categoryCode': + 'performance_storage_replication'} + ], + 'id': 192033, + 'locationGroupId': '' + } + ] + } + ] + } + + result = storage_utils.find_saas_replication_price( + package, iops=800 + ) + + self.assertEqual({'id': 192033}, result) + + # --------------------------------------------------------------------- + # Tests for find_snapshot_schedule_id() + # --------------------------------------------------------------------- + def test_find_snapshot_schedule_id_no_schedules(self): + volume = { + 'schedules': [] + } + + exception = self.assertRaises( + ValueError, + storage_utils.find_snapshot_schedule_id, + volume, 'SNAPSHOT_WEEKLY' + ) + + self.assertEqual( + "The given snapshot schedule ID was not found for " + "the given storage volume", + str(exception) + ) + + def test_find_snapshot_schedule_id_no_type_in_schedule(self): + volume = { + 'schedules': [ + {'id': 888} + ] + } + + exception = self.assertRaises( + ValueError, + storage_utils.find_snapshot_schedule_id, + volume, 'SNAPSHOT_WEEKLY' + ) + + self.assertEqual( + "The given snapshot schedule ID was not found for " + "the given storage volume", + str(exception) + ) + + def test_find_snapshot_schedule_id_no_keyname_in_schedule_type(self): + volume = { + 'schedules': [ + { + 'id': 888, + 'type': {} + } + ] + } + + exception = self.assertRaises( + ValueError, + storage_utils.find_snapshot_schedule_id, + volume, 'SNAPSHOT_WEEKLY' + ) + + self.assertEqual( + "The given snapshot schedule ID was not found for " + "the given storage volume", + str(exception) + ) + + def test_find_snapshot_schedule_id_no_matching_keyname(self): + volume = { + 'schedules': [ + { + 'id': 888, + 'type': {'keyname': 'SNAPSHOT_DAILY'} + } + ] + } + + exception = self.assertRaises( + ValueError, + storage_utils.find_snapshot_schedule_id, + volume, 'SNAPSHOT_WEEKLY' + ) + + self.assertEqual( + "The given snapshot schedule ID was not found for " + "the given storage volume", + str(exception) + ) + + def test_find_snapshot_schedule_id(self): + volume = { + 'schedules': [ + { + 'id': 888, + 'type': {'keyname': 'SNAPSHOT_DAILY'} + }, { + 'id': 999, + 'type': {'keyname': 'SNAPSHOT_WEEKLY'} + } + ] + } + + result = storage_utils.find_snapshot_schedule_id( + volume, 'SNAPSHOT_WEEKLY' + ) + + self.assertEqual(999, result) + + # --------------------------------------------------------------------- + # Tests for prepare_snapshot_order_object() + # --------------------------------------------------------------------- + def test_prep_snapshot_order_billing_item_cancelled(self): + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_billing_item = mock_volume['billingItem'] + del mock_volume['billingItem'] + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_snapshot_order_object, + self.block, mock_volume, 10, None, False + ) + + self.assertEqual( + "This volume has been cancelled; unable to order snapshot space", + str(exception) + ) + + mock_volume['billingItem'] = prev_billing_item + + def test_prep_snapshot_order_invalid_billing_item_category_code(self): + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_billing_item_category = mock_volume['billingItem']['categoryCode'] + mock_volume['billingItem']['categoryCode'] = 'invalid_type_ninja_cat' + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_snapshot_order_object, + self.block, mock_volume, 10, None, False + ) + + self.assertEqual( + "Snapshot space cannot be ordered for a primary volume with a " + "billing item category code of 'invalid_type_ninja_cat'", + str(exception) + ) + + mock_volume['billingItem']['categoryCode'] = prev_billing_item_category + + def test_prep_snapshot_order_saas_endurance_tier_is_not_none(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_Enterprise_SnapshotSpace', + 'packageId': 759, + 'prices': [{'id': 193613}], + 'quantity': 1, + 'location': 449500, + 'volumeId': 102 + } + + result = storage_utils.prepare_snapshot_order_object( + self.block, mock_volume, 10, 2, False + ) + + self.assertEqual(expected_object, result) + + def test_prep_snapshot_order_saas_endurance_upgrade(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_Enterprise_SnapshotSpace_Upgrade', + 'packageId': 759, + 'prices': [{'id': 193853}], + 'quantity': 1, + 'location': 449500, + 'volumeId': 102 + } + + result = storage_utils.prepare_snapshot_order_object( + self.block, mock_volume, 20, None, True + ) + + self.assertEqual(expected_object, result) + + def test_prep_snapshot_order_saas_performance_volume_below_staas_v2(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type_keyname = mock_volume['storageType']['keyName'] + prev_staas_version = mock_volume['staasVersion'] + mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' + mock_volume['staasVersion'] = '1' + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_snapshot_order_object, + self.block, mock_volume, 10, None, False + ) + + self.assertEqual( + "Snapshot space cannot be ordered for this performance " + "volume since it does not support Encryption at Rest.", + str(exception) + ) + + mock_volume['storageType']['keyName'] = prev_storage_type_keyname + mock_volume['staasVersion'] = prev_staas_version + + def test_prep_snapshot_order_saas_performance(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type_keyname = mock_volume['storageType']['keyName'] + mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_Enterprise_SnapshotSpace', + 'packageId': 759, + 'prices': [{'id': 191193}], + 'quantity': 1, + 'location': 449500, + 'volumeId': 102 + } + + result = storage_utils.prepare_snapshot_order_object( + self.block, mock_volume, 10, None, False + ) + + self.assertEqual(expected_object, result) + + mock_volume['storageType']['keyName'] = prev_storage_type_keyname + + def test_prep_snapshot_order_saas_invalid_storage_type(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type_keyname = mock_volume['storageType']['keyName'] + mock_volume['storageType']['keyName'] = 'TASTY_PASTA_STORAGE' + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_snapshot_order_object, + self.block, mock_volume, 10, None, False + ) + + self.assertEqual( + "Storage volume does not have a valid storage type " + "(with an appropriate keyName to indicate the " + "volume is a PERFORMANCE or an ENDURANCE volume)", + str(exception) + ) + + mock_volume['storageType']['keyName'] = prev_storage_type_keyname + + def test_prep_snapshot_order_enterprise_tier_is_not_none(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [ + fixtures.SoftLayer_Product_Package.ENTERPRISE_PACKAGE + ] + + mock_volume = fixtures.SoftLayer_Network_Storage.getObject + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_Enterprise_SnapshotSpace', + 'packageId': 240, + 'prices': [{'id': 46160}], + 'quantity': 1, + 'location': 449500, + 'volumeId': 100 + } + + result = storage_utils.prepare_snapshot_order_object( + self.block, mock_volume, 10, 2, False + ) + + self.assertEqual(expected_object, result) + + def test_prep_snapshot_order_enterprise(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [ + fixtures.SoftLayer_Product_Package.ENTERPRISE_PACKAGE + ] + + mock_volume = fixtures.SoftLayer_Network_Storage.getObject + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_Enterprise_SnapshotSpace', + 'packageId': 240, + 'prices': [{'id': 45860}], + 'quantity': 1, + 'location': 449500, + 'volumeId': 100 + } + + result = storage_utils.prepare_snapshot_order_object( + self.block, mock_volume, 20, None, False + ) + + self.assertEqual(expected_object, result) + + # --------------------------------------------------------------------- + # Tests for prepare_volume_order_object() + # --------------------------------------------------------------------- + def test_prep_volume_order_invalid_storage_type(self): + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_volume_order_object, + self.block, 'saxophone_cat', 'dal09', 1000, + None, 4, None, 'enterprise', 'block' + ) + + self.assertEqual( + "Volume storage type must be either performance or endurance", + str(exception) + ) + + def test_prep_volume_order_invalid_location(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [] + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_volume_order_object, + self.block, 'endurance', 'hoth01', 1000, + None, 4, None, 'enterprise', 'block' + ) + + self.assertEqual( + "Invalid datacenter name specified. " + "Please provide the lower case short name (e.g.: dal09)", + str(exception) + ) + + def test_prep_volume_order_enterprise_offering_invalid_storage_type(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 29, 'name': 'dal09'}] + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_volume_order_object, + self.block, 'performance', 'dal09', 1000, + None, 4, None, 'enterprise', 'block' + ) + + self.assertEqual( + "The requested offering package, 'enterprise', is not " + "available for the 'performance' storage type.", + str(exception) + ) + + def test_prep_volume_order_performance_offering_invalid_storage_type(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 29, 'name': 'dal09'}] + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_volume_order_object, + self.block, 'endurance', 'dal09', 1000, + 800, None, None, 'performance', 'block' + ) + + self.assertEqual( + "The requested offering package, 'performance', is not " + "available for the 'endurance' storage type.", + str(exception) + ) + + def test_prep_volume_order_invalid_offering(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 29, 'name': 'dal09'}] + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_volume_order_object, + self.block, 'endurance', 'dal09', 1000, + None, 4, None, 'jazz_penguins', 'block' + ) + + self.assertEqual( + "The requested service offering package is not valid. " + "Please check the available options and try again.", + str(exception) + ) + + def test_prep_volume_order_saas_performance(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 29, 'name': 'dal09'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189453}, + {'id': 190113}, + {'id': 190173} + ], + 'quantity': 1, + 'location': 29, + 'volumeSize': 1000, + 'iops': 800 + } + + result = storage_utils.prepare_volume_order_object( + self.file, 'performance', 'dal09', 1000, + 800, None, None, 'storage_as_a_service', 'file' + ) + + self.assertEqual(expected_object, result) + + def test_prep_volume_order_saas_performance_with_snapshot(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 29, 'name': 'dal09'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189453}, + {'id': 190113}, + {'id': 190173}, + {'id': 191193} + ], + 'quantity': 1, + 'location': 29, + 'volumeSize': 1000, + 'iops': 800 + } + + result = storage_utils.prepare_volume_order_object( + self.file, 'performance', 'dal09', 1000, + 800, None, 10, 'storage_as_a_service', 'file' + ) + + self.assertEqual(expected_object, result) + + def test_prep_volume_order_saas_endurance(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 29, 'name': 'dal09'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189443}, + {'id': 194763}, + {'id': 194703} + ], + 'quantity': 1, + 'location': 29, + 'volumeSize': 1000 + } + + result = storage_utils.prepare_volume_order_object( + self.block, 'endurance', 'dal09', 1000, + None, 4, None, 'storage_as_a_service', 'block' + ) + + self.assertEqual(expected_object, result) + + def test_prep_volume_order_saas_endurance_with_snapshot(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 29, 'name': 'dal09'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189443}, + {'id': 194763}, + {'id': 194703}, + {'id': 194943} + ], + 'quantity': 1, + 'location': 29, + 'volumeSize': 1000 + } + + result = storage_utils.prepare_volume_order_object( + self.block, 'endurance', 'dal09', 1000, + None, 4, 10, 'storage_as_a_service', 'block' + ) + + self.assertEqual(expected_object, result) + + def test_prep_volume_order_perf_performance_block(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 29, 'name': 'dal09'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [ + fixtures.SoftLayer_Product_Package.PERFORMANCE_PACKAGE + ] + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_PerformanceStorage_Iscsi', + 'packageId': 222, + 'prices': [ + {'id': 40672}, + {'id': 40742}, + {'id': 41562} + ], + 'quantity': 1, + 'location': 29 + } + + result = storage_utils.prepare_volume_order_object( + self.block, 'performance', 'dal09', 1000, + 800, None, None, 'performance', 'block' + ) + + self.assertEqual(expected_object, result) + + def test_prep_volume_order_perf_performance_file(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 29, 'name': 'dal09'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [ + fixtures.SoftLayer_Product_Package.PERFORMANCE_PACKAGE + ] + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_PerformanceStorage_Nfs', + 'packageId': 222, + 'prices': [ + {'id': 40662}, + {'id': 40742}, + {'id': 41562} + ], + 'quantity': 1, + 'location': 29 + } + + result = storage_utils.prepare_volume_order_object( + self.file, 'performance', 'dal09', 1000, + 800, None, None, 'performance', 'file' + ) + + self.assertEqual(expected_object, result) + + def test_prep_volume_order_ent_endurance(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 29, 'name': 'dal09'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [ + fixtures.SoftLayer_Product_Package.ENTERPRISE_PACKAGE + ] + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_Enterprise', + 'packageId': 240, + 'prices': [ + {'id': 45058}, + {'id': 45108}, + {'id': 45318}, + {'id': 45088} + ], + 'quantity': 1, + 'location': 29 + } + + result = storage_utils.prepare_volume_order_object( + self.file, 'endurance', 'dal09', 1000, + None, 4, None, 'enterprise', 'file' + ) + + self.assertEqual(expected_object, result) + + def test_prep_volume_order_ent_endurance_with_snapshot(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 29, 'name': 'dal09'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [ + fixtures.SoftLayer_Product_Package.ENTERPRISE_PACKAGE + ] + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_Enterprise', + 'packageId': 240, + 'prices': [ + {'id': 45058}, + {'id': 45098}, + {'id': 45318}, + {'id': 45088}, + {'id': 46170} + ], + 'quantity': 1, + 'location': 29 + } + + result = storage_utils.prepare_volume_order_object( + self.block, 'endurance', 'dal09', 1000, + None, 4, 10, 'enterprise', 'block' + ) + + self.assertEqual(expected_object, result) + + # --------------------------------------------------------------------- + # Tests for prepare_replicant_order_object() + # --------------------------------------------------------------------- + def test_prep_replicant_order_volume_cancelled(self): + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_billing_item = mock_volume['billingItem'] + del mock_volume['billingItem'] + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_replicant_order_object, + self.block, 'WEEKLY', 'wdc04', None, mock_volume, 'block' + ) + + self.assertEqual( + 'This volume is set for cancellation; ' + 'unable to order replicant volume', + str(exception) + ) + + mock_volume['billingItem'] = prev_billing_item + + def test_prep_replicant_order_volume_cancellation_date_set(self): + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_cancellation_date = mock_volume['billingItem']['cancellationDate'] + mock_volume['billingItem']['cancellationDate'] = 'y2k, oh nooooo' + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_replicant_order_object, + self.block, 'WEEKLY', 'wdc04', None, mock_volume, 'block' + ) + + self.assertEqual( + 'This volume is set for cancellation; ' + 'unable to order replicant volume', + str(exception) + ) + + mock_volume['billingItem']['cancellationDate'] = prev_cancellation_date + + def test_prep_replicant_order_snapshot_space_cancelled(self): + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + snapshot_billing_item = mock_volume['billingItem']['activeChildren'][0] + prev_cancellation_date = snapshot_billing_item['cancellationDate'] + snapshot_billing_item['cancellationDate'] = 'daylight saving time, no!' + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_replicant_order_object, + self.block, 'WEEKLY', 'wdc04', None, mock_volume, 'block' + ) + + self.assertEqual( + 'The snapshot space for this volume is set for ' + 'cancellation; unable to order replicant volume', + str(exception) + ) + + snapshot_billing_item['cancellationDate'] = prev_cancellation_date + + def test_prep_replicant_order_invalid_location(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_replicant_order_object, + self.block, 'WEEKLY', 'hoth02', None, mock_volume, 'block' + ) + + self.assertEqual( + "Invalid datacenter name specified. " + "Please provide the lower case short name (e.g.: dal09)", + str(exception) + ) + + def test_prep_replicant_order_enterprise_offering_invalid_storage_type(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 51, 'name': 'wdc04'}] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_billing_item_category = mock_volume['billingItem']['categoryCode'] + mock_volume['billingItem']['categoryCode'] = 'invalid_type_ninja_cat' + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_replicant_order_object, + self.block, 'WEEKLY', 'wdc04', None, mock_volume, 'block' + ) + + self.assertEqual( + "A replicant volume cannot be ordered for a primary volume with a " + "billing item category code of 'invalid_type_ninja_cat'", + str(exception) + ) + + mock_volume['billingItem']['categoryCode'] = prev_billing_item_category + + def test_prep_replicant_order_snapshot_capacity_not_found(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 51, 'name': 'wdc04'}] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_snapshot_capacity = mock_volume['snapshotCapacityGb'] + del mock_volume['snapshotCapacityGb'] + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_replicant_order_object, + self.block, 'WEEKLY', 'wdc04', None, mock_volume, 'block' + ) + + self.assertEqual( + "Snapshot capacity not found for the given primary volume", + str(exception) + ) + + mock_volume['snapshotCapacityGb'] = prev_snapshot_capacity + + def test_prep_replicant_order_saas_endurance(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 51, 'name': 'wdc04'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189443}, + {'id': 193433}, + {'id': 193373}, + {'id': 193613}, + {'id': 194693} + ], + 'quantity': 1, + 'location': 51, + 'originVolumeId': 102, + 'originVolumeScheduleId': 978, + 'volumeSize': 500 + } + + result = storage_utils.prepare_replicant_order_object( + self.block, 'WEEKLY', 'wdc04', None, mock_volume, 'block' + ) + + self.assertEqual(expected_object, result) + + def test_prep_replicant_order_saas_endurance_tier_is_not_none(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 51, 'name': 'wdc04'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189443}, + {'id': 193433}, + {'id': 193373}, + {'id': 193613}, + {'id': 194693} + ], + 'quantity': 1, + 'location': 51, + 'originVolumeId': 102, + 'originVolumeScheduleId': 978, + 'volumeSize': 500 + } + + result = storage_utils.prepare_replicant_order_object( + self.block, 'WEEKLY', 'wdc04', 2, mock_volume, 'block' + ) + + self.assertEqual(expected_object, result) + + def test_prep_replicant_order_saas_performance_volume_below_staas_v2(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 51, 'name': 'wdc04'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type = mock_volume['storageType']['keyName'] + prev_has_encryption_at_rest_flag = mock_volume['hasEncryptionAtRest'] + mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' + mock_volume['hasEncryptionAtRest'] = 0 + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_replicant_order_object, + self.block, 'WEEKLY', 'wdc04', None, mock_volume, 'block' + ) + + self.assertEqual( + "A replica volume cannot be ordered for this performance " + "volume since it does not support Encryption at Rest.", + str(exception) + ) + + mock_volume['storageType']['keyName'] = prev_storage_type + mock_volume['hasEncryptionAtRest'] = prev_has_encryption_at_rest_flag + + def test_prep_replicant_order_saas_performance(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 51, 'name': 'wdc04'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type = mock_volume['storageType']['keyName'] + mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189443}, + {'id': 189993}, + {'id': 190053}, + {'id': 191193}, + {'id': 192033} + ], + 'quantity': 1, + 'location': 51, + 'originVolumeId': 102, + 'originVolumeScheduleId': 978, + 'volumeSize': 500, + 'iops': 1000 + } + + result = storage_utils.prepare_replicant_order_object( + self.block, 'WEEKLY', 'wdc04', None, mock_volume, 'block' + ) + + self.assertEqual(expected_object, result) + + mock_volume['storageType']['keyName'] = prev_storage_type + + def test_prep_replicant_order_saas_invalid_storage_type(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 51, 'name': 'wdc04'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_storage_type = mock_volume['storageType']['keyName'] + mock_volume['storageType']['keyName'] = 'CATS_LIKE_PIANO_MUSIC' + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_replicant_order_object, + self.block, 'WEEKLY', 'wdc04', None, mock_volume, 'block' + ) + + self.assertEqual( + "Storage volume does not have a valid storage type " + "(with an appropriate keyName to indicate the " + "volume is a PERFORMANCE or an ENDURANCE volume)", + str(exception) + ) + + mock_volume['storageType']['keyName'] = prev_storage_type + + def test_prep_replicant_order_ent_endurance(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 51, 'name': 'wdc04'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [ + fixtures.SoftLayer_Product_Package.ENTERPRISE_PACKAGE + ] + + mock_volume = fixtures.SoftLayer_Network_Storage.getObject + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_Enterprise', + 'packageId': 240, + 'prices': [ + {'id': 45058}, + {'id': 45098}, + {'id': 45128}, + {'id': 45078}, + {'id': 46160}, + {'id': 46659} + ], + 'quantity': 1, + 'location': 51, + 'originVolumeId': 100, + 'originVolumeScheduleId': 978 + } + + result = storage_utils.prepare_replicant_order_object( + self.block, 'WEEKLY', 'wdc04', None, mock_volume, 'block' + ) + + self.assertEqual(expected_object, result) + + def test_prep_replicant_order_ent_endurance_tier_is_not_none(self): + mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') + mock.return_value = [{'id': 51, 'name': 'wdc04'}] + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [ + fixtures.SoftLayer_Product_Package.ENTERPRISE_PACKAGE + ] + + mock_volume = fixtures.SoftLayer_Network_Storage.getObject + + expected_object = { + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_Enterprise', + 'packageId': 240, + 'prices': [ + {'id': 45058}, + {'id': 45098}, + {'id': 45128}, + {'id': 45078}, + {'id': 46160}, + {'id': 46659} + ], + 'quantity': 1, + 'location': 51, + 'originVolumeId': 100, + 'originVolumeScheduleId': 978 + } + + result = storage_utils.prepare_replicant_order_object( + self.block, 'WEEKLY', 'wdc04', 2, mock_volume, 'block' + ) + + self.assertEqual(expected_object, result) + + # --------------------------------------------------------------------- + # Tests for prepare_duplicate_order_object() + # --------------------------------------------------------------------- + def test_prep_duplicate_order_origin_volume_cancelled(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_billing_item = mock_volume['billingItem'] + del mock_volume['billingItem'] + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_duplicate_order_object, + self.block, mock_volume, None, None, None, None, 'block' + ) + + self.assertEqual(str(exception), + "The origin volume has been cancelled; " + "unable to order duplicate volume") + + mock_volume['billingItem'] = prev_billing_item + + def test_prep_duplicate_order_origin_snapshot_capacity_not_found(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_snapshot_capacity_gb = mock_volume['snapshotCapacityGb'] del mock_volume['snapshotCapacityGb'] @@ -1274,7 +3582,7 @@ def test_prep_duplicate_order_origin_volume_location_not_found(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_location = mock_volume['billingItem']['location'] del mock_volume['billingItem']['location'] @@ -1289,11 +3597,31 @@ def test_prep_duplicate_order_origin_volume_location_not_found(self): mock_volume['billingItem']['location'] = prev_location + def test_prep_duplicate_order_origin_volume_staas_version_below_v2(self): + mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') + mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] + + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + prev_staas_version = mock_volume['staasVersion'] + mock_volume['staasVersion'] = 1 + + exception = self.assertRaises( + exceptions.SoftLayerError, + storage_utils.prepare_duplicate_order_object, + self.block, mock_volume, None, None, None, None, 'block' + ) + + self.assertEqual("This volume cannot be duplicated since it " + "does not support Encryption at Rest.", + str(exception)) + + mock_volume['staasVersion'] = prev_staas_version + def test_prep_duplicate_order_origin_volume_capacity_not_found(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_capacity_gb = mock_volume['capacityGb'] mock_volume['capacityGb'] = None @@ -1311,7 +3639,7 @@ def test_prep_duplicate_order_origin_originalVolumeSize_empty_block(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_original_volume_size = mock_volume['originalVolumeSize'] del mock_volume['originalVolumeSize'] @@ -1342,7 +3670,7 @@ def test_prep_duplicate_order_size_too_small(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME exception = self.assertRaises( exceptions.SoftLayerError, @@ -1359,7 +3687,7 @@ def test_prep_duplicate_order_size_too_large_block(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME exception = self.assertRaises( exceptions.SoftLayerError, @@ -1381,7 +3709,7 @@ def test_prep_duplicate_order_performance_origin_iops_not_found(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] prev_provisioned_iops = mock_volume['provisionedIops'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_'\ @@ -1404,7 +3732,7 @@ def test_prep_duplicate_order_performance_iops_above_limit(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] prev_provisioned_iops = mock_volume['provisionedIops'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' @@ -1428,7 +3756,7 @@ def test_prep_duplicate_order_performance_iops_below_limit(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' @@ -1449,7 +3777,7 @@ def test_prep_duplicate_order_performance_use_default_origin_values(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_'\ 'STORAGE_REPLICANT' @@ -1482,7 +3810,7 @@ def test_prep_duplicate_order_performance_block(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' @@ -1514,7 +3842,7 @@ def test_prep_duplicate_order_performance_file(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' @@ -1546,7 +3874,7 @@ def test_prep_duplicate_order_endurance_origin_tier_not_found(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_tier_level = mock_volume['storageTierLevel'] prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageTierLevel'] = 'NINJA_PENGUINS' @@ -1569,7 +3897,7 @@ def test_prep_duplicate_order_endurance_tier_above_limit(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_tier_level = mock_volume['storageTierLevel'] mock_volume['storageTierLevel'] = 'LOW_INTENSITY_TIER' @@ -1590,7 +3918,7 @@ def test_prep_duplicate_order_endurance_tier_below_limit(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME exception = self.assertRaises( exceptions.SoftLayerError, @@ -1607,7 +3935,7 @@ def test_prep_duplicate_order_endurance_use_default_origin_values(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_'\ 'STORAGE_REPLICANT' @@ -1639,7 +3967,7 @@ def test_prep_duplicate_order_endurance_block(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME expected_object = { 'complexType': 'SoftLayer_Container_Product_Order_' @@ -1666,7 +3994,7 @@ def test_prep_duplicate_order_endurance_file(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' @@ -1697,7 +4025,7 @@ def test_prep_duplicate_order_invalid_origin_storage_type(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.DUPLICATABLE_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'NINJA_CATS' @@ -1710,6 +4038,6 @@ def test_prep_duplicate_order_invalid_origin_storage_type(self): self.assertEqual(str(exception), "Origin volume does not have a valid storage type " "(with an appropriate keyName to indicate the " - "volume is a PERFORMANCE or ENDURANCE volume)") + "volume is a PERFORMANCE or an ENDURANCE volume)") mock_volume['storageType']['keyName'] = prev_storage_type_keyname From e3b3d24b91bce4cc77287eeecef8a1edc6051478 Mon Sep 17 00:00:00 2001 From: David Pickle Date: Mon, 17 Jul 2017 16:10:16 -0500 Subject: [PATCH 2/4] Update code to address pull-request feedback --- SoftLayer/CLI/block/order.py | 6 ++---- SoftLayer/CLI/file/order.py | 6 ++---- SoftLayer/managers/block.py | 1 + SoftLayer/managers/file.py | 1 + 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/SoftLayer/CLI/block/order.py b/SoftLayer/CLI/block/order.py index cdcaeef0a..865a38e23 100644 --- a/SoftLayer/CLI/block/order.py +++ b/SoftLayer/CLI/block/order.py @@ -50,7 +50,8 @@ 'the size (in GB) of snapshot space to order') @click.option('--service-offering', help='The service offering package to use for placing ' - 'the order [optional, default is \'storage_as_a_service\'', + 'the order [optional, default is \'storage_as_a_service\']', + default='storage_as_a_service', type=click.Choice([ 'storage_as_a_service', 'enterprise', @@ -62,9 +63,6 @@ def cli(env, storage_type, size, iops, tier, os_type, block_manager = SoftLayer.BlockStorageManager(env.client) storage_type = storage_type.lower() - if service_offering is None: - service_offering = 'storage_as_a_service' - if storage_type == 'performance': if iops is None: raise exceptions.CLIAbort( diff --git a/SoftLayer/CLI/file/order.py b/SoftLayer/CLI/file/order.py index 8d3e77ad3..c9ba4abcd 100644 --- a/SoftLayer/CLI/file/order.py +++ b/SoftLayer/CLI/file/order.py @@ -38,7 +38,8 @@ 'the size (in GB) of snapshot space to order') @click.option('--service-offering', help='The service offering package to use for placing ' - 'the order [optional, default is \'storage_as_a_service\'', + 'the order [optional, default is \'storage_as_a_service\']', + default='storage_as_a_service', type=click.Choice([ 'storage_as_a_service', 'enterprise', @@ -50,9 +51,6 @@ def cli(env, storage_type, size, iops, tier, file_manager = SoftLayer.FileStorageManager(env.client) storage_type = storage_type.lower() - if service_offering is None: - service_offering = 'storage_as_a_service' - if storage_type == 'performance': if iops is None: raise exceptions.CLIAbort( diff --git a/SoftLayer/managers/block.py b/SoftLayer/managers/block.py index ecf48b33d..c71555160 100644 --- a/SoftLayer/managers/block.py +++ b/SoftLayer/managers/block.py @@ -319,6 +319,7 @@ def order_block_volume(self, storage_type, location, size, os_type, :param snapshot_size: The size of optional snapshot space, if snapshot space should also be ordered (None if not ordered) :param service_offering: Requested offering package to use in the order + ('storage_as_a_service', 'enterprise', or 'performance') """ order = storage_utils.prepare_volume_order_object( self, storage_type, location, size, iops, tier_level, diff --git a/SoftLayer/managers/file.py b/SoftLayer/managers/file.py index c3919cb9f..ca4b9ebc9 100644 --- a/SoftLayer/managers/file.py +++ b/SoftLayer/managers/file.py @@ -298,6 +298,7 @@ def order_file_volume(self, storage_type, location, size, :param snapshot_size: The size of optional snapshot space, if snapshot space should also be ordered (None if not ordered) :param service_offering: Requested offering package to use in the order + ('storage_as_a_service', 'enterprise', or 'performance') """ order = storage_utils.prepare_volume_order_object( self, storage_type, location, size, iops, tier_level, From 76be0819cd5bcffaf6228b8bd146aaa164b58d59 Mon Sep 17 00:00:00 2001 From: David Pickle Date: Wed, 19 Jul 2017 10:34:39 -0500 Subject: [PATCH 3/4] Address additional PR feedback; fix bug in price lookup function --- .../fixtures/SoftLayer_Network_Storage.py | 2 +- SoftLayer/managers/storage_utils.py | 2 + tests/managers/block_tests.py | 24 +++--- tests/managers/file_tests.py | 20 ++--- tests/managers/storage_utils_tests.py | 80 +++++++++---------- 5 files changed, 65 insertions(+), 63 deletions(-) diff --git a/SoftLayer/fixtures/SoftLayer_Network_Storage.py b/SoftLayer/fixtures/SoftLayer_Network_Storage.py index de71ddfd5..f8dfae898 100644 --- a/SoftLayer/fixtures/SoftLayer_Network_Storage.py +++ b/SoftLayer/fixtures/SoftLayer_Network_Storage.py @@ -1,4 +1,4 @@ -SAAS_TEST_VOLUME = { +STAAS_TEST_VOLUME = { 'accountId': 1234, 'activeTransactions': None, 'activeTransactionCount': 0, diff --git a/SoftLayer/managers/storage_utils.py b/SoftLayer/managers/storage_utils.py index 8c6bbc833..14ae573a7 100644 --- a/SoftLayer/managers/storage_utils.py +++ b/SoftLayer/managers/storage_utils.py @@ -278,6 +278,8 @@ def find_saas_endurance_space_price(package, size, tier_level): :param tier_level: The endurance tier for which a price is desired :return: Returns the price for the size and tier, or an error if not found """ + if tier_level != 0.25: + tier_level = int(tier_level) key_name = 'STORAGE_SPACE_FOR_{0}_IOPS_PER_GB'.format(tier_level) key_name = key_name.replace(".", "_") for item in package['items']: diff --git a/tests/managers/block_tests.py b/tests/managers/block_tests.py index aeaea906f..9b9e4a776 100644 --- a/tests/managers/block_tests.py +++ b/tests/managers/block_tests.py @@ -277,7 +277,7 @@ def test_order_block_volume_performance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -324,7 +324,7 @@ def test_order_block_volume_endurance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -437,7 +437,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'ENDURANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -469,7 +469,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -494,7 +494,7 @@ def test_order_block_snapshot_space(self): ) def test_order_block_replicant_os_type_not_found(self): - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_os_type = mock_volume['osType'] del mock_volume['osType'] mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -521,7 +521,7 @@ def test_order_block_replicant_performance_os_type_given(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -570,7 +570,7 @@ def test_order_block_replicant_endurance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -606,7 +606,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_os_type = mock_volume['osType'] del mock_volume['osType'] mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -627,7 +627,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -666,7 +666,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -712,7 +712,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume @@ -746,7 +746,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') mock.return_value = mock_volume diff --git a/tests/managers/file_tests.py b/tests/managers/file_tests.py index d81a6e14a..321d6cb45 100644 --- a/tests/managers/file_tests.py +++ b/tests/managers/file_tests.py @@ -354,7 +354,7 @@ def test_order_file_volume_performance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -399,7 +399,7 @@ def test_order_file_volume_endurance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -440,7 +440,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -472,7 +472,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -507,7 +507,7 @@ def test_order_file_replicant_performance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -550,7 +550,7 @@ def test_order_file_replicant_endurance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -589,7 +589,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -627,7 +627,7 @@ 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 = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -672,7 +672,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') @@ -709,7 +709,7 @@ 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_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') diff --git a/tests/managers/storage_utils_tests.py b/tests/managers/storage_utils_tests.py index cca34fcad..f07e21f2d 100644 --- a/tests/managers/storage_utils_tests.py +++ b/tests/managers/storage_utils_tests.py @@ -2672,7 +2672,7 @@ def test_find_snapshot_schedule_id(self): # Tests for prepare_snapshot_order_object() # --------------------------------------------------------------------- def test_prep_snapshot_order_billing_item_cancelled(self): - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_billing_item = mock_volume['billingItem'] del mock_volume['billingItem'] @@ -2690,7 +2690,7 @@ def test_prep_snapshot_order_billing_item_cancelled(self): mock_volume['billingItem'] = prev_billing_item def test_prep_snapshot_order_invalid_billing_item_category_code(self): - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_billing_item_category = mock_volume['billingItem']['categoryCode'] mock_volume['billingItem']['categoryCode'] = 'invalid_type_ninja_cat' @@ -2712,7 +2712,7 @@ def test_prep_snapshot_order_saas_endurance_tier_is_not_none(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME expected_object = { 'complexType': 'SoftLayer_Container_Product_Order_' @@ -2734,7 +2734,7 @@ def test_prep_snapshot_order_saas_endurance_upgrade(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME expected_object = { 'complexType': 'SoftLayer_Container_Product_Order_' @@ -2756,7 +2756,7 @@ def test_prep_snapshot_order_saas_performance_volume_below_staas_v2(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] prev_staas_version = mock_volume['staasVersion'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' @@ -2781,7 +2781,7 @@ def test_prep_snapshot_order_saas_performance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' @@ -2807,7 +2807,7 @@ def test_prep_snapshot_order_saas_invalid_storage_type(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'TASTY_PASTA_STORAGE' @@ -3193,7 +3193,7 @@ def test_prep_volume_order_ent_endurance_with_snapshot(self): # Tests for prepare_replicant_order_object() # --------------------------------------------------------------------- def test_prep_replicant_order_volume_cancelled(self): - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_billing_item = mock_volume['billingItem'] del mock_volume['billingItem'] @@ -3212,7 +3212,7 @@ def test_prep_replicant_order_volume_cancelled(self): mock_volume['billingItem'] = prev_billing_item def test_prep_replicant_order_volume_cancellation_date_set(self): - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_cancellation_date = mock_volume['billingItem']['cancellationDate'] mock_volume['billingItem']['cancellationDate'] = 'y2k, oh nooooo' @@ -3231,7 +3231,7 @@ def test_prep_replicant_order_volume_cancellation_date_set(self): mock_volume['billingItem']['cancellationDate'] = prev_cancellation_date def test_prep_replicant_order_snapshot_space_cancelled(self): - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME snapshot_billing_item = mock_volume['billingItem']['activeChildren'][0] prev_cancellation_date = snapshot_billing_item['cancellationDate'] snapshot_billing_item['cancellationDate'] = 'daylight saving time, no!' @@ -3254,7 +3254,7 @@ def test_prep_replicant_order_invalid_location(self): mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') mock.return_value = [] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME exception = self.assertRaises( exceptions.SoftLayerError, @@ -3268,11 +3268,11 @@ def test_prep_replicant_order_invalid_location(self): str(exception) ) - def test_prep_replicant_order_enterprise_offering_invalid_storage_type(self): + def test_prep_replicant_order_enterprise_offering_invalid_type(self): mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') mock.return_value = [{'id': 51, 'name': 'wdc04'}] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_billing_item_category = mock_volume['billingItem']['categoryCode'] mock_volume['billingItem']['categoryCode'] = 'invalid_type_ninja_cat' @@ -3294,7 +3294,7 @@ def test_prep_replicant_order_snapshot_capacity_not_found(self): mock = self.set_mock('SoftLayer_Location_Datacenter', 'getDatacenters') mock.return_value = [{'id': 51, 'name': 'wdc04'}] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_snapshot_capacity = mock_volume['snapshotCapacityGb'] del mock_volume['snapshotCapacityGb'] @@ -3317,7 +3317,7 @@ def test_prep_replicant_order_saas_endurance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME expected_object = { 'complexType': 'SoftLayer_Container_Product_Order_' @@ -3350,7 +3350,7 @@ def test_prep_replicant_order_saas_endurance_tier_is_not_none(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME expected_object = { 'complexType': 'SoftLayer_Container_Product_Order_' @@ -3383,7 +3383,7 @@ def test_prep_replicant_order_saas_performance_volume_below_staas_v2(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type = mock_volume['storageType']['keyName'] prev_has_encryption_at_rest_flag = mock_volume['hasEncryptionAtRest'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' @@ -3410,7 +3410,7 @@ def test_prep_replicant_order_saas_performance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' @@ -3448,7 +3448,7 @@ def test_prep_replicant_order_saas_invalid_storage_type(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'CATS_LIKE_PIANO_MUSIC' @@ -3542,7 +3542,7 @@ def test_prep_duplicate_order_origin_volume_cancelled(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_billing_item = mock_volume['billingItem'] del mock_volume['billingItem'] @@ -3562,7 +3562,7 @@ def test_prep_duplicate_order_origin_snapshot_capacity_not_found(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_snapshot_capacity_gb = mock_volume['snapshotCapacityGb'] del mock_volume['snapshotCapacityGb'] @@ -3582,7 +3582,7 @@ def test_prep_duplicate_order_origin_volume_location_not_found(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_location = mock_volume['billingItem']['location'] del mock_volume['billingItem']['location'] @@ -3601,7 +3601,7 @@ def test_prep_duplicate_order_origin_volume_staas_version_below_v2(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_staas_version = mock_volume['staasVersion'] mock_volume['staasVersion'] = 1 @@ -3621,7 +3621,7 @@ def test_prep_duplicate_order_origin_volume_capacity_not_found(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_capacity_gb = mock_volume['capacityGb'] mock_volume['capacityGb'] = None @@ -3639,7 +3639,7 @@ def test_prep_duplicate_order_origin_originalVolumeSize_empty_block(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_original_volume_size = mock_volume['originalVolumeSize'] del mock_volume['originalVolumeSize'] @@ -3670,7 +3670,7 @@ def test_prep_duplicate_order_size_too_small(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME exception = self.assertRaises( exceptions.SoftLayerError, @@ -3687,7 +3687,7 @@ def test_prep_duplicate_order_size_too_large_block(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME exception = self.assertRaises( exceptions.SoftLayerError, @@ -3709,7 +3709,7 @@ def test_prep_duplicate_order_performance_origin_iops_not_found(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] prev_provisioned_iops = mock_volume['provisionedIops'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_'\ @@ -3732,7 +3732,7 @@ def test_prep_duplicate_order_performance_iops_above_limit(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] prev_provisioned_iops = mock_volume['provisionedIops'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' @@ -3756,7 +3756,7 @@ def test_prep_duplicate_order_performance_iops_below_limit(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' @@ -3777,7 +3777,7 @@ def test_prep_duplicate_order_performance_use_default_origin_values(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_'\ 'STORAGE_REPLICANT' @@ -3810,7 +3810,7 @@ def test_prep_duplicate_order_performance_block(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_BLOCK_STORAGE' @@ -3842,7 +3842,7 @@ def test_prep_duplicate_order_performance_file(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'PERFORMANCE_FILE_STORAGE' @@ -3874,7 +3874,7 @@ def test_prep_duplicate_order_endurance_origin_tier_not_found(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_tier_level = mock_volume['storageTierLevel'] prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageTierLevel'] = 'NINJA_PENGUINS' @@ -3897,7 +3897,7 @@ def test_prep_duplicate_order_endurance_tier_above_limit(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_tier_level = mock_volume['storageTierLevel'] mock_volume['storageTierLevel'] = 'LOW_INTENSITY_TIER' @@ -3918,7 +3918,7 @@ def test_prep_duplicate_order_endurance_tier_below_limit(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME exception = self.assertRaises( exceptions.SoftLayerError, @@ -3935,7 +3935,7 @@ def test_prep_duplicate_order_endurance_use_default_origin_values(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_'\ 'STORAGE_REPLICANT' @@ -3967,7 +3967,7 @@ def test_prep_duplicate_order_endurance_block(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME expected_object = { 'complexType': 'SoftLayer_Container_Product_Order_' @@ -3994,7 +3994,7 @@ def test_prep_duplicate_order_endurance_file(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'ENDURANCE_FILE_STORAGE' @@ -4025,7 +4025,7 @@ def test_prep_duplicate_order_invalid_origin_storage_type(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') mock.return_value = [fixtures.SoftLayer_Product_Package.SAAS_PACKAGE] - mock_volume = fixtures.SoftLayer_Network_Storage.SAAS_TEST_VOLUME + mock_volume = fixtures.SoftLayer_Network_Storage.STAAS_TEST_VOLUME prev_storage_type_keyname = mock_volume['storageType']['keyName'] mock_volume['storageType']['keyName'] = 'NINJA_CATS' From 15abd827c1b6df7abb1f96e6bbdd150f6706cdd7 Mon Sep 17 00:00:00 2001 From: David Pickle Date: Thu, 27 Jul 2017 10:17:51 -0500 Subject: [PATCH 4/4] Fix bug in file/block volume-detail (found while testing) --- SoftLayer/CLI/block/detail.py | 10 ++++++---- SoftLayer/CLI/file/detail.py | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/SoftLayer/CLI/block/detail.py b/SoftLayer/CLI/block/detail.py index b8ba8bed5..70a41c0c0 100644 --- a/SoftLayer/CLI/block/detail.py +++ b/SoftLayer/CLI/block/detail.py @@ -86,16 +86,18 @@ def cli(env, volume_id): replicant['id']]) replicant_table.add_row([ 'Volume Name', - replicant['username']]) + utils.lookup(replicant, 'username')]) replicant_table.add_row([ 'Target IP', - replicant['serviceResourceBackendIpAddress']]) + utils.lookup(replicant, 'serviceResourceBackendIpAddress')]) replicant_table.add_row([ 'Data Center', - replicant['serviceResource']['datacenter']['name']]) + utils.lookup(replicant, + 'serviceResource', 'datacenter', 'name')]) replicant_table.add_row([ 'Schedule', - replicant['replicationSchedule']['type']['keyname']]) + utils.lookup(replicant, + 'replicationSchedule', 'type', 'keyname')]) replicant_list.append(replicant_table) table.add_row(['Replicant Volumes', replicant_list]) diff --git a/SoftLayer/CLI/file/detail.py b/SoftLayer/CLI/file/detail.py index 3c9af3f23..9f7d97dd6 100644 --- a/SoftLayer/CLI/file/detail.py +++ b/SoftLayer/CLI/file/detail.py @@ -102,16 +102,18 @@ def cli(env, volume_id): replicant['id']]) replicant_table.add_row([ 'Volume Name', - replicant['username']]) + utils.lookup(replicant, 'username')]) replicant_table.add_row([ 'Target IP', - replicant['serviceResourceBackendIpAddress']]) + utils.lookup(replicant, 'serviceResourceBackendIpAddress')]) replicant_table.add_row([ 'Data Center', - replicant['serviceResource']['datacenter']['name']]) + utils.lookup(replicant, + 'serviceResource', 'datacenter', 'name')]) replicant_table.add_row([ 'Schedule', - replicant['replicationSchedule']['type']['keyname']]) + utils.lookup(replicant, + 'replicationSchedule', 'type', 'keyname')]) replicant_list.append(replicant_table) table.add_row(['Replicant Volumes', replicant_list])