Add support for multiple cinder endpoints

Before v1 and v2 were set to the same service_type, so you could only
have one set at a time. This assumes the catalog is setup for v1
service_type 'volume' and v2 service_type 'volumev2'.

For backwards compatibility, we will allow v2 to be setup with
service_type 'volume' for existing installations.

Change-Id: Ife6d2cdb12d894b84ea3b276767fb93d487355d5
This commit is contained in:
Mike Perez
2013-08-07 10:01:26 -07:00
parent 8a107396c2
commit 34c7c8c2e2
7 changed files with 254 additions and 110 deletions

View File

@@ -52,15 +52,22 @@ class ServiceCatalog(object):
catalog = self.catalog['access']['serviceCatalog']
for service in catalog:
if service.get("type") != service_type:
# NOTE(thingee): For backwards compatibility, if they have v2
# enabled and the service_type is set to 'volume', go ahead and
# accept that.
skip_service_type_check = False
if service_type == 'volumev2' and service['type'] == 'volume':
version = service['endpoints'][0]['publicURL'].split('/')[3]
if version == 'v2':
skip_service_type_check = True
if (not skip_service_type_check
and service.get("type") != service_type):
continue
if (service_name and service_type == 'compute' and
service.get('name') != service_name):
continue
if (volume_service_name and service_type == 'volume' and
service.get('name') != volume_service_name):
if (volume_service_name and service_type in ('volume', 'volumev2')
and service.get('name') != volume_service_name):
continue
endpoints = service['endpoints']

View File

@@ -41,7 +41,7 @@ from cinderclient.v2 import shell as shell_v2
DEFAULT_OS_VOLUME_API_VERSION = "1"
DEFAULT_CINDER_ENDPOINT_TYPE = 'publicURL'
DEFAULT_CINDER_SERVICE_TYPE = 'compute'
DEFAULT_CINDER_SERVICE_TYPE = 'volume'
logger = logging.getLogger(__name__)
@@ -145,7 +145,7 @@ class OpenStackCinderShell(object):
parser.add_argument('--service-type',
metavar='<service-type>',
help='Defaults to compute for most actions')
help='Defaults to volume for most actions')
parser.add_argument('--service_type',
help=argparse.SUPPRESS)
@@ -173,7 +173,7 @@ class OpenStackCinderShell(object):
help=argparse.SUPPRESS)
parser.add_argument('--os-volume-api-version',
metavar='<compute-api-ver>',
metavar='<volume-api-ver>',
default=utils.env('OS_VOLUME_API_VERSION',
default=DEFAULT_OS_VOLUME_API_VERSION),
help='Accepts 1 or 2,defaults '

View File

@@ -72,7 +72,7 @@ SERVICE_CATALOG = {
"endpoints_links": [],
},
{
"name": "Nova Volumes",
"name": "Cinder Volume Service",
"type": "volume",
"endpoints": [
{
@@ -101,6 +101,128 @@ SERVICE_CATALOG = {
},
],
},
{
"name": "Cinder Volume Service V2",
"type": "volumev2",
"endpoints": [
{
"tenantId": "1",
"publicURL": "https://volume1.host/v2/1234",
"internalURL": "https://volume1.host/v2/1234",
"region": "South",
"versionId": "2.0",
"versionInfo": "uri",
"versionList": "uri"
},
{
"tenantId": "2",
"publicURL": "https://volume1.host/v2/3456",
"internalURL": "https://volume1.host/v2/3456",
"region": "South",
"versionId": "1.1",
"versionInfo": "https://volume1.host/v2/",
"versionList": "https://volume1.host/"
},
],
"endpoints_links": [
{
"rel": "next",
"href": "https://identity1.host/v2.0/endpoints"
},
],
},
],
"serviceCatalog_links": [
{
"rel": "next",
"href": "https://identity.host/v2.0/endpoints?session=2hfh8Ar",
},
],
},
}
SERVICE_COMPATIBILITY_CATALOG = {
"access": {
"token": {
"id": "ab48a9efdfedb23ty3494",
"expires": "2010-11-01T03:32:15-05:00",
"tenant": {
"id": "345",
"name": "My Project"
}
},
"user": {
"id": "123",
"name": "jqsmith",
"roles": [
{
"id": "234",
"name": "compute:admin",
},
{
"id": "235",
"name": "object-store:admin",
"tenantId": "1",
}
],
"roles_links": [],
},
"serviceCatalog": [
{
"name": "Cloud Servers",
"type": "compute",
"endpoints": [
{
"tenantId": "1",
"publicURL": "https://compute1.host/v1/1234",
"internalURL": "https://compute1.host/v1/1234",
"region": "North",
"versionId": "1.0",
"versionInfo": "https://compute1.host/v1/",
"versionList": "https://compute1.host/"
},
{
"tenantId": "2",
"publicURL": "https://compute1.host/v1/3456",
"internalURL": "https://compute1.host/v1/3456",
"region": "North",
"versionId": "1.1",
"versionInfo": "https://compute1.host/v1/",
"versionList": "https://compute1.host/"
},
],
"endpoints_links": [],
},
{
"name": "Cinder Volume Service V2",
"type": "volume",
"endpoints": [
{
"tenantId": "1",
"publicURL": "https://volume1.host/v2/1234",
"internalURL": "https://volume1.host/v2/1234",
"region": "South",
"versionId": "2.0",
"versionInfo": "uri",
"versionList": "uri"
},
{
"tenantId": "2",
"publicURL": "https://volume1.host/v2/3456",
"internalURL": "https://volume1.host/v2/3456",
"region": "South",
"versionId": "1.1",
"versionInfo": "https://volume1.host/v2/",
"versionList": "https://volume1.host/"
},
],
"endpoints_links": [
{
"rel": "next",
"href": "https://identity1.host/v2.0/endpoints"
},
],
},
],
"serviceCatalog_links": [
{
@@ -136,5 +258,18 @@ class ServiceCatalogTest(utils.TestCase):
self.assertEquals(sc.url_for('tenantId', '2', service_type='volume'),
"https://volume1.host/v1/3456")
self.assertEquals(sc.url_for('tenantId', '2', service_type='volumev2'),
"https://volume1.host/v2/3456")
self.assertEquals(sc.url_for('tenantId', '2', service_type='volumev2'),
"https://volume1.host/v2/3456")
self.assertRaises(exceptions.EndpointNotFound, sc.url_for,
"region", "North", service_type='volume')
def test_compatibility_service_type(self):
sc = service_catalog.ServiceCatalog(SERVICE_COMPATIBILITY_CATALOG)
self.assertEquals(sc.url_for('tenantId', '1', service_type='volume'),
"https://volume1.host/v2/1234")
self.assertEquals(sc.url_for('tenantId', '2', service_type='volume'),
"https://volume1.host/v2/3456")

View File

@@ -24,7 +24,7 @@ from cinderclient.tests import utils
class AuthenticateAgainstKeystoneTests(utils.TestCase):
def test_authenticate_success(self):
cs = client.Client("username", "password", "project_id",
"auth_url/v2.0", service_type='compute')
"http://localhost:8776/v1", service_type='volume')
resp = {
"access": {
"token": {
@@ -33,13 +33,13 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
},
"serviceCatalog": [
{
"type": "compute",
"type": "volume",
"endpoints": [
{
"region": "RegionOne",
"adminURL": "http://localhost:8774/v1",
"internalURL": "http://localhost:8774/v1",
"publicURL": "http://localhost:8774/v1/",
"adminURL": "http://localhost:8776/v1",
"internalURL": "http://localhost:8776/v1",
"publicURL": "http://localhost:8776/v1",
},
],
},
@@ -89,8 +89,9 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
test_auth_call()
def test_authenticate_tenant_id(self):
cs = client.Client("username", "password", auth_url="auth_url/v2.0",
tenant_id='tenant_id', service_type='compute')
cs = client.Client("username", "password",
auth_url="http://localhost:8776/v1",
tenant_id='tenant_id', service_type='volume')
resp = {
"access": {
"token": {
@@ -105,13 +106,13 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
},
"serviceCatalog": [
{
"type": "compute",
"type": "volume",
"endpoints": [
{
"region": "RegionOne",
"adminURL": "http://localhost:8774/v1",
"internalURL": "http://localhost:8774/v1",
"publicURL": "http://localhost:8774/v1/",
"adminURL": "http://localhost:8776/v1",
"internalURL": "http://localhost:8776/v1",
"publicURL": "http://localhost:8776/v1",
},
],
},
@@ -164,7 +165,7 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
def test_authenticate_failure(self):
cs = client.Client("username", "password", "project_id",
"auth_url/v2.0")
"http://localhost:8776/v1")
resp = {"unauthorized": {"message": "Unauthorized", "code": "401"}}
auth_response = utils.TestResponse({
"status_code": 401,
@@ -181,7 +182,7 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
def test_auth_redirect(self):
cs = client.Client("username", "password", "project_id",
"auth_url/v1", service_type='compute')
"http://localhost:8776/v1", service_type='volume')
dict_correct_response = {
"access": {
"token": {
@@ -190,13 +191,13 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
},
"serviceCatalog": [
{
"type": "compute",
"type": "volume",
"endpoints": [
{
"adminURL": "http://localhost:8774/v1",
"adminURL": "http://localhost:8776/v1",
"region": "RegionOne",
"internalURL": "http://localhost:8774/v1",
"publicURL": "http://localhost:8774/v1/",
"internalURL": "http://localhost:8776/v1",
"publicURL": "http://localhost:8776/v1/",
},
],
},
@@ -265,7 +266,7 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
def test_ambiguous_endpoints(self):
cs = client.Client("username", "password", "project_id",
"auth_url/v2.0", service_type='compute')
"http://localhost:8776/v1", service_type='volume')
resp = {
"access": {
"token": {
@@ -274,25 +275,25 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
},
"serviceCatalog": [
{
"adminURL": "http://localhost:8774/v1",
"type": "compute",
"name": "Compute CLoud",
"adminURL": "http://localhost:8776/v1",
"type": "volume",
"name": "Cinder Volume Service",
"endpoints": [
{
"region": "RegionOne",
"internalURL": "http://localhost:8774/v1",
"publicURL": "http://localhost:8774/v1/",
"internalURL": "http://localhost:8776/v1",
"publicURL": "http://localhost:8776/v1",
},
],
},
{
"adminURL": "http://localhost:8774/v1",
"type": "compute",
"name": "Hyper-compute Cloud",
"adminURL": "http://localhost:8776/v1",
"type": "volume",
"name": "Cinder Volume Cloud Service",
"endpoints": [
{
"internalURL": "http://localhost:8774/v1",
"publicURL": "http://localhost:8774/v1/",
"internalURL": "http://localhost:8776/v1",
"publicURL": "http://localhost:8776/v1",
},
],
},

View File

@@ -27,7 +27,7 @@ from cinderclient.tests import utils
class AuthenticateAgainstKeystoneTests(utils.TestCase):
def test_authenticate_success(self):
cs = client.Client("username", "password", "project_id",
"auth_url/v2.0", service_type='compute')
"http://localhost:8776/v2", service_type='volumev2')
resp = {
"access": {
"token": {
@@ -36,13 +36,13 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
},
"serviceCatalog": [
{
"type": "compute",
"type": "volumev2",
"endpoints": [
{
"region": "RegionOne",
"adminURL": "http://localhost:8774/v2",
"internalURL": "http://localhost:8774/v2",
"publicURL": "http://localhost:8774/v2/",
"adminURL": "http://localhost:8776/v2",
"internalURL": "http://localhost:8776/v2",
"publicURL": "http://localhost:8776/v2",
},
],
},
@@ -92,8 +92,9 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
test_auth_call()
def test_authenticate_tenant_id(self):
cs = client.Client("username", "password", auth_url="auth_url/v2.0",
tenant_id='tenant_id', service_type='compute')
cs = client.Client("username", "password",
auth_url="http://localhost:8776/v2",
tenant_id='tenant_id', service_type='volumev2')
resp = {
"access": {
"token": {
@@ -108,13 +109,13 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
},
"serviceCatalog": [
{
"type": "compute",
"type": 'volumev2',
"endpoints": [
{
"region": "RegionOne",
"adminURL": "http://localhost:8774/v2",
"internalURL": "http://localhost:8774/v2",
"publicURL": "http://localhost:8774/v2/",
"adminURL": "http://localhost:8776/v2",
"internalURL": "http://localhost:8776/v2",
"publicURL": "http://localhost:8776/v2",
},
],
},
@@ -167,7 +168,7 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
def test_authenticate_failure(self):
cs = client.Client("username", "password", "project_id",
"auth_url/v2.0")
"http://localhost:8776/v2")
resp = {"unauthorized": {"message": "Unauthorized", "code": "401"}}
auth_response = utils.TestResponse({
"status_code": 401,
@@ -184,7 +185,7 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
def test_auth_redirect(self):
cs = client.Client("username", "password", "project_id",
"auth_url/v2", service_type='compute')
"http://localhost:8776/v2", service_type='volumev2')
dict_correct_response = {
"access": {
"token": {
@@ -193,13 +194,13 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
},
"serviceCatalog": [
{
"type": "compute",
"type": "volumev2",
"endpoints": [
{
"adminURL": "http://localhost:8774/v2",
"adminURL": "http://localhost:8776/v2",
"region": "RegionOne",
"internalURL": "http://localhost:8774/v2",
"publicURL": "http://localhost:8774/v2/",
"internalURL": "http://localhost:8776/v2",
"publicURL": "http://localhost:8776/v2/",
},
],
},
@@ -268,7 +269,7 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
def test_ambiguous_endpoints(self):
cs = client.Client("username", "password", "project_id",
"auth_url/v2.0", service_type='compute')
"http://localhost:8776/v2", service_type='volumev2')
resp = {
"access": {
"token": {
@@ -277,25 +278,25 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
},
"serviceCatalog": [
{
"adminURL": "http://localhost:8774/v2",
"type": "compute",
"name": "Compute CLoud",
"adminURL": "http://localhost:8776/v1",
"type": "volumev2",
"name": "Cinder Volume Service",
"endpoints": [
{
"region": "RegionOne",
"internalURL": "http://localhost:8774/v2",
"publicURL": "http://localhost:8774/v2/",
"internalURL": "http://localhost:8776/v1",
"publicURL": "http://localhost:8776/v1",
},
],
},
{
"adminURL": "http://localhost:8774/v2",
"type": "compute",
"name": "Hyper-compute Cloud",
"adminURL": "http://localhost:8776/v2",
"type": "volumev2",
"name": "Cinder Volume V2",
"endpoints": [
{
"internalURL": "http://localhost:8774/v2",
"publicURL": "http://localhost:8774/v2/",
"internalURL": "http://localhost:8776/v2",
"publicURL": "http://localhost:8776/v2",
},
],
},

View File

@@ -44,7 +44,7 @@ class Client(object):
insecure=False, timeout=None, tenant_id=None,
proxy_tenant_id=None, proxy_token=None, region_name=None,
endpoint_type='publicURL', extensions=None,
service_type='volume', service_name=None,
service_type='volumev2', service_name=None,
volume_service_name=None, retries=None,
http_log_debug=False,
cacert=None):

View File

@@ -146,7 +146,7 @@ def _extract_metadata(args):
metavar='<status>',
default=None,
help='Filter results by status')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_list(cs, args):
"""List all the volumes."""
# NOTE(thingee): Backwards-compatibility with v1 args
@@ -174,7 +174,7 @@ def do_list(cs, args):
@utils.arg('volume',
metavar='<volume>',
help='ID of the volume.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_show(cs, args):
"""Show details about a volume."""
info = dict()
@@ -247,7 +247,7 @@ def do_show(cs, args):
action='append',
default=[],
help='Scheduler hint like in nova')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_create(cs, args):
"""Add a new volume."""
# NOTE(thingee): Backwards-compatibility with v1 args
@@ -298,7 +298,7 @@ def do_create(cs, args):
@utils.arg('volume',
metavar='<volume>',
help='ID of the volume to delete.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_delete(cs, args):
"""Remove a volume."""
volume = _find_volume(cs, args.volume)
@@ -308,7 +308,7 @@ def do_delete(cs, args):
@utils.arg('volume',
metavar='<volume>',
help='ID of the volume to delete.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_force_delete(cs, args):
"""Attempt forced removal of a volume, regardless of its state."""
volume = _find_volume(cs, args.volume)
@@ -320,7 +320,7 @@ def do_force_delete(cs, args):
help=('Indicate which state to assign the volume. Options include '
'available, error, creating, deleting, error_deleting. If no '
'state is provided, available will be used.'))
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_reset_state(cs, args):
"""Explicitly update the state of a volume."""
volume = _find_volume(cs, args.volume)
@@ -341,7 +341,7 @@ def do_reset_state(cs, args):
help=argparse.SUPPRESS)
@utils.arg('--display_description',
help=argparse.SUPPRESS)
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_rename(cs, args):
"""Rename a volume."""
kwargs = {}
@@ -369,7 +369,7 @@ def do_rename(cs, args):
action='append',
default=[],
help='Metadata to set/unset (only key is necessary on unset)')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_metadata(cs, args):
"""Set or Delete metadata on a volume."""
volume = _find_volume(cs, args.volume)
@@ -412,7 +412,7 @@ def do_metadata(cs, args):
help='Filter results by volume-id')
@utils.arg('--volume_id',
help=argparse.SUPPRESS)
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_snapshot_list(cs, args):
"""List all the snapshots."""
all_tenants = int(os.environ.get("ALL_TENANTS", args.all_tenants))
@@ -436,7 +436,7 @@ def do_snapshot_list(cs, args):
@utils.arg('snapshot',
metavar='<snapshot>',
help='ID of the snapshot.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_snapshot_show(cs, args):
"""Show details about a snapshot."""
snapshot = _find_volume_snapshot(cs, args.snapshot)
@@ -468,7 +468,7 @@ def do_snapshot_show(cs, args):
help=argparse.SUPPRESS)
@utils.arg('--display_description',
help=argparse.SUPPRESS)
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_snapshot_create(cs, args):
"""Add a new snapshot."""
if args.display_name is not None:
@@ -487,7 +487,7 @@ def do_snapshot_create(cs, args):
@utils.arg('snapshot-id',
metavar='<snapshot-id>',
help='ID of the snapshot to delete.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_snapshot_delete(cs, args):
"""Remove a snapshot."""
snapshot = _find_volume_snapshot(cs, args.snapshot_id)
@@ -504,7 +504,7 @@ def do_snapshot_delete(cs, args):
help=argparse.SUPPRESS)
@utils.arg('--display_description',
help=argparse.SUPPRESS)
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_snapshot_rename(cs, args):
"""Rename a snapshot."""
kwargs = {}
@@ -528,7 +528,7 @@ def do_snapshot_rename(cs, args):
'Options include available, error, creating, '
'deleting, error_deleting. If no state is provided, '
'available will be used.'))
@utils.service_type('snapshot')
@utils.service_type('volumev2')
def do_snapshot_reset_state(cs, args):
"""Explicitly update the state of a snapshot."""
snapshot = _find_volume_snapshot(cs, args.snapshot)
@@ -544,14 +544,14 @@ def _print_type_and_extra_specs_list(vtypes):
utils.print_list(vtypes, ['ID', 'Name', 'extra_specs'], formatters)
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_type_list(cs, args):
"""Print a list of available 'volume types'."""
vtypes = cs.volume_types.list()
_print_volume_type_list(vtypes)
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_extra_specs_list(cs, args):
"""Print a list of current 'volume types and extra specs' (Admin Only)."""
vtypes = cs.volume_types.list()
@@ -561,7 +561,7 @@ def do_extra_specs_list(cs, args):
@utils.arg('name',
metavar='<name>',
help="Name of the new volume type")
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_type_create(cs, args):
"""Create a new volume type."""
vtype = cs.volume_types.create(args.name)
@@ -571,7 +571,7 @@ def do_type_create(cs, args):
@utils.arg('id',
metavar='<id>',
help="Unique ID of the volume type to delete")
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_type_delete(cs, args):
"""Delete a specific volume type."""
cs.volume_types.delete(args.id)
@@ -590,7 +590,7 @@ def do_type_delete(cs, args):
action='append',
default=[],
help='Extra_specs to set/unset (only key is necessary on unset)')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_type_key(cs, args):
"Set or unset extra_spec for a volume type."""
vtype = _find_volume_type(cs, args.vtype)
@@ -648,7 +648,7 @@ def _quota_update(manager, identifier, args):
@utils.arg('tenant',
metavar='<tenant_id>',
help='UUID of tenant to list the quotas for.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_quota_show(cs, args):
"""List the quotas for a tenant."""
@@ -658,7 +658,7 @@ def do_quota_show(cs, args):
@utils.arg('tenant',
metavar='<tenant_id>',
help='UUID of tenant to list the default quotas for.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_quota_defaults(cs, args):
"""List the default quotas for a tenant."""
@@ -684,7 +684,7 @@ def do_quota_defaults(cs, args):
metavar='<volume_type_name>',
default=None,
help='Volume type (Optional, Default=None)')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_quota_update(cs, args):
"""Update the quotas for a tenant."""
@@ -694,7 +694,7 @@ def do_quota_update(cs, args):
@utils.arg('class_name',
metavar='<class>',
help='Name of quota class to list the quotas for.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_quota_class_show(cs, args):
"""List the quotas for a quota class."""
@@ -720,14 +720,14 @@ def do_quota_class_show(cs, args):
metavar='<volume_type_name>',
default=None,
help='Volume type (Optional, Default=None)')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_quota_class_update(cs, args):
"""Update the quotas for a quota class."""
_quota_update(cs.quota_classes, args.class_name, args)
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_absolute_limits(cs, args):
"""Print a list of absolute limits for a user"""
limits = cs.limits.get().absolute
@@ -735,7 +735,7 @@ def do_absolute_limits(cs, args):
utils.print_list(limits, columns)
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_rate_limits(cs, args):
"""Print a list of rate limits for a user"""
limits = cs.limits.get().rate
@@ -783,7 +783,7 @@ def _find_volume_type(cs, vtype):
help='Name for created image')
@utils.arg('--image_name',
help=argparse.SUPPRESS)
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_upload_to_image(cs, args):
"""Upload volume to image service as image."""
volume = _find_volume(cs, args.volume_id)
@@ -809,7 +809,7 @@ def do_upload_to_image(cs, args):
metavar='<description>',
default=None,
help='Options backup description (Default=None)')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_backup_create(cs, args):
"""Creates a backup."""
if args.display_name is not None:
@@ -825,7 +825,7 @@ def do_backup_create(cs, args):
@utils.arg('backup', metavar='<backup>', help='ID of the backup.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_backup_show(cs, args):
"""Show details about a backup."""
backup = _find_backup(cs, args.backup)
@@ -836,7 +836,7 @@ def do_backup_show(cs, args):
utils.print_dict(info)
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_backup_list(cs, args):
"""List all the backups."""
backups = cs.backups.list()
@@ -847,7 +847,7 @@ def do_backup_list(cs, args):
@utils.arg('backup', metavar='<backup>',
help='ID of the backup to delete.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_backup_delete(cs, args):
"""Remove a backup."""
backup = _find_backup(cs, args.backup)
@@ -859,7 +859,7 @@ def do_backup_delete(cs, args):
@utils.arg('--volume-id', metavar='<volume-id>',
help='Optional ID of the volume to restore to.',
default=None)
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_backup_restore(cs, args):
"""Restore a backup."""
cs.restores.restore(args.backup,
@@ -874,7 +874,7 @@ def do_backup_restore(cs, args):
help='Optional transfer name. (Default=None)')
@utils.arg('--display-name',
help=argparse.SUPPRESS)
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_transfer_create(cs, args):
"""Creates a volume transfer."""
if args.display_name is not None:
@@ -891,7 +891,7 @@ def do_transfer_create(cs, args):
@utils.arg('transfer', metavar='<transfer>',
help='ID of the transfer to delete.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_transfer_delete(cs, args):
"""Undo a transfer."""
transfer = _find_transfer(cs, args.transfer)
@@ -902,7 +902,7 @@ def do_transfer_delete(cs, args):
help='ID of the transfer to accept.')
@utils.arg('auth_key', metavar='<auth_key>',
help='Auth key of the transfer to accept.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_transfer_accept(cs, args):
"""Accepts a volume transfer."""
transfer = cs.transfers.accept(args.transfer, args.auth_key)
@@ -913,7 +913,7 @@ def do_transfer_accept(cs, args):
utils.print_dict(info)
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_transfer_list(cs, args):
"""List all the transfers."""
transfers = cs.transfers.list()
@@ -923,7 +923,7 @@ def do_transfer_list(cs, args):
@utils.arg('transfer', metavar='<transfer>',
help='ID of the transfer to accept.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_transfer_show(cs, args):
"""Show details about a transfer."""
transfer = _find_transfer(cs, args.transfer)
@@ -939,7 +939,7 @@ def do_transfer_show(cs, args):
metavar='<new_size>',
type=int,
help='New size of volume in GB')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_extend(cs, args):
"""Attempt to extend the size of an existing volume."""
volume = _find_volume(cs, args.volume)
@@ -950,7 +950,7 @@ def do_extend(cs, args):
help='Name of host.')
@utils.arg('--binary', metavar='<binary>', default=None,
help='Service binary.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_service_list(cs, args):
"""List all the services. Filter by host & service binary."""
result = cs.services.list(host=args.host, binary=args.binary)
@@ -960,7 +960,7 @@ def do_service_list(cs, args):
@utils.arg('host', metavar='<hostname>', help='Name of host.')
@utils.arg('binary', metavar='<binary>', help='Service binary.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_service_enable(cs, args):
"""Enable the service."""
cs.services.enable(args.host, args.binary)
@@ -968,7 +968,7 @@ def do_service_enable(cs, args):
@utils.arg('host', metavar='<hostname>', help='Name of host.')
@utils.arg('binary', metavar='<binary>', help='Service binary.')
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_service_disable(cs, args):
"""Disable the service."""
cs.services.disable(args.host, args.binary)
@@ -1016,7 +1016,7 @@ def _treeizeAvailabilityZone(zone):
return result
@utils.service_type('volume')
@utils.service_type('volumev2')
def do_availability_zone_list(cs, _args):
"""List all the availability zones."""
try: