Skip to content

Commit f6b0fd7

Browse files
Tomy DurdenKevin McDonald
authored andcommitted
Initial addition of softlayer-python block storage
* Created SoftLayer.managers.block.BlockStorageManager * Created SoftLayer.managers.block.BlockStorageManager#list_block_volumes * Created SoftLayer.managers.block.BlockStorageManager#get_block_volume_details * Created SoftLayer.managers.block.BlockStorageManager#get_block_volume_access_list * Created SoftLayer.managers.block.BlockStorageManager#get_block_volume_snapshot_list * Created SoftLayer.managers.block.BlockStorageManager#order_block_volume * Created SoftLayer.managers.block.BlockStorageManager#_get_package * Created SoftLayer.managers.block.BlockStorageManager#_get_item_prices_performance * Created SoftLayer.managers.block.BlockStorageManager#_get_item_prices_endurance * Created SoftLayer.managers.block.BlockStorageManager#_get_location_id * Created block.volume-list route and CLI module * Created block.volume-detail route and CLI module * Created block.volume-order route and CLI module * Created block.access-list route and CLI module * Created block.snapshot-list route and CLI module
1 parent 6c63d74 commit f6b0fd7

11 files changed

Lines changed: 614 additions & 0 deletions

File tree

SoftLayer/CLI/block/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Block Storage."""
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Block Storage Access Control."""

SoftLayer/CLI/block/access/list.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
"""List hosts with access to volume."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import SoftLayer
5+
from SoftLayer.CLI import columns as column_helper
6+
from SoftLayer.CLI import environment
7+
from SoftLayer.CLI import formatting
8+
9+
import click
10+
11+
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',)),
16+
]
17+
18+
DEFAULT_COLUMNS = [
19+
'id',
20+
'hostname',
21+
'type',
22+
'primaryBackendIpAddress',
23+
]
24+
25+
26+
@click.command()
27+
@click.argument('volume_id')
28+
@click.option('--sortby', help='Column to sort by', default='hostname')
29+
@click.option('--columns',
30+
callback=column_helper.get_formatter(COLUMNS),
31+
help='Columns to display. Options: {0}'.format(
32+
', '.join(column.name for column in COLUMNS)),
33+
default=','.join(DEFAULT_COLUMNS))
34+
@environment.pass_env
35+
def cli(env, columns, sortby, volume_id):
36+
"""List block storage."""
37+
block_manager = SoftLayer.BlockStorageManager(env.client)
38+
access_list = block_manager.get_block_volume_access_list(volume_id=volume_id)
39+
table = formatting.Table(columns.columns)
40+
table.sortby = sortby
41+
42+
if access_list:
43+
if 'allowedVirtualGuests' in access_list.keys():
44+
for host in access_list['allowedVirtualGuests']:
45+
host['type'] = 'VIRTUAL'
46+
host['hostname'] = "{0}.{1}".format(
47+
host['hostname'],
48+
host['domain'])
49+
table.add_row([value or formatting.blank()
50+
for value in columns.row(host)])
51+
52+
if 'allowedHardware' in access_list.keys():
53+
for host in access_list['allowedHardware']:
54+
host['type'] = 'HARDWARE'
55+
host['hostname'] = "{0}.{1}".format(
56+
host['hostname'],
57+
host['domain'])
58+
table.add_row([value or formatting.blank()
59+
for value in columns.row(host)])
60+
61+
if 'allowedSubnets' in access_list.keys():
62+
for host in access_list['allowedSubnets']:
63+
host['type'] = 'SUBNET'
64+
if 'note' in host.keys():
65+
host['hostname'] = "{0}/{1} ({3})".format(
66+
host['networkIdentifier'],
67+
host['cidr'],
68+
host['note'],
69+
)
70+
else:
71+
host['hostname'] = "{0}/{1}".format(
72+
host['networkIdentifier'],
73+
host['cidr']
74+
)
75+
table.add_row([value or formatting.blank()
76+
for value in columns.row(host)])
77+
78+
if 'allowedIpAddresses' in access_list.keys():
79+
for host in access_list['allowedIpAddresses']:
80+
host['type'] = 'IP'
81+
if 'note' in host.keys():
82+
host['hostname'] = "{0} ({1})".format(
83+
host['ipAddress'],
84+
host['note']
85+
)
86+
else:
87+
host['hostname'] = host['ipAddress']
88+
table.add_row([value or formatting.blank()
89+
for value in columns.row(host)])
90+
91+
env.fout(table)
92+
else:
93+
click.echo("No authorized hosts found.")

SoftLayer/CLI/block/detail.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""Display details for a specified volume."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import SoftLayer
5+
from SoftLayer.CLI import environment
6+
from SoftLayer.CLI import formatting
7+
from SoftLayer import utils
8+
9+
import click
10+
11+
12+
@click.command()
13+
@click.argument('volume_id')
14+
@environment.pass_env
15+
def cli(env, volume_id):
16+
"""Display details for a specified volume."""
17+
block_manager = SoftLayer.BlockStorageManager(env.client)
18+
block_volume = block_manager.get_block_volume_details(volume_id)
19+
block_volume = utils.NestedDict(block_volume)
20+
21+
table = formatting.KeyValueTable(['Name', 'Value'])
22+
table.align['Name'] = 'r'
23+
table.align['Value'] = 'l'
24+
25+
table.add_row(
26+
['ID', block_volume['id']])
27+
table.add_row(
28+
['Username', block_volume['username']])
29+
table.add_row(
30+
['Type', block_volume['storageType']['keyName'].split('_').pop(0)])
31+
table.add_row(
32+
['Capacity (GB)', "%iGB" % block_volume['capacityGb']])
33+
34+
if block_volume['storageType']['keyName'].split('_').pop(0) == 'PERFORMANCE':
35+
table.add_row(
36+
['IOPs', block_volume['iops']])
37+
if block_volume['storageType']['keyName'].split('_').pop(0) == 'ENDURANCE':
38+
table.add_row(
39+
['Endurance Tier', block_volume['storageTierLevel']['description']])
40+
41+
table.add_row(
42+
['Data Center', block_volume['serviceResource']['datacenter']['name']])
43+
table.add_row(
44+
['Bytes Used', block_volume['bytesUsed']])
45+
table.add_row(
46+
['IP', block_volume['serviceResourceBackendIpAddress']])
47+
48+
if block_volume['snapshotCapacityGb']:
49+
table.add_row(
50+
['Snapshot Reserved (GB)', block_volume['snapshotCapacityGb']])
51+
table.add_row(
52+
['Snapshot Used (Byes)', block_volume['snapshotSizeBytes']])
53+
54+
env.fout(table)

SoftLayer/CLI/block/list.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""List block storage volumes."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import SoftLayer
5+
from SoftLayer.CLI import columns as column_helper
6+
from SoftLayer.CLI import environment
7+
from SoftLayer.CLI import formatting
8+
9+
import click
10+
11+
COLUMNS = [
12+
column_helper.Column('id', ('id',)),
13+
column_helper.Column('username', ('username',)),
14+
column_helper.Column('datacenter',
15+
('serviceResource', 'datacenter', 'name')),
16+
column_helper.Column('storageType', ('storageType', 'keyName')),
17+
column_helper.Column('capacityGb', ('capacityGb',)),
18+
column_helper.Column('bytesUsed', ('bytesUsed',)),
19+
column_helper.Column('ipAddr', ('serviceResourceBackendIpAddress',)),
20+
]
21+
22+
DEFAULT_COLUMNS = [
23+
'id',
24+
'username',
25+
'datacenter',
26+
'storageType',
27+
'capacityGb',
28+
'bytesUsed',
29+
'ipAddr'
30+
]
31+
32+
33+
@click.command()
34+
@click.option('--username', '-u', help='Volume username')
35+
@click.option('--datacenter', '-d', help='Datacenter shortname')
36+
@click.option('--storage_type',
37+
help='Type of storage volume',
38+
type=click.Choice(['performance', 'endurance']))
39+
@click.option('--sortby', help='Column to sort by', default='username')
40+
@click.option('--columns',
41+
callback=column_helper.get_formatter(COLUMNS),
42+
help='Columns to display. Options: {0}'.format(
43+
', '.join(column.name for column in COLUMNS)),
44+
default=','.join(DEFAULT_COLUMNS))
45+
@environment.pass_env
46+
def cli(env, sortby, columns, datacenter, username, storage_type):
47+
"""List block storage."""
48+
block_manager = SoftLayer.BlockStorageManager(env.client)
49+
block_volumes = block_manager.list_block_volumes(datacenter=datacenter,
50+
username=username,
51+
storage_type=storage_type,
52+
mask=columns.mask())
53+
54+
table = formatting.Table(columns.columns)
55+
table.sortby = sortby
56+
57+
for block_volume in block_volumes:
58+
block_volume['storageType']['keyName'] = block_volume['storageType'][
59+
'keyName'].split('_').pop(0)
60+
table.add_row([value or formatting.blank()
61+
for value in columns.row(block_volume)])
62+
63+
env.fout(table)

SoftLayer/CLI/block/order.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""Order a block storage volume."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import SoftLayer
5+
from SoftLayer.CLI import environment
6+
from SoftLayer.CLI import exceptions
7+
import click
8+
9+
10+
@click.command()
11+
@click.option('--storage_type',
12+
help='Type of storage volume',
13+
type=click.Choice(['performance', 'endurance']),
14+
required=True)
15+
@click.option('--size',
16+
help='Size of storage volume',
17+
required=True)
18+
@click.option('--iops',
19+
help='Performance Storage IOPs')
20+
@click.option('--tier',
21+
help='Endurance Storage Tier (IOP per GB)',
22+
type=click.Choice(['0.25', '2', '4']))
23+
@click.option('--os',
24+
help='Operating System',
25+
type=click.Choice([
26+
'HYPER_V',
27+
'LINUX',
28+
'VMWARE',
29+
'WINDOWS_2008',
30+
'WINDOWS_GPT',
31+
'WINDOWS',
32+
'XEN']),
33+
required=True)
34+
@click.option('--location',
35+
help='Size of storage volume',
36+
required=True)
37+
@environment.pass_env
38+
def cli(env, storage_type, size, iops, tier, os, location):
39+
"""Order a block storage volume."""
40+
block_manager = SoftLayer.BlockStorageManager(env.client)
41+
42+
if storage_type == 'performance':
43+
if iops is None:
44+
raise exceptions.CLIAbort('Option --iops required with performance')
45+
46+
order = block_manager.order_block_volume(
47+
storage_type='performance_storage_iscsi',
48+
location=location,
49+
size=size,
50+
iops=iops,
51+
os_type=os
52+
)
53+
54+
if storage_type == 'endurance':
55+
if tier is None:
56+
raise exceptions.CLIAbort('Option --tier required with performance')
57+
58+
order = block_manager.order_block_volume(
59+
storage_type='storage_service_enterprise',
60+
location=location,
61+
size=size,
62+
tier_level=tier,
63+
os_type=os
64+
)
65+
66+
if 'placedOrder' in order.keys():
67+
print "Order #{0} placed successfully!".format(
68+
order['placedOrder']['id'])
69+
for item in order['placedOrder']['items']:
70+
print " > %s" % item['description']
71+
else:
72+
print "Order could not be placed! Please verify your options " \
73+
"and try again."
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Block Storage Snapshots."""
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""List block storage snapshots."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import SoftLayer
5+
from SoftLayer.CLI import columns as column_helper
6+
from SoftLayer.CLI import environment
7+
from SoftLayer.CLI import formatting
8+
9+
import click
10+
11+
COLUMNS = [
12+
column_helper.Column('id', ('id',)),
13+
column_helper.Column('name', ('name',)),
14+
column_helper.Column('snapshotCreationTimestamp',
15+
('snapshotCreationTimestamp',)),
16+
column_helper.Column('snapshotSizeBytes', ('snapshotSizeBytes',)),
17+
]
18+
19+
DEFAULT_COLUMNS = [
20+
'id',
21+
'name',
22+
'snapshotCreationTimestamp',
23+
'snapshotSizeBytes'
24+
]
25+
26+
27+
@click.command()
28+
@click.argument('volume_id')
29+
@click.option('--sortby', help='Column to sort by',
30+
default='snapshotCreationTimestamp')
31+
@click.option('--columns',
32+
callback=column_helper.get_formatter(COLUMNS),
33+
help='Columns to display. Options: {0}'.format(
34+
', '.join(column.name for column in COLUMNS)),
35+
default=','.join(DEFAULT_COLUMNS))
36+
@environment.pass_env
37+
def cli(env, sortby, columns, volume_id):
38+
"""List block storage."""
39+
block_manager = SoftLayer.BlockStorageManager(env.client)
40+
volume = block_manager.get_block_volume_snapshot_list(volume_id=volume_id)
41+
42+
table = formatting.Table(columns.columns)
43+
table.sortby = sortby
44+
45+
if volume and 'snapshots' in volume.keys():
46+
for snapshot in volume['snapshots']:
47+
48+
if 'notes' in snapshot.keys():
49+
snapshot['name'] = snapshot['notes']
50+
51+
table.add_row([value or formatting.blank()
52+
for value in columns.row(snapshot)])
53+
54+
env.fout(table)
55+
else:
56+
click.echo("No snapshots found.")

SoftLayer/CLI/routes.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@
5656
('dns:zone-list', 'SoftLayer.CLI.dns.zone_list:cli'),
5757
('dns:zone-print', 'SoftLayer.CLI.dns.zone_print:cli'),
5858

59+
('block', 'SoftLayer.CLI.block'),
60+
('block:volume-list', 'SoftLayer.CLI.block.list:cli'),
61+
('block:volume-detail', 'SoftLayer.CLI.block.detail:cli'),
62+
('block:volume-order', 'SoftLayer.CLI.block.order:cli'),
63+
('block:snapshot-list', 'SoftLayer.CLI.block.snapshot.list:cli'),
64+
('block:access-list', 'SoftLayer.CLI.block.access.list:cli'),
65+
5966
('firewall', 'SoftLayer.CLI.firewall'),
6067
('firewall:add', 'SoftLayer.CLI.firewall.add:cli'),
6168
('firewall:cancel', 'SoftLayer.CLI.firewall.cancel:cli'),

SoftLayer/managers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
88
:license: MIT, see LICENSE for more details.
99
"""
10+
from SoftLayer.managers.block import BlockStorageManager
1011
from SoftLayer.managers.cdn import CDNManager
1112
from SoftLayer.managers.dns import DNSManager
1213
from SoftLayer.managers.firewall import FirewallManager
@@ -25,6 +26,7 @@
2526
from SoftLayer.managers.vs import VSManager
2627

2728
__all__ = [
29+
'BlockStorageManager',
2830
'CDNManager',
2931
'DNSManager',
3032
'FirewallManager',

0 commit comments

Comments
 (0)