Implement qos support
This patch enables Cinder v1/v2 QoS API support, adding following subcommands to cinder client: * create QoS Specs cinder qos-create <name> <key=value> [<key=value> ...] * delete QoS Specs cinder qos-delete [--force <True|False>] <qos_specs> 'force' is a flag indicates whether to delete a 'in-use' qos specs, which is still associated with other entities (e.g. volume types). * update QoS Specs - add new key/value pairs or update existing key/value cinder qos-key <qos_specs_id> set key=value [key=value ...] - delete key/value pairs cinder qos-key <qos_specs id> unset key [key ...] * associate QoS Specs with specified volume type cinder qos-associate <qos_specs_id> <volume_type_id> * disassociate QoS Specs from specified volume type cinder qos-disassociate <qos_specs_id> <volume_type_id> * disassociate QoS Specs from all associated volume types cinder qos-disassociate-all <qos_specs> * query entities that are associated with specified QoS Specs cinder qos-get-associations <qos_specs_id> * list all QoS Specs cinder qos-list DocImpact Change-Id: Ie1ddd29fede8660b475bac14c4fc35496d5fe0bc
This commit is contained in:
parent
5ad95e9fd2
commit
87628cc485
@ -116,6 +116,34 @@ def _stub_restore():
|
|||||||
return {'volume_id': '712f4980-5ac1-41e5-9383-390aa7c9f58b'}
|
return {'volume_id': '712f4980-5ac1-41e5-9383-390aa7c9f58b'}
|
||||||
|
|
||||||
|
|
||||||
|
def _stub_qos_full(id, base_uri, tenant_id, name=None, specs=None):
|
||||||
|
if not name:
|
||||||
|
name = 'fake-name'
|
||||||
|
if not specs:
|
||||||
|
specs = {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
'qos_specs': {
|
||||||
|
'id': id,
|
||||||
|
'name': name,
|
||||||
|
'consumer': 'back-end',
|
||||||
|
'specs': specs,
|
||||||
|
},
|
||||||
|
'links': {
|
||||||
|
'href': _bookmark_href(base_uri, tenant_id, id),
|
||||||
|
'rel': 'bookmark'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _stub_qos_associates(id, name):
|
||||||
|
return {
|
||||||
|
'assoications_type': 'volume_type',
|
||||||
|
'name': name,
|
||||||
|
'id': id,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _stub_transfer_full(id, base_uri, tenant_id):
|
def _stub_transfer_full(id, base_uri, tenant_id):
|
||||||
return {
|
return {
|
||||||
'id': id,
|
'id': id,
|
||||||
@ -505,6 +533,68 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
return (200, {},
|
return (200, {},
|
||||||
{'restore': _stub_restore()})
|
{'restore': _stub_restore()})
|
||||||
|
|
||||||
|
#
|
||||||
|
# QoSSpecs
|
||||||
|
#
|
||||||
|
|
||||||
|
def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C(self, **kw):
|
||||||
|
base_uri = 'http://localhost:8776'
|
||||||
|
tenant_id = '0fa851f6668144cf9cd8c8419c1646c1'
|
||||||
|
qos_id1 = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
return (200, {},
|
||||||
|
_stub_qos_full(qos_id1, base_uri, tenant_id))
|
||||||
|
|
||||||
|
def get_qos_specs(self, **kw):
|
||||||
|
base_uri = 'http://localhost:8776'
|
||||||
|
tenant_id = '0fa851f6668144cf9cd8c8419c1646c1'
|
||||||
|
qos_id1 = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
qos_id2 = '0FD8DD14-A396-4E55-9573-1FE59042E95B'
|
||||||
|
return (200, {},
|
||||||
|
{'qos_specs': [
|
||||||
|
_stub_qos_full(qos_id1, base_uri, tenant_id, 'name-1'),
|
||||||
|
_stub_qos_full(qos_id2, base_uri, tenant_id)]})
|
||||||
|
|
||||||
|
def post_qos_specs(self, **kw):
|
||||||
|
base_uri = 'http://localhost:8776'
|
||||||
|
tenant_id = '0fa851f6668144cf9cd8c8419c1646c1'
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
qos_name = 'qos-name'
|
||||||
|
return (202, {},
|
||||||
|
_stub_qos_full(qos_id, base_uri, tenant_id, qos_name))
|
||||||
|
|
||||||
|
def put_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C(self, **kw):
|
||||||
|
return (202, {}, None)
|
||||||
|
|
||||||
|
def put_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_delete_keys(
|
||||||
|
self, **kw):
|
||||||
|
return (202, {}, None)
|
||||||
|
|
||||||
|
def delete_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C(self, **kw):
|
||||||
|
return (202, {}, None)
|
||||||
|
|
||||||
|
def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_associations(
|
||||||
|
self, **kw):
|
||||||
|
type_id1 = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF'
|
||||||
|
type_id2 = '4230B13A-AB37-4E84-B777-EFBA6FCEE4FF'
|
||||||
|
type_name1 = 'type1'
|
||||||
|
type_name2 = 'type2'
|
||||||
|
return (202, {},
|
||||||
|
{'qos_associations': [
|
||||||
|
_stub_qos_associates(type_id1, type_name1),
|
||||||
|
_stub_qos_associates(type_id2, type_name2)]})
|
||||||
|
|
||||||
|
def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_associate(
|
||||||
|
self, **kw):
|
||||||
|
return (202, {}, None)
|
||||||
|
|
||||||
|
def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_disassociate(
|
||||||
|
self, **kw):
|
||||||
|
return (202, {}, None)
|
||||||
|
|
||||||
|
def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_disassociate_all(
|
||||||
|
self, **kw):
|
||||||
|
return (202, {}, None)
|
||||||
|
|
||||||
#
|
#
|
||||||
# VolumeTransfers
|
# VolumeTransfers
|
||||||
#
|
#
|
||||||
|
79
cinderclient/tests/v1/test_qos.py
Normal file
79
cinderclient/tests/v1/test_qos.py
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# Copyright (C) 2013 eBay Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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 cinderclient.tests import utils
|
||||||
|
from cinderclient.tests.v1 import fakes
|
||||||
|
|
||||||
|
|
||||||
|
cs = fakes.FakeClient()
|
||||||
|
|
||||||
|
|
||||||
|
class QoSSpecsTest(utils.TestCase):
|
||||||
|
|
||||||
|
def test_create(self):
|
||||||
|
specs = dict(k1='v1', k2='v2')
|
||||||
|
cs.qos_specs.create('qos-name', specs)
|
||||||
|
cs.assert_called('POST', '/qos-specs')
|
||||||
|
|
||||||
|
def test_get(self):
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
cs.qos_specs.get(qos_id)
|
||||||
|
cs.assert_called('GET', '/qos-specs/%s' % qos_id)
|
||||||
|
|
||||||
|
def test_list(self):
|
||||||
|
cs.qos_specs.list()
|
||||||
|
cs.assert_called('GET', '/qos-specs')
|
||||||
|
|
||||||
|
def test_delete(self):
|
||||||
|
cs.qos_specs.delete('1B6B6A04-A927-4AEB-810B-B7BAAD49F57C')
|
||||||
|
cs.assert_called('DELETE',
|
||||||
|
'/qos-specs/1B6B6A04-A927-4AEB-810B-B7BAAD49F57C?'
|
||||||
|
'force=False')
|
||||||
|
|
||||||
|
def test_set_keys(self):
|
||||||
|
body = {'qos_specs': dict(k1='v1')}
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
cs.qos_specs.set_keys(qos_id, body)
|
||||||
|
cs.assert_called('PUT', '/qos-specs/%s' % qos_id)
|
||||||
|
|
||||||
|
def test_unset_keys(self):
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
body = {'keys': ['k1']}
|
||||||
|
cs.qos_specs.unset_keys(qos_id, body)
|
||||||
|
cs.assert_called('PUT', '/qos-specs/%s/delete_keys' % qos_id)
|
||||||
|
|
||||||
|
def test_get_associations(self):
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
cs.qos_specs.get_associations(qos_id)
|
||||||
|
cs.assert_called('GET', '/qos-specs/%s/associations' % qos_id)
|
||||||
|
|
||||||
|
def test_associate(self):
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
type_id = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF'
|
||||||
|
cs.qos_specs.associate(qos_id, type_id)
|
||||||
|
cs.assert_called('GET', '/qos-specs/%s/associate?vol_type_id=%s'
|
||||||
|
% (qos_id, type_id))
|
||||||
|
|
||||||
|
def test_disassociate(self):
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
type_id = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF'
|
||||||
|
cs.qos_specs.disassociate(qos_id, type_id)
|
||||||
|
cs.assert_called('GET', '/qos-specs/%s/disassociate?vol_type_id=%s'
|
||||||
|
% (qos_id, type_id))
|
||||||
|
|
||||||
|
def test_disassociate_all(self):
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
cs.qos_specs.disassociate_all(qos_id)
|
||||||
|
cs.assert_called('GET', '/qos-specs/%s/disassociate_all' % qos_id)
|
@ -119,6 +119,34 @@ def _stub_backup(id, base_uri, tenant_id):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _stub_qos_full(id, base_uri, tenant_id, name=None, specs=None):
|
||||||
|
if not name:
|
||||||
|
name = 'fake-name'
|
||||||
|
if not specs:
|
||||||
|
specs = {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
'qos_specs': {
|
||||||
|
'id': id,
|
||||||
|
'name': name,
|
||||||
|
'consumer': 'back-end',
|
||||||
|
'specs': specs,
|
||||||
|
},
|
||||||
|
'links': {
|
||||||
|
'href': _bookmark_href(base_uri, tenant_id, id),
|
||||||
|
'rel': 'bookmark'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _stub_qos_associates(id, name):
|
||||||
|
return {
|
||||||
|
'assoications_type': 'volume_type',
|
||||||
|
'name': name,
|
||||||
|
'id': id,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _stub_restore():
|
def _stub_restore():
|
||||||
return {'volume_id': '712f4980-5ac1-41e5-9383-390aa7c9f58b'}
|
return {'volume_id': '712f4980-5ac1-41e5-9383-390aa7c9f58b'}
|
||||||
|
|
||||||
@ -512,6 +540,69 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
return (200, {},
|
return (200, {},
|
||||||
{'restore': _stub_restore()})
|
{'restore': _stub_restore()})
|
||||||
|
|
||||||
|
#
|
||||||
|
# QoSSpecs
|
||||||
|
#
|
||||||
|
|
||||||
|
def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C(self, **kw):
|
||||||
|
base_uri = 'http://localhost:8776'
|
||||||
|
tenant_id = '0fa851f6668144cf9cd8c8419c1646c1'
|
||||||
|
qos_id1 = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
return (200, {},
|
||||||
|
_stub_qos_full(qos_id1, base_uri, tenant_id))
|
||||||
|
|
||||||
|
def get_qos_specs(self, **kw):
|
||||||
|
base_uri = 'http://localhost:8776'
|
||||||
|
tenant_id = '0fa851f6668144cf9cd8c8419c1646c1'
|
||||||
|
qos_id1 = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
qos_id2 = '0FD8DD14-A396-4E55-9573-1FE59042E95B'
|
||||||
|
return (200, {},
|
||||||
|
{'qos_specs': [
|
||||||
|
_stub_qos_full(qos_id1, base_uri, tenant_id, 'name-1'),
|
||||||
|
_stub_qos_full(qos_id2, base_uri, tenant_id)]})
|
||||||
|
|
||||||
|
def post_qos_specs(self, **kw):
|
||||||
|
base_uri = 'http://localhost:8776'
|
||||||
|
tenant_id = '0fa851f6668144cf9cd8c8419c1646c1'
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
qos_name = 'qos-name'
|
||||||
|
return (202, {},
|
||||||
|
_stub_qos_full(qos_id, base_uri, tenant_id, qos_name))
|
||||||
|
|
||||||
|
def put_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C(self, **kw):
|
||||||
|
return (202, {}, None)
|
||||||
|
|
||||||
|
def put_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_delete_keys(
|
||||||
|
self, **kw):
|
||||||
|
return (202, {}, None)
|
||||||
|
|
||||||
|
def delete_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C(self, **kw):
|
||||||
|
return (202, {}, None)
|
||||||
|
|
||||||
|
def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_associations(
|
||||||
|
self, **kw):
|
||||||
|
type_id1 = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF'
|
||||||
|
type_id2 = '4230B13A-AB37-4E84-B777-EFBA6FCEE4FF'
|
||||||
|
type_name1 = 'type1'
|
||||||
|
type_name2 = 'type2'
|
||||||
|
return (202, {},
|
||||||
|
{'qos_associations': [
|
||||||
|
_stub_qos_associates(type_id1, type_name1),
|
||||||
|
_stub_qos_associates(type_id2, type_name2)]})
|
||||||
|
|
||||||
|
def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_associate(
|
||||||
|
self, **kw):
|
||||||
|
return (202, {}, None)
|
||||||
|
|
||||||
|
def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_disassociate(
|
||||||
|
self, **kw):
|
||||||
|
return (202, {}, None)
|
||||||
|
|
||||||
|
def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_disassociate_all(
|
||||||
|
self, **kw):
|
||||||
|
return (202, {}, None)
|
||||||
|
|
||||||
|
#
|
||||||
#
|
#
|
||||||
# VolumeTransfers
|
# VolumeTransfers
|
||||||
#
|
#
|
||||||
|
79
cinderclient/tests/v2/test_qos.py
Normal file
79
cinderclient/tests/v2/test_qos.py
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# Copyright (C) 2013 eBay Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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 cinderclient.tests import utils
|
||||||
|
from cinderclient.tests.v2 import fakes
|
||||||
|
|
||||||
|
|
||||||
|
cs = fakes.FakeClient()
|
||||||
|
|
||||||
|
|
||||||
|
class QoSSpecsTest(utils.TestCase):
|
||||||
|
|
||||||
|
def test_create(self):
|
||||||
|
specs = dict(k1='v1', k2='v2')
|
||||||
|
cs.qos_specs.create('qos-name', specs)
|
||||||
|
cs.assert_called('POST', '/qos-specs')
|
||||||
|
|
||||||
|
def test_get(self):
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
cs.qos_specs.get(qos_id)
|
||||||
|
cs.assert_called('GET', '/qos-specs/%s' % qos_id)
|
||||||
|
|
||||||
|
def test_list(self):
|
||||||
|
cs.qos_specs.list()
|
||||||
|
cs.assert_called('GET', '/qos-specs')
|
||||||
|
|
||||||
|
def test_delete(self):
|
||||||
|
cs.qos_specs.delete('1B6B6A04-A927-4AEB-810B-B7BAAD49F57C')
|
||||||
|
cs.assert_called('DELETE',
|
||||||
|
'/qos-specs/1B6B6A04-A927-4AEB-810B-B7BAAD49F57C?'
|
||||||
|
'force=False')
|
||||||
|
|
||||||
|
def test_set_keys(self):
|
||||||
|
body = {'qos_specs': dict(k1='v1')}
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
cs.qos_specs.set_keys(qos_id, body)
|
||||||
|
cs.assert_called('PUT', '/qos-specs/%s' % qos_id)
|
||||||
|
|
||||||
|
def test_unset_keys(self):
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
body = {'keys': ['k1']}
|
||||||
|
cs.qos_specs.unset_keys(qos_id, body)
|
||||||
|
cs.assert_called('PUT', '/qos-specs/%s/delete_keys' % qos_id)
|
||||||
|
|
||||||
|
def test_get_associations(self):
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
cs.qos_specs.get_associations(qos_id)
|
||||||
|
cs.assert_called('GET', '/qos-specs/%s/associations' % qos_id)
|
||||||
|
|
||||||
|
def test_associate(self):
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
type_id = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF'
|
||||||
|
cs.qos_specs.associate(qos_id, type_id)
|
||||||
|
cs.assert_called('GET', '/qos-specs/%s/associate?vol_type_id=%s'
|
||||||
|
% (qos_id, type_id))
|
||||||
|
|
||||||
|
def test_disassociate(self):
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
type_id = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF'
|
||||||
|
cs.qos_specs.disassociate(qos_id, type_id)
|
||||||
|
cs.assert_called('GET', '/qos-specs/%s/disassociate?vol_type_id=%s'
|
||||||
|
% (qos_id, type_id))
|
||||||
|
|
||||||
|
def test_disassociate_all(self):
|
||||||
|
qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C'
|
||||||
|
cs.qos_specs.disassociate_all(qos_id)
|
||||||
|
cs.assert_called('GET', '/qos-specs/%s/disassociate_all' % qos_id)
|
@ -16,6 +16,7 @@
|
|||||||
from cinderclient import client
|
from cinderclient import client
|
||||||
from cinderclient.v1 import availability_zones
|
from cinderclient.v1 import availability_zones
|
||||||
from cinderclient.v1 import limits
|
from cinderclient.v1 import limits
|
||||||
|
from cinderclient.v1 import qos_specs
|
||||||
from cinderclient.v1 import quota_classes
|
from cinderclient.v1 import quota_classes
|
||||||
from cinderclient.v1 import quotas
|
from cinderclient.v1 import quotas
|
||||||
from cinderclient.v1 import services
|
from cinderclient.v1 import services
|
||||||
@ -62,6 +63,7 @@ class Client(object):
|
|||||||
self.volume_types = volume_types.VolumeTypeManager(self)
|
self.volume_types = volume_types.VolumeTypeManager(self)
|
||||||
self.volume_encryption_types = \
|
self.volume_encryption_types = \
|
||||||
volume_encryption_types.VolumeEncryptionTypeManager(self)
|
volume_encryption_types.VolumeEncryptionTypeManager(self)
|
||||||
|
self.qos_specs = qos_specs.QoSSpecsManager(self)
|
||||||
self.quota_classes = quota_classes.QuotaClassSetManager(self)
|
self.quota_classes = quota_classes.QuotaClassSetManager(self)
|
||||||
self.quotas = quotas.QuotaSetManager(self)
|
self.quotas = quotas.QuotaSetManager(self)
|
||||||
self.backups = volume_backups.VolumeBackupManager(self)
|
self.backups = volume_backups.VolumeBackupManager(self)
|
||||||
|
149
cinderclient/v1/qos_specs.py
Normal file
149
cinderclient/v1/qos_specs.py
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
# Copyright (c) 2013 eBay Inc.
|
||||||
|
# Copyright (c) OpenStack LLC.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
QoS Specs interface.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from cinderclient import base
|
||||||
|
|
||||||
|
|
||||||
|
class QoSSpecs(base.Resource):
|
||||||
|
"""QoS specs entity represents quality-of-service parameters/requirements.
|
||||||
|
|
||||||
|
A QoS specs is a set of parameters or requirements for quality-of-service
|
||||||
|
purpose, which can be associated with volume types (for now). In future,
|
||||||
|
QoS specs may be extended to be associated other entities, such as single
|
||||||
|
volume.
|
||||||
|
"""
|
||||||
|
def __repr__(self):
|
||||||
|
return "<QoSSpecs: %s>" % self.name
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
return self.manager.delete(self)
|
||||||
|
|
||||||
|
|
||||||
|
class QoSSpecsManager(base.ManagerWithFind):
|
||||||
|
"""
|
||||||
|
Manage :class:`QoSSpecs` resources.
|
||||||
|
"""
|
||||||
|
resource_class = QoSSpecs
|
||||||
|
|
||||||
|
def list(self):
|
||||||
|
"""Get a list of all qos specs.
|
||||||
|
|
||||||
|
:rtype: list of :class:`QoSSpecs`.
|
||||||
|
"""
|
||||||
|
return self._list("/qos-specs", "qos_specs")
|
||||||
|
|
||||||
|
def get(self, qos_specs):
|
||||||
|
"""Get a specific qos specs.
|
||||||
|
|
||||||
|
:param qos_specs: The ID of the :class:`QoSSpecs` to get.
|
||||||
|
:rtype: :class:`QoSSpecs`
|
||||||
|
"""
|
||||||
|
return self._get("/qos-specs/%s" % base.getid(qos_specs), "qos_specs")
|
||||||
|
|
||||||
|
def delete(self, qos_specs, force=False):
|
||||||
|
"""Delete a specific qos specs.
|
||||||
|
|
||||||
|
:param qos_specs: The ID of the :class:`QoSSpecs` to be removed.
|
||||||
|
:param force: Flag that indicates whether to delete target qos specs
|
||||||
|
if it was in-use.
|
||||||
|
"""
|
||||||
|
self._delete("/qos-specs/%s?force=%s" %
|
||||||
|
(base.getid(qos_specs), force))
|
||||||
|
|
||||||
|
def create(self, name, specs):
|
||||||
|
"""Create a qos specs.
|
||||||
|
|
||||||
|
:param name: Descriptive name of the qos specs, must be unique
|
||||||
|
:param specs: A dict of key/value pairs to be set
|
||||||
|
:rtype: :class:`QoSSpecs`
|
||||||
|
"""
|
||||||
|
|
||||||
|
body = {
|
||||||
|
"qos_specs": {
|
||||||
|
"name": name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body["qos_specs"].update(specs)
|
||||||
|
return self._create("/qos-specs", body, "qos_specs")
|
||||||
|
|
||||||
|
def set_keys(self, qos_specs, specs):
|
||||||
|
"""Update a qos specs with new specifications.
|
||||||
|
|
||||||
|
:param qos_specs: The ID of qos specs
|
||||||
|
:param specs: A dict of key/value pairs to be set
|
||||||
|
:rtype: :class:`QoSSpecs`
|
||||||
|
"""
|
||||||
|
|
||||||
|
body = {
|
||||||
|
"qos_specs": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
body["qos_specs"].update(specs)
|
||||||
|
return self._update("/qos-specs/%s" % qos_specs, body)
|
||||||
|
|
||||||
|
def unset_keys(self, qos_specs, specs):
|
||||||
|
"""Update a qos specs with new specifications.
|
||||||
|
|
||||||
|
:param qos_specs: The ID of qos specs
|
||||||
|
:param specs: A list of key to be unset
|
||||||
|
:rtype: :class:`QoSSpecs`
|
||||||
|
"""
|
||||||
|
|
||||||
|
body = {'keys': specs}
|
||||||
|
|
||||||
|
return self._update("/qos-specs/%s/delete_keys" % qos_specs,
|
||||||
|
body)
|
||||||
|
|
||||||
|
def get_associations(self, qos_specs):
|
||||||
|
"""Get associated entities of a qos specs.
|
||||||
|
|
||||||
|
:param qos_specs: The id of the :class: `QoSSpecs`
|
||||||
|
:return: a list of entities that associated with specific qos specs.
|
||||||
|
"""
|
||||||
|
return self._list("/qos-specs/%s/associations" % base.getid(qos_specs),
|
||||||
|
"qos_associations")
|
||||||
|
|
||||||
|
def associate(self, qos_specs, vol_type_id):
|
||||||
|
"""Associate a volume type with specific qos specs.
|
||||||
|
|
||||||
|
:param qos_specs: The qos specs to be associated with
|
||||||
|
:param vol_type_id: The volume type id to be associated with
|
||||||
|
"""
|
||||||
|
self.api.client.get("/qos-specs/%s/associate?vol_type_id=%s" %
|
||||||
|
(base.getid(qos_specs), vol_type_id))
|
||||||
|
|
||||||
|
def disassociate(self, qos_specs, vol_type_id):
|
||||||
|
"""Disassociate qos specs from volume type.
|
||||||
|
|
||||||
|
:param qos_specs: The qos specs to be associated with
|
||||||
|
:param vol_type_id: The volume type id to be associated with
|
||||||
|
"""
|
||||||
|
self.api.client.get("/qos-specs/%s/disassociate?vol_type_id=%s" %
|
||||||
|
(base.getid(qos_specs), vol_type_id))
|
||||||
|
|
||||||
|
def disassociate_all(self, qos_specs):
|
||||||
|
"""Disassociate all entities from specific qos specs.
|
||||||
|
|
||||||
|
:param qos_specs: The qos specs to be associated with
|
||||||
|
"""
|
||||||
|
self.api.client.get("/qos-specs/%s/disassociate_all" %
|
||||||
|
base.getid(qos_specs))
|
@ -24,6 +24,7 @@ import sys
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from cinderclient import exceptions
|
from cinderclient import exceptions
|
||||||
|
from cinderclient.openstack.common import strutils
|
||||||
from cinderclient import utils
|
from cinderclient import utils
|
||||||
from cinderclient.v1 import availability_zones
|
from cinderclient.v1 import availability_zones
|
||||||
|
|
||||||
@ -75,6 +76,11 @@ def _find_transfer(cs, transfer):
|
|||||||
return utils.find_resource(cs.transfers, transfer)
|
return utils.find_resource(cs.transfers, transfer)
|
||||||
|
|
||||||
|
|
||||||
|
def _find_qos_specs(cs, qos_specs):
|
||||||
|
"""Get a qos specs by ID."""
|
||||||
|
return utils.find_resource(cs.qos_specs, qos_specs)
|
||||||
|
|
||||||
|
|
||||||
def _print_volume(volume):
|
def _print_volume(volume):
|
||||||
utils.print_dict(volume._info)
|
utils.print_dict(volume._info)
|
||||||
|
|
||||||
@ -1068,3 +1074,125 @@ def do_migrate(cs, args):
|
|||||||
"""Migrate the volume to the new host."""
|
"""Migrate the volume to the new host."""
|
||||||
volume = _find_volume(cs, args.volume)
|
volume = _find_volume(cs, args.volume)
|
||||||
volume.migrate_volume(args.host, args.force_host_copy)
|
volume.migrate_volume(args.host, args.force_host_copy)
|
||||||
|
|
||||||
|
|
||||||
|
def _print_qos_specs(qos_specs):
|
||||||
|
utils.print_dict(qos_specs._info)
|
||||||
|
|
||||||
|
|
||||||
|
def _print_qos_specs_list(q_specs):
|
||||||
|
utils.print_list(q_specs, ['ID', 'Name', 'Consumer', 'specs'])
|
||||||
|
|
||||||
|
|
||||||
|
def _print_qos_specs_and_associations_list(q_specs):
|
||||||
|
utils.print_list(q_specs, ['ID', 'Name', 'Consumer', 'specs'])
|
||||||
|
|
||||||
|
|
||||||
|
def _print_associations_list(associations):
|
||||||
|
utils.print_list(associations, ['Association_Type', 'Name', 'ID'])
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('name',
|
||||||
|
metavar='<name>',
|
||||||
|
help="Name of the new QoS specs")
|
||||||
|
@utils.arg('metadata',
|
||||||
|
metavar='<key=value>',
|
||||||
|
nargs='+',
|
||||||
|
default=[],
|
||||||
|
help='Specifications for QoS')
|
||||||
|
@utils.service_type('volume')
|
||||||
|
def do_qos_create(cs, args):
|
||||||
|
"""Create a new qos specs."""
|
||||||
|
keypair = None
|
||||||
|
if args.metadata is not None:
|
||||||
|
keypair = _extract_metadata(args)
|
||||||
|
qos_specs = cs.qos_specs.create(args.name, keypair)
|
||||||
|
_print_qos_specs(qos_specs)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.service_type('volume')
|
||||||
|
def do_qos_list(cs, args):
|
||||||
|
"""Get full list of qos specs."""
|
||||||
|
qos_specs = cs.qos_specs.list()
|
||||||
|
_print_qos_specs_list(qos_specs)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of the qos_specs to show.')
|
||||||
|
@utils.service_type('volume')
|
||||||
|
def do_qos_show(cs, args):
|
||||||
|
"""Get a specific qos specs."""
|
||||||
|
qos_specs = _find_qos_specs(cs, args.qos_specs)
|
||||||
|
_print_qos_specs(qos_specs)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of the qos_specs to delete.')
|
||||||
|
@utils.arg('--force',
|
||||||
|
metavar='<True|False>',
|
||||||
|
default=False,
|
||||||
|
help='Optional flag that indicates whether to delete '
|
||||||
|
'specified qos specs even if it is in-use.')
|
||||||
|
@utils.service_type('volume')
|
||||||
|
def do_qos_delete(cs, args):
|
||||||
|
"""Delete a specific qos specs."""
|
||||||
|
force = strutils.bool_from_string(args.force)
|
||||||
|
qos_specs = _find_qos_specs(cs, args.qos_specs)
|
||||||
|
cs.qos_specs.delete(qos_specs, force)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of qos_specs.')
|
||||||
|
@utils.arg('vol_type_id', metavar='<volume_type_id>',
|
||||||
|
help='ID of volume type to be associated with.')
|
||||||
|
@utils.service_type('volume')
|
||||||
|
def do_qos_associate(cs, args):
|
||||||
|
"""Associate qos specs with specific volume type."""
|
||||||
|
cs.qos_specs.associate(args.qos_specs, args.vol_type_id)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of qos_specs.')
|
||||||
|
@utils.arg('vol_type_id', metavar='<volume_type_id>',
|
||||||
|
help='ID of volume type to be associated with.')
|
||||||
|
@utils.service_type('volume')
|
||||||
|
def do_qos_disassociate(cs, args):
|
||||||
|
"""Disassociate qos specs from specific volume type."""
|
||||||
|
cs.qos_specs.disassociate(args.qos_specs, args.vol_type_id)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of qos_specs to be operate on.')
|
||||||
|
@utils.service_type('volume')
|
||||||
|
def do_qos_disassociate_all(cs, args):
|
||||||
|
"""Disassociate qos specs from all of its associations."""
|
||||||
|
cs.qos_specs.disassociate_all(args.qos_specs)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of qos specs')
|
||||||
|
@utils.arg('action',
|
||||||
|
metavar='<action>',
|
||||||
|
choices=['set', 'unset'],
|
||||||
|
help="Actions: 'set' or 'unset'")
|
||||||
|
@utils.arg('metadata', metavar='key=value',
|
||||||
|
nargs='+',
|
||||||
|
default=[],
|
||||||
|
help='QoS specs to set/unset (only key is necessary on unset)')
|
||||||
|
def do_qos_key(cs, args):
|
||||||
|
"""Set or unset specifications for a qos spec."""
|
||||||
|
keypair = _extract_metadata(args)
|
||||||
|
|
||||||
|
if args.action == 'set':
|
||||||
|
cs.qos_specs.set_keys(args.qos_specs, keypair)
|
||||||
|
elif args.action == 'unset':
|
||||||
|
cs.qos_specs.unset_keys(args.qos_specs, list(keypair.keys()))
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of the qos_specs.')
|
||||||
|
@utils.service_type('volume')
|
||||||
|
def do_qos_get_association(cs, args):
|
||||||
|
"""Get all associations of specific qos specs."""
|
||||||
|
associations = cs.qos_specs.get_associations(args.qos_specs)
|
||||||
|
_print_associations_list(associations)
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
from cinderclient import client
|
from cinderclient import client
|
||||||
from cinderclient.v1 import availability_zones
|
from cinderclient.v1 import availability_zones
|
||||||
from cinderclient.v2 import limits
|
from cinderclient.v2 import limits
|
||||||
|
from cinderclient.v2 import qos_specs
|
||||||
from cinderclient.v2 import quota_classes
|
from cinderclient.v2 import quota_classes
|
||||||
from cinderclient.v2 import quotas
|
from cinderclient.v2 import quotas
|
||||||
from cinderclient.v2 import services
|
from cinderclient.v2 import services
|
||||||
@ -60,6 +61,7 @@ class Client(object):
|
|||||||
self.volume_types = volume_types.VolumeTypeManager(self)
|
self.volume_types = volume_types.VolumeTypeManager(self)
|
||||||
self.volume_encryption_types = \
|
self.volume_encryption_types = \
|
||||||
volume_encryption_types.VolumeEncryptionTypeManager(self)
|
volume_encryption_types.VolumeEncryptionTypeManager(self)
|
||||||
|
self.qos_specs = qos_specs.QoSSpecsManager(self)
|
||||||
self.quota_classes = quota_classes.QuotaClassSetManager(self)
|
self.quota_classes = quota_classes.QuotaClassSetManager(self)
|
||||||
self.quotas = quotas.QuotaSetManager(self)
|
self.quotas = quotas.QuotaSetManager(self)
|
||||||
self.backups = volume_backups.VolumeBackupManager(self)
|
self.backups = volume_backups.VolumeBackupManager(self)
|
||||||
|
149
cinderclient/v2/qos_specs.py
Normal file
149
cinderclient/v2/qos_specs.py
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
# Copyright (c) 2013 eBay Inc.
|
||||||
|
# Copyright (c) OpenStack LLC.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
QoS Specs interface.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from cinderclient import base
|
||||||
|
|
||||||
|
|
||||||
|
class QoSSpecs(base.Resource):
|
||||||
|
"""QoS specs entity represents quality-of-service parameters/requirements.
|
||||||
|
|
||||||
|
A QoS specs is a set of parameters or requirements for quality-of-service
|
||||||
|
purpose, which can be associated with volume types (for now). In future,
|
||||||
|
QoS specs may be extended to be associated other entities, such as single
|
||||||
|
volume.
|
||||||
|
"""
|
||||||
|
def __repr__(self):
|
||||||
|
return "<QoSSpecs: %s>" % self.name
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
return self.manager.delete(self)
|
||||||
|
|
||||||
|
|
||||||
|
class QoSSpecsManager(base.ManagerWithFind):
|
||||||
|
"""
|
||||||
|
Manage :class:`QoSSpecs` resources.
|
||||||
|
"""
|
||||||
|
resource_class = QoSSpecs
|
||||||
|
|
||||||
|
def list(self):
|
||||||
|
"""Get a list of all qos specs.
|
||||||
|
|
||||||
|
:rtype: list of :class:`QoSSpecs`.
|
||||||
|
"""
|
||||||
|
return self._list("/qos-specs", "qos_specs")
|
||||||
|
|
||||||
|
def get(self, qos_specs):
|
||||||
|
"""Get a specific qos specs.
|
||||||
|
|
||||||
|
:param qos_specs: The ID of the :class:`QoSSpecs` to get.
|
||||||
|
:rtype: :class:`QoSSpecs`
|
||||||
|
"""
|
||||||
|
return self._get("/qos-specs/%s" % base.getid(qos_specs), "qos_specs")
|
||||||
|
|
||||||
|
def delete(self, qos_specs, force=False):
|
||||||
|
"""Delete a specific qos specs.
|
||||||
|
|
||||||
|
:param qos_specs: The ID of the :class:`QoSSpecs` to be removed.
|
||||||
|
:param force: Flag that indicates whether to delete target qos specs
|
||||||
|
if it was in-use.
|
||||||
|
"""
|
||||||
|
self._delete("/qos-specs/%s?force=%s" %
|
||||||
|
(base.getid(qos_specs), force))
|
||||||
|
|
||||||
|
def create(self, name, specs):
|
||||||
|
"""Create a qos specs.
|
||||||
|
|
||||||
|
:param name: Descriptive name of the qos specs, must be unique
|
||||||
|
:param specs: A dict of key/value pairs to be set
|
||||||
|
:rtype: :class:`QoSSpecs`
|
||||||
|
"""
|
||||||
|
|
||||||
|
body = {
|
||||||
|
"qos_specs": {
|
||||||
|
"name": name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body["qos_specs"].update(specs)
|
||||||
|
return self._create("/qos-specs", body, "qos_specs")
|
||||||
|
|
||||||
|
def set_keys(self, qos_specs, specs):
|
||||||
|
"""Update a qos specs with new specifications.
|
||||||
|
|
||||||
|
:param qos_specs: The ID of qos specs
|
||||||
|
:param specs: A dict of key/value pairs to be set
|
||||||
|
:rtype: :class:`QoSSpecs`
|
||||||
|
"""
|
||||||
|
|
||||||
|
body = {
|
||||||
|
"qos_specs": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
body["qos_specs"].update(specs)
|
||||||
|
return self._update("/qos-specs/%s" % qos_specs, body)
|
||||||
|
|
||||||
|
def unset_keys(self, qos_specs, specs):
|
||||||
|
"""Update a qos specs with new specifications.
|
||||||
|
|
||||||
|
:param qos_specs: The ID of qos specs
|
||||||
|
:param specs: A list of key to be unset
|
||||||
|
:rtype: :class:`QoSSpecs`
|
||||||
|
"""
|
||||||
|
|
||||||
|
body = {'keys': specs}
|
||||||
|
|
||||||
|
return self._update("/qos-specs/%s/delete_keys" % qos_specs,
|
||||||
|
body)
|
||||||
|
|
||||||
|
def get_associations(self, qos_specs):
|
||||||
|
"""Get associated entities of a qos specs.
|
||||||
|
|
||||||
|
:param qos_specs: The id of the :class: `QoSSpecs`
|
||||||
|
:return: a list of entities that associated with specific qos specs.
|
||||||
|
"""
|
||||||
|
return self._list("/qos-specs/%s/associations" % base.getid(qos_specs),
|
||||||
|
"qos_associations")
|
||||||
|
|
||||||
|
def associate(self, qos_specs, vol_type_id):
|
||||||
|
"""Associate a volume type with specific qos specs.
|
||||||
|
|
||||||
|
:param qos_specs: The qos specs to be associated with
|
||||||
|
:param vol_type_id: The volume type id to be associated with
|
||||||
|
"""
|
||||||
|
self.api.client.get("/qos-specs/%s/associate?vol_type_id=%s" %
|
||||||
|
(base.getid(qos_specs), vol_type_id))
|
||||||
|
|
||||||
|
def disassociate(self, qos_specs, vol_type_id):
|
||||||
|
"""Disassociate qos specs from volume type.
|
||||||
|
|
||||||
|
:param qos_specs: The qos specs to be associated with
|
||||||
|
:param vol_type_id: The volume type id to be associated with
|
||||||
|
"""
|
||||||
|
self.api.client.get("/qos-specs/%s/disassociate?vol_type_id=%s" %
|
||||||
|
(base.getid(qos_specs), vol_type_id))
|
||||||
|
|
||||||
|
def disassociate_all(self, qos_specs):
|
||||||
|
"""Disassociate all entities from specific qos specs.
|
||||||
|
|
||||||
|
:param qos_specs: The qos specs to be associated with
|
||||||
|
"""
|
||||||
|
self.api.client.get("/qos-specs/%s/disassociate_all" %
|
||||||
|
base.getid(qos_specs))
|
@ -25,6 +25,7 @@ import six
|
|||||||
|
|
||||||
from cinderclient import exceptions
|
from cinderclient import exceptions
|
||||||
from cinderclient import utils
|
from cinderclient import utils
|
||||||
|
from cinderclient.openstack.common import strutils
|
||||||
from cinderclient.v2 import availability_zones
|
from cinderclient.v2 import availability_zones
|
||||||
|
|
||||||
|
|
||||||
@ -73,6 +74,11 @@ def _find_transfer(cs, transfer):
|
|||||||
return utils.find_resource(cs.transfers, transfer)
|
return utils.find_resource(cs.transfers, transfer)
|
||||||
|
|
||||||
|
|
||||||
|
def _find_qos_specs(cs, qos_specs):
|
||||||
|
"""Get a qos specs by ID."""
|
||||||
|
return utils.find_resource(cs.qos_specs, qos_specs)
|
||||||
|
|
||||||
|
|
||||||
def _print_volume_snapshot(snapshot):
|
def _print_volume_snapshot(snapshot):
|
||||||
utils.print_dict(snapshot._info)
|
utils.print_dict(snapshot._info)
|
||||||
|
|
||||||
@ -106,7 +112,7 @@ def _translate_availability_zone_keys(collection):
|
|||||||
|
|
||||||
def _extract_metadata(args):
|
def _extract_metadata(args):
|
||||||
metadata = {}
|
metadata = {}
|
||||||
for metadatum in args.metadata[0]:
|
for metadatum in args.metadata:
|
||||||
# unset doesn't require a val, so we have the if/else
|
# unset doesn't require a val, so we have the if/else
|
||||||
if '=' in metadatum:
|
if '=' in metadatum:
|
||||||
(key, value) = metadatum.split('=', 1)
|
(key, value) = metadatum.split('=', 1)
|
||||||
@ -369,7 +375,6 @@ def do_rename(cs, args):
|
|||||||
@utils.arg('metadata',
|
@utils.arg('metadata',
|
||||||
metavar='<key=value>',
|
metavar='<key=value>',
|
||||||
nargs='+',
|
nargs='+',
|
||||||
action='append',
|
|
||||||
default=[],
|
default=[],
|
||||||
help='Metadata to set/unset (only key is necessary on unset)')
|
help='Metadata to set/unset (only key is necessary on unset)')
|
||||||
@utils.service_type('volumev2')
|
@utils.service_type('volumev2')
|
||||||
@ -592,12 +597,11 @@ def do_type_delete(cs, args):
|
|||||||
@utils.arg('metadata',
|
@utils.arg('metadata',
|
||||||
metavar='<key=value>',
|
metavar='<key=value>',
|
||||||
nargs='+',
|
nargs='+',
|
||||||
action='append',
|
|
||||||
default=[],
|
default=[],
|
||||||
help='Extra_specs to set/unset (only key is necessary on unset)')
|
help='Extra_specs to set/unset (only key is necessary on unset)')
|
||||||
@utils.service_type('volumev2')
|
@utils.service_type('volumev2')
|
||||||
def do_type_key(cs, args):
|
def do_type_key(cs, args):
|
||||||
"Set or unset extra_spec for a volume type."""
|
"""Set or unset extra_spec for a volume type."""
|
||||||
vtype = _find_volume_type(cs, args.vtype)
|
vtype = _find_volume_type(cs, args.vtype)
|
||||||
keypair = _extract_metadata(args)
|
keypair = _extract_metadata(args)
|
||||||
|
|
||||||
@ -1148,3 +1152,125 @@ def do_encryption_type_create(cs, args):
|
|||||||
|
|
||||||
result = cs.volume_encryption_types.create(volume_type, body)
|
result = cs.volume_encryption_types.create(volume_type, body)
|
||||||
_print_volume_encryption_type_list([result])
|
_print_volume_encryption_type_list([result])
|
||||||
|
|
||||||
|
|
||||||
|
def _print_qos_specs(qos_specs):
|
||||||
|
utils.print_dict(qos_specs._info)
|
||||||
|
|
||||||
|
|
||||||
|
def _print_qos_specs_list(q_specs):
|
||||||
|
utils.print_list(q_specs, ['ID', 'Name', 'Consumer', 'specs'])
|
||||||
|
|
||||||
|
|
||||||
|
def _print_qos_specs_and_associations_list(q_specs):
|
||||||
|
utils.print_list(q_specs, ['ID', 'Name', 'Consumer', 'specs'])
|
||||||
|
|
||||||
|
|
||||||
|
def _print_associations_list(associations):
|
||||||
|
utils.print_list(associations, ['Association_Type', 'Name', 'ID'])
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('name',
|
||||||
|
metavar='<name>',
|
||||||
|
help="Name of the new QoS specs")
|
||||||
|
@utils.arg('metadata',
|
||||||
|
metavar='<key=value>',
|
||||||
|
nargs='+',
|
||||||
|
default=[],
|
||||||
|
help='Specifications for QoS')
|
||||||
|
@utils.service_type('volumev2')
|
||||||
|
def do_qos_create(cs, args):
|
||||||
|
"""Create a new qos specs."""
|
||||||
|
keypair = None
|
||||||
|
if args.metadata is not None:
|
||||||
|
keypair = _extract_metadata(args)
|
||||||
|
qos_specs = cs.qos_specs.create(args.name, keypair)
|
||||||
|
_print_qos_specs(qos_specs)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.service_type('volumev2')
|
||||||
|
def do_qos_list(cs, args):
|
||||||
|
"""Get full list of qos specs."""
|
||||||
|
qos_specs = cs.qos_specs.list()
|
||||||
|
_print_qos_specs_list(qos_specs)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of the qos_specs to show.')
|
||||||
|
@utils.service_type('volumev2')
|
||||||
|
def do_qos_show(cs, args):
|
||||||
|
"""Get a specific qos specs."""
|
||||||
|
qos_specs = _find_qos_specs(cs, args.qos_specs)
|
||||||
|
_print_qos_specs(qos_specs)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of the qos_specs to delete.')
|
||||||
|
@utils.arg('--force',
|
||||||
|
metavar='<True|False>',
|
||||||
|
default=False,
|
||||||
|
help='Optional flag that indicates whether to delete '
|
||||||
|
'specified qos specs even if it is in-use.')
|
||||||
|
@utils.service_type('volumev2')
|
||||||
|
def do_qos_delete(cs, args):
|
||||||
|
"""Delete a specific qos specs."""
|
||||||
|
force = strutils.bool_from_string(args.force)
|
||||||
|
qos_specs = _find_qos_specs(cs, args.qos_specs)
|
||||||
|
cs.qos_specs.delete(qos_specs, force)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of qos_specs.')
|
||||||
|
@utils.arg('vol_type_id', metavar='<volume_type_id>',
|
||||||
|
help='ID of volume type to be associated with.')
|
||||||
|
@utils.service_type('volumev2')
|
||||||
|
def do_qos_associate(cs, args):
|
||||||
|
"""Associate qos specs with specific volume type."""
|
||||||
|
cs.qos_specs.associate(args.qos_specs, args.vol_type_id)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of qos_specs.')
|
||||||
|
@utils.arg('vol_type_id', metavar='<volume_type_id>',
|
||||||
|
help='ID of volume type to be associated with.')
|
||||||
|
@utils.service_type('volumev2')
|
||||||
|
def do_qos_disassociate(cs, args):
|
||||||
|
"""Disassociate qos specs from specific volume type."""
|
||||||
|
cs.qos_specs.disassociate(args.qos_specs, args.vol_type_id)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of qos_specs to be operate on.')
|
||||||
|
@utils.service_type('volumev2')
|
||||||
|
def do_qos_disassociate_all(cs, args):
|
||||||
|
"""Disassociate qos specs from all of its associations."""
|
||||||
|
cs.qos_specs.disassociate_all(args.qos_specs)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of qos specs')
|
||||||
|
@utils.arg('action',
|
||||||
|
metavar='<action>',
|
||||||
|
choices=['set', 'unset'],
|
||||||
|
help="Actions: 'set' or 'unset'")
|
||||||
|
@utils.arg('metadata', metavar='key=value',
|
||||||
|
nargs='+',
|
||||||
|
default=[],
|
||||||
|
help='QoS specs to set/unset (only key is necessary on unset)')
|
||||||
|
def do_qos_key(cs, args):
|
||||||
|
"""Set or unset specifications for a qos spec."""
|
||||||
|
keypair = _extract_metadata(args)
|
||||||
|
|
||||||
|
if args.action == 'set':
|
||||||
|
cs.qos_specs.set_keys(args.qos_specs, keypair)
|
||||||
|
elif args.action == 'unset':
|
||||||
|
cs.qos_specs.unset_keys(args.qos_specs, list(keypair.keys()))
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg('qos_specs', metavar='<qos_specs>',
|
||||||
|
help='ID of the qos_specs.')
|
||||||
|
@utils.service_type('volumev2')
|
||||||
|
def do_qos_get_association(cs, args):
|
||||||
|
"""Get all associations of specific qos specs."""
|
||||||
|
associations = cs.qos_specs.get_associations(args.qos_specs)
|
||||||
|
_print_associations_list(associations)
|
||||||
|
Loading…
Reference in New Issue
Block a user