[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