Skip to content

Commit c837331

Browse files
Merge branch 'master' into fo_vs_create_flavor_test
2 parents 65af93f + 86d658b commit c837331

File tree

11 files changed

+133
-39
lines changed

11 files changed

+133
-39
lines changed

SoftLayer/CLI/order/package_list.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
from SoftLayer.CLI import formatting
88
from SoftLayer.managers import ordering
99

10-
COLUMNS = ['name',
10+
COLUMNS = ['id',
11+
'name',
1112
'keyName',
1213
'type']
1314

@@ -51,6 +52,7 @@ def cli(env, keyword, package_type):
5152

5253
for package in packages:
5354
table.add_row([
55+
package['id'],
5456
package['name'],
5557
package['keyName'],
5658
package['type']['keyName']

SoftLayer/CLI/virt/upgrade.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,17 @@
2121
help="CPU core will be on a dedicated host server.")
2222
@click.option('--memory', type=virt.MEM_TYPE, help="Memory in megabytes")
2323
@click.option('--network', type=click.INT, help="Network port speed in Mbps")
24+
@click.option('--flavor', type=click.STRING, help="Flavor keyName\n"
25+
"Do not use --memory, --cpu or --private, if you are using flavors")
2426
@environment.pass_env
25-
def cli(env, identifier, cpu, private, memory, network):
27+
def cli(env, identifier, cpu, private, memory, network, flavor):
2628
"""Upgrade a virtual server."""
2729

2830
vsi = SoftLayer.VSManager(env.client)
2931

30-
if not any([cpu, memory, network]):
32+
if not any([cpu, memory, network, flavor]):
3133
raise exceptions.ArgumentError(
32-
"Must provide [--cpu], [--memory], or [--network] to upgrade")
34+
"Must provide [--cpu], [--memory], [--network], or [--flavor] to upgrade")
3335

3436
if private and not cpu:
3537
raise exceptions.ArgumentError(
@@ -48,5 +50,6 @@ def cli(env, identifier, cpu, private, memory, network):
4850
cpus=cpu,
4951
memory=memory,
5052
nic_speed=network,
51-
public=not private):
53+
public=not private,
54+
preset=flavor):
5255
raise exceptions.CLIAbort('VS Upgrade Failed')

SoftLayer/fixtures/SoftLayer_Product_Package.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,3 +1514,31 @@
15141514
}
15151515
}
15161516
]
1517+
getActivePresets = [
1518+
{
1519+
"description": "M1.64x512x25",
1520+
"id": 799,
1521+
"isActive": "1",
1522+
"keyName": "M1_64X512X25",
1523+
"name": "M1.64x512x25",
1524+
"packageId": 835
1525+
},
1526+
{
1527+
"description": "M1.56x448x100",
1528+
"id": 797,
1529+
"isActive": "1",
1530+
"keyName": "M1_56X448X100",
1531+
"name": "M1.56x448x100",
1532+
"packageId": 835
1533+
},
1534+
{
1535+
"description": "M1.64x512x100",
1536+
"id": 801,
1537+
"isActive": "1",
1538+
"keyName": "M1_64X512X100",
1539+
"name": "M1.64x512x100",
1540+
"packageId": 835
1541+
}
1542+
]
1543+
1544+
getAccountRestrictedActivePresets = []

SoftLayer/fixtures/SoftLayer_Virtual_Guest.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
{'nextInvoiceTotalRecurringAmount': 1},
1515
{'nextInvoiceTotalRecurringAmount': 1},
1616
],
17+
'package': {
18+
"id": 835,
19+
"keyName": "PUBLIC_CLOUD_SERVER"
20+
},
1721
'orderItem': {
1822
'order': {
1923
'userRecord': {

SoftLayer/managers/ticket.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def list_tickets(self, open_status=True, closed_status=True):
4040
else:
4141
raise ValueError("open_status and closed_status cannot both be False")
4242

43-
return self.client.call('Account', call, mask=mask)
43+
return self.client.call('Account', call, mask=mask, iter=True)
4444

4545
def list_subjects(self):
4646
"""List all ticket subjects."""

SoftLayer/managers/vs.py

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def __init__(self, client, ordering_manager=None):
5151
self.client = client
5252
self.account = client['Account']
5353
self.guest = client['Virtual_Guest']
54+
self.package_svc = client['Product_Package']
5455
self.resolvers = [self._get_ids_from_ip, self._get_ids_from_hostname]
5556
if ordering_manager is None:
5657
self.ordering_manager = ordering.OrderingManager(client)
@@ -209,6 +210,7 @@ def get_instance(self, instance_id, **kwargs):
209210
'maxMemory,'
210211
'datacenter,'
211212
'activeTransaction[id, transactionStatus[friendlyName,name]],'
213+
'lastTransaction[transactionStatus],'
212214
'lastOperatingSystemReload.id,'
213215
'blockDevices,'
214216
'blockDeviceTemplateGroup[id, name, globalIdentifier],'
@@ -225,6 +227,7 @@ def get_instance(self, instance_id, **kwargs):
225227
'hourlyBillingFlag,'
226228
'userData,'
227229
'''billingItem[id,nextInvoiceTotalRecurringAmount,
230+
package[id,keyName],
228231
children[categoryCode,nextInvoiceTotalRecurringAmount],
229232
orderItem[id,
230233
order.userRecord[username],
@@ -803,7 +806,7 @@ def capture(self, instance_id, name, additional_disks=False, notes=None):
803806
name, disks_to_capture, notes, id=instance_id)
804807

805808
def upgrade(self, instance_id, cpus=None, memory=None,
806-
nic_speed=None, public=True):
809+
nic_speed=None, public=True, preset=None):
807810
"""Upgrades a VS instance.
808811
809812
Example::
@@ -817,6 +820,7 @@ def upgrade(self, instance_id, cpus=None, memory=None,
817820
:param int instance_id: Instance id of the VS to be upgraded
818821
:param int cpus: The number of virtual CPUs to upgrade to
819822
of a VS instance.
823+
:param string preset: preset assigned to the vsi
820824
:param int memory: RAM of the VS to be upgraded to.
821825
:param int nic_speed: The port speed to set
822826
:param bool public: CPU will be in Private/Public Node.
@@ -826,9 +830,28 @@ def upgrade(self, instance_id, cpus=None, memory=None,
826830
upgrade_prices = self._get_upgrade_prices(instance_id)
827831
prices = []
828832

829-
for option, value in {'cpus': cpus,
830-
'memory': memory,
831-
'nic_speed': nic_speed}.items():
833+
data = {'nic_speed': nic_speed}
834+
835+
if cpus is not None and preset is not None:
836+
raise exceptions.SoftLayerError("Do not use cpu, private and memory if you are using flavors")
837+
data['cpus'] = cpus
838+
839+
if memory is not None and preset is not None:
840+
raise exceptions.SoftLayerError("Do not use memory, private or cpu if you are using flavors")
841+
data['memory'] = memory
842+
843+
maintenance_window = datetime.datetime.now(utils.UTC())
844+
order = {
845+
'complexType': 'SoftLayer_Container_Product_Order_Virtual_Guest_'
846+
'Upgrade',
847+
'properties': [{
848+
'name': 'MAINTENANCE_WINDOW',
849+
'value': maintenance_window.strftime("%Y-%m-%d %H:%M:%S%z")
850+
}],
851+
'virtualGuests': [{'id': int(instance_id)}],
852+
}
853+
854+
for option, value in data.items():
832855
if not value:
833856
continue
834857
price_id = self._get_price_id_for_upgrade_option(upgrade_prices,
@@ -841,19 +864,13 @@ def upgrade(self, instance_id, cpus=None, memory=None,
841864
"Unable to find %s option with value %s" % (option, value))
842865

843866
prices.append({'id': price_id})
867+
order['prices'] = prices
844868

845-
maintenance_window = datetime.datetime.now(utils.UTC())
846-
order = {
847-
'complexType': 'SoftLayer_Container_Product_Order_Virtual_Guest_'
848-
'Upgrade',
849-
'prices': prices,
850-
'properties': [{
851-
'name': 'MAINTENANCE_WINDOW',
852-
'value': maintenance_window.strftime("%Y-%m-%d %H:%M:%S%z")
853-
}],
854-
'virtualGuests': [{'id': int(instance_id)}],
855-
}
856-
if prices:
869+
if preset is not None:
870+
vs_object = self.get_instance(instance_id)['billingItem']['package']
871+
order['presetId'] = self.ordering_manager.get_preset_by_key(vs_object['keyName'], preset)['id']
872+
873+
if prices or preset:
857874
self.client['Product_Order'].placeOrder(order)
858875
return True
859876
return False

setup.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
[tool:pytest]
22
python_files = *_tests.py
3+
filterwarnings =
4+
ignore::DeprecationWarning
5+
ignore::PendingDeprecationWarning
36

47
[wheel]
58
universal=1

tests/CLI/modules/order_tests.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,50 +47,43 @@ def test_item_list(self):
4747
self.assertEqual(expected_results, json.loads(result.output))
4848

4949
def test_package_list(self):
50-
item1 = {'name': 'package1', 'keyName': 'PACKAGE1', 'type': {'keyName': 'BARE_METAL_CPU'}, 'isActive': 1}
51-
item2 = {'name': 'package2', 'keyName': 'PACKAGE2', 'type': {'keyName': 'BARE_METAL_CPU'}, 'isActive': 1}
52-
item3 = {'name': 'package2', 'keyName': 'PACKAGE2', 'type': {'keyName': 'BARE_METAL_CPU'}, 'isActive': 0}
5350
p_mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects')
54-
p_mock.return_value = [item1, item2, item3]
51+
p_mock.return_value = _get_all_packages()
5552
_filter = {'type': {'keyName': {'operation': '!= BLUEMIX_SERVICE'}}}
5653

5754
result = self.run_command(['order', 'package-list'])
5855

5956
self.assert_no_fail(result)
6057
self.assert_called_with('SoftLayer_Product_Package', 'getAllObjects', filter=_filter)
61-
expected_results = [{'name': 'package1', 'keyName': 'PACKAGE1', 'type': 'BARE_METAL_CPU'},
62-
{'name': 'package2', 'keyName': 'PACKAGE2', 'type': 'BARE_METAL_CPU'}]
58+
expected_results = [{'id': 1, 'name': 'package1', 'keyName': 'PACKAGE1', 'type': 'BARE_METAL_CPU'},
59+
{'id': 2, 'name': 'package2', 'keyName': 'PACKAGE2', 'type': 'BARE_METAL_CPU'}]
6360
self.assertEqual(expected_results, json.loads(result.output))
6461

6562
def test_package_list_keyword(self):
66-
item1 = {'name': 'package1', 'keyName': 'PACKAGE1', 'type': {'keyName': 'BARE_METAL_CPU'}, 'isActive': 1}
67-
item2 = {'name': 'package2', 'keyName': 'PACKAGE2', 'type': {'keyName': 'BARE_METAL_CPU'}, 'isActive': 1}
6863
p_mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects')
69-
p_mock.return_value = [item1, item2]
64+
p_mock.return_value = _get_all_packages()
7065

7166
_filter = {'type': {'keyName': {'operation': '!= BLUEMIX_SERVICE'}}}
7267
_filter['name'] = {'operation': '*= package1'}
7368
result = self.run_command(['order', 'package-list', '--keyword', 'package1'])
7469

7570
self.assert_no_fail(result)
7671
self.assert_called_with('SoftLayer_Product_Package', 'getAllObjects', filter=_filter)
77-
expected_results = [{'name': 'package1', 'keyName': 'PACKAGE1', 'type': 'BARE_METAL_CPU'},
78-
{'name': 'package2', 'keyName': 'PACKAGE2', 'type': 'BARE_METAL_CPU'}]
72+
expected_results = [{'id': 1, 'name': 'package1', 'keyName': 'PACKAGE1', 'type': 'BARE_METAL_CPU'},
73+
{'id': 2, 'name': 'package2', 'keyName': 'PACKAGE2', 'type': 'BARE_METAL_CPU'}]
7974
self.assertEqual(expected_results, json.loads(result.output))
8075

8176
def test_package_list_type(self):
82-
item1 = {'name': 'package1', 'keyName': 'PACKAGE1', 'type': {'keyName': 'BARE_METAL_CPU'}, 'isActive': 1}
83-
item2 = {'name': 'package2', 'keyName': 'PACKAGE2', 'type': {'keyName': 'BARE_METAL_CPU'}, 'isActive': 1}
8477
p_mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects')
85-
p_mock.return_value = [item1, item2]
78+
p_mock.return_value = _get_all_packages()
8679

8780
_filter = {'type': {'keyName': {'operation': 'BARE_METAL_CPU'}}}
8881
result = self.run_command(['order', 'package-list', '--package_type', 'BARE_METAL_CPU'])
8982

9083
self.assert_no_fail(result)
9184
self.assert_called_with('SoftLayer_Product_Package', 'getAllObjects', filter=_filter)
92-
expected_results = [{'name': 'package1', 'keyName': 'PACKAGE1', 'type': 'BARE_METAL_CPU'},
93-
{'name': 'package2', 'keyName': 'PACKAGE2', 'type': 'BARE_METAL_CPU'}]
85+
expected_results = [{'id': 1, 'name': 'package1', 'keyName': 'PACKAGE1', 'type': 'BARE_METAL_CPU'},
86+
{'id': 2, 'name': 'package2', 'keyName': 'PACKAGE2', 'type': 'BARE_METAL_CPU'}]
9487
self.assertEqual(expected_results, json.loads(result.output))
9588

9689
def test_place(self):
@@ -256,3 +249,13 @@ def _get_verified_order_return(self):
256249
price2 = {'item': item2, 'hourlyRecurringFee': '0.05',
257250
'recurringFee': '150'}
258251
return {'orderContainers': [{'prices': [price1, price2]}]}
252+
253+
254+
def _get_all_packages():
255+
package_type = {'keyName': 'BARE_METAL_CPU'}
256+
all_packages = [
257+
{'id': 1, 'name': 'package1', 'keyName': 'PACKAGE1', 'type': package_type, 'isActive': 1},
258+
{'id': 2, 'name': 'package2', 'keyName': 'PACKAGE2', 'type': package_type, 'isActive': 1},
259+
{'id': 3, 'name': 'package2', 'keyName': 'PACKAGE2', 'type': package_type, 'isActive': 0}
260+
]
261+
return all_packages

tests/CLI/modules/vs_tests.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,23 @@ def test_upgrade(self, confirm_mock):
912912
self.assertIn({'id': 1122}, order_container['prices'])
913913
self.assertEqual(order_container['virtualGuests'], [{'id': 100}])
914914

915+
@mock.patch('SoftLayer.CLI.formatting.confirm')
916+
def test_upgrade_with_flavor(self, confirm_mock):
917+
confirm_mock.return_value = True
918+
result = self.run_command(['vs', 'upgrade', '100', '--flavor=M1_64X512X100'])
919+
self.assert_no_fail(result)
920+
self.assert_called_with('SoftLayer_Product_Order', 'placeOrder')
921+
call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0]
922+
order_container = call.args[0]
923+
self.assertEqual(799, order_container['presetId'])
924+
self.assertIn({'id': 100}, order_container['virtualGuests'])
925+
self.assertEqual(order_container['virtualGuests'], [{'id': 100}])
926+
927+
def test_upgrade_with_cpu_memory_and_flavor(self):
928+
result = self.run_command(['vs', 'upgrade', '100', '--cpu=4',
929+
'--memory=1024', '--flavor=M1_64X512X100'])
930+
self.assertEqual("Do not use cpu, private and memory if you are using flavors", str(result.exception))
931+
915932
def test_edit(self):
916933
result = self.run_command(['vs', 'edit',
917934
'--domain=example.com',

tests/managers/vs_tests.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,22 @@ def test_upgrade_full(self):
879879
self.assertIn({'id': 1122}, order_container['prices'])
880880
self.assertEqual(order_container['virtualGuests'], [{'id': 1}])
881881

882+
def test_upgrade_with_flavor(self):
883+
# Testing Upgrade with parameter preset
884+
result = self.vs.upgrade(1,
885+
preset="M1_64X512X100",
886+
nic_speed=1000,
887+
public=True)
888+
889+
self.assertEqual(result, True)
890+
self.assert_called_with('SoftLayer_Product_Order', 'placeOrder')
891+
call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0]
892+
order_container = call.args[0]
893+
self.assertEqual(799, order_container['presetId'])
894+
self.assertIn({'id': 1}, order_container['virtualGuests'])
895+
self.assertIn({'id': 1122}, order_container['prices'])
896+
self.assertEqual(order_container['virtualGuests'], [{'id': 1}])
897+
882898
def test_upgrade_dedicated_host_instance(self):
883899
mock = self.set_mock('SoftLayer_Virtual_Guest', 'getUpgradeItemPrices')
884900
mock.return_value = fixtures.SoftLayer_Virtual_Guest.DEDICATED_GET_UPGRADE_ITEM_PRICES

0 commit comments

Comments
 (0)