Add Trove to mistral actions

Implement Trove actions in mistral, useful for Trove automated backups

Change-Id: I638a7cad1d12d5e08a8a1741e72a75fd19d62233
Implements: blueprint trove-api-actions
This commit is contained in:
Bhaskar Duvvuri 2015-11-19 23:23:14 +05:30
parent c11ef5c435
commit 56e62a5bee
8 changed files with 167 additions and 4 deletions

View File

@ -23,5 +23,6 @@ def all_generators():
generators.HeatActionGenerator,
generators.NeutronActionGenerator,
generators.CinderActionGenerator,
generators.CeilometerActionGenerator
generators.CeilometerActionGenerator,
generators.TroveActionGenerator
]

View File

@ -49,3 +49,8 @@ class CinderActionGenerator(base.OpenStackActionGenerator):
class CeilometerActionGenerator(base.OpenStackActionGenerator):
action_namespace = "ceilometer"
base_action_class = actions.CeilometerAction
class TroveActionGenerator(base.OpenStackActionGenerator):
action_namespace = "trove"
base_action_class = actions.TroveAction

View File

@ -20,6 +20,8 @@ from keystoneclient import httpclient
from keystoneclient.v3 import client as keystoneclient
from neutronclient.v2_0 import client as neutronclient
from novaclient import client as novaclient
from troveclient import client as troveclient
from oslo_config import cfg
from oslo_log import log
@ -231,3 +233,38 @@ class CinderAction(base.OpenStackAction):
@classmethod
def _get_fake_client(cls):
return cls._client_class()
class TroveAction(base.OpenStackAction):
_client_class = troveclient.Client
def _get_client(self):
ctx = context.ctx()
LOG.debug("Trove action security context: %s" % ctx)
trove_endpoint = keystone_utils.get_endpoint_for_project(
service_type='database'
)
trove_url = keystone_utils.format_url(
trove_endpoint.url,
{'tenant_id': ctx.project_id}
)
client = self._client_class(
ctx.user_name,
ctx.auth_token,
project_id=ctx.project_id,
auth_url=trove_url,
region_name=trove_endpoint.region
)
client.client.auth_token = ctx.auth_token
client.client.management_url = trove_url
return client
@classmethod
def _get_fake_client(cls):
return cls._client_class()

View File

@ -795,5 +795,75 @@
"volumes_update_all_metadata": "volumes.update_all_metadata",
"volumes_update_readonly_flag": "volumes.update_readonly_flag",
"volumes_upload_to_image": "volumes.upload_to_image"
},
"trove": {
"_comment": "It uses troveclient.v1.",
"flavors_list": "flavors.list",
"flavors_list_datastore_version_associated_flavors": "flavors.list_datastore_version_associated_flavors",
"flavors_get": "flavors.get",
"users_create": "users.create",
"users_delete": "users.delete",
"users_list": "users.list",
"users_get": "users.get",
"users_update_attributes": "users.update_attributes",
"users_list_access": "users.list_access",
"users_grant": "users.grant",
"users_revoke": "users.revoke",
"users_change_passwords": "users.change_passwords",
"databases_create": "databases.create",
"databases_delete": "databases.delete",
"databases_list": "databases.list",
"backups_list": "backups.list",
"backups_create": "backups.create",
"backups_get": "backups.get",
"backups_delete": "backups.delete",
"clusters_create": "clusters.create",
"clusters_get": "clusters.get",
"clusters_list": "clusters.list",
"clusters_delete": "clusters.delete",
"clusters_add_shard": "clusters.add_shard",
"clusters_grow": "clusters.grow",
"clusters_shrink": "clusters.shrink",
"instances_create": "instances.create",
"instances_modify": "instances.modify",
"instances_edit": "instances.edit",
"instances_list": "instances.list",
"instances_get": "instances.get",
"instances_backups": "instances.backups",
"instances_delete": "instances.delete",
"instances_resize_volume": "instances.resize_volume",
"instances_resize_instance": "instances.resize_instance",
"instances_restart": "instances.restart",
"instances_configuration": "instances.configuration",
"instances_promote_to_replica_source": "instances.promote_to_replica_source",
"instances_eject_replica_source": "instances.eject_replica_source",
"limits_list": "limits.list",
"root_create": "root.create",
"root_create_instance_root": "root.create_instance_root",
"root_create_cluster_root": "root.create_cluster_root",
"root_is_root_enabled": "root.is_root_enabled",
"root_is_instance_root_enabled": "root.is_instance_root_enabled",
"root_is_cluster_root_enabled": "root.is_cluster_root_enabled",
"security_group_rules_create": "security_group_rules.create",
"security_group_rules_delete": "security_group_rules.delete",
"security_groups_list": "security_groups.list",
"security_groups_get": "security_groups.get",
"datastores_list": "datastores.list",
"datastores_get": "datastores.get",
"datastore_versions_list": "datastore_versions.list",
"datastore_versions_get": "datastore_versions.get",
"datastore_versions_get_by_uuid": "datastore_versions.get_by_uuid",
"datastore_versions_update": "datastore_versions.update",
"configurations_get": "configurations.get",
"configurations_instances": "configurations.instances",
"configurations_list": "configurations.list",
"configurations_create": "configurations.create",
"configurations_update": "configurations.update",
"configurations_edit": "configurations.edit",
"configurations_delete": "configurations.delete",
"configuration_parameters_parameters": "configuration_parameters.parameters",
"configuration_parameters_get_parameter": "configuration_parameters.get_parameter",
"configuration_parameters_parameters_by_version": "configuration_parameters.parameters_by_version",
"configuration_parameters_get_parameter_by_version": "configuration_parameters.get_parameter_by_version"
}
}
}

View File

@ -102,3 +102,15 @@ class OpenStackActionTest(base.BaseTestCase):
self.assertTrue(mocked().alarms.get.called)
mocked().alarms.get.assert_called_once_with(alarm_id="1234-abcd")
@mock.patch.object(actions.TroveAction, '_get_client')
def test_trove_action(self, mocked):
method_name = "instances.get"
action_class = actions.TroveAction
action_class.client_method_name = method_name
params = {'instance': '1234-abcd'}
action = action_class(**params)
action.run()
self.assertTrue(mocked().instances.get.called)
mocked().instances.get.assert_called_once_with(instance="1234-abcd")

View File

@ -0,0 +1,32 @@
# Copyright 2015 - AT&T Services, 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.unit import base
class TroveGeneratorTest(base.BaseTest):
def test_generator(self):
action_name = "trove.instances_list"
generator = generators.TroveActionGenerator
action_classes = generator.create_actions()
action = self._assert_single_item(
action_classes,
name=action_name
)
self.assertIsNotNone(generator)
self.assertTrue(issubclass(action['class'], actions.TroveAction))
self.assertEqual("instances.list", action['class'].client_method_name)

View File

@ -28,6 +28,7 @@ python-heatclient>=0.6.0
python-keystoneclient!=1.8.0,>=1.6.0
python-neutronclient>=2.6.0
python-novaclient!=2.33.0,>=2.29.0
python-troveclient>=1.2.0
PyYAML>=3.1.0
requests!=2.8.0,>=2.5.2
retrying!=1.3.0,>=1.2.3 # Apache-2.0

View File

@ -28,7 +28,8 @@ from keystoneclient import base as keystone_base
from keystoneclient.v3 import client as keystoneclient
from novaclient import client as novaclient
from novaclient.openstack.common.apiclient import base as nova_base
from troveclient import base as trove_base
from troveclient.v1 import client as troveclient
# TODO(nmakhotkin): Find a rational way to do it for neutron.
# TODO(nmakhotkin): Implement recursive way of searching for managers
@ -60,7 +61,7 @@ BASE_HEAT_MANAGER = heat_base.HookableMixin
BASE_NOVA_MANAGER = nova_base.HookableMixin
BASE_KEYSTONE_MANAGER = keystone_base.Manager
BASE_CINDER_MANAGER = cinder_base.HookableMixin
BASE_TROVE_MANAGER = trove_base.HookableMixin
def get_parser():
parser = argparse.ArgumentParser(
@ -134,6 +135,8 @@ def get_ceilometer_client(**kwargs):
def get_cinder_client(**kwargs):
return cinderclient.Client()
def get_trove_client(**kwargs):
return troveclient.Client()
CLIENTS = {
'nova': get_nova_client,
@ -142,6 +145,7 @@ CLIENTS = {
'cinder': get_cinder_client,
'keystone': get_keystone_client,
'glance': get_glance_client,
'trove' : get_trove_client,
# 'neutron': get_nova_client
}
BASE_MANAGERS = {
@ -151,6 +155,7 @@ BASE_MANAGERS = {
'cinder': BASE_CINDER_MANAGER,
'keystone': BASE_KEYSTONE_MANAGER,
'glance': None,
'trove': BASE_TROVE_MANAGER,
# 'neutron': BASE_NOVA_MANAGER
}
NAMESPACES = {