From 417fc31edcb8b07c43914520e35b810f1ddba25d Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Mon, 3 Sep 2018 16:32:43 -0400 Subject: [PATCH 1/4] fixed vs upgrade using flavors --- SoftLayer/CLI/virt/upgrade.py | 11 ++- .../fixtures/SoftLayer_Product_Package.py | 27 +++++++ SoftLayer/managers/vs.py | 79 +++++++++++++++---- tests/CLI/modules/vs_tests.py | 18 +++++ tests/managers/vs_tests.py | 16 ++++ 5 files changed, 131 insertions(+), 20 deletions(-) diff --git a/SoftLayer/CLI/virt/upgrade.py b/SoftLayer/CLI/virt/upgrade.py index 419456f91..039e7cbfc 100644 --- a/SoftLayer/CLI/virt/upgrade.py +++ b/SoftLayer/CLI/virt/upgrade.py @@ -21,15 +21,17 @@ help="CPU core will be on a dedicated host server.") @click.option('--memory', type=virt.MEM_TYPE, help="Memory in megabytes") @click.option('--network', type=click.INT, help="Network port speed in Mbps") +@click.option('--flavor', type=click.STRING, help="Flavor keyName\n" + "Do not use --memory, --cpu or --private, if you are using flavors") @environment.pass_env -def cli(env, identifier, cpu, private, memory, network): +def cli(env, identifier, cpu, private, memory, network, flavor): """Upgrade a virtual server.""" vsi = SoftLayer.VSManager(env.client) - if not any([cpu, memory, network]): + if not any([cpu, memory, network, flavor]): raise exceptions.ArgumentError( - "Must provide [--cpu], [--memory], or [--network] to upgrade") + "Must provide [--cpu], [--memory], [--network], or [--flavor] to upgrade") if private and not cpu: raise exceptions.ArgumentError( @@ -48,5 +50,6 @@ def cli(env, identifier, cpu, private, memory, network): cpus=cpu, memory=memory, nic_speed=network, - public=not private): + public=not private, + preset=flavor): raise exceptions.CLIAbort('VS Upgrade Failed') diff --git a/SoftLayer/fixtures/SoftLayer_Product_Package.py b/SoftLayer/fixtures/SoftLayer_Product_Package.py index 9b5d53741..4fd413bde 100644 --- a/SoftLayer/fixtures/SoftLayer_Product_Package.py +++ b/SoftLayer/fixtures/SoftLayer_Product_Package.py @@ -1340,3 +1340,30 @@ }] }] }] + +getActivePresets = [ + { + "description": "M1.64x512x25", + "id": 799, + "isActive": "1", + "keyName": "M1_64X512X25", + "name": "M1.64x512x25", + "packageId": 835 + }, + { + "description": "M1.56x448x100", + "id": 797, + "isActive": "1", + "keyName": "M1_56X448X100", + "name": "M1.56x448x100", + "packageId": 835 + }, + { + "description": "M1.64x512x100", + "id": 801, + "isActive": "1", + "keyName": "M1_64X512X100", + "name": "M1.64x512x100", + "packageId": 835 + } +] diff --git a/SoftLayer/managers/vs.py b/SoftLayer/managers/vs.py index 059f06066..1eb9d84f2 100644 --- a/SoftLayer/managers/vs.py +++ b/SoftLayer/managers/vs.py @@ -51,6 +51,7 @@ def __init__(self, client, ordering_manager=None): self.client = client self.account = client['Account'] self.guest = client['Virtual_Guest'] + self.package_svc = client['Product_Package'] self.resolvers = [self._get_ids_from_ip, self._get_ids_from_hostname] if ordering_manager is None: self.ordering_manager = ordering.OrderingManager(client) @@ -803,7 +804,7 @@ def capture(self, instance_id, name, additional_disks=False, notes=None): name, disks_to_capture, notes, id=instance_id) def upgrade(self, instance_id, cpus=None, memory=None, - nic_speed=None, public=True): + nic_speed=None, public=True, preset=None): """Upgrades a VS instance. Example:: @@ -817,6 +818,7 @@ def upgrade(self, instance_id, cpus=None, memory=None, :param int instance_id: Instance id of the VS to be upgraded :param int cpus: The number of virtual CPUs to upgrade to of a VS instance. + :param string preset: preset assigned to the vsi :param int memory: RAM of the VS to be upgraded to. :param int nic_speed: The port speed to set :param bool public: CPU will be in Private/Public Node. @@ -826,9 +828,30 @@ def upgrade(self, instance_id, cpus=None, memory=None, upgrade_prices = self._get_upgrade_prices(instance_id) prices = [] - for option, value in {'cpus': cpus, - 'memory': memory, - 'nic_speed': nic_speed}.items(): + data = {'nic_speed': nic_speed} + + if cpus is not None and preset is not None: + raise exceptions.SoftLayerError("Do not use cpu, private and memory if you are using flavors") + else: + data['cpus'] = cpus + + if memory is not None and preset is not None: + raise exceptions.SoftLayerError("Do not use memory, private or cpu if you are using flavors") + else: + data['memory'] = memory + + maintenance_window = datetime.datetime.now(utils.UTC()) + order = { + 'complexType': 'SoftLayer_Container_Product_Order_Virtual_Guest_' + 'Upgrade', + 'properties': [{ + 'name': 'MAINTENANCE_WINDOW', + 'value': maintenance_window.strftime("%Y-%m-%d %H:%M:%S%z") + }], + 'virtualGuests': [{'id': int(instance_id)}], + } + + for option, value in data.items(): if not value: continue price_id = self._get_price_id_for_upgrade_option(upgrade_prices, @@ -841,23 +864,47 @@ def upgrade(self, instance_id, cpus=None, memory=None, "Unable to find %s option with value %s" % (option, value)) prices.append({'id': price_id}) + order['prices'] = prices - maintenance_window = datetime.datetime.now(utils.UTC()) - order = { - 'complexType': 'SoftLayer_Container_Product_Order_Virtual_Guest_' - 'Upgrade', - 'prices': prices, - 'properties': [{ - 'name': 'MAINTENANCE_WINDOW', - 'value': maintenance_window.strftime("%Y-%m-%d %H:%M:%S%z") - }], - 'virtualGuests': [{'id': int(instance_id)}], - } - if prices: + if preset is not None: + presetId = self._get_active_presets(preset) + order['presetId'] = presetId + + if prices or preset: self.client['Product_Order'].placeOrder(order) return True return False + def _get_active_presets(self, preset): + """Following Method gets the active presets. + """ + packageId = 835 + + _filter = { + 'activePresets': { + 'keyName': { + 'operation': preset + } + }, + 'accountRestrictedActivePresets': { + 'keyName': { + 'operation': preset + } + } + } + + mask = 'mask[id]' + active_presets = self.package_svc.getActivePresets(id=packageId, mask=mask, filter=_filter) + + if len(active_presets) == 0: + raise exceptions.SoftLayerError( + "Preset {} does not exist in package {}".format(preset, + packageId)) + + for presetId in active_presets: + id = presetId['id'] + return id + def _get_package_items(self): """Following Method gets all the item ids related to VS. diff --git a/tests/CLI/modules/vs_tests.py b/tests/CLI/modules/vs_tests.py index c976a952e..833ad5bb6 100644 --- a/tests/CLI/modules/vs_tests.py +++ b/tests/CLI/modules/vs_tests.py @@ -901,6 +901,24 @@ def test_upgrade(self, confirm_mock): self.assertIn({'id': 1122}, order_container['prices']) self.assertEqual(order_container['virtualGuests'], [{'id': 100}]) + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_upgrade_with_flavor(self, confirm_mock): + confirm_mock.return_value = True + result = self.run_command(['vs', 'upgrade', '100', '--flavor=M1_64X512X100']) + self.assert_no_fail(result) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] + order_container = call.args[0] + self.assertEquals(801, order_container['presetId']) + self.assertIn({'id': 100}, order_container['virtualGuests']) + self.assertEqual(order_container['virtualGuests'], [{'id': 100}]) + + def test_upgrade_with_cpu_memory_and_flavor(self): + result = self.run_command(['vs', 'upgrade', '100', '--cpu=4', + '--memory=1024', '--flavor=M1_64X512X100']) + self.assertEqual(result.exit_code, 2) + self.assertIsInstance(result.exception, exceptions.CLIAbort) + def test_edit(self): result = self.run_command(['vs', 'edit', '--domain=example.com', diff --git a/tests/managers/vs_tests.py b/tests/managers/vs_tests.py index 456b5cbc3..dfbb561b8 100644 --- a/tests/managers/vs_tests.py +++ b/tests/managers/vs_tests.py @@ -879,6 +879,22 @@ def test_upgrade_full(self): self.assertIn({'id': 1122}, order_container['prices']) self.assertEqual(order_container['virtualGuests'], [{'id': 1}]) + def test_upgrade_with_flavor(self): + # Testing Upgrade with parameter preset + result = self.vs.upgrade(1, + preset="M1_64X512X100", + nic_speed=1000, + public=True) + + self.assertEqual(result, True) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] + order_container = call.args[0] + self.assertEquals(801, order_container['presetId']) + self.assertIn({'id': 1}, order_container['virtualGuests']) + self.assertIn({'id': 1122}, order_container['prices']) + self.assertEqual(order_container['virtualGuests'], [{'id': 1}]) + def test_upgrade_dedicated_host_instance(self): mock = self.set_mock('SoftLayer_Virtual_Guest', 'getUpgradeItemPrices') mock.return_value = fixtures.SoftLayer_Virtual_Guest.DEDICATED_GET_UPGRADE_ITEM_PRICES From 437015c5affe66aaf045495a5b72bb5364af1ad6 Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Mon, 3 Sep 2018 17:31:22 -0400 Subject: [PATCH 2/4] fixed vs upgrade using flavors --- SoftLayer/fixtures/SoftLayer_Virtual_Guest.py | 3 +++ SoftLayer/managers/vs.py | 11 +++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py b/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py index 776db8778..9f60f0b8d 100644 --- a/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py +++ b/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py @@ -14,6 +14,9 @@ {'nextInvoiceTotalRecurringAmount': 1}, {'nextInvoiceTotalRecurringAmount': 1}, ], + 'package': { + "id": 835 + }, 'orderItem': { 'order': { 'userRecord': { diff --git a/SoftLayer/managers/vs.py b/SoftLayer/managers/vs.py index 1eb9d84f2..06ca3c014 100644 --- a/SoftLayer/managers/vs.py +++ b/SoftLayer/managers/vs.py @@ -226,6 +226,7 @@ def get_instance(self, instance_id, **kwargs): 'hourlyBillingFlag,' 'userData,' '''billingItem[id,nextInvoiceTotalRecurringAmount, + package['id'], children[categoryCode,nextInvoiceTotalRecurringAmount], orderItem[id, order.userRecord[username], @@ -867,7 +868,7 @@ def upgrade(self, instance_id, cpus=None, memory=None, order['prices'] = prices if preset is not None: - presetId = self._get_active_presets(preset) + presetId = self._get_active_presets(preset, instance_id) order['presetId'] = presetId if prices or preset: @@ -875,11 +876,9 @@ def upgrade(self, instance_id, cpus=None, memory=None, return True return False - def _get_active_presets(self, preset): + def _get_active_presets(self, preset, instance_id): """Following Method gets the active presets. """ - packageId = 835 - _filter = { 'activePresets': { 'keyName': { @@ -893,6 +892,10 @@ def _get_active_presets(self, preset): } } + vs_object = self.get_instance(instance_id, mask='mask[billingItem[package[id]]]') + package = vs_object['billingItem']['package'] + packageId = package['id'] + mask = 'mask[id]' active_presets = self.package_svc.getActivePresets(id=packageId, mask=mask, filter=_filter) From e4adae57420da47ade58e5b146f7c8cebf7a31f3 Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Mon, 3 Sep 2018 18:55:01 -0400 Subject: [PATCH 3/4] fixed vs upgrade using flavors --- SoftLayer/managers/vs.py | 4 ++++ tests/CLI/modules/vs_tests.py | 5 ++--- tests/managers/vs_tests.py | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/SoftLayer/managers/vs.py b/SoftLayer/managers/vs.py index 06ca3c014..388e29c74 100644 --- a/SoftLayer/managers/vs.py +++ b/SoftLayer/managers/vs.py @@ -210,6 +210,7 @@ def get_instance(self, instance_id, **kwargs): 'maxMemory,' 'datacenter,' 'activeTransaction[id, transactionStatus[friendlyName,name]],' + 'lastTransaction[transactionStatus],' 'lastOperatingSystemReload.id,' 'blockDevices,' 'blockDeviceTemplateGroup[id, name, globalIdentifier],' @@ -878,6 +879,9 @@ def upgrade(self, instance_id, cpus=None, memory=None, def _get_active_presets(self, preset, instance_id): """Following Method gets the active presets. + + :param string preset: preset data to be upgrade de vs. + :param int instance_id: To get the instance information. """ _filter = { 'activePresets': { diff --git a/tests/CLI/modules/vs_tests.py b/tests/CLI/modules/vs_tests.py index 833ad5bb6..e327bef70 100644 --- a/tests/CLI/modules/vs_tests.py +++ b/tests/CLI/modules/vs_tests.py @@ -909,15 +909,14 @@ def test_upgrade_with_flavor(self, confirm_mock): self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] order_container = call.args[0] - self.assertEquals(801, order_container['presetId']) + self.assertEqual(801, order_container['presetId']) self.assertIn({'id': 100}, order_container['virtualGuests']) self.assertEqual(order_container['virtualGuests'], [{'id': 100}]) def test_upgrade_with_cpu_memory_and_flavor(self): result = self.run_command(['vs', 'upgrade', '100', '--cpu=4', '--memory=1024', '--flavor=M1_64X512X100']) - self.assertEqual(result.exit_code, 2) - self.assertIsInstance(result.exception, exceptions.CLIAbort) + self.assertEqual("Do not use cpu, private and memory if you are using flavors", str(result.exception)) def test_edit(self): result = self.run_command(['vs', 'edit', diff --git a/tests/managers/vs_tests.py b/tests/managers/vs_tests.py index dfbb561b8..d53f9da9e 100644 --- a/tests/managers/vs_tests.py +++ b/tests/managers/vs_tests.py @@ -890,7 +890,7 @@ def test_upgrade_with_flavor(self): self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] order_container = call.args[0] - self.assertEquals(801, order_container['presetId']) + self.assertEqual(801, order_container['presetId']) self.assertIn({'id': 1}, order_container['virtualGuests']) self.assertIn({'id': 1122}, order_container['prices']) self.assertEqual(order_container['virtualGuests'], [{'id': 1}]) From 5576b39a7fb07814637b8bbc3c0fab9e210c8691 Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Tue, 4 Sep 2018 17:19:38 -0400 Subject: [PATCH 4/4] Fixed the vs upgrade with flavor data --- .../fixtures/SoftLayer_Product_Package.py | 2 + SoftLayer/fixtures/SoftLayer_Virtual_Guest.py | 3 +- SoftLayer/managers/vs.py | 47 ++----------------- tests/CLI/modules/vs_tests.py | 2 +- tests/managers/vs_tests.py | 2 +- 5 files changed, 11 insertions(+), 45 deletions(-) diff --git a/SoftLayer/fixtures/SoftLayer_Product_Package.py b/SoftLayer/fixtures/SoftLayer_Product_Package.py index 4fd413bde..2642b77e8 100644 --- a/SoftLayer/fixtures/SoftLayer_Product_Package.py +++ b/SoftLayer/fixtures/SoftLayer_Product_Package.py @@ -1367,3 +1367,5 @@ "packageId": 835 } ] + +getAccountRestrictedActivePresets = [] diff --git a/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py b/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py index 9f60f0b8d..ac20acb90 100644 --- a/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py +++ b/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py @@ -15,7 +15,8 @@ {'nextInvoiceTotalRecurringAmount': 1}, ], 'package': { - "id": 835 + "id": 835, + "keyName": "PUBLIC_CLOUD_SERVER" }, 'orderItem': { 'order': { diff --git a/SoftLayer/managers/vs.py b/SoftLayer/managers/vs.py index 388e29c74..03595d8d5 100644 --- a/SoftLayer/managers/vs.py +++ b/SoftLayer/managers/vs.py @@ -227,7 +227,7 @@ def get_instance(self, instance_id, **kwargs): 'hourlyBillingFlag,' 'userData,' '''billingItem[id,nextInvoiceTotalRecurringAmount, - package['id'], + package[id,keyName], children[categoryCode,nextInvoiceTotalRecurringAmount], orderItem[id, order.userRecord[username], @@ -834,13 +834,11 @@ def upgrade(self, instance_id, cpus=None, memory=None, if cpus is not None and preset is not None: raise exceptions.SoftLayerError("Do not use cpu, private and memory if you are using flavors") - else: - data['cpus'] = cpus + data['cpus'] = cpus if memory is not None and preset is not None: raise exceptions.SoftLayerError("Do not use memory, private or cpu if you are using flavors") - else: - data['memory'] = memory + data['memory'] = memory maintenance_window = datetime.datetime.now(utils.UTC()) order = { @@ -869,49 +867,14 @@ def upgrade(self, instance_id, cpus=None, memory=None, order['prices'] = prices if preset is not None: - presetId = self._get_active_presets(preset, instance_id) - order['presetId'] = presetId + vs_object = self.get_instance(instance_id)['billingItem']['package'] + order['presetId'] = self.ordering_manager.get_preset_by_key(vs_object['keyName'], preset)['id'] if prices or preset: self.client['Product_Order'].placeOrder(order) return True return False - def _get_active_presets(self, preset, instance_id): - """Following Method gets the active presets. - - :param string preset: preset data to be upgrade de vs. - :param int instance_id: To get the instance information. - """ - _filter = { - 'activePresets': { - 'keyName': { - 'operation': preset - } - }, - 'accountRestrictedActivePresets': { - 'keyName': { - 'operation': preset - } - } - } - - vs_object = self.get_instance(instance_id, mask='mask[billingItem[package[id]]]') - package = vs_object['billingItem']['package'] - packageId = package['id'] - - mask = 'mask[id]' - active_presets = self.package_svc.getActivePresets(id=packageId, mask=mask, filter=_filter) - - if len(active_presets) == 0: - raise exceptions.SoftLayerError( - "Preset {} does not exist in package {}".format(preset, - packageId)) - - for presetId in active_presets: - id = presetId['id'] - return id - def _get_package_items(self): """Following Method gets all the item ids related to VS. diff --git a/tests/CLI/modules/vs_tests.py b/tests/CLI/modules/vs_tests.py index e327bef70..284963444 100644 --- a/tests/CLI/modules/vs_tests.py +++ b/tests/CLI/modules/vs_tests.py @@ -909,7 +909,7 @@ def test_upgrade_with_flavor(self, confirm_mock): self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] order_container = call.args[0] - self.assertEqual(801, order_container['presetId']) + self.assertEqual(799, order_container['presetId']) self.assertIn({'id': 100}, order_container['virtualGuests']) self.assertEqual(order_container['virtualGuests'], [{'id': 100}]) diff --git a/tests/managers/vs_tests.py b/tests/managers/vs_tests.py index d53f9da9e..97b6c5c4d 100644 --- a/tests/managers/vs_tests.py +++ b/tests/managers/vs_tests.py @@ -890,7 +890,7 @@ def test_upgrade_with_flavor(self): self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] order_container = call.args[0] - self.assertEqual(801, order_container['presetId']) + self.assertEqual(799, order_container['presetId']) self.assertIn({'id': 1}, order_container['virtualGuests']) self.assertIn({'id': 1122}, order_container['prices']) self.assertEqual(order_container['virtualGuests'], [{'id': 1}])