Skip to content

Commit 23a748a

Browse files
Merge pull request #1249 from FernandoOjeda/issue_1241
Storage feature for virtual and hardware servers
2 parents f4f403c + 3bffd7a commit 23a748a

File tree

17 files changed

+924
-4
lines changed

17 files changed

+924
-4
lines changed

SoftLayer/CLI/hardware/detail.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,23 @@ def cli(env, identifier, passwords, price):
2727
hardware_id = helpers.resolve_id(hardware.resolve_ids, identifier, 'hardware')
2828
result = hardware.get_hardware(hardware_id)
2929
result = utils.NestedDict(result)
30+
hard_drives = hardware.get_hard_drives(hardware_id)
3031

3132
operating_system = utils.lookup(result, 'operatingSystem', 'softwareLicense', 'softwareDescription') or {}
3233
memory = formatting.gb(result.get('memoryCapacity', 0))
3334
owner = None
3435
if utils.lookup(result, 'billingItem') != []:
3536
owner = utils.lookup(result, 'billingItem', 'orderItem', 'order', 'userRecord', 'username')
3637

38+
table_hard_drives = formatting.Table(['Name', 'Capacity', 'Serial #'])
39+
for drives in hard_drives:
40+
name = drives['hardwareComponentModel']['manufacturer'] + " " + drives['hardwareComponentModel']['name']
41+
capacity = str(drives['hardwareComponentModel']['hardwareGenericComponentModel']['capacity']) + " " + str(
42+
drives['hardwareComponentModel']['hardwareGenericComponentModel']['units'])
43+
serial = drives['serialNumber']
44+
45+
table_hard_drives.add_row([name, capacity, serial])
46+
3747
table.add_row(['id', result['id']])
3848
table.add_row(['guid', result['globalIdentifier'] or formatting.blank()])
3949
table.add_row(['hostname', result['hostname']])
@@ -43,6 +53,7 @@ def cli(env, identifier, passwords, price):
4353
table.add_row(['datacenter', result['datacenter']['name'] or formatting.blank()])
4454
table.add_row(['cores', result['processorPhysicalCoreAmount']])
4555
table.add_row(['memory', memory])
56+
table.add_row(['drives', table_hard_drives])
4657
table.add_row(['public_ip', result['primaryIpAddress'] or formatting.blank()])
4758
table.add_row(['private_ip', result['primaryBackendIpAddress'] or formatting.blank()])
4859
table.add_row(['ipmi_ip', result['networkManagementIpAddress'] or formatting.blank()])

SoftLayer/CLI/hardware/storage.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
"""Get storage details for a hardware 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 formatting
9+
from SoftLayer.CLI import helpers
10+
11+
12+
@click.command()
13+
@click.argument('identifier')
14+
@environment.pass_env
15+
def cli(env, identifier):
16+
"""Get storage details for a hardware server."""
17+
18+
hardware = SoftLayer.HardwareManager(env.client)
19+
hardware_id = helpers.resolve_id(hardware.resolve_ids, identifier, 'hardware')
20+
iscsi_storage_data = hardware.get_storage_details(hardware_id, "ISCSI")
21+
nas_storage_data = hardware.get_storage_details(hardware_id, "NAS")
22+
storage_credentials = hardware.get_storage_credentials(hardware_id)
23+
hard_drives = hardware.get_hard_drives(hardware_id)
24+
25+
table_credentials = formatting.Table(['Username', 'Password', 'IQN'], title="Block Storage Details \n iSCSI")
26+
if storage_credentials:
27+
table_credentials.add_row([storage_credentials['credential']['username'],
28+
storage_credentials['credential']['password'],
29+
storage_credentials['name']])
30+
31+
table_iscsi = formatting.Table(['LUN name', 'capacity', 'Target address', 'Location', 'Notes'])
32+
for iscsi in iscsi_storage_data:
33+
table_iscsi.add_row([iscsi['username'], iscsi['capacityGb'],
34+
iscsi['serviceResourceBackendIpAddress'],
35+
iscsi['allowedHardware'][0]['datacenter']['longName'],
36+
iscsi.get('notes', None)])
37+
38+
table_nas = formatting.Table(['Volume name', 'capacity', 'Host Name', 'Location', 'Notes'],
39+
title="File Storage Details")
40+
for nas in nas_storage_data:
41+
table_nas.add_row([nas['username'], nas['capacityGb'],
42+
nas['serviceResourceBackendIpAddress'],
43+
nas['allowedHardware'][0]['datacenter']['longName'],
44+
nas.get('notes', None)])
45+
46+
table_hard_drives = formatting.Table(['Type', 'Name', 'Capacity', 'Serial #'], title="Other storage details")
47+
for drives in hard_drives:
48+
type_drive = drives['hardwareComponentModel']['hardwareGenericComponentModel']['hardwareComponentType']['type']
49+
name = drives['hardwareComponentModel']['manufacturer'] + " " + drives['hardwareComponentModel']['name']
50+
capacity = str(drives['hardwareComponentModel']['hardwareGenericComponentModel']['capacity']) + " " + str(
51+
drives['hardwareComponentModel']['hardwareGenericComponentModel']['units'])
52+
serial = drives['serialNumber']
53+
54+
table_hard_drives.add_row([type_drive, name, capacity, serial])
55+
56+
env.fout(table_credentials)
57+
env.fout(table_iscsi)
58+
env.fout(table_nas)
59+
env.fout(table_hard_drives)

SoftLayer/CLI/routes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
('virtual:ready', 'SoftLayer.CLI.virt.ready:cli'),
4141
('virtual:reboot', 'SoftLayer.CLI.virt.power:reboot'),
4242
('virtual:reload', 'SoftLayer.CLI.virt.reload:cli'),
43+
('virtual:storage', 'SoftLayer.CLI.virt.storage:cli'),
4344
('virtual:upgrade', 'SoftLayer.CLI.virt.upgrade:cli'),
4445
('virtual:usage', 'SoftLayer.CLI.virt.usage:cli'),
4546
('virtual:credentials', 'SoftLayer.CLI.virt.credentials:cli'),
@@ -248,6 +249,7 @@
248249
('hardware:ready', 'SoftLayer.CLI.hardware.ready:cli'),
249250
('hardware:toggle-ipmi', 'SoftLayer.CLI.hardware.toggle_ipmi:cli'),
250251
('hardware:dns-sync', 'SoftLayer.CLI.hardware.dns:cli'),
252+
('hardware:storage', 'SoftLayer.CLI.hardware.storage:cli'),
251253

252254
('securitygroup', 'SoftLayer.CLI.securitygroup'),
253255
('securitygroup:list', 'SoftLayer.CLI.securitygroup.list:cli'),

SoftLayer/CLI/virt/detail.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ def cli(env, identifier, passwords=False, price=False):
3232
vs_id = helpers.resolve_id(vsi.resolve_ids, identifier, 'VS')
3333
result = vsi.get_instance(vs_id)
3434
result = utils.NestedDict(result)
35+
local_disks = vsi.get_local_disks(vs_id)
36+
37+
table_local_disks = formatting.Table(['Type', 'Name', 'Capacity'])
38+
for disks in local_disks:
39+
if 'diskImage' in disks:
40+
table_local_disks.add_row([get_local_type(disks), disks['mountType'],
41+
str(disks['diskImage']['capacity']) + " " + str(disks['diskImage']['units'])])
3542

3643
table.add_row(['id', result['id']])
3744
table.add_row(['guid', result['globalIdentifier']])
@@ -57,6 +64,7 @@ def cli(env, identifier, passwords=False, price=False):
5764
table.add_row(['os_version', operating_system.get('version', '-')])
5865
table.add_row(['cores', result['maxCpu']])
5966
table.add_row(['memory', formatting.mb_to_gb(result['maxMemory'])])
67+
table.add_row(['drives', table_local_disks])
6068
table.add_row(['public_ip', result.get('primaryIpAddress', '-')])
6169
table.add_row(['private_ip', result.get('primaryBackendIpAddress', '-')])
6270
table.add_row(['private_only', result['privateNetworkOnlyFlag']])
@@ -192,3 +200,15 @@ def _get_security_table(result):
192200
return secgroup_table
193201
else:
194202
return None
203+
204+
205+
def get_local_type(disks):
206+
"""Returns the virtual server local disk type.
207+
208+
:param disks: virtual serve local disks.
209+
"""
210+
disk_type = 'System'
211+
if 'SWAP' in disks['diskImage']['description']:
212+
disk_type = 'Swap'
213+
214+
return disk_type

SoftLayer/CLI/virt/storage.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""Get storage details for 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 formatting
9+
from SoftLayer.CLI import helpers
10+
11+
12+
@click.command()
13+
@click.argument('identifier')
14+
@environment.pass_env
15+
def cli(env, identifier):
16+
"""Get storage details for a virtual server."""
17+
18+
vsi = SoftLayer.VSManager(env.client)
19+
vsi_id = helpers.resolve_id(vsi.resolve_ids, identifier, 'VS')
20+
iscsi_storage_data = vsi.get_storage_details(vsi_id, "ISCSI")
21+
nas_storage_data = vsi.get_storage_details(vsi_id, "NAS")
22+
storage_credentials = vsi.get_storage_credentials(vsi_id)
23+
portable_storage = vsi.get_portable_storage(vsi_id)
24+
local_disks = vsi.get_local_disks(vsi_id)
25+
26+
table_credentials = formatting.Table(['Username', 'Password', 'IQN'], title="Block Storage Details \n iSCSI")
27+
if storage_credentials:
28+
table_credentials.add_row([storage_credentials['credential']['username'],
29+
storage_credentials['credential']['password'],
30+
storage_credentials['name']])
31+
32+
table_iscsi = formatting.Table(['LUN name', 'capacity', 'Target address', 'Location', 'Notes'])
33+
for iscsi in iscsi_storage_data:
34+
table_iscsi.add_row([iscsi['username'], iscsi['capacityGb'],
35+
iscsi['serviceResourceBackendIpAddress'],
36+
iscsi['allowedVirtualGuests'][0]['datacenter']['longName'],
37+
iscsi.get('notes', None)])
38+
39+
table_portable = formatting.Table(['Description', 'Capacity'], title="Portable Storage")
40+
for portable in portable_storage:
41+
table_portable.add_row([portable.get('description', None), portable.get('capacity', None)])
42+
43+
table_nas = formatting.Table(['Volume name', 'capacity', 'Host Name', 'Location', 'Notes'],
44+
title="File Storage Details")
45+
for nas in nas_storage_data:
46+
table_nas.add_row([nas['username'], nas['capacityGb'],
47+
nas['serviceResourceBackendIpAddress'],
48+
nas['allowedVirtualGuests'][0]['datacenter']['longName'],
49+
nas.get('notes', None)])
50+
51+
table_local_disks = formatting.Table(['Type', 'Name', 'Capacity'], title="Other storage details")
52+
for disks in local_disks:
53+
if 'diskImage' in disks:
54+
table_local_disks.add_row([get_local_type(disks), disks['mountType'],
55+
str(disks['diskImage']['capacity']) + " " + str(disks['diskImage']['units'])])
56+
57+
env.fout(table_credentials)
58+
env.fout(table_iscsi)
59+
env.fout(table_portable)
60+
env.fout(table_nas)
61+
env.fout(table_local_disks)
62+
63+
64+
def get_local_type(disks):
65+
"""Returns the virtual server local disk type.
66+
67+
:param disks: virtual serve local disks.
68+
"""
69+
disk_type = 'System'
70+
if 'SWAP' in disks['diskImage']['description']:
71+
disk_type = 'Swap'
72+
73+
return disk_type

SoftLayer/fixtures/SoftLayer_Account.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,22 @@
853853
}
854854
]
855855

856+
857+
getPortableStorageVolumes = [
858+
{
859+
"capacity": 200,
860+
"createDate": "2018-10-06T04:27:59-06:00",
861+
"description": "Disk 2",
862+
"id": 11111,
863+
"modifyDate": "",
864+
"name": "Disk 2",
865+
"parentId": "",
866+
"storageRepositoryId": 22222,
867+
"typeId": 241,
868+
"units": "GB",
869+
"uuid": "fd477feb-bf32-408e-882f-02540gghgh111"
870+
}
871+
]
856872
getAllTopLevelBillingItems = [
857873
{
858874
"allowCancellationFlag": 1,

SoftLayer/fixtures/SoftLayer_Hardware_Server.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,96 @@
149149
]
150150

151151
getMetricTrackingObjectId = 1000
152+
153+
getAttachedNetworkStorages = [
154+
{
155+
"accountId": 11111,
156+
"capacityGb": 20,
157+
"createDate": "2018-04-05T05:15:49-06:00",
158+
"id": 22222,
159+
"nasType": "NAS",
160+
"serviceProviderId": 1,
161+
"storageTypeId": "13",
162+
"username": "SL02SEV311111_11",
163+
"allowedHardware": [
164+
{
165+
"id": 12345,
166+
"datacenter": {
167+
"id": 449506,
168+
"longName": "Frankfurt 2",
169+
"name": "fra02",
170+
"statusId": 2
171+
}
172+
}
173+
],
174+
"serviceResourceBackendIpAddress": "fsn-fra0201a-fz.service.softlayer.com",
175+
"serviceResourceName": "Storage Type 02 File Aggregate stfm-fra0201a"
176+
},
177+
{
178+
"accountId": 11111,
179+
"capacityGb": 12000,
180+
"createDate": "2018-01-28T04:57:30-06:00",
181+
"id": 3777111,
182+
"nasType": "ISCSI",
183+
"notes": "BlockStorage12T",
184+
"password": "",
185+
"serviceProviderId": 1,
186+
"storageTypeId": "7",
187+
"username": "SL02SEL32222-9",
188+
"allowedHardware": [
189+
{
190+
"id": 629222,
191+
"datacenter": {
192+
"id": 449506,
193+
"longName": "Frankfurt 2",
194+
"name": "fra02",
195+
"statusId": 2
196+
}
197+
}
198+
],
199+
"serviceResourceBackendIpAddress": "10.31.95.152",
200+
"serviceResourceName": "Storage Type 02 Block Aggregate stbm-fra0201a"
201+
}
202+
]
203+
204+
getAllowedHost = {
205+
"accountId": 11111,
206+
"credentialId": 22222,
207+
"id": 33333,
208+
"name": "iqn.2020-03.com.ibm:sl02su11111-v62941551",
209+
"resourceTableId": 6291111,
210+
"resourceTableName": "VIRTUAL_GUEST",
211+
"credential": {
212+
"accountId": "11111",
213+
"createDate": "2020-03-20T13:35:47-06:00",
214+
"id": 44444,
215+
"nasCredentialTypeId": 2,
216+
"password": "SjFDCpHrjskfj",
217+
"username": "SL02SU11111-V62941551"
218+
}
219+
}
220+
221+
getHardDrives = [
222+
{
223+
"id": 11111,
224+
"serialNumber": "z1w4sdf",
225+
"serviceProviderId": 1,
226+
"hardwareComponentModel": {
227+
"capacity": "1000",
228+
"description": "SATAIII:2000:8300:Constellation",
229+
"id": 111,
230+
"manufacturer": "Seagate",
231+
"name": "Constellation ES",
232+
"hardwareGenericComponentModel": {
233+
"capacity": "1000",
234+
"units": "GB",
235+
"hardwareComponentType": {
236+
"id": 1,
237+
"keyName": "HARD_DRIVE",
238+
"type": "Hard Drive",
239+
"typeParentId": 5
240+
}
241+
}
242+
}
243+
}
244+
]
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
getObject = {
2+
"id": 11111,
3+
"allowedVirtualGuests": [
4+
{
5+
"id": 22222,
6+
"allowedHost": {
7+
"accountId": 12345,
8+
"id": 18311111,
9+
"name": "iqn.2020-03.com.ibm:sl02su11111-v62941551",
10+
"resourceTableId": 6222222,
11+
"resourceTableName": "VIRTUAL_GUEST",
12+
"credential": {
13+
"accountId": "12345",
14+
"createDate": "2020-03-20T13:35:47-06:00",
15+
"id": 1522222,
16+
"nasCredentialTypeId": 2,
17+
"password": "SjFDCpHrmKewos",
18+
"username": "SL02SU322222-V62922222"
19+
}
20+
}
21+
}
22+
]
23+
}

0 commit comments

Comments
 (0)