[Python-modules-commits] [python-softlayer] 01/10: Import python-softlayer_5.1.0.orig.tar.gz
Scott Kitterman
kitterman at moszumanska.debian.org
Thu May 26 12:44:28 UTC 2016
This is an automated email from the git hooks/post-receive script.
kitterman pushed a commit to branch master
in repository python-softlayer.
commit 6245ba4560ae1a6a4f13dadcdc2df91e58aa5cd9
Author: Scott Kitterman <scott at kitterman.com>
Date: Thu May 26 08:05:16 2016 -0400
Import python-softlayer_5.1.0.orig.tar.gz
---
CHANGELOG | 10 +
README.rst | 2 +-
SoftLayer/CLI/block/__init__.py | 1 +
SoftLayer/CLI/block/access_list.py | 123 ++++++++
SoftLayer/CLI/block/cancel.py | 28 ++
SoftLayer/CLI/block/detail.py | 59 ++++
SoftLayer/CLI/block/list.py | 66 ++++
SoftLayer/CLI/block/order.py | 99 ++++++
SoftLayer/CLI/block/snapshot_delete.py | 15 +
SoftLayer/CLI/block/snapshot_list.py | 58 ++++
SoftLayer/CLI/routes.py | 11 +
SoftLayer/CLI/ticket/attach.py | 42 +++
SoftLayer/CLI/ticket/create.py | 36 ++-
SoftLayer/CLI/ticket/detach.py | 42 +++
SoftLayer/CLI/virt/detail.py | 16 +-
SoftLayer/CLI/vlan/detail.py | 6 +-
SoftLayer/consts.py | 2 +-
SoftLayer/fixtures/SoftLayer_Account.py | 20 ++
SoftLayer/fixtures/SoftLayer_Network_Storage.py | 65 ++++
SoftLayer/fixtures/SoftLayer_Ticket.py | 17 +
SoftLayer/fixtures/SoftLayer_Virtual_Guest.py | 5 +
SoftLayer/managers/__init__.py | 2 +
SoftLayer/managers/block.py | 403 ++++++++++++++++++++++++
SoftLayer/managers/network.py | 11 +-
SoftLayer/managers/ticket.py | 40 ++-
SoftLayer/managers/vs.py | 3 +
SoftLayer/testing/__init__.py | 7 +
SoftLayer/utils.py | 9 +-
docs/conf.py | 4 +-
fabfile.py | 8 +-
setup.py | 2 +-
tests/CLI/core_tests.py | 6 +-
tests/CLI/modules/block_tests.py | 98 ++++++
tests/CLI/modules/call_api_tests.py | 16 +-
tests/CLI/modules/cdn_tests.py | 14 +-
tests/CLI/modules/config_tests.py | 4 +-
tests/CLI/modules/dns_tests.py | 16 +-
tests/CLI/modules/firewall_tests.py | 2 +-
tests/CLI/modules/globalip_tests.py | 8 +-
tests/CLI/modules/nas_tests.py | 2 +-
tests/CLI/modules/object_storage_tests.py | 4 +-
tests/CLI/modules/rwhois_tests.py | 6 +-
tests/CLI/modules/server_tests.py | 38 +--
tests/CLI/modules/sshkey_tests.py | 14 +-
tests/CLI/modules/summary_tests.py | 2 +-
tests/CLI/modules/ticket_tests.py | 137 +++++++-
tests/CLI/modules/vs_tests.py | 30 +-
tests/managers/block_tests.py | 212 +++++++++++++
tests/managers/ticket_tests.py | 25 ++
tox.ini | 7 +-
50 files changed, 1733 insertions(+), 120 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 39c1ee4..60b8a22 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,13 @@
+5.1.0
+
+ * Added block storage functionality. You can order, list, detail, cancel volumes. You can list and delete snapshots. You can also list ACLs for volumes.
+
+ * Added functionality to attach/detach devices to tickets
+
+ * Virtual list now lists users and passwords for all known software
+
+ * Fixes bug with `vlan detail` CLI command
+
5.0.1
* Adds missing depdendency that was previously pulled in by prompt_toolkit
diff --git a/README.rst b/README.rst
index d8949f2..31da9b6 100644
--- a/README.rst
+++ b/README.rst
@@ -57,7 +57,7 @@ This library relies on the `requests <http://docs.python-requests.org/>`_ librar
System Requirements
-------------------
-* Python 2.7, 3.3, or 3.4.
+* Python 2.7, 3.3 or higher.
* A valid SoftLayer API username and key.
* A connection to SoftLayer's private network is required to use
our private network API endpoints.
diff --git a/SoftLayer/CLI/block/__init__.py b/SoftLayer/CLI/block/__init__.py
new file mode 100644
index 0000000..7ccee03
--- /dev/null
+++ b/SoftLayer/CLI/block/__init__.py
@@ -0,0 +1 @@
+"""Block Storage."""
diff --git a/SoftLayer/CLI/block/access_list.py b/SoftLayer/CLI/block/access_list.py
new file mode 100644
index 0000000..4b45a54
--- /dev/null
+++ b/SoftLayer/CLI/block/access_list.py
@@ -0,0 +1,123 @@
+"""List hosts with access to volume."""
+# :license: MIT, see LICENSE for more details.
+
+import click
+import SoftLayer
+from SoftLayer.CLI import columns as column_helper
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import formatting
+
+
+def _format_name(obj):
+ if obj['type'] == 'VIRTUAL':
+ return "{0}.{1}".format(obj['hostname'], obj['domain'])
+
+ elif obj['type'] == 'HARDWARE':
+ return "{0}.{1}".format(obj['hostname'], obj['domain'])
+
+ elif obj['type'] == 'SUBNET':
+ name = "{0}/{1}".format(
+ obj['networkIdentifier'],
+ obj['cidr']
+ )
+ if 'note' in obj.keys():
+ name = "{0} ({1})".format(name, obj['note'])
+
+ return name
+
+ elif obj['type'] == 'IP':
+ name = obj['ipAddress']
+ if 'note' in obj.keys():
+ name = "{0} ({1})".format(name, obj['note'])
+
+ return name
+ else:
+ raise Exception('Unknown type %s' % obj['type'])
+
+
+COLUMNS = [
+ column_helper.Column('id', ('id',)),
+ column_helper.Column('name', _format_name, """
+allowedVirtualGuests[hostname,domain],
+allowedHardware[hostname,domain],
+allowedSubnets[networkIdentifier,cidr,note],
+allowedIpAddresses[ipAddress,note],
+"""),
+ column_helper.Column('type', ('type',)),
+ column_helper.Column(
+ 'private_ip_address',
+ ('primaryBackendIpAddress',),
+ """
+allowedVirtualGuests.primaryBackendIpAddress
+allowedHardware.primaryBackendIpAddress
+allowedSubnets.primaryBackendIpAddress
+allowedIpAddresses.primaryBackendIpAddress
+"""),
+ column_helper.Column(
+ 'host_iqn',
+ ('allowedHost', 'name',),
+ """
+allowedVirtualGuests.allowedHost.name
+allowedHardware.allowedHost.name
+allowedSubnets.allowedHost.name
+allowedIpAddresses.allowedHost.name
+"""),
+ column_helper.Column(
+ 'username',
+ ('allowedHost', 'credential', 'username',),
+ """
+allowedVirtualGuests.allowedHost.credential.username
+allowedHardware.allowedHost.credential.username
+allowedSubnets.allowedHost.credential.username
+allowedIpAddresses.allowedHost.credential.username
+"""),
+ column_helper.Column(
+ 'password',
+ ('allowedHost', 'credential', 'password',),
+ """
+allowedVirtualGuests.allowedHost.credential.password
+allowedHardware.allowedHost.credential.password
+allowedSubnets.allowedHost.credential.password
+allowedIpAddresses.allowedHost.credential.password
+"""),
+]
+
+
+DEFAULT_COLUMNS = [
+ 'id',
+ 'name',
+ 'type',
+ 'private_ip_address',
+ 'host_iqn',
+ 'username',
+ 'password',
+]
+
+
+ at click.command()
+ at click.argument('volume_id')
+ at click.option('--sortby', help='Column to sort by', default='name')
+ at click.option('--columns',
+ callback=column_helper.get_formatter(COLUMNS),
+ help='Columns to display. Options: {0}'.format(
+ ', '.join(column.name for column in COLUMNS)),
+ default=','.join(DEFAULT_COLUMNS))
+ at environment.pass_env
+def cli(env, columns, sortby, volume_id):
+ """List ACLs."""
+ block_manager = SoftLayer.BlockStorageManager(env.client)
+ access_list = block_manager.get_block_volume_access_list(
+ volume_id=volume_id)
+ table = formatting.Table(columns.columns)
+ table.sortby = sortby
+
+ for key, type_name in [('allowedVirtualGuests', 'VIRTUAL'),
+ ('allowedHardware', 'HARDWARE'),
+ ('allowedSubnets', 'SUBNET'),
+ ('allowedIpAddresses', 'IP')]:
+ for obj in access_list.get(key, []):
+ obj['type'] = type_name
+ table.add_row([value or formatting.blank()
+ for value in columns.row(obj)])
+
+ env.fout(table)
diff --git a/SoftLayer/CLI/block/cancel.py b/SoftLayer/CLI/block/cancel.py
new file mode 100644
index 0000000..a23cee0
--- /dev/null
+++ b/SoftLayer/CLI/block/cancel.py
@@ -0,0 +1,28 @@
+"""Cancel an existing iSCSI account."""
+# :license: MIT, see LICENSE for more details.
+
+import click
+
+import SoftLayer
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import exceptions
+from SoftLayer.CLI import formatting
+
+
+ at click.command()
+ at click.argument('volume-id')
+ at click.option('--reason', help="An optional reason for cancellation")
+ at click.option('--immediate',
+ is_flag=True,
+ help="Cancels the block storage volume immediately instead "
+ "of on the billing anniversary")
+ at environment.pass_env
+def cli(env, volume_id, reason, immediate):
+ """Cancel an existing block storage volume."""
+
+ block_storage_manager = SoftLayer.BlockStorageManager(env.client)
+
+ if not (env.skip_confirmations or formatting.no_going_back(volume_id)):
+ raise exceptions.CLIAbort('Aborted')
+
+ block_storage_manager.cancel_block_volume(volume_id, reason, immediate)
diff --git a/SoftLayer/CLI/block/detail.py b/SoftLayer/CLI/block/detail.py
new file mode 100644
index 0000000..c98736e
--- /dev/null
+++ b/SoftLayer/CLI/block/detail.py
@@ -0,0 +1,59 @@
+"""Display details for a specified volume."""
+# :license: MIT, see LICENSE for more details.
+
+import click
+import SoftLayer
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import formatting
+from SoftLayer import utils
+
+
+ at click.command()
+ at click.argument('volume_id')
+ at environment.pass_env
+def cli(env, volume_id):
+ """Display details for a specified volume."""
+ block_manager = SoftLayer.BlockStorageManager(env.client)
+ block_volume = block_manager.get_block_volume_details(volume_id)
+ block_volume = utils.NestedDict(block_volume)
+
+ table = formatting.KeyValueTable(['Name', 'Value'])
+ table.align['Name'] = 'r'
+ table.align['Value'] = 'l'
+
+ storage_type = block_volume['storageType']['keyName'].split('_').pop(0)
+ table.add_row(['ID', block_volume['id']])
+ table.add_row(['Username', block_volume['username']])
+ table.add_row(['Type', storage_type])
+ table.add_row(['Capacity (GB)', "%iGB" % block_volume['capacityGb']])
+ table.add_row(['LUN Id', "%s" % block_volume['lunId']])
+
+ if block_volume.get('iops'):
+ table.add_row(['IOPs', block_volume['iops']])
+
+ if block_volume.get('storageTierLevel'):
+ table.add_row([
+ 'Endurance Tier',
+ block_volume['storageTierLevel']['description'],
+ ])
+
+ table.add_row([
+ 'Data Center',
+ block_volume['serviceResource']['datacenter']['name'],
+ ])
+ table.add_row([
+ 'Target IP',
+ block_volume['serviceResourceBackendIpAddress'],
+ ])
+
+ if block_volume['snapshotCapacityGb']:
+ table.add_row([
+ 'Snapshot Capacity (GB)',
+ block_volume['snapshotCapacityGb'],
+ ])
+ table.add_row([
+ 'Snapshot Used (Bytes)',
+ block_volume['parentVolume']['snapshotSizeBytes'],
+ ])
+
+ env.fout(table)
diff --git a/SoftLayer/CLI/block/list.py b/SoftLayer/CLI/block/list.py
new file mode 100644
index 0000000..40edcb7
--- /dev/null
+++ b/SoftLayer/CLI/block/list.py
@@ -0,0 +1,66 @@
+"""List block storage volumes."""
+# :license: MIT, see LICENSE for more details.
+
+import click
+import SoftLayer
+from SoftLayer.CLI import columns as column_helper
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import formatting
+
+
+COLUMNS = [
+ column_helper.Column('id', ('id',), mask="id"),
+ column_helper.Column('username', ('username',), mask="username"),
+ column_helper.Column('datacenter',
+ ('serviceResource', 'datacenter', 'name'),
+ mask="serviceResource.datacenter.name"),
+ column_helper.Column(
+ 'storage_type',
+ lambda b: b['storageType']['keyName'].split('_').pop(0),
+ mask="storageType.keyName"),
+ column_helper.Column('capacity_gb', ('capacityGb',), mask="capacityGb"),
+ column_helper.Column('bytes_used', ('bytesUsed',), mask="bytesUsed"),
+ column_helper.Column('ip_addr', ('serviceResourceBackendIpAddress',),
+ mask="serviceResourceBackendIpAddress"),
+]
+
+DEFAULT_COLUMNS = [
+ 'id',
+ 'username',
+ 'datacenter',
+ 'storage_type',
+ 'capacity_gb',
+ 'bytes_used',
+ 'ip_addr'
+]
+
+
+ at click.command()
+ at click.option('--username', '-u', help='Volume username')
+ at click.option('--datacenter', '-d', help='Datacenter shortname')
+ at click.option('--storage-type',
+ help='Type of storage volume',
+ type=click.Choice(['performance', 'endurance']))
+ at click.option('--sortby', help='Column to sort by', default='username')
+ at click.option('--columns',
+ callback=column_helper.get_formatter(COLUMNS),
+ help='Columns to display. Options: {0}'.format(
+ ', '.join(column.name for column in COLUMNS)),
+ default=','.join(DEFAULT_COLUMNS))
+ at environment.pass_env
+def cli(env, sortby, columns, datacenter, username, storage_type):
+ """List block storage."""
+ block_manager = SoftLayer.BlockStorageManager(env.client)
+ block_volumes = block_manager.list_block_volumes(datacenter=datacenter,
+ username=username,
+ storage_type=storage_type,
+ mask=columns.mask())
+
+ table = formatting.Table(columns.columns)
+ table.sortby = sortby
+
+ for block_volume in block_volumes:
+ table.add_row([value or formatting.blank()
+ for value in columns.row(block_volume)])
+
+ env.fout(table)
diff --git a/SoftLayer/CLI/block/order.py b/SoftLayer/CLI/block/order.py
new file mode 100644
index 0000000..f184007
--- /dev/null
+++ b/SoftLayer/CLI/block/order.py
@@ -0,0 +1,99 @@
+"""Order a block storage volume."""
+# :license: MIT, see LICENSE for more details.
+
+import click
+import SoftLayer
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import exceptions
+
+
+CONTEXT_SETTINGS = dict(token_normalize_func=lambda x: x.upper())
+
+
+ at click.command(context_settings=CONTEXT_SETTINGS)
+ at click.option('--storage-type',
+ help='Type of storage volume',
+ type=click.Choice(['performance', 'endurance']),
+ required=True)
+ at click.option('--size',
+ type=int,
+ help='Size of storage volume in GB',
+ required=True)
+ at click.option('--iops',
+ type=int,
+ help='Performance Storage IOPs,'
+ ' between 100 and 6000 in multiples of 100'
+ ' [required for storage-type performance]')
+ at click.option('--tier',
+ help='Endurance Storage Tier (IOP per GB)'
+ ' [required for storage-type endurance]',
+ type=click.Choice(['0.25', '2', '4']))
+ at click.option('--os-type',
+ help='Operating System',
+ type=click.Choice([
+ 'HYPER_V',
+ 'LINUX',
+ 'VMWARE',
+ 'WINDOWS_2008',
+ 'WINDOWS_GPT',
+ 'WINDOWS',
+ 'XEN']),
+ required=True)
+ at click.option('--location',
+ help='Datacenter short name (e.g.: dal09)',
+ required=True)
+ at environment.pass_env
+def cli(env, storage_type, size, iops, tier, os_type, location):
+ """Order a block storage volume."""
+ block_manager = SoftLayer.BlockStorageManager(env.client)
+ storage_type = storage_type.lower()
+
+ if storage_type == 'performance':
+ if iops is None:
+ raise exceptions.CLIAbort(
+ 'Option --iops required with Performance')
+
+ if iops < 100 or iops > 6000:
+ raise exceptions.CLIAbort(
+ 'Option --iops must be between 100 and 6000, inclusive')
+
+ if iops % 100 != 0:
+ raise exceptions.CLIAbort(
+ 'Option --iops must be a multiple of 100'
+ )
+
+ try:
+ order = block_manager.order_block_volume(
+ storage_type='performance_storage_iscsi',
+ location=location,
+ size=size,
+ iops=iops,
+ os_type=os_type
+ )
+ except ValueError as ex:
+ raise exceptions.ArgumentError(str(ex))
+
+ if storage_type == 'endurance':
+ if tier is None:
+ raise exceptions.CLIAbort(
+ 'Option --tier required with Endurance in IOPS/GB [0.25,2,4]')
+
+ try:
+ order = block_manager.order_block_volume(
+ storage_type='storage_service_enterprise',
+ location=location,
+ size=size,
+ tier_level=float(tier),
+ os_type=os_type
+ )
+ except ValueError as ex:
+ raise exceptions.ArgumentError(str(ex))
+
+ if 'placedOrder' in order.keys():
+ click.echo("Order #{0} placed successfully!".format(
+ order['placedOrder']['id']))
+ for item in order['placedOrder']['items']:
+ click.echo(" > %s" % item['description'])
+ else:
+ click.echo("Order could not be placed! Please verify your options " +
+ "and try again.")
diff --git a/SoftLayer/CLI/block/snapshot_delete.py b/SoftLayer/CLI/block/snapshot_delete.py
new file mode 100644
index 0000000..6daa3f4
--- /dev/null
+++ b/SoftLayer/CLI/block/snapshot_delete.py
@@ -0,0 +1,15 @@
+"""Create a block storage snapshot."""
+# :license: MIT, see LICENSE for more details.
+
+import click
+import SoftLayer
+from SoftLayer.CLI import environment
+
+
+ at click.command()
+ at click.argument('snapshot_id')
+ at environment.pass_env
+def cli(env, snapshot_id):
+ """Deletes a snapshot on a given volume"""
+ block_manager = SoftLayer.BlockStorageManager(env.client)
+ block_manager.delete_snapshot(snapshot_id)
diff --git a/SoftLayer/CLI/block/snapshot_list.py b/SoftLayer/CLI/block/snapshot_list.py
new file mode 100644
index 0000000..7ffea3f
--- /dev/null
+++ b/SoftLayer/CLI/block/snapshot_list.py
@@ -0,0 +1,58 @@
+"""List block storage snapshots."""
+# :license: MIT, see LICENSE for more details.
+
+import click
+import SoftLayer
+from SoftLayer.CLI import columns as column_helper
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import formatting
+
+
+COLUMNS = [
+ column_helper.Column(
+ 'id',
+ ('snapshots', 'id',),
+ mask='snapshots.id'),
+ column_helper.Column('name', ('snapshots', 'notes',),
+ mask='snapshots.notes'),
+ column_helper.Column('created',
+ ('snapshots', 'snapshotCreationTimestamp',),
+ mask='snapshots.snapshotCreationTimestamp'),
+ column_helper.Column('size_bytes', ('snapshots', 'snapshotSizeBytes',),
+ mask='snapshots.snapshotSizeBytes'),
+]
+
+DEFAULT_COLUMNS = [
+ 'id',
+ 'name',
+ 'created',
+ 'size_bytes'
+]
+
+
+ at click.command()
+ at click.argument('volume_id')
+ at click.option('--sortby', help='Column to sort by',
+ default='created')
+ at click.option('--columns',
+ callback=column_helper.get_formatter(COLUMNS),
+ help='Columns to display. Options: {0}'.format(
+ ', '.join(column.name for column in COLUMNS)),
+ default=','.join(DEFAULT_COLUMNS))
+ at environment.pass_env
+def cli(env, sortby, columns, volume_id):
+ """List block storage snapshots."""
+ block_manager = SoftLayer.BlockStorageManager(env.client)
+ snapshots = block_manager.get_block_volume_snapshot_list(
+ volume_id=volume_id,
+ mask=columns.mask(),
+ )
+
+ table = formatting.Table(columns.columns)
+ table.sortby = sortby
+
+ for snapshot in snapshots:
+ table.add_row([value or formatting.blank()
+ for value in columns.row(snapshot)])
+
+ env.fout(table)
diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py
index 0d93f2e..a9aec3c 100644
--- a/SoftLayer/CLI/routes.py
+++ b/SoftLayer/CLI/routes.py
@@ -56,6 +56,15 @@ ALL_ROUTES = [
('dns:zone-list', 'SoftLayer.CLI.dns.zone_list:cli'),
('dns:zone-print', 'SoftLayer.CLI.dns.zone_print:cli'),
+ ('block', 'SoftLayer.CLI.block'),
+ ('block:volume-list', 'SoftLayer.CLI.block.list:cli'),
+ ('block:volume-detail', 'SoftLayer.CLI.block.detail:cli'),
+ ('block:volume-cancel', 'SoftLayer.CLI.block.cancel:cli'),
+ ('block:volume-order', 'SoftLayer.CLI.block.order:cli'),
+ ('block:snapshot-list', 'SoftLayer.CLI.block.snapshot_list:cli'),
+ ('block:snapshot-delete', 'SoftLayer.CLI.block.snapshot_delete:cli'),
+ ('block:access-list', 'SoftLayer.CLI.block.access_list:cli'),
+
('firewall', 'SoftLayer.CLI.firewall'),
('firewall:add', 'SoftLayer.CLI.firewall.add:cli'),
('firewall:cancel', 'SoftLayer.CLI.firewall.cancel:cli'),
@@ -188,6 +197,8 @@ ALL_ROUTES = [
('ticket:update', 'SoftLayer.CLI.ticket.update:cli'),
('ticket:subjects', 'SoftLayer.CLI.ticket.subjects:cli'),
('ticket:summary', 'SoftLayer.CLI.ticket.summary:cli'),
+ ('ticket:attach', 'SoftLayer.CLI.ticket.attach:cli'),
+ ('ticket:detach', 'SoftLayer.CLI.ticket.detach:cli'),
('vlan', 'SoftLayer.CLI.vlan'),
('vlan:detail', 'SoftLayer.CLI.vlan.detail:cli'),
diff --git a/SoftLayer/CLI/ticket/attach.py b/SoftLayer/CLI/ticket/attach.py
new file mode 100644
index 0000000..98adaa6
--- /dev/null
+++ b/SoftLayer/CLI/ticket/attach.py
@@ -0,0 +1,42 @@
+"""Attach devices to a ticket."""
+# :license: MIT, see LICENSE for more details.
+
+import click
+
+import SoftLayer
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import exceptions
+from SoftLayer.CLI import helpers
+
+
+ at click.command()
+ at click.argument('identifier', type=int)
+ at click.option('--hardware',
+ 'hardware_identifier',
+ help="The identifier for hardware to attach")
+ at click.option('--virtual',
+ 'virtual_identifier',
+ help="The identifier for a virtual server to attach")
+ at environment.pass_env
+def cli(env, identifier, hardware_identifier, virtual_identifier):
+ """Attach devices to a ticket."""
+ ticket_mgr = SoftLayer.TicketManager(env.client)
+
+ if hardware_identifier and virtual_identifier:
+ raise exceptions.ArgumentError(
+ "Cannot attach hardware and a virtual server at the same time")
+ elif hardware_identifier:
+ hardware_mgr = SoftLayer.HardwareManager(env.client)
+ hardware_id = helpers.resolve_id(hardware_mgr.resolve_ids,
+ hardware_identifier,
+ 'hardware')
+ ticket_mgr.attach_hardware(identifier, hardware_id)
+ elif virtual_identifier:
+ vs_mgr = SoftLayer.VSManager(env.client)
+ vs_id = helpers.resolve_id(vs_mgr.resolve_ids,
+ virtual_identifier,
+ 'VS')
+ ticket_mgr.attach_virtual_server(identifier, vs_id)
+ else:
+ raise exceptions.ArgumentError(
+ "Must have a hardware or virtual server identifier to attach")
diff --git a/SoftLayer/CLI/ticket/create.py b/SoftLayer/CLI/ticket/create.py
index 82f81ee..71ebd26 100644
--- a/SoftLayer/CLI/ticket/create.py
+++ b/SoftLayer/CLI/ticket/create.py
@@ -5,25 +5,49 @@ import click
import SoftLayer
from SoftLayer.CLI import environment
+from SoftLayer.CLI import helpers
from SoftLayer.CLI import ticket
@click.command()
@click.option('--title', required=True, help="The title of the ticket")
@click.option('--subject-id',
+ type=int,
required=True,
help="""The subject id to use for the ticket,
issue 'slcli ticket subjects' to get the list""")
@click.option('--body', help="The ticket body")
+ at click.option('--hardware',
+ 'hardware_identifier',
+ help="The identifier for hardware to attach")
+ at click.option('--virtual',
+ 'virtual_identifier',
+ help="The identifier for a virtual server to attach")
@environment.pass_env
-def cli(env, title, subject_id, body):
+def cli(env, title, subject_id, body, hardware_identifier, virtual_identifier):
"""Create a support ticket."""
- mgr = SoftLayer.TicketManager(env.client)
+ ticket_mgr = SoftLayer.TicketManager(env.client)
if body is None:
body = click.edit('\n\n' + ticket.TEMPLATE_MSG)
- created_ticket = mgr.create_ticket(title=title,
- body=body,
- subject=subject_id)
- env.fout(ticket.get_ticket_results(mgr, created_ticket['id']))
+ created_ticket = ticket_mgr.create_ticket(
+ title=title,
+ body=body,
+ subject=subject_id)
+
+ if hardware_identifier:
+ hardware_mgr = SoftLayer.HardwareManager(env.client)
+ hardware_id = helpers.resolve_id(hardware_mgr.resolve_ids,
+ hardware_identifier,
+ 'hardware')
+ ticket_mgr.attach_hardware(created_ticket['id'], hardware_id)
+
+ if virtual_identifier:
+ vs_mgr = SoftLayer.VSManager(env.client)
+ vs_id = helpers.resolve_id(vs_mgr.resolve_ids,
+ virtual_identifier,
+ 'VS')
+ ticket_mgr.attach_virtual_server(created_ticket['id'], vs_id)
+
+ env.fout(ticket.get_ticket_results(ticket_mgr, created_ticket['id']))
diff --git a/SoftLayer/CLI/ticket/detach.py b/SoftLayer/CLI/ticket/detach.py
new file mode 100644
index 0000000..8c8cae0
--- /dev/null
+++ b/SoftLayer/CLI/ticket/detach.py
@@ -0,0 +1,42 @@
+"""Detach devices from a ticket."""
+# :license: MIT, see LICENSE for more details.
+
+import click
+
+import SoftLayer
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import exceptions
+from SoftLayer.CLI import helpers
+
+
+ at click.command()
+ at click.argument('identifier', type=int)
+ at click.option('--hardware',
+ 'hardware_identifier',
+ help="The identifier for hardware to detach")
+ at click.option('--virtual',
+ 'virtual_identifier',
+ help="The identifier for a virtual server to detach")
+ at environment.pass_env
+def cli(env, identifier, hardware_identifier, virtual_identifier):
+ """Detach devices from a ticket."""
+ ticket_mgr = SoftLayer.TicketManager(env.client)
+
+ if hardware_identifier and virtual_identifier:
+ raise exceptions.ArgumentError(
+ "Cannot detach hardware and a virtual server at the same time")
+ elif hardware_identifier:
+ hardware_mgr = SoftLayer.HardwareManager(env.client)
+ hardware_id = helpers.resolve_id(hardware_mgr.resolve_ids,
+ hardware_identifier,
+ 'hardware')
+ ticket_mgr.detach_hardware(identifier, hardware_id)
+ elif virtual_identifier:
+ vs_mgr = SoftLayer.VSManager(env.client)
+ vs_id = helpers.resolve_id(vs_mgr.resolve_ids,
+ virtual_identifier,
+ 'VS')
+ ticket_mgr.detach_virtual_server(identifier, vs_id)
+ else:
+ raise exceptions.ArgumentError(
+ "Must have a hardware or virtual server identifier to detach")
diff --git a/SoftLayer/CLI/virt/detail.py b/SoftLayer/CLI/virt/detail.py
index 957cce8..a4464e6 100644
--- a/SoftLayer/CLI/virt/detail.py
+++ b/SoftLayer/CLI/virt/detail.py
@@ -90,9 +90,19 @@ def cli(env, identifier, passwords=False, price=False):
result['billingItem']['recurringFee']])
if passwords:
- pass_table = formatting.Table(['username', 'password'])
- for item in result['operatingSystem']['passwords']:
- pass_table.add_row([item['username'], item['password']])
+ pass_table = formatting.Table(['software', 'username', 'password'])
+
+ for component in result['softwareComponents']:
+ for item in component['passwords']:
+ pass_table.add_row([
+ utils.lookup(component,
+ 'softwareLicense',
+ 'softwareDescription',
+ 'name'),
+ item['username'],
+ item['password'],
+ ])
+
table.add_row(['users', pass_table])
table.add_row(['tags', formatting.tags(result['tagReferences'])])
diff --git a/SoftLayer/CLI/vlan/detail.py b/SoftLayer/CLI/vlan/detail.py
index f97928a..59a0865 100644
--- a/SoftLayer/CLI/vlan/detail.py
+++ b/SoftLayer/CLI/vlan/detail.py
@@ -39,7 +39,7 @@ def cli(env, identifier, no_vs, no_hardware):
table.add_row(['firewall',
'Yes' if vlan['firewallInterfaces'] else 'No'])
subnets = []
- for subnet in vlan['subnets']:
+ for subnet in vlan.get('subnets', []):
subnet_table = formatting.KeyValueTable(['name', 'value'])
subnet_table.align['name'] = 'r'
subnet_table.align['value'] = 'l'
@@ -57,7 +57,7 @@ def cli(env, identifier, no_vs, no_hardware):
server_columns = ['hostname', 'domain', 'public_ip', 'private_ip']
if not no_vs:
- if vlan['virtualGuests']:
+ if vlan.get('virtualGuests'):
vs_table = formatting.KeyValueTable(server_columns)
for vsi in vlan['virtualGuests']:
vs_table.add_row([vsi['hostname'],
@@ -69,7 +69,7 @@ def cli(env, identifier, no_vs, no_hardware):
table.add_row(['vs', 'none'])
if not no_hardware:
- if vlan['hardware']:
+ if vlan.get('hardware'):
hw_table = formatting.Table(server_columns)
for hardware in vlan['hardware']:
hw_table.add_row([hardware['hostname'],
diff --git a/SoftLayer/consts.py b/SoftLayer/consts.py
index abcd90c..184730e 100644
--- a/SoftLayer/consts.py
+++ b/SoftLayer/consts.py
@@ -5,7 +5,7 @@
:license: MIT, see LICENSE for more details.
"""
-VERSION = 'v5.0.1'
+VERSION = 'v5.1.0'
API_PUBLIC_ENDPOINT = 'https://api.softlayer.com/xmlrpc/v3.1/'
API_PRIVATE_ENDPOINT = 'https://api.service.softlayer.com/xmlrpc/v3.1/'
API_PUBLIC_ENDPOINT_REST = 'https://api.softlayer.com/rest/v3.1/'
diff --git a/SoftLayer/fixtures/SoftLayer_Account.py b/SoftLayer/fixtures/SoftLayer_Account.py
index a1fde3c..b03c26d 100644
--- a/SoftLayer/fixtures/SoftLayer_Account.py
+++ b/SoftLayer/fixtures/SoftLayer_Account.py
@@ -509,3 +509,23 @@ getNextInvoiceTotalAmount = 2
getHubNetworkStorage = [{'id': 12345, 'username': 'SLOS12345-1'},
{'id': 12346, 'username': 'SLOS12345-2'}]
+
+getIscsiNetworkStorage = [{
+ 'accountId': 1234,
+ 'billingItem': {'id': 449},
+ 'capacityGb': 20,
+ 'createDate': '2015:50:15-04:00',
+ 'guestId': '',
+ 'hardwareId': '',
+ 'hostId': '',
+ 'id': 100,
+ 'nasType': 'ISCSI',
+ 'notes': """{'status': 'available'}""",
+ 'password': '',
+ 'serviceProviderId': 1,
+ 'serviceResource': {'datacenter': {'id': 449500}},
+ 'serviceResourceBackendIpAddress': '10.1.2.3',
+ 'serviceResourceName': 'Storage Type 01 Aggregate staaspar0101_pc01',
+ 'username': 'username',
+ 'storageType': {'keyName': 'ENDURANCE_STORAGE'},
+}]
diff --git a/SoftLayer/fixtures/SoftLayer_Network_Storage.py b/SoftLayer/fixtures/SoftLayer_Network_Storage.py
new file mode 100644
index 0000000..0257b16
--- /dev/null
+++ b/SoftLayer/fixtures/SoftLayer_Network_Storage.py
@@ -0,0 +1,65 @@
+getObject = {
+ 'accountId': 1234,
+ 'billingItem': {'id': 449},
+ 'capacityGb': 20,
+ 'createDate': '2015:50:15-04:00',
+ 'guestId': '',
+ 'hardwareId': '',
+ 'hostId': '',
+ 'id': 100,
+ 'nasType': 'ISCSI',
+ 'notes': """{'status': 'available'}""",
+ 'password': '',
+ 'serviceProviderId': 1,
+ 'iops': 1000,
+ 'storageTierLevel': {'description': 'Tier 1'},
+ 'snapshotCapacityGb': 10,
+ 'parentVolume': {'snapshotSizeBytes': 1024},
+ 'serviceResource': {'datacenter': {'id': 449500, 'name': 'dal05'}},
+ 'serviceResourceBackendIpAddress': '10.1.2.3',
+ 'serviceResourceName': 'Storage Type 01 Aggregate staaspar0101_pc01',
+ 'username': 'username',
+ 'storageType': {'keyName': 'ENDURANCE_STORAGE'},
+ 'allowedVirtualGuests': [{
+ 'id': 1234,
+ 'hostname': 'test-server',
+ 'domain': 'example.com',
+ 'primaryBackendIpAddress': '10.0.0.1',
+ 'allowedHost': {
+ 'name': 'test-server',
+ 'credential': {'username': 'joe', 'password': '12345'},
+ },
+ }],
+ 'lunId': 2,
+ 'allowedHardware': [{
+ 'id': 1234,
+ 'hostname': 'test-server',
+ 'domain': 'example.com',
+ 'primaryBackendIpAddress': '10.0.0.2',
+ 'allowedHost': {
+ 'name': 'test-server',
+ 'credential': {'username': 'joe', 'password': '12345'},
+ },
+ }],
+ 'allowedSubnets': [{
+ 'id': 1234,
+ 'networkIdentifier': '10.0.0.1',
+ 'cidr': '24',
+ 'note': 'backend subnet',
+ 'allowedHost': {
+ 'name': 'test-server',
+ 'credential': {'username': 'joe', 'password': '12345'},
+ },
+ }],
+ 'allowedIpAddresses': [{
+ 'id': 1234,
+ 'ipAddress': '10.0.0.1',
+ 'note': 'backend ip',
+ 'allowedHost': {
+ 'name': 'test-server',
+ 'credential': {'username': 'joe', 'password': '12345'},
+ },
+ }],
+}
+getSnapshots = []
+deleteObject = True
diff --git a/SoftLayer/fixtures/SoftLayer_Ticket.py b/SoftLayer/fixtures/SoftLayer_Ticket.py
index 4933cc6..c85deda 100644
--- a/SoftLayer/fixtures/SoftLayer_Ticket.py
+++ b/SoftLayer/fixtures/SoftLayer_Ticket.py
@@ -33,3 +33,20 @@ createStandardTicket = {
}
edit = True
addUpdate = {}
+
+addAttachedHardware = {
+ "id": 123,
+ "createDate": "2013-08-01T14:14:04-07:00",
+ "hardwareId": 1,
+ "ticketId": 100
+}
+
+addAttachedVirtualGuest = {
+ "id": 123,
+ "createDate": "2013-08-01T14:14:04-07:00",
+ "virtualGuestId": 1,
+ "ticketId": 100
+}
+
+removeAttachedHardware = True
+removeAttachedVirtualGuest = True
diff --git a/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py b/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py
index 4380096..cb067b4 100644
--- a/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py
+++ b/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py
@@ -40,6 +40,11 @@ getObject = {
'softwareDescription': {'version': '12.04-64 Minimal for VSI',
'name': 'Ubuntu'}}
},
+ 'softwareComponents': [{
+ 'passwords': [{'username': 'user', 'password': 'pass'}],
+ 'softwareLicense': {
+ 'softwareDescription': {'name': 'Ubuntu'}}
+ }],
'tagReferences': [{'tag': {'name': 'production'}}],
}
diff --git a/SoftLayer/managers/__init__.py b/SoftLayer/managers/__init__.py
index ff8b040..cab39fb 100644
--- a/SoftLayer/managers/__init__.py
+++ b/SoftLayer/managers/__init__.py
@@ -7,6 +7,7 @@
:license: MIT, see LICENSE for more details.
"""
+from SoftLayer.managers.block import BlockStorageManager
from SoftLayer.managers.cdn import CDNManager
from SoftLayer.managers.dns import DNSManager
from SoftLayer.managers.firewall import FirewallManager
@@ -25,6 +26,7 @@ from SoftLayer.managers.ticket import TicketManager
from SoftLayer.managers.vs import VSManager
__all__ = [
+ 'BlockStorageManager',
'CDNManager',
... 1900 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-softlayer.git
More information about the Python-modules-commits
mailing list