Skip to content

Commit 26a7e66

Browse files
Merge pull request #1442 from FernandoOjeda/ft/virtual_authorize_storage
Add authorize block, file and portable storage to a vs.
2 parents 4b68924 + 4ff8aba commit 26a7e66

File tree

8 files changed

+163
-0
lines changed

8 files changed

+163
-0
lines changed

SoftLayer/CLI/routes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
('virtual:upgrade', 'SoftLayer.CLI.virt.upgrade:cli'),
4646
('virtual:usage', 'SoftLayer.CLI.virt.usage:cli'),
4747
('virtual:credentials', 'SoftLayer.CLI.virt.credentials:cli'),
48+
('virtual:authorize-storage', 'SoftLayer.CLI.virt.authorize_storage:cli'),
4849
('virtual:capacity', 'SoftLayer.CLI.virt.capacity:cli'),
4950
('virtual:placementgroup', 'SoftLayer.CLI.virt.placementgroup:cli'),
5051
('virtual:migrate', 'SoftLayer.CLI.virt.migrate:cli'),
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""Authorize File, Block and Portable Storage to a Virtual Server"""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import click
5+
6+
import SoftLayer
7+
from SoftLayer.CLI import environment
8+
from SoftLayer.CLI import exceptions
9+
from SoftLayer.CLI import formatting
10+
from SoftLayer.CLI import helpers
11+
12+
13+
@click.command()
14+
@click.argument('identifier')
15+
@click.option('--username-storage', '-u', type=click.STRING,
16+
help="The storage username to be added to the virtual server")
17+
@click.option('--portable-id', type=click.INT,
18+
help="The portable storage id to be added to the virtual server")
19+
@environment.pass_env
20+
def cli(env, identifier, username_storage, portable_id):
21+
"""Authorize File, Block and Portable Storage to a Virtual Server."""
22+
virtual = SoftLayer.VSManager(env.client)
23+
virtual_id = helpers.resolve_id(virtual.resolve_ids, identifier, 'virtual')
24+
table = formatting.KeyValueTable(['name', 'value'], title="Portable Storage Detail")
25+
table.align['name'] = 'r'
26+
table.align['value'] = 'l'
27+
28+
if username_storage:
29+
if not virtual.authorize_storage(virtual_id, username_storage):
30+
raise exceptions.CLIAbort('Authorize Volume Failed')
31+
env.fout('Successfully Volume: %s was Added.' % username_storage)
32+
if portable_id:
33+
portable_id = helpers.resolve_id(virtual.resolve_ids, portable_id, 'storage')
34+
portable_result = virtual.attach_portable_storage(virtual_id, portable_id)
35+
36+
env.fout('Successfully Portable Storage: %i was Added.' % portable_id)
37+
38+
table.add_row(['Id', portable_result['id']])
39+
table.add_row(['createDate', portable_result['createDate']])
40+
env.fout(table)

SoftLayer/fixtures/SoftLayer_Account.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,3 +1057,22 @@
10571057
"statusId": 2
10581058
}
10591059
}]
1060+
1061+
getNetworkStorage = [
1062+
{
1063+
"accountId": 1111111,
1064+
"capacityGb": 20,
1065+
"createDate": "2016-01-21T12:11:07-06:00",
1066+
"id": 1234567,
1067+
"nasType": "ISCSI",
1068+
"username": "SL01SEL301234-11",
1069+
},
1070+
{
1071+
"accountId": 1111111,
1072+
"capacityGb": 20,
1073+
"createDate": "2015-04-29T07:55:55-06:00",
1074+
"id": 4917123,
1075+
"nasType": "NAS",
1076+
"username": "SL01SEV1234567_111"
1077+
}
1078+
]

SoftLayer/fixtures/SoftLayer_Virtual_Guest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,3 +876,9 @@
876876

877877
migrate = True
878878
migrateDedicatedHost = True
879+
allowAccessToNetworkStorageList = True
880+
881+
attachDiskImage = {
882+
"createDate": "2021-03-22T13:15:31-06:00",
883+
"id": 1234567
884+
}

SoftLayer/managers/vs.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,3 +1404,45 @@ def get_hardware_guests(self):
14041404
object_filter = {"hardware": {"virtualHost": {"id": {"operation": "not null"}}}}
14051405
mask = "mask[virtualHost[guests[powerState]]]"
14061406
return self.client.call('SoftLayer_Account', 'getHardware', mask=mask, filter=object_filter)
1407+
1408+
def authorize_storage(self, vs_id, username_storage):
1409+
"""Authorize File or Block Storage to a Virtual Server.
1410+
1411+
:param int vs_id: Virtual server id.
1412+
:param string username_storage: Storage username.
1413+
1414+
:return: bool.
1415+
"""
1416+
_filter = {"networkStorage": {"username": {"operation": username_storage}}}
1417+
1418+
storage_result = self.client.call('Account', 'getNetworkStorage', filter=_filter)
1419+
1420+
if len(storage_result) == 0:
1421+
raise SoftLayerError("The Storage with username: %s was not found, please"
1422+
" enter a valid storage username" % username_storage)
1423+
1424+
storage_template = [
1425+
{
1426+
"id": storage_result[0]['id'],
1427+
"username": username_storage
1428+
}
1429+
]
1430+
1431+
result = self.client.call('SoftLayer_Virtual_Guest', 'allowAccessToNetworkStorageList',
1432+
storage_template, id=vs_id)
1433+
1434+
return result
1435+
1436+
def attach_portable_storage(self, vs_id, portable_id):
1437+
"""Attach portal storage to a Virtual Server.
1438+
1439+
:param int vs_id: Virtual server id.
1440+
:param int portable_id: Portal storage id.
1441+
1442+
:return: SoftLayer_Provisioning_Version1_Transaction.
1443+
"""
1444+
disk_id = portable_id
1445+
result = self.client.call('SoftLayer_Virtual_Guest', 'attachDiskImage',
1446+
disk_id, id=vs_id)
1447+
1448+
return result

docs/cli/vs.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,10 @@ If no timezone is specified, IMS local time (CST) will be assumed, which might n
267267
:prog: virtual migrate
268268
:show-nested:
269269

270+
.. click:: SoftLayer.CLI.virt.authorize_storage:cli
271+
:prog: virtual authorize-storage
272+
:show-nested:
273+
270274
Manages the migration of virutal guests. Supports migrating virtual guests on Dedicated Hosts as well.
271275

272276
Reserved Capacity

tests/CLI/modules/vs/vs_tests.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,3 +892,38 @@ def test_credentail(self):
892892
"username": "user",
893893
"password": "pass"
894894
}])
895+
896+
@mock.patch('SoftLayer.CLI.formatting.confirm')
897+
def test_authorize_storage_vs_no_confirm(self, confirm_mock):
898+
confirm_mock.return_value = False
899+
result = self.run_command(['vs', 'authorize-storage', '-u', '1234'])
900+
901+
self.assertEqual(result.exit_code, 2)
902+
903+
@mock.patch('SoftLayer.CLI.formatting.confirm')
904+
def test_authorize_vs_empty(self, confirm_mock):
905+
confirm_mock.return_value = True
906+
storage_result = self.set_mock('SoftLayer_Account', 'getNetworkStorage')
907+
storage_result.return_value = []
908+
result = self.run_command(['vs', 'authorize-storage', '--username-storage=#', '1234'])
909+
910+
self.assertEqual(str(result.exception), "The Storage with username: # was not found, "
911+
"please enter a valid storage username")
912+
913+
def test_authorize_storage_vs(self):
914+
result = self.run_command(['vs', 'authorize-storage', '--username-storage=SL01SEL301234-11', '1234'])
915+
self.assert_no_fail(result)
916+
917+
def test_authorize_portable_storage_vs(self):
918+
mock = self.set_mock('SoftLayer_Virtual_Guest', 'attachDiskImage')
919+
mock.return_value = {
920+
"createDate": "2021-03-22T13:15:31-06:00",
921+
"id": 1234567
922+
}
923+
result = self.run_command(['vs', 'authorize-storage', '--portable-id=12345', '1234'])
924+
self.assert_no_fail(result)
925+
926+
def test_authorize_volume_and_portable_storage_vs(self):
927+
result = self.run_command(['vs', 'authorize-storage', '--username-storage=SL01SEL301234-11',
928+
'--portable-id=12345', '1234'])
929+
self.assert_no_fail(result)

tests/managers/vs/vs_tests.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,3 +1309,19 @@ def test_get_hardware_guests(self):
13091309

13101310
result = self.vs.get_hardware_guests()
13111311
self.assertEqual("NSX-T Manager", result[0]['virtualHost']['guests'][0]['hostname'])
1312+
1313+
def test_authorize_storage(self):
1314+
options = self.vs.authorize_storage(1234, "SL01SEL301234-11")
1315+
1316+
self.assertEqual(True, options)
1317+
1318+
def test_authorize_storage_empty(self):
1319+
mock = self.set_mock('SoftLayer_Account', 'getNetworkStorage')
1320+
mock.return_value = []
1321+
self.assertRaises(SoftLayer.exceptions.SoftLayerError,
1322+
self.vs.authorize_storage,
1323+
1234, "#")
1324+
1325+
def test_authorize_portable_storage(self):
1326+
options = self.vs.attach_portable_storage(1234, 1234567)
1327+
self.assertEqual(1234567, options['id'])

0 commit comments

Comments
 (0)