2012-10-23 22:25:18 -07:00
|
|
|
# Copyright 2012 United States Government as represented by the
|
|
|
|
# Administrator of the National Aeronautics and Space Administration.
|
|
|
|
# All Rights Reserved.
|
|
|
|
#
|
2013-09-20 02:49:55 +08:00
|
|
|
# Copyright 2012 OpenStack Foundation
|
2012-10-23 22:25:18 -07:00
|
|
|
# Copyright 2012 Nebula, Inc.
|
|
|
|
# Copyright (c) 2012 X.commerce, a business unit of eBay Inc.
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
|
|
# not use this file except in compliance with the License. You may obtain
|
|
|
|
# a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
# License for the specific language governing permissions and limitations
|
|
|
|
# under the License.
|
|
|
|
|
|
|
|
from __future__ import absolute_import
|
|
|
|
|
|
|
|
import logging
|
|
|
|
|
2014-01-03 17:31:49 +01:00
|
|
|
from django.conf import settings
|
2014-09-09 14:58:28 +09:00
|
|
|
from django.utils.translation import pgettext_lazy
|
2014-01-03 17:31:49 +01:00
|
|
|
from django.utils.translation import ugettext_lazy as _
|
2012-10-23 22:25:18 -07:00
|
|
|
|
2017-03-16 18:27:03 +01:00
|
|
|
from cinderclient import api_versions
|
|
|
|
from cinderclient import client as cinder_client
|
2015-08-17 19:12:23 +05:30
|
|
|
from cinderclient import exceptions as cinder_exception
|
2014-10-22 15:11:09 -07:00
|
|
|
from cinderclient.v2.contrib import list_extensions as cinder_list_extensions
|
2012-10-23 22:25:18 -07:00
|
|
|
|
2013-06-10 14:29:44 +02:00
|
|
|
from horizon import exceptions
|
2017-03-17 19:15:23 +00:00
|
|
|
from horizon.utils.memoized import memoized
|
2013-06-10 14:29:44 +02:00
|
|
|
|
2019-02-09 20:20:44 +09:00
|
|
|
from openstack_dashboard.api import _nova
|
2013-08-02 13:23:46 +04:00
|
|
|
from openstack_dashboard.api import base
|
2017-03-16 18:27:03 +01:00
|
|
|
from openstack_dashboard.api import microversions
|
2016-07-08 19:04:42 +03:00
|
|
|
from openstack_dashboard.contrib.developer.profiler import api as profiler
|
2019-04-16 13:46:31 +09:00
|
|
|
from openstack_dashboard.utils import settings as utils
|
|
|
|
|
2012-10-23 22:25:18 -07:00
|
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
# API static values
|
|
|
|
VOLUME_STATE_AVAILABLE = "available"
|
2013-05-24 00:01:30 +08:00
|
|
|
DEFAULT_QUOTA_NAME = 'default'
|
2012-10-23 22:25:18 -07:00
|
|
|
|
2014-08-11 11:05:24 -07:00
|
|
|
# Available consumer choices associated with QOS Specs
|
|
|
|
CONSUMER_CHOICES = (
|
|
|
|
('back-end', _('back-end')),
|
|
|
|
('front-end', _('front-end')),
|
2014-09-09 14:58:28 +09:00
|
|
|
('both', pgettext_lazy('Both of front-end and back-end', u'both')),
|
2014-08-11 11:05:24 -07:00
|
|
|
)
|
2012-10-23 22:25:18 -07:00
|
|
|
|
2017-12-13 21:21:48 +02:00
|
|
|
VERSIONS = base.APIVersionManager("volume", preferred_version='3')
|
2014-01-29 15:07:15 +00:00
|
|
|
|
|
|
|
try:
|
2018-12-02 06:21:02 +09:00
|
|
|
# pylint: disable=ungrouped-imports
|
2014-01-29 15:07:15 +00:00
|
|
|
from cinderclient.v2 import client as cinder_client_v2
|
2017-03-16 18:27:03 +01:00
|
|
|
VERSIONS.load_supported_version('2', {"client": cinder_client_v2,
|
|
|
|
"version": '2'})
|
2017-12-13 21:21:48 +02:00
|
|
|
from cinderclient.v3 import client as cinder_client_v3
|
|
|
|
VERSIONS.load_supported_version('3', {"client": cinder_client_v3,
|
|
|
|
"version": '3'})
|
2014-01-29 15:07:15 +00:00
|
|
|
except ImportError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class BaseCinderAPIResourceWrapper(base.APIResourceWrapper):
|
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
# If a volume doesn't have a name, use its id.
|
|
|
|
return (getattr(self._apiresource, 'name', None) or
|
|
|
|
getattr(self._apiresource, 'id', None))
|
|
|
|
|
|
|
|
@property
|
|
|
|
def description(self):
|
|
|
|
return (getattr(self._apiresource, 'description', None) or
|
|
|
|
getattr(self._apiresource, 'display_description', None))
|
|
|
|
|
|
|
|
|
|
|
|
class Volume(BaseCinderAPIResourceWrapper):
|
|
|
|
|
|
|
|
_attrs = ['id', 'name', 'description', 'size', 'status', 'created_at',
|
2014-04-16 09:36:27 -07:00
|
|
|
'volume_type', 'availability_zone', 'imageRef', 'bootable',
|
2014-01-29 15:07:15 +00:00
|
|
|
'snapshot_id', 'source_volid', 'attachments', 'tenant_name',
|
2018-01-08 10:43:49 +09:00
|
|
|
'group_id', 'consistencygroup_id', 'os-vol-host-attr:host',
|
Add Horizon support for volume consistency groups
Cinder has added support for creating and managing volume consistency
groups. This first patch adds this functionality into Horizon.
Subsequent patches will add features to utilize these consistency
groups - such as for creating snapshots.
Background/setup info:
This feature provides a Horizon interface to the Cinder consistency
groups (CG) API. CGs allow a user to group a set of volumes together,
and then perform actions on all of the volumes in one command.
For example:
- Create CG snapshot. This will pause all volume I/O and create a
snapshot for each volume in the CG at the same point in time.
- Create CG from another CG. This will clone a new set of volumes based
on the current state of all volumes in the original CG.
- Create CG from CG snapshot. This will clone new set of volumes based
on the saved state of all snapshots from the original CG snapshot.
This patch is limited to just creating consistency groups. A second
and final patch will add the snapshot features.
To run the patch, you will need to enable some consistency group
policies, which currently are defaulted to "none", which means they
are disabled.
The policies are set in /etc/cinder/policy.json - they need to be set
to the following:
"consistencygroup:create" : "rule:admin_or_owner",
"consistencygroup:delete": "rule:admin_or_owner",
"consistencygroup:update": "rule:admin_or_owner",
"consistencygroup:get": "rule:admin_or_owner",
"consistencygroup:get_all": "rule:admin_or_owner",
"consistencygroup:create_cgsnapshot" : "rule:admin_or_owner",
"consistencygroup:delete_cgsnapshot": "rule:admin_or_owner",
"consistencygroup:get_cgsnapshot": "rule:admin_or_owner",
"consistencygroup:get_all_cgsnapshots": "rule:admin_or_owner",
Once this is done, you will need to restart all 3 of the cinder
services in "screen -r" (c-api, c-sch, and c-vol).
The new panel is a tab named "Volume Consistency Groups" and is
located in "Project -> Volumes".
Co-Authored-By: Brad Pokorny <brad_pokorny@symantec.com>
Change-Id: I33ebe39e79d7c1d1dc7e741b4199bcb259b642d1
Partially-implements: blueprint cinder-consistency-groups
2015-12-09 09:04:45 -08:00
|
|
|
'os-vol-tenant-attr:tenant_id', 'metadata',
|
2018-02-25 14:38:43 -05:00
|
|
|
'volume_image_metadata', 'encrypted', 'transfer',
|
|
|
|
'multiattach']
|
2014-01-29 15:07:15 +00:00
|
|
|
|
2014-05-15 14:44:45 -03:00
|
|
|
@property
|
|
|
|
def is_bootable(self):
|
|
|
|
return self.bootable == 'true'
|
|
|
|
|
2019-02-13 10:04:58 +00:00
|
|
|
@property
|
|
|
|
def tenant_id(self):
|
|
|
|
return getattr(self, 'os-vol-tenant-attr:tenant_id', "")
|
|
|
|
|
2014-01-29 15:07:15 +00:00
|
|
|
|
|
|
|
class VolumeSnapshot(BaseCinderAPIResourceWrapper):
|
|
|
|
|
|
|
|
_attrs = ['id', 'name', 'description', 'size', 'status',
|
2018-01-11 05:31:39 +09:00
|
|
|
'created_at', 'volume_id', 'group_snapshot_id',
|
2016-02-11 13:34:52 -08:00
|
|
|
'os-extended-snapshot-attributes:project_id',
|
|
|
|
'metadata']
|
2014-01-29 15:07:15 +00:00
|
|
|
|
2019-02-13 10:04:58 +00:00
|
|
|
@property
|
|
|
|
def project_id(self):
|
|
|
|
return getattr(self, 'os-extended-snapshot-attributes:project_id', "")
|
|
|
|
|
2014-01-29 15:07:15 +00:00
|
|
|
|
Enable changing volume type of a volume
Expose the functionality of the 'cinder retype' command in the UI.
It allows user to change the volume type of a volume whose status is
in-use or available when horizon's cinder API version is >= 2.
cinder retype is only supported starting cinder v2.
If enabled_backends is specified in /etc/cinder/cinder.conf,
retype is actually performed by a specific driver.
It depends on the drivers (backends) that are associated
with volume types.
Volume types are set through type-key extra specs.
If enabled_backends in cinder.conf is not specified, volumes are
created by LVM so retype is actually performaned in LVM.
During retype, if cinder finds it can not retype, it will check
if the migration policy is on_demand or never. If the policy is
is never, then cinder does not do anything, otherwise, it will
perform migration. By default, in the horizon retype dialog UI,
migration policy is never which is also the default
of the cinder cli command.
Currently in horizon cinder api default version is 1. In order to
test this functionallity, you need to update
openstack_dashboard/local/local_settings.py to have the "volume"
API to use version 2 so the "Change Volume Type" action menu
shows up for the volume. If local_settings.py is not available, you
need to copy the local_settings.py.example file, change it to
local_settings.py, update other necessary settings and also update
have the API version setting like the followings:
OPENSTACK_API_VERSIONS = {
#"data_processing": 1.1,
#"identity": 3,
"volume": 2
}
Implements: blueprint volume-retype
Change-Id: Id8bc539e1849f5910df34d7b76cc250ec82f9671
2014-07-11 14:40:02 -07:00
|
|
|
class VolumeType(BaseCinderAPIResourceWrapper):
|
|
|
|
|
2015-10-12 11:15:03 -07:00
|
|
|
_attrs = ['id', 'name', 'extra_specs', 'created_at', 'encryption',
|
|
|
|
'associated_qos_spec', 'description',
|
Enable changing volume type of a volume
Expose the functionality of the 'cinder retype' command in the UI.
It allows user to change the volume type of a volume whose status is
in-use or available when horizon's cinder API version is >= 2.
cinder retype is only supported starting cinder v2.
If enabled_backends is specified in /etc/cinder/cinder.conf,
retype is actually performed by a specific driver.
It depends on the drivers (backends) that are associated
with volume types.
Volume types are set through type-key extra specs.
If enabled_backends in cinder.conf is not specified, volumes are
created by LVM so retype is actually performaned in LVM.
During retype, if cinder finds it can not retype, it will check
if the migration policy is on_demand or never. If the policy is
is never, then cinder does not do anything, otherwise, it will
perform migration. By default, in the horizon retype dialog UI,
migration policy is never which is also the default
of the cinder cli command.
Currently in horizon cinder api default version is 1. In order to
test this functionallity, you need to update
openstack_dashboard/local/local_settings.py to have the "volume"
API to use version 2 so the "Change Volume Type" action menu
shows up for the volume. If local_settings.py is not available, you
need to copy the local_settings.py.example file, change it to
local_settings.py, update other necessary settings and also update
have the API version setting like the followings:
OPENSTACK_API_VERSIONS = {
#"data_processing": 1.1,
#"identity": 3,
"volume": 2
}
Implements: blueprint volume-retype
Change-Id: Id8bc539e1849f5910df34d7b76cc250ec82f9671
2014-07-11 14:40:02 -07:00
|
|
|
'os-extended-snapshot-attributes:project_id']
|
|
|
|
|
|
|
|
|
2014-03-28 10:50:01 -05:00
|
|
|
class VolumeBackup(BaseCinderAPIResourceWrapper):
|
|
|
|
|
|
|
|
_attrs = ['id', 'name', 'description', 'container', 'size', 'status',
|
2019-06-26 18:22:58 +00:00
|
|
|
'created_at', 'volume_id', 'availability_zone', 'snapshot_id']
|
2014-03-28 10:50:01 -05:00
|
|
|
_volume = None
|
2019-06-26 18:22:58 +00:00
|
|
|
_snapshot = None
|
2014-03-28 10:50:01 -05:00
|
|
|
@property
|
|
|
|
def volume(self):
|
|
|
|
return self._volume
|
|
|
|
|
|
|
|
@volume.setter
|
|
|
|
def volume(self, value):
|
|
|
|
self._volume = value
|
|
|
|
|
2019-06-26 18:22:58 +00:00
|
|
|
@property
|
|
|
|
def snapshot(self):
|
|
|
|
return self._snapshot
|
|
|
|
|
|
|
|
@snapshot.setter
|
|
|
|
def snapshot(self, value):
|
|
|
|
self._snapshot = value
|
|
|
|
|
2014-03-28 10:50:01 -05:00
|
|
|
|
2015-10-12 11:15:03 -07:00
|
|
|
class QosSpecs(BaseCinderAPIResourceWrapper):
|
|
|
|
|
|
|
|
_attrs = ['id', 'name', 'consumer', 'specs']
|
|
|
|
|
|
|
|
|
2013-12-26 14:53:00 +08:00
|
|
|
class VolTypeExtraSpec(object):
|
|
|
|
def __init__(self, type_id, key, val):
|
|
|
|
self.type_id = type_id
|
|
|
|
self.id = key
|
|
|
|
self.key = key
|
|
|
|
self.value = val
|
|
|
|
|
|
|
|
|
2019-02-19 09:05:11 +00:00
|
|
|
class GroupTypeSpec(object):
|
|
|
|
def __init__(self, group_type_id, key, val):
|
|
|
|
self.group_type_id = group_type_id
|
|
|
|
self.id = key
|
|
|
|
self.key = key
|
|
|
|
self.value = val
|
|
|
|
|
|
|
|
|
2014-08-01 08:45:20 -07:00
|
|
|
class QosSpec(object):
|
2014-08-04 10:57:02 -07:00
|
|
|
def __init__(self, id, key, val):
|
|
|
|
self.id = id
|
2014-08-01 08:45:20 -07:00
|
|
|
self.key = key
|
|
|
|
self.value = val
|
|
|
|
|
|
|
|
|
Add support for volume transfers
Cinder supports volume transfers, which are transfers of ownership from
one project to another. The normal flow is that a donor creates a volume
transfer, captures the resulting transfer id and secret authentication
key, and passes that information out of band to the recipient (such as
by email, text message, etc.). The recipient then accepts the transfer,
supplying the transfer id and authentication key. The ownership of the
volume is then transferred from the donor to the recipient, and the
volome is no longer visible to the donor.
It is important to know of some limitations about the cinder API for
volume transfers and their impact on the UI design.
1. When creating a volume transfer, you cannot specify who the intended
recipient will be, and anyone with the transfer ID and auth key can
claim the volume. Therefore there is no UI to prompt for a
recipient.
2. Current volume transfers are only visible to the donor; users in
other projects are unable to view these transfers. This makes it
pointless to create a project table to view and accept volume
transfers, since the current transfers are not visible. Instead, the
transfer information has been added to the volume details, which are
visible by the donor, and the volume state clearly reflects that a
transfer has been created. It it also impossible to present to the
recipient a pull-down list of transfers to accept.
3. The only time that the authorization key is visible to the donor is
in the response from the creation of the transfer; after creation it
is impossible for even the donor to recover it. Since the donor must
capture the transfer ID and authorization key in order to send it to
the recipient, an extra form was created to present this information
to the donor immediately after the transfer has been created. It is
not enough to put the information in a success message, since these
are typically only displayed for a small number of seconds before
they disappear.
Co-Authored-By: Gary W. Smith <gary.w.smith@hp.com>
Co-Authored-By: Julie Gravel <julie.gravel@hp.com>
Implements blueprint cinder-volume-transfer
Change-Id: I0134f90c93a8d804d2c87fe9713bcef9e1629d79
2014-07-31 16:35:05 -07:00
|
|
|
class VolumeTransfer(base.APIResourceWrapper):
|
|
|
|
|
|
|
|
_attrs = ['id', 'name', 'created_at', 'volume_id', 'auth_key']
|
|
|
|
|
|
|
|
|
2015-01-15 17:20:35 +00:00
|
|
|
class VolumePool(base.APIResourceWrapper):
|
|
|
|
|
|
|
|
_attrs = ['name', 'pool_name', 'total_capacity_gb', 'free_capacity_gb',
|
|
|
|
'allocated_capacity_gb', 'QoS_support', 'reserved_percentage',
|
|
|
|
'volume_backend_name', 'vendor_name', 'driver_version',
|
|
|
|
'storage_protocol', 'extra_specs']
|
|
|
|
|
|
|
|
|
2018-01-08 10:43:49 +09:00
|
|
|
class Group(base.APIResourceWrapper):
|
|
|
|
_attrs = ['id', 'status', 'availability_zone', 'created_at', 'name',
|
|
|
|
'description', 'group_type', 'volume_types',
|
2019-02-04 08:35:36 +00:00
|
|
|
'group_snapshot_id', 'source_group_id', 'replication_status',
|
|
|
|
'project_id']
|
2018-01-08 10:43:49 +09:00
|
|
|
|
|
|
|
|
|
|
|
class GroupSnapshot(base.APIResourceWrapper):
|
|
|
|
_attrs = ['id', 'name', 'description', 'status', 'created_at',
|
2019-03-02 08:02:17 +00:00
|
|
|
'group_id', 'group_type_id', 'project_id']
|
2018-01-08 10:43:49 +09:00
|
|
|
|
|
|
|
|
|
|
|
class GroupType(base.APIResourceWrapper):
|
|
|
|
_attrs = ['id', 'name', 'description', 'is_public', 'group_specs']
|
|
|
|
|
|
|
|
|
2020-02-26 02:26:29 +09:00
|
|
|
def _find_cinder_url(request, version=None):
|
|
|
|
if version is None:
|
|
|
|
api_version = VERSIONS.get_active_version()
|
|
|
|
version = api_version['version']
|
|
|
|
version = base.Version(version)
|
|
|
|
|
|
|
|
# We support only cinder v2 and v3.
|
|
|
|
if version.major == 3:
|
|
|
|
candidates = ['volumev3', 'volume']
|
|
|
|
else:
|
|
|
|
candidates = ['volumev2', 'volume']
|
|
|
|
|
|
|
|
for service_name in candidates:
|
2017-03-16 18:27:03 +01:00
|
|
|
try:
|
2020-02-26 02:26:29 +09:00
|
|
|
return version, base.url_for(request, service_name)
|
2017-03-16 18:27:03 +01:00
|
|
|
except exceptions.ServiceCatalogException:
|
|
|
|
pass
|
2020-02-26 02:26:29 +09:00
|
|
|
else:
|
2017-03-16 18:27:03 +01:00
|
|
|
raise exceptions.ServiceCatalogException(
|
2020-02-26 02:26:29 +09:00
|
|
|
("Cinder %(version)s requested but no '%(service)s' service "
|
|
|
|
"type available in Keystone catalog.") %
|
|
|
|
{'version': version, 'service': candidates})
|
2016-05-10 14:52:24 -05:00
|
|
|
|
|
|
|
|
2018-09-25 11:40:02 +02:00
|
|
|
@memoized
|
|
|
|
def cinderclient(request, version=None):
|
2020-02-26 02:26:29 +09:00
|
|
|
version, cinder_url = _find_cinder_url(request, version)
|
|
|
|
|
2019-04-11 06:26:54 +09:00
|
|
|
insecure = settings.OPENSTACK_SSL_NO_VERIFY
|
|
|
|
cacert = settings.OPENSTACK_SSL_CACERT
|
2016-05-10 14:52:24 -05:00
|
|
|
|
2017-03-16 18:27:03 +01:00
|
|
|
c = cinder_client.Client(
|
|
|
|
version,
|
2020-02-26 02:26:29 +09:00
|
|
|
request.user.username,
|
|
|
|
request.user.token.id,
|
|
|
|
project_id=request.user.tenant_id,
|
|
|
|
auth_url=base.url_for(request, 'identity'),
|
2017-03-16 18:27:03 +01:00
|
|
|
insecure=insecure,
|
|
|
|
cacert=cacert,
|
|
|
|
http_log_debug=settings.DEBUG,
|
|
|
|
)
|
2020-02-26 02:26:29 +09:00
|
|
|
c.client.auth_token = request.user.token.id
|
2012-12-10 13:49:38 +01:00
|
|
|
c.client.management_url = cinder_url
|
2012-10-23 22:25:18 -07:00
|
|
|
return c
|
|
|
|
|
|
|
|
|
2017-10-22 18:17:03 +00:00
|
|
|
def get_microversion(request, features):
|
2020-02-26 02:26:29 +09:00
|
|
|
try:
|
|
|
|
version, cinder_url = _find_cinder_url(request)
|
|
|
|
except exceptions.ServiceCatalogException:
|
2017-03-16 18:27:03 +01:00
|
|
|
return None
|
2019-08-12 16:19:44 +03:00
|
|
|
|
|
|
|
insecure = settings.OPENSTACK_SSL_NO_VERIFY
|
|
|
|
cacert = settings.OPENSTACK_SSL_CACERT
|
|
|
|
|
|
|
|
min_ver, max_ver = cinder_client.get_server_version(cinder_url,
|
|
|
|
insecure, cacert)
|
2019-01-15 04:23:08 +09:00
|
|
|
return microversions.get_microversion_for_features(
|
|
|
|
'cinder', features, api_versions.APIVersion, min_ver, max_ver)
|
2017-03-16 18:27:03 +01:00
|
|
|
|
|
|
|
|
2019-01-15 04:23:08 +09:00
|
|
|
def _cinderclient_with_features(request, features,
|
|
|
|
raise_exc=False, message=False):
|
|
|
|
version = get_microversion(request, features)
|
|
|
|
if version is None:
|
|
|
|
if message:
|
|
|
|
versions = microversions.get_requested_versions('cinder', features)
|
|
|
|
if message is True:
|
|
|
|
message = ('Insufficient microversion for cinder feature(s) '
|
|
|
|
'%(features)s. One of the following API '
|
|
|
|
'microversion(s) is required: %(versions).')
|
|
|
|
LOG.warning(message,
|
|
|
|
{'features': features, 'versions': versions})
|
|
|
|
if raise_exc:
|
|
|
|
raise microversions.MicroVersionNotFound(features)
|
2018-01-08 10:43:49 +09:00
|
|
|
if version is not None:
|
|
|
|
version = version.get_string()
|
|
|
|
return cinderclient(request, version=version)
|
|
|
|
|
|
|
|
|
2019-01-15 04:23:08 +09:00
|
|
|
def _cinderclient_with_generic_groups(request):
|
|
|
|
return _cinderclient_with_features(request, 'groups')
|
|
|
|
|
|
|
|
|
Enable changing volume type of a volume
Expose the functionality of the 'cinder retype' command in the UI.
It allows user to change the volume type of a volume whose status is
in-use or available when horizon's cinder API version is >= 2.
cinder retype is only supported starting cinder v2.
If enabled_backends is specified in /etc/cinder/cinder.conf,
retype is actually performed by a specific driver.
It depends on the drivers (backends) that are associated
with volume types.
Volume types are set through type-key extra specs.
If enabled_backends in cinder.conf is not specified, volumes are
created by LVM so retype is actually performaned in LVM.
During retype, if cinder finds it can not retype, it will check
if the migration policy is on_demand or never. If the policy is
is never, then cinder does not do anything, otherwise, it will
perform migration. By default, in the horizon retype dialog UI,
migration policy is never which is also the default
of the cinder cli command.
Currently in horizon cinder api default version is 1. In order to
test this functionallity, you need to update
openstack_dashboard/local/local_settings.py to have the "volume"
API to use version 2 so the "Change Volume Type" action menu
shows up for the volume. If local_settings.py is not available, you
need to copy the local_settings.py.example file, change it to
local_settings.py, update other necessary settings and also update
have the API version setting like the followings:
OPENSTACK_API_VERSIONS = {
#"data_processing": 1.1,
#"identity": 3,
"volume": 2
}
Implements: blueprint volume-retype
Change-Id: Id8bc539e1849f5910df34d7b76cc250ec82f9671
2014-07-11 14:40:02 -07:00
|
|
|
def version_get():
|
|
|
|
api_version = VERSIONS.get_active_version()
|
|
|
|
return api_version['version']
|
|
|
|
|
|
|
|
|
2014-09-02 15:35:17 -04:00
|
|
|
def volume_list(request, search_opts=None, marker=None, sort_dir="desc"):
|
|
|
|
volumes, _, __ = volume_list_paged(
|
|
|
|
request, search_opts=search_opts, marker=marker, paginate=False,
|
|
|
|
sort_dir=sort_dir)
|
|
|
|
return volumes
|
|
|
|
|
|
|
|
|
2015-11-30 18:07:39 +03:00
|
|
|
def update_pagination(entities, page_size, marker, sort_dir):
|
|
|
|
has_more_data, has_prev_data = False, False
|
|
|
|
if len(entities) > page_size:
|
|
|
|
has_more_data = True
|
|
|
|
entities.pop()
|
|
|
|
if marker is not None:
|
|
|
|
has_prev_data = True
|
|
|
|
# first page condition when reached via prev back
|
|
|
|
elif sort_dir == 'asc' and marker is not None:
|
|
|
|
has_more_data = True
|
|
|
|
# last page condition
|
|
|
|
elif marker is not None:
|
|
|
|
has_prev_data = True
|
|
|
|
|
2018-11-21 18:19:21 +08:00
|
|
|
if sort_dir == 'asc':
|
|
|
|
entities.reverse()
|
|
|
|
|
2015-11-30 18:07:39 +03:00
|
|
|
return entities, has_more_data, has_prev_data
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-09-02 15:35:17 -04:00
|
|
|
def volume_list_paged(request, search_opts=None, marker=None, paginate=False,
|
|
|
|
sort_dir="desc"):
|
2017-06-09 10:47:12 +00:00
|
|
|
"""List volumes with pagination.
|
|
|
|
|
|
|
|
To see all volumes in the cloud as an admin you can pass in a special
|
2012-10-23 22:25:18 -07:00
|
|
|
search option: {'all_tenants': 1}
|
|
|
|
"""
|
2014-09-02 15:35:17 -04:00
|
|
|
has_more_data = False
|
|
|
|
has_prev_data = False
|
|
|
|
volumes = []
|
2015-01-15 17:20:35 +00:00
|
|
|
|
2018-01-08 10:43:49 +09:00
|
|
|
# To support filtering with group_id, we need to use the microversion.
|
|
|
|
c_client = _cinderclient_with_generic_groups(request)
|
2013-01-10 12:00:20 +01:00
|
|
|
if c_client is None:
|
2014-09-02 15:35:17 -04:00
|
|
|
return volumes, has_more_data, has_prev_data
|
Add support for volume transfers
Cinder supports volume transfers, which are transfers of ownership from
one project to another. The normal flow is that a donor creates a volume
transfer, captures the resulting transfer id and secret authentication
key, and passes that information out of band to the recipient (such as
by email, text message, etc.). The recipient then accepts the transfer,
supplying the transfer id and authentication key. The ownership of the
volume is then transferred from the donor to the recipient, and the
volome is no longer visible to the donor.
It is important to know of some limitations about the cinder API for
volume transfers and their impact on the UI design.
1. When creating a volume transfer, you cannot specify who the intended
recipient will be, and anyone with the transfer ID and auth key can
claim the volume. Therefore there is no UI to prompt for a
recipient.
2. Current volume transfers are only visible to the donor; users in
other projects are unable to view these transfers. This makes it
pointless to create a project table to view and accept volume
transfers, since the current transfers are not visible. Instead, the
transfer information has been added to the volume details, which are
visible by the donor, and the volume state clearly reflects that a
transfer has been created. It it also impossible to present to the
recipient a pull-down list of transfers to accept.
3. The only time that the authorization key is visible to the donor is
in the response from the creation of the transfer; after creation it
is impossible for even the donor to recover it. Since the donor must
capture the transfer ID and authorization key in order to send it to
the recipient, an extra form was created to present this information
to the donor immediately after the transfer has been created. It is
not enough to put the information in a success message, since these
are typically only displayed for a small number of seconds before
they disappear.
Co-Authored-By: Gary W. Smith <gary.w.smith@hp.com>
Co-Authored-By: Julie Gravel <julie.gravel@hp.com>
Implements blueprint cinder-volume-transfer
Change-Id: I0134f90c93a8d804d2c87fe9713bcef9e1629d79
2014-07-31 16:35:05 -07:00
|
|
|
|
|
|
|
# build a dictionary of volume_id -> transfer
|
|
|
|
transfers = {t.volume_id: t
|
|
|
|
for t in transfer_list(request, search_opts=search_opts)}
|
|
|
|
|
2014-09-02 15:35:17 -04:00
|
|
|
if VERSIONS.active > 1 and paginate:
|
|
|
|
page_size = utils.get_page_size(request)
|
|
|
|
# sort_key and sort_dir deprecated in kilo, use sort
|
|
|
|
# if pagination is true, we use a single sort parameter
|
|
|
|
# by default, it is "created_at"
|
|
|
|
sort = 'created_at:' + sort_dir
|
|
|
|
for v in c_client.volumes.list(search_opts=search_opts,
|
|
|
|
limit=page_size + 1,
|
|
|
|
marker=marker,
|
|
|
|
sort=sort):
|
|
|
|
v.transfer = transfers.get(v.id)
|
|
|
|
volumes.append(Volume(v))
|
2015-11-30 18:07:39 +03:00
|
|
|
volumes, has_more_data, has_prev_data = update_pagination(
|
|
|
|
volumes, page_size, marker, sort_dir)
|
2014-09-02 15:35:17 -04:00
|
|
|
else:
|
|
|
|
for v in c_client.volumes.list(search_opts=search_opts):
|
|
|
|
v.transfer = transfers.get(v.id)
|
|
|
|
volumes.append(Volume(v))
|
|
|
|
|
|
|
|
return volumes, has_more_data, has_prev_data
|
2012-10-23 22:25:18 -07:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2012-10-23 22:25:18 -07:00
|
|
|
def volume_get(request, volume_id):
|
2018-01-11 05:31:39 +09:00
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
volume_data = client.volumes.get(volume_id)
|
2012-10-23 22:25:18 -07:00
|
|
|
|
|
|
|
for attachment in volume_data.attachments:
|
|
|
|
if "server_id" in attachment:
|
2019-02-09 20:20:44 +09:00
|
|
|
instance = _nova.server_get(request, attachment['server_id'])
|
2012-10-23 22:25:18 -07:00
|
|
|
attachment['instance_name'] = instance.name
|
|
|
|
else:
|
2015-01-15 17:20:35 +00:00
|
|
|
# Nova volume can occasionally send back error'd attachments
|
|
|
|
# the lack a server_id property; to work around that we'll
|
2012-10-23 22:25:18 -07:00
|
|
|
# give the attached instance a generic name.
|
|
|
|
attachment['instance_name'] = _("Unknown instance")
|
Add support for volume transfers
Cinder supports volume transfers, which are transfers of ownership from
one project to another. The normal flow is that a donor creates a volume
transfer, captures the resulting transfer id and secret authentication
key, and passes that information out of band to the recipient (such as
by email, text message, etc.). The recipient then accepts the transfer,
supplying the transfer id and authentication key. The ownership of the
volume is then transferred from the donor to the recipient, and the
volome is no longer visible to the donor.
It is important to know of some limitations about the cinder API for
volume transfers and their impact on the UI design.
1. When creating a volume transfer, you cannot specify who the intended
recipient will be, and anyone with the transfer ID and auth key can
claim the volume. Therefore there is no UI to prompt for a
recipient.
2. Current volume transfers are only visible to the donor; users in
other projects are unable to view these transfers. This makes it
pointless to create a project table to view and accept volume
transfers, since the current transfers are not visible. Instead, the
transfer information has been added to the volume details, which are
visible by the donor, and the volume state clearly reflects that a
transfer has been created. It it also impossible to present to the
recipient a pull-down list of transfers to accept.
3. The only time that the authorization key is visible to the donor is
in the response from the creation of the transfer; after creation it
is impossible for even the donor to recover it. Since the donor must
capture the transfer ID and authorization key in order to send it to
the recipient, an extra form was created to present this information
to the donor immediately after the transfer has been created. It is
not enough to put the information in a success message, since these
are typically only displayed for a small number of seconds before
they disappear.
Co-Authored-By: Gary W. Smith <gary.w.smith@hp.com>
Co-Authored-By: Julie Gravel <julie.gravel@hp.com>
Implements blueprint cinder-volume-transfer
Change-Id: I0134f90c93a8d804d2c87fe9713bcef9e1629d79
2014-07-31 16:35:05 -07:00
|
|
|
|
|
|
|
volume_data.transfer = None
|
|
|
|
if volume_data.status == 'awaiting-transfer':
|
|
|
|
for transfer in transfer_list(request):
|
|
|
|
if transfer.volume_id == volume_id:
|
|
|
|
volume_data.transfer = transfer
|
|
|
|
break
|
|
|
|
|
2014-01-29 15:07:15 +00:00
|
|
|
return Volume(volume_data)
|
2012-10-23 22:25:18 -07:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
Added support for volume types
As cinder already supports volume types, it's time
to be added in Horizon. The types are added in admin panel.
A volume can either have a *valid* type, or None.
There are two minor issues:
1. When a type is deleted, if there is a volume with
this type, the type is returned as the id,
instead of the name. Which is good as consistency,
but maybe a type should not be deleted if used by a volume?
2. If no vol type is passed(None) value, the type is being
assigned as 'None', and returned as a string('None')
3. In the create volume type form, the 'Description' is
empty at the moment, I couldn't find any help info
to add for volume types...
Implements blueprint volume-types
Tested with n-cinder and n-vol services. Since Folsom both
support volume-types. I'm not sure if it is possible a grizzly
Dashboard to work with essex nova, which could be a problem.
Dashboard doesn't seem to provide permissions based on tables,
so if it needs to check if a service is available to show/hide
volume types, this will need some more effors to implement
permissions on table/action level. Or maybe this needs to be
added as a standalone panel?
Patch set 2: implemented suggestions, added one more thing:
When creating a volume from a snapshot, set the volume type
initial as the type of the original volume from which
the snapshot is being created.
Patch Set 3: Updated the description of volume types,
based on the notes from:
https://etherpad.openstack.org/grizzly-cinder-volumetypes
https://etherpad.openstack.org/cinder-usecases
Any feedback on the description is welcome.
Change-Id: Ib0c136c5c8cd9fbd34ce1dd346260f404c96f667
2012-10-25 14:48:27 +03:00
|
|
|
def volume_create(request, size, name, description, volume_type,
|
2013-09-25 11:47:10 -05:00
|
|
|
snapshot_id=None, metadata=None, image_id=None,
|
2018-02-10 15:44:38 +09:00
|
|
|
availability_zone=None, source_volid=None,
|
|
|
|
group_id=None):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
2014-01-29 15:07:15 +00:00
|
|
|
data = {'name': name,
|
|
|
|
'description': description,
|
|
|
|
'volume_type': volume_type,
|
|
|
|
'snapshot_id': snapshot_id,
|
|
|
|
'metadata': metadata,
|
|
|
|
'imageRef': image_id,
|
|
|
|
'availability_zone': availability_zone,
|
2018-02-10 15:44:38 +09:00
|
|
|
'source_volid': source_volid,
|
|
|
|
'group_id': group_id}
|
2014-01-29 15:07:15 +00:00
|
|
|
|
2018-02-10 15:44:38 +09:00
|
|
|
volume = client.volumes.create(size, **data)
|
2014-01-29 15:07:15 +00:00
|
|
|
return Volume(volume)
|
2012-10-23 22:25:18 -07:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2013-12-19 13:09:04 +08:00
|
|
|
def volume_extend(request, volume_id, new_size):
|
|
|
|
return cinderclient(request).volumes.extend(volume_id, new_size)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2012-10-23 22:25:18 -07:00
|
|
|
def volume_delete(request, volume_id):
|
|
|
|
return cinderclient(request).volumes.delete(volume_id)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
Enable changing volume type of a volume
Expose the functionality of the 'cinder retype' command in the UI.
It allows user to change the volume type of a volume whose status is
in-use or available when horizon's cinder API version is >= 2.
cinder retype is only supported starting cinder v2.
If enabled_backends is specified in /etc/cinder/cinder.conf,
retype is actually performed by a specific driver.
It depends on the drivers (backends) that are associated
with volume types.
Volume types are set through type-key extra specs.
If enabled_backends in cinder.conf is not specified, volumes are
created by LVM so retype is actually performaned in LVM.
During retype, if cinder finds it can not retype, it will check
if the migration policy is on_demand or never. If the policy is
is never, then cinder does not do anything, otherwise, it will
perform migration. By default, in the horizon retype dialog UI,
migration policy is never which is also the default
of the cinder cli command.
Currently in horizon cinder api default version is 1. In order to
test this functionallity, you need to update
openstack_dashboard/local/local_settings.py to have the "volume"
API to use version 2 so the "Change Volume Type" action menu
shows up for the volume. If local_settings.py is not available, you
need to copy the local_settings.py.example file, change it to
local_settings.py, update other necessary settings and also update
have the API version setting like the followings:
OPENSTACK_API_VERSIONS = {
#"data_processing": 1.1,
#"identity": 3,
"volume": 2
}
Implements: blueprint volume-retype
Change-Id: Id8bc539e1849f5910df34d7b76cc250ec82f9671
2014-07-11 14:40:02 -07:00
|
|
|
def volume_retype(request, volume_id, new_type, migration_policy):
|
|
|
|
return cinderclient(request).volumes.retype(volume_id,
|
|
|
|
new_type,
|
|
|
|
migration_policy)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-11-19 06:10:18 -08:00
|
|
|
def volume_set_bootable(request, volume_id, bootable):
|
|
|
|
return cinderclient(request).volumes.set_bootable(volume_id,
|
|
|
|
bootable)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2013-12-31 11:26:02 +08:00
|
|
|
def volume_update(request, volume_id, name, description):
|
2014-01-29 15:07:15 +00:00
|
|
|
vol_data = {'name': name,
|
|
|
|
'description': description}
|
2013-12-31 11:26:02 +08:00
|
|
|
return cinderclient(request).volumes.update(volume_id,
|
|
|
|
**vol_data)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-09-05 10:58:41 +02:00
|
|
|
def volume_set_metadata(request, volume_id, metadata):
|
|
|
|
return cinderclient(request).volumes.set_metadata(volume_id, metadata)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-09-05 10:58:41 +02:00
|
|
|
def volume_delete_metadata(request, volume_id, keys):
|
|
|
|
return cinderclient(request).volumes.delete_metadata(volume_id, keys)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-06-17 14:36:59 -07:00
|
|
|
def volume_reset_state(request, volume_id, state):
|
2018-02-22 02:53:26 +04:00
|
|
|
cinderclient(request).volumes.reset_state(volume_id, state)
|
2014-06-17 14:36:59 -07:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-08-05 10:25:23 -07:00
|
|
|
def volume_upload_to_image(request, volume_id, force, image_name,
|
|
|
|
container_format, disk_format):
|
|
|
|
return cinderclient(request).volumes.upload_to_image(volume_id,
|
|
|
|
force,
|
|
|
|
image_name,
|
|
|
|
container_format,
|
|
|
|
disk_format)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2015-01-08 17:25:09 -05:00
|
|
|
def volume_get_encryption_metadata(request, volume_id):
|
|
|
|
return cinderclient(request).volumes.get_encryption_metadata(volume_id)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2016-02-05 14:10:19 +01:00
|
|
|
def volume_migrate(request, volume_id, host, force_host_copy=False,
|
|
|
|
lock_volume=False):
|
2015-04-14 18:16:26 +08:00
|
|
|
return cinderclient(request).volumes.migrate_volume(volume_id,
|
|
|
|
host,
|
2016-02-05 14:10:19 +01:00
|
|
|
force_host_copy,
|
|
|
|
lock_volume)
|
2015-04-14 18:16:26 +08:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2012-10-23 22:25:18 -07:00
|
|
|
def volume_snapshot_get(request, snapshot_id):
|
2018-01-11 05:31:39 +09:00
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
snapshot = client.volume_snapshots.get(snapshot_id)
|
2014-01-29 15:07:15 +00:00
|
|
|
return VolumeSnapshot(snapshot)
|
2012-10-23 22:25:18 -07:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-07-10 03:34:57 -07:00
|
|
|
def volume_snapshot_list(request, search_opts=None):
|
2015-11-30 18:07:39 +03:00
|
|
|
snapshots, _, __ = volume_snapshot_list_paged(request,
|
|
|
|
search_opts=search_opts,
|
|
|
|
paginate=False)
|
|
|
|
return snapshots
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2015-11-30 18:07:39 +03:00
|
|
|
def volume_snapshot_list_paged(request, search_opts=None, marker=None,
|
|
|
|
paginate=False, sort_dir="desc"):
|
|
|
|
has_more_data = False
|
|
|
|
has_prev_data = False
|
|
|
|
snapshots = []
|
2018-01-11 05:31:39 +09:00
|
|
|
c_client = _cinderclient_with_generic_groups(request)
|
2012-12-10 13:49:38 +01:00
|
|
|
if c_client is None:
|
2015-11-30 18:07:39 +03:00
|
|
|
return snapshots, has_more_data, has_more_data
|
|
|
|
|
|
|
|
if VERSIONS.active > 1 and paginate:
|
|
|
|
page_size = utils.get_page_size(request)
|
|
|
|
# sort_key and sort_dir deprecated in kilo, use sort
|
|
|
|
# if pagination is true, we use a single sort parameter
|
|
|
|
# by default, it is "created_at"
|
|
|
|
sort = 'created_at:' + sort_dir
|
|
|
|
for s in c_client.volume_snapshots.list(search_opts=search_opts,
|
|
|
|
limit=page_size + 1,
|
|
|
|
marker=marker,
|
|
|
|
sort=sort):
|
|
|
|
snapshots.append(VolumeSnapshot(s))
|
|
|
|
|
|
|
|
snapshots, has_more_data, has_prev_data = update_pagination(
|
|
|
|
snapshots, page_size, marker, sort_dir)
|
|
|
|
else:
|
|
|
|
for s in c_client.volume_snapshots.list(search_opts=search_opts):
|
|
|
|
snapshots.append(VolumeSnapshot(s))
|
|
|
|
|
|
|
|
return snapshots, has_more_data, has_prev_data
|
2012-10-23 22:25:18 -07:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2013-11-19 10:39:37 +08:00
|
|
|
def volume_snapshot_create(request, volume_id, name,
|
|
|
|
description=None, force=False):
|
2014-01-29 15:07:15 +00:00
|
|
|
data = {'name': name,
|
|
|
|
'description': description,
|
|
|
|
'force': force}
|
|
|
|
|
|
|
|
return VolumeSnapshot(cinderclient(request).volume_snapshots.create(
|
|
|
|
volume_id, **data))
|
2012-10-23 22:25:18 -07:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2012-10-23 22:25:18 -07:00
|
|
|
def volume_snapshot_delete(request, snapshot_id):
|
|
|
|
return cinderclient(request).volume_snapshots.delete(snapshot_id)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-02-25 10:23:30 +08:00
|
|
|
def volume_snapshot_update(request, snapshot_id, name, description):
|
|
|
|
snapshot_data = {'name': name,
|
|
|
|
'description': description}
|
|
|
|
return cinderclient(request).volume_snapshots.update(snapshot_id,
|
|
|
|
**snapshot_data)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-09-05 10:58:41 +02:00
|
|
|
def volume_snapshot_set_metadata(request, snapshot_id, metadata):
|
|
|
|
return cinderclient(request).volume_snapshots.set_metadata(
|
|
|
|
snapshot_id, metadata)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-09-05 10:58:41 +02:00
|
|
|
def volume_snapshot_delete_metadata(request, snapshot_id, keys):
|
|
|
|
return cinderclient(request).volume_snapshots.delete_metadata(
|
|
|
|
snapshot_id, keys)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-07-10 03:34:57 -07:00
|
|
|
def volume_snapshot_reset_state(request, snapshot_id, state):
|
|
|
|
return cinderclient(request).volume_snapshots.reset_state(
|
|
|
|
snapshot_id, state)
|
|
|
|
|
|
|
|
|
2014-03-28 10:50:01 -05:00
|
|
|
@memoized
|
|
|
|
def volume_backup_supported(request):
|
2017-06-09 10:47:12 +00:00
|
|
|
"""This method will determine if cinder supports backup."""
|
2014-03-28 10:50:01 -05:00
|
|
|
# TODO(lcheng) Cinder does not expose the information if cinder
|
|
|
|
# backup is configured yet. This is a workaround until that
|
|
|
|
# capability is available.
|
|
|
|
# https://bugs.launchpad.net/cinder/+bug/1334856
|
2019-09-25 21:29:05 +09:00
|
|
|
return utils.get_dict_config('OPENSTACK_CINDER_FEATURES', 'enable_backup')
|
2014-03-28 10:50:01 -05:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-03-28 10:50:01 -05:00
|
|
|
def volume_backup_get(request, backup_id):
|
|
|
|
backup = cinderclient(request).backups.get(backup_id)
|
|
|
|
return VolumeBackup(backup)
|
|
|
|
|
|
|
|
|
|
|
|
def volume_backup_list(request):
|
2015-11-30 18:07:39 +03:00
|
|
|
backups, _, __ = volume_backup_list_paged(request, paginate=False)
|
|
|
|
return backups
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2015-11-30 18:07:39 +03:00
|
|
|
def volume_backup_list_paged(request, marker=None, paginate=False,
|
|
|
|
sort_dir="desc"):
|
|
|
|
has_more_data = False
|
|
|
|
has_prev_data = False
|
|
|
|
backups = []
|
|
|
|
|
2014-03-28 10:50:01 -05:00
|
|
|
c_client = cinderclient(request)
|
|
|
|
if c_client is None:
|
2015-11-30 18:07:39 +03:00
|
|
|
return backups, has_more_data, has_prev_data
|
|
|
|
|
|
|
|
if VERSIONS.active > 1 and paginate:
|
|
|
|
page_size = utils.get_page_size(request)
|
|
|
|
# sort_key and sort_dir deprecated in kilo, use sort
|
|
|
|
# if pagination is true, we use a single sort parameter
|
|
|
|
# by default, it is "created_at"
|
|
|
|
sort = 'created_at:' + sort_dir
|
|
|
|
for b in c_client.backups.list(limit=page_size + 1,
|
|
|
|
marker=marker,
|
|
|
|
sort=sort):
|
|
|
|
backups.append(VolumeBackup(b))
|
|
|
|
|
|
|
|
backups, has_more_data, has_prev_data = update_pagination(
|
|
|
|
backups, page_size, marker, sort_dir)
|
|
|
|
else:
|
|
|
|
for b in c_client.backups.list():
|
|
|
|
backups.append(VolumeBackup(b))
|
|
|
|
|
|
|
|
return backups, has_more_data, has_prev_data
|
2014-03-28 10:50:01 -05:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-03-28 10:50:01 -05:00
|
|
|
def volume_backup_create(request,
|
|
|
|
volume_id,
|
|
|
|
container_name,
|
|
|
|
name,
|
2017-05-10 16:23:50 -07:00
|
|
|
description,
|
2019-06-26 18:22:58 +00:00
|
|
|
force=False,
|
|
|
|
snapshot_id=None):
|
2017-01-23 10:39:52 -07:00
|
|
|
# need to ensure the container name is not an empty
|
|
|
|
# string, but pass None to get the container name
|
|
|
|
# generated correctly
|
2014-03-28 10:50:01 -05:00
|
|
|
backup = cinderclient(request).backups.create(
|
|
|
|
volume_id,
|
2017-01-23 10:39:52 -07:00
|
|
|
container=container_name if container_name else None,
|
2014-03-28 10:50:01 -05:00
|
|
|
name=name,
|
2017-05-10 16:23:50 -07:00
|
|
|
description=description,
|
2019-06-26 18:22:58 +00:00
|
|
|
snapshot_id=snapshot_id,
|
2017-05-10 16:23:50 -07:00
|
|
|
force=force)
|
2014-03-28 10:50:01 -05:00
|
|
|
return VolumeBackup(backup)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-03-28 10:50:01 -05:00
|
|
|
def volume_backup_delete(request, backup_id):
|
|
|
|
return cinderclient(request).backups.delete(backup_id)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-03-28 10:50:01 -05:00
|
|
|
def volume_backup_restore(request, backup_id, volume_id):
|
|
|
|
return cinderclient(request).restores.restore(backup_id=backup_id,
|
|
|
|
volume_id=volume_id)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-10-20 01:48:19 -07:00
|
|
|
def volume_manage(request,
|
|
|
|
host,
|
|
|
|
identifier,
|
|
|
|
id_type,
|
|
|
|
name,
|
|
|
|
description,
|
|
|
|
volume_type,
|
|
|
|
availability_zone,
|
|
|
|
metadata,
|
|
|
|
bootable):
|
|
|
|
source = {id_type: identifier}
|
2018-02-22 02:53:26 +04:00
|
|
|
cinderclient(request).volumes.manage(
|
2014-10-20 01:48:19 -07:00
|
|
|
host=host,
|
|
|
|
ref=source,
|
|
|
|
name=name,
|
|
|
|
description=description,
|
|
|
|
volume_type=volume_type,
|
|
|
|
availability_zone=availability_zone,
|
|
|
|
metadata=metadata,
|
|
|
|
bootable=bootable)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-10-20 01:48:19 -07:00
|
|
|
def volume_unmanage(request, volume_id):
|
|
|
|
return cinderclient(request).volumes.unmanage(volume=volume_id)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2012-10-23 22:25:18 -07:00
|
|
|
def tenant_quota_get(request, tenant_id):
|
2012-12-10 13:49:38 +01:00
|
|
|
c_client = cinderclient(request)
|
|
|
|
if c_client is None:
|
2013-08-02 13:23:46 +04:00
|
|
|
return base.QuotaSet()
|
|
|
|
return base.QuotaSet(c_client.quotas.get(tenant_id))
|
2012-10-23 22:25:18 -07:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2012-10-23 22:25:18 -07:00
|
|
|
def tenant_quota_update(request, tenant_id, **kwargs):
|
|
|
|
return cinderclient(request).quotas.update(tenant_id, **kwargs)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2012-10-23 22:25:18 -07:00
|
|
|
def default_quota_get(request, tenant_id):
|
2013-08-02 13:23:46 +04:00
|
|
|
return base.QuotaSet(cinderclient(request).quotas.defaults(tenant_id))
|
Added support for volume types
As cinder already supports volume types, it's time
to be added in Horizon. The types are added in admin panel.
A volume can either have a *valid* type, or None.
There are two minor issues:
1. When a type is deleted, if there is a volume with
this type, the type is returned as the id,
instead of the name. Which is good as consistency,
but maybe a type should not be deleted if used by a volume?
2. If no vol type is passed(None) value, the type is being
assigned as 'None', and returned as a string('None')
3. In the create volume type form, the 'Description' is
empty at the moment, I couldn't find any help info
to add for volume types...
Implements blueprint volume-types
Tested with n-cinder and n-vol services. Since Folsom both
support volume-types. I'm not sure if it is possible a grizzly
Dashboard to work with essex nova, which could be a problem.
Dashboard doesn't seem to provide permissions based on tables,
so if it needs to check if a service is available to show/hide
volume types, this will need some more effors to implement
permissions on table/action level. Or maybe this needs to be
added as a standalone panel?
Patch set 2: implemented suggestions, added one more thing:
When creating a volume from a snapshot, set the volume type
initial as the type of the original volume from which
the snapshot is being created.
Patch Set 3: Updated the description of volume types,
based on the notes from:
https://etherpad.openstack.org/grizzly-cinder-volumetypes
https://etherpad.openstack.org/cinder-usecases
Any feedback on the description is welcome.
Change-Id: Ib0c136c5c8cd9fbd34ce1dd346260f404c96f667
2012-10-25 14:48:27 +03:00
|
|
|
|
|
|
|
|
2014-08-11 11:05:24 -07:00
|
|
|
def volume_type_list_with_qos_associations(request):
|
|
|
|
vol_types = volume_type_list(request)
|
|
|
|
vol_types_dict = {}
|
|
|
|
|
|
|
|
# initialize and build a dictionary for lookup access below
|
|
|
|
for vol_type in vol_types:
|
|
|
|
vol_type.associated_qos_spec = ""
|
|
|
|
vol_types_dict[vol_type.id] = vol_type
|
|
|
|
|
|
|
|
# get all currently defined qos specs
|
|
|
|
qos_specs = qos_spec_list(request)
|
|
|
|
for qos_spec in qos_specs:
|
|
|
|
# get all volume types this qos spec is associated with
|
|
|
|
assoc_vol_types = qos_spec_get_associations(request, qos_spec.id)
|
|
|
|
for assoc_vol_type in assoc_vol_types:
|
|
|
|
# update volume type to hold this association info
|
|
|
|
vol_type = vol_types_dict[assoc_vol_type.id]
|
|
|
|
vol_type.associated_qos_spec = qos_spec.name
|
|
|
|
|
|
|
|
return vol_types
|
|
|
|
|
|
|
|
|
2014-11-11 11:50:44 -08:00
|
|
|
def volume_type_get_with_qos_association(request, volume_type_id):
|
|
|
|
vol_type = volume_type_get(request, volume_type_id)
|
|
|
|
vol_type.associated_qos_spec = ""
|
|
|
|
|
|
|
|
# get all currently defined qos specs
|
|
|
|
qos_specs = qos_spec_list(request)
|
|
|
|
for qos_spec in qos_specs:
|
|
|
|
# get all volume types this qos spec is associated with
|
|
|
|
assoc_vol_types = qos_spec_get_associations(request, qos_spec.id)
|
|
|
|
for assoc_vol_type in assoc_vol_types:
|
|
|
|
if vol_type.id == assoc_vol_type.id:
|
|
|
|
# update volume type to hold this association info
|
|
|
|
vol_type.associated_qos_spec = qos_spec.name
|
|
|
|
return vol_type
|
|
|
|
|
|
|
|
return vol_type
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-05-29 17:10:10 -03:00
|
|
|
def default_quota_update(request, **kwargs):
|
|
|
|
cinderclient(request).quota_classes.update(DEFAULT_QUOTA_NAME, **kwargs)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
Added support for volume types
As cinder already supports volume types, it's time
to be added in Horizon. The types are added in admin panel.
A volume can either have a *valid* type, or None.
There are two minor issues:
1. When a type is deleted, if there is a volume with
this type, the type is returned as the id,
instead of the name. Which is good as consistency,
but maybe a type should not be deleted if used by a volume?
2. If no vol type is passed(None) value, the type is being
assigned as 'None', and returned as a string('None')
3. In the create volume type form, the 'Description' is
empty at the moment, I couldn't find any help info
to add for volume types...
Implements blueprint volume-types
Tested with n-cinder and n-vol services. Since Folsom both
support volume-types. I'm not sure if it is possible a grizzly
Dashboard to work with essex nova, which could be a problem.
Dashboard doesn't seem to provide permissions based on tables,
so if it needs to check if a service is available to show/hide
volume types, this will need some more effors to implement
permissions on table/action level. Or maybe this needs to be
added as a standalone panel?
Patch set 2: implemented suggestions, added one more thing:
When creating a volume from a snapshot, set the volume type
initial as the type of the original volume from which
the snapshot is being created.
Patch Set 3: Updated the description of volume types,
based on the notes from:
https://etherpad.openstack.org/grizzly-cinder-volumetypes
https://etherpad.openstack.org/cinder-usecases
Any feedback on the description is welcome.
Change-Id: Ib0c136c5c8cd9fbd34ce1dd346260f404c96f667
2012-10-25 14:48:27 +03:00
|
|
|
def volume_type_list(request):
|
|
|
|
return cinderclient(request).volume_types.list()
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2015-10-15 11:10:04 +08:00
|
|
|
def volume_type_create(request, name, description=None, is_public=True):
|
|
|
|
return cinderclient(request).volume_types.create(name, description,
|
|
|
|
is_public)
|
2014-11-11 11:50:44 -08:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2015-10-15 11:10:04 +08:00
|
|
|
def volume_type_update(request, volume_type_id, name=None, description=None,
|
|
|
|
is_public=None):
|
2014-11-11 11:50:44 -08:00
|
|
|
return cinderclient(request).volume_types.update(volume_type_id,
|
|
|
|
name,
|
2015-10-15 11:10:04 +08:00
|
|
|
description,
|
|
|
|
is_public)
|
2014-11-11 11:50:44 -08:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2015-09-08 10:26:21 -06:00
|
|
|
@memoized
|
2014-11-11 11:50:44 -08:00
|
|
|
def volume_type_default(request):
|
|
|
|
return cinderclient(request).volume_types.default()
|
Added support for volume types
As cinder already supports volume types, it's time
to be added in Horizon. The types are added in admin panel.
A volume can either have a *valid* type, or None.
There are two minor issues:
1. When a type is deleted, if there is a volume with
this type, the type is returned as the id,
instead of the name. Which is good as consistency,
but maybe a type should not be deleted if used by a volume?
2. If no vol type is passed(None) value, the type is being
assigned as 'None', and returned as a string('None')
3. In the create volume type form, the 'Description' is
empty at the moment, I couldn't find any help info
to add for volume types...
Implements blueprint volume-types
Tested with n-cinder and n-vol services. Since Folsom both
support volume-types. I'm not sure if it is possible a grizzly
Dashboard to work with essex nova, which could be a problem.
Dashboard doesn't seem to provide permissions based on tables,
so if it needs to check if a service is available to show/hide
volume types, this will need some more effors to implement
permissions on table/action level. Or maybe this needs to be
added as a standalone panel?
Patch set 2: implemented suggestions, added one more thing:
When creating a volume from a snapshot, set the volume type
initial as the type of the original volume from which
the snapshot is being created.
Patch Set 3: Updated the description of volume types,
based on the notes from:
https://etherpad.openstack.org/grizzly-cinder-volumetypes
https://etherpad.openstack.org/cinder-usecases
Any feedback on the description is welcome.
Change-Id: Ib0c136c5c8cd9fbd34ce1dd346260f404c96f667
2012-10-25 14:48:27 +03:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
Added support for volume types
As cinder already supports volume types, it's time
to be added in Horizon. The types are added in admin panel.
A volume can either have a *valid* type, or None.
There are two minor issues:
1. When a type is deleted, if there is a volume with
this type, the type is returned as the id,
instead of the name. Which is good as consistency,
but maybe a type should not be deleted if used by a volume?
2. If no vol type is passed(None) value, the type is being
assigned as 'None', and returned as a string('None')
3. In the create volume type form, the 'Description' is
empty at the moment, I couldn't find any help info
to add for volume types...
Implements blueprint volume-types
Tested with n-cinder and n-vol services. Since Folsom both
support volume-types. I'm not sure if it is possible a grizzly
Dashboard to work with essex nova, which could be a problem.
Dashboard doesn't seem to provide permissions based on tables,
so if it needs to check if a service is available to show/hide
volume types, this will need some more effors to implement
permissions on table/action level. Or maybe this needs to be
added as a standalone panel?
Patch set 2: implemented suggestions, added one more thing:
When creating a volume from a snapshot, set the volume type
initial as the type of the original volume from which
the snapshot is being created.
Patch Set 3: Updated the description of volume types,
based on the notes from:
https://etherpad.openstack.org/grizzly-cinder-volumetypes
https://etherpad.openstack.org/cinder-usecases
Any feedback on the description is welcome.
Change-Id: Ib0c136c5c8cd9fbd34ce1dd346260f404c96f667
2012-10-25 14:48:27 +03:00
|
|
|
def volume_type_delete(request, volume_type_id):
|
2015-08-17 19:12:23 +05:30
|
|
|
try:
|
|
|
|
return cinderclient(request).volume_types.delete(volume_type_id)
|
|
|
|
except cinder_exception.BadRequest:
|
|
|
|
raise exceptions.BadRequest(_(
|
|
|
|
"This volume type is used by one or more volumes."))
|
2013-05-16 09:56:24 -06:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2013-12-26 14:53:00 +08:00
|
|
|
def volume_type_get(request, volume_type_id):
|
|
|
|
return cinderclient(request).volume_types.get(volume_type_id)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2013-11-11 09:09:24 -05:00
|
|
|
def volume_encryption_type_create(request, volume_type_id, data):
|
|
|
|
return cinderclient(request).volume_encryption_types.create(volume_type_id,
|
|
|
|
specs=data)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-12-05 12:34:09 -08:00
|
|
|
def volume_encryption_type_delete(request, volume_type_id):
|
|
|
|
return cinderclient(request).volume_encryption_types.delete(volume_type_id)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2013-11-11 09:09:24 -05:00
|
|
|
def volume_encryption_type_get(request, volume_type_id):
|
|
|
|
return cinderclient(request).volume_encryption_types.get(volume_type_id)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2013-11-11 09:09:24 -05:00
|
|
|
def volume_encryption_type_list(request):
|
|
|
|
return cinderclient(request).volume_encryption_types.list()
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-02-07 18:20:32 -05:00
|
|
|
def volume_encryption_type_update(request, volume_type_id, data):
|
|
|
|
return cinderclient(request).volume_encryption_types.update(volume_type_id,
|
|
|
|
specs=data)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2013-12-26 14:53:00 +08:00
|
|
|
def volume_type_extra_get(request, type_id, raw=False):
|
|
|
|
vol_type = volume_type_get(request, type_id)
|
|
|
|
extras = vol_type.get_keys()
|
|
|
|
if raw:
|
|
|
|
return extras
|
|
|
|
return [VolTypeExtraSpec(type_id, key, value) for
|
|
|
|
key, value in extras.items()]
|
|
|
|
|
|
|
|
|
|
|
|
def volume_type_extra_set(request, type_id, metadata):
|
|
|
|
vol_type = volume_type_get(request, type_id)
|
|
|
|
if not metadata:
|
|
|
|
return None
|
|
|
|
return vol_type.set_keys(metadata)
|
|
|
|
|
|
|
|
|
|
|
|
def volume_type_extra_delete(request, type_id, keys):
|
|
|
|
vol_type = volume_type_get(request, type_id)
|
2014-09-05 10:58:41 +02:00
|
|
|
return vol_type.unset_keys(keys)
|
2013-12-26 14:53:00 +08:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-08-01 08:45:20 -07:00
|
|
|
def qos_spec_list(request):
|
|
|
|
return cinderclient(request).qos_specs.list()
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-08-01 08:45:20 -07:00
|
|
|
def qos_spec_get(request, qos_spec_id):
|
|
|
|
return cinderclient(request).qos_specs.get(qos_spec_id)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-08-01 08:45:20 -07:00
|
|
|
def qos_spec_delete(request, qos_spec_id):
|
|
|
|
return cinderclient(request).qos_specs.delete(qos_spec_id, force=True)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-08-11 01:59:06 -07:00
|
|
|
def qos_spec_create(request, name, specs):
|
|
|
|
return cinderclient(request).qos_specs.create(name, specs)
|
2014-08-01 08:45:20 -07:00
|
|
|
|
|
|
|
|
|
|
|
def qos_spec_get_keys(request, qos_spec_id, raw=False):
|
2014-08-04 10:57:02 -07:00
|
|
|
spec = qos_spec_get(request, qos_spec_id)
|
2014-08-01 08:45:20 -07:00
|
|
|
qos_specs = spec.specs
|
|
|
|
if raw:
|
|
|
|
return spec
|
|
|
|
return [QosSpec(qos_spec_id, key, value) for
|
|
|
|
key, value in qos_specs.items()]
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-08-01 08:45:20 -07:00
|
|
|
def qos_spec_set_keys(request, qos_spec_id, specs):
|
|
|
|
return cinderclient(request).qos_specs.set_keys(qos_spec_id, specs)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-08-01 08:45:20 -07:00
|
|
|
def qos_spec_unset_keys(request, qos_spec_id, specs):
|
|
|
|
return cinderclient(request).qos_specs.unset_keys(qos_spec_id, specs)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-08-11 11:05:24 -07:00
|
|
|
def qos_spec_associate(request, qos_specs, vol_type_id):
|
|
|
|
return cinderclient(request).qos_specs.associate(qos_specs, vol_type_id)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-08-11 11:05:24 -07:00
|
|
|
def qos_spec_disassociate(request, qos_specs, vol_type_id):
|
|
|
|
return cinderclient(request).qos_specs.disassociate(qos_specs, vol_type_id)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-08-11 11:05:24 -07:00
|
|
|
def qos_spec_get_associations(request, qos_spec_id):
|
|
|
|
return cinderclient(request).qos_specs.get_associations(qos_spec_id)
|
|
|
|
|
|
|
|
|
2015-10-12 11:15:03 -07:00
|
|
|
def qos_specs_list(request):
|
|
|
|
return [QosSpecs(s) for s in qos_spec_list(request)]
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-07-03 07:52:35 +01:00
|
|
|
@memoized
|
2017-10-22 22:50:42 +00:00
|
|
|
def tenant_absolute_limits(request, tenant_id=None):
|
2019-01-15 04:23:08 +09:00
|
|
|
_cinderclient = _cinderclient_with_features(
|
|
|
|
request, ['limits_project_id_query'],
|
|
|
|
message=('Insufficient microversion for GET limits with '
|
|
|
|
'project_id query. One of the following API micro '
|
|
|
|
'version is required: %(versions)s. '
|
|
|
|
'This causes bug 1810309 on updating quotas.'))
|
2019-01-15 03:34:23 +09:00
|
|
|
limits = _cinderclient.limits.get(tenant_id=tenant_id).absolute
|
2013-05-16 09:56:24 -06:00
|
|
|
limits_dict = {}
|
|
|
|
for limit in limits:
|
2014-10-28 13:02:15 +00:00
|
|
|
if limit.value < 0:
|
|
|
|
# In some cases, the absolute limits data in Cinder can get
|
|
|
|
# out of sync causing the total.*Used limits to return
|
|
|
|
# negative values instead of 0. For such cases, replace
|
|
|
|
# negative values with 0.
|
|
|
|
if limit.name.startswith('total') and limit.name.endswith('Used'):
|
|
|
|
limits_dict[limit.name] = 0
|
|
|
|
else:
|
|
|
|
# -1 is used to represent unlimited quotas
|
|
|
|
limits_dict[limit.name] = float("inf")
|
2013-05-16 09:56:24 -06:00
|
|
|
else:
|
|
|
|
limits_dict[limit.name] = limit.value
|
|
|
|
return limits_dict
|
2013-09-25 11:47:10 -05:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2014-05-27 15:08:57 -03:00
|
|
|
def service_list(request):
|
|
|
|
return cinderclient(request).services.list()
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2013-09-25 11:47:10 -05:00
|
|
|
def availability_zone_list(request, detailed=False):
|
|
|
|
return cinderclient(request).availability_zones.list(detailed=detailed)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2018-09-25 11:40:02 +02:00
|
|
|
@memoized
|
|
|
|
def list_extensions(request):
|
|
|
|
cinder_api = cinderclient(request)
|
2016-05-10 14:52:24 -05:00
|
|
|
return tuple(cinder_list_extensions.ListExtManager(cinder_api).show_all())
|
2013-09-25 11:47:10 -05:00
|
|
|
|
|
|
|
|
2018-09-25 11:40:02 +02:00
|
|
|
@memoized
|
|
|
|
def extension_supported(request, extension_name):
|
2017-06-09 10:47:12 +00:00
|
|
|
"""This method will determine if Cinder supports a given extension name."""
|
2018-09-25 11:40:02 +02:00
|
|
|
for extension in list_extensions(request):
|
2013-09-25 11:47:10 -05:00
|
|
|
if extension.name == extension_name:
|
|
|
|
return True
|
|
|
|
return False
|
Add support for volume transfers
Cinder supports volume transfers, which are transfers of ownership from
one project to another. The normal flow is that a donor creates a volume
transfer, captures the resulting transfer id and secret authentication
key, and passes that information out of band to the recipient (such as
by email, text message, etc.). The recipient then accepts the transfer,
supplying the transfer id and authentication key. The ownership of the
volume is then transferred from the donor to the recipient, and the
volome is no longer visible to the donor.
It is important to know of some limitations about the cinder API for
volume transfers and their impact on the UI design.
1. When creating a volume transfer, you cannot specify who the intended
recipient will be, and anyone with the transfer ID and auth key can
claim the volume. Therefore there is no UI to prompt for a
recipient.
2. Current volume transfers are only visible to the donor; users in
other projects are unable to view these transfers. This makes it
pointless to create a project table to view and accept volume
transfers, since the current transfers are not visible. Instead, the
transfer information has been added to the volume details, which are
visible by the donor, and the volume state clearly reflects that a
transfer has been created. It it also impossible to present to the
recipient a pull-down list of transfers to accept.
3. The only time that the authorization key is visible to the donor is
in the response from the creation of the transfer; after creation it
is impossible for even the donor to recover it. Since the donor must
capture the transfer ID and authorization key in order to send it to
the recipient, an extra form was created to present this information
to the donor immediately after the transfer has been created. It is
not enough to put the information in a success message, since these
are typically only displayed for a small number of seconds before
they disappear.
Co-Authored-By: Gary W. Smith <gary.w.smith@hp.com>
Co-Authored-By: Julie Gravel <julie.gravel@hp.com>
Implements blueprint cinder-volume-transfer
Change-Id: I0134f90c93a8d804d2c87fe9713bcef9e1629d79
2014-07-31 16:35:05 -07:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
Add support for volume transfers
Cinder supports volume transfers, which are transfers of ownership from
one project to another. The normal flow is that a donor creates a volume
transfer, captures the resulting transfer id and secret authentication
key, and passes that information out of band to the recipient (such as
by email, text message, etc.). The recipient then accepts the transfer,
supplying the transfer id and authentication key. The ownership of the
volume is then transferred from the donor to the recipient, and the
volome is no longer visible to the donor.
It is important to know of some limitations about the cinder API for
volume transfers and their impact on the UI design.
1. When creating a volume transfer, you cannot specify who the intended
recipient will be, and anyone with the transfer ID and auth key can
claim the volume. Therefore there is no UI to prompt for a
recipient.
2. Current volume transfers are only visible to the donor; users in
other projects are unable to view these transfers. This makes it
pointless to create a project table to view and accept volume
transfers, since the current transfers are not visible. Instead, the
transfer information has been added to the volume details, which are
visible by the donor, and the volume state clearly reflects that a
transfer has been created. It it also impossible to present to the
recipient a pull-down list of transfers to accept.
3. The only time that the authorization key is visible to the donor is
in the response from the creation of the transfer; after creation it
is impossible for even the donor to recover it. Since the donor must
capture the transfer ID and authorization key in order to send it to
the recipient, an extra form was created to present this information
to the donor immediately after the transfer has been created. It is
not enough to put the information in a success message, since these
are typically only displayed for a small number of seconds before
they disappear.
Co-Authored-By: Gary W. Smith <gary.w.smith@hp.com>
Co-Authored-By: Julie Gravel <julie.gravel@hp.com>
Implements blueprint cinder-volume-transfer
Change-Id: I0134f90c93a8d804d2c87fe9713bcef9e1629d79
2014-07-31 16:35:05 -07:00
|
|
|
def transfer_list(request, detailed=True, search_opts=None):
|
2017-06-09 10:47:12 +00:00
|
|
|
"""List volume transfers.
|
|
|
|
|
|
|
|
To see all volumes transfers as an admin pass in a special
|
Add support for volume transfers
Cinder supports volume transfers, which are transfers of ownership from
one project to another. The normal flow is that a donor creates a volume
transfer, captures the resulting transfer id and secret authentication
key, and passes that information out of band to the recipient (such as
by email, text message, etc.). The recipient then accepts the transfer,
supplying the transfer id and authentication key. The ownership of the
volume is then transferred from the donor to the recipient, and the
volome is no longer visible to the donor.
It is important to know of some limitations about the cinder API for
volume transfers and their impact on the UI design.
1. When creating a volume transfer, you cannot specify who the intended
recipient will be, and anyone with the transfer ID and auth key can
claim the volume. Therefore there is no UI to prompt for a
recipient.
2. Current volume transfers are only visible to the donor; users in
other projects are unable to view these transfers. This makes it
pointless to create a project table to view and accept volume
transfers, since the current transfers are not visible. Instead, the
transfer information has been added to the volume details, which are
visible by the donor, and the volume state clearly reflects that a
transfer has been created. It it also impossible to present to the
recipient a pull-down list of transfers to accept.
3. The only time that the authorization key is visible to the donor is
in the response from the creation of the transfer; after creation it
is impossible for even the donor to recover it. Since the donor must
capture the transfer ID and authorization key in order to send it to
the recipient, an extra form was created to present this information
to the donor immediately after the transfer has been created. It is
not enough to put the information in a success message, since these
are typically only displayed for a small number of seconds before
they disappear.
Co-Authored-By: Gary W. Smith <gary.w.smith@hp.com>
Co-Authored-By: Julie Gravel <julie.gravel@hp.com>
Implements blueprint cinder-volume-transfer
Change-Id: I0134f90c93a8d804d2c87fe9713bcef9e1629d79
2014-07-31 16:35:05 -07:00
|
|
|
search option: {'all_tenants': 1}
|
|
|
|
"""
|
|
|
|
c_client = cinderclient(request)
|
2016-02-08 08:39:50 +01:00
|
|
|
try:
|
|
|
|
return [VolumeTransfer(v) for v in c_client.transfers.list(
|
|
|
|
detailed=detailed, search_opts=search_opts)]
|
|
|
|
except cinder_exception.Forbidden as error:
|
|
|
|
LOG.error(error)
|
|
|
|
return []
|
Add support for volume transfers
Cinder supports volume transfers, which are transfers of ownership from
one project to another. The normal flow is that a donor creates a volume
transfer, captures the resulting transfer id and secret authentication
key, and passes that information out of band to the recipient (such as
by email, text message, etc.). The recipient then accepts the transfer,
supplying the transfer id and authentication key. The ownership of the
volume is then transferred from the donor to the recipient, and the
volome is no longer visible to the donor.
It is important to know of some limitations about the cinder API for
volume transfers and their impact on the UI design.
1. When creating a volume transfer, you cannot specify who the intended
recipient will be, and anyone with the transfer ID and auth key can
claim the volume. Therefore there is no UI to prompt for a
recipient.
2. Current volume transfers are only visible to the donor; users in
other projects are unable to view these transfers. This makes it
pointless to create a project table to view and accept volume
transfers, since the current transfers are not visible. Instead, the
transfer information has been added to the volume details, which are
visible by the donor, and the volume state clearly reflects that a
transfer has been created. It it also impossible to present to the
recipient a pull-down list of transfers to accept.
3. The only time that the authorization key is visible to the donor is
in the response from the creation of the transfer; after creation it
is impossible for even the donor to recover it. Since the donor must
capture the transfer ID and authorization key in order to send it to
the recipient, an extra form was created to present this information
to the donor immediately after the transfer has been created. It is
not enough to put the information in a success message, since these
are typically only displayed for a small number of seconds before
they disappear.
Co-Authored-By: Gary W. Smith <gary.w.smith@hp.com>
Co-Authored-By: Julie Gravel <julie.gravel@hp.com>
Implements blueprint cinder-volume-transfer
Change-Id: I0134f90c93a8d804d2c87fe9713bcef9e1629d79
2014-07-31 16:35:05 -07:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
Add support for volume transfers
Cinder supports volume transfers, which are transfers of ownership from
one project to another. The normal flow is that a donor creates a volume
transfer, captures the resulting transfer id and secret authentication
key, and passes that information out of band to the recipient (such as
by email, text message, etc.). The recipient then accepts the transfer,
supplying the transfer id and authentication key. The ownership of the
volume is then transferred from the donor to the recipient, and the
volome is no longer visible to the donor.
It is important to know of some limitations about the cinder API for
volume transfers and their impact on the UI design.
1. When creating a volume transfer, you cannot specify who the intended
recipient will be, and anyone with the transfer ID and auth key can
claim the volume. Therefore there is no UI to prompt for a
recipient.
2. Current volume transfers are only visible to the donor; users in
other projects are unable to view these transfers. This makes it
pointless to create a project table to view and accept volume
transfers, since the current transfers are not visible. Instead, the
transfer information has been added to the volume details, which are
visible by the donor, and the volume state clearly reflects that a
transfer has been created. It it also impossible to present to the
recipient a pull-down list of transfers to accept.
3. The only time that the authorization key is visible to the donor is
in the response from the creation of the transfer; after creation it
is impossible for even the donor to recover it. Since the donor must
capture the transfer ID and authorization key in order to send it to
the recipient, an extra form was created to present this information
to the donor immediately after the transfer has been created. It is
not enough to put the information in a success message, since these
are typically only displayed for a small number of seconds before
they disappear.
Co-Authored-By: Gary W. Smith <gary.w.smith@hp.com>
Co-Authored-By: Julie Gravel <julie.gravel@hp.com>
Implements blueprint cinder-volume-transfer
Change-Id: I0134f90c93a8d804d2c87fe9713bcef9e1629d79
2014-07-31 16:35:05 -07:00
|
|
|
def transfer_get(request, transfer_id):
|
|
|
|
transfer_data = cinderclient(request).transfers.get(transfer_id)
|
|
|
|
return VolumeTransfer(transfer_data)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
Add support for volume transfers
Cinder supports volume transfers, which are transfers of ownership from
one project to another. The normal flow is that a donor creates a volume
transfer, captures the resulting transfer id and secret authentication
key, and passes that information out of band to the recipient (such as
by email, text message, etc.). The recipient then accepts the transfer,
supplying the transfer id and authentication key. The ownership of the
volume is then transferred from the donor to the recipient, and the
volome is no longer visible to the donor.
It is important to know of some limitations about the cinder API for
volume transfers and their impact on the UI design.
1. When creating a volume transfer, you cannot specify who the intended
recipient will be, and anyone with the transfer ID and auth key can
claim the volume. Therefore there is no UI to prompt for a
recipient.
2. Current volume transfers are only visible to the donor; users in
other projects are unable to view these transfers. This makes it
pointless to create a project table to view and accept volume
transfers, since the current transfers are not visible. Instead, the
transfer information has been added to the volume details, which are
visible by the donor, and the volume state clearly reflects that a
transfer has been created. It it also impossible to present to the
recipient a pull-down list of transfers to accept.
3. The only time that the authorization key is visible to the donor is
in the response from the creation of the transfer; after creation it
is impossible for even the donor to recover it. Since the donor must
capture the transfer ID and authorization key in order to send it to
the recipient, an extra form was created to present this information
to the donor immediately after the transfer has been created. It is
not enough to put the information in a success message, since these
are typically only displayed for a small number of seconds before
they disappear.
Co-Authored-By: Gary W. Smith <gary.w.smith@hp.com>
Co-Authored-By: Julie Gravel <julie.gravel@hp.com>
Implements blueprint cinder-volume-transfer
Change-Id: I0134f90c93a8d804d2c87fe9713bcef9e1629d79
2014-07-31 16:35:05 -07:00
|
|
|
def transfer_create(request, transfer_id, name):
|
|
|
|
volume = cinderclient(request).transfers.create(transfer_id, name)
|
|
|
|
return VolumeTransfer(volume)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
Add support for volume transfers
Cinder supports volume transfers, which are transfers of ownership from
one project to another. The normal flow is that a donor creates a volume
transfer, captures the resulting transfer id and secret authentication
key, and passes that information out of band to the recipient (such as
by email, text message, etc.). The recipient then accepts the transfer,
supplying the transfer id and authentication key. The ownership of the
volume is then transferred from the donor to the recipient, and the
volome is no longer visible to the donor.
It is important to know of some limitations about the cinder API for
volume transfers and their impact on the UI design.
1. When creating a volume transfer, you cannot specify who the intended
recipient will be, and anyone with the transfer ID and auth key can
claim the volume. Therefore there is no UI to prompt for a
recipient.
2. Current volume transfers are only visible to the donor; users in
other projects are unable to view these transfers. This makes it
pointless to create a project table to view and accept volume
transfers, since the current transfers are not visible. Instead, the
transfer information has been added to the volume details, which are
visible by the donor, and the volume state clearly reflects that a
transfer has been created. It it also impossible to present to the
recipient a pull-down list of transfers to accept.
3. The only time that the authorization key is visible to the donor is
in the response from the creation of the transfer; after creation it
is impossible for even the donor to recover it. Since the donor must
capture the transfer ID and authorization key in order to send it to
the recipient, an extra form was created to present this information
to the donor immediately after the transfer has been created. It is
not enough to put the information in a success message, since these
are typically only displayed for a small number of seconds before
they disappear.
Co-Authored-By: Gary W. Smith <gary.w.smith@hp.com>
Co-Authored-By: Julie Gravel <julie.gravel@hp.com>
Implements blueprint cinder-volume-transfer
Change-Id: I0134f90c93a8d804d2c87fe9713bcef9e1629d79
2014-07-31 16:35:05 -07:00
|
|
|
def transfer_accept(request, transfer_id, auth_key):
|
|
|
|
return cinderclient(request).transfers.accept(transfer_id, auth_key)
|
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
Add support for volume transfers
Cinder supports volume transfers, which are transfers of ownership from
one project to another. The normal flow is that a donor creates a volume
transfer, captures the resulting transfer id and secret authentication
key, and passes that information out of band to the recipient (such as
by email, text message, etc.). The recipient then accepts the transfer,
supplying the transfer id and authentication key. The ownership of the
volume is then transferred from the donor to the recipient, and the
volome is no longer visible to the donor.
It is important to know of some limitations about the cinder API for
volume transfers and their impact on the UI design.
1. When creating a volume transfer, you cannot specify who the intended
recipient will be, and anyone with the transfer ID and auth key can
claim the volume. Therefore there is no UI to prompt for a
recipient.
2. Current volume transfers are only visible to the donor; users in
other projects are unable to view these transfers. This makes it
pointless to create a project table to view and accept volume
transfers, since the current transfers are not visible. Instead, the
transfer information has been added to the volume details, which are
visible by the donor, and the volume state clearly reflects that a
transfer has been created. It it also impossible to present to the
recipient a pull-down list of transfers to accept.
3. The only time that the authorization key is visible to the donor is
in the response from the creation of the transfer; after creation it
is impossible for even the donor to recover it. Since the donor must
capture the transfer ID and authorization key in order to send it to
the recipient, an extra form was created to present this information
to the donor immediately after the transfer has been created. It is
not enough to put the information in a success message, since these
are typically only displayed for a small number of seconds before
they disappear.
Co-Authored-By: Gary W. Smith <gary.w.smith@hp.com>
Co-Authored-By: Julie Gravel <julie.gravel@hp.com>
Implements blueprint cinder-volume-transfer
Change-Id: I0134f90c93a8d804d2c87fe9713bcef9e1629d79
2014-07-31 16:35:05 -07:00
|
|
|
def transfer_delete(request, transfer_id):
|
|
|
|
return cinderclient(request).transfers.delete(transfer_id)
|
2015-01-15 17:20:35 +00:00
|
|
|
|
|
|
|
|
2016-07-08 19:04:42 +03:00
|
|
|
@profiler.trace
|
2015-01-15 17:20:35 +00:00
|
|
|
def pool_list(request, detailed=False):
|
|
|
|
c_client = cinderclient(request)
|
|
|
|
if c_client is None:
|
|
|
|
return []
|
|
|
|
|
|
|
|
return [VolumePool(v) for v in c_client.pools.list(
|
|
|
|
detailed=detailed)]
|
2015-01-29 12:05:04 +09:00
|
|
|
|
|
|
|
|
2017-03-16 18:27:03 +01:00
|
|
|
@profiler.trace
|
|
|
|
def message_list(request, search_opts=None):
|
2019-01-15 04:23:08 +09:00
|
|
|
try:
|
|
|
|
c_client = _cinderclient_with_features(request, ['message_list'],
|
|
|
|
raise_exc=True, message=True)
|
|
|
|
except microversions.MicroVersionNotFound:
|
|
|
|
LOG.warning("Insufficient microversion for message_list")
|
2017-03-16 18:27:03 +01:00
|
|
|
return []
|
|
|
|
return c_client.messages.list(search_opts)
|
|
|
|
|
|
|
|
|
2015-01-29 12:05:04 +09:00
|
|
|
def is_volume_service_enabled(request):
|
|
|
|
return bool(
|
2017-12-13 21:21:48 +02:00
|
|
|
base.is_service_enabled(request, 'volumev3') or
|
2017-03-16 18:27:03 +01:00
|
|
|
base.is_service_enabled(request, 'volumev2') or
|
2017-12-13 21:21:48 +02:00
|
|
|
base.is_service_enabled(request, 'volume')
|
2015-01-29 12:05:04 +09:00
|
|
|
)
|
2015-09-09 15:11:40 +08:00
|
|
|
|
|
|
|
|
|
|
|
def volume_type_access_list(request, volume_type):
|
|
|
|
return cinderclient(request).volume_type_access.list(volume_type)
|
|
|
|
|
|
|
|
|
|
|
|
def volume_type_add_project_access(request, volume_type, project_id):
|
|
|
|
return cinderclient(request).volume_type_access.add_project_access(
|
|
|
|
volume_type, project_id)
|
|
|
|
|
|
|
|
|
|
|
|
def volume_type_remove_project_access(request, volume_type, project_id):
|
|
|
|
return cinderclient(request).volume_type_access.remove_project_access(
|
|
|
|
volume_type, project_id)
|
2018-01-08 10:43:49 +09:00
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
|
|
|
def group_type_list(request):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
return [GroupType(t) for t in client.group_types.list()]
|
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
|
|
|
def group_type_get(request, group_type_id):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
return GroupType(client.group_types.get(group_type_id))
|
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
|
|
|
def group_type_create(request, name, description=None, is_public=None):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
params = {'name': name}
|
|
|
|
if description is not None:
|
|
|
|
params['description'] = description
|
|
|
|
if is_public is not None:
|
|
|
|
params['is_public'] = is_public
|
|
|
|
return GroupType(client.group_types.create(**params))
|
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
2019-02-06 18:44:35 +00:00
|
|
|
def group_type_update(request, group_type_id, name=None, description=None,
|
|
|
|
is_public=None):
|
2018-01-08 10:43:49 +09:00
|
|
|
client = _cinderclient_with_generic_groups(request)
|
2019-02-06 18:44:35 +00:00
|
|
|
return GroupType(client.group_types.update(group_type_id,
|
|
|
|
name,
|
|
|
|
description,
|
|
|
|
is_public))
|
2018-01-08 10:43:49 +09:00
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
|
|
|
def group_type_delete(request, group_type_id):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
client.group_types.delete(group_type_id)
|
|
|
|
|
|
|
|
|
2019-02-19 09:05:11 +00:00
|
|
|
@profiler.trace
|
|
|
|
def group_type_spec_list(request, group_type_id, raw=False):
|
|
|
|
group_type = group_type_get(request, group_type_id)
|
|
|
|
specs = group_type._apiresource.get_keys()
|
|
|
|
if raw:
|
|
|
|
return specs
|
|
|
|
return [GroupTypeSpec(group_type_id, key, value) for
|
|
|
|
key, value in specs.items()]
|
|
|
|
|
|
|
|
|
2018-01-08 10:43:49 +09:00
|
|
|
@profiler.trace
|
|
|
|
def group_type_spec_set(request, group_type_id, metadata):
|
2019-02-19 09:05:11 +00:00
|
|
|
group_type = group_type_get(request, group_type_id)
|
|
|
|
if not metadata:
|
|
|
|
return None
|
|
|
|
return group_type._apiresource.set_keys(metadata)
|
2018-01-08 10:43:49 +09:00
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
|
|
|
def group_type_spec_unset(request, group_type_id, keys):
|
2019-02-19 09:05:11 +00:00
|
|
|
group_type = group_type_get(request, group_type_id)
|
|
|
|
return group_type._apiresource.unset_keys(keys)
|
2018-01-08 10:43:49 +09:00
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
|
|
|
def group_list(request, search_opts=None):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
return [Group(g) for g in client.groups.list(search_opts=search_opts)]
|
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
|
|
|
def group_list_with_vol_type_names(request, search_opts=None):
|
|
|
|
groups = group_list(request, search_opts)
|
|
|
|
vol_types = volume_type_list(request)
|
|
|
|
for group in groups:
|
|
|
|
group.volume_type_names = []
|
|
|
|
for vol_type_id in group.volume_types:
|
|
|
|
for vol_type in vol_types:
|
|
|
|
if vol_type.id == vol_type_id:
|
|
|
|
group.volume_type_names.append(vol_type.name)
|
|
|
|
break
|
|
|
|
|
|
|
|
return groups
|
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
|
|
|
def group_get(request, group_id):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
group = client.groups.get(group_id)
|
|
|
|
return Group(group)
|
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
|
|
|
def group_get_with_vol_type_names(request, group_id):
|
|
|
|
group = group_get(request, group_id)
|
|
|
|
vol_types = volume_type_list(request)
|
|
|
|
group.volume_type_names = []
|
|
|
|
for vol_type_id in group.volume_types:
|
|
|
|
for vol_type in vol_types:
|
|
|
|
if vol_type.id == vol_type_id:
|
|
|
|
group.volume_type_names.append(vol_type.name)
|
|
|
|
break
|
|
|
|
return group
|
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
|
|
|
def group_create(request, name, group_type, volume_types,
|
|
|
|
description=None, availability_zone=None):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
params = {'name': name,
|
|
|
|
'group_type': group_type,
|
|
|
|
# cinderclient expects a comma-separated list of volume types.
|
|
|
|
'volume_types': ','.join(volume_types)}
|
|
|
|
if description is not None:
|
|
|
|
params['description'] = description
|
|
|
|
if availability_zone is not None:
|
|
|
|
params['availability_zone'] = availability_zone
|
|
|
|
return Group(client.groups.create(**params))
|
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
|
|
|
def group_create_from_source(request, name, group_snapshot_id=None,
|
|
|
|
source_group_id=None, description=None,
|
|
|
|
user_id=None, project_id=None):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
return Group(client.groups.create_from_src(
|
|
|
|
group_snapshot_id, source_group_id, name, description,
|
|
|
|
user_id, project_id))
|
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
|
|
|
def group_delete(request, group_id, delete_volumes=False):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
client.groups.delete(group_id, delete_volumes)
|
|
|
|
|
|
|
|
|
|
|
|
@profiler.trace
|
|
|
|
def group_update(request, group_id, name=None, description=None,
|
|
|
|
add_volumes=None, remove_volumes=None):
|
|
|
|
data = {}
|
|
|
|
if name is not None:
|
|
|
|
data['name'] = name
|
|
|
|
if description is not None:
|
|
|
|
data['description'] = description
|
|
|
|
if add_volumes:
|
|
|
|
# cinderclient expects a comma-separated list of volume types.
|
|
|
|
data['add_volumes'] = ','.join(add_volumes)
|
|
|
|
if remove_volumes:
|
|
|
|
# cinderclient expects a comma-separated list of volume types.
|
|
|
|
data['remove_volumes'] = ','.join(remove_volumes)
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
return client.groups.update(group_id, **data)
|
|
|
|
|
|
|
|
|
|
|
|
def group_snapshot_create(request, group_id, name, description=None):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
return GroupSnapshot(client.group_snapshots.create(group_id, name,
|
|
|
|
description))
|
|
|
|
|
|
|
|
|
|
|
|
def group_snapshot_get(request, group_snapshot_id):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
return GroupSnapshot(client.group_snapshots.get(group_snapshot_id))
|
|
|
|
|
|
|
|
|
|
|
|
def group_snapshot_list(request, search_opts=None):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
return [GroupSnapshot(s) for s
|
|
|
|
in client.group_snapshots.list(search_opts=search_opts)]
|
|
|
|
|
|
|
|
|
|
|
|
def group_snapshot_delete(request, group_snapshot_id):
|
|
|
|
client = _cinderclient_with_generic_groups(request)
|
|
|
|
client.group_snapshots.delete(group_snapshot_id)
|