[Python-modules-commits] [python-softlayer] 01/06: Imported Upstream version 5.3.2
Scott Kitterman
kitterman at moszumanska.debian.org
Wed Jan 10 04:52:58 UTC 2018
This is an automated email from the git hooks/post-receive script.
kitterman pushed a commit to branch debian/master
in repository python-softlayer.
commit b8e5bd3315de93c29d6b0ead2dad19c769f12e13
Author: Scott Kitterman <scott at kitterman.com>
Date: Tue Jan 9 23:42:05 2018 -0500
Imported Upstream version 5.3.2
---
.travis.yml | 4 -
CHANGELOG.md | 35 +-
SoftLayer/API.py | 4 +-
SoftLayer/CLI/__init__.py | 2 +-
SoftLayer/CLI/block/detail.py | 22 +-
SoftLayer/CLI/block/duplicate.py | 4 +-
SoftLayer/CLI/block/modify.py | 57 ++
SoftLayer/CLI/block/replication/order.py | 4 +-
SoftLayer/CLI/block/snapshot/disable.py | 7 +-
SoftLayer/CLI/block/snapshot/enable.py | 11 +-
SoftLayer/CLI/block/snapshot/schedule_list.py | 70 +++
SoftLayer/CLI/config/setup.py | 13 +-
SoftLayer/CLI/dedicatedhost/__init__.py | 2 +
SoftLayer/CLI/dedicatedhost/create.py | 114 ++++
SoftLayer/CLI/dedicatedhost/create_options.py | 61 ++
SoftLayer/CLI/dedicatedhost/detail.py | 65 +++
SoftLayer/CLI/dedicatedhost/list.py | 70 +++
SoftLayer/CLI/exceptions.py | 1 +
SoftLayer/CLI/file/detail.py | 22 +-
SoftLayer/CLI/file/modify.py | 57 ++
SoftLayer/CLI/file/replication/order.py | 4 +-
SoftLayer/CLI/file/snapshot/disable.py | 7 +-
SoftLayer/CLI/file/snapshot/enable.py | 11 +-
SoftLayer/CLI/file/snapshot/schedule_list.py | 70 +++
SoftLayer/CLI/firewall/edit.py | 2 -
SoftLayer/CLI/formatting.py | 2 +-
SoftLayer/CLI/hardware/create.py | 2 +-
SoftLayer/CLI/hardware/credentials.py | 4 +-
SoftLayer/CLI/hardware/detail.py | 89 +--
SoftLayer/CLI/hardware/power.py | 17 +
SoftLayer/CLI/hardware/rescue.py | 28 -
SoftLayer/CLI/routes.py | 14 +
SoftLayer/CLI/storage_utils.py | 10 +
SoftLayer/CLI/virt/__init__.py | 8 +-
SoftLayer/CLI/virt/detail.py | 22 +
SoftLayer/__init__.py | 2 +-
SoftLayer/config.py | 20 +-
SoftLayer/consts.py | 2 +-
SoftLayer/decoration.py | 48 ++
SoftLayer/fixtures/SoftLayer_Account.py | 14 +-
SoftLayer/fixtures/SoftLayer_Hardware_Server.py | 6 +-
.../fixtures/SoftLayer_Network_SecurityGroup.py | 12 +-
SoftLayer/fixtures/SoftLayer_Network_Storage.py | 42 +-
SoftLayer/fixtures/SoftLayer_Product_Package.py | 239 +++++++-
SoftLayer/fixtures/SoftLayer_Resource_Metadata.py | 16 +-
.../fixtures/SoftLayer_Virtual_DedicatedHost.py | 78 +++
SoftLayer/fixtures/SoftLayer_Virtual_Guest.py | 1 +
SoftLayer/managers/__init__.py | 2 +
SoftLayer/managers/block.py | 50 +-
SoftLayer/managers/dedicated_host.py | 384 +++++++++++++
SoftLayer/managers/file.py | 52 +-
SoftLayer/managers/hardware.py | 12 +-
SoftLayer/managers/metadata.py | 36 +-
SoftLayer/managers/network.py | 8 +-
SoftLayer/managers/storage_utils.py | 173 +++---
SoftLayer/managers/vs.py | 76 +--
SoftLayer/shell/completer.py | 7 +-
SoftLayer/transports.py | 34 +-
docs/conf.py | 4 +-
setup.py | 2 +-
tests/CLI/modules/block_tests.py | 83 ++-
tests/CLI/modules/dedicatedhost_tests.py | 327 +++++++++++
tests/CLI/modules/file_tests.py | 83 ++-
tests/CLI/modules/securitygroup_tests.py | 19 +-
tests/CLI/modules/server_tests.py | 21 +-
tests/CLI/modules/vs_tests.py | 21 +
tests/decoration_tests.py | 95 ++++
tests/managers/block_tests.py | 96 +++-
tests/managers/dedicated_host_tests.py | 616 +++++++++++++++++++++
tests/managers/file_tests.py | 94 ++--
tests/managers/metadata_tests.py | 16 +-
tests/managers/network_tests.py | 17 +-
tests/managers/storage_utils_tests.py | 522 +++++++----------
tests/managers/vs_tests.py | 13 +-
tox.ini | 6 +-
75 files changed, 3440 insertions(+), 824 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index c75b2b6..735f4f6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,10 +4,6 @@ matrix:
include:
- python: "2.7"
env: TOX_ENV=py27
- - python: "3.3"
- env: TOX_ENV=py33
- - python: "3.4"
- env: TOX_ENV=py34
- python: "3.5"
env: TOX_ENV=py35
- python: "3.6"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 910cc1f..faed08f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,40 @@
# Change Log
+## [5.3.2] - 2017-12-18
+ - Changes: https://github.com/softlayer/softlayer-python/compare/v5.3.1...master
+
+ - Expanded `@retry` useage to a few areas in the hardware manager
+ - Added INTERVAL options to block and file replication
+ - Fixed pricing error on `hw detail --price`
+ - Added sub items to `hw detail --price`, removed reverse PTR entries
+
+### Added to CLI
+- slcli dedicatedhost
+
+
+## [5.3.1] - 2017-12-07
+ - Changes: https://github.com/softlayer/softlayer-python/compare/v5.3.0...v5.3.1
+ - Added support for storage volume modifications
+
+### Added to CLI
+- slcli block volume-modify
+- slcli file volume-modify
+
+## [5.3.0] - 2017-12-01
+ - Changes: https://github.com/softlayer/softlayer-python/compare/v5.2.15...v5.3.0
+ - Added a retry decorator. currently only used in setTags for VSI creation, which should allos VSI creation to be a bit more robust.
+ - Updated unit tests to work with pytest3.3
+
+## [5.2.15] - 2017-10-30
+ - Changes: https://github.com/softlayer/softlayer-python/compare/v5.2.14...v5.2.15
+ - Added dedicated host info to virt detail
+ - #885 - Fixed createObjects on the rest api endpoint
+ - changed securityGroups to use createObject instead of createObjects
+ - Always set the endpoint_url by defaulting to the public URL if the endpoint type cannot be determined.
+ - resource metadata update
+
## [5.2.14] - 2017-09-13
- - Changes: https://github.com/softlayer/softlayer-python/compare/v5.2.13...master
+ - Changes: https://github.com/softlayer/softlayer-python/compare/v5.2.13...v5.2.14
- Improved slcli vs create-options output
- Updated slcli vs create to support new virtual server public and dedicated host offerings
diff --git a/SoftLayer/API.py b/SoftLayer/API.py
index 2a79264..b155753 100644
--- a/SoftLayer/API.py
+++ b/SoftLayer/API.py
@@ -5,6 +5,7 @@
:license: MIT, see LICENSE for more details.
"""
+# pylint: disable=invalid-name
import warnings
from SoftLayer import auth as slauth
@@ -12,9 +13,6 @@ from SoftLayer import config
from SoftLayer import consts
from SoftLayer import transports
-# pylint: disable=invalid-name
-
-
API_PUBLIC_ENDPOINT = consts.API_PUBLIC_ENDPOINT
API_PRIVATE_ENDPOINT = consts.API_PRIVATE_ENDPOINT
__all__ = [
diff --git a/SoftLayer/CLI/__init__.py b/SoftLayer/CLI/__init__.py
index 5e4389c..3d5d6bf 100644
--- a/SoftLayer/CLI/__init__.py
+++ b/SoftLayer/CLI/__init__.py
@@ -5,6 +5,6 @@
:license: MIT, see LICENSE for more details.
"""
-# pylint: disable=w0401
+# pylint: disable=w0401, invalid-name
from SoftLayer.CLI.helpers import * # NOQA
diff --git a/SoftLayer/CLI/block/detail.py b/SoftLayer/CLI/block/detail.py
index 70a41c0..ecfd5c4 100644
--- a/SoftLayer/CLI/block/detail.py
+++ b/SoftLayer/CLI/block/detail.py
@@ -62,12 +62,10 @@ def cli(env, volume_id):
if block_volume['activeTransactions']:
for trans in block_volume['activeTransactions']:
- table.add_row([
- 'Ongoing Transactions',
- trans['transactionStatus']['friendlyName']])
+ if 'transactionStatus' in trans and 'friendlyName' in trans['transactionStatus']:
+ table.add_row(['Ongoing Transaction', trans['transactionStatus']['friendlyName']])
- table.add_row(['Replicant Count', "%u"
- % block_volume['replicationPartnerCount']])
+ table.add_row(['Replicant Count', "%u" % block_volume.get('replicationPartnerCount', 0)])
if block_volume['replicationPartnerCount'] > 0:
# This if/else temporarily handles a bug in which the SL API
@@ -102,12 +100,12 @@ def cli(env, volume_id):
table.add_row(['Replicant Volumes', replicant_list])
if block_volume.get('originalVolumeSize'):
- duplicate_info = formatting.Table(['Original Volume Name',
- block_volume['originalVolumeName']])
- duplicate_info.add_row(['Original Volume Size',
- block_volume['originalVolumeSize']])
- duplicate_info.add_row(['Original Snapshot Name',
- block_volume['originalSnapshotName']])
- table.add_row(['Duplicate Volume Properties', duplicate_info])
+ original_volume_info = formatting.Table(['Property', 'Value'])
+ original_volume_info.add_row(['Original Volume Size', block_volume['originalVolumeSize']])
+ if block_volume.get('originalVolumeName'):
+ original_volume_info.add_row(['Original Volume Name', block_volume['originalVolumeName']])
+ if block_volume.get('originalSnapshotName'):
+ original_volume_info.add_row(['Original Snapshot Name', block_volume['originalSnapshotName']])
+ table.add_row(['Original Volume Properties', original_volume_info])
env.fout(table)
diff --git a/SoftLayer/CLI/block/duplicate.py b/SoftLayer/CLI/block/duplicate.py
index 0ecf591..ec728f8 100644
--- a/SoftLayer/CLI/block/duplicate.py
+++ b/SoftLayer/CLI/block/duplicate.py
@@ -22,9 +22,7 @@ CONTEXT_SETTINGS = {'token_normalize_func': lambda x: x.upper()}
'the origin volume will be used.***\n'
'Potential Sizes: [20, 40, 80, 100, 250, '
'500, 1000, 2000, 4000, 8000, 12000] '
- 'Minimum: [the size of the origin volume] '
- 'Maximum: [the minimum of 12000 GB or '
- '10*(origin volume size)]')
+ 'Minimum: [the size of the origin volume]')
@click.option('--duplicate-iops', '-i',
type=int,
help='Performance Storage IOPS, between 100 and 6000 in '
diff --git a/SoftLayer/CLI/block/modify.py b/SoftLayer/CLI/block/modify.py
new file mode 100644
index 0000000..3697ddd
--- /dev/null
+++ b/SoftLayer/CLI/block/modify.py
@@ -0,0 +1,57 @@
+"""Modify an existing 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 = {'token_normalize_func': lambda x: x.upper()}
+
+
+ at click.command(context_settings=CONTEXT_SETTINGS)
+ at click.argument('volume-id')
+ at click.option('--new-size', '-c',
+ type=int,
+ help='New Size of block volume in GB. ***If no size is given, the original size of volume is used.***\n'
+ 'Potential Sizes: [20, 40, 80, 100, 250, 500, 1000, 2000, 4000, 8000, 12000]\n'
+ 'Minimum: [the original size of the volume]')
+ at click.option('--new-iops', '-i',
+ type=int,
+ help='Performance Storage IOPS, between 100 and 6000 in multiples of 100 [only for performance volumes] '
+ '***If no IOPS value is specified, the original IOPS value of the volume will be used.***\n'
+ 'Requirements: [If original IOPS/GB for the volume is less than 0.3, new IOPS/GB must also be '
+ 'less than 0.3. If original IOPS/GB for the volume is greater than or equal to 0.3, new IOPS/GB '
+ 'for the volume must also be greater than or equal to 0.3.]')
+ at click.option('--new-tier', '-t',
+ help='Endurance Storage Tier (IOPS per GB) [only for endurance volumes] '
+ '***If no tier is specified, the original tier of the volume will be used.***\n'
+ 'Requirements: [If original IOPS/GB for the volume is 0.25, new IOPS/GB for the volume must also '
+ 'be 0.25. If original IOPS/GB for the volume is greater than 0.25, new IOPS/GB for the volume '
+ 'must also be greater than 0.25.]',
+ type=click.Choice(['0.25', '2', '4', '10']))
+ at environment.pass_env
+def cli(env, volume_id, new_size, new_iops, new_tier):
+ """Modify an existing block storage volume."""
+ block_manager = SoftLayer.BlockStorageManager(env.client)
+
+ if new_tier is not None:
+ new_tier = float(new_tier)
+
+ try:
+ order = block_manager.order_modified_volume(
+ volume_id,
+ new_size=new_size,
+ new_iops=new_iops,
+ new_tier_level=new_tier,
+ )
+ 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/replication/order.py b/SoftLayer/CLI/block/replication/order.py
index 5aebea1..743c91c 100644
--- a/SoftLayer/CLI/block/replication/order.py
+++ b/SoftLayer/CLI/block/replication/order.py
@@ -14,9 +14,9 @@ CONTEXT_SETTINGS = {'token_normalize_func': lambda x: x.upper()}
@click.argument('volume_id')
@click.option('--snapshot-schedule', '-s',
help='Snapshot schedule to use for replication, '
- '(HOURLY | DAILY | WEEKLY)',
+ '(INTERVAL | HOURLY | DAILY | WEEKLY)',
required=True,
- type=click.Choice(['HOURLY', 'DAILY', 'WEEKLY']))
+ type=click.Choice(['INTERVAL', 'HOURLY', 'DAILY', 'WEEKLY']))
@click.option('--location', '-l',
help='Short name of the data center for the replicant '
'(e.g.: dal09)',
diff --git a/SoftLayer/CLI/block/snapshot/disable.py b/SoftLayer/CLI/block/snapshot/disable.py
index f34d348..0d776bc 100644
--- a/SoftLayer/CLI/block/snapshot/disable.py
+++ b/SoftLayer/CLI/block/snapshot/disable.py
@@ -10,16 +10,15 @@ from SoftLayer.CLI import exceptions
@click.command()
@click.argument('volume_id')
@click.option('--schedule-type',
- help='Snapshot schedule [HOURLY|DAILY|WEEKLY]',
+ help='Snapshot schedule [INTERVAL|HOURLY|DAILY|WEEKLY]',
required=True)
@environment.pass_env
def cli(env, volume_id, schedule_type):
"""Disables snapshots on the specified schedule for a given volume"""
- if (schedule_type != 'HOURLY' and schedule_type != 'DAILY'
- and schedule_type != 'WEEKLY'):
+ if (schedule_type not in ['INTERVAL', 'HOURLY', 'DAILY', 'WEEKLY']):
raise exceptions.CLIAbort(
- '--schedule-type must be HOURLY, DAILY, or WEEKLY')
+ '--schedule-type must be INTERVAL, HOURLY, DAILY, or WEEKLY')
block_manager = SoftLayer.BlockStorageManager(env.client)
disabled = block_manager.disable_snapshots(volume_id, schedule_type)
diff --git a/SoftLayer/CLI/block/snapshot/enable.py b/SoftLayer/CLI/block/snapshot/enable.py
index 6ade946..e81443e 100644
--- a/SoftLayer/CLI/block/snapshot/enable.py
+++ b/SoftLayer/CLI/block/snapshot/enable.py
@@ -10,7 +10,7 @@ from SoftLayer.CLI import exceptions
@click.command()
@click.argument('volume_id')
@click.option('--schedule-type',
- help='Snapshot schedule [HOURLY|DAILY|WEEKLY]',
+ help='Snapshot schedule [INTERVAL|HOURLY|DAILY|WEEKLY]',
required=True)
@click.option('--retention-count',
help='Number of snapshots to retain',
@@ -30,15 +30,18 @@ def cli(env, volume_id, schedule_type, retention_count,
"""Enables snapshots for a given volume on the specified schedule"""
block_manager = SoftLayer.BlockStorageManager(env.client)
- valid_schedule_types = {'HOURLY', 'DAILY', 'WEEKLY'}
+ valid_schedule_types = {'INTERVAL', 'HOURLY', 'DAILY', 'WEEKLY'}
valid_days = {'SUNDAY', 'MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY',
'FRIDAY', 'SATURDAY'}
if schedule_type not in valid_schedule_types:
raise exceptions.CLIAbort(
- '--schedule-type must be HOURLY, DAILY, or WEEKLY, not '
- + schedule_type)
+ '--schedule-type must be INTERVAL, HOURLY, DAILY,' +
+ 'or WEEKLY, not ' + schedule_type)
+ if schedule_type == 'INTERVAL' and (minute < 30 or minute > 59):
+ raise exceptions.CLIAbort(
+ '--minute value must be between 30 and 59')
if minute < 0 or minute > 59:
raise exceptions.CLIAbort(
'--minute value must be between 0 and 59')
diff --git a/SoftLayer/CLI/block/snapshot/schedule_list.py b/SoftLayer/CLI/block/snapshot/schedule_list.py
new file mode 100644
index 0000000..022427e
--- /dev/null
+++ b/SoftLayer/CLI/block/snapshot/schedule_list.py
@@ -0,0 +1,70 @@
+"""List scheduled snapshots of a specific volume"""
+# :license: MIT, see LICENSE for more details.
+
+import click
+import SoftLayer
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import formatting
+
+
+ at click.command()
+ at click.argument('volume_id')
+ at environment.pass_env
+def cli(env, volume_id):
+ """Lists snapshot schedules for a given volume"""
+
+ block_manager = SoftLayer.BlockStorageManager(env.client)
+
+ snapshot_schedules = block_manager.list_volume_schedules(volume_id)
+
+ table = formatting.Table(['id',
+ 'active',
+ 'type',
+ 'replication',
+ 'date_created',
+ 'minute',
+ 'hour',
+ 'day',
+ 'week',
+ 'day_of_week',
+ 'date_of_month',
+ 'month_of_year',
+ 'maximum_snapshots'])
+
+ for schedule in snapshot_schedules:
+
+ if 'REPLICATION' in schedule['type']['keyname']:
+ replication = '*'
+ else:
+ replication = formatting.blank()
+
+ block_schedule_type = schedule['type']['keyname'].replace('REPLICATION_', '')
+ block_schedule_type = block_schedule_type.replace('SNAPSHOT_', '')
+
+ property_list = ['MINUTE', 'HOUR', 'DAY', 'WEEK',
+ 'DAY_OF_WEEK', 'DAY_OF_MONTH',
+ 'MONTH_OF_YEAR', 'SNAPSHOT_LIMIT']
+
+ schedule_properties = []
+ for prop_key in property_list:
+ item = formatting.blank()
+ for schedule_property in schedule.get('properties', []):
+ if schedule_property['type']['keyname'] == prop_key:
+ if schedule_property['value'] == '-1':
+ item = '*'
+ else:
+ item = schedule_property['value']
+ break
+ schedule_properties.append(item)
+
+ table_row = [
+ schedule['id'],
+ '*' if schedule.get('active', '') else '',
+ block_schedule_type,
+ replication,
+ schedule.get('createDate', '')]
+ table_row.extend(schedule_properties)
+
+ table.add_row(table_row)
+
+ env.fout(table)
diff --git a/SoftLayer/CLI/config/setup.py b/SoftLayer/CLI/config/setup.py
index de3399a..cd5a24c 100644
--- a/SoftLayer/CLI/config/setup.py
+++ b/SoftLayer/CLI/config/setup.py
@@ -106,15 +106,14 @@ def get_user_input(env):
endpoint_type = env.input(
'Endpoint (public|private|custom)', default='public')
endpoint_type = endpoint_type.lower()
- if endpoint_type is None:
- endpoint_url = SoftLayer.API_PUBLIC_ENDPOINT
- if endpoint_type == 'public':
- endpoint_url = SoftLayer.API_PUBLIC_ENDPOINT
- elif endpoint_type == 'private':
- endpoint_url = SoftLayer.API_PRIVATE_ENDPOINT
- elif endpoint_type == 'custom':
+
+ if endpoint_type == 'custom':
endpoint_url = env.input('Endpoint URL',
default=defaults['endpoint_url'])
+ elif endpoint_type == 'private':
+ endpoint_url = SoftLayer.API_PRIVATE_ENDPOINT
+ else:
+ endpoint_url = SoftLayer.API_PUBLIC_ENDPOINT
# Ask for timeout
timeout = env.input('Timeout', default=defaults['timeout'] or 0)
diff --git a/SoftLayer/CLI/dedicatedhost/__init__.py b/SoftLayer/CLI/dedicatedhost/__init__.py
new file mode 100644
index 0000000..55d5d79
--- /dev/null
+++ b/SoftLayer/CLI/dedicatedhost/__init__.py
@@ -0,0 +1,2 @@
+"""Dedicated Host."""
+# :license: MIT, see LICENSE for more details.
diff --git a/SoftLayer/CLI/dedicatedhost/create.py b/SoftLayer/CLI/dedicatedhost/create.py
new file mode 100644
index 0000000..491da21
--- /dev/null
+++ b/SoftLayer/CLI/dedicatedhost/create.py
@@ -0,0 +1,114 @@
+"""Order/create a dedicated Host."""
+# :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
+from SoftLayer.CLI import template
+
+
+ at click.command(
+ epilog="See 'slcli dedicatedhost create-options' for valid options.")
+ at click.option('--hostname', '-H',
+ help="Host portion of the FQDN",
+ required=True,
+ prompt=True)
+ at click.option('--router', '-r',
+ help="Router hostname ex. fcr02a.dal13",
+ show_default=True)
+ at click.option('--domain', '-D',
+ help="Domain portion of the FQDN",
+ required=True,
+ prompt=True)
+ at click.option('--datacenter', '-d', help="Datacenter shortname",
+ required=True,
+ prompt=True)
+ at click.option('--flavor', '-f', help="Dedicated Virtual Host flavor",
+ required=True,
+ prompt=True)
+ at click.option('--billing',
+ type=click.Choice(['hourly', 'monthly']),
+ default='hourly',
+ show_default=True,
+ help="Billing rate")
+ at click.option('--verify',
+ is_flag=True,
+ help="Verify dedicatedhost without creating it.")
+ at click.option('--template', '-t',
+ is_eager=True,
+ callback=template.TemplateCallback(list_args=['key']),
+ help="A template file that defaults the command-line options",
+ type=click.Path(exists=True, readable=True, resolve_path=True))
+ at click.option('--export',
+ type=click.Path(writable=True, resolve_path=True),
+ help="Exports options to a template file")
+ at environment.pass_env
+def cli(env, **kwargs):
+ """Order/create a dedicated host."""
+ mgr = SoftLayer.DedicatedHostManager(env.client)
+
+ order = {
+ 'hostname': kwargs['hostname'],
+ 'domain': kwargs['domain'],
+ 'flavor': kwargs['flavor'],
+ 'location': kwargs['datacenter'],
+ 'hourly': kwargs.get('billing') == 'hourly',
+ }
+
+ if kwargs['router']:
+ order['router'] = kwargs['router']
+
+ do_create = not (kwargs['export'] or kwargs['verify'])
+
+ output = None
+
+ result = mgr.verify_order(**order)
+ table = formatting.Table(['Item', 'cost'])
+ table.align['Item'] = 'r'
+ table.align['cost'] = 'r'
+ if len(result['prices']) != 1:
+ raise exceptions.ArgumentError("More than 1 price was found or no "
+ "prices found")
+ price = result['prices']
+ if order['hourly']:
+ total = float(price[0].get('hourlyRecurringFee', 0.0))
+ else:
+ total = float(price[0].get('recurringFee', 0.0))
+
+ if order['hourly']:
+ table.add_row(['Total hourly cost', "%.2f" % total])
+ else:
+ table.add_row(['Total monthly cost', "%.2f" % total])
+
+ output = []
+ output.append(table)
+ output.append(formatting.FormattedItem(
+ '',
+ ' -- ! Prices reflected here are retail and do not '
+ 'take account level discounts and are not guaranteed.'))
+
+ if kwargs['export']:
+ export_file = kwargs.pop('export')
+ template.export_to_template(export_file, kwargs,
+ exclude=['wait', 'verify'])
+ env.fout('Successfully exported options to a template file.')
+
+ if do_create:
+ if not env.skip_confirmations and not formatting.confirm(
+ "This action will incur charges on your account. "
+ "Continue?"):
+ raise exceptions.CLIAbort('Aborting dedicated host order.')
+
+ result = mgr.place_order(**order)
+
+ table = formatting.KeyValueTable(['name', 'value'])
+ table.align['name'] = 'r'
+ table.align['value'] = 'l'
+ table.add_row(['id', result['orderId']])
+ table.add_row(['created', result['orderDate']])
+ output.append(table)
+
+ env.fout(output)
diff --git a/SoftLayer/CLI/dedicatedhost/create_options.py b/SoftLayer/CLI/dedicatedhost/create_options.py
new file mode 100644
index 0000000..94727ce
--- /dev/null
+++ b/SoftLayer/CLI/dedicatedhost/create_options.py
@@ -0,0 +1,61 @@
+"""Options for ordering a dedicated host"""
+# :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.option('--datacenter', '-d',
+ help="Router hostname (requires --flavor) "
+ "ex. ams01",
+ show_default=True)
+ at click.option('--flavor', '-f',
+ help="Dedicated Virtual Host flavor (requires --datacenter)"
+ " ex. 56_CORES_X_242_RAM_X_1_4_TB",
+ show_default=True)
+ at environment.pass_env
+def cli(env, **kwargs):
+ """host order options for a given dedicated host.
+
+ To get a list of available backend routers see example:
+ slcli dh create-options --datacenter dal05 --flavor 56_CORES_X_242_RAM_X_1_4_TB
+ """
+
+ mgr = SoftLayer.DedicatedHostManager(env.client)
+ tables = []
+
+ if not kwargs['flavor'] and not kwargs['datacenter']:
+ options = mgr.get_create_options()
+
+ # Datacenters
+ dc_table = formatting.Table(['datacenter', 'value'])
+ dc_table.sortby = 'value'
+ for location in options['locations']:
+ dc_table.add_row([location['name'], location['key']])
+ tables.append(dc_table)
+
+ dh_table = formatting.Table(['Dedicated Virtual Host Flavor(s)', 'value'])
+ dh_table.sortby = 'value'
+ for item in options['dedicated_host']:
+ dh_table.add_row([item['name'], item['key']])
+ tables.append(dh_table)
+ else:
+ if kwargs['flavor'] is None or kwargs['datacenter'] is None:
+ raise exceptions.ArgumentError('Both a flavor and datacenter need '
+ 'to be passed as arguments '
+ 'ex. slcli dh create-options -d '
+ 'ams01 -f '
+ '56_CORES_X_242_RAM_X_1_4_TB')
+ router_opt = mgr.get_router_options(kwargs['datacenter'], kwargs['flavor'])
+ br_table = formatting.Table(
+ ['Available Backend Routers'])
+ for router in router_opt:
+ br_table.add_row([router['hostname']])
+ tables.append(br_table)
+
+ env.fout(formatting.listing(tables, separator='\n'))
diff --git a/SoftLayer/CLI/dedicatedhost/detail.py b/SoftLayer/CLI/dedicatedhost/detail.py
new file mode 100644
index 0000000..e1c46b9
--- /dev/null
+++ b/SoftLayer/CLI/dedicatedhost/detail.py
@@ -0,0 +1,65 @@
+"""Get details for a dedicated host."""
+# :license: MIT, see LICENSE for more details.
+
+import logging
+
+import click
+
+import SoftLayer
+from SoftLayer.CLI import environment
+from SoftLayer.CLI import formatting
+from SoftLayer import utils
+
+LOGGER = logging.getLogger(__name__)
+
+
+ at click.command()
+ at click.argument('identifier')
+ at click.option('--price', is_flag=True, help='Show associated prices')
+ at click.option('--guests', is_flag=True, help='Show guests on dedicated host')
+ at environment.pass_env
+def cli(env, identifier, price=False, guests=False):
+ """Get details for a virtual server."""
+ dhost = SoftLayer.DedicatedHostManager(env.client)
+
+ table = formatting.KeyValueTable(['name', 'value'])
+ table.align['name'] = 'r'
+ table.align['value'] = 'l'
+
+ result = dhost.get_host(identifier)
+ result = utils.NestedDict(result)
+
+ table.add_row(['id', result['id']])
+ table.add_row(['name', result['name']])
+ table.add_row(['cpu count', result['cpuCount']])
+ table.add_row(['memory capacity', result['memoryCapacity']])
+ table.add_row(['disk capacity', result['diskCapacity']])
+ table.add_row(['create date', result['createDate']])
+ table.add_row(['modify date', result['modifyDate']])
+ table.add_row(['router id', result['backendRouter']['id']])
+ table.add_row(['router hostname', result['backendRouter']['hostname']])
+ table.add_row(['owner', formatting.FormattedItem(
+ utils.lookup(result, 'billingItem', 'orderItem', 'order', 'userRecord', 'username') or formatting.blank(),)])
+
+ if price:
+ total_price = utils.lookup(result,
+ 'billingItem',
+ 'nextInvoiceTotalRecurringAmount') or 0
+ total_price += sum(p['nextInvoiceTotalRecurringAmount']
+ for p
+ in utils.lookup(result,
+ 'billingItem',
+ 'children') or [])
+ table.add_row(['price_rate', total_price])
+
+ table.add_row(['guest count', result['guestCount']])
+ if guests:
+ guest_table = formatting.Table(['id', 'hostname', 'domain', 'uuid'])
+ for guest in result['guests']:
+ guest_table.add_row([
+ guest['id'], guest['hostname'], guest['domain'], guest['uuid']])
+ table.add_row(['guests', guest_table])
+
+ table.add_row(['datacenter', result['datacenter']['name']])
+
+ env.fout(table)
diff --git a/SoftLayer/CLI/dedicatedhost/list.py b/SoftLayer/CLI/dedicatedhost/list.py
new file mode 100644
index 0000000..56feefd
--- /dev/null
+++ b/SoftLayer/CLI/dedicatedhost/list.py
@@ -0,0 +1,70 @@
+"""List dedicated servers."""
+# :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
+from SoftLayer.CLI import helpers
+
+COLUMNS = [
+ column_helper.Column('datacenter', ('datacenter', 'name')),
+ column_helper.Column(
+ 'created_by',
+ ('billingItem', 'orderItem', 'order', 'userRecord', 'username')),
+ column_helper.Column(
+ 'tags',
+ lambda server: formatting.tags(server.get('tagReferences')),
+ mask="tagReferences.tag.name"),
+]
+
+DEFAULT_COLUMNS = [
+ 'id',
+ 'name',
+ 'cpuCount',
+ 'diskCapacity',
+ 'memoryCapacity',
+ 'datacenter',
+ 'guestCount',
+]
+
+
+ at click.command()
+ at click.option('--cpu', '-c', help='Number of CPU cores', type=click.INT)
+ at helpers.multi_option('--tag', help='Filter by tags')
+ at click.option('--sortby', help='Column to sort by',
+ default='name',
+ show_default=True)
+ at click.option('--columns',
+ callback=column_helper.get_formatter(COLUMNS),
+ help='Columns to display. [options: %s]'
+ % ', '.join(column.name for column in COLUMNS),
+ default=','.join(DEFAULT_COLUMNS),
+ show_default=True)
+ at click.option('--datacenter', '-d', help='Datacenter shortname')
+ at click.option('--name', '-H', help='Host portion of the FQDN')
+ at click.option('--memory', '-m', help='Memory capacity in mebibytes',
+ type=click.INT)
+ at click.option('--disk', '-D', help='Disk capacity')
+ at environment.pass_env
+def cli(env, sortby, cpu, columns, datacenter, name, memory, disk, tag):
+ """List dedicated host."""
+ mgr = SoftLayer.DedicatedHostManager(env.client)
+ hosts = mgr.list_instances(cpus=cpu,
+ datacenter=datacenter,
+ hostname=name,
+ memory=memory,
+ disk=disk,
+ tags=tag,
+ mask=columns.mask())
+
+ table = formatting.Table(columns.columns)
+ table.sortby = sortby
+
+ for host in hosts:
+ table.add_row([value or formatting.blank()
+ for value in columns.row(host)])
+
+ env.fout(table)
diff --git a/SoftLayer/CLI/exceptions.py b/SoftLayer/CLI/exceptions.py
index 8f5917f..98b3f28 100644
--- a/SoftLayer/CLI/exceptions.py
+++ b/SoftLayer/CLI/exceptions.py
@@ -7,6 +7,7 @@
"""
+# pylint: disable=keyword-arg-before-vararg
class CLIHalt(SystemExit):
"""Smoothly halt the execution of the command. No error."""
def __init__(self, code=0, *args):
diff --git a/SoftLayer/CLI/file/detail.py b/SoftLayer/CLI/file/detail.py
index 96437dc..cb712dc 100644
--- a/SoftLayer/CLI/file/detail.py
+++ b/SoftLayer/CLI/file/detail.py
@@ -78,12 +78,10 @@ def cli(env, volume_id):
if file_volume['activeTransactions']:
for trans in file_volume['activeTransactions']:
- table.add_row([
- 'Ongoing Transactions',
- trans['transactionStatus']['friendlyName']])
+ if 'transactionStatus' in trans and 'friendlyName' in trans['transactionStatus']:
+ table.add_row(['Ongoing Transaction', trans['transactionStatus']['friendlyName']])
- table.add_row(['Replicant Count', "%u"
- % file_volume['replicationPartnerCount']])
+ table.add_row(['Replicant Count', "%u" % file_volume.get('replicationPartnerCount', 0)])
if file_volume['replicationPartnerCount'] > 0:
# This if/else temporarily handles a bug in which the SL API
@@ -118,12 +116,12 @@ def cli(env, volume_id):
table.add_row(['Replicant Volumes', replicant_list])
if file_volume.get('originalVolumeSize'):
- duplicate_info = formatting.Table(['Original Volume Name',
- file_volume['originalVolumeName']])
- duplicate_info.add_row(['Original Volume Size',
- file_volume['originalVolumeSize']])
- duplicate_info.add_row(['Original Snapshot Name',
- file_volume['originalSnapshotName']])
- table.add_row(['Duplicate Volume Properties', duplicate_info])
+ original_volume_info = formatting.Table(['Property', 'Value'])
+ original_volume_info.add_row(['Original Volume Size', file_volume['originalVolumeSize']])
+ if file_volume.get('originalVolumeName'):
+ original_volume_info.add_row(['Original Volume Name', file_volume['originalVolumeName']])
+ if file_volume.get('originalSnapshotName'):
+ original_volume_info.add_row(['Original Snapshot Name', file_volume['originalSnapshotName']])
+ table.add_row(['Original Volume Properties', original_volume_info])
env.fout(table)
diff --git a/SoftLayer/CLI/file/modify.py b/SoftLayer/CLI/file/modify.py
new file mode 100644
index 0000000..5e0c097
--- /dev/null
+++ b/SoftLayer/CLI/file/modify.py
@@ -0,0 +1,57 @@
+"""Modify an existing file 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 = {'token_normalize_func': lambda x: x.upper()}
+
+
+ at click.command(context_settings=CONTEXT_SETTINGS)
+ at click.argument('volume-id')
+ at click.option('--new-size', '-c',
+ type=int,
+ help='New Size of file volume in GB. ***If no size is given, the original size of volume is used.***\n'
+ 'Potential Sizes: [20, 40, 80, 100, 250, 500, 1000, 2000, 4000, 8000, 12000]\n'
+ 'Minimum: [the original size of the volume]')
+ at click.option('--new-iops', '-i',
+ type=int,
+ help='Performance Storage IOPS, between 100 and 6000 in multiples of 100 [only for performance volumes] '
+ '***If no IOPS value is specified, the original IOPS value of the volume will be used.***\n'
+ 'Requirements: [If original IOPS/GB for the volume is less than 0.3, new IOPS/GB must also be '
+ 'less than 0.3. If original IOPS/GB for the volume is greater than or equal to 0.3, new IOPS/GB '
+ 'for the volume must also be greater than or equal to 0.3.]')
+ at click.option('--new-tier', '-t',
+ help='Endurance Storage Tier (IOPS per GB) [only for endurance volumes] '
+ '***If no tier is specified, the original tier of the volume will be used.***\n'
+ 'Requirements: [If original IOPS/GB for the volume is 0.25, new IOPS/GB for the volume must also '
+ 'be 0.25. If original IOPS/GB for the volume is greater than 0.25, new IOPS/GB for the volume '
+ 'must also be greater than 0.25.]',
+ type=click.Choice(['0.25', '2', '4', '10']))
+ at environment.pass_env
+def cli(env, volume_id, new_size, new_iops, new_tier):
+ """Modify an existing file storage volume."""
+ file_manager = SoftLayer.FileStorageManager(env.client)
+
+ if new_tier is not None:
+ new_tier = float(new_tier)
+
+ try:
+ order = file_manager.order_modified_volume(
+ volume_id,
+ new_size=new_size,
+ new_iops=new_iops,
+ new_tier_level=new_tier,
+ )
+ 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/file/replication/order.py b/SoftLayer/CLI/file/replication/order.py
index 4b3231e..9ba2c84 100644
--- a/SoftLayer/CLI/file/replication/order.py
+++ b/SoftLayer/CLI/file/replication/order.py
@@ -14,9 +14,9 @@ CONTEXT_SETTINGS = {'token_normalize_func': lambda x: x.upper()}
@click.argument('volume_id')
@click.option('--snapshot-schedule', '-s',
help='Snapshot schedule to use for replication, '
- '(HOURLY | DAILY | WEEKLY)',
+ '(INTERVAL | HOURLY | DAILY | WEEKLY)',
required=True,
- type=click.Choice(['HOURLY', 'DAILY', 'WEEKLY']))
+ type=click.Choice(['INTERVAL', 'HOURLY', 'DAILY', 'WEEKLY']))
@click.option('--location', '-l',
help='Short name of the data center for the replicant '
'(e.g.: dal09)',
diff --git a/SoftLayer/CLI/file/snapshot/disable.py b/SoftLayer/CLI/file/snapshot/disable.py
index 9ec4fde..07d68c4 100644
--- a/SoftLayer/CLI/file/snapshot/disable.py
+++ b/SoftLayer/CLI/file/snapshot/disable.py
@@ -10,16 +10,15 @@ from SoftLayer.CLI import exceptions
@click.command()
@click.argument('volume_id')
@click.option('--schedule-type',
- help='Snapshot schedule [HOURLY|DAILY|WEEKLY]',
+ help='Snapshot schedule [INTERVAL|HOURLY|DAILY|WEEKLY]',
required=True)
@environment.pass_env
def cli(env, volume_id, schedule_type):
"""Disables snapshots on the specified schedule for a given volume"""
- if (schedule_type != 'HOURLY' and schedule_type != 'DAILY'
- and schedule_type != 'WEEKLY'):
+ if (schedule_type not in ['INTERVAL', 'HOURLY', 'DAILY', 'WEEKLY']):
raise exceptions.CLIAbort(
- '--schedule_type must be HOURLY, DAILY, or WEEKLY')
+ '--schedule_type must be INTERVAL, HOURLY, DAILY, or WEEKLY')
file_manager = SoftLayer.FileStorageManager(env.client)
disabled = file_manager.disable_snapshots(volume_id, schedule_type)
diff --git a/SoftLayer/CLI/file/snapshot/enable.py b/SoftLayer/CLI/file/snapshot/enable.py
index 7e73fee..d4b3c10 100644
--- a/SoftLayer/CLI/file/snapshot/enable.py
+++ b/SoftLayer/CLI/file/snapshot/enable.py
@@ -10,7 +10,7 @@ from SoftLayer.CLI import exceptions
@click.command()
@click.argument('volume_id')
@click.option('--schedule-type',
- help='Snapshot schedule [HOURLY|DAILY|WEEKLY]',
+ help='Snapshot schedule [INTERVAL|HOURLY|DAILY|WEEKLY]',
required=True)
@click.option('--retention-count',
help='Number of snapshots to retain',
@@ -30,15 +30,18 @@ def cli(env, volume_id, schedule_type, retention_count,
"""Enables snapshots for a given volume on the specified schedule"""
file_manager = SoftLayer.FileStorageManager(env.client)
- valid_schedule_types = {'HOURLY', 'DAILY', 'WEEKLY'}
+ valid_schedule_types = {'INTERVAL', 'HOURLY', 'DAILY', 'WEEKLY'}
valid_days = {'SUNDAY', 'MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY',
'FRIDAY', 'SATURDAY'}
if schedule_type not in valid_schedule_types:
raise exceptions.CLIAbort(
- '--schedule-type must be HOURLY, DAILY, or WEEKLY, not '
- + schedule_type)
+ '--schedule-type must be INTERVAL, HOURLY, ' +
+ 'DAILY, or WEEKLY, not ' + schedule_type)
+ if schedule_type == 'INTERVAL' and (minute < 30 or minute > 59):
... 5321 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