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:
		
				
					committed by
					
						
						John Griffith
					
				
			
			
				
	
			
			
			
						parent
						
							5ad95e9fd2
						
					
				
				
					commit
					87628cc485
				
			@@ -116,6 +116,34 @@ def _stub_restore():
 | 
			
		||||
    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):
 | 
			
		||||
    return {
 | 
			
		||||
        'id': id,
 | 
			
		||||
@@ -505,6 +533,68 @@ class FakeHTTPClient(base_client.HTTPClient):
 | 
			
		||||
        return (200, {},
 | 
			
		||||
                {'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
 | 
			
		||||
    #
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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():
 | 
			
		||||
    return {'volume_id': '712f4980-5ac1-41e5-9383-390aa7c9f58b'}
 | 
			
		||||
 | 
			
		||||
@@ -512,6 +540,69 @@ class FakeHTTPClient(base_client.HTTPClient):
 | 
			
		||||
        return (200, {},
 | 
			
		||||
                {'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
 | 
			
		||||
    #
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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.v1 import availability_zones
 | 
			
		||||
from cinderclient.v1 import limits
 | 
			
		||||
from cinderclient.v1 import qos_specs
 | 
			
		||||
from cinderclient.v1 import quota_classes
 | 
			
		||||
from cinderclient.v1 import quotas
 | 
			
		||||
from cinderclient.v1 import services
 | 
			
		||||
@@ -62,6 +63,7 @@ class Client(object):
 | 
			
		||||
        self.volume_types = volume_types.VolumeTypeManager(self)
 | 
			
		||||
        self.volume_encryption_types = \
 | 
			
		||||
            volume_encryption_types.VolumeEncryptionTypeManager(self)
 | 
			
		||||
        self.qos_specs = qos_specs.QoSSpecsManager(self)
 | 
			
		||||
        self.quota_classes = quota_classes.QuotaClassSetManager(self)
 | 
			
		||||
        self.quotas = quotas.QuotaSetManager(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
 | 
			
		||||
 | 
			
		||||
from cinderclient import exceptions
 | 
			
		||||
from cinderclient.openstack.common import strutils
 | 
			
		||||
from cinderclient import utils
 | 
			
		||||
from cinderclient.v1 import availability_zones
 | 
			
		||||
 | 
			
		||||
@@ -75,6 +76,11 @@ def _find_transfer(cs, 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):
 | 
			
		||||
    utils.print_dict(volume._info)
 | 
			
		||||
 | 
			
		||||
@@ -1068,3 +1074,125 @@ def do_migrate(cs, args):
 | 
			
		||||
    """Migrate the volume to the new host."""
 | 
			
		||||
    volume = _find_volume(cs, args.volume)
 | 
			
		||||
    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.v1 import availability_zones
 | 
			
		||||
from cinderclient.v2 import limits
 | 
			
		||||
from cinderclient.v2 import qos_specs
 | 
			
		||||
from cinderclient.v2 import quota_classes
 | 
			
		||||
from cinderclient.v2 import quotas
 | 
			
		||||
from cinderclient.v2 import services
 | 
			
		||||
@@ -60,6 +61,7 @@ class Client(object):
 | 
			
		||||
        self.volume_types = volume_types.VolumeTypeManager(self)
 | 
			
		||||
        self.volume_encryption_types = \
 | 
			
		||||
            volume_encryption_types.VolumeEncryptionTypeManager(self)
 | 
			
		||||
        self.qos_specs = qos_specs.QoSSpecsManager(self)
 | 
			
		||||
        self.quota_classes = quota_classes.QuotaClassSetManager(self)
 | 
			
		||||
        self.quotas = quotas.QuotaSetManager(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 utils
 | 
			
		||||
from cinderclient.openstack.common import strutils
 | 
			
		||||
from cinderclient.v2 import availability_zones
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -73,6 +74,11 @@ def _find_transfer(cs, 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):
 | 
			
		||||
    utils.print_dict(snapshot._info)
 | 
			
		||||
 | 
			
		||||
@@ -106,7 +112,7 @@ def _translate_availability_zone_keys(collection):
 | 
			
		||||
 | 
			
		||||
def _extract_metadata(args):
 | 
			
		||||
    metadata = {}
 | 
			
		||||
    for metadatum in args.metadata[0]:
 | 
			
		||||
    for metadatum in args.metadata:
 | 
			
		||||
        # unset doesn't require a val, so we have the if/else
 | 
			
		||||
        if '=' in metadatum:
 | 
			
		||||
            (key, value) = metadatum.split('=', 1)
 | 
			
		||||
@@ -369,7 +375,6 @@ def do_rename(cs, args):
 | 
			
		||||
@utils.arg('metadata',
 | 
			
		||||
           metavar='<key=value>',
 | 
			
		||||
           nargs='+',
 | 
			
		||||
           action='append',
 | 
			
		||||
           default=[],
 | 
			
		||||
           help='Metadata to set/unset (only key is necessary on unset)')
 | 
			
		||||
@utils.service_type('volumev2')
 | 
			
		||||
@@ -592,12 +597,11 @@ def do_type_delete(cs, args):
 | 
			
		||||
@utils.arg('metadata',
 | 
			
		||||
           metavar='<key=value>',
 | 
			
		||||
           nargs='+',
 | 
			
		||||
           action='append',
 | 
			
		||||
           default=[],
 | 
			
		||||
           help='Extra_specs to set/unset (only key is necessary on unset)')
 | 
			
		||||
@utils.service_type('volumev2')
 | 
			
		||||
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)
 | 
			
		||||
    keypair = _extract_metadata(args)
 | 
			
		||||
 | 
			
		||||
@@ -1148,3 +1152,125 @@ def do_encryption_type_create(cs, args):
 | 
			
		||||
 | 
			
		||||
    result = cs.volume_encryption_types.create(volume_type, body)
 | 
			
		||||
    _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)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user