Add cinder actions

* Mistral now includes all Cinder actions
 * Unit tests

Change-Id: Ia663df09ae15f8154d49bbf232118617f92cba30
This commit is contained in:
Nikolay Mahotkin 2014-11-05 15:19:29 +03:00
parent 9ba091ae6e
commit 0ee563d7e4
8 changed files with 219 additions and 4 deletions

View File

@ -21,5 +21,6 @@ def all_generators():
generators.GlanceActionGenerator,
generators.KeystoneActionGenerator,
generators.HeatActionGenerator,
generators.NeutronActionGenerator
generators.NeutronActionGenerator,
generators.CinderActionGenerator
]

View File

@ -39,3 +39,8 @@ class HeatActionGenerator(base.OpenStackActionGenerator):
class NeutronActionGenerator(base.OpenStackActionGenerator):
action_namespace = "neutron"
base_action_class = actions.NeutronAction
class CinderActionGenerator(base.OpenStackActionGenerator):
action_namespace = "cinder"
base_action_class = actions.CinderAction

View File

@ -14,6 +14,7 @@
import inspect
from cinderclient.v1 import client as cinderclient
from glanceclient.v2 import client as glanceclient
from heatclient.v1 import client as heatclient
from keystoneclient import httpclient
@ -146,3 +147,31 @@ class NeutronAction(base.OpenStackAction):
token=ctx.auth_token,
auth_url=CONF.keystone_authtoken.auth_uri
)
class CinderAction(base.OpenStackAction):
_client_class = cinderclient.Client
def _get_client(self):
ctx = context.ctx()
LOG.debug("Cinder action security context: %s" % ctx)
cinder_url = keystone_utils.get_endpoint_for_project(
service_type='volume'
)
cinder_url = cinder_url % {'tenant_id': ctx.project_id}
client = self._client_class(
ctx.user_name,
ctx.auth_token,
project_id=ctx.project_id,
auth_url=cinder_url,
)
client.client.auth_token = ctx.auth_token
client.client.management_url = cinder_url
return client
@classmethod
def _get_fake_client(cls):
return cls._client_class()

View File

@ -516,5 +516,136 @@
"update_subnet": "update_subnet",
"update_vip": "update_vip",
"update_vpnservice": "update_vpnservice"
},
"cinder": {
"_comment": "It uses cinderclient.v1.",
"availability_zones_completion_cache": "availability_zones.completion_cache",
"availability_zones_find": "availability_zones.find",
"availability_zones_findall": "availability_zones.findall",
"availability_zones_list": "availability_zones.list",
"availability_zones_write_to_completion_cache": "availability_zones.write_to_completion_cache",
"backups_completion_cache": "backups.completion_cache",
"backups_create": "backups.create",
"backups_delete": "backups.delete",
"backups_export_record": "backups.export_record",
"backups_find": "backups.find",
"backups_findall": "backups.findall",
"backups_get": "backups.get",
"backups_import_record": "backups.import_record",
"backups_list": "backups.list",
"backups_write_to_completion_cache": "backups.write_to_completion_cache",
"get_volume_api_version_from_endpoint": "get_volume_api_version_from_endpoint",
"limits_completion_cache": "limits.completion_cache",
"limits_get": "limits.get",
"limits_write_to_completion_cache": "limits.write_to_completion_cache",
"qos_specs_associate": "qos_specs.associate",
"qos_specs_completion_cache": "qos_specs.completion_cache",
"qos_specs_create": "qos_specs.create",
"qos_specs_delete": "qos_specs.delete",
"qos_specs_disassociate": "qos_specs.disassociate",
"qos_specs_disassociate_all": "qos_specs.disassociate_all",
"qos_specs_find": "qos_specs.find",
"qos_specs_findall": "qos_specs.findall",
"qos_specs_get": "qos_specs.get",
"qos_specs_get_associations": "qos_specs.get_associations",
"qos_specs_list": "qos_specs.list",
"qos_specs_set_keys": "qos_specs.set_keys",
"qos_specs_unset_keys": "qos_specs.unset_keys",
"qos_specs_write_to_completion_cache": "qos_specs.write_to_completion_cache",
"quota_classes_completion_cache": "quota_classes.completion_cache",
"quota_classes_get": "quota_classes.get",
"quota_classes_update": "quota_classes.update",
"quota_classes_write_to_completion_cache": "quota_classes.write_to_completion_cache",
"quotas_completion_cache": "quotas.completion_cache",
"quotas_defaults": "quotas.defaults",
"quotas_delete": "quotas.delete",
"quotas_get": "quotas.get",
"quotas_update": "quotas.update",
"quotas_write_to_completion_cache": "quotas.write_to_completion_cache",
"restores_completion_cache": "restores.completion_cache",
"restores_restore": "restores.restore",
"restores_write_to_completion_cache": "restores.write_to_completion_cache",
"services_completion_cache": "services.completion_cache",
"services_disable": "services.disable",
"services_disable_log_reason": "services.disable_log_reason",
"services_enable": "services.enable",
"services_find": "services.find",
"services_findall": "services.findall",
"services_list": "services.list",
"services_write_to_completion_cache": "services.write_to_completion_cache",
"transfers_accept": "transfers.accept",
"transfers_completion_cache": "transfers.completion_cache",
"transfers_create": "transfers.create",
"transfers_delete": "transfers.delete",
"transfers_find": "transfers.find",
"transfers_findall": "transfers.findall",
"transfers_get": "transfers.get",
"transfers_list": "transfers.list",
"transfers_write_to_completion_cache": "transfers.write_to_completion_cache",
"volume_encryption_types_completion_cache": "volume_encryption_types.completion_cache",
"volume_encryption_types_create": "volume_encryption_types.create",
"volume_encryption_types_delete": "volume_encryption_types.delete",
"volume_encryption_types_find": "volume_encryption_types.find",
"volume_encryption_types_findall": "volume_encryption_types.findall",
"volume_encryption_types_get": "volume_encryption_types.get",
"volume_encryption_types_list": "volume_encryption_types.list",
"volume_encryption_types_update": "volume_encryption_types.update",
"volume_encryption_types_write_to_completion_cache": "volume_encryption_types.write_to_completion_cache",
"volume_snapshots_completion_cache": "volume_snapshots.completion_cache",
"volume_snapshots_create": "volume_snapshots.create",
"volume_snapshots_delete": "volume_snapshots.delete",
"volume_snapshots_delete_metadata": "volume_snapshots.delete_metadata",
"volume_snapshots_find": "volume_snapshots.find",
"volume_snapshots_findall": "volume_snapshots.findall",
"volume_snapshots_get": "volume_snapshots.get",
"volume_snapshots_list": "volume_snapshots.list",
"volume_snapshots_reset_state": "volume_snapshots.reset_state",
"volume_snapshots_set_metadata": "volume_snapshots.set_metadata",
"volume_snapshots_update": "volume_snapshots.update",
"volume_snapshots_update_all_metadata": "volume_snapshots.update_all_metadata",
"volume_snapshots_update_snapshot_status": "volume_snapshots.update_snapshot_status",
"volume_snapshots_write_to_completion_cache": "volume_snapshots.write_to_completion_cache",
"volume_types_completion_cache": "volume_types.completion_cache",
"volume_types_create": "volume_types.create",
"volume_types_delete": "volume_types.delete",
"volume_types_find": "volume_types.find",
"volume_types_findall": "volume_types.findall",
"volume_types_get": "volume_types.get",
"volume_types_list": "volume_types.list",
"volume_types_write_to_completion_cache": "volume_types.write_to_completion_cache",
"volumes_attach": "volumes.attach",
"volumes_begin_detaching": "volumes.begin_detaching",
"volumes_completion_cache": "volumes.completion_cache",
"volumes_create": "volumes.create",
"volumes_delete": "volumes.delete",
"volumes_delete_metadata": "volumes.delete_metadata",
"volumes_detach": "volumes.detach",
"volumes_extend": "volumes.extend",
"volumes_find": "volumes.find",
"volumes_findall": "volumes.findall",
"volumes_force_delete": "volumes.force_delete",
"volumes_get": "volumes.get",
"volumes_get_encryption_metadata": "volumes.get_encryption_metadata",
"volumes_initialize_connection": "volumes.initialize_connection",
"volumes_list": "volumes.list",
"volumes_manage": "volumes.manage",
"volumes_migrate_volume": "volumes.migrate_volume",
"volumes_migrate_volume_completion": "volumes.migrate_volume_completion",
"volumes_promote": "volumes.promote",
"volumes_reenable": "volumes.reenable",
"volumes_reserve": "volumes.reserve",
"volumes_reset_state": "volumes.reset_state",
"volumes_retype": "volumes.retype",
"volumes_roll_detaching": "volumes.roll_detaching",
"volumes_set_bootable": "volumes.set_bootable",
"volumes_set_metadata": "volumes.set_metadata",
"volumes_terminate_connection": "volumes.terminate_connection",
"volumes_unmanage": "volumes.unmanage",
"volumes_unreserve": "volumes.unreserve",
"volumes_update": "volumes.update",
"volumes_update_all_metadata": "volumes.update_all_metadata",
"volumes_update_readonly_flag": "volumes.update_readonly_flag",
"volumes_upload_to_image": "volumes.upload_to_image",
"volumes_write_to_completion_cache": "volumes.write_to_completion_cache"
}
}

View File

@ -0,0 +1,32 @@
# Copyright 2014 - Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from mistral.actions.openstack.action_generator import generators
from mistral.actions.openstack import actions
from mistral.tests import base
class CinderGeneratorTest(base.BaseTest):
def test_generator(self):
action_name = "cinder.volumes_list"
generator = generators.CinderActionGenerator
action_classes = generator.create_actions()
action = self._assert_single_item(
action_classes,
name=action_name
)
self.assertIsNotNone(generator)
self.assertTrue(issubclass(action['class'], actions.CinderAction))
self.assertEqual("volumes.list", action['class'].client_method_name)

View File

@ -78,3 +78,15 @@ class OpenStackActionTest(base.BaseTestCase):
self.assertTrue(mocked().show_network.called)
mocked().show_network.assert_called_once_with(id="1234-abcd")
@mock.patch.object(actions.CinderAction, '_get_client')
def test_cinder_action(self, mocked):
method_name = "volumes.get"
action_class = actions.CinderAction
action_class.client_method_name = method_name
params = {'volume': '1234-abcd'}
action = action_class(**params)
action.run()
self.assertTrue(mocked().volumes.get.called)
mocked().volumes.get.assert_called_once_with(volume="1234-abcd")

View File

@ -55,11 +55,15 @@ def client_for_trusts(trust_id):
return _admin_client(trust_id=trust_id)
def get_endpoint_for_project(service_name):
def get_endpoint_for_project(service_name=None, service_type=None):
admin_project_name = CONF.keystone_authtoken.admin_tenant_name
keystone_client = _admin_client(project_name=admin_project_name)
service_list = keystone_client.services.list()
service_id = [s.id for s in service_list if s.name == service_name][0]
if service_name:
service_id = [s.id for s in service_list if s.name == service_name][0]
elif service_type:
service_id = [s.id for s in service_list if s.type == service_type][0]
return keystone_client.endpoints.find(service_id=service_id,
interface='public').url

View File

@ -15,6 +15,7 @@ oslo.config>=1.4.0 # Apache-2.0
oslo.db>=1.0.0 # Apache-2.0
oslo.messaging>=1.4.0
paramiko>=1.13.0
python-cinderclient>=1.1.0
python-heatclient>=0.2.9
python-keystoneclient>=0.10.0
python-neutronclient>=2.3.6,<3