Skip to content

Commit 7b8a339

Browse files
author
Neetu Jain
committed
Merge remote-tracking branch 'upstream/master'
2 parents 92d2d82 + def654a commit 7b8a339

105 files changed

Lines changed: 2609 additions & 434 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.travis.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@ matrix:
88
env: TOX_ENV=py33
99
- python: "3.4"
1010
env: TOX_ENV=py34
11+
- python: "3.5"
12+
env: TOX_ENV=py35
1113
- python: "pypy"
1214
env: TOX_ENV=pypy
1315
- python: "2.7"
1416
env: TOX_ENV=analysis
1517
- python: "2.7"
1618
env: TOX_ENV=coverage
17-
allow_failures:
18-
- python: "nightly"
19-
env: TOX_ENV=py35
2019
install:
2120
- pip install tox
2221
- pip install coveralls

CHANGELOG

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,37 @@
1+
5.1.0
2+
3+
* Added block storage functionality. You can order, list, detail, cancel volumes. You can list and delete snapshots. You can also list ACLs for volumes.
4+
5+
* Added functionality to attach/detach devices to tickets
6+
7+
* Virtual list now lists users and passwords for all known software
8+
9+
* Fixes bug with `vlan detail` CLI command
10+
11+
5.0.1
12+
13+
* Adds missing depdendency that was previously pulled in by prompt_toolkit
14+
15+
* Fix a bug by updating the CDN manager to use the new purge method
16+
17+
* Fixes bug that occured when iscsi listings with resources have no datacenter
18+
19+
5.0.0
20+
21+
* Adds a shell (accessable with `slcli shell`) which provides autocomplete for slcli commands and options
22+
23+
* Move modifying nic speed to `slcli virtual edit` and `slcli hardware edit` instead of having its own command
24+
25+
* How filters work with `slcli call-api` has changed significantly. Instead of accepting JSON, it now accepts an easier-to-use format. See `slcli call-api -h` for examples
26+
27+
* Adds manager for object storage
28+
29+
* 'virtual' and 'hardware' are preferred over 'vs' and 'server' in the CLI
30+
31+
* Improved REST transport support
32+
33+
* Many bug fixes
34+
135
4.1.1
236

337
* Fixes to work with Click v5

ISSUE_TEMPLATE

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
### Expected Behavior
2+
3+
### Actual Behavior
4+
5+
### Environment Information
6+
Operating System:
7+
softlayer-python version (`slcli --version`):

LICENSE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2014 SoftLayer Technologies, Inc. All rights reserved.
1+
Copyright (c) 2016 SoftLayer Technologies, Inc. All rights reserved.
22

33
Permission is hereby granted, free of charge, to any person obtaining a copy
44
of this software and associated documentation files (the "Software"), to deal
@@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1616
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1717
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1818
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19-
THE SOFTWARE.
19+
THE SOFTWARE.

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@ This library relies on the `requests <http://docs.python-requests.org/>`_ librar
5757

5858
System Requirements
5959
-------------------
60-
* Python 2.7, 3.3, or 3.4.
60+
* Python 2.7, 3.3 or higher.
6161
* A valid SoftLayer API username and key.
6262
* A connection to SoftLayer's private network is required to use
6363
our private network API endpoints.
6464

6565

6666
Copyright
6767
---------
68-
This software is Copyright (c) 2015 SoftLayer Technologies, Inc.
68+
This software is Copyright (c) 2016 SoftLayer Technologies, Inc.
6969

7070
See the bundled LICENSE file for more information.

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."""

SoftLayer/CLI/block/access_list.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
"""List hosts with access to volume."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import click
5+
import SoftLayer
6+
from SoftLayer.CLI import columns as column_helper
7+
from SoftLayer.CLI import environment
8+
from SoftLayer.CLI import formatting
9+
10+
11+
def _format_name(obj):
12+
if obj['type'] == 'VIRTUAL':
13+
return "{0}.{1}".format(obj['hostname'], obj['domain'])
14+
15+
elif obj['type'] == 'HARDWARE':
16+
return "{0}.{1}".format(obj['hostname'], obj['domain'])
17+
18+
elif obj['type'] == 'SUBNET':
19+
name = "{0}/{1}".format(
20+
obj['networkIdentifier'],
21+
obj['cidr']
22+
)
23+
if 'note' in obj.keys():
24+
name = "{0} ({1})".format(name, obj['note'])
25+
26+
return name
27+
28+
elif obj['type'] == 'IP':
29+
name = obj['ipAddress']
30+
if 'note' in obj.keys():
31+
name = "{0} ({1})".format(name, obj['note'])
32+
33+
return name
34+
else:
35+
raise Exception('Unknown type %s' % obj['type'])
36+
37+
38+
COLUMNS = [
39+
column_helper.Column('id', ('id',)),
40+
column_helper.Column('name', _format_name, """
41+
allowedVirtualGuests[hostname,domain],
42+
allowedHardware[hostname,domain],
43+
allowedSubnets[networkIdentifier,cidr,note],
44+
allowedIpAddresses[ipAddress,note],
45+
"""),
46+
column_helper.Column('type', ('type',)),
47+
column_helper.Column(
48+
'private_ip_address',
49+
('primaryBackendIpAddress',),
50+
"""
51+
allowedVirtualGuests.primaryBackendIpAddress
52+
allowedHardware.primaryBackendIpAddress
53+
allowedSubnets.primaryBackendIpAddress
54+
allowedIpAddresses.primaryBackendIpAddress
55+
"""),
56+
column_helper.Column(
57+
'host_iqn',
58+
('allowedHost', 'name',),
59+
"""
60+
allowedVirtualGuests.allowedHost.name
61+
allowedHardware.allowedHost.name
62+
allowedSubnets.allowedHost.name
63+
allowedIpAddresses.allowedHost.name
64+
"""),
65+
column_helper.Column(
66+
'username',
67+
('allowedHost', 'credential', 'username',),
68+
"""
69+
allowedVirtualGuests.allowedHost.credential.username
70+
allowedHardware.allowedHost.credential.username
71+
allowedSubnets.allowedHost.credential.username
72+
allowedIpAddresses.allowedHost.credential.username
73+
"""),
74+
column_helper.Column(
75+
'password',
76+
('allowedHost', 'credential', 'password',),
77+
"""
78+
allowedVirtualGuests.allowedHost.credential.password
79+
allowedHardware.allowedHost.credential.password
80+
allowedSubnets.allowedHost.credential.password
81+
allowedIpAddresses.allowedHost.credential.password
82+
"""),
83+
]
84+
85+
86+
DEFAULT_COLUMNS = [
87+
'id',
88+
'name',
89+
'type',
90+
'private_ip_address',
91+
'host_iqn',
92+
'username',
93+
'password',
94+
]
95+
96+
97+
@click.command()
98+
@click.argument('volume_id')
99+
@click.option('--sortby', help='Column to sort by', default='name')
100+
@click.option('--columns',
101+
callback=column_helper.get_formatter(COLUMNS),
102+
help='Columns to display. Options: {0}'.format(
103+
', '.join(column.name for column in COLUMNS)),
104+
default=','.join(DEFAULT_COLUMNS))
105+
@environment.pass_env
106+
def cli(env, columns, sortby, volume_id):
107+
"""List ACLs."""
108+
block_manager = SoftLayer.BlockStorageManager(env.client)
109+
access_list = block_manager.get_block_volume_access_list(
110+
volume_id=volume_id)
111+
table = formatting.Table(columns.columns)
112+
table.sortby = sortby
113+
114+
for key, type_name in [('allowedVirtualGuests', 'VIRTUAL'),
115+
('allowedHardware', 'HARDWARE'),
116+
('allowedSubnets', 'SUBNET'),
117+
('allowedIpAddresses', 'IP')]:
118+
for obj in access_list.get(key, []):
119+
obj['type'] = type_name
120+
table.add_row([value or formatting.blank()
121+
for value in columns.row(obj)])
122+
123+
env.fout(table)

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

SoftLayer/CLI/block/list.py

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

0 commit comments

Comments
 (0)