diff --git a/SoftLayer/CLI/block/order.py b/SoftLayer/CLI/block/order.py index 4aaf03067..aa18a1626 100644 --- a/SoftLayer/CLI/block/order.py +++ b/SoftLayer/CLI/block/order.py @@ -17,7 +17,8 @@ required=True) @click.option('--size', type=int, - help='Size of block storage volume in GB', + help='Size of block storage volume in GB. Permitted Sizes:\n' + '20, 40, 80, 100, 250, 500, 1000, 2000, 4000, 8000, 12000', required=True) @click.option('--iops', type=int, @@ -71,7 +72,7 @@ def cli(env, storage_type, size, iops, tier, os_type, if snapshot_size is not None: raise exceptions.CLIAbort( 'Option --snapshot-size not allowed for performance volumes.' - ' Snapshots are only available for endurance storage.' + 'Snapshots are only available for endurance storage.' ) try: diff --git a/SoftLayer/CLI/iscsi/__init__.py b/SoftLayer/CLI/iscsi/__init__.py deleted file mode 100644 index 2b379049a..000000000 --- a/SoftLayer/CLI/iscsi/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""iSCSI storage.""" diff --git a/SoftLayer/CLI/iscsi/cancel.py b/SoftLayer/CLI/iscsi/cancel.py deleted file mode 100644 index f744cb627..000000000 --- a/SoftLayer/CLI/iscsi/cancel.py +++ /dev/null @@ -1,30 +0,0 @@ -"""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 -from SoftLayer.CLI import helpers - - -@click.command() -@click.argument('identifier') -@click.option('--reason', help="An optional reason for cancellation") -@click.option('--immediate', - is_flag=True, - help="Cancels the iSCSI immediately instead of on the billing " - "anniversary") -@environment.pass_env -def cli(env, identifier, reason, immediate): - """Cancel an existing iSCSI account.""" - - iscsi_mgr = SoftLayer.ISCSIManager(env.client) - iscsi_id = helpers.resolve_id(iscsi_mgr.resolve_ids, identifier, 'iSCSI') - - if not (env.skip_confirmations or formatting.no_going_back(iscsi_id)): - raise exceptions.CLIAbort('Aborted') - - iscsi_mgr.cancel_iscsi(iscsi_id, reason, immediate) diff --git a/SoftLayer/CLI/iscsi/create.py b/SoftLayer/CLI/iscsi/create.py deleted file mode 100644 index 95872c79a..000000000 --- a/SoftLayer/CLI/iscsi/create.py +++ /dev/null @@ -1,23 +0,0 @@ -"""Creates an iSCSI target.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment - - -@click.command() -@click.option('--size', - type=click.INT, - required=True, - help="Size of the iSCSI volume to create (in gibibytes)") -@click.option('--datacenter', - required=True, - help="Datacenter shortname (sng01, dal05, ...)") -@environment.pass_env -def cli(env, size, datacenter): - """Creates an iSCSI target.""" - - iscsi_mgr = SoftLayer.ISCSIManager(env.client) - iscsi_mgr.create_iscsi(size=size, location=datacenter) diff --git a/SoftLayer/CLI/iscsi/detail.py b/SoftLayer/CLI/iscsi/detail.py deleted file mode 100644 index 6ad433272..000000000 --- a/SoftLayer/CLI/iscsi/detail.py +++ /dev/null @@ -1,54 +0,0 @@ -"""Get details for an iSCSI target.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import formatting -from SoftLayer.CLI import helpers -from SoftLayer import utils - - -@click.command() -@click.argument('identifier') -@click.option('--password', - is_flag=True, - help="Show credentials to access the iSCSI target") -@environment.pass_env -def cli(env, identifier, password): - """Get details for an iSCSI target.""" - - iscsi_mgr = SoftLayer.ISCSIManager(env.client) - - iscsi_id = helpers.resolve_id(iscsi_mgr.resolve_ids, identifier, 'iSCSI') - result = iscsi_mgr.get_iscsi(iscsi_id) - result = utils.NestedDict(result) - - table = formatting.KeyValueTable(['name', 'value']) - table.align['name'] = 'r' - table.align['value'] = 'l' - - table.add_row(['id', result['id']]) - table.add_row(['serviceResourceName', result['serviceResourceName']]) - table.add_row(['createDate', result['createDate']]) - table.add_row(['nasType', result['nasType']]) - table.add_row(['capacityGb', result['capacityGb']]) - - if result['snapshotCapacityGb']: - table.add_row(['snapshotCapacityGb', result['snapshotCapacityGb']]) - - table.add_row(['mountableFlag', result['mountableFlag']]) - table.add_row(['serviceResourceBackendIpAddress', - result['serviceResourceBackendIpAddress']]) - table.add_row(['price', result['billingItem']['recurringFee']]) - table.add_row(['BillingItemId', result['billingItem']['id']]) - if result.get('notes'): - table.add_row(['notes', result['notes']]) - - if password: - pass_table = formatting.Table(['username', 'password']) - pass_table.add_row([result['username'], result['password']]) - table.add_row(['users', pass_table]) - - env.fout(table) diff --git a/SoftLayer/CLI/iscsi/list.py b/SoftLayer/CLI/iscsi/list.py deleted file mode 100644 index e36a04bfb..000000000 --- a/SoftLayer/CLI/iscsi/list.py +++ /dev/null @@ -1,43 +0,0 @@ -"""List iSCSI targets.""" -# :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 - - -@click.command() -@environment.pass_env -def cli(env): - """List iSCSI targets.""" - - iscsi_mgr = SoftLayer.ISCSIManager(env.client) - iscsi_list = iscsi_mgr.list_iscsi() - iscsi_list = [utils.NestedDict(n) for n in iscsi_list] - table = formatting.Table([ - 'id', - 'datacenter', - 'size', - 'username', - 'password', - 'server' - ]) - for iscsi in iscsi_list: - table.add_row([ - iscsi['id'], - utils.lookup(iscsi, - 'serviceResource', - 'datacenter', - 'name') or formatting.blank(), - formatting.FormattedItem(iscsi.get('capacityGb', - formatting.blank()), - "%dGB" % iscsi.get('capacityGb', 0)), - iscsi.get('username', formatting.blank()), - iscsi.get('password', formatting.blank()), - iscsi.get('serviceResourceBackendIpAddress', - formatting.blank())]) - - env.fout(table) diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py index e66f8df83..7dcfa6b27 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -118,12 +118,6 @@ ('image:import', 'SoftLayer.CLI.image.import:cli'), ('image:export', 'SoftLayer.CLI.image.export:cli'), - ('iscsi', 'SoftLayer.CLI.iscsi'), - ('iscsi:cancel', 'SoftLayer.CLI.iscsi.cancel:cli'), - ('iscsi:create', 'SoftLayer.CLI.iscsi.create:cli'), - ('iscsi:detail', 'SoftLayer.CLI.iscsi.detail:cli'), - ('iscsi:list', 'SoftLayer.CLI.iscsi.list:cli'), - ('loadbal', 'SoftLayer.CLI.loadbal'), ('loadbal:cancel', 'SoftLayer.CLI.loadbal.cancel:cli'), ('loadbal:create', 'SoftLayer.CLI.loadbal.create:cli'), @@ -193,13 +187,6 @@ ('hardware:credentials', 'SoftLayer.CLI.hardware.credentials:cli'), ('hardware:update-firmware', 'SoftLayer.CLI.hardware.update_firmware:cli'), - ('snapshot', 'SoftLayer.CLI.snapshot'), - ('snapshot:cancel', 'SoftLayer.CLI.snapshot.cancel:cli'), - ('snapshot:create', 'SoftLayer.CLI.snapshot.create:cli'), - ('snapshot:create-space', 'SoftLayer.CLI.snapshot.create_space:cli'), - ('snapshot:list', 'SoftLayer.CLI.snapshot.list:cli'), - ('snapshot:restore-volume', 'SoftLayer.CLI.snapshot.restore_volume:cli'), - ('sshkey', 'SoftLayer.CLI.sshkey'), ('sshkey:add', 'SoftLayer.CLI.sshkey.add:cli'), ('sshkey:remove', 'SoftLayer.CLI.sshkey.remove:cli'), diff --git a/SoftLayer/CLI/snapshot/__init__.py b/SoftLayer/CLI/snapshot/__init__.py deleted file mode 100644 index 59e9a51fa..000000000 --- a/SoftLayer/CLI/snapshot/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Snapshots.""" diff --git a/SoftLayer/CLI/snapshot/cancel.py b/SoftLayer/CLI/snapshot/cancel.py deleted file mode 100644 index a684f87ff..000000000 --- a/SoftLayer/CLI/snapshot/cancel.py +++ /dev/null @@ -1,21 +0,0 @@ -"""Cancel/Delete iSCSI snapshot.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import helpers - - -@click.command() -@click.argument('identifier') -@environment.pass_env -def cli(env, identifier): - """Cancel/Delete iSCSI snapshot.""" - - iscsi_mgr = SoftLayer.ISCSIManager(env.client) - snapshot_id = helpers.resolve_id(iscsi_mgr.resolve_ids, - identifier, - 'Snapshot') - iscsi_mgr.delete_snapshot(snapshot_id) diff --git a/SoftLayer/CLI/snapshot/create.py b/SoftLayer/CLI/snapshot/create.py deleted file mode 100644 index 531b4d2eb..000000000 --- a/SoftLayer/CLI/snapshot/create.py +++ /dev/null @@ -1,20 +0,0 @@ -"""Create a snapshot of an iSCSI volume.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import helpers - - -@click.command() -@click.argument('identifier') -@click.option('--notes', help="An optional note for the snapshot") -@environment.pass_env -def cli(env, identifier, notes): - """Create a snapshot of an iSCSI volume.""" - - iscsi_mgr = SoftLayer.ISCSIManager(env.client) - iscsi_id = helpers.resolve_id(iscsi_mgr.resolve_ids, identifier, 'iSCSI') - iscsi_mgr.create_snapshot(iscsi_id, notes) diff --git a/SoftLayer/CLI/snapshot/create_space.py b/SoftLayer/CLI/snapshot/create_space.py deleted file mode 100644 index 2636e7d8e..000000000 --- a/SoftLayer/CLI/snapshot/create_space.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Orders snapshot space for given iSCSI.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import helpers - - -@click.command() -@click.argument('identifier') -@click.option('--capacity', - type=click.INT, - help="Size of snapshot space to create") -@environment.pass_env -def cli(env, identifier, capacity): - """Orders snapshot space for given iSCSI.""" - - iscsi_mgr = SoftLayer.ISCSIManager(env.client) - iscsi_id = helpers.resolve_id(iscsi_mgr.resolve_ids, identifier, 'iSCSI') - iscsi_mgr.create_snapshot_space(iscsi_id, capacity) diff --git a/SoftLayer/CLI/snapshot/list.py b/SoftLayer/CLI/snapshot/list.py deleted file mode 100644 index 8de8c082c..000000000 --- a/SoftLayer/CLI/snapshot/list.py +++ /dev/null @@ -1,37 +0,0 @@ -"""List iSCSI Snapshots.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import formatting -from SoftLayer.CLI import helpers -from SoftLayer import utils - - -@click.command() -@click.argument('iscsi-identifier') -@environment.pass_env -def cli(env, iscsi_identifier): - """List iSCSI Snapshots.""" - - iscsi_mgr = SoftLayer.ISCSIManager(env.client) - iscsi_id = helpers.resolve_id(iscsi_mgr.resolve_ids, - iscsi_identifier, - 'iSCSI') - iscsi = env.client['Network_Storage_Iscsi'] - snapshots = iscsi.getPartnerships( - mask='volumeId,partnerVolumeId,createDate,type', id=iscsi_id) - snapshots = [utils.NestedDict(n) for n in snapshots] - - table = formatting.Table(['id', 'createDate', 'name', 'description']) - - for snapshot in snapshots: - table.add_row([ - snapshot['partnerVolumeId'], - snapshot['createDate'], - snapshot['type']['name'], - snapshot['type']['description'], - ]) - env.fout(table) diff --git a/SoftLayer/CLI/snapshot/restore_volume.py b/SoftLayer/CLI/snapshot/restore_volume.py deleted file mode 100644 index 7fa4168ad..000000000 --- a/SoftLayer/CLI/snapshot/restore_volume.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Restores volume from existing snapshot.""" -# :license: MIT, see LICENSE for more details. - -import click - -import SoftLayer -from SoftLayer.CLI import environment -from SoftLayer.CLI import helpers - - -@click.command() -@click.argument('snapshot-id') -@click.argument('volume-id') -@environment.pass_env -def cli(env, snapshot_id, volume_id): - """Restores volume from existing snapshot.""" - iscsi_mgr = SoftLayer.ISCSIManager(env.client) - volume_id = helpers.resolve_id(iscsi_mgr.resolve_ids, volume_id, 'iSCSI') - snapshot_id = helpers.resolve_id(iscsi_mgr.resolve_ids, - snapshot_id, - 'Snapshot') - iscsi_mgr.restore_from_snapshot(volume_id, snapshot_id) diff --git a/SoftLayer/managers/__init__.py b/SoftLayer/managers/__init__.py index b9a44a0d7..4b63b7726 100644 --- a/SoftLayer/managers/__init__.py +++ b/SoftLayer/managers/__init__.py @@ -14,7 +14,6 @@ from SoftLayer.managers.firewall import FirewallManager from SoftLayer.managers.hardware import HardwareManager from SoftLayer.managers.image import ImageManager -from SoftLayer.managers.iscsi import ISCSIManager from SoftLayer.managers.load_balancer import LoadBalancerManager from SoftLayer.managers.messaging import MessagingManager from SoftLayer.managers.metadata import MetadataManager @@ -34,7 +33,6 @@ 'FirewallManager', 'HardwareManager', 'ImageManager', - 'ISCSIManager', 'LoadBalancerManager', 'MessagingManager', 'MetadataManager', diff --git a/SoftLayer/managers/iscsi.py b/SoftLayer/managers/iscsi.py deleted file mode 100644 index 85df7d401..000000000 --- a/SoftLayer/managers/iscsi.py +++ /dev/null @@ -1,174 +0,0 @@ -""" - SoftLayer.iscsi - ~~~~~~~~~~~~~~~ - ISCSI Manager/helpers - - :license: MIT, see LICENSE for more details. -""" -from SoftLayer import exceptions -from SoftLayer import utils - - -class ISCSIManager(utils.IdentifierMixin, object): - """Manages SoftLayer iSCSI storage accounts. - - See product information here: - https://knowledgelayer.softlayer.com/topic/iscsi - - :param SoftLayer.API.BaseClient client: the client instance - - """ - - def __init__(self, client): - self.configuration = {} - self.client = client - self.iscsi_svc = self.client['Network_Storage_Iscsi'] - self.product_order = self.client['Product_Order'] - - def _find_item_prices(self, size, categorycode=''): - """Retrieves the Item Price IDs.""" - item_prices = self.client['Product_Package'].getItems( - id=0, - mask='id,capacity,prices[id]', - filter={ - 'items': { - 'capacity': {'operation': int(size)}, - 'categories': { - 'categoryCode': {'operation': categorycode} - }}}) - - for item_price in item_prices: - for price in item_price['prices']: - return price['id'] - - raise exceptions.SoftLayerError( - "Could not find a valid price with for the given size") - - def _build_order(self, item_price, location): - """Returns a dict appropriate for Product_Order::placeOrder().""" - - location_id = self._get_location_id(location) - order = { - 'complexType': - 'SoftLayer_Container_Product_Order_Network_Storage_Iscsi', - 'location': location_id, - 'packageId': 0, # storage package - 'prices': [{'id': item_price}], - 'quantity': 1 - } - return order - - def _get_location_id(self, location): - """Returns location id of datacenter for ProductOrder::placeOrder().""" - loc_svc = self.client['Location_Datacenter'] - datacenters = loc_svc.getDatacenters(mask='mask[longName,id,name]') - for datacenter in datacenters: - if datacenter['name'] == location: - location = datacenter['id'] - return location - raise ValueError('Invalid datacenter name specified.') - - def create_iscsi(self, size=None, location=None): - """Places an order for iSCSI volume. - - :param integer size: size of iSCSI volume to create - :param string location: datacenter to use to create volume in - """ - item_price = self._find_item_prices(int(size), - categorycode='iscsi') - iscsi_order = self._build_order(item_price, location) - return self.product_order.placeOrder(iscsi_order) - - def list_iscsi(self): - """List iSCSI volume.""" - account = self.client['Account'] - iscsi_list = account.getIscsiNetworkStorage( - mask='eventCount,serviceResource[datacenter.name]') - return iscsi_list - - def get_iscsi(self, volume_id, **kwargs): - """Get details about a iSCSI storage. - - :param integer volume_id: the volume ID - :returns: A dictionary containing a large amount of information about - the specified storage. - """ - - if 'mask' not in kwargs: - items = [ - 'id', - 'serviceResourceName', - 'createDate', - 'nasType', - 'capacityGb', - 'snapshotCapacityGb', - 'mountableFlag', - 'serviceResourceBackendIpAddress', - 'billingItem', - 'notes', - 'username', - 'password' - ] - kwargs['mask'] = "mask[%s]" % ','.join(items) - return self.iscsi_svc.getObject(id=volume_id, **kwargs) - - def cancel_iscsi(self, volume_id, reason='unNeeded', immediate=False): - """Cancels the given iSCSI volume. - - :param integer volume_id: the volume ID - - """ - iscsi = self.get_iscsi( - volume_id, - mask='mask[id,capacityGb,username,password,billingItem[id]]') - billingitemid = iscsi['billingItem']['id'] - self.client['Billing_Item'].cancelItem( - immediate, - True, - reason, - id=billingitemid) - - def create_snapshot(self, volume_id, notes='No longer needed'): - """Orders a snapshot for given volume. - - :param integer volume_id: the volume ID - """ - - self.iscsi_svc.createSnapshot(notes, id=volume_id) - - def create_snapshot_space(self, volume_id, capacity): - """Orders a snapshot space for given volume. - - :param integer volume_id: the volume ID - :param integer capacity: capacity in ~GB - """ - item_price = self._find_item_prices( - int(capacity), categorycode='iscsi_snapshot_space') - result = self.get_iscsi( - volume_id, mask='mask[id,capacityGb,serviceResource[datacenter]]') - snapshotspaceorder = { - 'complexType': - 'SoftLayer_Container_Product_Order_\ -Network_Storage_Iscsi_SnapshotSpace', - 'location': result['serviceResource']['datacenter']['id'], - 'packageId': 0, - 'prices': [{'id': item_price}], - 'quantity': 1, - 'volumeId': volume_id} - self.product_order.placeOrder(snapshotspaceorder) - - def delete_snapshot(self, snapshot_id): - """Deletes the given snapshot. - - :params: integer snapshot_id: the snapshot ID - """ - - self.iscsi_svc.deleteObject(id=snapshot_id) - - def restore_from_snapshot(self, volume_id, snapshot_id): - """Restore the volume to snapshot's contents. - - :params: imteger volume_id: the volume ID - :params: integer snapshot_id: the snapshot ID - """ - self.iscsi_svc.restoreFromSnapshot(snapshot_id, id=volume_id) diff --git a/tests/managers/iscsi_tests.py b/tests/managers/iscsi_tests.py deleted file mode 100644 index 7ba43834b..000000000 --- a/tests/managers/iscsi_tests.py +++ /dev/null @@ -1,122 +0,0 @@ -""" - SoftLayer.tests.managers.iscsi_tests - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - :license: MIT, see LICENSE for more details. -""" - -import SoftLayer -from SoftLayer import fixtures -from SoftLayer import testing - - -class ISCSITests(testing.TestCase): - def set_up(self): - self.iscsi = SoftLayer.ISCSIManager(self.client) - - def test_get_iscsi(self): - result = self.iscsi.get_iscsi(100) - - self.assertEqual(fixtures.SoftLayer_Network_Storage_Iscsi.getObject, - result) - self.assert_called_with('SoftLayer_Network_Storage_Iscsi', 'getObject', - identifier=100) - - def test_cancel_iscsi_immediately(self): - self.iscsi.cancel_iscsi(600, immediate=True) - - self.assert_called_with('SoftLayer_Billing_Item', 'cancelItem', - args=(True, True, 'unNeeded'), - identifier=600) - - def test_cancel_iscsi_without_reason(self): - self.iscsi.cancel_iscsi(600) - - self.assert_called_with('SoftLayer_Billing_Item', 'cancelItem', - args=(False, True, 'unNeeded'), - identifier=600) - - def test_cancel_iscsi_with_reason(self): - self.iscsi.cancel_iscsi(600, 'Network Performance') - - self.assert_called_with('SoftLayer_Billing_Item', 'cancelItem', - args=(False, True, 'Network Performance'), - identifier=600) - - def test_invalid_datacenter(self): - self.assertRaises(ValueError, - self.iscsi.create_iscsi, - size=10, location='foo') - - def test_create_iscsi(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getItems') - mock.return_value = [ - { - 'id': 4439, - 'capacity': '1', - 'description': '1 GB iSCSI Storage', - 'itemCategory': {'categoryCode': 'iscsi'}, - 'prices': [{'id': 2222}] - } - ] - - self.iscsi.create_iscsi(size=1, location='dal05') - - args = ({'prices': [{'id': 2222}], - 'quantity': 1, - 'location': 0, - 'packageId': 0, - 'complexType': - 'SoftLayer_Container_Product_Order_Network_Storage_Iscsi'},) - self.assert_called_with('SoftLayer_Product_Order', 'placeOrder', - args=args) - - def test_delete_snapshot(self): - self.iscsi.delete_snapshot(1) - - self.assert_called_with('SoftLayer_Network_Storage_Iscsi', - 'deleteObject', - identifier=1) - - def test_create_snapshot(self): - self.iscsi.create_snapshot(100, 'unNeeded') - - self.assert_called_with('SoftLayer_Network_Storage_Iscsi', - 'createSnapshot', - identifier=100) - - def test_create_snapshot_space(self): - mock = self.set_mock('SoftLayer_Product_Package', 'getItems') - mock.return_value = [ - { - 'id': 1121, - 'capacity': '20', - 'description': '20 GB iSCSI snapshot', - 'itemCategory': {'categoryCode': 'iscsi_snapshot_space'}, - 'prices': [{'id': 2014}] - }] - - self.iscsi.create_snapshot_space(100, 20) - - args = ( - { - 'volumeId': 100, - 'location': 138124, - 'packageId': 0, - 'complexType': - 'SoftLayer_Container_' - 'Product_Order_Network_Storage_Iscsi_SnapshotSpace', - 'prices': [{'id': 2014}], - 'quantity': 1, - }, - ) - self.assert_called_with('SoftLayer_Product_Order', 'placeOrder', - args=args) - - def test_restore_from_snapshot(self): - self.iscsi.restore_from_snapshot(100, 101) - - self.assert_called_with('SoftLayer_Network_Storage_Iscsi', - 'restoreFromSnapshot', - args=(101,), - identifier=100)