From 96ec10c90a36237b315ae99cbdd98c870fd02e33 Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Tue, 19 Jun 2018 13:34:37 -0400 Subject: [PATCH 1/4] Fixed cancel block storage issue --- SoftLayer/managers/block.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/SoftLayer/managers/block.py b/SoftLayer/managers/block.py index 74b5fb423..428edc13d 100644 --- a/SoftLayer/managers/block.py +++ b/SoftLayer/managers/block.py @@ -510,16 +510,20 @@ def cancel_block_volume(self, volume_id, block_volume = self.get_block_volume_details( volume_id, mask='mask[id,billingItem[id,hourlyFlag]]') - billing_item_id = block_volume['billingItem']['id'] + billingItem = 'billingItem' in block_volume + if billingItem == False: + print('The block storage was cancelled') + else: + billing_item_id = block_volume['billingItem']['id'] - if utils.lookup(block_volume, 'billingItem', 'hourlyFlag'): - immediate = True + if utils.lookup(block_volume, 'billingItem', 'hourlyFlag'): + immediate = True - return self.client['Billing_Item'].cancelItem( - immediate, - True, - reason, - id=billing_item_id) + return self.client['Billing_Item'].cancelItem( + immediate, + True, + reason, + id=billing_item_id) def failover_to_replicant(self, volume_id, replicant_id, immediate=False): """Failover to a volume replicant. From 9e62b2a48a66487a41452dc2a5fa4a6ebbb0d11d Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Tue, 19 Jun 2018 13:56:13 -0400 Subject: [PATCH 2/4] Fixed cancel block storage issue --- SoftLayer/managers/block.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SoftLayer/managers/block.py b/SoftLayer/managers/block.py index 428edc13d..9d2ead3e1 100644 --- a/SoftLayer/managers/block.py +++ b/SoftLayer/managers/block.py @@ -511,7 +511,7 @@ def cancel_block_volume(self, volume_id, volume_id, mask='mask[id,billingItem[id,hourlyFlag]]') billingItem = 'billingItem' in block_volume - if billingItem == False: + if billingItem is False: print('The block storage was cancelled') else: billing_item_id = block_volume['billingItem']['id'] From 9c2f95e616838b762a6ba531de9a8724359c3335 Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Wed, 20 Jun 2018 14:28:46 -0400 Subject: [PATCH 3/4] Fixed cancel block storage issue --- SoftLayer/managers/block.py | 24 +- tests/managers/block_tests.py | 446 ++++++++++++++++++---------------- 2 files changed, 255 insertions(+), 215 deletions(-) diff --git a/SoftLayer/managers/block.py b/SoftLayer/managers/block.py index 9d2ead3e1..b1efd033c 100644 --- a/SoftLayer/managers/block.py +++ b/SoftLayer/managers/block.py @@ -510,20 +510,20 @@ def cancel_block_volume(self, volume_id, block_volume = self.get_block_volume_details( volume_id, mask='mask[id,billingItem[id,hourlyFlag]]') - billingItem = 'billingItem' in block_volume - if billingItem is False: - print('The block storage was cancelled') - else: - billing_item_id = block_volume['billingItem']['id'] - if utils.lookup(block_volume, 'billingItem', 'hourlyFlag'): - immediate = True + if 'billingItem' not in block_volume: + raise exceptions.SoftLayerError("Block Storage was already cancelled") + + billing_item_id = block_volume['billingItem']['id'] + + if utils.lookup(block_volume, 'billingItem', 'hourlyFlag'): + immediate = True - return self.client['Billing_Item'].cancelItem( - immediate, - True, - reason, - id=billing_item_id) + return self.client['Billing_Item'].cancelItem( + immediate, + True, + reason, + id=billing_item_id) def failover_to_replicant(self, volume_id, replicant_id, immediate=False): """Failover to a volume replicant. diff --git a/tests/managers/block_tests.py b/tests/managers/block_tests.py index 6f2e5eb6f..873b63908 100644 --- a/tests/managers/block_tests.py +++ b/tests/managers/block_tests.py @@ -41,33 +41,73 @@ def test_cancel_block_volume_immediately_hourly_billing(self): identifier=449, ) + def test_cancel_block_volume_exception_billing_item_not_found(self): + mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = { + 'capacityGb': 20, + 'createDate': '2017-06-20T14:24:21-06:00', + 'nasType': 'ISCSI', + 'storageTypeId': '7', + 'serviceResourceName':'PerfStor Aggr aggr_staasdal0601_pc01' + } + exception = self.assertRaises( + exceptions.SoftLayerError, + self.block.cancel_block_volume, + 12345, + immediate=True + ) + self.assertEqual( + 'Block Storage was already cancelled', + str(exception) + ) + + def test_cancel_block_volume_billing_item_found(self): + mock = self.set_mock('SoftLayer_Network_Storage', 'getObject') + mock.return_value = { + 'capacityGb': 20, + 'createDate': '2017-06-20T14:24:21-06:00', + 'nasType': 'ISCSI', + 'storageTypeId': '7', + 'serviceResourceName':'PerfStor Aggr aggr_staasdal0601_pc01', + 'billingItem': {'hourlyFlag': True, 'id': 449}, + } + self.block.cancel_block_volume(123, immediate=False) + + self.assert_called_with( + 'SoftLayer_Billing_Item', + 'cancelItem', + args=(True, True, 'No longer needed'), + identifier=449, + ) + + def test_get_block_volume_details(self): result = self.block.get_block_volume_details(100) self.assertEqual(fixtures.SoftLayer_Network_Storage.getObject, result) - expected_mask = 'id,'\ - 'username,'\ - 'password,'\ - 'capacityGb,'\ - 'snapshotCapacityGb,'\ - 'parentVolume.snapshotSizeBytes,'\ - 'storageType.keyName,'\ - 'serviceResource.datacenter[name],'\ - 'serviceResourceBackendIpAddress,'\ - 'storageTierLevel,'\ - 'provisionedIops,'\ - 'lunId,'\ - 'originalVolumeName,'\ - 'originalSnapshotName,'\ - 'originalVolumeSize,'\ - 'activeTransactionCount,'\ - 'activeTransactions.transactionStatus[friendlyName],'\ - 'replicationPartnerCount,'\ - 'replicationStatus,'\ - 'replicationPartners[id,username,'\ - 'serviceResourceBackendIpAddress,'\ - 'serviceResource[datacenter[name]],'\ + expected_mask = 'id,' \ + 'username,' \ + 'password,' \ + 'capacityGb,' \ + 'snapshotCapacityGb,' \ + 'parentVolume.snapshotSizeBytes,' \ + 'storageType.keyName,' \ + 'serviceResource.datacenter[name],' \ + 'serviceResourceBackendIpAddress,' \ + 'storageTierLevel,' \ + 'provisionedIops,' \ + 'lunId,' \ + 'originalVolumeName,' \ + 'originalSnapshotName,' \ + 'originalVolumeSize,' \ + 'activeTransactionCount,' \ + 'activeTransactions.transactionStatus[friendlyName],' \ + 'replicationPartnerCount,' \ + 'replicationStatus,' \ + 'replicationPartners[id,username,' \ + 'serviceResourceBackendIpAddress,' \ + 'serviceResource[datacenter[name]],' \ 'replicationSchedule[type[keyname]]]' self.assert_called_with( @@ -75,7 +115,7 @@ def test_get_block_volume_details(self): 'getObject', identifier=100, mask='mask[%s]' % expected_mask - ) + ) def test_list_block_volumes(self): result = self.block.list_block_volumes() @@ -96,14 +136,14 @@ def test_list_block_volumes(self): } } - expected_mask = 'id,'\ - 'username,'\ - 'lunId,'\ - 'capacityGb,'\ - 'bytesUsed,'\ - 'serviceResource.datacenter[name],'\ - 'serviceResourceBackendIpAddress,'\ - 'activeTransactionCount,'\ + expected_mask = 'id,' \ + 'username,' \ + 'lunId,' \ + 'capacityGb,' \ + 'bytesUsed,' \ + 'serviceResource.datacenter[name],' \ + 'serviceResourceBackendIpAddress,' \ + 'activeTransactionCount,' \ 'replicationPartnerCount' self.assert_called_with( @@ -138,14 +178,14 @@ def test_list_block_volumes_with_additional_filters(self): } } - expected_mask = 'id,'\ - 'username,'\ - 'lunId,'\ - 'capacityGb,'\ - 'bytesUsed,'\ - 'serviceResource.datacenter[name],'\ - 'serviceResourceBackendIpAddress,'\ - 'activeTransactionCount,'\ + expected_mask = 'id,' \ + 'username,' \ + 'lunId,' \ + 'capacityGb,' \ + 'bytesUsed,' \ + 'serviceResource.datacenter[name],' \ + 'serviceResourceBackendIpAddress,' \ + 'activeTransactionCount,' \ 'replicationPartnerCount' self.assert_called_with( @@ -357,22 +397,22 @@ def test_order_block_volume_performance(self): '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, - 'useHourlyPricing': False, - 'osFormatType': {'keyName': 'LINUX'} - },) + '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, + 'useHourlyPricing': False, + 'osFormatType': {'keyName': 'LINUX'} + },) ) def test_order_block_volume_endurance(self): @@ -401,21 +441,21 @@ def test_order_block_volume_endurance(self): '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, - 'useHourlyPricing': False, - 'osFormatType': {'keyName': 'LINUX'} - },) + '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, + 'useHourlyPricing': False, + 'osFormatType': {'keyName': 'LINUX'} + },) ) def test_authorize_host_to_volume(self): @@ -525,17 +565,17 @@ def test_order_block_snapshot_space_upgrade(self): '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, - 'useHourlyPricing': False - },) + 'complexType': 'SoftLayer_Container_Product_Order_Network_' + 'Storage_Enterprise_SnapshotSpace_Upgrade', + 'packageId': 759, + 'prices': [ + {'id': 193853} + ], + 'quantity': 1, + 'location': 449500, + 'volumeId': 102, + 'useHourlyPricing': False + },) ) def test_order_block_snapshot_space(self): @@ -554,17 +594,17 @@ def test_order_block_snapshot_space(self): '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, - 'useHourlyPricing': False - },) + 'complexType': 'SoftLayer_Container_Product_Order_Network_' + 'Storage_Enterprise_SnapshotSpace', + 'packageId': 759, + 'prices': [ + {'id': 193613} + ], + 'quantity': 1, + 'location': 449500, + 'volumeId': 102, + 'useHourlyPricing': False + },) ) def test_order_block_replicant_os_type_not_found(self): @@ -610,26 +650,26 @@ def test_order_block_replicant_performance_os_type_given(self): '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, - 'useHourlyPricing': False, - 'osFormatType': {'keyName': 'XEN'} - },) + '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, + 'useHourlyPricing': False, + 'osFormatType': {'keyName': 'XEN'} + },) ) def test_order_block_replicant_endurance(self): @@ -651,25 +691,25 @@ def test_order_block_replicant_endurance(self): '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, - 'useHourlyPricing': False, - 'osFormatType': {'keyName': 'LINUX'} - },) + '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, + 'useHourlyPricing': False, + 'osFormatType': {'keyName': 'LINUX'} + },) ) def test_order_block_duplicate_origin_os_type_not_found(self): @@ -709,23 +749,23 @@ def test_order_block_duplicate_performance_no_duplicate_snapshot(self): 'SoftLayer_Product_Order', 'placeOrder', args=({ - 'complexType': 'SoftLayer_Container_Product_Order_' - 'Network_Storage_AsAService', - 'packageId': 759, - 'prices': [ - {'id': 189433}, - {'id': 189443}, - {'id': 189993}, - {'id': 190053} - ], - 'volumeSize': 500, - 'quantity': 1, - 'location': 449500, - 'duplicateOriginVolumeId': 102, - 'osFormatType': {'keyName': 'LINUX'}, - 'iops': 1000, - 'useHourlyPricing': False - },)) + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189443}, + {'id': 189993}, + {'id': 190053} + ], + 'volumeSize': 500, + 'quantity': 1, + 'location': 449500, + 'duplicateOriginVolumeId': 102, + 'osFormatType': {'keyName': 'LINUX'}, + 'iops': 1000, + 'useHourlyPricing': False + },)) def test_order_block_duplicate_performance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') @@ -743,7 +783,7 @@ def test_order_block_duplicate_performance(self): duplicate_iops=2000, duplicate_tier_level=None, duplicate_snapshot_size=10 - ) + ) self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) @@ -751,25 +791,25 @@ def test_order_block_duplicate_performance(self): 'SoftLayer_Product_Order', 'placeOrder', args=({ - 'complexType': 'SoftLayer_Container_Product_Order_' - 'Network_Storage_AsAService', - 'packageId': 759, - 'prices': [ - {'id': 189433}, - {'id': 189443}, - {'id': 190113}, - {'id': 190173}, - {'id': 191193} - ], - 'volumeSize': 1000, - 'quantity': 1, - 'location': 449500, - 'duplicateOriginVolumeId': 102, - 'osFormatType': {'keyName': 'LINUX'}, - 'duplicateOriginSnapshotId': 470, - 'iops': 2000, - 'useHourlyPricing': False - },)) + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189443}, + {'id': 190113}, + {'id': 190173}, + {'id': 191193} + ], + 'volumeSize': 1000, + 'quantity': 1, + 'location': 449500, + 'duplicateOriginVolumeId': 102, + 'osFormatType': {'keyName': 'LINUX'}, + 'duplicateOriginSnapshotId': 470, + 'iops': 2000, + 'useHourlyPricing': False + },)) def test_order_block_duplicate_endurance_no_duplicate_snapshot(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') @@ -789,22 +829,22 @@ def test_order_block_duplicate_endurance_no_duplicate_snapshot(self): 'SoftLayer_Product_Order', 'placeOrder', args=({ - 'complexType': 'SoftLayer_Container_Product_Order_' - 'Network_Storage_AsAService', - 'packageId': 759, - 'prices': [ - {'id': 189433}, - {'id': 189443}, - {'id': 193433}, - {'id': 193373} - ], - 'volumeSize': 500, - 'quantity': 1, - 'location': 449500, - 'duplicateOriginVolumeId': 102, - 'osFormatType': {'keyName': 'LINUX'}, - 'useHourlyPricing': False - },)) + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189443}, + {'id': 193433}, + {'id': 193373} + ], + 'volumeSize': 500, + 'quantity': 1, + 'location': 449500, + 'duplicateOriginVolumeId': 102, + 'osFormatType': {'keyName': 'LINUX'}, + 'useHourlyPricing': False + },)) def test_order_block_duplicate_endurance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') @@ -821,7 +861,7 @@ def test_order_block_duplicate_endurance(self): duplicate_iops=None, duplicate_tier_level=4, duplicate_snapshot_size=10 - ) + ) self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) @@ -829,24 +869,24 @@ def test_order_block_duplicate_endurance(self): 'SoftLayer_Product_Order', 'placeOrder', args=({ - 'complexType': 'SoftLayer_Container_Product_Order_' - 'Network_Storage_AsAService', - 'packageId': 759, - 'prices': [ - {'id': 189433}, - {'id': 189443}, - {'id': 194763}, - {'id': 194703}, - {'id': 194943} - ], - 'volumeSize': 1000, - 'quantity': 1, - 'location': 449500, - 'duplicateOriginVolumeId': 102, - 'osFormatType': {'keyName': 'LINUX'}, - 'duplicateOriginSnapshotId': 470, - 'useHourlyPricing': False - },)) + 'complexType': 'SoftLayer_Container_Product_Order_' + 'Network_Storage_AsAService', + 'packageId': 759, + 'prices': [ + {'id': 189433}, + {'id': 189443}, + {'id': 194763}, + {'id': 194703}, + {'id': 194943} + ], + 'volumeSize': 1000, + 'quantity': 1, + 'location': 449500, + 'duplicateOriginVolumeId': 102, + 'osFormatType': {'keyName': 'LINUX'}, + 'duplicateOriginSnapshotId': 470, + 'useHourlyPricing': False + },)) def test_order_block_modified_performance(self): mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects') From 64fe8b0f7795b6518bab39829c78ee35662f7f94 Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Wed, 20 Jun 2018 14:49:23 -0400 Subject: [PATCH 4/4] Fixed cancel block storage issue --- tests/managers/block_tests.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/managers/block_tests.py b/tests/managers/block_tests.py index 873b63908..fa5dacb2b 100644 --- a/tests/managers/block_tests.py +++ b/tests/managers/block_tests.py @@ -48,7 +48,7 @@ def test_cancel_block_volume_exception_billing_item_not_found(self): 'createDate': '2017-06-20T14:24:21-06:00', 'nasType': 'ISCSI', 'storageTypeId': '7', - 'serviceResourceName':'PerfStor Aggr aggr_staasdal0601_pc01' + 'serviceResourceName': 'PerfStor Aggr aggr_staasdal0601_pc01' } exception = self.assertRaises( exceptions.SoftLayerError, @@ -68,7 +68,7 @@ def test_cancel_block_volume_billing_item_found(self): 'createDate': '2017-06-20T14:24:21-06:00', 'nasType': 'ISCSI', 'storageTypeId': '7', - 'serviceResourceName':'PerfStor Aggr aggr_staasdal0601_pc01', + 'serviceResourceName': 'PerfStor Aggr aggr_staasdal0601_pc01', 'billingItem': {'hourlyFlag': True, 'id': 449}, } self.block.cancel_block_volume(123, immediate=False) @@ -80,7 +80,6 @@ def test_cancel_block_volume_billing_item_found(self): identifier=449, ) - def test_get_block_volume_details(self): result = self.block.get_block_volume_details(100)