Skip to content

Commit 4eac4db

Browse files
storagedaemonKevin McDonald
authored andcommitted
Modify block-storage manager, detail, order, access-list to include more information
Add volume-cancel option to performance/endurance block storage Add support for deleting snapshots Fix block detail view for snapshot capacity
1 parent f6b0fd7 commit 4eac4db

12 files changed

Lines changed: 380 additions & 118 deletions

File tree

SoftLayer/CLI/block/access/list.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,45 @@
11
"""List hosts with access to volume."""
22
# :license: MIT, see LICENSE for more details.
33

4+
import click
45
import SoftLayer
56
from SoftLayer.CLI import columns as column_helper
67
from SoftLayer.CLI import environment
78
from SoftLayer.CLI import formatting
89

9-
import click
1010

1111
COLUMNS = [
12-
column_helper.Column('id', ('id',)),
13-
column_helper.Column('hostname', ('hostname',)),
14-
column_helper.Column('type', ('type',)),
15-
column_helper.Column('primaryBackendIpAddress', ('primaryBackendIpAddress',)),
12+
column_helper.Column(
13+
'id',
14+
('id',)),
15+
column_helper.Column(
16+
'hostname',
17+
('hostname',)),
18+
column_helper.Column(
19+
'type',
20+
('type',)),
21+
column_helper.Column(
22+
'primaryBackendIpAddress',
23+
('primaryBackendIpAddress',)),
24+
column_helper.Column(
25+
'hostIqn',
26+
('allowedHost', 'name',)),
27+
column_helper.Column(
28+
'username',
29+
('allowedHost', 'credential', 'username',)),
30+
column_helper.Column(
31+
'password',
32+
('allowedHost', 'credential', 'password',)),
1633
]
1734

1835
DEFAULT_COLUMNS = [
1936
'id',
2037
'hostname',
2138
'type',
2239
'primaryBackendIpAddress',
40+
'hostIqn',
41+
'username',
42+
'password',
2343
]
2444

2545

@@ -35,7 +55,8 @@
3555
def cli(env, columns, sortby, volume_id):
3656
"""List block storage."""
3757
block_manager = SoftLayer.BlockStorageManager(env.client)
38-
access_list = block_manager.get_block_volume_access_list(volume_id=volume_id)
58+
access_list = block_manager.get_block_volume_access_list(
59+
volume_id=volume_id)
3960
table = formatting.Table(columns.columns)
4061
table.sortby = sortby
4162

SoftLayer/CLI/block/cancel.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""Cancel an existing iSCSI account."""
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+
11+
12+
@click.command()
13+
@click.argument('volume-id')
14+
@click.option('--reason', help="An optional reason for cancellation")
15+
@click.option('--immediate',
16+
is_flag=True,
17+
help="Cancels the block storage volume immediately instead "
18+
"of on the billing anniversary")
19+
@environment.pass_env
20+
def cli(env, volume_id, reason, immediate):
21+
"""Cancel an existing block storage volume."""
22+
23+
block_storage_manager = SoftLayer.BlockStorageManager(env.client)
24+
25+
if not (env.skip_confirmations or formatting.no_going_back(volume_id)):
26+
raise exceptions.CLIAbort('Aborted')
27+
28+
block_storage_manager.cancel_block_volume(volume_id, reason, immediate)

SoftLayer/CLI/block/detail.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
"""Display details for a specified volume."""
22
# :license: MIT, see LICENSE for more details.
33

4+
import click
45
import SoftLayer
56
from SoftLayer.CLI import environment
67
from SoftLayer.CLI import formatting
78
from SoftLayer import utils
89

9-
import click
10-
1110

1211
@click.command()
1312
@click.argument('volume_id')
@@ -30,25 +29,28 @@ def cli(env, volume_id):
3029
['Type', block_volume['storageType']['keyName'].split('_').pop(0)])
3130
table.add_row(
3231
['Capacity (GB)', "%iGB" % block_volume['capacityGb']])
32+
table.add_row(
33+
['LUN Id', "%s" % block_volume['lunId']])
3334

34-
if block_volume['storageType']['keyName'].split('_').pop(0) == 'PERFORMANCE':
35+
if block_volume['storageType']['keyName'].split('_').pop(0)\
36+
== 'PERFORMANCE':
3537
table.add_row(
3638
['IOPs', block_volume['iops']])
3739
if block_volume['storageType']['keyName'].split('_').pop(0) == 'ENDURANCE':
3840
table.add_row(
39-
['Endurance Tier', block_volume['storageTierLevel']['description']])
41+
['Endurance Tier',
42+
block_volume['storageTierLevel']['description']])
4043

4144
table.add_row(
4245
['Data Center', block_volume['serviceResource']['datacenter']['name']])
4346
table.add_row(
44-
['Bytes Used', block_volume['bytesUsed']])
45-
table.add_row(
46-
['IP', block_volume['serviceResourceBackendIpAddress']])
47+
['Target IP', block_volume['serviceResourceBackendIpAddress']])
4748

4849
if block_volume['snapshotCapacityGb']:
4950
table.add_row(
50-
['Snapshot Reserved (GB)', block_volume['snapshotCapacityGb']])
51+
['Snapshot Capacity (GB)', block_volume['snapshotCapacityGb']])
5152
table.add_row(
52-
['Snapshot Used (Byes)', block_volume['snapshotSizeBytes']])
53+
['Snapshot Used (Bytes)',
54+
block_volume['parentVolume']['snapshotSizeBytes']])
5355

5456
env.fout(table)

SoftLayer/CLI/block/list.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
"""List block storage volumes."""
22
# :license: MIT, see LICENSE for more details.
33

4+
import click
45
import SoftLayer
56
from SoftLayer.CLI import columns as column_helper
67
from SoftLayer.CLI import environment
78
from SoftLayer.CLI import formatting
89

9-
import click
1010

1111
COLUMNS = [
1212
column_helper.Column('id', ('id',)),
@@ -33,7 +33,7 @@
3333
@click.command()
3434
@click.option('--username', '-u', help='Volume username')
3535
@click.option('--datacenter', '-d', help='Datacenter shortname')
36-
@click.option('--storage_type',
36+
@click.option('--storage-type',
3737
help='Type of storage volume',
3838
type=click.Choice(['performance', 'endurance']))
3939
@click.option('--sortby', help='Column to sort by', default='username')
@@ -47,9 +47,9 @@ def cli(env, sortby, columns, datacenter, username, storage_type):
4747
"""List block storage."""
4848
block_manager = SoftLayer.BlockStorageManager(env.client)
4949
block_volumes = block_manager.list_block_volumes(datacenter=datacenter,
50-
username=username,
51-
storage_type=storage_type,
52-
mask=columns.mask())
50+
username=username,
51+
storage_type=storage_type,
52+
mask=columns.mask())
5353

5454
table = formatting.Table(columns.columns)
5555
table.sortby = sortby

SoftLayer/CLI/block/order.py

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,34 @@
11
"""Order a block storage volume."""
22
# :license: MIT, see LICENSE for more details.
33

4+
import click
45
import SoftLayer
56
from SoftLayer.CLI import environment
67
from SoftLayer.CLI import exceptions
7-
import click
88

99

10-
@click.command()
11-
@click.option('--storage_type',
10+
CONTEXT_SETTINGS = dict(token_normalize_func=lambda x: x.upper())
11+
12+
13+
@click.command(context_settings=CONTEXT_SETTINGS)
14+
@click.option('--storage-type',
1215
help='Type of storage volume',
1316
type=click.Choice(['performance', 'endurance']),
1417
required=True)
1518
@click.option('--size',
16-
help='Size of storage volume',
19+
type=int,
20+
help='Size of storage volume in GB',
1721
required=True)
1822
@click.option('--iops',
19-
help='Performance Storage IOPs')
23+
type=int,
24+
help='Performance Storage IOPs,'
25+
+ ' between 100 and 6000 in multiples of 100'
26+
+ ' [required for storage-type performance]')
2027
@click.option('--tier',
21-
help='Endurance Storage Tier (IOP per GB)',
28+
help='Endurance Storage Tier (IOP per GB)'
29+
+ ' [required for storage-type endurance]',
2230
type=click.Choice(['0.25', '2', '4']))
23-
@click.option('--os',
31+
@click.option('--os-type',
2432
help='Operating System',
2533
type=click.Choice([
2634
'HYPER_V',
@@ -32,42 +40,54 @@
3240
'XEN']),
3341
required=True)
3442
@click.option('--location',
35-
help='Size of storage volume',
43+
help='Datacenter short name (e.g.: dal09)',
3644
required=True)
3745
@environment.pass_env
38-
def cli(env, storage_type, size, iops, tier, os, location):
46+
def cli(env, storage_type, size, iops, tier, os_type, location):
3947
"""Order a block storage volume."""
4048
block_manager = SoftLayer.BlockStorageManager(env.client)
49+
storage_type = storage_type.lower()
4150

4251
if storage_type == 'performance':
4352
if iops is None:
44-
raise exceptions.CLIAbort('Option --iops required with performance')
53+
raise exceptions.CLIAbort(
54+
'Option --iops required with Performance')
55+
56+
if iops < 100 or iops > 6000:
57+
raise exceptions.CLIAbort(
58+
'Option --iops must be between 100 and 6000, inclusive')
59+
60+
if iops % 100 != 0:
61+
raise exceptions.CLIAbort(
62+
'Option --iops must be a multiple of 100'
63+
)
4564

4665
order = block_manager.order_block_volume(
4766
storage_type='performance_storage_iscsi',
4867
location=location,
4968
size=size,
5069
iops=iops,
51-
os_type=os
70+
os_type=os_type
5271
)
5372

5473
if storage_type == 'endurance':
5574
if tier is None:
56-
raise exceptions.CLIAbort('Option --tier required with performance')
75+
raise exceptions.CLIAbort(
76+
'Option --tier required with Endurance in IOPS/GB [0.25,2,4]')
5777

5878
order = block_manager.order_block_volume(
5979
storage_type='storage_service_enterprise',
6080
location=location,
6181
size=size,
6282
tier_level=tier,
63-
os_type=os
83+
os_type=os_type
6484
)
6585

6686
if 'placedOrder' in order.keys():
67-
print "Order #{0} placed successfully!".format(
68-
order['placedOrder']['id'])
87+
click.echo("Order #{0} placed successfully!".format(
88+
order['placedOrder']['id']))
6989
for item in order['placedOrder']['items']:
70-
print " > %s" % item['description']
90+
click.echo(" > %s" % item['description'])
7191
else:
72-
print "Order could not be placed! Please verify your options " \
73-
"and try again."
92+
click.echo("Order could not be placed! Please verify your options " +
93+
"and try again.")
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""Create a block storage snapshot."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import click
5+
import SoftLayer
6+
from SoftLayer.CLI import environment
7+
8+
9+
@click.command()
10+
@click.argument('snapshot_id')
11+
@environment.pass_env
12+
def cli(env, snapshot_id):
13+
"""Deletes a snapshot on a given volume"""
14+
block_manager = SoftLayer.BlockStorageManager(env.client)
15+
block_manager.delete_snapshot(snapshot_id)

SoftLayer/CLI/block/snapshot/list.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
"""List block storage snapshots."""
22
# :license: MIT, see LICENSE for more details.
33

4+
import click
45
import SoftLayer
56
from SoftLayer.CLI import columns as column_helper
67
from SoftLayer.CLI import environment
78
from SoftLayer.CLI import formatting
89

9-
import click
1010

1111
COLUMNS = [
1212
column_helper.Column('id', ('id',)),

SoftLayer/CLI/routes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@
5959
('block', 'SoftLayer.CLI.block'),
6060
('block:volume-list', 'SoftLayer.CLI.block.list:cli'),
6161
('block:volume-detail', 'SoftLayer.CLI.block.detail:cli'),
62+
('block:volume-cancel', 'SoftLayer.CLI.block.cancel:cli'),
6263
('block:volume-order', 'SoftLayer.CLI.block.order:cli'),
6364
('block:snapshot-list', 'SoftLayer.CLI.block.snapshot.list:cli'),
65+
('block:snapshot-delete', 'SoftLayer.CLI.block.snapshot.delete:cli'),
6466
('block:access-list', 'SoftLayer.CLI.block.access.list:cli'),
6567

6668
('firewall', 'SoftLayer.CLI.firewall'),

SoftLayer/fixtures/SoftLayer_Account.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,3 +509,22 @@
509509

510510
getHubNetworkStorage = [{'id': 12345, 'username': 'SLOS12345-1'},
511511
{'id': 12346, 'username': 'SLOS12345-2'}]
512+
513+
getIscsiNetworkStorage = [{
514+
'accountId': 1234,
515+
'billingItem': {'id': 449},
516+
'capacityGb': 20,
517+
'createDate': '2015:50:15-04:00',
518+
'guestId': '',
519+
'hardwareId': '',
520+
'hostId': '',
521+
'id': 100,
522+
'nasType': 'ISCSI',
523+
'notes': """{'status': 'available'}""",
524+
'password': '',
525+
'serviceProviderId': 1,
526+
'serviceResource': {'datacenter': {'id': 449500}},
527+
'serviceResourceBackendIpAddress': '10.1.2.3',
528+
'serviceResourceName': 'Storage Type 01 Aggregate staaspar0101_pc01',
529+
'username': 'username'
530+
}]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
getObject = {
2+
'accountId': 1234,
3+
'billingItem': {'id': 449},
4+
'capacityGb': 20,
5+
'createDate': '2015:50:15-04:00',
6+
'guestId': '',
7+
'hardwareId': '',
8+
'hostId': '',
9+
'id': 100,
10+
'nasType': 'ISCSI',
11+
'notes': """{'status': 'available'}""",
12+
'password': '',
13+
'serviceProviderId': 1,
14+
'serviceResource': {'datacenter': {'id': 449500}},
15+
'serviceResourceBackendIpAddress': '10.1.2.3',
16+
'serviceResourceName': 'Storage Type 01 Aggregate staaspar0101_pc01',
17+
'username': 'username'
18+
}
19+
20+
deleteObject = True

0 commit comments

Comments
 (0)