Skip to content

Commit d7941ad

Browse files
Merge branch 'master' into issue_1990
2 parents 941b49e + 2831a43 commit d7941ad

File tree

9 files changed

+161
-22
lines changed

9 files changed

+161
-22
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""Delete bandwidth pool."""
2+
# :license: MIT, see LICENSE for more details.
3+
import click
4+
5+
from SoftLayer import BandwidthManager
6+
from SoftLayer.CLI.command import SLCommand as SLCommand
7+
from SoftLayer.CLI import environment
8+
9+
10+
@click.command(cls=SLCommand)
11+
@click.argument('identifier')
12+
@environment.pass_env
13+
def cli(env, identifier):
14+
"""Delete bandwidth pool."""
15+
16+
manager = BandwidthManager(env.client)
17+
manager.delete_pool(identifier)
18+
env.fout(f"Bandwidth pool {identifier} has been scheduled for deletion.")
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""Edit bandwidth pool."""
2+
# :license: MIT, see LICENSE for more details.
3+
import click
4+
5+
from SoftLayer import BandwidthManager
6+
from SoftLayer.CLI.command import SLCommand as SLCommand
7+
from SoftLayer.CLI import environment
8+
from SoftLayer.CLI import formatting
9+
from SoftLayer import utils
10+
11+
location_groups = {
12+
"SJC/DAL/WDC/TOR/MON": "US/Canada",
13+
"AMS/LON/MAD/PAR": "AMS/LON/MAD/PAR",
14+
"SNG/HKG/OSA/TOK": "SNG/HKG/JPN",
15+
"SYD": "AUS",
16+
"MEX": "MEX",
17+
"SAO": "BRA",
18+
"CHE": "IND",
19+
"MIL": "ITA",
20+
"SEO": "KOR",
21+
"FRA": "FRA"
22+
}
23+
24+
25+
@click.command(cls=SLCommand)
26+
@click.argument('identifier')
27+
@click.option('--name', required=True, help="Pool name")
28+
@environment.pass_env
29+
def cli(env, identifier, name):
30+
"""Edit bandwidth pool."""
31+
32+
manager = BandwidthManager(env.client)
33+
bandwidth_pool = manager.edit_pool(identifier, name)
34+
35+
if bandwidth_pool:
36+
37+
edited_pool = manager.get_bandwidth_detail(identifier)
38+
locations = manager.get_location_group()
39+
40+
location = next(
41+
(location for location in locations if location['id'] == edited_pool.get('locationGroupId')), None)
42+
43+
region_name = next((key for key, value in location_groups.items() if value == location.get('name')), None)
44+
45+
table = formatting.KeyValueTable(['Name', 'Value'])
46+
table.add_row(['Id', edited_pool.get('id')])
47+
table.add_row(['Name Pool', name])
48+
table.add_row(['Region', region_name])
49+
table.add_row(['Created Date', utils.clean_time(edited_pool.get('createDate'))])
50+
env.fout(table)

SoftLayer/CLI/routes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,8 @@
425425
('bandwidth:pools', 'SoftLayer.CLI.bandwidth.pools:cli'),
426426
('bandwidth:pools-detail', 'SoftLayer.CLI.bandwidth.pools_detail:cli'),
427427
('bandwidth:pools-create', 'SoftLayer.CLI.bandwidth.pools_create:cli'),
428+
('bandwidth:pools-edit', 'SoftLayer.CLI.bandwidth.pools_edit:cli'),
429+
('bandwidth:pools-delete', 'SoftLayer.CLI.bandwidth.pools_delete:cli'),
428430
]
429431

430432
ALL_ALIASES = {

SoftLayer/fixtures/SoftLayer_Network_Bandwidth_Version1_Allotment.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,7 @@
156156
"name": "NewRegion",
157157
"serviceProviderId": 1
158158
}
159+
160+
editObject = True
161+
162+
requestVdrCancellation = True

SoftLayer/managers/bandwidth.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,36 @@ def create_pool(self, name_pool, id_location_group):
4343
}
4444

4545
return self.client.call('Network_Bandwidth_Version1_Allotment', 'createObject', template)
46+
47+
def get_bandwidth_detail(self, identifier):
48+
"""Gets bandwidth pool detail.
49+
50+
:returns: bandwidth pool detail
51+
"""
52+
_mask = """activeDetails[allocation],projectedPublicBandwidthUsage, billingCyclePublicBandwidthUsage,
53+
hardware[outboundBandwidthUsage,bandwidthAllotmentDetail[allocation]],inboundPublicBandwidthUsage,
54+
virtualGuests[outboundPublicBandwidthUsage,bandwidthAllotmentDetail[allocation]],
55+
bareMetalInstances[outboundBandwidthUsage,bandwidthAllotmentDetail[allocation]]"""
56+
return self.client['SoftLayer_Network_Bandwidth_Version1_Allotment'].getObject(id=identifier, mask=_mask)
57+
58+
def edit_pool(self, identifier, new_name_pool):
59+
"""Edit bandwidth pool name
60+
61+
:return: Bandwidth object
62+
"""
63+
actual_bandwidth = self.get_bandwidth_detail(identifier)
64+
template = {
65+
"accountId": actual_bandwidth.get('accountId'),
66+
"bandwidthAllotmentTypeId": actual_bandwidth.get('bandwidthAllotmentTypeId'),
67+
"locationGroupId": actual_bandwidth.get('locationGroupId'),
68+
"name": new_name_pool
69+
}
70+
71+
return self.client.call('Network_Bandwidth_Version1_Allotment', 'editObject', template, id=identifier)
72+
73+
def delete_pool(self, identifier):
74+
"""Delete bandwidth pool
75+
76+
:return: Boolean value
77+
"""
78+
return self.client.call('Network_Bandwidth_Version1_Allotment', 'requestVdrCancellation', id=identifier)

SoftLayer/managers/ordering.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
from SoftLayer import exceptions
1212

13+
from SoftLayer import utils
14+
1315
CATEGORY_MASK = '''id, isRequired, itemCategory[id, name, categoryCode]'''
1416

1517
ITEM_MASK = '''id, keyName, description, itemCategory, categories, prices'''
@@ -32,6 +34,8 @@ def __init__(self, client):
3234
self.order_svc = client['Product_Order']
3335
self.billing_svc = client['Billing_Order']
3436
self.package_preset = client['Product_Package_Preset']
37+
self.package_mask = 'id, description, capacity, itemCategory, keyName, prices[categories], ' \
38+
'softwareDescription[id,referenceCode,longDescription]'
3539

3640
def get_packages_of_type(self, package_types, mask=None):
3741
"""Get packages that match a certain type.
@@ -370,22 +374,27 @@ def get_price_id_list(self, package_keyname, item_keynames, core=None):
370374
keynames in the given package
371375
372376
"""
373-
mask = 'id, description, capacity, itemCategory, keyName, prices[categories]'
377+
mask = 'id, description, capacity, itemCategory, keyName, prices[categories], ' \
378+
'softwareDescription[id,referenceCode,longDescription]'
374379
items = self.list_items(package_keyname, mask=mask)
375380
item_capacity = self.get_item_capacity(items, item_keynames)
376381

377382
prices = []
378383
category_dict = {"gpu0": -1, "pcie_slot0": -1}
379384

380385
for item_keyname in item_keynames:
381-
try:
382-
# Need to find the item in the package that has a matching
383-
# keyName with the current item we are searching for
384-
matching_item = [i for i in items
385-
if i['keyName'] == item_keyname][0]
386-
except IndexError as ex:
386+
matching_item = []
387+
# Need to find the item in the package that has a matching
388+
# keyName with the current item we are searching for
389+
for i in items:
390+
reference_code = utils.lookup(i, 'softwareDescription', 'referenceCode')
391+
if i['keyName'] == item_keyname or reference_code == item_keyname:
392+
matching_item.append(i)
393+
394+
if len(matching_item) == 0:
387395
message = f"Item {item_keyname} does not exist for package {package_keyname}"
388-
raise exceptions.SoftLayerError(message) from ex
396+
raise exceptions.SoftLayerError(message)
397+
matching_item = matching_item[0]
389398

390399
# we want to get the price ID that has no location attached to it,
391400
# because that is the most generic price. verifyOrder/placeOrder

docs/cli/bandwidth.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,11 @@ bandwidth Commands
1919
.. click:: SoftLayer.CLI.bandwidth.pools_create:cli
2020
:prog: bandwidth pools-create
2121
:show-nested:
22+
23+
.. click:: SoftLayer.CLI.bandwidth.pools_edit:cli
24+
:prog: bandwidth pools-edit
25+
:show-nested:
26+
27+
.. click:: SoftLayer.CLI.bandwidth.pools_delete:cli
28+
:prog: bandwidth pools-delete
29+
:show-nested:

tests/CLI/modules/bandwidth_tests.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
import json
1010

11-
from pprint import pprint as pp
12-
1311

1412
class BandwidthTests(testing.TestCase):
1513
def test_bandwidth_pools(self):
@@ -31,7 +29,6 @@ def test_bandwidth_summary(self):
3129
self.assert_no_fail(result)
3230
self.assert_called_with('SoftLayer_Search', 'advancedSearch')
3331
json_output = json.loads(result.output)
34-
pp(json_output)
3532
self.assertEqual(5, len(json_output))
3633
self.assertEqual(100250634, json_output[0]['Id'])
3734
self.assertEqual('TestRegion', json_output[0]['Pool'])
@@ -51,11 +48,26 @@ def test_create_bandwidth(self):
5148
self.assert_no_fail(result)
5249
self.assert_called_with('SoftLayer_Network_Bandwidth_Version1_Allotment', 'createObject')
5350
json_output = json.loads(result.output)
54-
pp(json_output)
5551
self.assertEqual(123456789, json_output['Id'])
5652
self.assertEqual('NewRegion', json_output['Name Pool'])
5753
self.assertEqual('SJC/DAL/WDC/TOR/MON', json_output['Region'])
5854

55+
def test_edit_bandwidth(self):
56+
result = self.run_command(['bandwidth', 'pools-edit', '123456', '--name=MexRegionEdited'])
57+
self.assert_no_fail(result)
58+
self.assert_called_with('SoftLayer_Network_Bandwidth_Version1_Allotment', 'editObject')
59+
json_output = json.loads(result.output)
60+
self.assertEqual(123456, json_output['Id'])
61+
self.assertEqual('MexRegionEdited', json_output['Name Pool'])
62+
self.assertEqual('MEX', json_output['Region'])
63+
64+
def test_delete_bandwidth(self):
65+
result = self.run_command(['bandwidth', 'pools-delete', '123456'])
66+
self.assert_no_fail(result)
67+
self.assert_called_with('SoftLayer_Network_Bandwidth_Version1_Allotment', 'requestVdrCancellation')
68+
json_output = json.loads(result.output)
69+
self.assertEqual("Bandwidth pool 123456 has been scheduled for deletion.", json_output)
70+
5971
def test_create_bandwidth_single_region(self):
6072
result = self.run_command(['bandwidth', 'pools-create', '--name=NewRegion', '--region=AMS'])
6173
self.assert_no_fail(result)

tests/managers/ordering_tests.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,7 @@ def test_get_price_id_list(self):
316316

317317
prices = self.ordering.get_price_id_list('PACKAGE_KEYNAME', ['ITEM1', 'ITEM2'], "8")
318318

319-
list_mock.assert_called_once_with('PACKAGE_KEYNAME', mask='id, description, capacity, itemCategory, keyName, '
320-
'prices[categories]')
319+
list_mock.assert_called_once_with('PACKAGE_KEYNAME', mask=self.ordering.package_mask)
321320
self.assertEqual([price1['id'], price2['id']], prices)
322321

323322
def test_get_price_id_list_no_core(self):
@@ -335,22 +334,24 @@ def test_get_price_id_list_no_core(self):
335334
prices = self.ordering.get_price_id_list('PACKAGE_KEYNAME', ['ITEM1', 'ITEM2'], None)
336335

337336
list_mock.assert_called_once_with('PACKAGE_KEYNAME', mask='id, description, capacity, itemCategory, keyName, '
338-
'prices[categories]')
337+
'prices[categories], softwareDescription[id,referenceCode,longDescription]')
339338
self.assertEqual([price1['id'], price2['id']], prices)
340339

341340
def test_get_price_id_list_item_not_found(self):
342341
category1 = {'categoryCode': 'cat1'}
343342
price1 = {'id': 1234, 'locationGroupId': '', 'categories': [category1]}
344-
item1 = {'id': 1111, 'keyName': 'ITEM1', 'itemCategory': category1, 'prices': [price1]}
343+
softwareDescription1 = {'id': 1234, 'longDescription': 'ABCD 1.2-34', 'referenceCode': 'ABCD_9_32'}
344+
item1 = {'id': 1111, 'keyName': 'ITEM1', 'itemCategory': category1,
345+
'prices': [price1], 'softwareDescription': softwareDescription1, }
345346

346347
with mock.patch.object(self.ordering, 'list_items') as list_mock:
347348
list_mock.return_value = [item1]
348349

349350
exc = self.assertRaises(exceptions.SoftLayerError,
350351
self.ordering.get_price_id_list,
351-
'PACKAGE_KEYNAME', ['ITEM2'], "8")
352+
'PACKAGE_KEYNAME', ['ITEM2'], "12")
352353
list_mock.assert_called_once_with('PACKAGE_KEYNAME', mask='id, description, capacity, itemCategory, keyName, '
353-
'prices[categories]')
354+
'prices[categories], softwareDescription[id,referenceCode,longDescription]')
354355
self.assertEqual("Item ITEM2 does not exist for package PACKAGE_KEYNAME", str(exc))
355356

356357
def test_get_price_id_list_gpu_items_with_two_categories(self):
@@ -365,7 +366,8 @@ def test_get_price_id_list_gpu_items_with_two_categories(self):
365366
prices = self.ordering.get_price_id_list('PACKAGE_KEYNAME', ['ITEM1', 'ITEM1'], "8")
366367

367368
list_mock.assert_called_once_with('PACKAGE_KEYNAME', mask='id, description, capacity, itemCategory, '
368-
'keyName, ' 'prices[categories]')
369+
'keyName, prices[categories], '
370+
'softwareDescription[id,referenceCode,longDescription]')
369371
self.assertEqual([price2['id'], price1['id']], prices)
370372

371373
def test_generate_no_complex_type(self):
@@ -620,7 +622,7 @@ def test_location_group_id_none(self):
620622
prices = self.ordering.get_price_id_list('PACKAGE_KEYNAME', ['ITEM1', 'ITEM2'], "8")
621623

622624
list_mock.assert_called_once_with('PACKAGE_KEYNAME', mask='id, description, capacity, itemCategory, keyName, '
623-
'prices[categories]')
625+
'prices[categories], softwareDescription[id,referenceCode,longDescription]')
624626
self.assertEqual([price1['id'], price2['id']], prices)
625627

626628
def test_location_groud_id_empty(self):
@@ -637,8 +639,9 @@ def test_location_groud_id_empty(self):
637639

638640
prices = self.ordering.get_price_id_list('PACKAGE_KEYNAME', ['ITEM1', 'ITEM2'], "8")
639641

640-
list_mock.assert_called_once_with('PACKAGE_KEYNAME', mask='id, description, capacity, itemCategory, keyName, '
641-
'prices[categories]')
642+
list_mock.assert_called_once_with('PACKAGE_KEYNAME', mask='id, description, capacity, itemCategory, '
643+
'keyName, prices[categories], '
644+
'softwareDescription[id,referenceCode,longDescription]')
642645
self.assertEqual([price1['id'], price2['id']], prices)
643646

644647
def test_get_item_price_id_without_capacity_restriction(self):

0 commit comments

Comments
 (0)