Decouple cloud backends
This is an attempt to fix stevedore confusion when loading plugins. It also removes the ceilometer backend which is not used anywhere Change-Id: Ic4f6165ca6c89daa24946126feeb23cdd431be0c
This commit is contained in:
parent
730b6d0127
commit
9763e308f3
|
@ -41,7 +41,6 @@ class SenlinDriver(object):
|
|||
self.network = backend.network
|
||||
self.octavia = backend.octavia
|
||||
self.orchestration = backend.orchestration
|
||||
self.telemetry = backend.telemetry
|
||||
self.identity = backend.identity
|
||||
self.message = backend.message
|
||||
self.workflow = backend.workflow
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
import docker
|
||||
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
|
||||
class DockerClient(object):
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
# 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 senlin.drivers import base
|
||||
from senlin.drivers.openstack import sdk
|
||||
|
||||
|
||||
class CeilometerClient(base.DriverBase):
|
||||
'''Ceilometer V2 driver.'''
|
||||
|
||||
def __init__(self, params):
|
||||
super(CeilometerClient, self).__init__(params)
|
||||
self.conn = sdk.create_connection(params)
|
||||
|
||||
@sdk.translate_exception
|
||||
def alarm_create(self, **attrs):
|
||||
return self.conn.telemetry.create_alarm(**attrs)
|
||||
|
||||
@sdk.translate_exception
|
||||
def alarm_delete(self, value, ignore_missing=True):
|
||||
return self.conn.telemetry.delete_alarm(value, ignore_missing)
|
||||
|
||||
@sdk.translate_exception
|
||||
def alarm_find(self, name_or_id, ignore_missing=True):
|
||||
return self.conn.telemetry.find_alarm(name_or_id, ignore_missing)
|
||||
|
||||
@sdk.translate_exception
|
||||
def alarm_get(self, value):
|
||||
return self.conn.telemetry.get_alarm(value)
|
||||
|
||||
@sdk.translate_exception
|
||||
def alarm_list(self, **query):
|
||||
return self.conn.telemetry.alarms(**query)
|
||||
|
||||
@sdk.translate_exception
|
||||
def alarm_update(self, value, **attrs):
|
||||
return self.conn.telemetry.update_alarm(value, **attrs)
|
||||
|
||||
@sdk.translate_exception
|
||||
def sample_create(self, **attrs):
|
||||
return self.conn.telemetry.create_sample(**attrs)
|
|
@ -1,80 +0,0 @@
|
|||
# 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 oslo_utils import uuidutils
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack_test import sdk
|
||||
|
||||
|
||||
class MistralClient(base.DriverBase):
|
||||
'''Fake mistral V2 driver for test.'''
|
||||
|
||||
def __init__(self, ctx):
|
||||
|
||||
self.fake_workflow = {
|
||||
'created_at': '1970-01-01T00:00:00.000000',
|
||||
'definition': 'workflow_def',
|
||||
'id': 'ffaed25e-46f5-4089-8e20-b3b4722fd597',
|
||||
'input': {
|
||||
'cluster_id': '8c74607c-5a74-4490-9414-a3475b1926c2',
|
||||
'node_id': 'fba2cc5d-706f-4631-9577-3956048d13a2',
|
||||
'flavor_id': '1'
|
||||
},
|
||||
'name': "cluster-coldmigration",
|
||||
'project_id': 'a7eb669e9819420ea4bd1453e672c0a7',
|
||||
'scope': 'private',
|
||||
'tags': [
|
||||
'large',
|
||||
'expensive'
|
||||
],
|
||||
'updated_at': '1970-01-01T00:00:00.000000',
|
||||
}
|
||||
|
||||
self.fake_workflow_create = {
|
||||
'scope': 'private',
|
||||
'id': 'ffaed25e-46f5-4089-8e20-b3b4722fd597',
|
||||
'definition': 'workflow_def',
|
||||
}
|
||||
|
||||
self.fake_execution_create = {
|
||||
'id': 'ffaed25e-46f5-4089-8e20-b3b4722fd597',
|
||||
'workflow_name': 'cluster-coldmigration',
|
||||
'input': {
|
||||
'cluster_id': '8c74607c-5a74-4490-9414-a3475b1926c2',
|
||||
'node_id': 'fba2cc5d-706f-4631-9577-3956048d13a2',
|
||||
'flavor_id': '1'
|
||||
}
|
||||
}
|
||||
|
||||
def wait_for_execution(self, execution, status='SUCCESS',
|
||||
failures=['ERROR'], interval=2,
|
||||
timeout=None):
|
||||
return
|
||||
|
||||
def workflow_find(self, name_or_id, ignore_missing=True):
|
||||
return sdk.FakeResourceObject(self.fake_workflow)
|
||||
|
||||
def workflow_delete(self, workflow, ignore_missing=True):
|
||||
return
|
||||
|
||||
def execution_delete(self, execution, ignore_missing=True):
|
||||
return
|
||||
|
||||
def workflow_create(self, definition, scope):
|
||||
self.fake_workflow_create['id'] = uuidutils.generate_uuid()
|
||||
return sdk.FakeResourceObject(self.fake_workflow_create)
|
||||
|
||||
def execution_create(self, name, inputs):
|
||||
self.fake_execution_create['id'] = uuidutils.generate_uuid()
|
||||
return sdk.FakeResourceObject(self.fake_execution_create)
|
|
@ -1,28 +0,0 @@
|
|||
# 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.
|
||||
|
||||
|
||||
class FakeResourceObject(object):
|
||||
'''Generate a fake SDK resource object based on given dictionary'''
|
||||
def __init__(self, params):
|
||||
for key in params:
|
||||
setattr(self, key, params[key])
|
||||
|
||||
def to_dict(self):
|
||||
'''Override this function in subclass to handle special attributes'''
|
||||
data = {}
|
||||
for attr in dir(self):
|
||||
if not attr.startswith('__'):
|
||||
# Exclude built-in attributes of python object
|
||||
data[attr] = getattr(self, attr)
|
||||
|
||||
return data
|
|
@ -10,18 +10,18 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from senlin.drivers.openstack import ceilometer_v2
|
||||
from senlin.drivers.openstack import cinder_v2
|
||||
from senlin.drivers.openstack import heat_v1
|
||||
from senlin.drivers.openstack import keystone_v3
|
||||
from senlin.drivers.openstack import lbaas
|
||||
from senlin.drivers.openstack import mistral_v2
|
||||
from senlin.drivers.openstack import neutron_v2
|
||||
from senlin.drivers.openstack import nova_v2
|
||||
from senlin.drivers.openstack import octavia_v2
|
||||
from senlin.drivers.openstack import zaqar_v2
|
||||
from senlin.drivers.os import cinder_v2
|
||||
from senlin.drivers.os import heat_v1
|
||||
from senlin.drivers.os import keystone_v3
|
||||
from senlin.drivers.os import lbaas
|
||||
from senlin.drivers.os import mistral_v2
|
||||
from senlin.drivers.os import neutron_v2
|
||||
from senlin.drivers.os import nova_v2
|
||||
from senlin.drivers.os import octavia_v2
|
||||
from senlin.drivers.os import zaqar_v2
|
||||
|
||||
|
||||
block_storage = cinder_v2.CinderClient
|
||||
compute = nova_v2.NovaClient
|
||||
identity = keystone_v3.KeystoneClient
|
||||
loadbalancing = lbaas.LoadBalancerDriver
|
||||
|
@ -29,6 +29,4 @@ message = zaqar_v2.ZaqarClient
|
|||
network = neutron_v2.NeutronClient
|
||||
octavia = octavia_v2.OctaviaClient
|
||||
orchestration = heat_v1.HeatClient
|
||||
telemetry = ceilometer_v2.CeilometerClient
|
||||
workflow = mistral_v2.MistralClient
|
||||
block_storage = cinder_v2.CinderClient
|
|
@ -11,7 +11,7 @@
|
|||
# under the License.
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
|
||||
class CinderClient(base.DriverBase):
|
|
@ -11,7 +11,7 @@
|
|||
# under the License.
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
|
||||
class GlanceClient(base.DriverBase):
|
|
@ -13,7 +13,7 @@
|
|||
from oslo_config import cfg
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
|
||||
class HeatClient(base.DriverBase):
|
|
@ -14,7 +14,7 @@ from oslo_config import cfg
|
|||
from oslo_log import log
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
|
@ -19,8 +19,8 @@ from oslo_log import log as logging
|
|||
from senlin.common import exception
|
||||
from senlin.common.i18n import _
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack import neutron_v2 as neutronclient
|
||||
from senlin.drivers.openstack import octavia_v2 as octaviaclient
|
||||
from senlin.drivers.os import neutron_v2 as neutronclient
|
||||
from senlin.drivers.os import octavia_v2 as octaviaclient
|
||||
from senlin.engine import node as nodem
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
|
@ -11,8 +11,9 @@
|
|||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
|
||||
class MistralClient(base.DriverBase):
|
|
@ -13,7 +13,7 @@
|
|||
from oslo_utils import uuidutils
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
|
||||
class NeutronClient(base.DriverBase):
|
|
@ -14,7 +14,7 @@ from oslo_config import cfg
|
|||
from oslo_log import log
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
# under the License.
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
|
||||
class OctaviaClient(base.DriverBase):
|
2
senlin/drivers/openstack/zaqar_v2.py → senlin/drivers/os/zaqar_v2.py
Executable file → Normal file
2
senlin/drivers/openstack/zaqar_v2.py → senlin/drivers/os/zaqar_v2.py
Executable file → Normal file
|
@ -13,7 +13,7 @@
|
|||
from openstack import exceptions as sdk_exc
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
|
||||
class ZaqarClient(base.DriverBase):
|
|
@ -10,17 +10,16 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from senlin.drivers.openstack import ceilometer_v2
|
||||
from senlin.drivers.openstack import keystone_v3
|
||||
|
||||
from senlin.drivers.openstack_test import cinder_v2
|
||||
from senlin.drivers.openstack_test import heat_v1
|
||||
from senlin.drivers.openstack_test import lbaas
|
||||
from senlin.drivers.openstack_test import mistral_v2
|
||||
from senlin.drivers.openstack_test import neutron_v2
|
||||
from senlin.drivers.openstack_test import nova_v2
|
||||
from senlin.drivers.openstack_test import octavia_v2
|
||||
from senlin.drivers.openstack_test import zaqar_v2
|
||||
from senlin.drivers.os_test import cinder_v2
|
||||
from senlin.drivers.os_test import heat_v1
|
||||
from senlin.drivers.os_test import keystone_v3
|
||||
from senlin.drivers.os_test import lbaas
|
||||
from senlin.drivers.os_test import mistral_v2
|
||||
from senlin.drivers.os_test import neutron_v2
|
||||
from senlin.drivers.os_test import nova_v2
|
||||
from senlin.drivers.os_test import octavia_v2
|
||||
from senlin.drivers.os_test import zaqar_v2
|
||||
|
||||
|
||||
block_storage = cinder_v2.CinderClient
|
||||
|
@ -31,5 +30,4 @@ message = zaqar_v2.ZaqarClient
|
|||
network = neutron_v2.NeutronClient
|
||||
octavia = octavia_v2.OctaviaClient
|
||||
orchestration = heat_v1.HeatClient
|
||||
telemetry = ceilometer_v2.CeilometerClient
|
||||
workflow = mistral_v2.MistralClient
|
|
@ -11,7 +11,7 @@
|
|||
# under the License.
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack_test import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
|
||||
class CinderClient(base.DriverBase):
|
|
@ -11,7 +11,7 @@
|
|||
# under the License.
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack_test import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
|
||||
class HeatClient(base.DriverBase):
|
|
@ -0,0 +1,154 @@
|
|||
# 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 oslo_config import cfg
|
||||
from oslo_log import log
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers import sdk
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class KeystoneClient(base.DriverBase):
|
||||
'''Keystone V3 driver.'''
|
||||
|
||||
def __init__(self, params):
|
||||
super(KeystoneClient, self).__init__(params)
|
||||
self.conn = sdk.create_connection(params)
|
||||
self.session = self.conn.session
|
||||
|
||||
@sdk.translate_exception
|
||||
def trust_get_by_trustor(self, trustor, trustee=None, project=None):
|
||||
'''Get trust by trustor.
|
||||
|
||||
Note we cannot provide two or more filters to keystone due to
|
||||
constraints in keystone implementation. We do additional filtering
|
||||
after the results are returned.
|
||||
|
||||
:param trustor: ID of the trustor;
|
||||
:param trustee: ID of the trustee;
|
||||
:param project: ID of the project to which the trust is scoped.
|
||||
:returns: The trust object or None if no matching trust is found.
|
||||
'''
|
||||
filters = {'trustor_user_id': trustor}
|
||||
|
||||
trusts = [t for t in self.conn.identity.trusts(**filters)]
|
||||
|
||||
for trust in trusts:
|
||||
if (trustee and trust.trustee_user_id != trustee):
|
||||
continue
|
||||
|
||||
if (project and trust.project_id != project):
|
||||
continue
|
||||
|
||||
return trust
|
||||
|
||||
return None
|
||||
|
||||
@sdk.translate_exception
|
||||
def trust_create(self, trustor, trustee, project, roles=None,
|
||||
impersonation=True):
|
||||
'''Create trust between two users.
|
||||
|
||||
:param trustor: ID of the user who is the trustor.
|
||||
:param trustee: ID of the user who is the trustee.
|
||||
:param project: Scope of the trust which is a project ID.
|
||||
:param roles: List of roles the trustee will inherit from the trustor.
|
||||
:param impersonation: Whether the trustee is allowed to impersonate
|
||||
the trustor.
|
||||
'''
|
||||
|
||||
if roles:
|
||||
role_list = [{'name': role} for role in roles]
|
||||
else:
|
||||
role_list = []
|
||||
params = {
|
||||
'trustor_user_id': trustor,
|
||||
'trustee_user_id': trustee,
|
||||
'project_id': project,
|
||||
'impersonation': impersonation,
|
||||
'allow_redelegation': True,
|
||||
'roles': role_list
|
||||
}
|
||||
|
||||
result = self.conn.identity.create_trust(**params)
|
||||
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
@sdk.translate_exception
|
||||
def get_token(cls, **creds):
|
||||
'''Get token using given credential'''
|
||||
|
||||
access_info = sdk.authenticate(**creds)
|
||||
return access_info['token']
|
||||
|
||||
@classmethod
|
||||
@sdk.translate_exception
|
||||
def get_user_id(cls, **creds):
|
||||
'''Get ID of the user with given credential'''
|
||||
|
||||
access_info = sdk.authenticate(**creds)
|
||||
return access_info['user_id']
|
||||
|
||||
@classmethod
|
||||
def get_service_credentials(cls, **kwargs):
|
||||
'''Senlin service credential to use with Keystone.
|
||||
|
||||
:param kwargs: An additional keyword argument list that can be used
|
||||
for customizing the default settings.
|
||||
'''
|
||||
|
||||
creds = {
|
||||
'auth_url': CONF.authentication.auth_url,
|
||||
'username': CONF.authentication.service_username,
|
||||
'password': CONF.authentication.service_password,
|
||||
'project_name': CONF.authentication.service_project_name,
|
||||
'user_domain_name': cfg.CONF.authentication.service_user_domain,
|
||||
'project_domain_name':
|
||||
cfg.CONF.authentication.service_project_domain,
|
||||
}
|
||||
creds.update(**kwargs)
|
||||
return creds
|
||||
|
||||
@sdk.translate_exception
|
||||
def validate_regions(self, regions):
|
||||
"""Check whether the given regions are valid.
|
||||
|
||||
:param regions: A list of regions for validation.
|
||||
:returns: A list of regions that are found available on keystone.
|
||||
"""
|
||||
region_list = self.conn.identity.regions()
|
||||
known = [r['id'] for r in region_list]
|
||||
|
||||
validated = []
|
||||
for r in regions:
|
||||
if r in known:
|
||||
validated.append(r)
|
||||
else:
|
||||
LOG.warning('Region %s is not found.', r)
|
||||
|
||||
return validated
|
||||
|
||||
@sdk.translate_exception
|
||||
def get_senlin_endpoint(self):
|
||||
'''Get Senlin service endpoint.'''
|
||||
region = cfg.CONF.default_region_name
|
||||
# TODO(Yanyan Hu): Currently, region filtering is unsupported in
|
||||
# session.get_endpoint(). Need to propose fix to openstacksdk.
|
||||
base = self.conn.session.get_endpoint(service_type='clustering',
|
||||
interface='public',
|
||||
region=region)
|
||||
|
||||
return base
|
|
@ -0,0 +1,42 @@
|
|||
# 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 senlin.drivers import base
|
||||
from senlin.drivers import sdk
|
||||
|
||||
|
||||
class MistralClient(base.DriverBase):
|
||||
'''Fake Mistral V2 driver.'''
|
||||
|
||||
def __init__(self, params):
|
||||
self.fake_workflow = {}
|
||||
self.fake_execution = {}
|
||||
|
||||
def workflow_create(self, definition, scope):
|
||||
return sdk.FakeResourceObject(self.fake_workflow)
|
||||
|
||||
def workflow_delete(self, workflow, ignore_missing=True):
|
||||
return None
|
||||
|
||||
def workflow_find(self, name_or_id, ignore_missing=True):
|
||||
return sdk.FakeResourceObject(self.fake_workflow)
|
||||
|
||||
def execution_create(self, name, inputs):
|
||||
return sdk.FakeResourceObject(self.fake_execution)
|
||||
|
||||
def execution_delete(self, execution, ignore_missing=True):
|
||||
return None
|
||||
|
||||
def wait_for_execution(self, execution, status='SUCCESS',
|
||||
failures=['ERROR'], interval=2,
|
||||
timeout=None):
|
||||
return None
|
|
@ -11,7 +11,7 @@
|
|||
# under the License.
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack_test import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
|
||||
class NeutronClient(base.DriverBase):
|
|
@ -15,7 +15,7 @@ import copy
|
|||
from oslo_utils import uuidutils
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack_test import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
|
||||
class NovaClient(base.DriverBase):
|
|
@ -11,7 +11,7 @@
|
|||
# under the License.
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack_test import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
FAKE_LB_ID = "607226db-27ef-4d41-ae89-f2a800e9c2db"
|
||||
FAKE_LISTENER_ID = "023f2e34-7806-443b-bfae-16c324569a3d"
|
|
@ -11,7 +11,7 @@
|
|||
# under the License.
|
||||
|
||||
from senlin.drivers import base
|
||||
from senlin.drivers.openstack_test import sdk
|
||||
from senlin.drivers import sdk
|
||||
|
||||
FAKE_SUBSCRIPTION_ID = "0d8dbb71-1538-42ac-99fb-bb52d0ad1b6f"
|
||||
FAKE_MESSAGE_ID = "51db6f78c508f17ddc924357"
|
||||
|
@ -51,24 +51,24 @@ class ZaqarClient(base.DriverBase):
|
|||
return True
|
||||
|
||||
def queue_delete(self, queue, ignore_missing=True):
|
||||
return
|
||||
return None
|
||||
|
||||
def subscription_create(self, queue_name, **attrs):
|
||||
return sdk.FakeResourceObject(self.fake_subscription)
|
||||
|
||||
def subscription_delete(self, queue_name, subscription,
|
||||
ignore_missing=True):
|
||||
return
|
||||
return None
|
||||
|
||||
def claim_create(self, queue_name, **attrs):
|
||||
return sdk.FakeResourceObject(self.fake_claim)
|
||||
|
||||
def claim_delete(self, queue_name, claim, ignore_missing=True):
|
||||
return
|
||||
return None
|
||||
|
||||
def message_delete(self, queue_name, message, claim_id=None,
|
||||
ignore_missing=True):
|
||||
return
|
||||
return None
|
||||
|
||||
def message_post(self, queue_name, message):
|
||||
return sdk.FakeResourceObject(self.fake_message)
|
|
@ -16,16 +16,15 @@ SDK Client
|
|||
import sys
|
||||
|
||||
import functools
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import six
|
||||
|
||||
from openstack import connection
|
||||
from openstack import exceptions as sdk_exc
|
||||
from openstack import profile
|
||||
from openstack import utils as sdk_utils
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_serialization import jsonutils
|
||||
from requests import exceptions as req_exc
|
||||
import six
|
||||
|
||||
from senlin.common import exception as senlin_exc
|
||||
|
||||
|
@ -138,3 +137,20 @@ def authenticate(**kwargs):
|
|||
}
|
||||
|
||||
return access_info
|
||||
|
||||
|
||||
class FakeResourceObject(object):
|
||||
'''Generate a fake SDK resource object based on given dictionary'''
|
||||
def __init__(self, params):
|
||||
for key in params:
|
||||
setattr(self, key, params[key])
|
||||
|
||||
def to_dict(self):
|
||||
'''Override this function in subclass to handle special attributes'''
|
||||
data = {}
|
||||
for attr in dir(self):
|
||||
if not attr.startswith('__'):
|
||||
# Exclude built-in attributes of python object
|
||||
data[attr] = getattr(self, attr)
|
||||
|
||||
return data
|
|
@ -301,6 +301,13 @@ class ClusterAction(base.Action):
|
|||
result, reason = self._update_nodes(profile_id, self.entity.nodes)
|
||||
return result, reason
|
||||
|
||||
def _handle_lifecycle_timeout(self, child):
|
||||
for action_id, node_id in child:
|
||||
status = ao.Action.check_status(self.context, action_id, 0)
|
||||
if (status == consts.ACTION_WAITING_LIFECYCLE_COMPLETION):
|
||||
ao.Action.update(self.context, action_id,
|
||||
{'status': base.Action.READY})
|
||||
|
||||
def _delete_nodes(self, node_ids):
|
||||
action_name = consts.NODE_DELETE
|
||||
|
||||
|
@ -319,11 +326,10 @@ class ClusterAction(base.Action):
|
|||
lifecycle_hook_params = lifecycle_hook.get('params')
|
||||
if lifecycle_hook_type == "zaqar":
|
||||
lifecycle_hook_target = lifecycle_hook_params.get('queue')
|
||||
elif lifecycle_hook_type == "webhook":
|
||||
lifecycle_hook_target = lifecycle_hook_params.get('url')
|
||||
else:
|
||||
return self.RES_ERROR, _("Invalid lifecycle hook type "
|
||||
"specified in deletion policy")
|
||||
# lifecycle_hook_target = lifecycle_hook_params.get('url')
|
||||
return self.RES_ERROR, _("Lifecycle hook type '%s' is not "
|
||||
"implemented") % lifecycle_hook_type
|
||||
|
||||
child = []
|
||||
for node_id in node_ids:
|
||||
|
@ -355,22 +361,18 @@ class ClusterAction(base.Action):
|
|||
ao.Action.update(self.context, action_id,
|
||||
{'status': status})
|
||||
if lifecycle_hook:
|
||||
if lifecycle_hook_type == "zaqar":
|
||||
# post message to zaqar
|
||||
kwargs = {
|
||||
'user': self.context.user_id,
|
||||
'project': self.context.project_id,
|
||||
'domain': self.context.domain_id
|
||||
}
|
||||
# lifecycle_hook_type has to be "zaqar"
|
||||
# post message to zaqar
|
||||
kwargs = {
|
||||
'user': self.context.user_id,
|
||||
'project': self.context.project_id,
|
||||
'domain': self.context.domain_id
|
||||
}
|
||||
|
||||
notifier = msg.Message(lifecycle_hook_target, **kwargs)
|
||||
notifier.post_lifecycle_hook_message(
|
||||
action_id, node_id,
|
||||
consts.LIFECYCLE_NODE_TERMINATION)
|
||||
else:
|
||||
reason = _("Lifecycle hook type '{}' is not "
|
||||
"implemented").format(lifecycle_hook_type)
|
||||
return self.RES_ERROR, reason
|
||||
notifier = msg.Message(lifecycle_hook_target, **kwargs)
|
||||
notifier.post_lifecycle_hook_message(
|
||||
action_id, node_id,
|
||||
consts.LIFECYCLE_NODE_TERMINATION)
|
||||
|
||||
res = None
|
||||
if lifecycle_hook:
|
||||
|
@ -378,13 +380,7 @@ class ClusterAction(base.Action):
|
|||
res, reason = self._wait_for_dependents(lifecycle_hook_timeout)
|
||||
|
||||
if res == self.RES_LIFECYCLE_HOOK_TIMEOUT:
|
||||
for action_id, node_id in child:
|
||||
status = ao.Action.check_status(self.context,
|
||||
action_id, 0)
|
||||
if (status ==
|
||||
consts.ACTION_WAITING_LIFECYCLE_COMPLETION):
|
||||
ao.Action.update(self.context, action_id,
|
||||
{'status': base.Action.READY})
|
||||
self._handle_lifecycle_timeout(child)
|
||||
|
||||
if res is None or res == self.RES_LIFECYCLE_HOOK_TIMEOUT:
|
||||
dispatcher.start_action()
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import mock
|
||||
|
||||
from senlin.drivers.openstack import ceilometer_v2
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.tests.unit.common import base
|
||||
from senlin.tests.unit.common import utils
|
||||
|
||||
|
||||
class TestCeilometerV2(base.SenlinTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestCeilometerV2, self).setUp()
|
||||
|
||||
self.ctx = utils.dummy_context()
|
||||
self.conn_params = self.ctx.to_dict()
|
||||
self.mock_conn = mock.Mock()
|
||||
self.mock_create = self.patchobject(
|
||||
sdk, 'create_connection',
|
||||
return_value=self.mock_conn)
|
||||
|
||||
def test_init(self):
|
||||
d = ceilometer_v2.CeilometerClient(self.conn_params)
|
||||
self.mock_create.assert_called_once_with(self.conn_params)
|
||||
self.assertEqual(self.mock_conn, d.conn)
|
||||
|
||||
def test_alarm_create(self):
|
||||
d = ceilometer_v2.CeilometerClient(self.conn_params)
|
||||
d.alarm_create(name='test_alarm')
|
||||
self.mock_conn.telemetry.create_alarm.assert_called_once_with(
|
||||
name='test_alarm')
|
||||
|
||||
def test_alarm_delete(self):
|
||||
d = ceilometer_v2.CeilometerClient(self.conn_params)
|
||||
d.alarm_delete('foo', True)
|
||||
self.mock_conn.telemetry.delete_alarm.assert_called_once_with(
|
||||
'foo', True)
|
||||
|
||||
self.mock_conn.telemetry.delete_alarm.reset_mock()
|
||||
|
||||
d.alarm_delete('foo', False)
|
||||
self.mock_conn.telemetry.delete_alarm.assert_called_once_with(
|
||||
'foo', False)
|
||||
|
||||
self.mock_conn.telemetry.delete_alarm.reset_mock()
|
||||
|
||||
d.alarm_delete('foo')
|
||||
self.mock_conn.telemetry.delete_alarm.assert_called_once_with(
|
||||
'foo', True)
|
||||
|
||||
def test_alarm_find(self):
|
||||
d = ceilometer_v2.CeilometerClient(self.conn_params)
|
||||
d.alarm_find('fakeid', True)
|
||||
self.mock_conn.telemetry.find_alarm.assert_called_once_with(
|
||||
'fakeid', True)
|
||||
|
||||
self.mock_conn.telemetry.find_alarm.reset_mock()
|
||||
|
||||
d.alarm_find('fakeid', False)
|
||||
self.mock_conn.telemetry.find_alarm.assert_called_once_with(
|
||||
'fakeid', False)
|
||||
|
||||
self.mock_conn.telemetry.find_alarm.reset_mock()
|
||||
|
||||
d.alarm_find('fakeid')
|
||||
self.mock_conn.telemetry.find_alarm.assert_called_once_with(
|
||||
'fakeid', True)
|
||||
|
||||
def test_alarm_get(self):
|
||||
d = ceilometer_v2.CeilometerClient(self.conn_params)
|
||||
d.alarm_get('fakeid')
|
||||
self.mock_conn.telemetry.get_alarm.assert_called_once_with('fakeid')
|
||||
|
||||
def test_alarm_list(self):
|
||||
d = ceilometer_v2.CeilometerClient(self.conn_params)
|
||||
d.alarm_list()
|
||||
self.mock_conn.telemetry.alarms.assert_called_once_with()
|
||||
|
||||
self.mock_conn.telemetry.alarms.reset_mock()
|
||||
|
||||
d.alarm_list(name='fakename')
|
||||
self.mock_conn.telemetry.alarms.assert_called_once_with(
|
||||
name='fakename')
|
||||
|
||||
def test_alarm_update(self):
|
||||
d = ceilometer_v2.CeilometerClient(self.conn_params)
|
||||
attrs = {'enabled': False}
|
||||
d.alarm_update('fakeid', **attrs)
|
||||
self.mock_conn.telemetry.update_alarm.assert_called_once_with(
|
||||
'fakeid', **attrs)
|
||||
|
||||
def test_sample_create(self):
|
||||
d = ceilometer_v2.CeilometerClient(self.conn_params)
|
||||
attrs = {'foo': 'bar'}
|
||||
d.sample_create(**attrs)
|
||||
self.mock_conn.telemetry.create_sample.assert_called_once_with(
|
||||
foo='bar')
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
import mock
|
||||
|
||||
from senlin.drivers.openstack import cinder_v2
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers.os import cinder_v2
|
||||
from senlin.drivers import sdk
|
||||
from senlin.tests.unit.common import base
|
||||
from senlin.tests.unit.common import utils
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
import mock
|
||||
|
||||
from senlin.drivers.openstack import glance_v2
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers.os import glance_v2
|
||||
from senlin.drivers import sdk
|
||||
from senlin.tests.unit.common import base
|
||||
from senlin.tests.unit.common import utils
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
import mock
|
||||
from oslo_config import cfg
|
||||
|
||||
from senlin.drivers.openstack import heat_v1
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers.os import heat_v1
|
||||
from senlin.drivers import sdk
|
||||
from senlin.tests.unit.common import base
|
||||
from senlin.tests.unit.common import utils
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ import copy
|
|||
import mock
|
||||
from oslo_config import cfg
|
||||
|
||||
from senlin.drivers.openstack import keystone_v3 as kv3
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers.os import keystone_v3 as kv3
|
||||
from senlin.drivers import sdk
|
||||
from senlin.tests.unit.common import base
|
||||
from senlin.tests.unit.common import utils
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@ from oslo_context import context as oslo_context
|
|||
|
||||
from senlin.common import exception
|
||||
from senlin.common.i18n import _
|
||||
from senlin.drivers.openstack import lbaas
|
||||
from senlin.drivers.openstack import neutron_v2
|
||||
from senlin.drivers.openstack import octavia_v2
|
||||
from senlin.drivers.os import lbaas
|
||||
from senlin.drivers.os import neutron_v2
|
||||
from senlin.drivers.os import octavia_v2
|
||||
from senlin.engine import node as nodem
|
||||
from senlin.tests.unit.common import base
|
||||
from senlin.tests.unit.common import utils
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
import mock
|
||||
|
||||
from senlin.drivers.openstack import mistral_v2
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers.os import mistral_v2
|
||||
from senlin.drivers import sdk
|
||||
from senlin.tests.unit.common import base
|
||||
from senlin.tests.unit.common import utils
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
import mock
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from senlin.drivers.openstack import neutron_v2
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers.os import neutron_v2
|
||||
from senlin.drivers import sdk
|
||||
from senlin.tests.unit.common import base
|
||||
from senlin.tests.unit.common import utils
|
||||
|
|
@ -13,8 +13,8 @@
|
|||
import mock
|
||||
from oslo_config import cfg
|
||||
|
||||
from senlin.drivers.openstack import nova_v2
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers.os import nova_v2
|
||||
from senlin.drivers import sdk
|
||||
from senlin.tests.unit.common import base
|
||||
from senlin.tests.unit.common import utils
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
import mock
|
||||
|
||||
from senlin.drivers.openstack import octavia_v2
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers.os import octavia_v2
|
||||
from senlin.drivers import sdk
|
||||
from senlin.tests.unit.common import base
|
||||
from senlin.tests.unit.common import utils
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ from requests import exceptions as req_exc
|
|||
import six
|
||||
|
||||
from senlin.common import exception as senlin_exc
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers import sdk
|
||||
from senlin.tests.unit.common import base
|
||||
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ import mock
|
|||
|
||||
from openstack import exceptions as sdk_exc
|
||||
|
||||
from senlin.drivers.openstack import sdk
|
||||
from senlin.drivers.openstack import zaqar_v2
|
||||
from senlin.drivers.os import zaqar_v2
|
||||
from senlin.drivers import sdk
|
||||
from senlin.tests.unit.common import base
|
||||
from senlin.tests.unit.common import utils
|
||||
|
||||
|
|
|
@ -286,8 +286,7 @@ class ClusterDeleteTest(base.SenlinTestCase):
|
|||
# assertions (other assertions are skipped)
|
||||
self.assertEqual(action.RES_ERROR, res_code)
|
||||
self.assertEqual(
|
||||
'Invalid lifecycle hook type specified in deletion policy',
|
||||
res_msg)
|
||||
"Lifecycle hook type 'unknown_type' is not implemented", res_msg)
|
||||
|
||||
@mock.patch.object(ao.Action, 'update')
|
||||
@mock.patch.object(ab.Action, 'create')
|
||||
|
@ -317,8 +316,7 @@ class ClusterDeleteTest(base.SenlinTestCase):
|
|||
# assertions (other assertions are skipped)
|
||||
self.assertEqual(action.RES_ERROR, res_code)
|
||||
self.assertEqual(
|
||||
'Lifecycle hook type \'webhook\' is not implemented',
|
||||
res_msg)
|
||||
"Lifecycle hook type \'webhook\' is not implemented", res_msg)
|
||||
|
||||
@mock.patch.object(ao.Action, 'update')
|
||||
@mock.patch.object(ab.Action, 'create')
|
||||
|
|
|
@ -41,8 +41,8 @@ oslo.policy.policies =
|
|||
senlin = senlin.common.policies:list_rules
|
||||
|
||||
senlin.drivers =
|
||||
openstack = senlin.drivers.openstack
|
||||
openstack_test = senlin.drivers.openstack_test
|
||||
openstack = senlin.drivers.os
|
||||
openstack_test = senlin.drivers.os_test
|
||||
|
||||
senlin.profiles =
|
||||
os.heat.stack-1.0 = senlin.profiles.os.heat.stack:StackProfile
|
||||
|
|
Loading…
Reference in New Issue