Rename Bay DB, Object, and internal usage to Cluster

This is patch 3 of 3 to change the internal usage of the terms
Bay and BayModel.  This patch updates Bay to Cluster in DB and
Object as well as all the usages.  No functionality should be
changed by this patch, just naming and db updates.

Change-Id: Ife04b0f944ded03ca932d70e09e6766d09cf5d9f
Implements: blueprint rename-bay-to-cluster
This commit is contained in:
Jaycen Grant 2016-09-06 14:17:43 -07:00
parent 68463dd005
commit 729c2d0ab4
100 changed files with 2357 additions and 2214 deletions

View File

@ -143,12 +143,12 @@ class Controller(rest.RestController):
Example:
@base.Controller.api_version("1.1", "1.2")
@expose.expose(Cluster, types.uuid_or_name)
def get_one(self, bay_ident):
def get_one(self, cluster_ident):
{...code for versions 1.1 to 1.2...}
@base.Controller.api_version("1.3")
@expose.expose(Cluster, types.uuid_or_name)
def get_one(self, bay_ident):
def get_one(self, cluster_ident):
{...code for versions 1.3 to latest}
@min_ver: string representing minimum version

View File

@ -28,7 +28,7 @@ from magnum.api.controllers.v1 import collection
from magnum.api.controllers.v1 import types
from magnum.api import expose
from magnum.api import utils as api_utils
from magnum.api.validation import validate_bay_properties
from magnum.api.validation import validate_cluster_properties
from magnum.common import clients
from magnum.common import exception
from magnum.common import name_generator
@ -66,7 +66,7 @@ class Bay(base.APIBase):
self._baymodel_id = baymodel.uuid
except exception.ClusterTemplateNotFound as e:
# Change error code because 404 (NotFound) is inappropriate
# response for a POST request to create a Bay
# response for a POST request to create a Cluster
e.code = 400 # BadRequest
raise
elif value == wtypes.Unset:
@ -99,7 +99,7 @@ class Bay(base.APIBase):
stack_id = wsme.wsattr(wtypes.text, readonly=True)
"""Stack id of the heat stack"""
status = wtypes.Enum(str, *fields.BayStatus.ALL)
status = wtypes.Enum(str, *fields.ClusterStatus.ALL)
"""Status of the bay from the heat stack"""
status_reason = wtypes.text
@ -131,13 +131,43 @@ class Bay(base.APIBase):
super(Bay, self).__init__()
self.fields = []
for field in objects.Bay.fields:
for field in objects.Cluster.fields:
# Skip fields we do not expose.
if not hasattr(self, field):
continue
self.fields.append(field)
setattr(self, field, kwargs.get(field, wtypes.Unset))
# Set the renamed attributes for bay backwards compatibility
self.fields.append('baymodel_id')
if 'baymodel_id' in kwargs.keys():
setattr(self, 'cluster_template_id',
kwargs.get('baymodel_id', None))
setattr(self, 'baymodel_id',
kwargs.get('baymodel_id', None))
else:
setattr(self, 'baymodel_id', kwargs.get('cluster_template_id',
None))
self.fields.append('bay_create_timeout')
if 'bay_create_timeout' in kwargs.keys():
setattr(self, 'create_timeout',
kwargs.get('bay_create_timeout', wtypes.Unset))
setattr(self, 'bay_create_timeout',
kwargs.get('bay_create_timeout', wtypes.Unset))
else:
setattr(self, 'bay_create_timeout', kwargs.get('create_timeout',
wtypes.Unset))
self.fields.append('bay_faults')
if 'bay_faults' in kwargs.keys():
setattr(self, 'faults',
kwargs.get('bay_faults', wtypes.Unset))
setattr(self, 'bay_faults',
kwargs.get('bay_faults', wtypes.Unset))
else:
setattr(self, 'bay_faults', kwargs.get('faults', wtypes.Unset))
@staticmethod
def _convert_with_links(bay, url, expand=True):
if not expand:
@ -167,7 +197,7 @@ class Bay(base.APIBase):
master_count=1,
bay_create_timeout=15,
stack_id='49dc23f5-ffc9-40c3-9d34-7be7f9e34d63',
status=fields.BayStatus.CREATE_COMPLETE,
status=fields.ClusterStatus.CREATE_COMPLETE,
status_reason="CREATE completed successfully",
api_address='172.24.4.3',
node_addresses=['172.24.4.4', '172.24.4.5'],
@ -177,6 +207,24 @@ class Bay(base.APIBase):
container_version=None)
return cls._convert_with_links(sample, 'http://localhost:9511', expand)
def as_dict(self):
"""Render this object as a dict of its fields."""
# Override this for old bay values
d = super(Bay, self).as_dict()
d['cluster_template_id'] = d['baymodel_id']
del d['baymodel_id']
d['create_timeout'] = d['bay_create_timeout']
del d['bay_create_timeout']
if 'bay_faults' in d.keys():
d['faults'] = d['bay_faults']
del d['bay_faults']
return d
class BayPatchType(types.JsonPatchType):
_api_base = Bay
@ -239,12 +287,12 @@ class BaysController(base.Controller):
marker_obj = None
if marker:
marker_obj = objects.Bay.get_by_uuid(pecan.request.context,
marker)
marker_obj = objects.Cluster.get_by_uuid(pecan.request.context,
marker)
bays = objects.Bay.list(pecan.request.context, limit,
marker_obj, sort_key=sort_key,
sort_dir=sort_dir)
bays = objects.Cluster.list(pecan.request.context, limit,
marker_obj, sort_key=sort_key,
sort_dir=sort_dir)
return BayCollection.convert_with_links(bays, limit,
url=resource_url,
@ -323,13 +371,13 @@ class BaysController(base.Controller):
:param bay_ident: UUID of a bay or logical name of the bay.
"""
context = pecan.request.context
bay = api_utils.get_resource('Bay', bay_ident)
bay = api_utils.get_resource('Cluster', bay_ident)
policy.enforce(context, 'bay:get', bay,
action='bay:get')
bay = Bay.convert_with_links(bay)
if bay.status in fields.BayStatus.STATUS_FAILED:
if bay.status in fields.ClusterStatus.STATUS_FAILED:
bay.bay_faults = self._collect_fault_info(context, bay)
return bay
@ -342,8 +390,8 @@ class BaysController(base.Controller):
:param bay: a bay within the request body.
"""
new_bay = self._post(bay)
res_bay = pecan.request.rpcapi.bay_create(new_bay,
bay.bay_create_timeout)
res_bay = pecan.request.rpcapi.cluster_create(new_bay,
bay.bay_create_timeout)
# Set the HTTP Location Header
pecan.response.location = link.build_url('bays', res_bay.uuid)
@ -357,7 +405,8 @@ class BaysController(base.Controller):
:param bay: a bay within the request body.
"""
new_bay = self._post(bay)
pecan.request.rpcapi.bay_create_async(new_bay, bay.bay_create_timeout)
pecan.request.rpcapi.cluster_create_async(new_bay,
bay.bay_create_timeout)
return BayID(new_bay.uuid)
def _post(self, bay):
@ -378,7 +427,7 @@ class BaysController(base.Controller):
bay_dict['coe_version'] = None
bay_dict['container_version'] = None
new_bay = objects.Bay(context, **bay_dict)
new_bay = objects.Cluster(context, **bay_dict)
new_bay.uuid = uuid.uuid4()
return new_bay
@ -392,7 +441,7 @@ class BaysController(base.Controller):
:param patch: a json PATCH document to apply to this bay.
"""
bay = self._patch(bay_ident, patch)
res_bay = pecan.request.rpcapi.bay_update(bay)
res_bay = pecan.request.rpcapi.cluster_update(bay)
return Bay.convert_with_links(res_bay)
@base.Controller.api_version("1.2", "1.2") # noqa
@ -406,7 +455,7 @@ class BaysController(base.Controller):
:param patch: a json PATCH document to apply to this bay.
"""
bay = self._patch(bay_ident, patch)
pecan.request.rpcapi.bay_update_async(bay)
pecan.request.rpcapi.cluster_update_async(bay)
return BayID(bay.uuid)
@base.Controller.api_version("1.3") # noqa
@ -421,12 +470,12 @@ class BaysController(base.Controller):
:param patch: a json PATCH document to apply to this bay.
"""
bay = self._patch(bay_ident, patch)
pecan.request.rpcapi.bay_update_async(bay, rollback=rollback)
pecan.request.rpcapi.cluster_update_async(bay, rollback=rollback)
return BayID(bay.uuid)
def _patch(self, bay_ident, patch):
context = pecan.request.context
bay = api_utils.get_resource('Bay', bay_ident)
bay = api_utils.get_resource('Cluster', bay_ident)
policy.enforce(context, 'bay:update', bay,
action='bay:update')
try:
@ -436,7 +485,7 @@ class BaysController(base.Controller):
raise exception.PatchError(patch=patch, reason=e)
# Update only the fields that have changed
for field in objects.Bay.fields:
for field in objects.Cluster.fields:
try:
patch_val = getattr(new_bay, field)
except AttributeError:
@ -449,7 +498,7 @@ class BaysController(base.Controller):
delta = bay.obj_what_changed()
validate_bay_properties(delta)
validate_cluster_properties(delta)
return bay
@base.Controller.api_version("1.1", "1.1")
@ -461,7 +510,7 @@ class BaysController(base.Controller):
"""
bay = self._delete(bay_ident)
pecan.request.rpcapi.bay_delete(bay.uuid)
pecan.request.rpcapi.cluster_delete(bay.uuid)
@base.Controller.api_version("1.2") # noqa
@expose.expose(None, types.uuid_or_name, status_code=204)
@ -472,11 +521,11 @@ class BaysController(base.Controller):
"""
bay = self._delete(bay_ident)
pecan.request.rpcapi.bay_delete_async(bay.uuid)
pecan.request.rpcapi.cluster_delete_async(bay.uuid)
def _delete(self, bay_ident):
context = pecan.request.context
bay = api_utils.get_resource('Bay', bay_ident)
bay = api_utils.get_resource('Cluster', bay_ident)
policy.enforce(context, 'bay:delete', bay,
action='bay:delete')
return bay

View File

@ -46,7 +46,7 @@ class BayModel(base.APIBase):
name = wtypes.StringType(min_length=1, max_length=255)
"""The name of the Baymodel"""
coe = wtypes.Enum(str, *fields.BayType.ALL, mandatory=True)
coe = wtypes.Enum(str, *fields.ClusterType.ALL, mandatory=True)
"""The Container Orchestration Engine for this bay model"""
image_id = wsme.wsattr(wtypes.StringType(min_length=1, max_length=255),
@ -181,7 +181,7 @@ class BayModel(base.APIBase):
docker_volume_size=25,
docker_storage_driver='devicemapper',
cluster_distro='fedora-atomic',
coe=fields.BayType.KUBERNETES,
coe=fields.ClusterType.KUBERNETES,
http_proxy='http://proxy.com:123',
https_proxy='https://proxy.com:123',
no_proxy='192.168.0.1,192.168.0.2,192.168.0.3',

View File

@ -46,11 +46,11 @@ class Certificate(base.APIBase):
def _set_cluster_uuid(self, value):
if value and self._cluster_uuid != value:
try:
self._cluster = api_utils.get_resource('Bay', value)
self._cluster = api_utils.get_resource('Cluster', value)
self._cluster_uuid = self._cluster.uuid
except exception.ClusterNotFound as e:
# Change error code because 404 (NotFound) is inappropriate
# response for a POST request to create a Bay
# response for a POST request to create a Cluster
e.code = 400 # BadRequest
raise
elif value == wtypes.Unset:
@ -90,7 +90,8 @@ class Certificate(base.APIBase):
def get_cluster(self):
if not self._cluster:
self._cluster = api_utils.get_resource('Bay', self.cluster_uuid)
self._cluster = api_utils.get_resource('Cluster',
self.cluster_uuid)
return self._cluster
@staticmethod
@ -141,7 +142,7 @@ class CertificateController(base.Controller):
logical name of the cluster.
"""
context = pecan.request.context
cluster = api_utils.get_resource('Bay', cluster_ident)
cluster = api_utils.get_resource('Cluster', cluster_ident)
policy.enforce(context, 'certificate:get', cluster,
action='certificate:get')
certificate = pecan.request.rpcapi.get_ca_certificate(cluster)

View File

@ -28,7 +28,7 @@ from magnum.api.controllers.v1 import collection
from magnum.api.controllers.v1 import types
from magnum.api import expose
from magnum.api import utils as api_utils
from magnum.api.validation import validate_bay_properties
from magnum.api.validation import validate_cluster_properties
from magnum.common import clients
from magnum.common import exception
from magnum.common import name_generator
@ -110,7 +110,7 @@ class Cluster(base.APIBase):
stack_id = wsme.wsattr(wtypes.text, readonly=True)
"""Stack id of the heat stack"""
status = wtypes.Enum(str, *fields.BayStatus.ALL)
status = wtypes.Enum(str, *fields.ClusterStatus.ALL)
"""Status of the cluster from the heat stack"""
status_reason = wtypes.text
@ -141,36 +141,13 @@ class Cluster(base.APIBase):
def __init__(self, **kwargs):
super(Cluster, self).__init__()
self.fields = []
for field in objects.Bay.fields:
for field in objects.Cluster.fields:
# Skip fields we do not expose.
if not hasattr(self, field):
continue
self.fields.append(field)
setattr(self, field, kwargs.get(field, wtypes.Unset))
# Set the renamed attributes for clusters
self.fields.append('cluster_template_id')
if 'cluster_template_id' in kwargs.keys():
setattr(self, 'cluster_template_id',
kwargs.get('cluster_template_id', wtypes.Unset))
else:
setattr(self, 'cluster_template_id', kwargs.get('baymodel_id',
wtypes.Unset))
self.fields.append('create_timeout')
if 'create_timeout' in kwargs.keys():
setattr(self, 'create_timeout', kwargs.get('create_timeout',
wtypes.Unset))
else:
setattr(self, 'create_timeout', kwargs.get('bay_create_timeout',
wtypes.Unset))
self.fields.append('faults')
if 'faults' in kwargs.keys():
setattr(self, 'faults', kwargs.get('faults', wtypes.Unset))
else:
setattr(self, 'faults', kwargs.get('bay_faults', wtypes.Unset))
@staticmethod
def _convert_with_links(cluster, url, expand=True):
if not expand:
@ -180,9 +157,9 @@ class Cluster(base.APIBase):
'stack_id'])
cluster.links = [link.Link.make_link('self', url,
'bays', cluster.uuid),
'clusters', cluster.uuid),
link.Link.make_link('bookmark', url,
'bays', cluster.uuid,
'clusters', cluster.uuid,
bookmark=True)]
return cluster
@ -201,7 +178,7 @@ class Cluster(base.APIBase):
master_count=1,
create_timeout=15,
stack_id='49dc23f5-ffc9-40c3-9d34-7be7f9e34d63',
status=fields.BayStatus.CREATE_COMPLETE,
status=fields.ClusterStatus.CREATE_COMPLETE,
status_reason="CREATE completed successfully",
api_address='172.24.4.3',
node_addresses=['172.24.4.4', '172.24.4.5'],
@ -211,26 +188,6 @@ class Cluster(base.APIBase):
container_version=None)
return cls._convert_with_links(sample, 'http://localhost:9511', expand)
def as_dict(self):
"""Render this object as a dict of its fields."""
# Override this for updated cluster values
d = super(Cluster, self).as_dict()
if 'cluster_template_id' in d.keys():
d['baymodel_id'] = d['cluster_template_id']
del d['cluster_template_id']
if 'create_timeout' in d.keys():
d['bay_create_timeout'] = d['create_timeout']
del d['create_timeout']
if 'faults' in d.keys():
d['bay_faults'] = d['faults']
del d['faults']
return d
class ClusterPatchType(types.JsonPatchType):
_api_base = Cluster
@ -295,12 +252,12 @@ class ClustersController(base.Controller):
marker_obj = None
if marker:
marker_obj = objects.Bay.get_by_uuid(pecan.request.context,
marker)
marker_obj = objects.Cluster.get_by_uuid(pecan.request.context,
marker)
clusters = objects.Bay.list(pecan.request.context, limit,
marker_obj, sort_key=sort_key,
sort_dir=sort_dir)
clusters = objects.Cluster.list(pecan.request.context, limit,
marker_obj, sort_key=sort_key,
sort_dir=sort_dir)
return ClusterCollection.convert_with_links(clusters, limit,
url=resource_url,
@ -380,13 +337,13 @@ class ClustersController(base.Controller):
:param cluster_ident: UUID or logical name of the Cluster.
"""
context = pecan.request.context
cluster = api_utils.get_resource('Bay', cluster_ident)
cluster = api_utils.get_resource('Cluster', cluster_ident)
policy.enforce(context, 'cluster:get', cluster,
action='cluster:get')
cluster = Cluster.convert_with_links(cluster)
if cluster.status in fields.BayStatus.STATUS_FAILED:
if cluster.status in fields.ClusterStatus.STATUS_FAILED:
cluster.faults = self._collect_fault_info(context, cluster)
return cluster
@ -420,10 +377,10 @@ class ClustersController(base.Controller):
cluster_dict['coe_version'] = None
cluster_dict['container_version'] = None
new_cluster = objects.Bay(context, **cluster_dict)
new_cluster = objects.Cluster(context, **cluster_dict)
new_cluster.uuid = uuid.uuid4()
pecan.request.rpcapi.bay_create_async(new_cluster,
cluster.create_timeout)
pecan.request.rpcapi.cluster_create_async(new_cluster,
cluster.create_timeout)
return ClusterID(new_cluster.uuid)
@ -438,7 +395,7 @@ class ClustersController(base.Controller):
:param patch: a json PATCH document to apply to this cluster.
"""
cluster = self._patch(cluster_ident, patch)
pecan.request.rpcapi.bay_update_async(cluster)
pecan.request.rpcapi.cluster_update_async(cluster)
return ClusterID(cluster.uuid)
@base.Controller.api_version("1.3") # noqa
@ -453,12 +410,12 @@ class ClustersController(base.Controller):
:param patch: a json PATCH document to apply to this cluster.
"""
cluster = self._patch(cluster_ident, patch)
pecan.request.rpcapi.bay_update_async(cluster, rollback)
pecan.request.rpcapi.cluster_update_async(cluster, rollback)
return ClusterID(cluster.uuid)
def _patch(self, cluster_ident, patch):
context = pecan.request.context
cluster = api_utils.get_resource('Bay', cluster_ident)
cluster = api_utils.get_resource('Cluster', cluster_ident)
policy.enforce(context, 'cluster:update', cluster,
action='cluster:update')
try:
@ -469,7 +426,7 @@ class ClustersController(base.Controller):
raise exception.PatchError(patch=patch, reason=e)
# Update only the fields that have changed
for field in objects.Bay.fields:
for field in objects.Cluster.fields:
try:
patch_val = getattr(new_cluster, field)
except AttributeError:
@ -482,7 +439,7 @@ class ClustersController(base.Controller):
delta = cluster.obj_what_changed()
validate_bay_properties(delta)
validate_cluster_properties(delta)
return cluster
@expose.expose(None, types.uuid_or_name, status_code=204)
@ -492,8 +449,8 @@ class ClustersController(base.Controller):
:param cluster_ident: UUID of cluster or logical name of the cluster.
"""
context = pecan.request.context
cluster = api_utils.get_resource('Bay', cluster_ident)
cluster = api_utils.get_resource('Cluster', cluster_ident)
policy.enforce(context, 'cluster:delete', cluster,
action='cluster:delete')
pecan.request.rpcapi.bay_delete_async(cluster.uuid)
pecan.request.rpcapi.cluster_delete_async(cluster.uuid)

View File

@ -47,7 +47,7 @@ class ClusterTemplate(base.APIBase):
name = wtypes.StringType(min_length=1, max_length=255)
"""The name of the ClusterTemplate"""
coe = wtypes.Enum(str, *fields.BayType.ALL, mandatory=True)
coe = wtypes.Enum(str, *fields.ClusterType.ALL, mandatory=True)
"""The Container Orchestration Engine for this clustertemplate"""
image_id = wsme.wsattr(wtypes.StringType(min_length=1, max_length=255),
@ -185,7 +185,7 @@ class ClusterTemplate(base.APIBase):
docker_volume_size=25,
docker_storage_driver='devicemapper',
cluster_distro='fedora-atomic',
coe=fields.BayType.KUBERNETES,
coe=fields.ClusterType.KUBERNETES,
http_proxy='http://proxy.com:123',
https_proxy='https://proxy.com:123',
no_proxy='192.168.0.1,192.168.0.2,192.168.0.3',

View File

@ -65,32 +65,35 @@ cluster_template_opts = [
cfg.CONF.register_opts(cluster_template_opts, group='cluster_template')
bay_update_allowed_properties = set(['node_count'])
cluster_update_allowed_properties = set(['node_count'])
def enforce_bay_types(*bay_types):
"""Enforce that bay_type is in supported list."""
def enforce_cluster_types(*cluster_types):
"""Enforce that cluster_type is in supported list."""
@decorator.decorator
def wrapper(func, *args, **kwargs):
# Note(eliqiao): This decorator has some assumptions
# args[1] should be an APIBase instance or
# args[2] should be a bay_ident
# args[2] should be a cluster_ident
obj = args[1]
if hasattr(obj, 'bay_uuid'):
bay = objects.Bay.get_by_uuid(pecan.request.context, obj.bay_uuid)
if hasattr(obj, 'cluster_uuid'):
cluster = objects.Cluster.get_by_uuid(pecan.request.context,
obj.cluster_uuid)
else:
bay_ident = args[2]
if uuidutils.is_uuid_like(bay_ident):
bay = objects.Bay.get_by_uuid(pecan.request.context, bay_ident)
cluster_ident = args[2]
if uuidutils.is_uuid_like(cluster_ident):
cluster = objects.Cluster.get_by_uuid(pecan.request.context,
cluster_ident)
else:
bay = objects.Bay.get_by_name(pecan.request.context, bay_ident)
cluster = objects.Cluster.get_by_name(pecan.request.context,
cluster_ident)
if bay.cluster_template.coe not in bay_types:
if cluster.cluster_template.coe not in cluster_types:
raise exception.InvalidParameterValue(_(
'Cannot fulfill request with a %(bay_type)s bay, '
'expecting a %(supported_bay_types)s bay.') %
{'bay_type': bay.cluster_template.coe,
'supported_bay_types': '/'.join(bay_types)})
'Cannot fulfill request with a %(cluster_type)s cluster, '
'expecting a %(supported_cluster_types)s cluster.') %
{'cluster_type': cluster.cluster_template.coe,
'supported_cluster_types': '/'.join(cluster_types)})
return func(*args, **kwargs)
@ -192,11 +195,11 @@ def _enforce_volume_storage_size(cluster_template):
'driver.') % (volume_size, storage_driver)
def validate_bay_properties(delta):
def validate_cluster_properties(delta):
update_disallowed_properties = delta - bay_update_allowed_properties
update_disallowed_properties = delta - cluster_update_allowed_properties
if update_disallowed_properties:
err = (_("cannot change bay property(ies) %s.") %
err = (_("cannot change cluster property(ies) %s.") %
", ".join(update_disallowed_properties))
raise exception.InvalidParameterValue(err=err)

View File

@ -25,8 +25,8 @@ from oslo_service import service
from magnum.common import rpc_service
from magnum.common import service as magnum_service
from magnum.common import short_id
from magnum.conductor.handlers import bay_conductor
from magnum.conductor.handlers import ca_conductor
from magnum.conductor.handlers import cluster_conductor
from magnum.conductor.handlers import conductor_listener
from magnum.conductor.handlers import indirection_api
from magnum.i18n import _LI
@ -49,7 +49,7 @@ def main():
conductor_id = short_id.generate_id()
endpoints = [
indirection_api.Handler(),
bay_conductor.Handler(),
cluster_conductor.Handler(),
conductor_listener.Handler(),
ca_conductor.Handler(),
]

View File

@ -50,7 +50,7 @@ class TemplateList(lister.Lister):
parser.add_argument('-d', '--details',
action='store_true',
dest='details',
help=('display the bay types provided by '
help=('display the cluster types provided by '
'each template'))
parser.add_argument('-p', '--paths',
action='store_true',
@ -77,10 +77,10 @@ class TemplateList(lister.Lister):
path=definition.template_path)
if parsed_args.details:
for bay_type in definition.provides:
for cluster_type in definition.provides:
row = dict()
row.update(template)
row.update(bay_type)
row.update(cluster_type)
rows.append(row)
else:
rows.append(template)

View File

@ -105,15 +105,15 @@ def make_admin_context(show_deleted=False, all_tenants=False):
return context
def make_bay_context(bay, show_deleted=False):
"""Create a user context based on a bay's stored Keystone trust.
def make_cluster_context(cluster, show_deleted=False):
"""Create a user context based on a cluster's stored Keystone trust.
:param bay: the bay supplying the Keystone trust to use
:param cluster: the cluster supplying the Keystone trust to use
:param show_deleted: if True, will show deleted items when query db
"""
context = RequestContext(user_name=bay.trustee_username,
password=bay.trustee_password,
trust_id=bay.trust_id,
context = RequestContext(user_name=cluster.trustee_username,
password=cluster.trustee_password,
trust_id=cluster.trust_id,
show_deleted=show_deleted,
user_domain_id=CONF.trust.trustee_domain_id,
user_domain_name=CONF.trust.trustee_domain_name)

View File

@ -75,20 +75,21 @@ def is_docker_api_version_atleast(docker, version):
@contextlib.contextmanager
def docker_for_bay(context, bay):
cluster_template = conductor_utils.retrieve_cluster_template(context, bay)
def docker_for_cluster(context, cluster):
cluster_template = conductor_utils.retrieve_cluster_template(
context, cluster)
ca_cert, magnum_key, magnum_cert = None, None, None
client_kwargs = dict()
if not cluster_template.tls_disabled:
(ca_cert, magnum_key,
magnum_cert) = cert_manager.create_client_files(bay)
magnum_cert) = cert_manager.create_client_files(cluster)
client_kwargs['ca_cert'] = ca_cert.name
client_kwargs['client_key'] = magnum_key.name
client_kwargs['client_cert'] = magnum_cert.name
yield DockerHTTPClient(
bay.api_address,
cluster.api_address,
CONF.docker.docker_remote_api_version,
CONF.docker.default_timeout,
**client_kwargs

View File

@ -154,7 +154,7 @@ class GetDiscoveryUrlFailed(MagnumException):
message = _("Failed to get discovery url from '%(discovery_endpoint)s'.")
class InvalidBayDiscoveryURL(Invalid):
class InvalidClusterDiscoveryURL(Invalid):
message = _("Invalid discovery URL '%(discovery_url)s'.")
@ -271,11 +271,11 @@ class PodAlreadyExists(Conflict):
class PodListNotFound(ResourceNotFound):
message = _("Pod list could not be found for Bay %(bay_uuid)s.")
message = _("Pod list could not be found for Cluster %(cluster_uuid)s.")
class PodCreationFailed(Invalid):
message = _("Pod creation failed in Bay %(bay_uuid)s.")
message = _("Pod creation failed in Cluster %(cluster_uuid)s.")
class ServiceNotFound(ResourceNotFound):
@ -287,11 +287,12 @@ class ServiceAlreadyExists(Conflict):
class ServiceListNotFound(ResourceNotFound):
message = _("Service list could not be found for Bay %(bay_uuid)s.")
message = _("Service list could not be found for Cluster "
"%(cluster_uuid)s.")
class ServiceCreationFailed(Invalid):
message = _("Service creation failed for Bay %(bay_uuid)s.")
message = _("Service creation failed for Cluster %(cluster_uuid)s.")
class ContainerException(Exception):
@ -303,13 +304,13 @@ class NotSupported(MagnumException):
code = 400
class BayTypeNotSupported(MagnumException):
message = _("Bay type (%(server_type)s, %(os)s, %(coe)s)"
class ClusterTypeNotSupported(MagnumException):
message = _("Cluster type (%(server_type)s, %(os)s, %(coe)s)"
" not supported.")
class BayTypeNotEnabled(MagnumException):
message = _("Bay type (%(server_type)s, %(os)s, %(coe)s)"
class ClusterTypeNotEnabled(MagnumException):
message = _("Cluster type (%(server_type)s, %(os)s, %(coe)s)"
" not enabled.")
@ -322,7 +323,8 @@ class Urllib2InvalidScheme(MagnumException):
class OperationInProgress(Invalid):
message = _("Bay %(bay_name)s already has an operation in progress.")
message = _("Cluster %(cluster_name)s already has an operation in "
"progress.")
class ImageNotFound(ResourceNotFound):
@ -383,11 +385,11 @@ class MagnumServiceAlreadyExists(Conflict):
class UnsupportedK8sQuantityFormat(MagnumException):
message = _("Unsupported quantity format for k8s bay.")
message = _("Unsupported quantity format for k8s cluster.")
class UnsupportedDockerQuantityFormat(MagnumException):
message = _("Unsupported quantity format for Swarm bay.")
message = _("Unsupported quantity format for Swarm cluster.")
class FlavorNotFound(ResourceNotFound):
@ -429,8 +431,9 @@ class RegionsListFailed(MagnumException):
message = _("Failed to list regions.")
class TrusteeOrTrustToBayFailed(MagnumException):
message = _("Failed to create trustee or trust for Bay: %(bay_uuid)s")
class TrusteeOrTrustToClusterFailed(MagnumException):
message = _("Failed to create trustee or trust for Cluster: "
"%(cluster_uuid)s")
class CertificatesToClusterFailed(MagnumException):

View File

@ -32,9 +32,9 @@ LOG = logging.getLogger(__name__)
trust_opts = [
cfg.StrOpt('trustee_domain_id',
help=_('Id of the domain to create trustee for bays')),
help=_('Id of the domain to create trustee for clusters')),
cfg.StrOpt('trustee_domain_name',
help=_('Name of the domain to create trustee for bays')),
help=_('Name of the domain to create trustee for s')),
cfg.StrOpt('trustee_domain_admin_id',
help=_('Id of the admin with roles sufficient to manage users'
' in the trustee_domain')),
@ -256,21 +256,21 @@ class KeystoneClientV3(object):
trustee_user_id=trustee_user)
return trust
def delete_trust(self, context, bay):
if bay.trust_id is None:
def delete_trust(self, context, cluster):
if cluster.trust_id is None:
return
# Trust can only be deleted by the user who creates it. So when
# other users in the same project want to delete the bay, we need
# other users in the same project want to delete the cluster, we need
# use the trustee which can impersonate the trustor to delete the
# trust.
if context.user_id == bay.user_id:
if context.user_id == cluster.user_id:
client = self.client
else:
auth = ka_v3.Password(auth_url=self.auth_url,
user_id=bay.trustee_user_id,
password=bay.trustee_password,
trust_id=bay.trust_id)
user_id=cluster.trustee_user_id,
password=cluster.trustee_password,
trust_id=cluster.trust_id)
sess = ka_loading.session.Session().load_from_options(
auth=auth,
@ -280,12 +280,12 @@ class KeystoneClientV3(object):
cert=CONF[CFG_LEGACY_GROUP].certfile)
client = kc_v3.Client(session=sess)
try:
client.trusts.delete(bay.trust_id)
client.trusts.delete(cluster.trust_id)
except kc_exception.NotFound:
pass
except Exception:
LOG.exception(_LE('Failed to delete trust'))
raise exception.TrustDeleteFailed(trust_id=bay.trust_id)
raise exception.TrustDeleteFailed(trust_id=cluster.trust_id)
def create_trustee(self, username, password):
domain_id = self.trustee_domain_id

View File

@ -104,11 +104,11 @@ def enforce_wsgi(api_name, act=None):
example:
from magnum.common import policy
class BaysController(rest.RestController):
class ClustersController(rest.RestController):
....
@policy.enforce_wsgi("bay", "delete")
@policy.enforce_wsgi("cluster", "delete")
@wsme_pecan.wsexpose(None, types.uuid_or_name, status_code=204)
def delete(self, bay_ident):
def delete(self, cluster_ident):
...
"""
@decorator.decorator

View File

@ -44,8 +44,8 @@ TRANSPORT_ALIASES = {
periodic_opts = [
cfg.BoolOpt('periodic_global_stack_list',
default=False,
help="List Heat stacks globally when syncing bays. "
"Default is to do retrieve each bay's stack "
help="List Heat stacks globally when syncing clusters. "
"Default is to do retrieve each cluster's stack "
"individually. Reduces number of requests against "
"Heat API if enabled but requires changes to Heat's "
"policy.json."),

View File

@ -28,27 +28,27 @@ class API(rpc_service.API):
super(API, self).__init__(transport, context,
topic=cfg.CONF.conductor.topic)
# Bay Operations
# Cluster Operations
def bay_create(self, bay, bay_create_timeout):
return self._call('bay_create', bay=bay,
bay_create_timeout=bay_create_timeout)
def cluster_create(self, cluster, create_timeout):
return self._call('cluster_create', cluster=cluster,
create_timeout=create_timeout)
def bay_create_async(self, bay, bay_create_timeout):
self._cast('bay_create', bay=bay,
bay_create_timeout=bay_create_timeout)
def cluster_create_async(self, cluster, create_timeout):
self._cast('cluster_create', cluster=cluster,
create_timeout=create_timeout)
def bay_delete(self, uuid):
return self._call('bay_delete', uuid=uuid)
def cluster_delete(self, uuid):
return self._call('cluster_delete', uuid=uuid)
def bay_delete_async(self, uuid):
self._cast('bay_delete', uuid=uuid)
def cluster_delete_async(self, uuid):
self._cast('cluster_delete', uuid=uuid)
def bay_update(self, bay):
return self._call('bay_update', bay=bay)
def cluster_update(self, cluster):
return self._call('cluster_update', cluster=cluster)
def bay_update_async(self, bay, rollback=False):
self._cast('bay_update', bay=bay, rollback=rollback)
def cluster_update_async(self, cluster, rollback=False):
self._cast('cluster_update', cluster=cluster, rollback=rollback)
# CA operations

View File

@ -68,8 +68,9 @@ CONF.register_opts(cluster_heat_opts, group='cluster_heat')
LOG = logging.getLogger(__name__)
def _extract_template_definition(context, bay, scale_manager=None):
cluster_template = conductor_utils.retrieve_cluster_template(context, bay)
def _extract_template_definition(context, cluster, scale_manager=None):
cluster_template = conductor_utils.retrieve_cluster_template(context,
cluster)
cluster_distro = cluster_template.cluster_distro
cluster_coe = cluster_template.coe
cluster_server_type = cluster_template.server_type
@ -77,7 +78,7 @@ def _extract_template_definition(context, bay, scale_manager=None):
cluster_server_type,
cluster_distro,
cluster_coe)
return definition.extract_definition(context, cluster_template, bay,
return definition.extract_definition(context, cluster_template, cluster,
scale_manager=scale_manager)
@ -91,9 +92,9 @@ def _get_env_files(template_path, env_rel_paths):
return environment_files, env_map
def _create_stack(context, osc, bay, bay_create_timeout):
def _create_stack(context, osc, cluster, create_timeout):
template_path, heat_params, env_files = (
_extract_template_definition(context, bay))
_extract_template_definition(context, cluster))
tpl_files, template = template_utils.get_template_contents(template_path)
@ -101,11 +102,11 @@ def _create_stack(context, osc, bay, bay_create_timeout):
tpl_files.update(env_map)
# Make sure no duplicate stack name
stack_name = '%s-%s' % (bay.name, short_id.generate_id())
if bay_create_timeout:
heat_timeout = bay_create_timeout
stack_name = '%s-%s' % (cluster.name, short_id.generate_id())
if create_timeout:
heat_timeout = create_timeout
else:
# no bay_create_timeout value was passed in to the request
# no create_timeout value was passed in to the request
# so falling back on configuration file value
heat_timeout = cfg.CONF.cluster_heat.create_timeout
fields = {
@ -121,9 +122,9 @@ def _create_stack(context, osc, bay, bay_create_timeout):
return created_stack
def _update_stack(context, osc, bay, scale_manager=None, rollback=False):
def _update_stack(context, osc, cluster, scale_manager=None, rollback=False):
template_path, heat_params, env_files = _extract_template_definition(
context, bay, scale_manager=scale_manager)
context, cluster, scale_manager=scale_manager)
tpl_files, template = template_utils.get_template_contents(template_path)
environment_files, env_map = _get_env_files(template_path, env_files)
@ -137,7 +138,7 @@ def _update_stack(context, osc, bay, scale_manager=None, rollback=False):
'disable_rollback': not rollback
}
return osc.heat().stacks.update(bay.stack_id, **fields)
return osc.heat().stacks.update(cluster.stack_id, **fields)
class Handler(object):
@ -145,26 +146,28 @@ class Handler(object):
def __init__(self):
super(Handler, self).__init__()
# Bay Operations
# Cluster Operations
def bay_create(self, context, bay, bay_create_timeout):
LOG.debug('bay_heat bay_create')
def cluster_create(self, context, cluster, create_timeout):
LOG.debug('cluster_heat cluster_create')
osc = clients.OpenStackClients(context)
try:
# Create trustee/trust and set them to bay
trust_manager.create_trustee_and_trust(osc, bay)
# Generate certificate and set the cert reference to bay
cert_manager.generate_certificates_to_cluster(bay, context=context)
conductor_utils.notify_about_bay_operation(
# Create trustee/trust and set them to cluster
trust_manager.create_trustee_and_trust(osc, cluster)
# Generate certificate and set the cert reference to cluster
cert_manager.generate_certificates_to_cluster(cluster,
context=context)
conductor_utils.notify_about_cluster_operation(
context, taxonomy.ACTION_CREATE, taxonomy.OUTCOME_PENDING)
created_stack = _create_stack(context, osc, bay,
bay_create_timeout)
created_stack = _create_stack(context, osc, cluster,
create_timeout)
except Exception as e:
cert_manager.delete_certificates_from_cluster(bay, context=context)
trust_manager.delete_trustee_and_trust(osc, context, bay)
conductor_utils.notify_about_bay_operation(
cert_manager.delete_certificates_from_cluster(cluster,
context=context)
trust_manager.delete_trustee_and_trust(osc, context, cluster)
conductor_utils.notify_about_cluster_operation(
context, taxonomy.ACTION_CREATE, taxonomy.OUTCOME_FAILURE)
if isinstance(e, exc.HTTPBadRequest):
@ -173,111 +176,112 @@ class Handler(object):
raise e
raise
bay.stack_id = created_stack['stack']['id']
bay.status = fields.BayStatus.CREATE_IN_PROGRESS
bay.create()
cluster.stack_id = created_stack['stack']['id']
cluster.status = fields.ClusterStatus.CREATE_IN_PROGRESS
cluster.create()
self._poll_and_check(osc, bay)
self._poll_and_check(osc, cluster)
return bay
return cluster
def bay_update(self, context, bay, rollback=False):
LOG.debug('bay_heat bay_update')
def cluster_update(self, context, cluster, rollback=False):
LOG.debug('cluster_heat cluster_update')
osc = clients.OpenStackClients(context)
stack = osc.heat().stacks.get(bay.stack_id)
stack = osc.heat().stacks.get(cluster.stack_id)
allow_update_status = (
fields.BayStatus.CREATE_COMPLETE,
fields.BayStatus.UPDATE_COMPLETE,
fields.BayStatus.RESUME_COMPLETE,
fields.BayStatus.RESTORE_COMPLETE,
fields.BayStatus.ROLLBACK_COMPLETE,
fields.BayStatus.SNAPSHOT_COMPLETE,
fields.BayStatus.CHECK_COMPLETE,
fields.BayStatus.ADOPT_COMPLETE
fields.ClusterStatus.CREATE_COMPLETE,
fields.ClusterStatus.UPDATE_COMPLETE,
fields.ClusterStatus.RESUME_COMPLETE,
fields.ClusterStatus.RESTORE_COMPLETE,
fields.ClusterStatus.ROLLBACK_COMPLETE,
fields.ClusterStatus.SNAPSHOT_COMPLETE,
fields.ClusterStatus.CHECK_COMPLETE,
fields.ClusterStatus.ADOPT_COMPLETE
)
if stack.stack_status not in allow_update_status:
conductor_utils.notify_about_bay_operation(
conductor_utils.notify_about_cluster_operation(
context, taxonomy.ACTION_UPDATE, taxonomy.OUTCOME_FAILURE)
operation = _('Updating a bay when stack status is '
operation = _('Updating a cluster when stack status is '
'"%s"') % stack.stack_status
raise exception.NotSupported(operation=operation)
delta = bay.obj_what_changed()
delta = cluster.obj_what_changed()
if not delta:
return bay
return cluster
manager = scale_manager.ScaleManager(context, osc, bay)
manager = scale_manager.ScaleManager(context, osc, cluster)
conductor_utils.notify_about_bay_operation(
conductor_utils.notify_about_cluster_operation(
context, taxonomy.ACTION_UPDATE, taxonomy.OUTCOME_PENDING)
_update_stack(context, osc, bay, manager, rollback)
self._poll_and_check(osc, bay)
_update_stack(context, osc, cluster, manager, rollback)
self._poll_and_check(osc, cluster)
return bay
return cluster
def bay_delete(self, context, uuid):
LOG.debug('bay_heat bay_delete')
def cluster_delete(self, context, uuid):
LOG.debug('cluster_heat cluster_delete')
osc = clients.OpenStackClients(context)
bay = objects.Bay.get_by_uuid(context, uuid)
cluster = objects.Cluster.get_by_uuid(context, uuid)
stack_id = bay.stack_id
stack_id = cluster.stack_id
# NOTE(sdake): This will execute a stack_delete operation. This will
# Ignore HTTPNotFound exceptions (stack wasn't present). In the case
# that Heat couldn't find the stack representing the bay, likely a user
# has deleted the stack outside the context of Magnum. Therefore the
# contents of the bay are forever lost.
# that Heat couldn't find the stack representing the cluster, likely a
# user has deleted the stack outside the context of Magnum. Therefore
# the contents of the cluster are forever lost.
#
# If the exception is unhandled, the original exception will be raised.
try:
conductor_utils.notify_about_bay_operation(
conductor_utils.notify_about_cluster_operation(
context, taxonomy.ACTION_DELETE, taxonomy.OUTCOME_PENDING)
osc.heat().stacks.delete(stack_id)
except exc.HTTPNotFound:
LOG.info(_LI('The stack %s was not found during bay'
LOG.info(_LI('The stack %s was not found during cluster'
' deletion.'), stack_id)
try:
trust_manager.delete_trustee_and_trust(osc, context, bay)
cert_manager.delete_certificates_from_cluster(bay,
trust_manager.delete_trustee_and_trust(osc, context, cluster)
cert_manager.delete_certificates_from_cluster(cluster,
context=context)
bay.destroy()
cluster.destroy()
except exception.ClusterNotFound:
LOG.info(_LI('The bay %s has been deleted by others.'), uuid)
conductor_utils.notify_about_bay_operation(
LOG.info(_LI('The cluster %s has been deleted by others.'),
uuid)
conductor_utils.notify_about_cluster_operation(
context, taxonomy.ACTION_DELETE, taxonomy.OUTCOME_SUCCESS)
return None
except exc.HTTPConflict:
conductor_utils.notify_about_bay_operation(
conductor_utils.notify_about_cluster_operation(
context, taxonomy.ACTION_DELETE, taxonomy.OUTCOME_FAILURE)
raise exception.OperationInProgress(bay_name=bay.name)
raise exception.OperationInProgress(cluster_name=cluster.name)
except Exception:
conductor_utils.notify_about_bay_operation(
conductor_utils.notify_about_cluster_operation(
context, taxonomy.ACTION_DELETE, taxonomy.OUTCOME_FAILURE)
raise
bay.status = fields.BayStatus.DELETE_IN_PROGRESS
bay.save()
cluster.status = fields.ClusterStatus.DELETE_IN_PROGRESS
cluster.save()
self._poll_and_check(osc, bay)
self._poll_and_check(osc, cluster)
return None
def _poll_and_check(self, osc, bay):
poller = HeatPoller(osc, bay)
def _poll_and_check(self, osc, cluster):
poller = HeatPoller(osc, cluster)
lc = loopingcall.FixedIntervalLoopingCall(f=poller.poll_and_check)
lc.start(cfg.CONF.cluster_heat.wait_interval, True)
class HeatPoller(object):
def __init__(self, openstack_client, bay):
def __init__(self, openstack_client, cluster):
self.openstack_client = openstack_client
self.context = self.openstack_client.context
self.bay = bay
self.cluster = cluster
self.attempts = 0
self.cluster_template = conductor_utils.retrieve_cluster_template(
self.context, bay)
self.context, cluster)
self.template_def = \
template_def.TemplateDefinition.get_template_definition(
self.cluster_template.server_type,
@ -286,97 +290,97 @@ class HeatPoller(object):
def poll_and_check(self):
# TODO(yuanying): temporary implementation to update api_address,
# node_addresses and bay status
stack = self.openstack_client.heat().stacks.get(self.bay.stack_id)
# node_addresses and cluster status
stack = self.openstack_client.heat().stacks.get(self.cluster.stack_id)
self.attempts += 1
status_to_event = {
fields.BayStatus.DELETE_COMPLETE: taxonomy.ACTION_DELETE,
fields.BayStatus.CREATE_COMPLETE: taxonomy.ACTION_CREATE,
fields.BayStatus.UPDATE_COMPLETE: taxonomy.ACTION_UPDATE,
fields.BayStatus.ROLLBACK_COMPLETE: taxonomy.ACTION_UPDATE,
fields.BayStatus.CREATE_FAILED: taxonomy.ACTION_CREATE,
fields.BayStatus.DELETE_FAILED: taxonomy.ACTION_DELETE,
fields.BayStatus.UPDATE_FAILED: taxonomy.ACTION_UPDATE,
fields.BayStatus.ROLLBACK_FAILED: taxonomy.ACTION_UPDATE
fields.ClusterStatus.DELETE_COMPLETE: taxonomy.ACTION_DELETE,
fields.ClusterStatus.CREATE_COMPLETE: taxonomy.ACTION_CREATE,
fields.ClusterStatus.UPDATE_COMPLETE: taxonomy.ACTION_UPDATE,
fields.ClusterStatus.ROLLBACK_COMPLETE: taxonomy.ACTION_UPDATE,
fields.ClusterStatus.CREATE_FAILED: taxonomy.ACTION_CREATE,
fields.ClusterStatus.DELETE_FAILED: taxonomy.ACTION_DELETE,
fields.ClusterStatus.UPDATE_FAILED: taxonomy.ACTION_UPDATE,
fields.ClusterStatus.ROLLBACK_FAILED: taxonomy.ACTION_UPDATE
}
# poll_and_check is detached and polling long time to check status,
# so another user/client can call delete bay/stack.
if stack.stack_status == fields.BayStatus.DELETE_COMPLETE:
# so another user/client can call delete cluster/stack.
if stack.stack_status == fields.ClusterStatus.DELETE_COMPLETE:
self._delete_complete()
conductor_utils.notify_about_bay_operation(
conductor_utils.notify_about_cluster_operation(
self.context, status_to_event[stack.stack_status],
taxonomy.OUTCOME_SUCCESS)
raise loopingcall.LoopingCallDone()
if stack.stack_status in (fields.BayStatus.CREATE_COMPLETE,
fields.BayStatus.UPDATE_COMPLETE):
self._sync_bay_and_template_status(stack)
conductor_utils.notify_about_bay_operation(
if stack.stack_status in (fields.ClusterStatus.CREATE_COMPLETE,
fields.ClusterStatus.UPDATE_COMPLETE):
self._sync_cluster_and_template_status(stack)
conductor_utils.notify_about_cluster_operation(
self.context, status_to_event[stack.stack_status],
taxonomy.OUTCOME_SUCCESS)
raise loopingcall.LoopingCallDone()
elif stack.stack_status != self.bay.status:
self._sync_bay_status(stack)
elif stack.stack_status != self.cluster.status:
self._sync_cluster_status(stack)
if stack.stack_status in (fields.BayStatus.CREATE_FAILED,
fields.BayStatus.DELETE_FAILED,
fields.BayStatus.UPDATE_FAILED,
fields.BayStatus.ROLLBACK_COMPLETE,
fields.BayStatus.ROLLBACK_FAILED):
self._sync_bay_and_template_status(stack)
self._bay_failed(stack)
conductor_utils.notify_about_bay_operation(
if stack.stack_status in (fields.ClusterStatus.CREATE_FAILED,
fields.ClusterStatus.DELETE_FAILED,
fields.ClusterStatus.UPDATE_FAILED,
fields.ClusterStatus.ROLLBACK_COMPLETE,
fields.ClusterStatus.ROLLBACK_FAILED):
self._sync_cluster_and_template_status(stack)
self._cluster_failed(stack)
conductor_utils.notify_about_cluster_operation(
self.context, status_to_event[stack.stack_status],
taxonomy.OUTCOME_FAILURE)
raise loopingcall.LoopingCallDone()
# only check max attempts when the stack is being created when
# the timeout hasn't been set. If the timeout has been set then
# the loop will end when the stack completes or the timeout occurs
if stack.stack_status == fields.BayStatus.CREATE_IN_PROGRESS:
if stack.stack_status == fields.ClusterStatus.CREATE_IN_PROGRESS:
if (stack.timeout_mins is None and
self.attempts > cfg.CONF.cluster_heat.max_attempts):
LOG.error(_LE('Bay check exit after %(attempts)s attempts,'
LOG.error(_LE('Cluster check exit after %(attempts)s attempts,'
'stack_id: %(id)s, stack_status: %(status)s') %
{'attempts': cfg.CONF.cluster_heat.max_attempts,
'id': self.bay.stack_id,
'id': self.cluster.stack_id,
'status': stack.stack_status})
raise loopingcall.LoopingCallDone()
else:
if self.attempts > cfg.CONF.cluster_heat.max_attempts:
LOG.error(_LE('Bay check exit after %(attempts)s attempts,'
LOG.error(_LE('Cluster check exit after %(attempts)s attempts,'
'stack_id: %(id)s, stack_status: %(status)s') %
{'attempts': cfg.CONF.cluster_heat.max_attempts,
'id': self.bay.stack_id,
'id': self.cluster.stack_id,
'status': stack.stack_status})
raise loopingcall.LoopingCallDone()
def _delete_complete(self):
LOG.info(_LI('Bay has been deleted, stack_id: %s')
% self.bay.stack_id)
LOG.info(_LI('Cluster has been deleted, stack_id: %s')
% self.cluster.stack_id)
try:
trust_manager.delete_trustee_and_trust(self.openstack_client,
self.context,
self.bay)
cert_manager.delete_certificates_from_cluster(self.bay,
self.cluster)
cert_manager.delete_certificates_from_cluster(self.cluster,
context=self.context)
self.bay.destroy()
self.cluster.destroy()
except exception.ClusterNotFound:
LOG.info(_LI('The bay %s has been deleted by others.')
% self.bay.uuid)
LOG.info(_LI('The cluster %s has been deleted by others.')
% self.cluster.uuid)
def _sync_bay_status(self, stack):
self.bay.status = stack.stack_status
self.bay.status_reason = stack.stack_status_reason
def _sync_cluster_status(self, stack):
self.cluster.status = stack.stack_status
self.cluster.status_reason = stack.stack_status_reason
stack_nc_param = self.template_def.get_heat_param(
bay_attr='node_count')
self.bay.node_count = stack.parameters[stack_nc_param]
self.bay.save()
cluster_attr='node_count')
self.cluster.node_count = stack.parameters[stack_nc_param]
self.cluster.save()
def get_version_info(self, stack):
stack_param = self.template_def.get_heat_param(
bay_attr='coe_version')
cluster_attr='coe_version')
if stack_param:
self.bay.coe_version = stack.parameters[stack_param]
self.cluster.coe_version = stack.parameters[stack_param]
tdef = template_def.TemplateDefinition.get_template_definition(
self.cluster_template.server_type,
@ -388,18 +392,18 @@ class HeatPoller(object):
container_version = ver.container_version
except Exception:
container_version = None
self.bay.container_version = container_version
self.cluster.container_version = container_version
def _sync_bay_and_template_status(self, stack):
def _sync_cluster_and_template_status(self, stack):
self.template_def.update_outputs(stack, self.cluster_template,
self.bay)
self.cluster)
self.get_version_info(stack)
self._sync_bay_status(stack)
self._sync_cluster_status(stack)
def _bay_failed(self, stack):
LOG.error(_LE('Bay error, stack status: %(bay_status)s, '
def _cluster_failed(self, stack):
LOG.error(_LE('Cluster error, stack status: %(cluster_status)s, '
'stack_id: %(stack_id)s, '
'reason: %(reason)s') %
{'bay_status': stack.stack_status,
'stack_id': self.bay.stack_id,
'reason': self.bay.status_reason})
{'cluster_status': stack.stack_status,
'stack_id': self.cluster.stack_id,
'reason': self.cluster.status_reason})

View File

@ -19,36 +19,39 @@ from magnum.i18n import _LE
LOG = logging.getLogger(__name__)
def create_trustee_and_trust(osc, bay):
def create_trustee_and_trust(osc, cluster):
try:
password = utils.generate_password(length=18)
trustee = osc.keystone().create_trustee(
bay.uuid,
cluster.uuid,
password,
)
bay.trustee_username = trustee.name
bay.trustee_user_id = trustee.id
bay.trustee_password = password
cluster.trustee_username = trustee.name
cluster.trustee_user_id = trustee.id
cluster.trustee_password = password
trust = osc.keystone().create_trust(trustee.id)
bay.trust_id = trust.id
cluster.trust_id = trust.id
except Exception:
LOG.exception(_LE('Failed to create trustee and trust for Bay: %s'),
bay.uuid)
raise exception.TrusteeOrTrustToBayFailed(bay_uuid=bay.uuid)
LOG.exception(
_LE('Failed to create trustee and trust for Cluster: %s'),
cluster.uuid)
raise exception.TrusteeOrTrustToClusterFailed(
cluster_uuid=cluster.uuid)
def delete_trustee_and_trust(osc, context, bay):
def delete_trustee_and_trust(osc, context, cluster):
try:
# The bay which is upgraded from Liberty doesn't have trust_id
if bay.trust_id:
osc.keystone().delete_trust(context, bay)
# The cluster which is upgraded from Liberty doesn't have trust_id
if cluster.trust_id:
osc.keystone().delete_trust(context, cluster)
except Exception:
# Exceptions are already logged by keystone().delete_trust
pass
try:
# The bay which is upgraded from Liberty doesn't have trustee_user_id
if bay.trustee_user_id:
osc.keystone().delete_trustee(bay.trustee_user_id)
# The cluster which is upgraded from Liberty doesn't have
# trustee_user_id
if cluster.trustee_user_id:
osc.keystone().delete_trustee(cluster.trustee_user_id)
except Exception:
# Exceptions are already logged by keystone().delete_trustee
pass

View File

@ -41,17 +41,17 @@ class K8sAPI(apiv_api.ApivApi):
raise
return tmp
def __init__(self, context, bay):
def __init__(self, context, cluster):
self.ca_file = None
self.cert_file = None
self.key_file = None
if bay.magnum_cert_ref:
if cluster.magnum_cert_ref:
(self.ca_file, self.key_file,
self.cert_file) = create_client_files(bay, context)
self.cert_file) = create_client_files(cluster, context)
# build a connection with Kubernetes master
client = api_client.ApiClient(bay.api_address,
client = api_client.ApiClient(cluster.api_address,
key_file=self.key_file.name,
cert_file=self.cert_file.name,
ca_certs=self.ca_file.name)
@ -67,13 +67,13 @@ class K8sAPI(apiv_api.ApivApi):
self.key_file.close()
def create_k8s_api(context, bay):
def create_k8s_api(context, cluster):
"""Create a kubernetes API client
Creates connection with Kubernetes master and creates ApivApi instance
to call Kubernetes APIs.
:param context: The security context
:param bay: Bay object
:param cluster: Cluster object
"""
return K8sAPI(context, bay)
return K8sAPI(context, cluster)

View File

@ -19,8 +19,8 @@ from magnum.conductor import monitors
class K8sMonitor(monitors.MonitorBase):
def __init__(self, context, bay):
super(K8sMonitor, self).__init__(context, bay)
def __init__(self, context, cluster):
super(K8sMonitor, self).__init__(context, cluster)
self.data = {}
self.data['nodes'] = []
self.data['pods'] = []
@ -39,7 +39,7 @@ class K8sMonitor(monitors.MonitorBase):
}
def pull_data(self):
k8s_api = k8s.create_k8s_api(self.context, self.bay)
k8s_api = k8s.create_k8s_api(self.context, self.cluster)
nodes = k8s_api.list_namespaced_node()
self.data['nodes'] = self._parse_node_info(nodes)
pods = k8s_api.list_namespaced_pod('default')

View File

@ -18,8 +18,8 @@ from magnum.conductor import monitors
class MesosMonitor(monitors.MonitorBase):
def __init__(self, context, bay):
super(MesosMonitor, self).__init__(context, bay)
def __init__(self, context, cluster):
super(MesosMonitor, self).__init__(context, cluster)
self.data = {}
@property
@ -46,7 +46,7 @@ class MesosMonitor(monitors.MonitorBase):
self.data['mem_used'] = 0
self.data['cpu_total'] = 0
self.data['cpu_used'] = 0
for master_addr in self.bay.master_addresses:
for master_addr in self.cluster.master_addresses:
mesos_master_url = self._build_url(master_addr, port='5050',
path='/state')
master = jsonutils.loads(urlfetch.get(mesos_master_url))

View File

@ -34,18 +34,18 @@ CONF.import_opt('default_timeout',
group='docker')
COE_CLASS_PATH = {
fields.BayType.SWARM: 'magnum.conductor.swarm_monitor.SwarmMonitor',
fields.BayType.KUBERNETES: 'magnum.conductor.k8s_monitor.K8sMonitor',
fields.BayType.MESOS: 'magnum.conductor.mesos_monitor.MesosMonitor'
fields.ClusterType.SWARM: 'magnum.conductor.swarm_monitor.SwarmMonitor',
fields.ClusterType.KUBERNETES: 'magnum.conductor.k8s_monitor.K8sMonitor',
fields.ClusterType.MESOS: 'magnum.conductor.mesos_monitor.MesosMonitor'
}
@six.add_metaclass(abc.ABCMeta)
class MonitorBase(object):
def __init__(self, context, bay):
def __init__(self, context, cluster):
self.context = context
self.bay = bay
self.cluster = cluster
@abc.abstractproperty
def metrics_spec(self):
@ -67,12 +67,12 @@ class MonitorBase(object):
return func()
def create_monitor(context, bay):
if bay.cluster_template.coe in COE_CLASS_PATH:
def create_monitor(context, cluster):
if cluster.cluster_template.coe in COE_CLASS_PATH:
coe_cls = importutils.import_class(
COE_CLASS_PATH[bay.cluster_template.coe])
return coe_cls(context, bay)
COE_CLASS_PATH[cluster.cluster_template.coe])
return coe_cls(context, cluster)
LOG.debug("Cannot create monitor with bay type '%s'",
bay.cluster_template.coe)
LOG.debug("Cannot create monitor with cluster type '%s'",
cluster.cluster_template.coe)
return None

View File

@ -27,18 +27,18 @@ LOG = logging.getLogger(__name__)
class ScaleManager(object):
def __init__(self, context, osclient, bay):
def __init__(self, context, osclient, cluster):
self.context = context
self.osclient = osclient
self.old_bay = objects.Bay.get_by_uuid(context, bay.uuid)
self.new_bay = bay
self.old_cluster = objects.Cluster.get_by_uuid(context, cluster.uuid)
self.new_cluster = cluster
def get_removal_nodes(self, hosts_output):
if not self._is_scale_down():
return list()
bay = self.new_bay
stack = self.osclient.heat().stacks.get(bay.stack_id)
cluster = self.new_cluster
stack = self.osclient.heat().stacks.get(cluster.stack_id)
hosts = hosts_output.get_output_value(stack)
if hosts is None:
raise exception.MagnumException(_(
@ -47,7 +47,7 @@ class ScaleManager(object):
'stack_id': stack.id})
hosts_no_container = list(hosts)
k8s_api = k8s.create_k8s_api(self.context, bay)
k8s_api = k8s.create_k8s_api(self.context, cluster)
for pod in k8s_api.list_namespaced_pod(namespace='default').items:
host = pod.spec.node_name
if host in hosts_no_container:
@ -72,7 +72,7 @@ class ScaleManager(object):
return hosts_to_remove
def _is_scale_down(self):
return self.new_bay.node_count < self.old_bay.node_count
return self.new_cluster.node_count < self.old_cluster.node_count
def _get_num_of_removal(self):
return self.old_bay.node_count - self.new_bay.node_count
return self.old_cluster.node_count - self.new_cluster.node_count

View File

@ -24,8 +24,8 @@ LOG = log.getLogger(__name__)
class SwarmMonitor(monitors.MonitorBase):
def __init__(self, context, bay):
super(SwarmMonitor, self).__init__(context, bay)
def __init__(self, context, cluster):
super(SwarmMonitor, self).__init__(context, cluster)
self.data = {}
self.data['nodes'] = []
self.data['containers'] = []
@ -40,8 +40,8 @@ class SwarmMonitor(monitors.MonitorBase):
}
def pull_data(self):
with docker_utils.docker_for_bay(self.context,
self.bay) as docker:
with docker_utils.docker_for_cluster(self.context,
self.cluster) as docker:
system_info = docker.info()
self.data['nodes'] = self._parse_node_info(system_info)

View File

@ -20,33 +20,33 @@ from pycadf import resource
from magnum.common import clients
from magnum.common import rpc
from magnum.objects import bay
from magnum.objects import cluster
from magnum.objects import cluster_template
def retrieve_bay(context, bay_ident):
if not uuidutils.is_uuid_like(bay_ident):
return bay.Bay.get_by_name(context, bay_ident)
def retrieve_cluster(context, cluster_ident):
if not uuidutils.is_uuid_like(cluster_ident):
return cluster.Cluster.get_by_name(context, cluster_ident)
else:
return bay.Bay.get_by_uuid(context, bay_ident)
return cluster.Cluster.get_by_uuid(context, cluster_ident)
def retrieve_cluster_template(context, bay):
return cluster_template.ClusterTemplate.get_by_uuid(context,
bay.baymodel_id)
def retrieve_cluster_template(context, cluster):
return cluster_template.ClusterTemplate.get_by_uuid(
context, cluster.cluster_template_id)
def retrieve_bay_uuid(context, bay_ident):
if not uuidutils.is_uuid_like(bay_ident):
bay_obj = bay.Bay.get_by_name(context, bay_ident)
return bay_obj.uuid
def retrieve_cluster_uuid(context, cluster_ident):
if not uuidutils.is_uuid_like(cluster_ident):
cluster_obj = cluster.Cluster.get_by_name(context, cluster_ident)
return cluster_obj.uuid
else:
return bay_ident
return cluster_ident
def object_has_stack(context, bay_uuid):
def object_has_stack(context, cluster_uuid):
osc = clients.OpenStackClients(context)
obj = retrieve_bay(context, bay_uuid)
obj = retrieve_cluster(context, cluster_uuid)
stack = osc.heat().stacks.get(obj.stack_id)
if (stack.stack_status == 'DELETE_COMPLETE' or
@ -86,8 +86,8 @@ def _get_request_audit_info(context):
return initiator
def notify_about_bay_operation(context, action, outcome):
"""Send a notification about bay operation.
def notify_about_cluster_operation(context, action, outcome):
"""Send a notification about cluster operation.
:param action: CADF action being audited
:param outcome: CADF outcome
@ -98,10 +98,10 @@ def notify_about_bay_operation(context, action, outcome):
outcome=outcome,
action=action,
initiator=_get_request_audit_info(context),
target=resource.Resource(typeURI='service/magnum/bay'),
observer=resource.Resource(typeURI='service/magnum/bay'))
target=resource.Resource(typeURI='service/magnum/cluster'),
observer=resource.Resource(typeURI='service/magnum/cluster'))
service = 'magnum'
event_type = '%(service)s.bay.%(action)s' % {
event_type = '%(service)s.cluster.%(action)s' % {
'service': service, 'action': action}
payload = event.as_dict()

View File

@ -41,17 +41,17 @@ class Connection(object):
"""Constructor."""
@abc.abstractmethod
def get_bay_list(self, context, filters=None, limit=None,
marker=None, sort_key=None, sort_dir=None):
"""Get matching bays.
def get_cluster_list(self, context, filters=None, limit=None,
marker=None, sort_key=None, sort_dir=None):
"""Get matching clusters.
Return a list of the specified columns for all bays that match the
Return a list of the specified columns for all clusters that match the
specified filters.
:param context: The security context
:param filters: Filters to apply. Defaults to None.
:param limit: Maximum number of bays to return.
:param limit: Maximum number of clusters to return.
:param marker: the last item of the previous page; we return the next
result set.
:param sort_key: Attribute by which results should be sorted.
@ -61,12 +61,13 @@ class Connection(object):
"""
@abc.abstractmethod
def create_bay(self, values):
"""Create a new bay.
def create_cluster(self, values):
"""Create a new cluster.
:param values: A dict containing several items used to identify
and track the bay, and several dicts which are passed
into the Drivers when managing this bay. For example:
and track the cluster, and several dicts which are
passed into the Drivers when managing this cluster.
For example:
::
@ -75,49 +76,49 @@ class Connection(object):
'name': 'example',
'type': 'virt'
}
:returns: A bay.
:returns: A cluster.
"""
@abc.abstractmethod
def get_bay_by_id(self, context, bay_id):
"""Return a bay.
def get_cluster_by_id(self, context, cluster_id):
"""Return a cluster.
:param context: The security context
:param bay_id: The id of a bay.
:returns: A bay.
:param cluster_id: The id of a cluster.
:returns: A cluster.
"""
@abc.abstractmethod
def get_bay_by_uuid(self, context, bay_uuid):
"""Return a bay.
def get_cluster_by_uuid(self, context, cluster_uuid):
"""Return a cluster.
:param context: The security context
:param bay_uuid: The uuid of a bay.
:returns: A bay.
:param cluster_uuid: The uuid of a cluster.
:returns: A cluster.
"""
@abc.abstractmethod
def get_bay_by_name(self, context, bay_name):
"""Return a bay.
def get_cluster_by_name(self, context, cluster_name):
"""Return a cluster.
:param context: The security context
:param bay_name: The name of a bay.
:returns: A bay.
:param cluster_name: The name of a cluster.
:returns: A cluster.
"""
@abc.abstractmethod
def destroy_bay(self, bay_id):
"""Destroy a bay and all associated interfaces.
def destroy_cluster(self, cluster_id):
"""Destroy a cluster and all associated interfaces.
:param bay_id: The id or uuid of a bay.
:param cluster_id: The id or uuid of a cluster.
"""
@abc.abstractmethod
def update_bay(self, bay_id, values):
"""Update properties of a bay.
def update_cluster(self, cluster_id, values):
"""Update properties of a cluster.
:param bay_id: The id or uuid of a bay.
:returns: A bay.
:param cluster_id: The id or uuid of a cluster.
:returns: A cluster.
:raises: ClusterNotFound
"""

View File

@ -0,0 +1,35 @@
# 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.
"""rename bay table to cluster
Revision ID: 720f640f43d1
Revises: fb03fdef8919
Create Date: 2016-09-02 09:43:41.485934
"""
# revision identifiers, used by Alembic.
revision = '720f640f43d1'
down_revision = 'fb03fdef8919'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.alter_column('bay', 'baymodel_id',
new_column_name='cluster_template_id',
existing_type=sa.String(255))
op.alter_column('bay', 'bay_create_timeout',
new_column_name='create_timeout',
existing_type=sa.Integer())
op.rename_table('bay', 'cluster')

View File

@ -120,11 +120,11 @@ class Connection(api.Connection):
return query
def _add_bays_filters(self, query, filters):
def _add_clusters_filters(self, query, filters):
if filters is None:
filters = {}
possible_filters = ["baymodel_id", "name", "node_count",
possible_filters = ["cluster_template_id", "name", "node_count",
"master_count", "stack_id", "api_address",
"node_addresses", "project_id", "user_id"]
@ -135,91 +135,91 @@ class Connection(api.Connection):
query = query.filter_by(**filter_dict)
if 'status' in filters:
query = query.filter(models.Bay.status.in_(filters['status']))
query = query.filter(models.Cluster.status.in_(filters['status']))
return query
def get_bay_list(self, context, filters=None, limit=None, marker=None,
sort_key=None, sort_dir=None):
query = model_query(models.Bay)
def get_cluster_list(self, context, filters=None, limit=None, marker=None,
sort_key=None, sort_dir=None):
query = model_query(models.Cluster)
query = self._add_tenant_filters(context, query)
query = self._add_bays_filters(query, filters)
return _paginate_query(models.Bay, limit, marker,
query = self._add_clusters_filters(query, filters)
return _paginate_query(models.Cluster, limit, marker,
sort_key, sort_dir, query)
def create_bay(self, values):
# ensure defaults are present for new bays
def create_cluster(self, values):
# ensure defaults are present for new clusters
if not values.get('uuid'):
values['uuid'] = uuidutils.generate_uuid()
bay = models.Bay()
bay.update(values)
cluster = models.Cluster()
cluster.update(values)
try:
bay.save()
cluster.save()
except db_exc.DBDuplicateEntry:
raise exception.ClusterAlreadyExists(uuid=values['uuid'])
return bay
return cluster
def get_bay_by_id(self, context, bay_id):
query = model_query(models.Bay)
def get_cluster_by_id(self, context, cluster_id):
query = model_query(models.Cluster)
query = self._add_tenant_filters(context, query)
query = query.filter_by(id=bay_id)
query = query.filter_by(id=cluster_id)
try:
return query.one()
except NoResultFound:
raise exception.ClusterNotFound(cluster=bay_id)
raise exception.ClusterNotFound(cluster=cluster_id)
def get_bay_by_name(self, context, bay_name):
query = model_query(models.Bay)
def get_cluster_by_name(self, context, cluster_name):
query = model_query(models.Cluster)
query = self._add_tenant_filters(context, query)
query = query.filter_by(name=bay_name)
query = query.filter_by(name=cluster_name)
try:
return query.one()
except MultipleResultsFound:
raise exception.Conflict('Multiple bays exist with same name.'
' Please use the bay uuid instead.')
raise exception.Conflict('Multiple clusters exist with same name.'
' Please use the cluster uuid instead.')
except NoResultFound:
raise exception.ClusterNotFound(cluster=bay_name)
raise exception.ClusterNotFound(cluster=cluster_name)
def get_bay_by_uuid(self, context, bay_uuid):
query = model_query(models.Bay)
def get_cluster_by_uuid(self, context, cluster_uuid):
query = model_query(models.Cluster)
query = self._add_tenant_filters(context, query)
query = query.filter_by(uuid=bay_uuid)
query = query.filter_by(uuid=cluster_uuid)
try:
return query.one()
except NoResultFound:
raise exception.ClusterNotFound(cluster=bay_uuid)
raise exception.ClusterNotFound(cluster=cluster_uuid)
def destroy_bay(self, bay_id):
def destroy_cluster(self, cluster_id):
session = get_session()
with session.begin():
query = model_query(models.Bay, session=session)
query = add_identity_filter(query, bay_id)
query = model_query(models.Cluster, session=session)
query = add_identity_filter(query, cluster_id)
try:
query.one()
except NoResultFound:
raise exception.ClusterNotFound(cluster=bay_id)
raise exception.ClusterNotFound(cluster=cluster_id)
query.delete()
def update_bay(self, bay_id, values):
def update_cluster(self, cluster_id, values):
# NOTE(dtantsur): this can lead to very strange errors
if 'uuid' in values:
msg = _("Cannot overwrite UUID for an existing Bay.")
msg = _("Cannot overwrite UUID for an existing Cluster.")
raise exception.InvalidParameterValue(err=msg)
return self._do_update_bay(bay_id, values)
return self._do_update_cluster(cluster_id, values)
def _do_update_bay(self, bay_id, values):
def _do_update_cluster(self, cluster_id, values):
session = get_session()
with session.begin():
query = model_query(models.Bay, session=session)
query = add_identity_filter(query, bay_id)
query = model_query(models.Cluster, session=session)
query = add_identity_filter(query, cluster_id)
try:
ref = query.with_lockmode('update').one()
except NoResultFound:
raise exception.ClusterNotFound(cluster=bay_id)
raise exception.ClusterNotFound(cluster=cluster_id)
if 'provision_state' in values:
values['provision_updated_at'] = timeutils.utcnow()
@ -309,9 +309,9 @@ class Connection(api.Connection):
def _is_cluster_template_referenced(self, session, cluster_template_uuid):
"""Checks whether the ClusterTemplate is referenced by cluster(s)."""
query = model_query(models.Bay, session=session)
query = self._add_bays_filters(query, {'baymodel_id':
cluster_template_uuid})
query = model_query(models.Cluster, session=session)
query = self._add_clusters_filters(query, {'cluster_template_id':
cluster_template_uuid})
return query.count() != 0
def _is_publishing_cluster_template(self, values):

View File

@ -99,10 +99,10 @@ class MagnumBase(models.TimestampMixin,
Base = declarative_base(cls=MagnumBase)
class Bay(Base):
"""Represents a bay."""
class Cluster(Base):
"""Represents a Cluster."""
__tablename__ = 'bay'
__tablename__ = 'cluster'
__table_args__ = (
schema.UniqueConstraint('uuid', name='uniq_bay0uuid'),
table_args()
@ -112,7 +112,7 @@ class Bay(Base):
user_id = Column(String(255))
uuid = Column(String(36))
name = Column(String(255))
baymodel_id = Column(String(255))
cluster_template_id = Column(String(255))
stack_id = Column(String(255))
api_address = Column(String(255))
node_addresses = Column(JSONEncodedList)
@ -120,7 +120,7 @@ class Bay(Base):
master_count = Column(Integer())
status = Column(String(20))
status_reason = Column(Text)
bay_create_timeout = Column(Integer())
create_timeout = Column(Integer())
discovery_url = Column(String(255))
master_addresses = Column(JSONEncodedList)
# TODO(wanghua): encrypt trust_id in db

View File

@ -24,8 +24,8 @@ KUBE_INSECURE_PORT = '8080'
class K8sApiAddressOutputMapping(template_def.OutputMapping):
def set_output(self, stack, cluster_template, bay):
if self.bay_attr is None:
def set_output(self, stack, cluster_template, cluster):
if self.cluster_attr is None:
return
output_value = self.get_output_value(stack)
@ -43,7 +43,7 @@ class K8sApiAddressOutputMapping(template_def.OutputMapping):
'port': port,
}
value = "%(protocol)s://%(address)s:%(port)s" % params
setattr(bay, self.bay_attr, value)
setattr(cluster, self.cluster_attr, value)
class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
@ -56,7 +56,7 @@ class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
self.add_parameter('minion_flavor',
cluster_template_attr='flavor_id')
self.add_parameter('number_of_minions',
bay_attr='node_count')
cluster_attr='node_count')
self.add_parameter('external_network',
cluster_template_attr='external_network_id',
required=True)
@ -69,23 +69,23 @@ class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
required=True)
self.add_parameter('registry_enabled',
cluster_template_attr='registry_enabled')
self.add_parameter('bay_uuid',
bay_attr='uuid',
self.add_parameter('cluster_uuid',
cluster_attr='uuid',
param_type=str)
self.add_parameter('insecure_registry_url',
cluster_template_attr='insecure_registry')
self.add_parameter('kube_version',
bay_attr='coe_version')
cluster_attr='coe_version')
self.add_output('api_address',
bay_attr='api_address',
cluster_attr='api_address',
mapping_type=K8sApiAddressOutputMapping)
self.add_output('kube_minions_private',
bay_attr=None)
cluster_attr=None)
self.add_output('kube_masters_private',
bay_attr=None)
cluster_attr=None)
def get_params(self, context, cluster_template, bay, **kwargs):
def get_params(self, context, cluster_template, cluster, **kwargs):
extra_params = kwargs.pop('extra_params', {})
scale_mgr = kwargs.pop('scale_manager', None)
if scale_mgr:
@ -93,7 +93,7 @@ class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
extra_params['minions_to_remove'] = (
scale_mgr.get_removal_nodes(hosts))
extra_params['discovery_url'] = self.get_discovery_url(bay)
extra_params['discovery_url'] = self.get_discovery_url(cluster)
osc = self.get_osc(context)
extra_params['magnum_url'] = osc.magnum_url()
@ -112,6 +112,6 @@ class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
CONF.docker_registry.swift_registry_container)
return super(K8sTemplateDefinition,
self).get_params(context, cluster_template, bay,
self).get_params(context, cluster_template, cluster,
extra_params=extra_params,
**kwargs)

View File

@ -62,37 +62,37 @@ CONF.import_opt('trustee_domain_id', 'magnum.common.keystone', group='trust')
class ParameterMapping(object):
"""A mapping associating heat param and bay/cluster_template attr.
"""A mapping associating heat param and cluster_template attr.
A ParameterMapping is an association of a Heat parameter name with
an attribute on a Bay, ClusterTemplate, or both.
an attribute on a Cluster, ClusterTemplate, or both.
In the case of both cluster_template_attr and bay_attr being set, the
ClusterTemplate will be checked first and then Bay if the attribute isn't
set on the ClusterTemplate.
In the case of both cluster_template_attr and cluster_attr being set, the
ClusterTemplate will be checked first and then Cluster if the attribute
isn't set on the ClusterTemplate.
Parameters can also be set as 'required'. If a required parameter
isn't set, a RequiredArgumentNotProvided exception will be raised.
"""
def __init__(self, heat_param, cluster_template_attr=None,
bay_attr=None, required=False,
cluster_attr=None, required=False,
param_type=lambda x: x):
self.heat_param = heat_param
self.cluster_template_attr = cluster_template_attr
self.bay_attr = bay_attr
self.cluster_attr = cluster_attr
self.required = required
self.param_type = param_type
def set_param(self, params, cluster_template, bay):
def set_param(self, params, cluster_template, cluster):
value = None
if (self.cluster_template_attr and
getattr(cluster_template, self.cluster_template_attr, None)
is not None):
value = getattr(cluster_template, self.cluster_template_attr)
elif (self.bay_attr and
getattr(bay, self.bay_attr, None) is not None):
value = getattr(bay, self.bay_attr)
elif (self.cluster_attr and
getattr(cluster, self.cluster_attr, None) is not None):
value = getattr(cluster, self.cluster_attr)
elif self.required:
kwargs = dict(heat_param=self.heat_param)
raise exception.RequiredParameterNotProvided(**kwargs)
@ -103,23 +103,23 @@ class ParameterMapping(object):
class OutputMapping(object):
"""A mapping associating heat outputs and bay attr.
"""A mapping associating heat outputs and cluster attr.
An OutputMapping is an association of a Heat output with a key
Magnum understands.
"""
def __init__(self, heat_output, bay_attr=None):
self.bay_attr = bay_attr
def __init__(self, heat_output, cluster_attr=None):
self.cluster_attr = cluster_attr
self.heat_output = heat_output
def set_output(self, stack, cluster_template, bay):
if self.bay_attr is None:
def set_output(self, stack, cluster_template, cluster):
if self.cluster_attr is None:
return
output_value = self.get_output_value(stack)
if output_value is not None:
setattr(bay, self.bay_attr, output_value)
setattr(cluster, self.cluster_attr, output_value)
def matched(self, output_key):
return self.heat_output == output_key
@ -155,7 +155,7 @@ class TemplateDefinition(object):
@classmethod
def get_template_definitions(cls):
'''Retrieves bay definitions from python entry_points.
'''Retrieves cluster definitions from python entry_points.
Example:
@ -190,11 +190,11 @@ class TemplateDefinition(object):
if not cls.definitions:
cls.definitions = dict()
for entry_point, def_class in cls.load_entry_points():
for bay_type in def_class.provides:
bay_type_tuple = (bay_type['server_type'],
bay_type['os'],
bay_type['coe'])
providers = cls.definitions.setdefault(bay_type_tuple,
for cluster_type in def_class.provides:
cluster_type_tuple = (cluster_type['server_type'],
cluster_type['os'],
cluster_type['coe'])
providers = cls.definitions.setdefault(cluster_type_tuple,
dict())
providers[entry_point.name] = def_class
@ -205,7 +205,7 @@ class TemplateDefinition(object):
'''Get enabled TemplateDefinitions.
Returns the enabled TemplateDefinition class for the provided
bay_type.
cluster_type.
With the following classes:
class TemplateDefinition1(TemplateDefinition):
@ -227,30 +227,30 @@ class TemplateDefinition(object):
get_template_name_1_definition('server_type2', 'os2', 'coe2')
will return: TemplateDefinition2
:param server_type: The server_type the bay definition
:param server_type: The server_type the cluster definition
will build on
:param os: The operating system the bay definition will build on
:param coe: The Container Orchestration Environment the bay will
:param os: The operating system the cluster definition will build on
:param coe: The Container Orchestration Environment the cluster will
produce
:return: class
'''
definition_map = cls.get_template_definitions()
bay_type = (server_type, os, coe)
cluster_type = (server_type, os, coe)
if bay_type not in definition_map:
raise exception.BayTypeNotSupported(
if cluster_type not in definition_map:
raise exception.ClusterTypeNotSupported(
server_type=server_type,
os=os,
coe=coe)
type_definitions = definition_map[bay_type]
type_definitions = definition_map[cluster_type]
for name in cfg.CONF.cluster.enabled_definitions:
if name in type_definitions:
return type_definitions[name]()
raise exception.BayTypeNotEnabled(
raise exception.ClusterTypeNotEnabled(
server_type=server_type, os=os, coe=coe)
def add_parameter(self, *args, **kwargs):
@ -269,13 +269,13 @@ class TemplateDefinition(object):
return None
def get_params(self, context, cluster_template, bay, **kwargs):
"""Pulls template parameters from ClusterTemplate and/or Bay.
def get_params(self, context, cluster_template, cluster, **kwargs):
"""Pulls template parameters from ClusterTemplate.
:param context: Context to pull template parameters for
:param cluster_template: ClusterTemplate to pull template parameters
from
:param bay: Bay to pull template parameters from
:param cluster: Cluster to pull template parameters from
:param extra_params: Any extra params to be provided to the template
:return: dict of template parameters
@ -283,7 +283,7 @@ class TemplateDefinition(object):
template_params = dict()
for mapping in self.param_mappings:
mapping.set_param(template_params, cluster_template, bay)
mapping.set_param(template_params, cluster_template, cluster)
if 'extra_params' in kwargs:
template_params.update(kwargs.get('extra_params'))
@ -302,26 +302,27 @@ class TemplateDefinition(object):
"""
return []
def get_heat_param(self, bay_attr=None, cluster_template_attr=None):
def get_heat_param(self, cluster_attr=None, cluster_template_attr=None):
"""Returns stack param name.
Return stack param name using bay and cluster_template attributes
:param bay_attr bay attribute from which it maps to stack attribute
Return stack param name using cluster and cluster_template attributes
:param cluster_attr cluster attribute from which it maps to stack
attribute
:param cluster_template_attr cluster_template attribute from which it
maps to stack attribute
:return stack parameter name or None
"""
for mapping in self.param_mappings:
if (mapping.bay_attr == bay_attr and
if (mapping.cluster_attr == cluster_attr and
mapping.cluster_template_attr == cluster_template_attr):
return mapping.heat_param
return None
def update_outputs(self, stack, cluster_template, bay):
def update_outputs(self, stack, cluster_template, cluster):
for output in self.output_mappings:
output.set_output(stack, cluster_template, bay)
output.set_output(stack, cluster_template, cluster)
@abc.abstractproperty
def driver_module_path(self):
@ -331,9 +332,9 @@ class TemplateDefinition(object):
def template_path(self):
pass
def extract_definition(self, context, cluster_template, bay, **kwargs):
def extract_definition(self, context, cluster_template, cluster, **kwargs):
return (self.template_path,
self.get_params(context, cluster_template, bay, **kwargs),
self.get_params(context, cluster_template, cluster, **kwargs),
self.get_env_files(cluster_template))
@ -356,7 +357,7 @@ class BaseTemplateDefinition(TemplateDefinition):
self.add_parameter('no_proxy',
cluster_template_attr='no_proxy')
self.add_parameter('number_of_masters',
bay_attr='master_count')
cluster_attr='master_count')
@property
def driver_module_path(self):
@ -371,19 +372,19 @@ class BaseTemplateDefinition(TemplateDefinition):
self._osc = clients.OpenStackClients(context)
return self._osc
def get_params(self, context, cluster_template, bay, **kwargs):
def get_params(self, context, cluster_template, cluster, **kwargs):
osc = self.get_osc(context)
extra_params = kwargs.pop('extra_params', {})
extra_params['trustee_domain_id'] = osc.keystone().trustee_domain_id
extra_params['trustee_user_id'] = bay.trustee_user_id
extra_params['trustee_username'] = bay.trustee_username
extra_params['trustee_password'] = bay.trustee_password
extra_params['trust_id'] = bay.trust_id
extra_params['trustee_user_id'] = cluster.trustee_user_id
extra_params['trustee_username'] = cluster.trustee_username
extra_params['trustee_password'] = cluster.trustee_password
extra_params['trust_id'] = cluster.trust_id
extra_params['auth_url'] = context.auth_url
return super(BaseTemplateDefinition,
self).get_params(context, cluster_template, bay,
self).get_params(context, cluster_template, cluster,
extra_params=extra_params,
**kwargs)
@ -404,17 +405,17 @@ class BaseTemplateDefinition(TemplateDefinition):
try:
result = ast.literal_eval(result)
except (ValueError, SyntaxError):
raise exception.InvalidBayDiscoveryURL(
raise exception.InvalidClusterDiscoveryURL(
discovery_url=discovery_url)
node_value = result.get('node', None)
if node_value is None:
raise exception.InvalidBayDiscoveryURL(
raise exception.InvalidClusterDiscoveryURL(
discovery_url=discovery_url)
value = node_value.get('value', None)
if value is None:
raise exception.InvalidBayDiscoveryURL(
raise exception.InvalidClusterDiscoveryURL(
discovery_url=discovery_url)
elif int(value) != expect_size:
raise exception.InvalidClusterSize(
@ -422,18 +423,18 @@ class BaseTemplateDefinition(TemplateDefinition):
size=int(value),
discovery_url=discovery_url)
def get_discovery_url(self, bay):
if hasattr(bay, 'discovery_url') and bay.discovery_url:
if getattr(bay, 'master_count', None) is not None:
self.validate_discovery_url(bay.discovery_url,
bay.master_count)
def get_discovery_url(self, cluster):
if hasattr(cluster, 'discovery_url') and cluster.discovery_url:
if getattr(cluster, 'master_count', None) is not None:
self.validate_discovery_url(cluster.discovery_url,
cluster.master_count)
else:
self.validate_discovery_url(bay.discovery_url, 1)
discovery_url = bay.discovery_url
self.validate_discovery_url(cluster.discovery_url, 1)
discovery_url = cluster.discovery_url
else:
discovery_endpoint = (
cfg.CONF.cluster.etcd_discovery_service_endpoint_format %
{'size': bay.master_count})
{'size': cluster.master_count})
try:
discovery_url = requests.get(discovery_endpoint).text
except req_exceptions.RequestException as err:
@ -445,5 +446,5 @@ class BaseTemplateDefinition(TemplateDefinition):
discovery_url=discovery_url,
discovery_endpoint=discovery_endpoint)
else:
bay.discovery_url = discovery_url
cluster.discovery_url = discovery_url
return discovery_url

View File

@ -33,7 +33,7 @@ $configure_docker_storage_driver
if [ "$DOCKER_STORAGE_DRIVER" = "overlay" ]; then
if [ $(echo -e "$(uname -r)\n3.18" | sort -V | head -1) \
= $(uname -r) ]; then
ERROR_MESSAGE="OverlayFS requires at least Linux kernel 3.18. Bay node kernel version: $(uname -r)"
ERROR_MESSAGE="OverlayFS requires at least Linux kernel 3.18. Cluster node kernel version: $(uname -r)"
echo "ERROR: ${ERROR_MESSAGE}" >&2
sh -c "${WAIT_CURL} --data-binary '{\"status\": \"FAILURE\", \"reason\": \"${ERROR_MESSAGE}\"}'"
else

View File

@ -32,9 +32,9 @@ class CoreOSK8sTemplateDefinition(k8s_template_def.K8sTemplateDefinition):
def __init__(self):
super(CoreOSK8sTemplateDefinition, self).__init__()
self.add_output('kube_minions',
bay_attr='node_addresses')
cluster_attr='node_addresses')
self.add_output('kube_masters',
bay_attr='master_addresses')
cluster_attr='master_addresses')
def get_env_files(self, cluster_template):
if cluster_template.master_lb_enabled:

View File

@ -85,7 +85,7 @@ write_files:
ca_cert_json=$(curl -X GET \
-H "X-Auth-Token: $USER_TOKEN" \
$MAGNUM_URL/certificates/$BAY_UUID)
$MAGNUM_URL/certificates/$CLUSTER_UUID)
parse_json_response "${ca_cert_json}" > ${CA_CERT}
# Create config for client's csr
@ -117,7 +117,7 @@ write_files:
# encode newline (\n) characters
csr=$(cat $CLIENT_CSR | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\n/g')
csr_req="{\"bay_uuid\": \"$BAY_UUID\", \"csr\": \"$csr\"}"
csr_req="{\"cluster_uuid\": \"$CLUSTER_UUID\", \"csr\": \"$csr\"}"
# Send csr to Magnum to have it signed
client_cert_json=$(curl -X POST \
-H "X-Auth-Token: $USER_TOKEN" \

View File

@ -106,10 +106,10 @@ write_files:
rm -rf auth.json
# Get CA certificate for this bay
# Get CA certificate for this cluster
ca_cert_json=$(curl -X GET \
-H "X-Auth-Token: $USER_TOKEN" \
$MAGNUM_URL/certificates/$BAY_UUID)
$MAGNUM_URL/certificates/$CLUSTER_UUID)
parse_json_response "${ca_cert_json}" > ${CA_CERT}
# Create config for server's csr
@ -136,7 +136,7 @@ write_files:
# encode newline (\n) characters
csr=$(cat $SERVER_CSR | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\n/g')
csr_req="{\"bay_uuid\": \"$BAY_UUID\", \"csr\": \"$csr\"}"
csr_req="{\"cluster_uuid\": \"$CLUSTER_UUID\", \"csr\": \"$csr\"}"
# Send csr to Magnum to have it signed
server_cert_json=$(curl -X POST \
-H "X-Auth-Token: $USER_TOKEN" \

View File

@ -24,7 +24,7 @@ write_files:
TENANT_NAME="$TENANT_NAME"
CLUSTER_SUBNET="$CLUSTER_SUBNET"
TLS_DISABLED="$TLS_DISABLED"
BAY_UUID="$BAY_UUID"
CLUSTER_UUID="$CLUSTER_UUID"
MAGNUM_URL="$MAGNUM_URL"
HTTP_PROXY="$HTTP_PROXY"
HTTPS_PROXY="$HTTPS_PROXY"

View File

@ -21,7 +21,7 @@ write_files:
REGISTRY_INSECURE="$REGISTRY_INSECURE"
REGISTRY_CHUNKSIZE="$REGISTRY_CHUNKSIZE"
TLS_DISABLED="$TLS_DISABLED"
BAY_UUID="$BAY_UUID"
CLUSTER_UUID="$CLUSTER_UUID"
MAGNUM_URL="$MAGNUM_URL"
AUTH_URL="$AUTH_URL"
USERNAME="$USERNAME"

View File

@ -123,9 +123,9 @@ parameters:
service.
default: 6443
bay_uuid:
cluster_uuid:
type: string
description: identifier for the bay this template is generating
description: identifier for the cluster this template is generating
magnum_url:
type: string
@ -286,7 +286,7 @@ resources:
######################################################################
#
# resources that expose the IPs of either the kube master or a given
# LBaaS pool depending on whether LBaaS is enabled for the bay.
# LBaaS pool depending on whether LBaaS is enabled for the cluster.
#
api_address_switch:
@ -340,7 +340,7 @@ resources:
no_proxy: {get_param: no_proxy}
kube_version: {get_param: kube_version}
wait_condition_timeout: {get_param: wait_condition_timeout}
bay_uuid: {get_param: bay_uuid}
cluster_uuid: {get_param: cluster_uuid}
api_pool_id: {get_resource: api_pool}
etcd_pool_id: {get_resource: etcd_pool}
magnum_url: {get_param: magnum_url}
@ -384,7 +384,7 @@ resources:
kube_version: {get_param: kube_version}
etcd_server_ip: {get_attr: [etcd_address_switch, private_ip]}
wait_condition_timeout: {get_param: wait_condition_timeout}
bay_uuid: {get_param: bay_uuid}
cluster_uuid: {get_param: cluster_uuid}
magnum_url: {get_param: magnum_url}
trustee_user_id: {get_param: trustee_user_id}
trustee_password: {get_param: trustee_password}

View File

@ -95,9 +95,9 @@ parameters:
type: string
description: version of kubernetes used for kubernetes cluster
bay_uuid:
cluster_uuid:
type: string
description: identifier for the bay this template is generating
description: identifier for the cluster this template is generating
magnum_url:
type: string
@ -161,7 +161,7 @@ resources:
######################################################################
#
# resource that exposes the IPs of either the kube master or the API
# LBaaS pool depending on whether LBaaS is enabled for the bay.
# LBaaS pool depending on whether LBaaS is enabled for the cluster.
#
api_address_switch:
@ -237,7 +237,7 @@ resources:
"$KUBE_API_PORT": {get_param: kubernetes_port}
"$TLS_DISABLED": {get_param: tls_disabled}
"$KUBE_VERSION": {get_param: kube_version}
"$BAY_UUID": {get_param: bay_uuid}
"$CLUSTER_UUID": {get_param: cluster_uuid}
"$MAGNUM_URL": {get_param: magnum_url}
"$HTTP_PROXY": {get_param: http_proxy}
"$HTTPS_PROXY": {get_param: https_proxy}

View File

@ -45,9 +45,9 @@ parameters:
service.
default: 6443
bay_uuid:
cluster_uuid:
type: string
description: identifier for the bay this template is generating
description: identifier for the cluster this template is generating
magnum_url:
type: string
@ -165,7 +165,7 @@ resources:
"$NETWORK_DRIVER": {get_param: network_driver}
"$ETCD_SERVER_IP": {get_param: etcd_server_ip}
"$KUBE_VERSION": {get_param: kube_version}
"$BAY_UUID": {get_param: bay_uuid}
"$CLUSTER_UUID": {get_param: cluster_uuid}
"$MAGNUM_URL": {get_param: magnum_url}
"$HTTP_PROXY": {get_param: http_proxy}
"$HTTPS_PROXY": {get_param: https_proxy}

View File

@ -32,17 +32,17 @@ class ServerAddressOutputMapping(template_def.OutputMapping):
public_ip_output_key = None
private_ip_output_key = None
def __init__(self, dummy_arg, bay_attr=None):
self.bay_attr = bay_attr
def __init__(self, dummy_arg, cluster_attr=None):
self.cluster_attr = cluster_attr
self.heat_output = self.public_ip_output_key
def set_output(self, stack, cluster_template, bay):
def set_output(self, stack, cluster_template, cluster):
if not cluster_template.floating_ip_enabled:
self.heat_output = self.private_ip_output_key
LOG.debug("Using heat_output: %s", self.heat_output)
super(ServerAddressOutputMapping,
self).set_output(stack, cluster_template, bay)
self).set_output(stack, cluster_template, cluster)
class MasterAddressOutputMapping(ServerAddressOutputMapping):
@ -71,13 +71,13 @@ class AtomicK8sTemplateDefinition(k8s_template_def.K8sTemplateDefinition):
self.add_parameter('docker_storage_driver',
cluster_template_attr='docker_storage_driver')
self.add_output('kube_minions',
bay_attr='node_addresses',
cluster_attr='node_addresses',
mapping_type=NodeAddressOutputMapping)
self.add_output('kube_masters',
bay_attr='master_addresses',
cluster_attr='master_addresses',
mapping_type=MasterAddressOutputMapping)
def get_params(self, context, cluster_template, bay, **kwargs):
def get_params(self, context, cluster_template, cluster, **kwargs):
extra_params = kwargs.pop('extra_params', {})
extra_params['username'] = context.user_name
@ -86,7 +86,7 @@ class AtomicK8sTemplateDefinition(k8s_template_def.K8sTemplateDefinition):
extra_params['region_name'] = osc.cinder_region_name()
return super(AtomicK8sTemplateDefinition,
self).get_params(context, cluster_template, bay,
self).get_params(context, cluster_template, cluster,
extra_params=extra_params,
**kwargs)
@ -156,14 +156,14 @@ class FedoraK8sIronicTemplateDefinition(AtomicK8sTemplateDefinition):
return subnet['network_id']
def get_params(self, context, cluster_template, bay, **kwargs):
def get_params(self, context, cluster_template, cluster, **kwargs):
ep = kwargs.pop('extra_params', {})
osc = self.get_osc(context)
ep['fixed_network'] = self.get_fixed_network_id(osc, cluster_template)
return super(FedoraK8sIronicTemplateDefinition,
self).get_params(context, cluster_template, bay,
self).get_params(context, cluster_template, cluster,
extra_params=ep,
**kwargs)

View File

@ -67,10 +67,10 @@ url="$AUTH_URL/auth/tokens"
USER_TOKEN=`curl -s -i -X POST -H "$content_type" -d "$auth_json" $url \
| grep X-Subject-Token | awk '{print $2}' | tr -d '[[:space:]]'`
# Get CA certificate for this bay
# Get CA certificate for this cluster
curl -X GET \
-H "X-Auth-Token: $USER_TOKEN" \
$MAGNUM_URL/certificates/$BAY_UUID | python -c 'import sys, json; print json.load(sys.stdin)["pem"]' > $CA_CERT
$MAGNUM_URL/certificates/$CLUSTER_UUID | python -c 'import sys, json; print json.load(sys.stdin)["pem"]' > $CA_CERT
# Create config for client's csr
cat > ${cert_conf_dir}/client.conf <<EOF
@ -100,7 +100,7 @@ openssl req -new -days 1000 \
-config "${cert_conf_dir}/client.conf"
# Send csr to Magnum to have it signed
csr_req=$(python -c "import json; fp = open('${CLIENT_CSR}'); print json.dumps({'bay_uuid': '$BAY_UUID', 'csr': fp.read()}); fp.close()")
csr_req=$(python -c "import json; fp = open('${CLIENT_CSR}'); print json.dumps({'cluster_uuid': '$CLUSTER_UUID', 'csr': fp.read()}); fp.close()")
curl -X POST \
-H "X-Auth-Token: $USER_TOKEN" \
-H "Content-Type: application/json" \

View File

@ -89,10 +89,10 @@ url="$AUTH_URL/auth/tokens"
USER_TOKEN=`curl -s -i -X POST -H "$content_type" -d "$auth_json" $url \
| grep X-Subject-Token | awk '{print $2}' | tr -d '[[:space:]]'`
# Get CA certificate for this bay
# Get CA certificate for this cluster
curl -X GET \
-H "X-Auth-Token: $USER_TOKEN" \
$MAGNUM_URL/certificates/$BAY_UUID | python -c 'import sys, json; print json.load(sys.stdin)["pem"]' > ${CA_CERT}
$MAGNUM_URL/certificates/$CLUSTER_UUID | python -c 'import sys, json; print json.load(sys.stdin)["pem"]' > ${CA_CERT}
# Create config for server's csr
cat > ${cert_conf_dir}/server.conf <<EOF
@ -117,7 +117,7 @@ openssl req -new -days 1000 \
-config "${cert_conf_dir}/server.conf"
# Send csr to Magnum to have it signed
csr_req=$(python -c "import json; fp = open('${SERVER_CSR}'); print json.dumps({'bay_uuid': '$BAY_UUID', 'csr': fp.read()}); fp.close()")
csr_req=$(python -c "import json; fp = open('${SERVER_CSR}'); print json.dumps({'cluster_uuid': '$CLUSTER_UUID', 'csr': fp.read()}); fp.close()")
curl -X POST \
-H "X-Auth-Token: $USER_TOKEN" \
-H "Content-Type: application/json" \

View File

@ -25,7 +25,7 @@ write_files:
TENANT_NAME="$TENANT_NAME"
CLUSTER_SUBNET="$CLUSTER_SUBNET"
TLS_DISABLED="$TLS_DISABLED"
BAY_UUID="$BAY_UUID"
CLUSTER_UUID="$CLUSTER_UUID"
MAGNUM_URL="$MAGNUM_URL"
HTTP_PROXY="$HTTP_PROXY"
HTTPS_PROXY="$HTTPS_PROXY"

View File

@ -22,7 +22,7 @@ write_files:
REGISTRY_INSECURE="$REGISTRY_INSECURE"
REGISTRY_CHUNKSIZE="$REGISTRY_CHUNKSIZE"
TLS_DISABLED="$TLS_DISABLED"
BAY_UUID="$BAY_UUID"
CLUSTER_UUID="$CLUSTER_UUID"
MAGNUM_URL="$MAGNUM_URL"
AUTH_URL="$AUTH_URL"
USERNAME="$USERNAME"

View File

@ -212,9 +212,9 @@ parameters:
service.
default: 6443
bay_uuid:
cluster_uuid:
type: string
description: identifier for the bay this template is generating
description: identifier for the cluster this template is generating
magnum_url:
type: string
@ -374,7 +374,7 @@ resources:
######################################################################
#
# resources that expose the IPs of either the kube master or a given
# LBaaS pool depending on whether LBaaS is enabled for the bay.
# LBaaS pool depending on whether LBaaS is enabled for the cluster.
#
api_address_switch:
@ -419,7 +419,7 @@ resources:
flannel_backend: {get_param: flannel_backend}
portal_network_cidr: {get_param: portal_network_cidr}
discovery_url: {get_param: discovery_url}
bay_uuid: {get_param: bay_uuid}
cluster_uuid: {get_param: cluster_uuid}
magnum_url: {get_param: magnum_url}
fixed_network: {get_param: fixed_network}
fixed_subnet: {get_param: fixed_subnet}
@ -475,7 +475,7 @@ resources:
registry_container: {get_param: registry_container}
registry_insecure: {get_param: registry_insecure}
registry_chunksize: {get_param: registry_chunksize}
bay_uuid: {get_param: bay_uuid}
cluster_uuid: {get_param: cluster_uuid}
magnum_url: {get_param: magnum_url}
volume_driver: {get_param: volume_driver}
region_name: {get_param: region_name}

View File

@ -204,9 +204,9 @@ parameters:
service.
default: 6443
bay_uuid:
cluster_uuid:
type: string
description: identifier for the bay this template is generating
description: identifier for the cluster this template is generating
magnum_url:
type: string
@ -396,7 +396,7 @@ resources:
######################################################################
#
# resources that expose the IPs of either the kube master or a given
# LBaaS pool depending on whether LBaaS is enabled for the bay.
# LBaaS pool depending on whether LBaaS is enabled for the cluster.
#
api_address_lb_switch:
@ -416,7 +416,7 @@ resources:
######################################################################
#
# resources that expose the IPs of either floating ip or a given
# fixed ip depending on whether FloatingIP is enabled for the bay.
# fixed ip depending on whether FloatingIP is enabled for the cluster.
#
api_address_floating_switch:
@ -456,7 +456,7 @@ resources:
flannel_backend: {get_param: flannel_backend}
portal_network_cidr: {get_param: portal_network_cidr}
discovery_url: {get_param: discovery_url}
bay_uuid: {get_param: bay_uuid}
cluster_uuid: {get_param: cluster_uuid}
magnum_url: {get_param: magnum_url}
fixed_network: {get_resource: fixed_network}
fixed_subnet: {get_resource: fixed_subnet}
@ -515,7 +515,7 @@ resources:
registry_container: {get_param: registry_container}
registry_insecure: {get_param: registry_insecure}
registry_chunksize: {get_param: registry_chunksize}
bay_uuid: {get_param: bay_uuid}
cluster_uuid: {get_param: cluster_uuid}
magnum_url: {get_param: magnum_url}
volume_driver: {get_param: volume_driver}
region_name: {get_param: region_name}

View File

@ -72,9 +72,9 @@ parameters:
The port which are used by kube-apiserver to provide Kubernetes
service.
bay_uuid:
cluster_uuid:
type: string
description: identifier for the bay this template is generating
description: identifier for the cluster this template is generating
magnum_url:
type: string
@ -192,7 +192,7 @@ resources:
######################################################################
#
# resource that exposes the IPs of either the kube master or the API
# LBaaS pool depending on whether LBaaS is enabled for the bay.
# LBaaS pool depending on whether LBaaS is enabled for the cluster.
#
api_address_switch:
@ -235,7 +235,7 @@ resources:
"$TENANT_NAME": {get_param: tenant_name}
"$CLUSTER_SUBNET": {get_param: fixed_subnet}
"$TLS_DISABLED": {get_param: tls_disabled}
"$BAY_UUID": {get_param: bay_uuid}
"$CLUSTER_UUID": {get_param: cluster_uuid}
"$MAGNUM_URL": {get_param: magnum_url}
"$HTTP_PROXY": {get_param: http_proxy}
"$HTTPS_PROXY": {get_param: https_proxy}

View File

@ -78,9 +78,9 @@ parameters:
The port which are used by kube-apiserver to provide Kubernetes
service.
bay_uuid:
cluster_uuid:
type: string
description: identifier for the bay this template is generating
description: identifier for the cluster this template is generating
magnum_url:
type: string
@ -198,7 +198,7 @@ resources:
######################################################################
#
# resource that exposes the IPs of either the kube master or the API
# LBaaS pool depending on whether LBaaS is enabled for the bay.
# LBaaS pool depending on whether LBaaS is enabled for the cluster.
#
api_address_switch:
@ -243,7 +243,7 @@ resources:
"$TENANT_NAME": {get_param: tenant_name}
"$CLUSTER_SUBNET": {get_param: fixed_subnet}
"$TLS_DISABLED": {get_param: tls_disabled}
"$BAY_UUID": {get_param: bay_uuid}
"$CLUSTER_UUID": {get_param: cluster_uuid}
"$MAGNUM_URL": {get_param: magnum_url}
"$HTTP_PROXY": {get_param: http_proxy}
"$HTTPS_PROXY": {get_param: https_proxy}

View File

@ -47,9 +47,9 @@ parameters:
The port which are used by kube-apiserver to provide Kubernetes
service.
bay_uuid:
cluster_uuid:
type: string
description: identifier for the bay this template is generating
description: identifier for the cluster this template is generating
magnum_url:
type: string
@ -228,7 +228,7 @@ resources:
$REGISTRY_INSECURE: {get_param: registry_insecure}
$REGISTRY_CHUNKSIZE: {get_param: registry_chunksize}
$TLS_DISABLED: {get_param: tls_disabled}
$BAY_UUID: {get_param: bay_uuid}
$CLUSTER _UUID: {get_param: cluster_uuid}
$MAGNUM_URL: {get_param: magnum_url}
$USERNAME: {get_param: username}
$PASSWORD: {get_param: password}

View File

@ -53,9 +53,9 @@ parameters:
The port which are used by kube-apiserver to provide Kubernetes
service.
bay_uuid:
cluster_uuid:
type: string
description: identifier for the bay this template is generating
description: identifier for the cluster this template is generating
magnum_url:
type: string
@ -236,7 +236,7 @@ resources:
$REGISTRY_INSECURE: {get_param: registry_insecure}
$REGISTRY_CHUNKSIZE: {get_param: registry_chunksize}
$TLS_DISABLED: {get_param: tls_disabled}
$BAY_UUID: {get_param: bay_uuid}
$CLUSTER_UUID: {get_param: cluster_uuid}
$MAGNUM_URL: {get_param: magnum_url}
$USERNAME: {get_param: username}
$PASSWORD: {get_param: password}

View File

@ -29,28 +29,28 @@ class UbuntuMesosTemplateDefinition(template_def.BaseTemplateDefinition):
cluster_template_attr='external_network_id',
required=True)
self.add_parameter('number_of_slaves',
bay_attr='node_count')
cluster_attr='node_count')
self.add_parameter('master_flavor',
cluster_template_attr='master_flavor_id')
self.add_parameter('slave_flavor',
cluster_template_attr='flavor_id')
self.add_parameter('cluster_name',
bay_attr='name')
cluster_attr='name')
self.add_parameter('volume_driver',
cluster_template_attr='volume_driver')
self.add_output('api_address',
bay_attr='api_address')
cluster_attr='api_address')
self.add_output('mesos_master_private',
bay_attr=None)
cluster_attr=None)
self.add_output('mesos_master',
bay_attr='master_addresses')
cluster_attr='master_addresses')
self.add_output('mesos_slaves_private',
bay_attr=None)
cluster_attr=None)
self.add_output('mesos_slaves',
bay_attr='node_addresses')
cluster_attr='node_addresses')
def get_params(self, context, cluster_template, bay, **kwargs):
def get_params(self, context, cluster_template, cluster, **kwargs):
extra_params = kwargs.pop('extra_params', {})
# HACK(apmelton) - This uses the user's bearer token, ideally
# it should be replaced with an actual trust token with only
@ -77,7 +77,7 @@ class UbuntuMesosTemplateDefinition(template_def.BaseTemplateDefinition):
scale_mgr.get_removal_nodes(hosts))
return super(UbuntuMesosTemplateDefinition,
self).get_params(context, cluster_template, bay,
self).get_params(context, cluster_template, cluster,
extra_params=extra_params,
**kwargs)

View File

@ -361,7 +361,7 @@ resources:
lb_method: ROUND_ROBIN
vip:
protocol_port: 8080
description: API pool for Mesos bay
description: API pool for Mesos cluster
api_pool_floating:
type: Magnum::Optional::Neutron::Pool::FloatingIP

View File

@ -45,15 +45,15 @@ locations:
These files are typically installed in the same locations on the
Neutron controller node. The policy.json file is copied into the
Docker image because it is fairly static and does not require
customization for the bay. If it is changed in the Neutron master
customization for the cluster. If it is changed in the Neutron master
repo, you just need to rebuild the Docker image to update the file.
Magnum will create the other 2 files on each bay node in the
Magnum will create the other 2 files on each cluster node in the
directory /etc/kuryr and map them to the proper directories in
the container using the Docker -v option.
Since Openvswitch needs to operate on the host network name space,
the Docker container will need the -net=host option.
The /var/run/openvswitch directory is also mapped to the bay node
The /var/run/openvswitch directory is also mapped to the cluster node
so that the Kuryr container can talk to openvswitch.
To run the image from Fedora Atomic::

View File

@ -22,8 +22,8 @@ DOCKER_PORT = '2376'
class SwarmApiAddressOutputMapping(template_def.OutputMapping):
def set_output(self, stack, cluster_template, bay):
if self.bay_attr is None:
def set_output(self, stack, cluster_template, cluster):
if self.cluster_attr is None:
return
output_value = self.get_output_value(stack)
@ -36,7 +36,7 @@ class SwarmApiAddressOutputMapping(template_def.OutputMapping):
'port': DOCKER_PORT,
}
value = "%(protocol)s://%(address)s:%(port)s" % params
setattr(bay, self.bay_attr, value)
setattr(cluster, self.cluster_attr, value)
class AtomicSwarmTemplateDefinition(template_def.BaseTemplateDefinition):
@ -48,11 +48,11 @@ class AtomicSwarmTemplateDefinition(template_def.BaseTemplateDefinition):
def __init__(self):
super(AtomicSwarmTemplateDefinition, self).__init__()
self.add_parameter('bay_uuid',
bay_attr='uuid',
self.add_parameter('cluster_uuid',
cluster_attr='uuid',
param_type=str)
self.add_parameter('number_of_nodes',
bay_attr='node_count')
cluster_attr='node_count')
self.add_parameter('master_flavor',
cluster_template_attr='master_flavor_id')
self.add_parameter('node_flavor',
@ -74,25 +74,25 @@ class AtomicSwarmTemplateDefinition(template_def.BaseTemplateDefinition):
self.add_parameter('docker_storage_driver',
cluster_template_attr='docker_storage_driver')
self.add_parameter('swarm_version',
bay_attr='coe_version')
cluster_attr='coe_version')
self.add_output('api_address',
bay_attr='api_address',
cluster_attr='api_address',
mapping_type=SwarmApiAddressOutputMapping)
self.add_output('swarm_master_private',
bay_attr=None)
cluster_attr=None)
self.add_output('swarm_masters',
bay_attr='master_addresses')
cluster_attr='master_addresses')
self.add_output('swarm_nodes_private',
bay_attr=None)
cluster_attr=None)
self.add_output('swarm_nodes',
bay_attr='node_addresses')
cluster_attr='node_addresses')
self.add_output('discovery_url',
bay_attr='discovery_url')
cluster_attr='discovery_url')
def get_params(self, context, cluster_template, bay, **kwargs):
def get_params(self, context, cluster_template, cluster, **kwargs):
extra_params = kwargs.pop('extra_params', {})
extra_params['discovery_url'] = self.get_discovery_url(bay)
extra_params['discovery_url'] = self.get_discovery_url(cluster)
# HACK(apmelton) - This uses the user's bearer token, ideally
# it should be replaced with an actual trust token with only
# access to do what the template needs it to do.
@ -113,7 +113,7 @@ class AtomicSwarmTemplateDefinition(template_def.BaseTemplateDefinition):
CONF.docker_registry.swift_registry_container)
return super(AtomicSwarmTemplateDefinition,
self).get_params(context, cluster_template, bay,
self).get_params(context, cluster_template, cluster,
extra_params=extra_params,
**kwargs)

View File

@ -25,9 +25,9 @@ parameters:
type: string
description: url provided for node discovery
bay_uuid:
cluster_uuid:
type: string
description: identifier for the bay this template is generating
description: identifier for the cluster this template is generating
magnum_url:
type: string
@ -335,7 +335,7 @@ resources:
######################################################################
#
# resources that expose the IPs of either the swarm master or a given
# LBaaS pool depending on whether LBaaS is enabled for the bay.
# LBaaS pool depending on whether LBaaS is enabled for the cluster.
#
api_address_switch:
@ -381,7 +381,7 @@ resources:
https_proxy: {get_param: https_proxy}
no_proxy: {get_param: no_proxy}
swarm_api_ip: {get_attr: [api_pool, vip, address]}
bay_uuid: {get_param: bay_uuid}
cluster_uuid: {get_param: cluster_uuid}
magnum_url: {get_param: magnum_url}
tls_disabled: {get_param: tls_disabled}
secgroup_swarm_master_id: {get_resource: secgroup_manager}
@ -423,7 +423,7 @@ resources:
https_proxy: {get_param: https_proxy}
no_proxy: {get_param: no_proxy}
swarm_api_ip: {get_attr: [api_address_switch, private_ip]}
bay_uuid: {get_param: bay_uuid}
cluster_uuid: {get_param: cluster_uuid}
magnum_url: {get_param: magnum_url}
tls_disabled: {get_param: tls_disabled}
secgroup_swarm_node_id: {get_resource: secgroup_manager}

View File

@ -81,10 +81,10 @@ def _build_subject_alt_names(config):
def write_ca_cert(config):
bay_cert_url = '%s/certificates/%s' % (config['MAGNUM_URL'],
config['BAY_UUID'])
cluster_cert_url = '%s/certificates/%s' % (config['MAGNUM_URL'],
config['CLUSTER_UUID'])
headers = {'X-Auth-Token': config['USER_TOKEN']}
ca_cert_resp = requests.get(bay_cert_url,
ca_cert_resp = requests.get(cluster_cert_url,
headers=headers)
with open(CA_CERT_PATH, 'w') as fp:
@ -116,7 +116,7 @@ def create_server_csr(config):
'-config', SERVER_CONF_PATH])
with open(SERVER_CSR_PATH, 'r') as fp:
return {'bay_uuid': config['BAY_UUID'], 'csr': fp.read()}
return {'cluster_uuid': config['CLUSTER_UUID'], 'csr': fp.read()}
def write_server_cert(config, csr_req):

View File

@ -16,7 +16,7 @@ write_files:
NO_PROXY="$NO_PROXY"
SWARM_API_IP="$SWARM_API_IP"
SWARM_NODE_IP="$SWARM_NODE_IP"
BAY_UUID="$BAY_UUID"
CLUSTER_UUID="$CLUSTER_UUID"
MAGNUM_URL="$MAGNUM_URL"
TLS_DISABLED="$TLS_DISABLED"
NETWORK_DRIVER="$NETWORK_DRIVER"

View File

@ -15,7 +15,7 @@ write_files:
NO_PROXY="$NO_PROXY"
SWARM_API_IP="$SWARM_API_IP"
SWARM_NODE_IP="$SWARM_NODE_IP"
BAY_UUID="$BAY_UUID"
CLUSTER_UUID="$CLUSTER_UUID"
MAGNUM_URL="$MAGNUM_URL"
TLS_DISABLED="$TLS_DISABLED"
NETWORK_DRIVER="$NETWORK_DRIVER"

View File

@ -30,9 +30,9 @@ parameters:
type: string
description: url provided for node discovery
bay_uuid:
cluster_uuid:
type: string
description: identifier for the bay this template is generating
description: identifier for the cluster this template is generating
magnum_url:
type: string
@ -170,7 +170,7 @@ resources:
######################################################################
#
# resource that exposes the IPs of either the Swarm master or the API
# LBaaS pool depending on whether LBaaS is enabled for the bay.
# LBaaS pool depending on whether LBaaS is enabled for the cluster.
#
api_address_switch:
@ -211,7 +211,7 @@ resources:
"$NO_PROXY": {get_param: no_proxy}
"$SWARM_API_IP": {get_attr: [api_address_switch, private_ip]}
"$SWARM_NODE_IP": {get_attr: [swarm_master_eth0, fixed_ips, 0, ip_address]}
"$BAY_UUID": {get_param: bay_uuid}
"$CLUSTER_UUID": {get_param: cluster_uuid}
"$MAGNUM_URL": {get_param: magnum_url}
"$TLS_DISABLED": {get_param: tls_disabled}
"$NETWORK_DRIVER": {get_param: network_driver}
@ -286,7 +286,7 @@ resources:
group: ungrouped
config:
str_replace:
template: {get_file: fragments/write-bay-failure-service.yaml}
template: {get_file: fragments/write-cluster-failure-service.yaml}
params:
"$SERVICE": swarm-manager
"$WAIT_HANDLE_ENDPOINT": {get_attr: [master_wait_handle, endpoint]}

View File

@ -71,9 +71,9 @@ parameters:
type: string
description: swarm master's api server public ip address
bay_uuid:
cluster_uuid:
type: string
description: identifier for the bay this template is generating
description: identifier for the cluster this template is generating
magnum_url:
type: string
@ -195,7 +195,7 @@ resources:
"$NO_PROXY": {get_param: no_proxy}
"$SWARM_API_IP": {get_param: swarm_api_ip}
"$SWARM_NODE_IP": {get_attr: [swarm_node_eth0, fixed_ips, 0, ip_address]}
"$BAY_UUID": {get_param: bay_uuid}
"$CLUSTER_UUID": {get_param: cluster_uuid}
"$MAGNUM_URL": {get_param: magnum_url}
"$TLS_DISABLED": {get_param: tls_disabled}
"$NETWORK_DRIVER": {get_param: network_driver}
@ -269,7 +269,7 @@ resources:
group: ungrouped
config:
str_replace:
template: {get_file: fragments/write-bay-failure-service.yaml}
template: {get_file: fragments/write-cluster-failure-service.yaml}
params:
"$SERVICE": swarm-agent
"$WAIT_HANDLE_ENDPOINT": {get_attr: [node_wait_handle, endpoint]}

View File

@ -12,19 +12,19 @@
# License for the specific language governing permissions and limitations
# under the License.
from magnum.objects import bay
from magnum.objects import certificate
from magnum.objects import cluster
from magnum.objects import cluster_template
from magnum.objects import magnum_service
from magnum.objects import x509keypair
Bay = bay.Bay
Cluster = cluster.Cluster
ClusterTemplate = cluster_template.ClusterTemplate
MagnumService = magnum_service.MagnumService
X509KeyPair = x509keypair.X509KeyPair
Certificate = certificate.Certificate
__all__ = (Bay,
__all__ = (Cluster,
ClusterTemplate,
MagnumService,
X509KeyPair,

View File

@ -20,13 +20,13 @@ from oslo_versionedobjects import fields
from magnum.common import exception
from magnum.db import api as dbapi
from magnum.objects import base
from magnum.objects import cluster_template
from magnum.objects.cluster_template import ClusterTemplate
from magnum.objects import fields as m_fields
@base.MagnumObjectRegistry.register
class Bay(base.MagnumPersistentObject, base.MagnumObject,
base.MagnumObjectDictCompat):
class Cluster(base.MagnumPersistentObject, base.MagnumObject,
base.MagnumObjectDictCompat):
# Version 1.0: Initial version
# Version 1.1: Added 'bay_create_timeout' field
# Version 1.2: Add 'registry_trust_id' field
@ -38,8 +38,11 @@ class Bay(base.MagnumPersistentObject, base.MagnumObject,
# Version 1.6: Add rollback support for Bay
# Version 1.7: Added 'coe_version' and 'container_version' fields
# Version 1.8: Rename 'baymodel' to 'cluster_template'
# Version 1.9: Rename table name from 'bay' to 'cluster'
# Rename 'baymodel_id' to 'cluster_template_id'
# Rename 'bay_create_timeout' to 'create_timeout'
VERSION = '1.8'
VERSION = '1.9'
dbapi = dbapi.get_instance()
@ -49,11 +52,11 @@ class Bay(base.MagnumPersistentObject, base.MagnumObject,
'name': fields.StringField(nullable=True),
'project_id': fields.StringField(nullable=True),
'user_id': fields.StringField(nullable=True),
'baymodel_id': fields.StringField(nullable=True),
'cluster_template_id': fields.StringField(nullable=True),
'stack_id': fields.StringField(nullable=True),
'status': m_fields.BayStatusField(nullable=True),
'status': m_fields.ClusterStatusField(nullable=True),
'status_reason': fields.StringField(nullable=True),
'bay_create_timeout': fields.IntegerField(nullable=True),
'create_timeout': fields.IntegerField(nullable=True),
'api_address': fields.StringField(nullable=True),
'node_addresses': fields.ListOfStringsField(nullable=True),
'node_count': fields.IntegerField(nullable=True),
@ -72,135 +75,136 @@ class Bay(base.MagnumPersistentObject, base.MagnumObject,
}
@staticmethod
def _from_db_object(bay, db_bay):
def _from_db_object(cluster, db_cluster):
"""Converts a database entity to a formal object."""
for field in bay.fields:
for field in cluster.fields:
if field != 'cluster_template':
bay[field] = db_bay[field]
cluster[field] = db_cluster[field]
# Note(eliqiao): The following line needs to be placed outside the
# loop because there is a dependency from cluster_template to
# baymodel_id. The baymodel_id must be populated first in the loop
# before it can be used to find the cluster_template.
bay['cluster_template'] = cluster_template.ClusterTemplate.get_by_uuid(
bay._context, bay.baymodel_id)
# cluster_template_id. The cluster_template_id must be populated
# first in the loop before it can be used to find the cluster_template.
cluster['cluster_template'] = ClusterTemplate.get_by_uuid(
cluster._context, cluster.cluster_template_id)
bay.obj_reset_changes()
return bay
cluster.obj_reset_changes()
return cluster
@staticmethod
def _from_db_object_list(db_objects, cls, context):
"""Converts a list of database entities to a list of formal objects."""
return [Bay._from_db_object(cls(context), obj) for obj in db_objects]
return [Cluster._from_db_object(cls(context), obj)
for obj in db_objects]
@base.remotable_classmethod
def get(cls, context, bay_id):
"""Find a bay based on its id or uuid and return a Bay object.
def get(cls, context, cluster_id):
"""Find a cluster based on its id or uuid and return a Cluster object.
:param bay_id: the id *or* uuid of a bay.
:param cluster_id: the id *or* uuid of a cluster.
:param context: Security context
:returns: a :class:`Bay` object.
:returns: a :class:`Cluster` object.
"""
if strutils.is_int_like(bay_id):
return cls.get_by_id(context, bay_id)
elif uuidutils.is_uuid_like(bay_id):
return cls.get_by_uuid(context, bay_id)
if strutils.is_int_like(cluster_id):
return cls.get_by_id(context, cluster_id)
elif uuidutils.is_uuid_like(cluster_id):
return cls.get_by_uuid(context, cluster_id)
else:
raise exception.InvalidIdentity(identity=bay_id)
raise exception.InvalidIdentity(identity=cluster_id)
@base.remotable_classmethod
def get_by_id(cls, context, bay_id):
"""Find a bay based on its integer id and return a Bay object.
def get_by_id(cls, context, cluster_id):
"""Find a cluster based on its integer id and return a Cluster object.
:param bay_id: the id of a bay.
:param cluster_id: the id of a cluster.
:param context: Security context
:returns: a :class:`Bay` object.
:returns: a :class:`Cluster` object.
"""
db_bay = cls.dbapi.get_bay_by_id(context, bay_id)
bay = Bay._from_db_object(cls(context), db_bay)
return bay
db_cluster = cls.dbapi.get_cluster_by_id(context, cluster_id)
cluster = Cluster._from_db_object(cls(context), db_cluster)
return cluster
@base.remotable_classmethod
def get_by_uuid(cls, context, uuid):
"""Find a bay based on uuid and return a :class:`Bay` object.
"""Find a cluster based on uuid and return a :class:`Cluster` object.
:param uuid: the uuid of a bay.
:param uuid: the uuid of a cluster.
:param context: Security context
:returns: a :class:`Bay` object.
:returns: a :class:`Cluster` object.
"""
db_bay = cls.dbapi.get_bay_by_uuid(context, uuid)
bay = Bay._from_db_object(cls(context), db_bay)
return bay
db_cluster = cls.dbapi.get_cluster_by_uuid(context, uuid)
cluster = Cluster._from_db_object(cls(context), db_cluster)
return cluster
@base.remotable_classmethod
def get_by_name(cls, context, name):
"""Find a bay based on name and return a Bay object.
"""Find a cluster based on name and return a Cluster object.
:param name: the logical name of a bay.
:param name: the logical name of a cluster.
:param context: Security context
:returns: a :class:`Bay` object.
:returns: a :class:`Cluster` object.
"""
db_bay = cls.dbapi.get_bay_by_name(context, name)
bay = Bay._from_db_object(cls(context), db_bay)
return bay
db_cluster = cls.dbapi.get_cluster_by_name(context, name)
cluster = Cluster._from_db_object(cls(context), db_cluster)
return cluster
@base.remotable_classmethod
def list(cls, context, limit=None, marker=None,
sort_key=None, sort_dir=None, filters=None):
"""Return a list of Bay objects.
"""Return a list of Cluster objects.
:param context: Security context.
:param limit: maximum number of resources to return in a single result.
:param marker: pagination marker for large data sets.
:param sort_key: column to sort results by.
:param sort_dir: direction to sort. "asc" or "desc".
:param filters: filter dict, can includes 'baymodel_id', 'name',
'node_count', 'stack_id', 'api_address',
:param filters: filter dict, can includes 'cluster_template_id',
'name', 'node_count', 'stack_id', 'api_address',
'node_addresses', 'project_id', 'user_id',
'status'(should be a status list), 'master_count'.
:returns: a list of :class:`Bay` object.
:returns: a list of :class:`Cluster` object.
"""
db_bays = cls.dbapi.get_bay_list(context, limit=limit,
marker=marker,
sort_key=sort_key,
sort_dir=sort_dir,
filters=filters)
return Bay._from_db_object_list(db_bays, cls, context)
db_clusters = cls.dbapi.get_cluster_list(context, limit=limit,
marker=marker,
sort_key=sort_key,
sort_dir=sort_dir,
filters=filters)
return Cluster._from_db_object_list(db_clusters, cls, context)
@base.remotable
def create(self, context=None):
"""Create a Bay record in the DB.
"""Create a Cluster record in the DB.
:param context: Security context. NOTE: This should only
be used internally by the indirection_api.
Unfortunately, RPC requires context as the first
argument, even though we don't use it.
A context should be set when instantiating the
object, e.g.: Bay(context)
object, e.g.: Cluster(context)
"""
values = self.obj_get_changes()
db_bay = self.dbapi.create_bay(values)
self._from_db_object(self, db_bay)
db_cluster = self.dbapi.create_cluster(values)
self._from_db_object(self, db_cluster)
@base.remotable
def destroy(self, context=None):
"""Delete the Bay from the DB.
"""Delete the Cluster from the DB.
:param context: Security context. NOTE: This should only
be used internally by the indirection_api.
Unfortunately, RPC requires context as the first
argument, even though we don't use it.
A context should be set when instantiating the
object, e.g.: Bay(context)
object, e.g.: Cluster(context)
"""
self.dbapi.destroy_bay(self.uuid)
self.dbapi.destroy_cluster(self.uuid)
self.obj_reset_changes()
@base.remotable
def save(self, context=None):
"""Save updates to this Bay.
"""Save updates to this Cluster.
Updates will be made column by column based on the result
of self.what_changed().
@ -210,27 +214,27 @@ class Bay(base.MagnumPersistentObject, base.MagnumObject,
Unfortunately, RPC requires context as the first
argument, even though we don't use it.
A context should be set when instantiating the
object, e.g.: Bay(context)
object, e.g.: Cluster(context)
"""
updates = self.obj_get_changes()
self.dbapi.update_bay(self.uuid, updates)
self.dbapi.update_cluster(self.uuid, updates)
self.obj_reset_changes()
@base.remotable
def refresh(self, context=None):
"""Loads updates for this Bay.
"""Loads updates for this Cluster.
Loads a bay with the same uuid from the database and
Loads a Cluster with the same uuid from the database and
checks for updated attributes. Updates are applied from
the loaded bay column by column, if there are any updates.
the loaded Cluster column by column, if there are any updates.
:param context: Security context. NOTE: This should only
be used internally by the indirection_api.
Unfortunately, RPC requires context as the first
argument, even though we don't use it.
A context should be set when instantiating the
object, e.g.: Bay(context)
object, e.g.: Cluster(context)
"""
current = self.__class__.get_by_uuid(self._context, uuid=self.uuid)
for field in self.fields:

View File

@ -40,7 +40,8 @@ class ClusterTemplate(base.MagnumPersistentObject, base.MagnumObject,
# Version 1.14: Added 'fixed_subnet' field
# Version 1.15: Added 'floating_ip_enabled' field
# Version 1.16: Renamed the class from "BayModel' to 'ClusterTemplate'
VERSION = '1.16'
# Version 1.17: 'coe' field type change to ClusterTypeField
VERSION = '1.17'
dbapi = dbapi.get_instance()
@ -65,7 +66,7 @@ class ClusterTemplate(base.MagnumPersistentObject, base.MagnumObject,
'docker_storage_driver': m_fields.DockerStorageDriverField(
nullable=True),
'cluster_distro': fields.StringField(nullable=True),
'coe': m_fields.BayTypeField(nullable=True),
'coe': m_fields.ClusterTypeField(nullable=True),
'http_proxy': fields.StringField(nullable=True),
'https_proxy': fields.StringField(nullable=True),
'no_proxy': fields.StringField(nullable=True),

View File

@ -15,7 +15,7 @@
from oslo_versionedobjects import fields
class BayStatus(fields.Enum):
class ClusterStatus(fields.Enum):
CREATE_IN_PROGRESS = 'CREATE_IN_PROGRESS'
CREATE_FAILED = 'CREATE_FAILED'
CREATE_COMPLETE = 'CREATE_COMPLETE'
@ -45,7 +45,7 @@ class BayStatus(fields.Enum):
DELETE_FAILED, ROLLBACK_FAILED)
def __init__(self):
super(BayStatus, self).__init__(valid_values=BayStatus.ALL)
super(ClusterStatus, self).__init__(valid_values=ClusterStatus.ALL)
class ContainerStatus(fields.Enum):
@ -60,7 +60,7 @@ class ContainerStatus(fields.Enum):
valid_values=ContainerStatus.ALL)
class BayType(fields.Enum):
class ClusterType(fields.Enum):
ALL = (
KUBERNETES, SWARM, MESOS,
) = (
@ -68,7 +68,7 @@ class BayType(fields.Enum):
)
def __init__(self):
super(BayType, self).__init__(valid_values=BayType.ALL)
super(ClusterType, self).__init__(valid_values=ClusterType.ALL)
class DockerStorageDriver(fields.Enum):
@ -99,8 +99,8 @@ class ListOfDictsField(fields.AutoTypedField):
AUTO_TYPE = fields.List(fields.Dict(fields.FieldType()))
class BayStatusField(fields.BaseEnumField):
AUTO_TYPE = BayStatus()
class ClusterStatusField(fields.BaseEnumField):
AUTO_TYPE = ClusterStatus()
class MagnumServiceField(fields.BaseEnumField):
@ -111,8 +111,8 @@ class ContainerStatusField(fields.BaseEnumField):
AUTO_TYPE = ContainerStatus()
class BayTypeField(fields.BaseEnumField):
AUTO_TYPE = BayType()
class ClusterTypeField(fields.BaseEnumField):
AUTO_TYPE = ClusterType()
class DockerStorageDriverField(fields.BaseEnumField):

View File

@ -24,7 +24,7 @@ import magnum.common.exception
import magnum.common.service
import magnum.common.x509.config
import magnum.conductor.config
import magnum.conductor.handlers.bay_conductor
import magnum.conductor.handlers.cluster_conductor
import magnum.db
import magnum.drivers.common.template_def
@ -52,7 +52,7 @@ def list_opts():
('neutron_client', magnum.common.clients.neutron_client_opts),
('x509', magnum.common.x509.config.x509_opts),
('cluster_heat',
magnum.conductor.handlers.bay_conductor.cluster_heat_opts),
magnum.conductor.handlers.cluster_conductor.cluster_heat_opts),
('certificates',
itertools.chain(magnum.common.cert_manager.cert_manager_opts,
local_cert_manager.local_cert_manager_opts,

View File

@ -69,140 +69,149 @@ class MagnumPeriodicTasks(periodic_task.PeriodicTasks):
@periodic_task.periodic_task(run_immediately=True)
@set_context
def sync_bay_status(self, ctx):
def sync_cluster_status(self, ctx):
try:
LOG.debug('Starting to sync up bay status')
LOG.debug('Starting to sync up cluster status')
osc = clients.OpenStackClients(ctx)
status = [fields.BayStatus.CREATE_IN_PROGRESS,
fields.BayStatus.UPDATE_IN_PROGRESS,
fields.BayStatus.DELETE_IN_PROGRESS,
fields.BayStatus.ROLLBACK_IN_PROGRESS]
status = [fields.ClusterStatus.CREATE_IN_PROGRESS,
fields.ClusterStatus.UPDATE_IN_PROGRESS,
fields.ClusterStatus.DELETE_IN_PROGRESS,
fields.ClusterStatus.ROLLBACK_IN_PROGRESS]
filters = {'status': status}
bays = objects.Bay.list(ctx, filters=filters)
if not bays:
clusters = objects.Cluster.list(ctx, filters=filters)
if not clusters:
return
sid_to_bay_mapping = {bay.stack_id: bay for bay in bays}
bay_stack_ids = sid_to_bay_mapping.keys()
sid_to_cluster_mapping = {cluster.stack_id:
cluster for cluster in clusters}
cluster_stack_ids = sid_to_cluster_mapping.keys()
if CONF.periodic_global_stack_list:
stacks = osc.heat().stacks.list(global_tenant=True,
filters={'id': bay_stack_ids})
stacks = osc.heat().stacks.list(
global_tenant=True, filters={'id': cluster_stack_ids})
else:
ret = self._get_bay_stacks(bays, sid_to_bay_mapping,
bay_stack_ids)
[stacks, bays, bay_stack_ids, sid_to_bay_mapping] = ret
ret = self._get_cluster_stacks(
clusters, sid_to_cluster_mapping, cluster_stack_ids)
[stacks, clusters, cluster_stack_ids,
sid_to_cluster_mapping] = ret
sid_to_stack_mapping = {s.id: s for s in stacks}
# intersection of bays magnum has and heat has
for sid in (six.viewkeys(sid_to_bay_mapping) &
# intersection of clusters magnum has and heat has
for sid in (six.viewkeys(sid_to_cluster_mapping) &
six.viewkeys(sid_to_stack_mapping)):
stack = sid_to_stack_mapping[sid]
bay = sid_to_bay_mapping[sid]
self._sync_existing_bay(bay, stack)
cluster = sid_to_cluster_mapping[sid]
self._sync_existing_cluster(cluster, stack)
# the stacks that magnum has but heat doesn't have
for sid in (six.viewkeys(sid_to_bay_mapping) -
for sid in (six.viewkeys(sid_to_cluster_mapping) -
six.viewkeys(sid_to_stack_mapping)):
bay = sid_to_bay_mapping[sid]
self._sync_missing_heat_stack(bay)
cluster = sid_to_cluster_mapping[sid]
self._sync_missing_heat_stack(cluster)
except Exception as e:
LOG.warning(_LW(
"Ignore error [%s] when syncing up bay status."
"Ignore error [%s] when syncing up cluster status."
), e, exc_info=True)
def _get_bay_stacks(self, bays, sid_to_bay_mapping, bay_stack_ids):
def _get_cluster_stacks(
self, clusters, sid_to_cluster_mapping, cluster_stack_ids):
stacks = []
_bays = bays
_sid_to_bay_mapping = sid_to_bay_mapping
_bay_stack_ids = bay_stack_ids
_clusters = clusters
_sid_to_cluster_mapping = sid_to_cluster_mapping
_cluster_stack_ids = cluster_stack_ids
for bay in _bays:
for cluster in _clusters:
try:
# Create client with bay's trustee user context
# Create client with cluster's trustee user context
bosc = clients.OpenStackClients(
context.make_bay_context(bay))
stack = bosc.heat().stacks.get(bay.stack_id)
context.make_cluster_context(cluster))
stack = bosc.heat().stacks.get(cluster.stack_id)
stacks.append(stack)
# No need to do anything in this case
except heat_exc.HTTPNotFound:
pass
except Exception as e:
# Any other exception means we do not perform any
# action on this bay in the current sync run, so remove
# action on this cluster in the current sync run, so remove
# it from all records.
LOG.warning(_LW("Exception while attempting to retrieve "
"Heat stack %(stack_id)s for bay %(bay_id)s. "
"Traceback follows."),
{'stack_id': bay.stack_id, 'bay_id': bay.id})
LOG.warning(
_LW("Exception while attempting to retrieve "
"Heat stack %(stack_id)s for cluster %(cluster_id)s. "
"Traceback follows."),
{'stack_id': cluster.stack_id, 'cluster_id': cluster.id})
LOG.warning(e)
_sid_to_bay_mapping.pop(bay.stack_id)
_bay_stack_ids.remove(bay.stack_id)
_bays.remove(bay)
return [stacks, _bays, _bay_stack_ids, _sid_to_bay_mapping]
_sid_to_cluster_mapping.pop(cluster.stack_id)
_cluster_stack_ids.remove(cluster.stack_id)
_clusters.remove(cluster)
return [stacks, _clusters, _cluster_stack_ids, _sid_to_cluster_mapping]
def _sync_existing_bay(self, bay, stack):
if bay.status != stack.stack_status:
old_status = bay.status
bay.status = stack.stack_status
bay.status_reason = stack.stack_status_reason
bay.save()
LOG.info(_LI("Sync up bay with id %(id)s from "
def _sync_existing_cluster(self, cluster, stack):
if cluster.status != stack.stack_status:
old_status = cluster.status
cluster.status = stack.stack_status
cluster.status_reason = stack.stack_status_reason
cluster.save()
LOG.info(_LI("Sync up cluster with id %(id)s from "
"%(old_status)s to %(status)s."),
{'id': bay.id, 'old_status': old_status,
'status': bay.status})
{'id': cluster.id, 'old_status': old_status,
'status': cluster.status})
def _sync_missing_heat_stack(self, bay):
if bay.status == fields.BayStatus.DELETE_IN_PROGRESS:
self._sync_deleted_stack(bay)
elif bay.status == fields.BayStatus.CREATE_IN_PROGRESS:
self._sync_missing_stack(bay, fields.BayStatus.CREATE_FAILED)
elif bay.status == fields.BayStatus.UPDATE_IN_PROGRESS:
self._sync_missing_stack(bay, fields.BayStatus.UPDATE_FAILED)
def _sync_missing_heat_stack(self, cluster):
if cluster.status == fields.ClusterStatus.DELETE_IN_PROGRESS:
self._sync_deleted_stack(cluster)
elif cluster.status == fields.ClusterStatus.CREATE_IN_PROGRESS:
self._sync_missing_stack(cluster,
fields.ClusterStatus.CREATE_FAILED)
elif cluster.status == fields.ClusterStatus.UPDATE_IN_PROGRESS:
self._sync_missing_stack(cluster,
fields.ClusterStatus.UPDATE_FAILED)
def _sync_deleted_stack(self, bay):
def _sync_deleted_stack(self, cluster):
try:
bay.destroy()
cluster.destroy()
except exception.ClusterNotFound:
LOG.info(_LI('The bay %s has been deleted by others.'), bay.uuid)
LOG.info(_LI('The cluster %s has been deleted by others.'),
cluster.uuid)
else:
LOG.info(_LI("Bay with id %(id)s not found in heat "
LOG.info(_LI("cluster with id %(id)s not found in heat "
"with stack id %(sid)s, with status_reason: "
"%(reason)s."), {'id': bay.id, 'sid': bay.stack_id,
'reason': bay.status_reason})
"%(reason)s."), {'id': cluster.id,
'sid': cluster.stack_id,
'reason': cluster.status_reason})
def _sync_missing_stack(self, bay, new_status):
bay.status = new_status
bay.status_reason = _("Stack with id %s not found in "
"Heat.") % bay.stack_id
bay.save()
LOG.info(_LI("Bay with id %(id)s has been set to "
def _sync_missing_stack(self, cluster, new_status):
cluster.status = new_status
cluster.status_reason = _("Stack with id %s not found in "
"Heat.") % cluster.stack_id
cluster.save()
LOG.info(_LI("Cluster with id %(id)s has been set to "
"%(status)s due to stack with id %(sid)s "
"not found in Heat."),
{'id': bay.id, 'status': bay.status,
'sid': bay.stack_id})
{'id': cluster.id, 'status': cluster.status,
'sid': cluster.stack_id})
@periodic_task.periodic_task(run_immediately=True)
@set_context
def _send_bay_metrics(self, ctx):
LOG.debug('Starting to send bay metrics')
for bay in objects.Bay.list(ctx):
if bay.status not in [fields.BayStatus.CREATE_COMPLETE,
fields.BayStatus.UPDATE_COMPLETE]:
def _send_cluster_metrics(self, ctx):
LOG.debug('Starting to send cluster metrics')
for cluster in objects.Cluster.list(ctx):
if cluster.status not in [fields.ClusterStatus.CREATE_COMPLETE,
fields.ClusterStatus.UPDATE_COMPLETE]:
continue
monitor = monitors.create_monitor(ctx, bay)
monitor = monitors.create_monitor(ctx, cluster)
if monitor is None:
continue
try:
monitor.pull_data()
except Exception as e:
LOG.warning(_LW("Skip pulling data from bay %(bay)s due to "
"error: %(e)s"),
{'e': e, 'bay': bay.uuid}, exc_info=True)
LOG.warning(
_LW("Skip pulling data from cluster %(cluster)s due to "
"error: %(e)s"),
{'e': e, 'cluster': cluster.uuid}, exc_info=True)
continue
metrics = list()
@ -220,11 +229,11 @@ class MagnumPeriodicTasks(periodic_task.PeriodicTasks):
{'e': e, 'name': name}, exc_info=True)
message = dict(metrics=metrics,
user_id=bay.user_id,
project_id=bay.project_id,
resource_id=bay.uuid)
user_id=cluster.user_id,
project_id=cluster.project_id,
resource_id=cluster.uuid)
LOG.debug("About to send notification: '%s'", message)
self.notifier.info(ctx, "magnum.bay.metrics.update",
self.notifier.info(ctx, "magnum.cluster.metrics.update",
message)

View File

@ -21,7 +21,7 @@ echo "Magnum's copy_instance_logs.sh was called..."
SSH_IP=$1
COE=${2-kubernetes}
NODE_TYPE=${3-master}
LOG_PATH=/opt/stack/logs/bay-nodes/${NODE_TYPE}-${SSH_IP}
LOG_PATH=/opt/stack/logs/cluster-nodes/${NODE_TYPE}-${SSH_IP}
KEYPAIR=${4-default}
PRIVATE_KEY=

View File

@ -25,7 +25,7 @@ function function_exists {
# Set up all necessary test data
function create_test_data {
# First we test Magnum's command line to see if we can stand up
# a baymodel, bay and a pod
# a cluster_template, cluster and a pod
coe=$1
special=$2

View File

@ -121,7 +121,7 @@ class TestRootController(api_base.FunctionalTest):
response = app.get('/v1/')
self.assertEqual(self.v1_expected, response.json)
response = app.get('/v1/baymodels')
response = app.get('/v1/clustertemplates')
self.assertEqual(200, response.status_int)
def test_auth_with_no_public_routes(self):
@ -146,7 +146,7 @@ class TestRootController(api_base.FunctionalTest):
response = app.get('/v1/', expect_errors=True)
self.assertEqual(401, response.status_int)
response = app.get('/v1/baymodels', expect_errors=True)
response = app.get('/v1/clustermodels', expect_errors=True)
self.assertEqual(401, response.status_int)
def test_auth_with_v1_access(self):
@ -160,7 +160,7 @@ class TestRootController(api_base.FunctionalTest):
response = app.get('/v1/')
self.assertEqual(self.v1_expected, response.json)
response = app.get('/v1/baymodels', expect_errors=True)
response = app.get('/v1/clustertemplates', expect_errors=True)
self.assertEqual(401, response.status_int)

View File

@ -16,6 +16,7 @@ import mock
from oslo_config import cfg
from oslo_utils import timeutils
from oslo_utils import uuidutils
from wsme import types as wtypes
from magnum.api import attr_validator
from magnum.api.controllers.v1 import bay as api_bay
@ -40,6 +41,29 @@ class TestBayObject(base.TestCase):
self.assertEqual(1, bay.master_count)
self.assertEqual(60, bay.bay_create_timeout)
# test unset value for baymodel_id
bay.baymodel_id = wtypes.Unset
self.assertEqual(wtypes.Unset, bay.baymodel_id)
# test backwards compatibility of bay fields with new objects
bay_dict['bay_create_timeout'] = 15
bay_dict['bay_faults'] = {'testfault': 'fault'}
bay = api_bay.Bay(**bay_dict)
self.assertEqual(15, bay.bay_create_timeout)
self.assertEqual(15, bay.create_timeout)
self.assertIn('testfault', bay.bay_faults)
self.assertIn('testfault', bay.faults)
def test_as_dict_faults(self):
bay_dict = apiutils.bay_post_data(baymodel_id=None)
del bay_dict['node_count']
del bay_dict['master_count']
del bay_dict['bay_create_timeout']
bay = api_bay.Bay(**bay_dict)
bay.bay_faults = {'testfault': 'fault'}
dict = bay.as_dict()
self.assertEqual({'testfault': 'fault'}, dict['faults'])
class TestListBay(api_base.FunctionalTest):
@ -60,7 +84,7 @@ class TestListBay(api_base.FunctionalTest):
self.assertEqual([], response['bays'])
def test_one(self):
bay = obj_utils.create_test_bay(self.context)
bay = obj_utils.create_test_cluster(self.context)
response = self.get_json('/bays')
self.assertEqual(bay.uuid, response['bays'][0]["uuid"])
self._verify_attrs(self._bay_attrs, response['bays'][0])
@ -70,7 +94,7 @@ class TestListBay(api_base.FunctionalTest):
self._verify_attrs(none_attrs, response['bays'][0], positive=False)
def test_get_one(self):
bay = obj_utils.create_test_bay(self.context)
bay = obj_utils.create_test_cluster(self.context)
response = self.get_json('/bays/%s' % bay['uuid'])
self.assertEqual(bay.uuid, response['uuid'])
self._verify_attrs(self._expand_bay_attrs, response)
@ -85,7 +109,8 @@ class TestListBay(api_base.FunctionalTest):
ht.resources.list.return_value = [fake_resources]
mock_heat.return_value = ht
bay = obj_utils.create_test_bay(self.context, status='CREATE_FAILED')
bay = obj_utils.create_test_cluster(self.context,
status='CREATE_FAILED')
response = self.get_json('/bays/%s' % bay['uuid'])
self.assertEqual(bay.uuid, response['uuid'])
self.assertEqual({'fake_name': 'fake_reason'}, response['bay_faults'])
@ -93,13 +118,14 @@ class TestListBay(api_base.FunctionalTest):
@mock.patch('magnum.common.clients.OpenStackClients.heat')
def test_get_one_failed_bay_heatclient_exception(self, mock_heat):
mock_heat.resources.list.side_effect = Exception('fake')
bay = obj_utils.create_test_bay(self.context, status='CREATE_FAILED')
bay = obj_utils.create_test_cluster(self.context,
status='CREATE_FAILED')
response = self.get_json('/bays/%s' % bay['uuid'])
self.assertEqual(bay.uuid, response['uuid'])
self.assertEqual({}, response['bay_faults'])
def test_get_one_by_name(self):
bay = obj_utils.create_test_bay(self.context)
bay = obj_utils.create_test_cluster(self.context)
response = self.get_json('/bays/%s' % bay['name'])
self.assertEqual(bay.uuid, response['uuid'])
self._verify_attrs(self._expand_bay_attrs, response)
@ -113,10 +139,10 @@ class TestListBay(api_base.FunctionalTest):
self.assertTrue(response.json['errors'])
def test_get_one_by_name_multiple_bay(self):
obj_utils.create_test_bay(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
obj_utils.create_test_bay(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
obj_utils.create_test_cluster(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
obj_utils.create_test_cluster(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
response = self.get_json('/bays/test_bay', expect_errors=True)
self.assertEqual(409, response.status_int)
self.assertEqual('application/json', response.content_type)
@ -125,8 +151,8 @@ class TestListBay(api_base.FunctionalTest):
def test_get_all_with_pagination_marker(self):
bay_list = []
for id_ in range(4):
bay = obj_utils.create_test_bay(self.context, id=id_,
uuid=uuidutils.generate_uuid())
bay = obj_utils.create_test_cluster(self.context, id=id_,
uuid=uuidutils.generate_uuid())
bay_list.append(bay)
response = self.get_json('/bays?limit=3&marker=%s'
@ -135,7 +161,7 @@ class TestListBay(api_base.FunctionalTest):
self.assertEqual(bay_list[-1].uuid, response['bays'][0]['uuid'])
def test_detail(self):
bay = obj_utils.create_test_bay(self.context)
bay = obj_utils.create_test_cluster(self.context)
response = self.get_json('/bays/detail')
self.assertEqual(bay.uuid, response['bays'][0]["uuid"])
self._verify_attrs(self._expand_bay_attrs, response['bays'][0])
@ -143,8 +169,8 @@ class TestListBay(api_base.FunctionalTest):
def test_detail_with_pagination_marker(self):
bay_list = []
for id_ in range(4):
bay = obj_utils.create_test_bay(self.context, id=id_,
uuid=uuidutils.generate_uuid())
bay = obj_utils.create_test_cluster(self.context, id=id_,
uuid=uuidutils.generate_uuid())
bay_list.append(bay)
response = self.get_json('/bays/detail?limit=3&marker=%s'
@ -154,7 +180,7 @@ class TestListBay(api_base.FunctionalTest):
self._verify_attrs(self._expand_bay_attrs, response['bays'][0])
def test_detail_against_single(self):
bay = obj_utils.create_test_bay(self.context)
bay = obj_utils.create_test_cluster(self.context)
response = self.get_json('/bays/%s/detail' % bay['uuid'],
expect_errors=True)
self.assertEqual(404, response.status_int)
@ -162,8 +188,8 @@ class TestListBay(api_base.FunctionalTest):
def test_many(self):
bm_list = []
for id_ in range(5):
bay = obj_utils.create_test_bay(self.context, id=id_,
uuid=uuidutils.generate_uuid())
bay = obj_utils.create_test_cluster(self.context, id=id_,
uuid=uuidutils.generate_uuid())
bm_list.append(bay.uuid)
response = self.get_json('/bays')
self.assertEqual(len(bm_list), len(response['bays']))
@ -172,7 +198,7 @@ class TestListBay(api_base.FunctionalTest):
def test_links(self):
uuid = uuidutils.generate_uuid()
obj_utils.create_test_bay(self.context, id=1, uuid=uuid)
obj_utils.create_test_cluster(self.context, id=1, uuid=uuid)
response = self.get_json('/bays/%s' % uuid)
self.assertIn('links', response.keys())
self.assertEqual(2, len(response['links']))
@ -183,8 +209,8 @@ class TestListBay(api_base.FunctionalTest):
def test_collection_links(self):
for id_ in range(5):
obj_utils.create_test_bay(self.context, id=id_,
uuid=uuidutils.generate_uuid())
obj_utils.create_test_cluster(self.context, id=id_,
uuid=uuidutils.generate_uuid())
response = self.get_json('/bays/?limit=3')
self.assertEqual(3, len(response['bays']))
@ -194,8 +220,8 @@ class TestListBay(api_base.FunctionalTest):
def test_collection_links_default_limit(self):
cfg.CONF.set_override('max_limit', 3, 'api')
for id_ in range(5):
obj_utils.create_test_bay(self.context, id=id_,
uuid=uuidutils.generate_uuid())
obj_utils.create_test_cluster(self.context, id=id_,
uuid=uuidutils.generate_uuid())
response = self.get_json('/bays')
self.assertEqual(3, len(response['bays']))
@ -209,10 +235,10 @@ class TestPatch(api_base.FunctionalTest):
super(TestPatch, self).setUp()
self.cluster_template = obj_utils.create_test_cluster_template(
self.context)
self.bay = obj_utils.create_test_bay(self.context,
name='bay_example_A',
node_count=3)
p = mock.patch.object(rpcapi.API, 'bay_update')
self.bay = obj_utils.create_test_cluster(self.context,
name='bay_example_A',
node_count=3)
p = mock.patch.object(rpcapi.API, 'cluster_update')
self.mock_bay_update = p.start()
self.mock_bay_update.side_effect = self._simulate_rpc_bay_update
self.addCleanup(p.stop)
@ -241,7 +267,7 @@ class TestPatch(api_base.FunctionalTest):
self.assertEqual(test_time, return_updated_at)
# Assert nothing else was changed
self.assertEqual(self.bay.uuid, response['uuid'])
self.assertEqual(self.bay.baymodel_id, response['baymodel_id'])
self.assertEqual(self.bay.cluster_template_id, response['baymodel_id'])
@mock.patch('oslo_utils.timeutils.utcnow')
def test_replace_ok_by_name(self, mock_utcnow):
@ -263,7 +289,7 @@ class TestPatch(api_base.FunctionalTest):
self.assertEqual(test_time, return_updated_at)
# Assert nothing else was changed
self.assertEqual(self.bay.uuid, response['uuid'])
self.assertEqual(self.bay.baymodel_id, response['baymodel_id'])
self.assertEqual(self.bay.cluster_template_id, response['baymodel_id'])
@mock.patch('oslo_utils.timeutils.utcnow')
def test_replace_ok_by_name_not_found(self, mock_utcnow):
@ -296,10 +322,10 @@ class TestPatch(api_base.FunctionalTest):
test_time = datetime.datetime(2000, 1, 1, 0, 0)
mock_utcnow.return_value = test_time
obj_utils.create_test_bay(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
obj_utils.create_test_bay(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
obj_utils.create_test_cluster(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
obj_utils.create_test_cluster(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
response = self.patch_json('/bays/test_bay',
[{'path': '/name', 'value': 'test_bay',
@ -356,7 +382,17 @@ class TestPatch(api_base.FunctionalTest):
self.assertEqual(400, response.status_int)
self.assertTrue(response.json['errors'])
@mock.patch.object(rpcapi.API, 'bay_update_async')
@mock.patch.object(rpcapi.API, 'cluster_update_async')
def test_update_bay_async(self, mock_update):
response = self.patch_json(
'/bays/%s' % self.bay.name,
[{'path': '/node_count', 'value': 4,
'op': 'replace'}],
headers={'OpenStack-API-Version': 'container-infra 1.2'})
self.assertEqual(202, response.status_code)
@mock.patch.object(rpcapi.API, 'cluster_update_async')
def test_update_bay_with_rollback_enabled(self, mock_update):
response = self.patch_json(
'/bays/%s/?rollback=True' % self.bay.name,
@ -381,7 +417,7 @@ class TestPatch(api_base.FunctionalTest):
self.assertEqual(1, response['node_count'])
# Assert nothing else was changed
self.assertEqual(self.bay.uuid, response['uuid'])
self.assertEqual(self.bay.baymodel_id, response['baymodel_id'])
self.assertEqual(self.bay.cluster_template_id, response['baymodel_id'])
self.assertEqual(self.bay.name, response['name'])
self.assertEqual(self.bay.master_count, response['master_count'])
@ -411,7 +447,7 @@ class TestPost(api_base.FunctionalTest):
super(TestPost, self).setUp()
self.cluster_template = obj_utils.create_test_cluster_template(
self.context)
p = mock.patch.object(rpcapi.API, 'bay_create')
p = mock.patch.object(rpcapi.API, 'cluster_create')
self.mock_bay_create = p.start()
self.mock_bay_create.side_effect = self._simulate_rpc_bay_create
self.addCleanup(p.stop)
@ -455,8 +491,8 @@ class TestPost(api_base.FunctionalTest):
self.post_json('/bays', bdict)
def test_create_bay_doesnt_contain_id(self):
with mock.patch.object(self.dbapi, 'create_bay',
wraps=self.dbapi.create_bay) as cc_mock:
with mock.patch.object(self.dbapi, 'create_cluster',
wraps=self.dbapi.create_cluster) as cc_mock:
bdict = apiutils.bay_post_data(name='bay_example_A')
response = self.post_json('/bays', bdict)
self.assertEqual(bdict['name'], response.json['name'])
@ -759,14 +795,14 @@ class TestDelete(api_base.FunctionalTest):
super(TestDelete, self).setUp()
self.cluster_template = obj_utils.create_test_cluster_template(
self.context)
self.bay = obj_utils.create_test_bay(self.context)
p = mock.patch.object(rpcapi.API, 'bay_delete')
self.bay = obj_utils.create_test_cluster(self.context)
p = mock.patch.object(rpcapi.API, 'cluster_delete')
self.mock_bay_delete = p.start()
self.mock_bay_delete.side_effect = self._simulate_rpc_bay_delete
self.addCleanup(p.stop)
def _simulate_rpc_bay_delete(self, bay_uuid):
bay = objects.Bay.get_by_uuid(self.context, bay_uuid)
bay = objects.Cluster.get_by_uuid(self.context, bay_uuid)
bay.destroy()
def test_delete_bay(self):
@ -796,10 +832,10 @@ class TestDelete(api_base.FunctionalTest):
self.assertEqual(204, response.status_int)
def test_delete_multiple_bay_by_name(self):
obj_utils.create_test_bay(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
obj_utils.create_test_bay(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
obj_utils.create_test_cluster(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
obj_utils.create_test_cluster(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
response = self.delete('/bays/test_bay', expect_errors=True)
self.assertEqual(409, response.status_int)
self.assertEqual('application/json', response.content_type)
@ -826,7 +862,7 @@ class TestBayPolicyEnforcement(api_base.FunctionalTest):
"bay:get_all", self.get_json, '/bays', expect_errors=True)
def test_policy_disallow_get_one(self):
self.bay = obj_utils.create_test_bay(self.context)
self.bay = obj_utils.create_test_cluster(self.context)
self._common_policy_check(
"bay:get", self.get_json, '/bays/%s' % self.bay.uuid,
expect_errors=True)
@ -838,9 +874,9 @@ class TestBayPolicyEnforcement(api_base.FunctionalTest):
expect_errors=True)
def test_policy_disallow_update(self):
self.bay = obj_utils.create_test_bay(self.context,
name='bay_example_A',
node_count=3)
self.bay = obj_utils.create_test_cluster(self.context,
name='bay_example_A',
node_count=3)
self._common_policy_check(
"bay:update", self.patch_json, '/bays/%s' % self.bay.name,
[{'path': '/name', 'value': "new_name", 'op': 'replace'}],
@ -852,15 +888,15 @@ class TestBayPolicyEnforcement(api_base.FunctionalTest):
"bay:create", self.post_json, '/bays', bdict, expect_errors=True)
def _simulate_rpc_bay_delete(self, bay_uuid):
bay = objects.Bay.get_by_uuid(self.context, bay_uuid)
bay = objects.Cluster.get_by_uuid(self.context, bay_uuid)
bay.destroy()
def test_policy_disallow_delete(self):
p = mock.patch.object(rpcapi.API, 'bay_delete')
p = mock.patch.object(rpcapi.API, 'cluster_delete')
self.mock_bay_delete = p.start()
self.mock_bay_delete.side_effect = self._simulate_rpc_bay_delete
self.addCleanup(p.stop)
self.bay = obj_utils.create_test_bay(self.context)
self.bay = obj_utils.create_test_cluster(self.context)
self._common_policy_check(
"bay:delete", self.delete, '/bays/%s' % self.bay.uuid,
expect_errors=True)
@ -875,18 +911,18 @@ class TestBayPolicyEnforcement(api_base.FunctionalTest):
response.json['errors'][0]['detail'])
def test_policy_only_owner_get_one(self):
bay = obj_utils.create_test_bay(self.context, user_id='another')
bay = obj_utils.create_test_cluster(self.context, user_id='another')
self._owner_check("bay:get", self.get_json, '/bays/%s' % bay.uuid,
expect_errors=True)
def test_policy_only_owner_update(self):
bay = obj_utils.create_test_bay(self.context, user_id='another')
bay = obj_utils.create_test_cluster(self.context, user_id='another')
self._owner_check(
"bay:update", self.patch_json, '/bays/%s' % bay.uuid,
[{'path': '/name', 'value': "new_name", 'op': 'replace'}],
expect_errors=True)
def test_policy_only_owner_delete(self):
bay = obj_utils.create_test_bay(self.context, user_id='another')
bay = obj_utils.create_test_cluster(self.context, user_id='another')
self._owner_check("bay:delete", self.delete, '/bays/%s' % bay.uuid,
expect_errors=True)

View File

@ -219,7 +219,8 @@ class TestPatch(api_base.FunctionalTest):
def test_update_baymodel_with_bay(self):
baymodel = obj_utils.create_test_cluster_template(self.context)
obj_utils.create_test_bay(self.context, baymodel_id=baymodel.uuid)
obj_utils.create_test_cluster(self.context,
cluster_template_id=baymodel.uuid)
response = self.patch_json('/baymodels/%s' % baymodel.uuid,
[{'path': '/name',
@ -253,7 +254,8 @@ class TestPatch(api_base.FunctionalTest):
def test_update_baymodel_with_bay_allow_update(self):
baymodel = obj_utils.create_test_cluster_template(self.context)
obj_utils.create_test_bay(self.context, baymodel_id=baymodel.uuid)
obj_utils.create_test_cluster(self.context,
cluster_template_id=baymodel.uuid)
response = self.patch_json('/baymodels/%s' % baymodel.uuid,
[{'path': '/public',
'value': True,
@ -265,7 +267,8 @@ class TestPatch(api_base.FunctionalTest):
def test_update_baymodel_with_bay_not_allow_update(self):
baymodel = obj_utils.create_test_cluster_template(self.context)
obj_utils.create_test_bay(self.context, baymodel_id=baymodel.uuid)
obj_utils.create_test_cluster(self.context,
cluster_template_id=baymodel.uuid)
response = self.patch_json('/baymodels/%s' % baymodel.uuid,
[{'path': '/name',
'value': 'new_name',
@ -911,7 +914,8 @@ class TestDelete(api_base.FunctionalTest):
def test_delete_baymodel_with_bay(self):
baymodel = obj_utils.create_test_cluster_template(self.context)
obj_utils.create_test_bay(self.context, baymodel_id=baymodel.uuid)
obj_utils.create_test_cluster(self.context,
cluster_template_id=baymodel.uuid)
response = self.delete('/baymodels/%s' % baymodel.uuid,
expect_errors=True)
self.assertEqual(400, response.status_int)

View File

@ -222,14 +222,14 @@ class TestPatch(api_base.FunctionalTest):
self.context)
self.cluster_obj = obj_utils.create_test_cluster(
self.context, name='cluster_example_A', node_count=3)
p = mock.patch.object(rpcapi.API, 'bay_update_async')
self.mock_bay_update = p.start()
self.mock_bay_update.side_effect = self._simulate_rpc_bay_update
p = mock.patch.object(rpcapi.API, 'cluster_update_async')
self.mock_cluster_update = p.start()
self.mock_cluster_update.side_effect = self._sim_rpc_cluster_update
self.addCleanup(p.stop)
def _simulate_rpc_bay_update(self, bay, rollback=False):
bay.save()
return bay
def _sim_rpc_cluster_update(self, cluster, rollback=False):
cluster.save()
return cluster
@mock.patch('oslo_utils.timeutils.utcnow')
def test_replace_ok(self, mock_utcnow):
@ -251,7 +251,7 @@ class TestPatch(api_base.FunctionalTest):
self.assertEqual(test_time, return_updated_at)
# Assert nothing else was changed
self.assertEqual(self.cluster_obj.uuid, response['uuid'])
self.assertEqual(self.cluster_obj.baymodel_id,
self.assertEqual(self.cluster_obj.cluster_template_id,
response['cluster_template_id'])
@mock.patch('oslo_utils.timeutils.utcnow')
@ -274,7 +274,7 @@ class TestPatch(api_base.FunctionalTest):
self.assertEqual(test_time, return_updated_at)
# Assert nothing else was changed
self.assertEqual(self.cluster_obj.uuid, response['uuid'])
self.assertEqual(self.cluster_obj.baymodel_id,
self.assertEqual(self.cluster_obj.cluster_template_id,
response['cluster_template_id'])
@mock.patch('oslo_utils.timeutils.utcnow')
@ -385,7 +385,7 @@ class TestPatch(api_base.FunctionalTest):
self.assertEqual(1, response['node_count'])
# Assert nothing else was changed
self.assertEqual(self.cluster_obj.uuid, response['uuid'])
self.assertEqual(self.cluster_obj.baymodel_id,
self.assertEqual(self.cluster_obj.cluster_template_id,
response['cluster_template_id'])
self.assertEqual(self.cluster_obj.name, response['name'])
self.assertEqual(self.cluster_obj.master_count,
@ -416,17 +416,17 @@ class TestPost(api_base.FunctionalTest):
super(TestPost, self).setUp()
self.cluster_template = obj_utils.create_test_cluster_template(
self.context)
p = mock.patch.object(rpcapi.API, 'bay_create_async')
self.mock_bay_create = p.start()
self.mock_bay_create.side_effect = self._simulate_rpc_bay_create
p = mock.patch.object(rpcapi.API, 'cluster_create_async')
self.mock_cluster_create = p.start()
self.mock_cluster_create.side_effect = self._simulate_cluster_create
self.addCleanup(p.stop)
p = mock.patch.object(attr_validator, 'validate_os_resources')
self.mock_valid_os_res = p.start()
self.addCleanup(p.stop)
def _simulate_rpc_bay_create(self, bay, bay_create_timeout):
bay.create()
return bay
def _simulate_cluster_create(self, cluster, create_timeout):
cluster.create()
return cluster
@mock.patch('oslo_utils.timeutils.utcnow')
def test_create_cluster(self, mock_utcnow):
@ -442,19 +442,19 @@ class TestPost(api_base.FunctionalTest):
def test_create_cluster_set_project_id_and_user_id(self):
bdict = apiutils.cluster_post_data()
def _simulate_rpc_bay_create(bay, bay_create_timeout):
self.assertEqual(self.context.project_id, bay.project_id)
self.assertEqual(self.context.user_id, bay.user_id)
bay.create()
return bay
def _simulate_rpc_cluster_create(cluster, create_timeout):
self.assertEqual(self.context.project_id, cluster.project_id)
self.assertEqual(self.context.user_id, cluster.user_id)
cluster.create()
return cluster
self.mock_bay_create.side_effect = _simulate_rpc_bay_create
self.mock_cluster_create.side_effect = _simulate_rpc_cluster_create
self.post_json('/clusters', bdict)
def test_create_cluster_doesnt_contain_id(self):
with mock.patch.object(self.dbapi, 'create_bay',
wraps=self.dbapi.create_bay) as cc_mock:
with mock.patch.object(self.dbapi, 'create_cluster',
wraps=self.dbapi.create_cluster) as cc_mock:
bdict = apiutils.cluster_post_data(name='cluster_example_A')
response = self.post_json('/clusters', bdict)
cc_mock.assert_called_once_with(mock.ANY)
@ -643,12 +643,12 @@ class TestPost(api_base.FunctionalTest):
self.assertEqual(202, response.status_int)
def test_create_cluster_with_no_timeout(self):
def _simulate_rpc_bay_create(bay, bay_create_timeout):
self.assertEqual(60, bay_create_timeout)
bay.create()
return bay
def _simulate_rpc_cluster_create(cluster, create_timeout):
self.assertEqual(60, create_timeout)
cluster.create()
return cluster
self.mock_bay_create.side_effect = _simulate_rpc_bay_create
self.mock_cluster_create.side_effect = _simulate_rpc_cluster_create
bdict = apiutils.cluster_post_data()
del bdict['create_timeout']
response = self.post_json('/clusters', bdict, expect_errors=True)
@ -748,14 +748,14 @@ class TestDelete(api_base.FunctionalTest):
self.cluster_template = obj_utils.create_test_cluster_template(
self.context)
self.cluster = obj_utils.create_test_cluster(self.context)
p = mock.patch.object(rpcapi.API, 'bay_delete_async')
self.mock_bay_delete = p.start()
self.mock_bay_delete.side_effect = self._simulate_rpc_bay_delete
p = mock.patch.object(rpcapi.API, 'cluster_delete_async')
self.mock_cluster_delete = p.start()
self.mock_cluster_delete.side_effect = self._simulate_cluster_delete
self.addCleanup(p.stop)
def _simulate_rpc_bay_delete(self, bay_uuid):
bay = objects.Bay.get_by_uuid(self.context, bay_uuid)
bay.destroy()
def _simulate_cluster_delete(self, cluster_uuid):
cluster = objects.Cluster.get_by_uuid(self.context, cluster_uuid)
cluster.destroy()
def test_delete_cluster(self):
self.delete('/clusters/%s' % self.cluster.uuid)
@ -840,14 +840,14 @@ class TestClusterPolicyEnforcement(api_base.FunctionalTest):
"cluster:create", self.post_json, '/clusters', bdict,
expect_errors=True)
def _simulate_rpc_bay_delete(self, bay_uuid):
bay = objects.Bay.get_by_uuid(self.context, bay_uuid)
bay.destroy()
def _simulate_cluster_delete(self, cluster_uuid):
cluster = objects.Cluster.get_by_uuid(self.context, cluster_uuid)
cluster.destroy()
def test_policy_disallow_delete(self):
p = mock.patch.object(rpcapi.API, 'bay_delete')
self.mock_bay_delete = p.start()
self.mock_bay_delete.side_effect = self._simulate_rpc_bay_delete
p = mock.patch.object(rpcapi.API, 'cluster_delete')
self.mock_cluster_delete = p.start()
self.mock_cluster_delete.side_effect = self._simulate_cluster_delete
self.addCleanup(p.stop)
self.cluster = obj_utils.create_test_cluster(self.context)
self._common_policy_check(

View File

@ -228,8 +228,8 @@ class TestPatch(api_base.FunctionalTest):
def test_update_cluster_template_with_cluster(self):
cluster_template = obj_utils.create_test_cluster_template(self.context)
obj_utils.create_test_cluster(self.context,
baymodel_id=cluster_template.uuid)
obj_utils.create_test_cluster(
self.context, cluster_template_id=cluster_template.uuid)
response = self.patch_json('/clustertemplates/%s' %
cluster_template.uuid,
@ -267,8 +267,8 @@ class TestPatch(api_base.FunctionalTest):
def test_update_cluster_template_with_cluster_allow_update(self):
cluster_template = obj_utils.create_test_cluster_template(self.context)
obj_utils.create_test_cluster(self.context,
baymodel_id=cluster_template.uuid)
obj_utils.create_test_cluster(
self.context, cluster_template_id=cluster_template.uuid)
response = self.patch_json('/clustertemplates/%s' %
cluster_template.uuid,
[{'path': '/public',
@ -282,8 +282,8 @@ class TestPatch(api_base.FunctionalTest):
def test_update_cluster_template_with_cluster_not_allow_update(self):
cluster_template = obj_utils.create_test_cluster_template(self.context)
obj_utils.create_test_cluster(self.context,
baymodel_id=cluster_template.uuid)
obj_utils.create_test_cluster(
self.context, cluster_template_id=cluster_template.uuid)
response = self.patch_json('/clustertemplates/%s' %
cluster_template.uuid,
[{'path': '/name',
@ -963,8 +963,8 @@ class TestDelete(api_base.FunctionalTest):
def test_delete_cluster_template_with_cluster(self):
cluster_template = obj_utils.create_test_cluster_template(self.context)
obj_utils.create_test_cluster(self.context,
baymodel_id=cluster_template.uuid)
obj_utils.create_test_cluster(
self.context, cluster_template_id=cluster_template.uuid)
response = self.delete('/clustertemplates/%s' % cluster_template.uuid,
expect_errors=True)
self.assertEqual(400, response.status_int)

View File

@ -53,40 +53,40 @@ class TestApiUtils(base.FunctionalTest):
'fake-sort')
@mock.patch('pecan.request')
@mock.patch('magnum.objects.Bay.get_by_name')
@mock.patch('magnum.objects.Bay.get_by_uuid')
@mock.patch('magnum.objects.Cluster.get_by_name')
@mock.patch('magnum.objects.Cluster.get_by_uuid')
def test_get_resource_with_uuid(
self,
mock_get_by_uuid,
mock_get_by_name,
mock_request):
mock_bay = mock.MagicMock
mock_get_by_uuid.return_value = mock_bay
mock_cluster = mock.MagicMock
mock_get_by_uuid.return_value = mock_cluster
uuid = uuidutils.generate_uuid()
returned_bay = utils.get_resource('Bay', uuid)
returned_cluster = utils.get_resource('Cluster', uuid)
mock_get_by_uuid.assert_called_once_with(mock_request.context, uuid)
self.assertFalse(mock_get_by_name.called)
self.assertEqual(mock_bay, returned_bay)
self.assertEqual(mock_cluster, returned_cluster)
@mock.patch('pecan.request')
@mock.patch('magnum.objects.Bay.get_by_name')
@mock.patch('magnum.objects.Bay.get_by_uuid')
@mock.patch('magnum.objects.Cluster.get_by_name')
@mock.patch('magnum.objects.Cluster.get_by_uuid')
def test_get_resource_with_name(
self,
mock_get_by_uuid,
mock_get_by_name,
mock_request):
mock_bay = mock.MagicMock
mock_get_by_name.return_value = mock_bay
mock_cluster = mock.MagicMock
mock_get_by_name.return_value = mock_cluster
returned_bay = utils.get_resource('Bay', 'fake-name')
returned_cluster = utils.get_resource('Cluster', 'fake-name')
self.assertFalse(mock_get_by_uuid.called)
mock_get_by_name.assert_called_once_with(mock_request.context,
'fake-name')
self.assertEqual(mock_bay, returned_bay)
self.assertEqual(mock_cluster, returned_cluster)
@mock.patch.object(uuidutils, 'is_uuid_like', return_value=True)
def test_get_openstack_resource_by_uuid(self, fake_is_uuid_like):
@ -125,13 +125,13 @@ class TestApiUtils(base.FunctionalTest):
@mock.patch.object(jsonpatch, 'apply_patch')
def test_apply_jsonpatch(self, mock_jsonpatch):
doc = {'bay_uuid': 'id', 'node_count': 1}
doc = {'cluster_uuid': 'id', 'node_count': 1}
patch = [{"path": "/node_count", "value": 2, "op": "replace"}]
utils.apply_jsonpatch(doc, patch)
mock_jsonpatch.assert_called_once_with(doc, patch)
def test_apply_jsonpatch_add_attr_not_exist(self):
doc = {'bay_uuid': 'id', 'node_count': 1}
doc = {'cluster_uuid': 'id', 'node_count': 1}
patch = [{"path": "/fake", "value": 2, "op": "add"}]
exc = self.assertRaises(wsme.exc.ClientSideError,
utils.apply_jsonpatch,
@ -141,7 +141,7 @@ class TestApiUtils(base.FunctionalTest):
"not allowed.", exc.faultstring)
def test_apply_jsonpatch_add_attr_already_exist(self):
doc = {'bay_uuid': 'id', 'node_count': 1}
doc = {'cluster_uuid': 'id', 'node_count': 1}
patch = [{"path": "/node_count", "value": 2, "op": "add"}]
exc = self.assertRaises(wsme.exc.ClientSideError,
utils.apply_jsonpatch,

View File

@ -26,148 +26,148 @@ from magnum.tests.unit.objects import utils as obj_utils
class TestValidation(base.BaseTestCase):
def _test_enforce_bay_types(
def _test_enforce_cluster_types(
self,
mock_bay_get_by_uuid,
mock_cluster_get_by_uuid,
mock_pecan_request,
bay_type,
allowed_bay_types,
cluster_type,
allowed_cluster_types,
assert_raised=False,
*args):
@v.enforce_bay_types(*allowed_bay_types)
@v.enforce_cluster_types(*allowed_cluster_types)
def test(self, *args):
if hasattr(args[0], 'bay_uuid'):
if hasattr(args[0], 'cluster_uuid'):
return args[0].name
else:
return args[1]
context = mock_pecan_request.context
bay = mock.MagicMock()
bay.baymodel_id = 'cluster_template_id'
cluster = mock.MagicMock()
cluster.cluster_template_id = 'cluster_template_id'
cluster_template = obj_utils.get_test_cluster_template(
context, uuid='cluster_template_id', coe=bay_type)
bay.cluster_template = cluster_template
context, uuid='cluster_template_id', coe=cluster_type)
cluster.cluster_template = cluster_template
mock_bay_get_by_uuid.return_value = bay
mock_cluster_get_by_uuid.return_value = cluster
if assert_raised:
self.assertRaises(
exception.InvalidParameterValue, test, self, *args)
else:
ret = test(self, *args)
if hasattr(args[0], 'bay_uuid'):
mock_bay_get_by_uuid.assert_called_once_with(context,
args[0].bay_uuid)
if hasattr(args[0], 'cluster_uuid'):
mock_cluster_get_by_uuid.assert_called_once_with(
context, args[0].cluster_uuid)
self.assertEqual(args[0].name, ret)
else:
mock_bay_get_by_uuid.assert_called_once_with(context, args[1])
mock_cluster_get_by_uuid.assert_called_once_with(
context, args[1])
self.assertEqual(args[1], ret)
@mock.patch('pecan.request')
@mock.patch('magnum.objects.Bay.get_by_uuid')
def test_enforce_bay_types_one_allowed(
@mock.patch('magnum.objects.Cluster.get_by_uuid')
def test_enforce_cluster_types_one_allowed(
self,
mock_bay_get_by_uuid,
mock_cluster_get_by_uuid,
mock_pecan_request):
obj = mock.MagicMock()
obj.name = 'test_object'
obj.bay_uuid = 'bay_uuid'
bay_type = 'swarm'
allowed_bay_types = ['swarm']
self._test_enforce_bay_types(
mock_bay_get_by_uuid, mock_pecan_request,
bay_type, allowed_bay_types, False, obj)
obj.cluster_uuid = 'cluster_uuid'
cluster_type = 'swarm'
allowed_cluster_types = ['swarm']
self._test_enforce_cluster_types(
mock_cluster_get_by_uuid, mock_pecan_request,
cluster_type, allowed_cluster_types, False, obj)
@mock.patch('pecan.request')
@mock.patch('magnum.objects.Bay.get_by_uuid')
def test_enforce_bay_types_two_allowed(
@mock.patch('magnum.objects.Cluster.get_by_uuid')
def test_enforce_cluster_types_two_allowed(
self,
mock_bay_get_by_uuid,
mock_cluster_get_by_uuid,
mock_pecan_request):
obj = mock.MagicMock()
obj.name = 'test_object'
obj.bay_uuid = 'bay_uuid'
bay_type = 'swarm'
allowed_bay_types = ['swarm', 'mesos']
self._test_enforce_bay_types(
mock_bay_get_by_uuid, mock_pecan_request,
bay_type, allowed_bay_types, False, obj)
obj.cluster_uuid = 'cluster_uuid'
cluster_type = 'swarm'
allowed_cluster_types = ['swarm', 'mesos']
self._test_enforce_cluster_types(
mock_cluster_get_by_uuid, mock_pecan_request,
cluster_type, allowed_cluster_types, False, obj)
@mock.patch('pecan.request')
@mock.patch('magnum.objects.Bay.get_by_uuid')
def test_enforce_bay_types_not_allowed(
@mock.patch('magnum.objects.Cluster.get_by_uuid')
def test_enforce_cluster_types_not_allowed(
self,
mock_bay_get_by_uuid,
mock_cluster_get_by_uuid,
mock_pecan_request):
obj = mock.MagicMock()
obj.name = 'test_object'
obj.bay_uuid = 'bay_uuid'
bay_type = 'swarm'
allowed_bay_types = ['mesos']
self._test_enforce_bay_types(
mock_bay_get_by_uuid, mock_pecan_request,
bay_type, allowed_bay_types,
obj.cluster_uuid = 'cluster_uuid'
cluster_type = 'swarm'
allowed_cluster_types = ['mesos']
self._test_enforce_cluster_types(
mock_cluster_get_by_uuid, mock_pecan_request,
cluster_type, allowed_cluster_types,
True, obj)
@mock.patch('pecan.request')
@mock.patch('magnum.objects.Bay.get_by_uuid')
def test_enforce_bay_types_with_bay_uuid(self, mock_bay_get_by_uuid,
mock_pecan_request):
@mock.patch('magnum.objects.Cluster.get_by_uuid')
def test_enforce_cluster_types_with_cluster_uuid(self,
mock_cluster_get_by_uuid,
mock_pecan_request):
bay_ident = 'e74c40e0-d825-11e2-a28f-0800200c9a66'
cluster_ident = 'e74c40e0-d825-11e2-a28f-0800200c9a66'
bay_type = 'swarm'
allowed_bay_types = ['swarm']
self._test_enforce_bay_types(
mock_bay_get_by_uuid, mock_pecan_request,
bay_type, allowed_bay_types, False,
None, bay_ident)
cluster_type = 'swarm'
allowed_cluster_types = ['swarm']
self._test_enforce_cluster_types(
mock_cluster_get_by_uuid, mock_pecan_request,
cluster_type, allowed_cluster_types, False,
None, cluster_ident)
@mock.patch('pecan.request')
@mock.patch('magnum.objects.Bay.get_by_uuid')
def test_enforce_bay_types_with_bay_uuid_not_allowed(self,
mock_bay_get_by_uuid,
mock_pecan_request):
@mock.patch('magnum.objects.Cluster.get_by_uuid')
def test_enforce_cluster_types_with_cluster_uuid_not_allowed(
self, mock_cluster_get_by_uuid, mock_pecan_request):
bay_ident = 'e74c40e0-d825-11e2-a28f-0800200c9a66'
cluster_ident = 'e74c40e0-d825-11e2-a28f-0800200c9a66'
bay_type = 'swarm'
allowed_bay_types = ['mesos']
self._test_enforce_bay_types(
mock_bay_get_by_uuid, mock_pecan_request,
bay_type, allowed_bay_types, True,
None, bay_ident)
cluster_type = 'swarm'
allowed_cluster_types = ['mesos']
self._test_enforce_cluster_types(
mock_cluster_get_by_uuid, mock_pecan_request,
cluster_type, allowed_cluster_types, True,
None, cluster_ident)
@mock.patch('pecan.request')
@mock.patch('magnum.objects.Bay.get_by_name')
def test_enforce_bay_types_with_bay_name(self, mock_bay_get_by_uuid,
mock_pecan_request):
@mock.patch('magnum.objects.Cluster.get_by_name')
def test_enforce_cluster_types_with_cluster_name(
self, mock_cluster_get_by_uuid, mock_pecan_request):
bay_ident = 'bay_name'
bay_type = 'swarm'
allowed_bay_types = ['swarm']
self._test_enforce_bay_types(
mock_bay_get_by_uuid, mock_pecan_request,
bay_type, allowed_bay_types, False,
None, bay_ident)
cluster_ident = 'cluster_name'
cluster_type = 'swarm'
allowed_cluster_types = ['swarm']
self._test_enforce_cluster_types(
mock_cluster_get_by_uuid, mock_pecan_request,
cluster_type, allowed_cluster_types, False,
None, cluster_ident)
@mock.patch('pecan.request')
@mock.patch('magnum.objects.Bay.get_by_name')
def test_enforce_bay_types_with_bay_name_not_allowed(self,
mock_bay_get_by_uuid,
mock_pecan_request):
@mock.patch('magnum.objects.Cluster.get_by_name')
def test_enforce_cluster_types_with_cluster_name_not_allowed(
self, mock_cluster_get_by_uuid, mock_pecan_request):
bay_ident = 'bay_name'
bay_type = 'swarm'
allowed_bay_types = ['mesos']
self._test_enforce_bay_types(
mock_bay_get_by_uuid, mock_pecan_request,
bay_type, allowed_bay_types, True,
None, bay_ident)
cluster_ident = 'cluster_name'
cluster_type = 'swarm'
allowed_cluster_types = ['mesos']
self._test_enforce_cluster_types(
mock_cluster_get_by_uuid, mock_pecan_request,
cluster_type, allowed_cluster_types, True,
None, cluster_ident)
def _test_enforce_network_driver_types_create(
self,
@ -413,11 +413,11 @@ class TestValidation(base.BaseTestCase):
volume_driver_type='cinder',
op='remove')
def test_validate_bay_properties(self):
allowed_properties = v.bay_update_allowed_properties
for field in objects.Bay.fields:
def test_validate_cluster_properties(self):
allowed_properties = v.cluster_update_allowed_properties
for field in objects.Cluster.fields:
if field in allowed_properties:
v.validate_bay_properties(set([field]))
v.validate_cluster_properties(set([field]))
else:
self.assertRaises(exception.InvalidParameterValue,
v.validate_bay_properties, set([field]))
v.validate_cluster_properties, set([field]))

View File

@ -42,19 +42,18 @@ def cluster_template_post_data(**kw):
def bay_post_data(**kw):
bay = utils.get_test_bay(**kw)
bay = utils.get_test_cluster(**kw)
bay['baymodel_id'] = kw.get('baymodel_id', bay['cluster_template_id'])
bay['bay_create_timeout'] = kw.get('bay_create_timeout', 15)
del bay['cluster_template_id']
del bay['create_timeout']
internal = bay_controller.BayPatchType.internal_attrs()
return remove_internal(bay, internal)
def cluster_post_data(**kw):
cluster = utils.get_test_bay(**kw)
cluster = utils.get_test_cluster(**kw)
cluster['create_timeout'] = kw.get('create_timeout', 15)
cluster['cluster_template_id'] = kw.get('cluster_template_id',
cluster['baymodel_id'])
del cluster['bay_create_timeout']
del cluster['baymodel_id']
internal = cluster_controller.ClusterPatchType.internal_attrs()
return remove_internal(cluster, internal)

View File

@ -112,18 +112,18 @@ class KeystoneClientTest(base.TestCase):
def test_delete_trust(self, mock_ks):
mock_ks.return_value.trusts.delete.return_value = None
ks_client = keystone.KeystoneClientV3(self.ctx)
bay = mock.MagicMock()
bay.trust_id = 'atrust123'
self.assertIsNone(ks_client.delete_trust(self.ctx, bay))
cluster = mock.MagicMock()
cluster.trust_id = 'atrust123'
self.assertIsNone(ks_client.delete_trust(self.ctx, cluster))
mock_ks.return_value.trusts.delete.assert_called_once_with('atrust123')
def test_delete_trust_not_found(self, mock_ks):
mock_delete = mock_ks.return_value.trusts.delete
mock_delete.side_effect = kc_exception.NotFound()
ks_client = keystone.KeystoneClientV3(self.ctx)
bay = mock.MagicMock()
bay.trust_id = 'atrust123'
self.assertIsNone(ks_client.delete_trust(self.ctx, bay))
cluster = mock.MagicMock()
cluster.trust_id = 'atrust123'
self.assertIsNone(ks_client.delete_trust(self.ctx, cluster))
@mock.patch('keystoneauth1.session.Session')
def test_create_trust_with_all_roles(self, mock_session, mock_ks):

View File

@ -35,8 +35,8 @@ class TrustManagerTestCase(base.BaseTestCase):
def test_create_trustee_and_trust(self, mock_generate_password):
mock_password = "password_mock"
mock_generate_password.return_value = mock_password
mock_bay = mock.MagicMock()
mock_bay.uuid = 'mock_bay_uuid'
mock_cluster = mock.MagicMock()
mock_cluster.uuid = 'mock_cluster_uuid'
mock_keystone = mock.MagicMock()
mock_trustee = mock.MagicMock()
mock_trustee.id = 'mock_trustee_id'
@ -49,75 +49,75 @@ class TrustManagerTestCase(base.BaseTestCase):
mock_keystone.create_trustee.return_value = mock_trustee
mock_keystone.create_trust.return_value = mock_trust
trust_manager.create_trustee_and_trust(self.osc, mock_bay)
trust_manager.create_trustee_and_trust(self.osc, mock_cluster)
mock_keystone.create_trustee.assert_called_once_with(
mock_bay.uuid,
mock_cluster.uuid,
mock_password,
)
mock_keystone.create_trust.assert_called_once_with(
mock_trustee.id,
)
self.assertEqual(mock_trustee.name, mock_bay.trustee_username)
self.assertEqual(mock_trustee.id, mock_bay.trustee_user_id)
self.assertEqual(mock_password, mock_bay.trustee_password)
self.assertEqual(mock_trust.id, mock_bay.trust_id)
self.assertEqual(mock_trustee.name, mock_cluster.trustee_username)
self.assertEqual(mock_trustee.id, mock_cluster.trustee_user_id)
self.assertEqual(mock_password, mock_cluster.trustee_password)
self.assertEqual(mock_trust.id, mock_cluster.trust_id)
@patch('magnum.common.utils.generate_password')
def test_create_trustee_and_trust_with_error(self, mock_generate_password):
mock_bay = mock.MagicMock()
mock_cluster = mock.MagicMock()
mock_generate_password.side_effect = exception.MagnumException()
self.assertRaises(exception.TrusteeOrTrustToBayFailed,
self.assertRaises(exception.TrusteeOrTrustToClusterFailed,
trust_manager.create_trustee_and_trust,
self.osc,
mock_bay)
mock_cluster)
def test_delete_trustee_and_trust(self):
mock_bay = mock.MagicMock()
mock_bay.trust_id = 'trust_id'
mock_bay.trustee_user_id = 'trustee_user_id'
mock_cluster = mock.MagicMock()
mock_cluster.trust_id = 'trust_id'
mock_cluster.trustee_user_id = 'trustee_user_id'
mock_keystone = mock.MagicMock()
self.osc.keystone.return_value = mock_keystone
context = mock.MagicMock()
trust_manager.delete_trustee_and_trust(self.osc, context,
mock_bay)
mock_cluster)
mock_keystone.delete_trust.assert_called_once_with(
context, mock_bay
context, mock_cluster
)
mock_keystone.delete_trustee.assert_called_once_with(
mock_bay.trustee_user_id,
mock_cluster.trustee_user_id,
)
def test_delete_trustee_and_trust_without_trust_id(self):
mock_bay = mock.MagicMock()
mock_bay.trust_id = None
mock_bay.trustee_user_id = 'trustee_user_id'
mock_cluster = mock.MagicMock()
mock_cluster.trust_id = None
mock_cluster.trustee_user_id = 'trustee_user_id'
mock_keystone = mock.MagicMock()
self.osc.keystone.return_value = mock_keystone
context = mock.MagicMock()
trust_manager.delete_trustee_and_trust(self.osc, context,
mock_bay)
mock_cluster)
self.assertEqual(0, mock_keystone.delete_trust.call_count)
mock_keystone.delete_trustee.assert_called_once_with(
mock_bay.trustee_user_id,
mock_cluster.trustee_user_id,
)
def test_delete_trustee_and_trust_without_trustee_user_id(self):
mock_bay = mock.MagicMock()
mock_bay.trust_id = 'trust_id'
mock_bay.trustee_user_id = None
mock_cluster = mock.MagicMock()
mock_cluster.trust_id = 'trust_id'
mock_cluster.trustee_user_id = None
mock_keystone = mock.MagicMock()
self.osc.keystone.return_value = mock_keystone
context = mock.MagicMock()
trust_manager.delete_trustee_and_trust(self.osc, context, mock_bay)
trust_manager.delete_trustee_and_trust(self.osc, context, mock_cluster)
mock_keystone.delete_trust.assert_called_once_with(
context, mock_bay
context, mock_cluster
)
self.assertEqual(0, mock_keystone.delete_trustee.call_count)

View File

@ -24,9 +24,9 @@ from oslo_service import loopingcall
from pycadf import cadftaxonomy as taxonomy
from magnum.common import exception
from magnum.conductor.handlers import bay_conductor
from magnum.conductor.handlers import cluster_conductor
from magnum import objects
from magnum.objects.fields import BayStatus as bay_status
from magnum.objects.fields import ClusterStatus as cluster_status
from magnum.tests import base
from magnum.tests import fake_notifier
from magnum.tests.unit.db import base as db_base
@ -37,92 +37,95 @@ class TestHandler(db_base.DbTestCase):
def setUp(self):
super(TestHandler, self).setUp()
self.handler = bay_conductor.Handler()
self.handler = cluster_conductor.Handler()
cluster_template_dict = utils.get_test_cluster_template()
self.cluster_template = objects.ClusterTemplate(
self.context, **cluster_template_dict)
self.cluster_template.create()
bay_dict = utils.get_test_bay(node_count=1)
self.bay = objects.Bay(self.context, **bay_dict)
self.bay.create()
cluster_dict = utils.get_test_cluster(node_count=1)
self.cluster = objects.Cluster(self.context, **cluster_dict)
self.cluster.create()
@patch('magnum.conductor.scale_manager.ScaleManager')
@patch('magnum.conductor.handlers.bay_conductor.Handler._poll_and_check')
@patch('magnum.conductor.handlers.bay_conductor._update_stack')
@patch(
'magnum.conductor.handlers.cluster_conductor.Handler._poll_and_check')
@patch('magnum.conductor.handlers.cluster_conductor._update_stack')
@patch('magnum.common.clients.OpenStackClients')
def test_update_node_count_success(
self, mock_openstack_client_class,
mock_update_stack, mock_poll_and_check,
mock_scale_manager):
def side_effect(*args, **kwargs):
self.bay.node_count = 2
self.bay.save()
self.cluster.node_count = 2
self.cluster.save()
mock_poll_and_check.side_effect = side_effect
mock_heat_stack = mock.MagicMock()
mock_heat_stack.stack_status = bay_status.CREATE_COMPLETE
mock_heat_stack.stack_status = cluster_status.CREATE_COMPLETE
mock_heat_client = mock.MagicMock()
mock_heat_client.stacks.get.return_value = mock_heat_stack
mock_openstack_client = mock_openstack_client_class.return_value
mock_openstack_client.heat.return_value = mock_heat_client
self.bay.node_count = 2
self.handler.bay_update(self.context, self.bay)
self.cluster.node_count = 2
self.handler.cluster_update(self.context, self.cluster)
notifications = fake_notifier.NOTIFICATIONS
self.assertEqual(1, len(notifications))
self.assertEqual(
'magnum.bay.update', notifications[0].event_type)
'magnum.cluster.update', notifications[0].event_type)
self.assertEqual(
taxonomy.OUTCOME_PENDING, notifications[0].payload['outcome'])
mock_update_stack.assert_called_once_with(
self.context, mock_openstack_client, self.bay,
self.context, mock_openstack_client, self.cluster,
mock_scale_manager.return_value, False)
bay = objects.Bay.get(self.context, self.bay.uuid)
self.assertEqual(2, bay.node_count)
cluster = objects.Cluster.get(self.context, self.cluster.uuid)
self.assertEqual(2, cluster.node_count)
@patch('magnum.conductor.handlers.bay_conductor.Handler._poll_and_check')
@patch('magnum.conductor.handlers.bay_conductor._update_stack')
@patch(
'magnum.conductor.handlers.cluster_conductor.Handler._poll_and_check')
@patch('magnum.conductor.handlers.cluster_conductor._update_stack')
@patch('magnum.common.clients.OpenStackClients')
def test_update_node_count_failure(
self, mock_openstack_client_class,
mock_update_stack, mock_poll_and_check):
def side_effect(*args, **kwargs):
self.bay.node_count = 2
self.bay.save()
self.cluster.node_count = 2
self.cluster.save()
mock_poll_and_check.side_effect = side_effect
mock_heat_stack = mock.MagicMock()
mock_heat_stack.stack_status = bay_status.CREATE_FAILED
mock_heat_stack.stack_status = cluster_status.CREATE_FAILED
mock_heat_client = mock.MagicMock()
mock_heat_client.stacks.get.return_value = mock_heat_stack
mock_openstack_client = mock_openstack_client_class.return_value
mock_openstack_client.heat.return_value = mock_heat_client
self.bay.node_count = 2
self.assertRaises(exception.NotSupported, self.handler.bay_update,
self.context, self.bay)
self.cluster.node_count = 2
self.assertRaises(exception.NotSupported, self.handler.cluster_update,
self.context, self.cluster)
notifications = fake_notifier.NOTIFICATIONS
self.assertEqual(1, len(notifications))
self.assertEqual(
'magnum.bay.update', notifications[0].event_type)
'magnum.cluster.update', notifications[0].event_type)
self.assertEqual(
taxonomy.OUTCOME_FAILURE, notifications[0].payload['outcome'])
bay = objects.Bay.get(self.context, self.bay.uuid)
self.assertEqual(1, bay.node_count)
cluster = objects.Cluster.get(self.context, self.cluster.uuid)
self.assertEqual(1, cluster.node_count)
@patch('magnum.conductor.scale_manager.ScaleManager')
@patch('magnum.conductor.handlers.bay_conductor.Handler._poll_and_check')
@patch('magnum.conductor.handlers.bay_conductor._update_stack')
@patch(
'magnum.conductor.handlers.cluster_conductor.Handler._poll_and_check')
@patch('magnum.conductor.handlers.cluster_conductor._update_stack')
@patch('magnum.common.clients.OpenStackClients')
def _test_update_bay_status_complete(
def _test_update_cluster_status_complete(
self, expect_status, mock_openstack_client_class,
mock_update_stack, mock_poll_and_check,
mock_scale_manager):
def side_effect(*args, **kwargs):
self.bay.node_count = 2
self.bay.save()
self.cluster.node_count = 2
self.cluster.save()
mock_poll_and_check.side_effect = side_effect
mock_heat_stack = mock.MagicMock()
mock_heat_stack.stack_status = expect_status
@ -131,47 +134,54 @@ class TestHandler(db_base.DbTestCase):
mock_openstack_client = mock_openstack_client_class.return_value
mock_openstack_client.heat.return_value = mock_heat_client
self.bay.node_count = 2
self.handler.bay_update(self.context, self.bay)
self.cluster.node_count = 2
self.handler.cluster_update(self.context, self.cluster)
notifications = fake_notifier.NOTIFICATIONS
self.assertEqual(1, len(notifications))
self.assertEqual(
'magnum.bay.update', notifications[0].event_type)
'magnum.cluster.update', notifications[0].event_type)
self.assertEqual(
taxonomy.OUTCOME_PENDING, notifications[0].payload['outcome'])
mock_update_stack.assert_called_once_with(
self.context, mock_openstack_client, self.bay,
self.context, mock_openstack_client, self.cluster,
mock_scale_manager.return_value, False)
bay = objects.Bay.get(self.context, self.bay.uuid)
self.assertEqual(2, bay.node_count)
cluster = objects.Cluster.get(self.context, self.cluster.uuid)
self.assertEqual(2, cluster.node_count)
def test_update_bay_status_update_compelete(self):
self._test_update_bay_status_complete(bay_status.UPDATE_COMPLETE)
def test_update_cluster_status_update_compelete(self):
self._test_update_cluster_status_complete(
cluster_status.UPDATE_COMPLETE)
def test_update_bay_status_resume_compelete(self):
self._test_update_bay_status_complete(bay_status.RESUME_COMPLETE)
def test_update_cluster_status_resume_compelete(self):
self._test_update_cluster_status_complete(
cluster_status.RESUME_COMPLETE)
def test_update_bay_status_restore_compelete(self):
self._test_update_bay_status_complete(bay_status.RESTORE_COMPLETE)
def test_update_cluster_status_restore_compelete(self):
self._test_update_cluster_status_complete(
cluster_status.RESTORE_COMPLETE)
def test_update_bay_status_rollback_compelete(self):
self._test_update_bay_status_complete(bay_status.ROLLBACK_COMPLETE)
def test_update_cluster_status_rollback_compelete(self):
self._test_update_cluster_status_complete(
cluster_status.ROLLBACK_COMPLETE)
def test_update_bay_status_snapshot_compelete(self):
self._test_update_bay_status_complete(bay_status.SNAPSHOT_COMPLETE)
def test_update_cluster_status_snapshot_compelete(self):
self._test_update_cluster_status_complete(
cluster_status.SNAPSHOT_COMPLETE)
def test_update_bay_status_check_compelete(self):
self._test_update_bay_status_complete(bay_status.CHECK_COMPLETE)
def test_update_cluster_status_check_compelete(self):
self._test_update_cluster_status_complete(
cluster_status.CHECK_COMPLETE)
def test_update_bay_status_adopt_compelete(self):
self._test_update_bay_status_complete(bay_status.ADOPT_COMPLETE)
def test_update_cluster_status_adopt_compelete(self):
self._test_update_cluster_status_complete(
cluster_status.ADOPT_COMPLETE)
@patch('magnum.conductor.handlers.bay_conductor.HeatPoller')
@patch('magnum.conductor.handlers.bay_conductor.trust_manager')
@patch('magnum.conductor.handlers.bay_conductor.cert_manager')
@patch('magnum.conductor.handlers.bay_conductor._create_stack')
@patch('magnum.conductor.handlers.cluster_conductor.HeatPoller')
@patch('magnum.conductor.handlers.cluster_conductor.trust_manager')
@patch('magnum.conductor.handlers.cluster_conductor.cert_manager')
@patch('magnum.conductor.handlers.cluster_conductor._create_stack')
@patch('magnum.common.clients.OpenStackClients')
def test_create(self, mock_openstack_client_class,
mock_create_stack, mock_cm, mock_trust_manager,
@ -183,39 +193,40 @@ class TestHandler(db_base.DbTestCase):
osc = mock.sentinel.osc
mock_openstack_client_class.return_value = osc
def create_stack_side_effect(context, osc, bay, timeout):
def create_stack_side_effect(context, osc, cluster, timeout):
return {'stack': {'id': 'stack-id'}}
mock_create_stack.side_effect = create_stack_side_effect
# FixMe(eliqiao): bay_create will call bay.create() again, this so bad
# because we have already called it in setUp since other test case will
# share the codes in setUp()
# But in self.handler.bay_create, we update bay.uuid and bay.stack_id
# so bay.create will create a new recored with baymodel_id None,
# this is bad because we load BayModel object in Bay object by
# baymodel_id. Here update self.bay.baymodel_id so bay.obj_get_changes
# will get notice that baymodel_id is updated and will update it
# FixMe(eliqiao): cluster_create will call cluster.create()
# again, this so bad because we have already called it in setUp
# since other test case will share the codes in setUp()
# But in self.handler.cluster_create, we update cluster.uuid and
# cluster.stack_id so cluster.create will create a new recored with
# clustermodel_id None, this is bad because we load clusterModel
# object in cluster object by clustermodel_id. Here update
# self.cluster.clustermodel_id so cluster.obj_get_changes will get
# notice that clustermodel_id is updated and will update it
# in db.
self.bay.baymodel_id = self.cluster_template.uuid
bay = self.handler.bay_create(self.context,
self.bay, timeout)
self.cluster.cluster_template_id = self.cluster_template.uuid
cluster = self.handler.cluster_create(self.context,
self.cluster, timeout)
notifications = fake_notifier.NOTIFICATIONS
self.assertEqual(1, len(notifications))
self.assertEqual(
'magnum.bay.create', notifications[0].event_type)
'magnum.cluster.create', notifications[0].event_type)
self.assertEqual(
taxonomy.OUTCOME_PENDING, notifications[0].payload['outcome'])
mock_create_stack.assert_called_once_with(self.context,
mock.sentinel.osc,
self.bay, timeout)
self.cluster, timeout)
mock_cm.generate_certificates_to_cluster.assert_called_once_with(
self.bay, context=self.context)
self.assertEqual(bay_status.CREATE_IN_PROGRESS, bay.status)
self.cluster, context=self.context)
self.assertEqual(cluster_status.CREATE_IN_PROGRESS, cluster.status)
mock_trust_manager.create_trustee_and_trust.assert_called_once_with(
osc, self.bay)
osc, self.cluster)
def _test_create_failed(self,
mock_openstack_client_class,
@ -230,29 +241,29 @@ class TestHandler(db_base.DbTestCase):
self.assertRaises(
expected_exception,
self.handler.bay_create,
self.handler.cluster_create,
self.context,
self.bay, timeout
self.cluster, timeout
)
gctb = mock_cert_manager.generate_certificates_to_cluster
if is_create_cert_called:
gctb.assert_called_once_with(self.bay, context=self.context)
gctb.assert_called_once_with(self.cluster, context=self.context)
else:
gctb.assert_not_called()
ctat = mock_trust_manager.create_trustee_and_trust
if is_create_trust_called:
ctat.assert_called_once_with(osc, self.bay)
ctat.assert_called_once_with(osc, self.cluster)
else:
ctat.assert_not_called()
mock_cert_manager.delete_certificates_from_cluster(self.bay)
mock_cert_manager.delete_certificates_from_cluster(self.cluster)
mock_trust_manager.delete_trustee_and_trust.assert_called_once_with(
osc, self.context, self.bay)
osc, self.context, self.cluster)
@patch('magnum.conductor.handlers.bay_conductor.trust_manager')
@patch('magnum.conductor.handlers.bay_conductor.cert_manager')
@patch('magnum.conductor.handlers.bay_conductor._create_stack')
@patch('magnum.conductor.handlers.cluster_conductor.trust_manager')
@patch('magnum.conductor.handlers.cluster_conductor.cert_manager')
@patch('magnum.conductor.handlers.cluster_conductor._create_stack')
@patch('magnum.common.clients.OpenStackClients')
def test_create_handles_bad_request(self, mock_openstack_client_class,
mock_create_stack,
@ -270,16 +281,16 @@ class TestHandler(db_base.DbTestCase):
notifications = fake_notifier.NOTIFICATIONS
self.assertEqual(2, len(notifications))
self.assertEqual(
'magnum.bay.create', notifications[0].event_type)
'magnum.cluster.create', notifications[0].event_type)
self.assertEqual(
taxonomy.OUTCOME_PENDING, notifications[0].payload['outcome'])
self.assertEqual(
'magnum.bay.create', notifications[1].event_type)
'magnum.cluster.create', notifications[1].event_type)
self.assertEqual(
taxonomy.OUTCOME_FAILURE, notifications[1].payload['outcome'])
@patch('magnum.conductor.handlers.bay_conductor.trust_manager')
@patch('magnum.conductor.handlers.bay_conductor.cert_manager')
@patch('magnum.conductor.handlers.cluster_conductor.trust_manager')
@patch('magnum.conductor.handlers.cluster_conductor.cert_manager')
@patch('magnum.common.clients.OpenStackClients')
def test_create_with_cert_failed(self, mock_openstack_client_class,
mock_cert_manager,
@ -297,39 +308,39 @@ class TestHandler(db_base.DbTestCase):
notifications = fake_notifier.NOTIFICATIONS
self.assertEqual(1, len(notifications))
self.assertEqual(
'magnum.bay.create', notifications[0].event_type)
'magnum.cluster.create', notifications[0].event_type)
self.assertEqual(
taxonomy.OUTCOME_FAILURE, notifications[0].payload['outcome'])
@patch('magnum.conductor.handlers.bay_conductor.trust_manager')
@patch('magnum.conductor.handlers.bay_conductor.cert_manager')
@patch('magnum.conductor.handlers.bay_conductor._create_stack')
@patch('magnum.conductor.handlers.cluster_conductor.trust_manager')
@patch('magnum.conductor.handlers.cluster_conductor.cert_manager')
@patch('magnum.conductor.handlers.cluster_conductor._create_stack')
@patch('magnum.common.clients.OpenStackClients')
def test_create_with_trust_failed(self, mock_openstack_client_class,
mock_create_stack,
mock_cert_manager,
mock_trust_manager):
e = exception.TrusteeOrTrustToBayFailed(bay_uuid='uuid')
e = exception.TrusteeOrTrustToClusterFailed(cluster_uuid='uuid')
mock_trust_manager.create_trustee_and_trust.side_effect = e
self._test_create_failed(
mock_openstack_client_class,
mock_cert_manager,
mock_trust_manager,
exception.TrusteeOrTrustToBayFailed,
exception.TrusteeOrTrustToClusterFailed,
False
)
notifications = fake_notifier.NOTIFICATIONS
self.assertEqual(1, len(notifications))
self.assertEqual(
'magnum.bay.create', notifications[0].event_type)
'magnum.cluster.create', notifications[0].event_type)
self.assertEqual(
taxonomy.OUTCOME_FAILURE, notifications[0].payload['outcome'])
@patch('magnum.conductor.handlers.bay_conductor.trust_manager')
@patch('magnum.conductor.handlers.bay_conductor.cert_manager')
@patch('magnum.conductor.handlers.bay_conductor._create_stack')
@patch('magnum.conductor.handlers.cluster_conductor.trust_manager')
@patch('magnum.conductor.handlers.cluster_conductor.cert_manager')
@patch('magnum.conductor.handlers.cluster_conductor._create_stack')
@patch('magnum.common.clients.OpenStackClients')
def test_create_with_invalid_unicode_name(self,
mock_openstack_client_class,
@ -351,23 +362,23 @@ class TestHandler(db_base.DbTestCase):
notifications = fake_notifier.NOTIFICATIONS
self.assertEqual(2, len(notifications))
self.assertEqual(
'magnum.bay.create', notifications[0].event_type)
'magnum.cluster.create', notifications[0].event_type)
self.assertEqual(
taxonomy.OUTCOME_PENDING, notifications[0].payload['outcome'])
self.assertEqual(
'magnum.bay.create', notifications[1].event_type)
'magnum.cluster.create', notifications[1].event_type)
self.assertEqual(
taxonomy.OUTCOME_FAILURE, notifications[1].payload['outcome'])
@patch('magnum.conductor.handlers.bay_conductor.HeatPoller')
@patch('magnum.conductor.handlers.cluster_conductor.HeatPoller')
@patch('heatclient.common.template_utils'
'.process_multiple_environments_and_files')
@patch('heatclient.common.template_utils.get_template_contents')
@patch('magnum.conductor.handlers.bay_conductor'
@patch('magnum.conductor.handlers.cluster_conductor'
'._extract_template_definition')
@patch('magnum.conductor.handlers.bay_conductor.trust_manager')
@patch('magnum.conductor.handlers.bay_conductor.cert_manager')
@patch('magnum.conductor.handlers.bay_conductor.short_id')
@patch('magnum.conductor.handlers.cluster_conductor.trust_manager')
@patch('magnum.conductor.handlers.cluster_conductor.cert_manager')
@patch('magnum.conductor.handlers.cluster_conductor.short_id')
@patch('magnum.common.clients.OpenStackClients')
def test_create_with_environment(self,
mock_openstack_client_class,
@ -379,8 +390,8 @@ class TestHandler(db_base.DbTestCase):
mock_process_mult,
mock_heat_poller_class):
timeout = 15
self.bay.baymodel_id = self.cluster_template.uuid
bay_name = self.bay.name
self.cluster.cluster_template_id = self.cluster_template.uuid
cluster_name = self.cluster.name
mock_short_id.generate_id.return_value = 'short_id'
mock_poller = mock.MagicMock()
mock_poller.poll_and_check.return_value = loopingcall.LoopingCallDone()
@ -412,9 +423,10 @@ class TestHandler(db_base.DbTestCase):
osc.heat.return_value = mock_hc
mock_openstack_client_class.return_value = osc
self.handler.bay_create(self.context, self.bay, timeout)
self.handler.cluster_create(self.context, self.cluster, timeout)
mock_extract_tmpl_def.assert_called_once_with(self.context, self.bay)
mock_extract_tmpl_def.assert_called_once_with(self.context,
self.cluster)
mock_get_template_contents.assert_called_once_with(
'the/template/path.yaml')
mock_process_mult.assert_called_once_with(
@ -432,54 +444,54 @@ class TestHandler(db_base.DbTestCase):
'content of file:///the/template/env_file_2'
},
parameters={'heat_param_1': 'foo', 'heat_param_2': 'bar'},
stack_name=('%s-short_id' % bay_name),
stack_name=('%s-short_id' % cluster_name),
template='some template yaml',
timeout_mins=timeout)
@patch('magnum.conductor.handlers.bay_conductor.cert_manager')
@patch('magnum.conductor.handlers.cluster_conductor.cert_manager')
@patch('magnum.common.clients.OpenStackClients')
def test_bay_delete(self, mock_openstack_client_class, cert_manager):
def test_cluster_delete(self, mock_openstack_client_class, cert_manager):
osc = mock.MagicMock()
mock_openstack_client_class.return_value = osc
osc.heat.side_effect = exc.HTTPNotFound
self.handler.bay_delete(self.context, self.bay.uuid)
self.handler.cluster_delete(self.context, self.cluster.uuid)
notifications = fake_notifier.NOTIFICATIONS
self.assertEqual(2, len(notifications))
self.assertEqual(
'magnum.bay.delete', notifications[0].event_type)
'magnum.cluster.delete', notifications[0].event_type)
self.assertEqual(
taxonomy.OUTCOME_PENDING, notifications[0].payload['outcome'])
self.assertEqual(
'magnum.bay.delete', notifications[1].event_type)
'magnum.cluster.delete', notifications[1].event_type)
self.assertEqual(
taxonomy.OUTCOME_SUCCESS, notifications[1].payload['outcome'])
self.assertEqual(
1, cert_manager.delete_certificates_from_cluster.call_count)
# The cluster has been destroyed
self.assertRaises(exception.ClusterNotFound,
objects.Bay.get, self.context, self.bay.uuid)
objects.Cluster.get, self.context, self.cluster.uuid)
@patch('magnum.conductor.handlers.bay_conductor.cert_manager')
@patch('magnum.conductor.handlers.cluster_conductor.cert_manager')
@patch('magnum.common.clients.OpenStackClients')
def test_bay_delete_conflict(self, mock_openstack_client_class,
cert_manager):
def test_cluster_delete_conflict(self, mock_openstack_client_class,
cert_manager):
osc = mock.MagicMock()
mock_openstack_client_class.return_value = osc
osc.heat.side_effect = exc.HTTPConflict
self.assertRaises(exception.OperationInProgress,
self.handler.bay_delete,
self.handler.cluster_delete,
self.context,
self.bay.uuid)
self.cluster.uuid)
notifications = fake_notifier.NOTIFICATIONS
self.assertEqual(2, len(notifications))
self.assertEqual(
'magnum.bay.delete', notifications[0].event_type)
'magnum.cluster.delete', notifications[0].event_type)
self.assertEqual(
taxonomy.OUTCOME_PENDING, notifications[0].payload['outcome'])
self.assertEqual(
'magnum.bay.delete', notifications[1].event_type)
'magnum.cluster.delete', notifications[1].event_type)
self.assertEqual(
taxonomy.OUTCOME_FAILURE, notifications[1].payload['outcome'])
self.assertEqual(
@ -495,7 +507,7 @@ class TestHeatPoller(base.TestCase):
mock_retrieve_cluster_template):
cfg.CONF.cluster_heat.max_attempts = 10
bay = mock.MagicMock()
cluster = mock.MagicMock()
cluster_template_dict = utils.get_test_cluster_template(
coe='kubernetes')
mock_heat_stack = mock.MagicMock()
@ -505,183 +517,183 @@ class TestHeatPoller(base.TestCase):
cluster_template = objects.ClusterTemplate(self.context,
**cluster_template_dict)
mock_retrieve_cluster_template.return_value = cluster_template
poller = bay_conductor.HeatPoller(mock_openstack_client, bay)
poller = cluster_conductor.HeatPoller(mock_openstack_client, cluster)
poller.get_version_info = mock.MagicMock()
return (mock_heat_stack, bay, poller)
return (mock_heat_stack, cluster, poller)
def test_poll_and_check_send_notification(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.CREATE_COMPLETE
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = cluster_status.CREATE_COMPLETE
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
mock_heat_stack.stack_status = bay_status.CREATE_FAILED
mock_heat_stack.stack_status = cluster_status.CREATE_FAILED
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
mock_heat_stack.stack_status = bay_status.DELETE_COMPLETE
mock_heat_stack.stack_status = cluster_status.DELETE_COMPLETE
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
mock_heat_stack.stack_status = bay_status.DELETE_FAILED
mock_heat_stack.stack_status = cluster_status.DELETE_FAILED
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
mock_heat_stack.stack_status = bay_status.UPDATE_COMPLETE
mock_heat_stack.stack_status = cluster_status.UPDATE_COMPLETE
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
mock_heat_stack.stack_status = bay_status.UPDATE_FAILED
mock_heat_stack.stack_status = cluster_status.UPDATE_FAILED
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
self.assertEqual(6, poller.attempts)
notifications = fake_notifier.NOTIFICATIONS
self.assertEqual(6, len(notifications))
self.assertEqual(
'magnum.bay.create', notifications[0].event_type)
'magnum.cluster.create', notifications[0].event_type)
self.assertEqual(
taxonomy.OUTCOME_SUCCESS, notifications[0].payload['outcome'])
self.assertEqual(
'magnum.bay.create', notifications[1].event_type)
'magnum.cluster.create', notifications[1].event_type)
self.assertEqual(
taxonomy.OUTCOME_FAILURE, notifications[1].payload['outcome'])
self.assertEqual(
'magnum.bay.delete', notifications[2].event_type)
'magnum.cluster.delete', notifications[2].event_type)
self.assertEqual(
taxonomy.OUTCOME_SUCCESS, notifications[2].payload['outcome'])
self.assertEqual(
'magnum.bay.delete', notifications[3].event_type)
'magnum.cluster.delete', notifications[3].event_type)
self.assertEqual(
taxonomy.OUTCOME_FAILURE, notifications[3].payload['outcome'])
self.assertEqual(
'magnum.bay.update', notifications[4].event_type)
'magnum.cluster.update', notifications[4].event_type)
self.assertEqual(
taxonomy.OUTCOME_SUCCESS, notifications[4].payload['outcome'])
self.assertEqual(
'magnum.bay.update', notifications[5].event_type)
'magnum.cluster.update', notifications[5].event_type)
self.assertEqual(
taxonomy.OUTCOME_FAILURE, notifications[5].payload['outcome'])
def test_poll_no_save(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
bay.status = bay_status.CREATE_IN_PROGRESS
mock_heat_stack.stack_status = bay_status.CREATE_IN_PROGRESS
cluster.status = cluster_status.CREATE_IN_PROGRESS
mock_heat_stack.stack_status = cluster_status.CREATE_IN_PROGRESS
poller.poll_and_check()
self.assertEqual(0, bay.save.call_count)
self.assertEqual(0, cluster.save.call_count)
self.assertEqual(1, poller.attempts)
def test_poll_save(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
bay.status = bay_status.CREATE_IN_PROGRESS
mock_heat_stack.stack_status = bay_status.CREATE_FAILED
cluster.status = cluster_status.CREATE_IN_PROGRESS
mock_heat_stack.stack_status = cluster_status.CREATE_FAILED
mock_heat_stack.stack_status_reason = 'Create failed'
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
self.assertEqual(2, bay.save.call_count)
self.assertEqual(bay_status.CREATE_FAILED, bay.status)
self.assertEqual('Create failed', bay.status_reason)
self.assertEqual(2, cluster.save.call_count)
self.assertEqual(cluster_status.CREATE_FAILED, cluster.status)
self.assertEqual('Create failed', cluster.status_reason)
self.assertEqual(1, poller.attempts)
def test_poll_done(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.DELETE_COMPLETE
mock_heat_stack.stack_status = cluster_status.DELETE_COMPLETE
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
mock_heat_stack.stack_status = bay_status.CREATE_FAILED
mock_heat_stack.stack_status = cluster_status.CREATE_FAILED
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
self.assertEqual(2, poller.attempts)
def test_poll_done_by_update(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.UPDATE_COMPLETE
mock_heat_stack.stack_status = cluster_status.UPDATE_COMPLETE
mock_heat_stack.parameters = {'number_of_minions': 2}
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
self.assertEqual(1, bay.save.call_count)
self.assertEqual(bay_status.UPDATE_COMPLETE, bay.status)
self.assertEqual(2, bay.node_count)
self.assertEqual(1, cluster.save.call_count)
self.assertEqual(cluster_status.UPDATE_COMPLETE, cluster.status)
self.assertEqual(2, cluster.node_count)
self.assertEqual(1, poller.attempts)
def test_poll_done_by_update_failed(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.UPDATE_FAILED
mock_heat_stack.stack_status = cluster_status.UPDATE_FAILED
mock_heat_stack.parameters = {'number_of_minions': 2}
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
self.assertEqual(2, bay.save.call_count)
self.assertEqual(bay_status.UPDATE_FAILED, bay.status)
self.assertEqual(2, bay.node_count)
self.assertEqual(2, cluster.save.call_count)
self.assertEqual(cluster_status.UPDATE_FAILED, cluster.status)
self.assertEqual(2, cluster.node_count)
self.assertEqual(1, poller.attempts)
def test_poll_done_by_rollback_complete(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.ROLLBACK_COMPLETE
mock_heat_stack.stack_status = cluster_status.ROLLBACK_COMPLETE
mock_heat_stack.parameters = {'number_of_minions': 1}
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
self.assertEqual(2, bay.save.call_count)
self.assertEqual(bay_status.ROLLBACK_COMPLETE, bay.status)
self.assertEqual(1, bay.node_count)
self.assertEqual(2, cluster.save.call_count)
self.assertEqual(cluster_status.ROLLBACK_COMPLETE, cluster.status)
self.assertEqual(1, cluster.node_count)
self.assertEqual(1, poller.attempts)
def test_poll_done_by_rollback_failed(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.ROLLBACK_FAILED
mock_heat_stack.stack_status = cluster_status.ROLLBACK_FAILED
mock_heat_stack.parameters = {'number_of_minions': 1}
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
self.assertEqual(2, bay.save.call_count)
self.assertEqual(bay_status.ROLLBACK_FAILED, bay.status)
self.assertEqual(1, bay.node_count)
self.assertEqual(2, cluster.save.call_count)
self.assertEqual(cluster_status.ROLLBACK_FAILED, cluster.status)
self.assertEqual(1, cluster.node_count)
self.assertEqual(1, poller.attempts)
def test_poll_destroy(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.DELETE_FAILED
mock_heat_stack.stack_status = cluster_status.DELETE_FAILED
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
# Destroy method is not called when stack delete failed
self.assertEqual(0, bay.destroy.call_count)
self.assertEqual(0, cluster.destroy.call_count)
mock_heat_stack.stack_status = bay_status.DELETE_IN_PROGRESS
mock_heat_stack.stack_status = cluster_status.DELETE_IN_PROGRESS
poller.poll_and_check()
self.assertEqual(0, bay.destroy.call_count)
self.assertEqual(bay_status.DELETE_IN_PROGRESS, bay.status)
self.assertEqual(0, cluster.destroy.call_count)
self.assertEqual(cluster_status.DELETE_IN_PROGRESS, cluster.status)
mock_heat_stack.stack_status = bay_status.DELETE_COMPLETE
mock_heat_stack.stack_status = cluster_status.DELETE_COMPLETE
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
# The bay status should still be DELETE_IN_PROGRESS, because
# the destroy() method may be failed. If success, this bay record
# The cluster status should still be DELETE_IN_PROGRESS, because
# the destroy() method may be failed. If success, this cluster record
# will delete directly, change status is meaningless.
self.assertEqual(bay_status.DELETE_IN_PROGRESS, bay.status)
self.assertEqual(1, bay.destroy.call_count)
self.assertEqual(cluster_status.DELETE_IN_PROGRESS, cluster.status)
self.assertEqual(1, cluster.destroy.call_count)
def test_poll_delete_in_progress_timeout_set(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.DELETE_IN_PROGRESS
mock_heat_stack.stack_status = cluster_status.DELETE_IN_PROGRESS
mock_heat_stack.timeout_mins = 60
# timeout only affects stack creation so expecting this
# to process normally
poller.poll_and_check()
def test_poll_delete_in_progress_max_attempts_reached(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.DELETE_IN_PROGRESS
mock_heat_stack.stack_status = cluster_status.DELETE_IN_PROGRESS
poller.attempts = cfg.CONF.cluster_heat.max_attempts
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
def test_poll_create_in_prog_max_att_reached_no_timeout(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.CREATE_IN_PROGRESS
mock_heat_stack.stack_status = cluster_status.CREATE_IN_PROGRESS
poller.attempts = cfg.CONF.cluster_heat.max_attempts
mock_heat_stack.timeout_mins = None
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
def test_poll_create_in_prog_max_att_reached_timeout_set(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.CREATE_IN_PROGRESS
mock_heat_stack.stack_status = cluster_status.CREATE_IN_PROGRESS
poller.attempts = cfg.CONF.cluster_heat.max_attempts
mock_heat_stack.timeout_mins = 60
# since the timeout is set the max attempts gets ignored since
@ -690,83 +702,83 @@ class TestHeatPoller(base.TestCase):
poller.poll_and_check()
def test_poll_create_in_prog_max_att_reached_timed_out(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.CREATE_FAILED
mock_heat_stack.stack_status = cluster_status.CREATE_FAILED
poller.attempts = cfg.CONF.cluster_heat.max_attempts
mock_heat_stack.timeout_mins = 60
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
def test_poll_create_in_prog_max_att_not_reached_no_timeout(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.CREATE_IN_PROGRESS
mock_heat_stack.stack_status = cluster_status.CREATE_IN_PROGRESS
mock_heat_stack.timeout.mins = None
poller.poll_and_check()
def test_poll_create_in_prog_max_att_not_reached_timeout_set(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.CREATE_IN_PROGRESS
mock_heat_stack.stack_status = cluster_status.CREATE_IN_PROGRESS
mock_heat_stack.timeout_mins = 60
poller.poll_and_check()
def test_poll_create_in_prog_max_att_not_reached_timed_out(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.CREATE_FAILED
mock_heat_stack.stack_status = cluster_status.CREATE_FAILED
mock_heat_stack.timeout_mins = 60
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
def test_poll_node_count(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.parameters = {'number_of_minions': 1}
mock_heat_stack.stack_status = bay_status.CREATE_IN_PROGRESS
mock_heat_stack.stack_status = cluster_status.CREATE_IN_PROGRESS
poller.poll_and_check()
self.assertEqual(1, bay.node_count)
self.assertEqual(1, cluster.node_count)
def test_poll_node_count_by_update(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.parameters = {'number_of_minions': 2}
mock_heat_stack.stack_status = bay_status.UPDATE_COMPLETE
mock_heat_stack.stack_status = cluster_status.UPDATE_COMPLETE
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
self.assertEqual(2, bay.node_count)
self.assertEqual(2, cluster.node_count)
@patch('magnum.conductor.handlers.bay_conductor.trust_manager')
@patch('magnum.conductor.handlers.bay_conductor.cert_manager')
@patch('magnum.conductor.handlers.cluster_conductor.trust_manager')
@patch('magnum.conductor.handlers.cluster_conductor.cert_manager')
def test_delete_complete(self, cert_manager, trust_manager):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
poller._delete_complete()
self.assertEqual(1, bay.destroy.call_count)
self.assertEqual(1, cluster.destroy.call_count)
self.assertEqual(
1, cert_manager.delete_certificates_from_cluster.call_count)
self.assertEqual(1,
trust_manager.delete_trustee_and_trust.call_count)
def test_create_or_complete(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.CREATE_COMPLETE
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = cluster_status.CREATE_COMPLETE
mock_heat_stack.stack_status_reason = 'stack complete'
poller._sync_bay_and_template_status(mock_heat_stack)
self.assertEqual('stack complete', bay.status_reason)
self.assertEqual(bay_status.CREATE_COMPLETE, bay.status)
self.assertEqual(1, bay.save.call_count)
poller._sync_cluster_and_template_status(mock_heat_stack)
self.assertEqual('stack complete', cluster.status_reason)
self.assertEqual(cluster_status.CREATE_COMPLETE, cluster.status)
self.assertEqual(1, cluster.save.call_count)
def test_sync_bay_status(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack.stack_status = bay_status.CREATE_IN_PROGRESS
def test_sync_cluster_status(self):
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.stack_status = cluster_status.CREATE_IN_PROGRESS
mock_heat_stack.stack_status_reason = 'stack incomplete'
poller._sync_bay_status(mock_heat_stack)
self.assertEqual('stack incomplete', bay.status_reason)
self.assertEqual(bay_status.CREATE_IN_PROGRESS, bay.status)
poller._sync_cluster_status(mock_heat_stack)
self.assertEqual('stack incomplete', cluster.status_reason)
self.assertEqual(cluster_status.CREATE_IN_PROGRESS, cluster.status)
@patch('magnum.conductor.handlers.bay_conductor.LOG')
def test_bay_failed(self, logger):
mock_heat_stack, bay, poller = self.setup_poll_test()
poller._sync_bay_and_template_status(mock_heat_stack)
poller._bay_failed(mock_heat_stack)
@patch('magnum.conductor.handlers.cluster_conductor.LOG')
def test_cluster_failed(self, logger):
mock_heat_stack, cluster, poller = self.setup_poll_test()
poller._sync_cluster_and_template_status(mock_heat_stack)
poller._cluster_failed(mock_heat_stack)
self.assertEqual(1, logger.error.call_count)

View File

@ -16,14 +16,14 @@ import mock
from mock import patch
from oslo_config import cfg
from magnum.conductor.handlers import bay_conductor
from magnum.conductor.handlers import cluster_conductor
from magnum import objects
from magnum.tests import base
class TestBayConductorWithK8s(base.TestCase):
class TestClusterConductorWithK8s(base.TestCase):
def setUp(self):
super(TestBayConductorWithK8s, self).setUp()
super(TestClusterConductorWithK8s, self).setUp()
self.cluster_template_dict = {
'image_id': 'image_id',
'flavor_id': 'flavor_id',
@ -51,10 +51,10 @@ class TestBayConductorWithK8s(base.TestCase):
'master_lb_enabled': False,
'floating_ip_enabled': False,
}
self.bay_dict = {
self.cluster_dict = {
'uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'baymodel_id': 'xx-xx-xx-xx',
'name': 'bay1',
'cluster_template_id': 'xx-xx-xx-xx',
'name': 'cluster1',
'stack_id': 'xx-xx-xx-xx',
'api_address': '172.17.2.3',
'node_addresses': ['172.17.2.4'],
@ -100,8 +100,8 @@ class TestBayConductorWithK8s(base.TestCase):
missing_attr=None):
if missing_attr in self.cluster_template_dict:
self.cluster_template_dict[missing_attr] = None
elif missing_attr in self.bay_dict:
self.bay_dict[missing_attr] = None
elif missing_attr in self.cluster_dict:
self.cluster_dict[missing_attr] = None
cluster_template = objects.ClusterTemplate(
self.context, **self.cluster_template_dict)
mock_objects_cluster_template_get_by_uuid.return_value = \
@ -111,12 +111,12 @@ class TestBayConductorWithK8s(base.TestCase):
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
cluster = objects.Cluster(self.context, **self.cluster_dict)
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
mapping = {
'dns_nameserver': 'dns_nameserver',
@ -137,7 +137,7 @@ class TestBayConductorWithK8s(base.TestCase):
'http_proxy': 'http_proxy',
'https_proxy': 'https_proxy',
'no_proxy': 'no_proxy',
'bay_uuid': self.bay_dict['uuid'],
'cluster_uuid': self.cluster_dict['uuid'],
'magnum_url': self.mock_osc.magnum_url.return_value,
'tls_disabled': False,
'insecure_registry': '10.0.0.1:5000',
@ -164,7 +164,7 @@ class TestBayConductorWithK8s(base.TestCase):
'no_proxy': 'no_proxy',
'tenant_name': 'fake_tenant',
'username': 'fake_user',
'bay_uuid': self.bay_dict['uuid'],
'cluster_uuid': self.cluster_dict['uuid'],
'magnum_url': self.mock_osc.magnum_url.return_value,
'region_name': self.mock_osc.cinder_region_name.return_value,
'tls_disabled': False,
@ -203,7 +203,7 @@ class TestBayConductorWithK8s(base.TestCase):
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
cluster = objects.Cluster(self.context, **self.cluster_dict)
cfg.CONF.set_override('swift_region',
'RegionOne',
@ -211,12 +211,12 @@ class TestBayConductorWithK8s(base.TestCase):
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
expected = {
'auth_url': 'http://192.168.10.10:5000/v3',
'bay_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'cluster_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'discovery_url': 'https://discovery.etcd.io/test',
'dns_nameserver': 'dns_nameserver',
'docker_storage_driver': 'devicemapper',
@ -275,12 +275,12 @@ class TestBayConductorWithK8s(base.TestCase):
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
cluster = objects.Cluster(self.context, **self.cluster_dict)
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
expected = {
'ssh_key_name': 'keypair_id',
@ -308,7 +308,7 @@ class TestBayConductorWithK8s(base.TestCase):
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3',
'bay_uuid': self.bay_dict['uuid'],
'cluster_uuid': self.cluster_dict['uuid'],
'magnum_url': self.mock_osc.magnum_url.return_value,
'insecure_registry_url': '10.0.0.1:5000',
'kube_version': 'fake-version',
@ -325,19 +325,19 @@ class TestBayConductorWithK8s(base.TestCase):
mock_objects_cluster_template_get_by_uuid,
reqget):
self.cluster_template_dict['cluster_distro'] = 'coreos'
self.bay_dict['discovery_url'] = None
self.cluster_dict['discovery_url'] = None
mock_req = mock.MagicMock(text='http://tokentest/h1/h2/h3')
reqget.return_value = mock_req
cluster_template = objects.ClusterTemplate(
self.context, **self.cluster_template_dict)
mock_objects_cluster_template_get_by_uuid.return_value = \
cluster_template
bay = objects.Bay(self.context, **self.bay_dict)
cluster = objects.Cluster(self.context, **self.cluster_dict)
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
expected = {
'ssh_key_name': 'keypair_id',
@ -365,7 +365,7 @@ class TestBayConductorWithK8s(base.TestCase):
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3',
'bay_uuid': self.bay_dict['uuid'],
'cluster_uuid': self.cluster_dict['uuid'],
'magnum_url': self.mock_osc.magnum_url.return_value,
'insecure_registry_url': '10.0.0.1:5000',
'kube_version': 'fake-version',
@ -484,9 +484,9 @@ class TestBayConductorWithK8s(base.TestCase):
self.context, **self.cluster_template_dict)
mock_objects_cluster_template_get_by_uuid.return_value = \
cluster_template
bay_dict = self.bay_dict
bay_dict['discovery_url'] = None
bay = objects.Bay(self.context, **bay_dict)
cluster_dict = self.cluster_dict
cluster_dict['discovery_url'] = None
cluster = objects.Cluster(self.context, **cluster_dict)
cfg.CONF.set_override('etcd_discovery_service_endpoint_format',
'http://etcd/test?size=%(size)d',
@ -496,8 +496,8 @@ class TestBayConductorWithK8s(base.TestCase):
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
expected = {
'ssh_key_name': 'keypair_id',
@ -521,7 +521,7 @@ class TestBayConductorWithK8s(base.TestCase):
'flannel_backend': 'vxlan',
'tenant_name': 'fake_tenant',
'username': 'fake_user',
'bay_uuid': self.bay_dict['uuid'],
'cluster_uuid': self.cluster_dict['uuid'],
'magnum_url': self.mock_osc.magnum_url.return_value,
'region_name': self.mock_osc.cinder_region_name.return_value,
'tls_disabled': False,
@ -544,7 +544,7 @@ class TestBayConductorWithK8s(base.TestCase):
@patch('magnum.common.short_id.generate_id')
@patch('heatclient.common.template_utils.get_template_contents')
@patch('magnum.conductor.handlers.bay_conductor'
@patch('magnum.conductor.handlers.cluster_conductor'
'._extract_template_definition')
def test_create_stack(self,
mock_extract_template_definition,
@ -554,7 +554,7 @@ class TestBayConductorWithK8s(base.TestCase):
mock_generate_id.return_value = 'xx-xx-xx-xx'
expected_stack_name = 'expected_stack_name-xx-xx-xx-xx'
expected_template_contents = 'template_contents'
dummy_bay_name = 'expected_stack_name'
dummy_cluster_name = 'expected_stack_name'
expected_timeout = 15
mock_tpl_files = {}
@ -565,11 +565,11 @@ class TestBayConductorWithK8s(base.TestCase):
mock_heat_client = mock.MagicMock()
mock_osc = mock.MagicMock()
mock_osc.heat.return_value = mock_heat_client
mock_bay = mock.MagicMock()
mock_bay.name = dummy_bay_name
mock_cluster = mock.MagicMock()
mock_cluster.name = dummy_cluster_name
bay_conductor._create_stack(self.context, mock_osc,
mock_bay, expected_timeout)
cluster_conductor._create_stack(self.context, mock_osc,
mock_cluster, expected_timeout)
expected_args = {
'stack_name': expected_stack_name,
@ -583,7 +583,7 @@ class TestBayConductorWithK8s(base.TestCase):
@patch('magnum.common.short_id.generate_id')
@patch('heatclient.common.template_utils.get_template_contents')
@patch('magnum.conductor.handlers.bay_conductor'
@patch('magnum.conductor.handlers.cluster_conductor'
'._extract_template_definition')
def test_create_stack_no_timeout_specified(
self,
@ -594,7 +594,7 @@ class TestBayConductorWithK8s(base.TestCase):
mock_generate_id.return_value = 'xx-xx-xx-xx'
expected_stack_name = 'expected_stack_name-xx-xx-xx-xx'
expected_template_contents = 'template_contents'
dummy_bay_name = 'expected_stack_name'
dummy_cluster_name = 'expected_stack_name'
expected_timeout = cfg.CONF.cluster_heat.create_timeout
mock_tpl_files = {}
@ -605,11 +605,11 @@ class TestBayConductorWithK8s(base.TestCase):
mock_heat_client = mock.MagicMock()
mock_osc = mock.MagicMock()
mock_osc.heat.return_value = mock_heat_client
mock_bay = mock.MagicMock()
mock_bay.name = dummy_bay_name
mock_cluster = mock.MagicMock()
mock_cluster.name = dummy_cluster_name
bay_conductor._create_stack(self.context, mock_osc,
mock_bay, None)
cluster_conductor._create_stack(self.context, mock_osc,
mock_cluster, None)
expected_args = {
'stack_name': expected_stack_name,
@ -623,7 +623,7 @@ class TestBayConductorWithK8s(base.TestCase):
@patch('magnum.common.short_id.generate_id')
@patch('heatclient.common.template_utils.get_template_contents')
@patch('magnum.conductor.handlers.bay_conductor'
@patch('magnum.conductor.handlers.cluster_conductor'
'._extract_template_definition')
def test_create_stack_timeout_is_zero(
self,
@ -634,8 +634,8 @@ class TestBayConductorWithK8s(base.TestCase):
mock_generate_id.return_value = 'xx-xx-xx-xx'
expected_stack_name = 'expected_stack_name-xx-xx-xx-xx'
expected_template_contents = 'template_contents'
dummy_bay_name = 'expected_stack_name'
bay_timeout = 0
dummy_cluster_name = 'expected_stack_name'
cluster_timeout = 0
expected_timeout = cfg.CONF.cluster_heat.create_timeout
mock_tpl_files = {}
@ -646,11 +646,11 @@ class TestBayConductorWithK8s(base.TestCase):
mock_heat_client = mock.MagicMock()
mock_osc = mock.MagicMock()
mock_osc.heat.return_value = mock_heat_client
mock_bay = mock.MagicMock()
mock_bay.name = dummy_bay_name
mock_cluster = mock.MagicMock()
mock_cluster.name = dummy_cluster_name
bay_conductor._create_stack(self.context, mock_osc,
mock_bay, bay_timeout)
cluster_conductor._create_stack(self.context, mock_osc,
mock_cluster, cluster_timeout)
expected_args = {
'stack_name': expected_stack_name,
@ -663,7 +663,7 @@ class TestBayConductorWithK8s(base.TestCase):
mock_heat_client.stacks.create.assert_called_once_with(**expected_args)
@patch('heatclient.common.template_utils.get_template_contents')
@patch('magnum.conductor.handlers.bay_conductor'
@patch('magnum.conductor.handlers.cluster_conductor'
'._extract_template_definition')
def test_update_stack(self,
mock_extract_template_definition,
@ -680,10 +680,10 @@ class TestBayConductorWithK8s(base.TestCase):
mock_heat_client = mock.MagicMock()
mock_osc = mock.MagicMock()
mock_osc.heat.return_value = mock_heat_client
mock_bay = mock.MagicMock()
mock_bay.stack_id = mock_stack_id
mock_cluster = mock.MagicMock()
mock_cluster.stack_id = mock_stack_id
bay_conductor._update_stack({}, mock_osc, mock_bay)
cluster_conductor._update_stack({}, mock_osc, mock_cluster)
expected_args = {
'parameters': {},

View File

@ -16,15 +16,15 @@ import mock
from mock import patch
from oslo_service import loopingcall
from magnum.conductor.handlers import bay_conductor
from magnum.conductor.handlers import cluster_conductor
from magnum import objects
from magnum.objects.fields import BayStatus as bay_status
from magnum.objects.fields import ClusterStatus as cluster_status
from magnum.tests import base
class TestBayConductorWithMesos(base.TestCase):
class TestClusterConductorWithMesos(base.TestCase):
def setUp(self):
super(TestBayConductorWithMesos, self).setUp()
super(TestClusterConductorWithMesos, self).setUp()
self.cluster_template_dict = {
'image_id': 'image_id',
'flavor_id': 'flavor_id',
@ -48,11 +48,11 @@ class TestBayConductorWithMesos(base.TestCase):
},
'master_lb_enabled': False,
}
self.bay_dict = {
self.cluster_dict = {
'id': 1,
'uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'baymodel_id': 'xx-xx-xx-xx',
'name': 'bay1',
'cluster_template_id': 'xx-xx-xx-xx',
'name': 'cluster1',
'stack_id': 'xx-xx-xx-xx',
'api_address': '172.17.2.3',
'node_addresses': ['172.17.2.4'],
@ -85,12 +85,12 @@ class TestBayConductorWithMesos(base.TestCase):
self.context, **self.cluster_template_dict)
mock_objects_cluster_template_get_by_uuid.return_value = \
cluster_template
bay = objects.Bay(self.context, **self.bay_dict)
cluster = objects.Cluster(self.context, **self.cluster_dict)
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
expected = {
'ssh_key_name': 'keypair_id',
@ -104,7 +104,7 @@ class TestBayConductorWithMesos(base.TestCase):
'http_proxy': 'http_proxy',
'https_proxy': 'https_proxy',
'no_proxy': 'no_proxy',
'cluster_name': 'bay1',
'cluster_name': 'cluster1',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
@ -141,19 +141,19 @@ class TestBayConductorWithMesos(base.TestCase):
self.context, **self.cluster_template_dict)
mock_objects_cluster_template_get_by_uuid.return_value = \
cluster_template
bay = objects.Bay(self.context, **self.bay_dict)
cluster = objects.Cluster(self.context, **self.cluster_dict)
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
expected = {
'ssh_key_name': 'keypair_id',
'external_network': 'external_network_id',
'number_of_slaves': 1,
'number_of_masters': 1,
'cluster_name': 'bay1',
'cluster_name': 'cluster1',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
@ -184,12 +184,12 @@ class TestBayConductorWithMesos(base.TestCase):
self.context, **self.cluster_template_dict)
mock_objects_cluster_template_get_by_uuid.return_value = \
cluster_template
bay = objects.Bay(self.context, **self.bay_dict)
cluster = objects.Cluster(self.context, **self.cluster_dict)
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
expected = {
'ssh_key_name': 'keypair_id',
@ -203,7 +203,7 @@ class TestBayConductorWithMesos(base.TestCase):
'http_proxy': 'http_proxy',
'https_proxy': 'https_proxy',
'no_proxy': 'no_proxy',
'cluster_name': 'bay1',
'cluster_name': 'cluster1',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
@ -231,17 +231,17 @@ class TestBayConductorWithMesos(base.TestCase):
self,
mock_objects_cluster_template_get_by_uuid):
self.cluster_template_dict['master_lb_enabled'] = True
self.bay_dict['master_count'] = 2
self.cluster_dict['master_count'] = 2
cluster_template = objects.ClusterTemplate(
self.context, **self.cluster_template_dict)
mock_objects_cluster_template_get_by_uuid.return_value = \
cluster_template
bay = objects.Bay(self.context, **self.bay_dict)
cluster = objects.Cluster(self.context, **self.cluster_dict)
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
expected = {
'ssh_key_name': 'keypair_id',
@ -255,7 +255,7 @@ class TestBayConductorWithMesos(base.TestCase):
'http_proxy': 'http_proxy',
'https_proxy': 'https_proxy',
'no_proxy': 'no_proxy',
'cluster_name': 'bay1',
'cluster_name': 'cluster1',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
@ -285,7 +285,7 @@ class TestBayConductorWithMesos(base.TestCase):
mock_retrieve_cluster_template):
cfg.CONF.cluster_heat.max_attempts = 10
bay = mock.MagicMock()
cluster = mock.MagicMock()
mock_heat_stack = mock.MagicMock()
mock_heat_client = mock.MagicMock()
mock_heat_client.stacks.get.return_value = mock_heat_stack
@ -293,24 +293,24 @@ class TestBayConductorWithMesos(base.TestCase):
cluster_template = objects.ClusterTemplate(
self.context, **self.cluster_template_dict)
mock_retrieve_cluster_template.return_value = cluster_template
poller = bay_conductor.HeatPoller(mock_openstack_client, bay)
poller = cluster_conductor.HeatPoller(mock_openstack_client, cluster)
poller.get_version_info = mock.MagicMock()
return (mock_heat_stack, bay, poller)
return (mock_heat_stack, cluster, poller)
def test_poll_node_count(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.parameters = {'number_of_slaves': 1}
mock_heat_stack.stack_status = bay_status.CREATE_IN_PROGRESS
mock_heat_stack.stack_status = cluster_status.CREATE_IN_PROGRESS
poller.poll_and_check()
self.assertEqual(1, bay.node_count)
self.assertEqual(1, cluster.node_count)
def test_poll_node_count_by_update(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.parameters = {'number_of_slaves': 2}
mock_heat_stack.stack_status = bay_status.UPDATE_COMPLETE
mock_heat_stack.stack_status = cluster_status.UPDATE_COMPLETE
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
self.assertEqual(2, bay.node_count)
self.assertEqual(2, cluster.node_count)

View File

@ -17,15 +17,15 @@ from mock import patch
from oslo_config import cfg
from oslo_service import loopingcall
from magnum.conductor.handlers import bay_conductor
from magnum.conductor.handlers import cluster_conductor
from magnum import objects
from magnum.objects.fields import BayStatus as bay_status
from magnum.objects.fields import ClusterStatus as cluster_status
from magnum.tests import base
class TestBayConductorWithSwarm(base.TestCase):
class TestClusterConductorWithSwarm(base.TestCase):
def setUp(self):
super(TestBayConductorWithSwarm, self).setUp()
super(TestClusterConductorWithSwarm, self).setUp()
self.cluster_template_dict = {
'image_id': 'image_id',
'flavor_id': 'flavor_id',
@ -51,11 +51,11 @@ class TestBayConductorWithSwarm(base.TestCase):
'master_lb_enabled': False,
'volume_driver': 'rexray'
}
self.bay_dict = {
self.cluster_dict = {
'id': 1,
'uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'baymodel_id': 'xx-xx-xx-xx',
'name': 'bay1',
'cluster_template_id': 'xx-xx-xx-xx',
'name': 'cluster1',
'stack_id': 'xx-xx-xx-xx',
'api_address': '172.17.2.3',
'node_addresses': ['172.17.2.4'],
@ -94,12 +94,12 @@ class TestBayConductorWithSwarm(base.TestCase):
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
cluster = objects.Cluster(self.context, **self.cluster_dict)
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
expected = {
'ssh_key_name': 'keypair_id',
@ -116,7 +116,7 @@ class TestBayConductorWithSwarm(base.TestCase):
'http_proxy': 'http_proxy',
'https_proxy': 'https_proxy',
'no_proxy': 'no_proxy',
'bay_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'cluster_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'magnum_url': self.mock_osc.magnum_url.return_value,
'tls_disabled': False,
'registry_enabled': False,
@ -155,7 +155,7 @@ class TestBayConductorWithSwarm(base.TestCase):
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
cluster = objects.Cluster(self.context, **self.cluster_dict)
cfg.CONF.set_override('swift_region',
'RegionOne',
@ -163,8 +163,8 @@ class TestBayConductorWithSwarm(base.TestCase):
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
expected = {
'ssh_key_name': 'keypair_id',
@ -180,7 +180,7 @@ class TestBayConductorWithSwarm(base.TestCase):
'http_proxy': 'http_proxy',
'https_proxy': 'https_proxy',
'no_proxy': 'no_proxy',
'bay_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'cluster_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'magnum_url': self.mock_osc.magnum_url.return_value,
'tls_disabled': False,
'registry_enabled': True,
@ -220,7 +220,7 @@ class TestBayConductorWithSwarm(base.TestCase):
'volume_driver', 'rexray_preempt']
for key in not_required:
self.cluster_template_dict[key] = None
self.bay_dict['discovery_url'] = 'https://discovery.etcd.io/test'
self.cluster_dict['discovery_url'] = 'https://discovery.etcd.io/test'
cluster_template = objects.ClusterTemplate(
self.context, **self.cluster_template_dict)
@ -231,12 +231,12 @@ class TestBayConductorWithSwarm(base.TestCase):
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
cluster = objects.Cluster(self.context, **self.cluster_dict)
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
expected = {
'ssh_key_name': 'keypair_id',
@ -244,7 +244,7 @@ class TestBayConductorWithSwarm(base.TestCase):
'number_of_masters': 1,
'number_of_nodes': 1,
'discovery_url': 'https://discovery.etcd.io/test',
'bay_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'cluster_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'magnum_url': self.mock_osc.magnum_url.return_value,
'tls_disabled': False,
'registry_enabled': False,
@ -281,12 +281,12 @@ class TestBayConductorWithSwarm(base.TestCase):
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
cluster = objects.Cluster(self.context, **self.cluster_dict)
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
expected = {
'ssh_key_name': 'keypair_id',
@ -303,7 +303,7 @@ class TestBayConductorWithSwarm(base.TestCase):
'http_proxy': 'http_proxy',
'https_proxy': 'https_proxy',
'no_proxy': 'no_proxy',
'bay_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'cluster_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'magnum_url': self.mock_osc.magnum_url.return_value,
'tls_disabled': False,
'registry_enabled': False,
@ -333,7 +333,7 @@ class TestBayConductorWithSwarm(base.TestCase):
mock_objects_cluster_template_get_by_uuid,
mock_get):
self.cluster_template_dict['master_lb_enabled'] = True
self.bay_dict['master_count'] = 2
self.cluster_dict['master_count'] = 2
cluster_template = objects.ClusterTemplate(
self.context, **self.cluster_template_dict)
mock_objects_cluster_template_get_by_uuid.return_value = \
@ -343,12 +343,12 @@ class TestBayConductorWithSwarm(base.TestCase):
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
cluster = objects.Cluster(self.context, **self.cluster_dict)
(template_path,
definition,
env_files) = bay_conductor._extract_template_definition(self.context,
bay)
env_files) = cluster_conductor._extract_template_definition(
self.context, cluster)
expected = {
'ssh_key_name': 'keypair_id',
@ -365,7 +365,7 @@ class TestBayConductorWithSwarm(base.TestCase):
'http_proxy': 'http_proxy',
'https_proxy': 'https_proxy',
'no_proxy': 'no_proxy',
'bay_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'cluster_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'magnum_url': self.mock_osc.magnum_url.return_value,
'tls_disabled': False,
'registry_enabled': False,
@ -395,7 +395,7 @@ class TestBayConductorWithSwarm(base.TestCase):
mock_retrieve_cluster_template):
cfg.CONF.cluster_heat.max_attempts = 10
bay = mock.MagicMock()
cluster = mock.MagicMock()
mock_heat_stack = mock.MagicMock()
mock_heat_client = mock.MagicMock()
mock_heat_client.stacks.get.return_value = mock_heat_stack
@ -404,24 +404,24 @@ class TestBayConductorWithSwarm(base.TestCase):
self.context, **self.cluster_template_dict)
mock_retrieve_cluster_template.return_value = \
cluster_template
poller = bay_conductor.HeatPoller(mock_openstack_client, bay)
poller = cluster_conductor.HeatPoller(mock_openstack_client, cluster)
poller.get_version_info = mock.MagicMock()
return (mock_heat_stack, bay, poller)
return (mock_heat_stack, cluster, poller)
def test_poll_node_count(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.parameters = {'number_of_nodes': 1}
mock_heat_stack.stack_status = bay_status.CREATE_IN_PROGRESS
mock_heat_stack.stack_status = cluster_status.CREATE_IN_PROGRESS
poller.poll_and_check()
self.assertEqual(1, bay.node_count)
self.assertEqual(1, cluster.node_count)
def test_poll_node_count_by_update(self):
mock_heat_stack, bay, poller = self.setup_poll_test()
mock_heat_stack, cluster, poller = self.setup_poll_test()
mock_heat_stack.parameters = {'number_of_nodes': 2}
mock_heat_stack.stack_status = bay_status.UPDATE_COMPLETE
mock_heat_stack.stack_status = cluster_status.UPDATE_COMPLETE
self.assertRaises(loopingcall.LoopingCallDone, poller.poll_and_check)
self.assertEqual(2, bay.node_count)
self.assertEqual(2, cluster.node_count)

View File

@ -42,14 +42,14 @@ class MonitorsTestCase(base.TestCase):
def setUp(self):
super(MonitorsTestCase, self).setUp()
bay = utils.get_test_bay(node_addresses=['1.2.3.4'],
api_address='https://5.6.7.8:2376',
master_addresses=['10.0.0.6'])
self.bay = objects.Bay(self.context, **bay)
self.monitor = swarm_monitor.SwarmMonitor(self.context, self.bay)
self.k8s_monitor = k8s_monitor.K8sMonitor(self.context, self.bay)
cluster = utils.get_test_cluster(node_addresses=['1.2.3.4'],
api_address='https://5.6.7.8:2376',
master_addresses=['10.0.0.6'])
self.cluster = objects.Cluster(self.context, **cluster)
self.monitor = swarm_monitor.SwarmMonitor(self.context, self.cluster)
self.k8s_monitor = k8s_monitor.K8sMonitor(self.context, self.cluster)
self.mesos_monitor = mesos_monitor.MesosMonitor(self.context,
self.bay)
self.cluster)
p = mock.patch('magnum.conductor.swarm_monitor.SwarmMonitor.'
'metrics_spec', new_callable=mock.PropertyMock)
self.mock_metrics_spec = p.start()
@ -57,31 +57,32 @@ class MonitorsTestCase(base.TestCase):
self.addCleanup(p.stop)
def test_create_monitor_success(self):
self.bay.cluster_template = obj_utils.get_test_cluster_template(
self.context, uuid=self.bay.baymodel_id, coe='swarm')
monitor = monitors.create_monitor(self.context, self.bay)
self.cluster.cluster_template = obj_utils.get_test_cluster_template(
self.context, uuid=self.cluster.cluster_template_id, coe='swarm')
monitor = monitors.create_monitor(self.context, self.cluster)
self.assertIsInstance(monitor, swarm_monitor.SwarmMonitor)
def test_create_monitor_k8s_bay(self):
self.bay.cluster_template = obj_utils.get_test_cluster_template(
self.context, uuid=self.bay.baymodel_id, coe='kubernetes')
monitor = monitors.create_monitor(self.context, self.bay)
def test_create_monitor_k8s_cluster(self):
self.cluster.cluster_template = obj_utils.get_test_cluster_template(
self.context, uuid=self.cluster.cluster_template_id,
coe='kubernetes')
monitor = monitors.create_monitor(self.context, self.cluster)
self.assertIsInstance(monitor, k8s_monitor.K8sMonitor)
def test_create_monitor_mesos_bay(self):
self.bay.cluster_template = obj_utils.get_test_cluster_template(
self.context, uuid=self.bay.baymodel_id, coe='mesos')
monitor = monitors.create_monitor(self.context, self.bay)
def test_create_monitor_mesos_cluster(self):
self.cluster.cluster_template = obj_utils.get_test_cluster_template(
self.context, uuid=self.cluster.cluster_template_id, coe='mesos')
monitor = monitors.create_monitor(self.context, self.cluster)
self.assertIsInstance(monitor, mesos_monitor.MesosMonitor)
@mock.patch('magnum.common.docker_utils.docker_for_bay')
def test_swarm_monitor_pull_data_success(self, mock_docker_for_bay):
@mock.patch('magnum.common.docker_utils.docker_for_cluster')
def test_swarm_monitor_pull_data_success(self, mock_docker_cluster):
mock_docker = mock.MagicMock()
mock_docker.info.return_value = {'DriverStatus': [[
u' \u2514 Reserved Memory', u'0 B / 1 GiB']]}
mock_docker.containers.return_value = [mock.MagicMock()]
mock_docker.inspect_container.return_value = 'test_container'
mock_docker_for_bay.return_value.__enter__.return_value = mock_docker
mock_docker_cluster.return_value.__enter__.return_value = mock_docker
self.monitor.pull_data()
@ -89,15 +90,15 @@ class MonitorsTestCase(base.TestCase):
self.monitor.data['nodes'])
self.assertEqual(['test_container'], self.monitor.data['containers'])
@mock.patch('magnum.common.docker_utils.docker_for_bay')
def test_swarm_monitor_pull_data_raise(self, mock_docker_for_bay):
@mock.patch('magnum.common.docker_utils.docker_for_cluster')
def test_swarm_monitor_pull_data_raise(self, mock_docker_cluster):
mock_container = mock.MagicMock()
mock_docker = mock.MagicMock()
mock_docker.info.return_value = {'DriverStatus': [[
u' \u2514 Reserved Memory', u'0 B / 1 GiB']]}
mock_docker.containers.return_value = [mock_container]
mock_docker.inspect_container.side_effect = Exception("inspect error")
mock_docker_for_bay.return_value.__enter__.return_value = mock_docker
mock_docker_cluster.return_value.__enter__.return_value = mock_docker
self.monitor.pull_data()
@ -288,7 +289,7 @@ class MonitorsTestCase(base.TestCase):
@mock.patch('magnum.common.urlfetch.get')
def test_mesos_monitor_pull_data_success_no_master(self, mock_url_get):
self.bay.master_addresses = []
self.cluster.master_addresses = []
self._test_mesos_monitor_pull_data(mock_url_get, {}, 0, 0, 0, 0)
def test_mesos_monitor_get_metric_names(self):

View File

@ -27,9 +27,9 @@ class RPCAPITestCase(base.DbTestCase):
def setUp(self):
super(RPCAPITestCase, self).setUp()
self.fake_bay = dbutils.get_test_bay(driver='fake-driver')
self.fake_cluster = dbutils.get_test_cluster(driver='fake-driver')
self.fake_certificate = objects.Certificate.from_db_cluster(
self.fake_bay)
self.fake_cluster)
self.fake_certificate.csr = 'fake-csr'
def _test_rpcapi(self, method, rpc_method, **kwargs):
@ -73,29 +73,29 @@ class RPCAPITestCase(base.DbTestCase):
for arg, expected_arg in zip(self.fake_args, expected_args):
self.assertEqual(expected_arg, arg)
def test_bay_create(self):
self._test_rpcapi('bay_create',
def test_cluster_create(self):
self._test_rpcapi('cluster_create',
'call',
version='1.0',
bay=self.fake_bay,
bay_create_timeout=15)
cluster=self.fake_cluster,
create_timeout=15)
def test_bay_delete(self):
self._test_rpcapi('bay_delete',
def test_cluster_delete(self):
self._test_rpcapi('cluster_delete',
'call',
version='1.0',
uuid=self.fake_bay['uuid'])
uuid=self.fake_cluster['uuid'])
self._test_rpcapi('bay_delete',
self._test_rpcapi('cluster_delete',
'call',
version='1.1',
uuid=self.fake_bay['name'])
uuid=self.fake_cluster['name'])
def test_bay_update(self):
self._test_rpcapi('bay_update',
def test_cluster_update(self):
self._test_rpcapi('cluster_update',
'call',
version='1.1',
bay=self.fake_bay['name'])
cluster=self.fake_cluster['name'])
def test_ping_conductor(self):
self._test_rpcapi('ping_conductor',
@ -107,11 +107,11 @@ class RPCAPITestCase(base.DbTestCase):
self._test_rpcapi('sign_certificate',
'call',
version='1.0',
cluster=self.fake_bay,
cluster=self.fake_cluster,
certificate=self.fake_certificate)
def test_get_ca_certificate(self):
self._test_rpcapi('get_ca_certificate',
'call',
version='1.0',
cluster=self.fake_bay)
cluster=self.fake_cluster)

View File

@ -49,9 +49,9 @@ class TestScaleManager(base.TestCase):
mock_osc.heat.return_value = mock_heat_client
mock_context = mock.MagicMock()
mock_bay = mock.MagicMock()
mock_cluster = mock.MagicMock()
scale_mgr = scale_manager.ScaleManager(mock_context, mock_osc,
mock_bay)
mock_cluster)
if expected_removal_hosts is None:
self.assertRaises(exception.MagnumException,
@ -61,9 +61,9 @@ class TestScaleManager(base.TestCase):
self.assertEqual(expected_removal_hosts, removal_hosts)
if num_of_removal > 0:
mock_create_k8s_api.assert_called_once_with(mock_context,
mock_bay)
mock_cluster)
@mock.patch('magnum.objects.Bay.get_by_uuid')
@mock.patch('magnum.objects.Cluster.get_by_uuid')
@mock.patch('magnum.conductor.scale_manager.ScaleManager._is_scale_down')
@mock.patch('magnum.conductor.scale_manager.ScaleManager.'
'_get_num_of_removal')
@ -82,7 +82,7 @@ class TestScaleManager(base.TestCase):
mock_get_by_uuid, is_scale_down, num_of_removal, hosts, pods,
expected_removal_hosts)
@mock.patch('magnum.objects.Bay.get_by_uuid')
@mock.patch('magnum.objects.Cluster.get_by_uuid')
@mock.patch('magnum.conductor.scale_manager.ScaleManager._is_scale_down')
@mock.patch('magnum.conductor.scale_manager.ScaleManager.'
'_get_num_of_removal')
@ -101,7 +101,7 @@ class TestScaleManager(base.TestCase):
mock_get_by_uuid, is_scale_down, num_of_removal, hosts, pods,
expected_removal_hosts)
@mock.patch('magnum.objects.Bay.get_by_uuid')
@mock.patch('magnum.objects.Cluster.get_by_uuid')
@mock.patch('magnum.conductor.scale_manager.ScaleManager._is_scale_down')
@mock.patch('magnum.conductor.scale_manager.ScaleManager.'
'_get_num_of_removal')
@ -120,7 +120,7 @@ class TestScaleManager(base.TestCase):
mock_get_by_uuid, is_scale_down, num_of_removal, hosts, pods,
expected_removal_hosts)
@mock.patch('magnum.objects.Bay.get_by_uuid')
@mock.patch('magnum.objects.Cluster.get_by_uuid')
@mock.patch('magnum.conductor.scale_manager.ScaleManager._is_scale_down')
@mock.patch('magnum.conductor.scale_manager.ScaleManager.'
'_get_num_of_removal')
@ -139,7 +139,7 @@ class TestScaleManager(base.TestCase):
mock_get_by_uuid, is_scale_down, num_of_removal, hosts, pods,
expected_removal_hosts)
@mock.patch('magnum.objects.Bay.get_by_uuid')
@mock.patch('magnum.objects.Cluster.get_by_uuid')
@mock.patch('magnum.conductor.scale_manager.ScaleManager._is_scale_down')
@mock.patch('magnum.conductor.scale_manager.ScaleManager.'
'_get_num_of_removal')
@ -158,7 +158,7 @@ class TestScaleManager(base.TestCase):
mock_get_by_uuid, is_scale_down, num_of_removal, hosts, pods,
expected_removal_hosts)
@mock.patch('magnum.objects.Bay.get_by_uuid')
@mock.patch('magnum.objects.Cluster.get_by_uuid')
@mock.patch('magnum.conductor.scale_manager.ScaleManager._is_scale_down')
@mock.patch('magnum.conductor.scale_manager.ScaleManager.'
'_get_num_of_removal')

View File

@ -22,11 +22,12 @@ from magnum.tests import base
class TestConductorUtils(base.TestCase):
def _test_retrieve_bay(self, expected_bay_uuid, mock_bay_get_by_uuid):
def _test_retrieve_cluster(self, expected_cluster_uuid,
mock_cluster_get_by_uuid):
expected_context = 'context'
utils.retrieve_bay(expected_context, expected_bay_uuid)
mock_bay_get_by_uuid.assert_called_once_with(expected_context,
expected_bay_uuid)
utils.retrieve_cluster(expected_context, expected_cluster_uuid)
mock_cluster_get_by_uuid.assert_called_once_with(
expected_context, expected_cluster_uuid)
def get_fake_id(self):
return '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
@ -40,38 +41,39 @@ class TestConductorUtils(base.TestCase):
expected_context = 'context'
expected_cluster_template_uuid = 'ClusterTemplate_uuid'
bay = objects.Bay({})
bay.baymodel_id = expected_cluster_template_uuid
cluster = objects.Cluster({})
cluster.cluster_template_id = expected_cluster_template_uuid
utils.retrieve_cluster_template(expected_context, bay)
utils.retrieve_cluster_template(expected_context, cluster)
mock_cluster_template_get_by_uuid.assert_called_once_with(
expected_context,
expected_cluster_template_uuid)
@patch('oslo_utils.uuidutils.is_uuid_like')
@patch('magnum.objects.Bay.get_by_name')
def test_retrieve_bay_uuid_from_name(self, mock_bay_get_by_name,
mock_uuid_like):
bay = objects.Bay(uuid='5d12f6fd-a196-4bf0-ae4c-1f639a523a52')
@patch('magnum.objects.Cluster.get_by_name')
def test_retrieve_cluster_uuid_from_name(self, mock_cluster_get_by_name,
mock_uuid_like):
cluster = objects.Cluster(uuid='5d12f6fd-a196-4bf0-ae4c-1f639a523a52')
mock_uuid_like.return_value = False
mock_bay_get_by_name.return_value = bay
bay_uuid = utils.retrieve_bay_uuid('context', 'fake_name')
self.assertEqual('5d12f6fd-a196-4bf0-ae4c-1f639a523a52', bay_uuid)
mock_cluster_get_by_name.return_value = cluster
cluster_uuid = utils.retrieve_cluster_uuid('context', 'fake_name')
self.assertEqual('5d12f6fd-a196-4bf0-ae4c-1f639a523a52', cluster_uuid)
mock_uuid_like.assert_called_once_with('fake_name')
mock_bay_get_by_name.assert_called_once_with('context', 'fake_name')
mock_cluster_get_by_name.assert_called_once_with('context',
'fake_name')
@patch('oslo_utils.uuidutils.is_uuid_like')
@patch('magnum.objects.Bay.get_by_name')
def test_retrieve_bay_uuid_from_uuid(self, mock_bay_get_by_name,
mock_uuid_like):
bay_uuid = utils.retrieve_bay_uuid(
@patch('magnum.objects.Cluster.get_by_name')
def test_retrieve_cluster_uuid_from_uuid(self, mock_cluster_get_by_name,
mock_uuid_like):
cluster_uuid = utils.retrieve_cluster_uuid(
'context',
'5d12f6fd-a196-4bf0-ae4c-1f639a523a52')
self.assertEqual('5d12f6fd-a196-4bf0-ae4c-1f639a523a52', bay_uuid)
self.assertEqual('5d12f6fd-a196-4bf0-ae4c-1f639a523a52', cluster_uuid)
mock_uuid_like.return_value = True
mock_bay_get_by_name.assert_not_called()
mock_cluster_get_by_name.assert_not_called()
def _get_heat_stacks_get_mock_obj(self, status):
mock_stack = mock.MagicMock()
@ -84,45 +86,46 @@ class TestConductorUtils(base.TestCase):
mock_osc.heat.return_value = mock_stack
return mock_osc
@patch('magnum.conductor.utils.retrieve_bay')
@patch('magnum.conductor.utils.retrieve_cluster')
@patch('magnum.conductor.utils.clients.OpenStackClients')
def test_object_has_stack_invalid_status(self, mock_oscs,
mock_retrieve_bay):
mock_retrieve_cluster):
mock_osc = self._get_heat_stacks_get_mock_obj("INVALID_STATUS")
mock_oscs.return_value = mock_osc
self.assertTrue(utils.object_has_stack('context', self.get_fake_id()))
mock_retrieve_bay.assert_called_with('context', self.get_fake_id())
mock_retrieve_cluster.assert_called_with('context', self.get_fake_id())
@patch('magnum.conductor.utils.retrieve_bay')
@patch('magnum.conductor.utils.retrieve_cluster')
@patch('magnum.conductor.utils.clients.OpenStackClients')
def test_object_has_stack_delete_in_progress(self, mock_oscs,
mock_retrieve_bay):
mock_retrieve_cluster):
mock_osc = self._get_heat_stacks_get_mock_obj("DELETE_IN_PROGRESS")
mock_oscs.return_value = mock_osc
self.assertFalse(utils.object_has_stack('context', self.get_fake_id()))
mock_retrieve_bay.assert_called_with('context', self.get_fake_id())
mock_retrieve_cluster.assert_called_with('context', self.get_fake_id())
@patch('magnum.conductor.utils.retrieve_bay')
@patch('magnum.conductor.utils.retrieve_cluster')
@patch('magnum.conductor.utils.clients.OpenStackClients')
def test_object_has_stack_delete_complete_status(self, mock_oscs,
mock_retrieve_bay):
mock_retrieve_cluster):
mock_osc = self._get_heat_stacks_get_mock_obj("DELETE_COMPLETE")
mock_oscs.return_value = mock_osc
self.assertFalse(utils.object_has_stack('context', self.get_fake_id()))
mock_retrieve_bay.assert_called_with('context', self.get_fake_id())
mock_retrieve_cluster.assert_called_with('context', self.get_fake_id())
@patch('magnum.objects.Bay.get_by_uuid')
def test_retrieve_bay_uuid(self, mock_get_by_uuid):
@patch('magnum.objects.Cluster.get_by_uuid')
def test_retrieve_cluster_uuid(self, mock_get_by_uuid):
mock_get_by_uuid.return_value = True
utils.retrieve_bay('context', '5d12f6fd-a196-4bf0-ae4c-1f639a523a52')
utils.retrieve_cluster('context',
'5d12f6fd-a196-4bf0-ae4c-1f639a523a52')
self.assertTrue(mock_get_by_uuid.called)
@patch('magnum.objects.Bay.get_by_name')
def test_retrieve_bay_name(self, mock_get_by_name):
@patch('magnum.objects.Cluster.get_by_name')
def test_retrieve_cluster_name(self, mock_get_by_name):
mock_get_by_name.return_value = mock.MagicMock()
utils.retrieve_bay('context', '1')
utils.retrieve_cluster('context', '1')
self.assertTrue(mock_get_by_name.called)
@patch('magnum.conductor.utils.resource.Resource')

View File

@ -45,25 +45,25 @@ class SqlAlchemyCustomTypesTestCase(base.DbTestCase):
['this is not a dict']})
def test_JSONEncodedList_default_value(self):
# Create bay w/o master_addresses
bay1_id = uuidutils.generate_uuid()
self.dbapi.create_bay({'uuid': bay1_id})
bay1 = sa_api.model_query(
models.Bay).filter_by(uuid=bay1_id).one()
self.assertEqual([], bay1.master_addresses)
# Create cluster w/o master_addresses
cluster1_id = uuidutils.generate_uuid()
self.dbapi.create_cluster({'uuid': cluster1_id})
cluster1 = sa_api.model_query(
models.Cluster).filter_by(uuid=cluster1_id).one()
self.assertEqual([], cluster1.master_addresses)
# Create bay with master_addresses
bay2_id = uuidutils.generate_uuid()
self.dbapi.create_bay({'uuid': bay2_id,
'master_addresses': ['mymaster_address1',
'mymaster_address2']})
bay2 = sa_api.model_query(
models.Bay).filter_by(uuid=bay2_id).one()
# Create cluster with master_addresses
cluster2_id = uuidutils.generate_uuid()
self.dbapi.create_cluster({'uuid': cluster2_id,
'master_addresses': ['mymaster_address1',
'mymaster_address2']})
cluster2 = sa_api.model_query(
models.Cluster).filter_by(uuid=cluster2_id).one()
self.assertEqual(['mymaster_address1', 'mymaster_address2'],
bay2.master_addresses)
cluster2.master_addresses)
def test_JSONEncodedList_type_check(self):
self.assertRaises(db_exc.DBError,
self.dbapi.create_bay,
self.dbapi.create_cluster,
{'master_addresses':
{'this is not a list': 'test'}})

View File

@ -1,214 +0,0 @@
# Copyright 2015 OpenStack Foundation
# 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.
"""Tests for manipulating Bays via the DB API"""
from oslo_utils import uuidutils
import six
from magnum.common import context
from magnum.common import exception
from magnum.objects.fields import BayStatus as bay_status
from magnum.tests.unit.db import base
from magnum.tests.unit.db import utils
class DbBayTestCase(base.DbTestCase):
def test_create_bay(self):
utils.create_test_bay()
def test_create_bay_nullable_baymodel_id(self):
utils.create_test_bay(baymodel_id=None)
def test_create_bay_already_exists(self):
utils.create_test_bay()
self.assertRaises(exception.ClusterAlreadyExists,
utils.create_test_bay)
def test_get_bay_by_id(self):
bay = utils.create_test_bay()
res = self.dbapi.get_bay_by_id(self.context, bay.id)
self.assertEqual(bay.id, res.id)
self.assertEqual(bay.uuid, res.uuid)
def test_get_bay_by_name(self):
bay = utils.create_test_bay()
res = self.dbapi.get_bay_by_name(self.context, bay.name)
self.assertEqual(bay.name, res.name)
self.assertEqual(bay.uuid, res.uuid)
def test_get_bay_by_uuid(self):
bay = utils.create_test_bay()
res = self.dbapi.get_bay_by_uuid(self.context, bay.uuid)
self.assertEqual(bay.id, res.id)
self.assertEqual(bay.uuid, res.uuid)
def test_get_bay_that_does_not_exist(self):
self.assertRaises(exception.ClusterNotFound,
self.dbapi.get_bay_by_id,
self.context, 999)
self.assertRaises(exception.ClusterNotFound,
self.dbapi.get_bay_by_uuid,
self.context,
'12345678-9999-0000-aaaa-123456789012')
def test_get_bay_list(self):
uuids = []
for i in range(1, 6):
bay = utils.create_test_bay(uuid=uuidutils.generate_uuid())
uuids.append(six.text_type(bay['uuid']))
res = self.dbapi.get_bay_list(self.context)
res_uuids = [r.uuid for r in res]
self.assertEqual(sorted(uuids), sorted(res_uuids))
def test_get_bay_list_sorted(self):
uuids = []
for _ in range(5):
bay = utils.create_test_bay(uuid=uuidutils.generate_uuid())
uuids.append(six.text_type(bay.uuid))
res = self.dbapi.get_bay_list(self.context, sort_key='uuid')
res_uuids = [r.uuid for r in res]
self.assertEqual(sorted(uuids), res_uuids)
self.assertRaises(exception.InvalidParameterValue,
self.dbapi.get_bay_list,
self.context,
sort_key='foo')
def test_get_bay_list_with_filters(self):
ct1 = utils.get_test_cluster_template(id=1,
uuid=uuidutils.generate_uuid())
ct2 = utils.get_test_cluster_template(id=2,
uuid=uuidutils.generate_uuid())
self.dbapi.create_cluster_template(ct1)
self.dbapi.create_cluster_template(ct2)
bay1 = utils.create_test_bay(
name='bay-one',
uuid=uuidutils.generate_uuid(),
baymodel_id=ct1['uuid'],
status=bay_status.CREATE_IN_PROGRESS)
bay2 = utils.create_test_bay(
name='bay-two',
uuid=uuidutils.generate_uuid(),
baymodel_id=ct2['uuid'],
node_count=1,
master_count=1,
status=bay_status.UPDATE_IN_PROGRESS)
bay3 = utils.create_test_bay(
name='bay-three',
node_count=2,
master_count=5,
status=bay_status.DELETE_IN_PROGRESS)
res = self.dbapi.get_bay_list(self.context,
filters={'baymodel_id': ct1['uuid']})
self.assertEqual([bay1.id], [r.id for r in res])
res = self.dbapi.get_bay_list(self.context,
filters={'baymodel_id': ct2['uuid']})
self.assertEqual([bay2.id], [r.id for r in res])
res = self.dbapi.get_bay_list(self.context,
filters={'name': 'bay-one'})
self.assertEqual([bay1.id], [r.id for r in res])
res = self.dbapi.get_bay_list(self.context,
filters={'name': 'bad-bay'})
self.assertEqual([], [r.id for r in res])
res = self.dbapi.get_bay_list(self.context,
filters={'node_count': 3})
self.assertEqual([bay1.id], [r.id for r in res])
res = self.dbapi.get_bay_list(self.context,
filters={'node_count': 1})
self.assertEqual([bay2.id], [r.id for r in res])
res = self.dbapi.get_bay_list(self.context,
filters={'master_count': 3})
self.assertEqual([bay1.id], [r.id for r in res])
res = self.dbapi.get_bay_list(self.context,
filters={'master_count': 1})
self.assertEqual([bay2.id], [r.id for r in res])
filters = {'status': [bay_status.CREATE_IN_PROGRESS,
bay_status.DELETE_IN_PROGRESS]}
res = self.dbapi.get_bay_list(self.context,
filters=filters)
self.assertEqual([bay1.id, bay3.id], [r.id for r in res])
def test_get_bay_list_by_admin_all_tenants(self):
uuids = []
for i in range(1, 6):
bay = utils.create_test_bay(
uuid=uuidutils.generate_uuid(),
project_id=uuidutils.generate_uuid(),
user_id=uuidutils.generate_uuid())
uuids.append(six.text_type(bay['uuid']))
ctx = context.make_admin_context(all_tenants=True)
res = self.dbapi.get_bay_list(ctx)
res_uuids = [r.uuid for r in res]
self.assertEqual(sorted(uuids), sorted(res_uuids))
def test_get_bay_list_baymodel_not_exist(self):
utils.create_test_bay()
self.assertEqual(1, len(self.dbapi.get_bay_list(self.context)))
res = self.dbapi.get_bay_list(self.context, filters={
'baymodel_id': uuidutils.generate_uuid()})
self.assertEqual(0, len(res))
def test_destroy_bay(self):
bay = utils.create_test_bay()
self.assertIsNotNone(self.dbapi.get_bay_by_id(self.context,
bay.id))
self.dbapi.destroy_bay(bay.id)
self.assertRaises(exception.ClusterNotFound,
self.dbapi.get_bay_by_id,
self.context, bay.id)
def test_destroy_bay_by_uuid(self):
bay = utils.create_test_bay()
self.assertIsNotNone(self.dbapi.get_bay_by_uuid(self.context,
bay.uuid))
self.dbapi.destroy_bay(bay.uuid)
self.assertRaises(exception.ClusterNotFound,
self.dbapi.get_bay_by_uuid, self.context,
bay.uuid)
def test_destroy_bay_that_does_not_exist(self):
self.assertRaises(exception.ClusterNotFound,
self.dbapi.destroy_bay,
'12345678-9999-0000-aaaa-123456789012')
def test_update_bay(self):
bay = utils.create_test_bay()
old_nc = bay.node_count
new_nc = 5
self.assertNotEqual(old_nc, new_nc)
res = self.dbapi.update_bay(bay.id, {'node_count': new_nc})
self.assertEqual(new_nc, res.node_count)
def test_update_bay_not_found(self):
bay_uuid = uuidutils.generate_uuid()
self.assertRaises(exception.ClusterNotFound, self.dbapi.update_bay,
bay_uuid, {'node_count': 5})
def test_update_bay_uuid(self):
bay = utils.create_test_bay()
self.assertRaises(exception.InvalidParameterValue,
self.dbapi.update_bay, bay.id,
{'uuid': ''})

View File

@ -0,0 +1,214 @@
# Copyright 2015 OpenStack Foundation
# 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.
"""Tests for manipulating Clusters via the DB API"""
from oslo_utils import uuidutils
import six
from magnum.common import context
from magnum.common import exception
from magnum.objects.fields import ClusterStatus as cluster_status
from magnum.tests.unit.db import base
from magnum.tests.unit.db import utils
class DbClusterTestCase(base.DbTestCase):
def test_create_cluster(self):
utils.create_test_cluster()
def test_create_cluster_nullable_cluster_template_id(self):
utils.create_test_cluster(cluster_template_id=None)
def test_create_cluster_already_exists(self):
utils.create_test_cluster()
self.assertRaises(exception.ClusterAlreadyExists,
utils.create_test_cluster)
def test_get_cluster_by_id(self):
cluster = utils.create_test_cluster()
res = self.dbapi.get_cluster_by_id(self.context, cluster.id)
self.assertEqual(cluster.id, res.id)
self.assertEqual(cluster.uuid, res.uuid)
def test_get_cluster_by_name(self):
cluster = utils.create_test_cluster()
res = self.dbapi.get_cluster_by_name(self.context, cluster.name)
self.assertEqual(cluster.name, res.name)
self.assertEqual(cluster.uuid, res.uuid)
def test_get_cluster_by_uuid(self):
cluster = utils.create_test_cluster()
res = self.dbapi.get_cluster_by_uuid(self.context, cluster.uuid)
self.assertEqual(cluster.id, res.id)
self.assertEqual(cluster.uuid, res.uuid)
def test_get_cluster_that_does_not_exist(self):
self.assertRaises(exception.ClusterNotFound,
self.dbapi.get_cluster_by_id,
self.context, 999)
self.assertRaises(exception.ClusterNotFound,
self.dbapi.get_cluster_by_uuid,
self.context,
'12345678-9999-0000-aaaa-123456789012')
def test_get_cluster_list(self):
uuids = []
for i in range(1, 6):
cluster = utils.create_test_cluster(uuid=uuidutils.generate_uuid())
uuids.append(six.text_type(cluster['uuid']))
res = self.dbapi.get_cluster_list(self.context)
res_uuids = [r.uuid for r in res]
self.assertEqual(sorted(uuids), sorted(res_uuids))
def test_get_cluster_list_sorted(self):
uuids = []
for _ in range(5):
cluster = utils.create_test_cluster(uuid=uuidutils.generate_uuid())
uuids.append(six.text_type(cluster.uuid))
res = self.dbapi.get_cluster_list(self.context, sort_key='uuid')
res_uuids = [r.uuid for r in res]
self.assertEqual(sorted(uuids), res_uuids)
self.assertRaises(exception.InvalidParameterValue,
self.dbapi.get_cluster_list,
self.context,
sort_key='foo')
def test_get_cluster_list_with_filters(self):
ct1 = utils.get_test_cluster_template(id=1,
uuid=uuidutils.generate_uuid())
ct2 = utils.get_test_cluster_template(id=2,
uuid=uuidutils.generate_uuid())
self.dbapi.create_cluster_template(ct1)
self.dbapi.create_cluster_template(ct2)
cluster1 = utils.create_test_cluster(
name='cluster-one',
uuid=uuidutils.generate_uuid(),
cluster_template_id=ct1['uuid'],
status=cluster_status.CREATE_IN_PROGRESS)
cluster2 = utils.create_test_cluster(
name='cluster-two',
uuid=uuidutils.generate_uuid(),
cluster_template_id=ct2['uuid'],
node_count=1,
master_count=1,
status=cluster_status.UPDATE_IN_PROGRESS)
cluster3 = utils.create_test_cluster(
name='cluster-three',
node_count=2,
master_count=5,
status=cluster_status.DELETE_IN_PROGRESS)
res = self.dbapi.get_cluster_list(
self.context, filters={'cluster_template_id': ct1['uuid']})
self.assertEqual([cluster1.id], [r.id for r in res])
res = self.dbapi.get_cluster_list(
self.context, filters={'cluster_template_id': ct2['uuid']})
self.assertEqual([cluster2.id], [r.id for r in res])
res = self.dbapi.get_cluster_list(self.context,
filters={'name': 'cluster-one'})
self.assertEqual([cluster1.id], [r.id for r in res])
res = self.dbapi.get_cluster_list(self.context,
filters={'name': 'bad-cluster'})
self.assertEqual([], [r.id for r in res])
res = self.dbapi.get_cluster_list(self.context,
filters={'node_count': 3})
self.assertEqual([cluster1.id], [r.id for r in res])
res = self.dbapi.get_cluster_list(self.context,
filters={'node_count': 1})
self.assertEqual([cluster2.id], [r.id for r in res])
res = self.dbapi.get_cluster_list(self.context,
filters={'master_count': 3})
self.assertEqual([cluster1.id], [r.id for r in res])
res = self.dbapi.get_cluster_list(self.context,
filters={'master_count': 1})
self.assertEqual([cluster2.id], [r.id for r in res])
filters = {'status': [cluster_status.CREATE_IN_PROGRESS,
cluster_status.DELETE_IN_PROGRESS]}
res = self.dbapi.get_cluster_list(self.context,
filters=filters)
self.assertEqual([cluster1.id, cluster3.id], [r.id for r in res])
def test_get_cluster_list_by_admin_all_tenants(self):
uuids = []
for i in range(1, 6):
cluster = utils.create_test_cluster(
uuid=uuidutils.generate_uuid(),
project_id=uuidutils.generate_uuid(),
user_id=uuidutils.generate_uuid())
uuids.append(six.text_type(cluster['uuid']))
ctx = context.make_admin_context(all_tenants=True)
res = self.dbapi.get_cluster_list(ctx)
res_uuids = [r.uuid for r in res]
self.assertEqual(sorted(uuids), sorted(res_uuids))
def test_get_cluster_list_cluster_template_not_exist(self):
utils.create_test_cluster()
self.assertEqual(1, len(self.dbapi.get_cluster_list(self.context)))
res = self.dbapi.get_cluster_list(self.context, filters={
'cluster_template_id': uuidutils.generate_uuid()})
self.assertEqual(0, len(res))
def test_destroy_cluster(self):
cluster = utils.create_test_cluster()
self.assertIsNotNone(self.dbapi.get_cluster_by_id(self.context,
cluster.id))
self.dbapi.destroy_cluster(cluster.id)
self.assertRaises(exception.ClusterNotFound,
self.dbapi.get_cluster_by_id,
self.context, cluster.id)
def test_destroy_cluster_by_uuid(self):
cluster = utils.create_test_cluster()
self.assertIsNotNone(self.dbapi.get_cluster_by_uuid(self.context,
cluster.uuid))
self.dbapi.destroy_cluster(cluster.uuid)
self.assertRaises(exception.ClusterNotFound,
self.dbapi.get_cluster_by_uuid, self.context,
cluster.uuid)
def test_destroy_cluster_that_does_not_exist(self):
self.assertRaises(exception.ClusterNotFound,
self.dbapi.destroy_cluster,
'12345678-9999-0000-aaaa-123456789012')
def test_update_cluster(self):
cluster = utils.create_test_cluster()
old_nc = cluster.node_count
new_nc = 5
self.assertNotEqual(old_nc, new_nc)
res = self.dbapi.update_cluster(cluster.id, {'node_count': new_nc})
self.assertEqual(new_nc, res.node_count)
def test_update_cluster_not_found(self):
cluster_uuid = uuidutils.generate_uuid()
self.assertRaises(exception.ClusterNotFound, self.dbapi.update_cluster,
cluster_uuid, {'node_count': 5})
def test_update_cluster_uuid(self):
cluster = utils.create_test_cluster()
self.assertRaises(exception.InvalidParameterValue,
self.dbapi.update_cluster, cluster.id,
{'uuid': ''})

View File

@ -178,10 +178,10 @@ class DbClusterTemplateTestCase(base.DbTestCase):
self.assertRaises(exception.ClusterTemplateNotFound,
self.dbapi.destroy_cluster_template, 666)
def test_destroy_cluster_template_that_referenced_by_bays(self):
def test_destroy_cluster_template_that_referenced_by_clusters(self):
ct = utils.create_test_cluster_template()
bay = utils.create_test_bay(cluster_template_id=ct['uuid'])
self.assertEqual(ct['uuid'], bay.baymodel_id)
cluster = utils.create_test_cluster(cluster_template_id=ct['uuid'])
self.assertEqual(ct['uuid'], cluster.cluster_template_id)
self.assertRaises(exception.ClusterTemplateReferenced,
self.dbapi.destroy_cluster_template, ct['id'])

View File

@ -24,7 +24,7 @@ def get_test_cluster_template(**kw):
'project_id': kw.get('project_id', 'fake_project'),
'user_id': kw.get('user_id', 'fake_user'),
'uuid': kw.get('uuid', 'e74c40e0-d825-11e2-a28f-0800200c9a66'),
'name': kw.get('name', 'baymodel1'),
'name': kw.get('name', 'clustermodel1'),
'image_id': kw.get('image_id', 'ubuntu'),
'flavor_id': kw.get('flavor_id', 'm1.small'),
'master_flavor_id': kw.get('master_flavor_id', 'm1.small'),
@ -73,22 +73,22 @@ def create_test_cluster_template(**kw):
return dbapi.create_cluster_template(cluster_template)
def get_test_bay(**kw):
def get_test_cluster(**kw):
attrs = {
'id': kw.get('id', 42),
'uuid': kw.get('uuid', '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'),
'name': kw.get('name', 'bay1'),
'name': kw.get('name', 'cluster1'),
'discovery_url': kw.get('discovery_url', None),
'ca_cert_ref': kw.get('ca_cert_ref', None),
'magnum_cert_ref': kw.get('magnum_cert_ref', None),
'project_id': kw.get('project_id', 'fake_project'),
'user_id': kw.get('user_id', 'fake_user'),
'baymodel_id': kw.get('baymodel_id',
'e74c40e0-d825-11e2-a28f-0800200c9a66'),
'cluster_template_id': kw.get('cluster_template_id',
'e74c40e0-d825-11e2-a28f-0800200c9a66'),
'stack_id': kw.get('stack_id', '047c6319-7abd-4bd9-a033-8c6af0173cd0'),
'status': kw.get('status', 'CREATE_IN_PROGRESS'),
'status_reason': kw.get('status_reason', 'Completed successfully'),
'bay_create_timeout': kw.get('bay_create_timeout', 60),
'create_timeout': kw.get('create_timeout', 60),
'api_address': kw.get('api_address', '172.17.2.3'),
'node_addresses': kw.get('node_addresses', ['172.17.2.4']),
'node_count': kw.get('node_count', 3),
@ -107,19 +107,19 @@ def get_test_bay(**kw):
return attrs
def create_test_bay(**kw):
"""Create test bay entry in DB and return Bay DB object.
def create_test_cluster(**kw):
"""Create test cluster entry in DB and return Cluster DB object.
Function to be used to create test Bay objects in the database.
:param kw: kwargs with overriding values for bay's attributes.
:returns: Test Bay DB object.
Function to be used to create test Cluster objects in the database.
:param kw: kwargs with overriding values for cluster's attributes.
:returns: Test Cluster DB object.
"""
bay = get_test_bay(**kw)
cluster = get_test_cluster(**kw)
# Let DB generate ID if it isn't specified explicitly
if 'id' not in kw:
del bay['id']
del cluster['id']
dbapi = db_api.get_instance()
return dbapi.create_bay(bay)
return dbapi.create_cluster(cluster)
def get_test_x509keypair(**kw):

View File

@ -104,7 +104,7 @@ class TemplateDefinitionTestCase(base.TestCase):
mesos_tdef.UbuntuMesosTemplateDefinition)
def test_get_definition_not_supported(self):
self.assertRaises(exception.BayTypeNotSupported,
self.assertRaises(exception.ClusterTypeNotSupported,
cmn_tdef.TemplateDefinition.get_template_definition,
'vm', 'not_supported', 'kubernetes')
@ -112,18 +112,18 @@ class TemplateDefinitionTestCase(base.TestCase):
cfg.CONF.set_override('enabled_definitions',
['magnum_vm_atomic_k8s'],
group='cluster')
self.assertRaises(exception.BayTypeNotEnabled,
self.assertRaises(exception.ClusterTypeNotEnabled,
cmn_tdef.TemplateDefinition.get_template_definition,
'vm', 'coreos', 'kubernetes')
def test_required_param_not_set(self):
param = cmn_tdef.ParameterMapping('test', cluster_template_attr='test',
required=True)
mock_baymodel = mock.MagicMock()
mock_baymodel.test = None
mock_cluster_template = mock.MagicMock()
mock_cluster_template.test = None
self.assertRaises(exception.RequiredParameterNotProvided,
param.set_param, {}, mock_baymodel, None)
param.set_param, {}, mock_cluster_template, None)
def test_output_mapping(self):
heat_outputs = [
@ -191,7 +191,7 @@ class BaseTemplateDefinitionTestCase(base.TestCase):
floating_ip_enabled=True,
public_ip_output_key='kube_masters',
private_ip_output_key='kube_masters_private',
bay_attr='master_addresses',
cluster_attr='master_addresses',
):
definition = self.get_definition()
@ -211,13 +211,14 @@ class BaseTemplateDefinitionTestCase(base.TestCase):
]
mock_stack = mock.MagicMock()
mock_stack.to_dict.return_value = {'outputs': outputs}
mock_bay = mock.MagicMock()
mock_baymodel = mock.MagicMock()
mock_baymodel.floating_ip_enabled = floating_ip_enabled
mock_cluster = mock.MagicMock()
mock_cluster_template = mock.MagicMock()
mock_cluster_template.floating_ip_enabled = floating_ip_enabled
definition.update_outputs(mock_stack, mock_baymodel, mock_bay)
definition.update_outputs(mock_stack, mock_cluster_template,
mock_cluster)
self.assertEqual(expected_address, getattr(mock_bay, bay_attr))
self.assertEqual(expected_address, getattr(mock_cluster, cluster_attr))
class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
@ -240,12 +241,12 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
mock_get_discovery_url, mock_osc_class):
mock_context = mock.MagicMock()
mock_context.auth_token = 'AUTH_TOKEN'
mock_baymodel = mock.MagicMock()
mock_baymodel.tls_disabled = False
mock_baymodel.registry_enabled = False
mock_bay = mock.MagicMock()
mock_bay.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
del mock_bay.stack_id
mock_cluster_template = mock.MagicMock()
mock_cluster_template.tls_disabled = False
mock_cluster_template.registry_enabled = False
mock_cluster = mock.MagicMock()
mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
del mock_cluster.stack_id
mock_scale_manager = mock.MagicMock()
mock_osc = mock.MagicMock()
mock_osc.magnum_url.return_value = 'http://127.0.0.1:9511/v1'
@ -260,13 +261,14 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
mock_context.user_name = 'fake_user'
mock_context.tenant = 'fake_tenant'
flannel_cidr = mock_baymodel.labels.get('flannel_network_cidr')
flannel_subnet = mock_baymodel.labels.get('flannel_network_subnetlen')
flannel_backend = mock_baymodel.labels.get('flannel_backend')
flannel_cidr = mock_cluster_template.labels.get('flannel_network_cidr')
flannel_subnet = mock_cluster_template.labels.get(
'flannel_network_subnetlen')
flannel_backend = mock_cluster_template.labels.get('flannel_backend')
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
k8s_def.get_params(mock_context, mock_baymodel, mock_bay,
k8s_def.get_params(mock_context, mock_cluster_template, mock_cluster,
scale_manager=mock_scale_manager)
expected_kwargs = {'extra_params': {
@ -279,8 +281,10 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
'tenant_name': 'fake_tenant',
'magnum_url': mock_osc.magnum_url.return_value,
'region_name': mock_osc.cinder_region_name.return_value}}
mock_get_params.assert_called_once_with(mock_context, mock_baymodel,
mock_bay, **expected_kwargs)
mock_get_params.assert_called_once_with(mock_context,
mock_cluster_template,
mock_cluster,
**expected_kwargs)
@mock.patch('magnum.common.clients.OpenStackClients')
@mock.patch('magnum.drivers.common.template_def'
@ -293,12 +297,12 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
mock_get_discovery_url, mock_osc_class):
mock_context = mock.MagicMock()
mock_context.auth_token = 'AUTH_TOKEN'
mock_baymodel = mock.MagicMock()
mock_baymodel.tls_disabled = True
mock_baymodel.registry_enabled = False
mock_bay = mock.MagicMock()
mock_bay.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
del mock_bay.stack_id
mock_cluster_template = mock.MagicMock()
mock_cluster_template.tls_disabled = True
mock_cluster_template.registry_enabled = False
mock_cluster = mock.MagicMock()
mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
del mock_cluster.stack_id
mock_scale_manager = mock.MagicMock()
mock_osc = mock.MagicMock()
mock_osc.magnum_url.return_value = 'http://127.0.0.1:9511/v1'
@ -313,13 +317,14 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
mock_context.user_name = 'fake_user'
mock_context.tenant = 'fake_tenant'
flannel_cidr = mock_baymodel.labels.get('flannel_network_cidr')
flannel_subnet = mock_baymodel.labels.get('flannel_network_subnetlen')
flannel_backend = mock_baymodel.labels.get('flannel_backend')
flannel_cidr = mock_cluster_template.labels.get('flannel_network_cidr')
flannel_subnet = mock_cluster_template.labels.get(
'flannel_network_subnetlen')
flannel_backend = mock_cluster_template.labels.get('flannel_backend')
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
k8s_def.get_params(mock_context, mock_baymodel, mock_bay,
k8s_def.get_params(mock_context, mock_cluster_template, mock_cluster,
scale_manager=mock_scale_manager)
expected_kwargs = {'extra_params': {
@ -334,8 +339,10 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
'region_name': mock_osc.cinder_region_name.return_value,
'loadbalancing_protocol': 'HTTP',
'kubernetes_port': 8080}}
mock_get_params.assert_called_once_with(mock_context, mock_baymodel,
mock_bay, **expected_kwargs)
mock_get_params.assert_called_once_with(mock_context,
mock_cluster_template,
mock_cluster,
**expected_kwargs)
@mock.patch('requests.get')
def test_k8s_validate_discovery_url(self, mock_get):
@ -364,7 +371,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
mock_get.return_value = mock_resp
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
self.assertRaises(exception.InvalidBayDiscoveryURL,
self.assertRaises(exception.InvalidClusterDiscoveryURL,
k8s_def.validate_discovery_url,
'http://etcd/test', 1)
@ -390,15 +397,15 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
mock_resp = mock.MagicMock()
mock_resp.text = expected_discovery_url
mock_get.return_value = mock_resp
mock_bay = mock.MagicMock()
mock_bay.master_count = 10
mock_bay.discovery_url = None
mock_cluster = mock.MagicMock()
mock_cluster.master_count = 10
mock_cluster.discovery_url = None
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
discovery_url = k8s_def.get_discovery_url(mock_bay)
discovery_url = k8s_def.get_discovery_url(mock_cluster)
mock_get.assert_called_once_with('http://etcd/test?size=10')
self.assertEqual(expected_discovery_url, mock_bay.discovery_url)
self.assertEqual(expected_discovery_url, mock_cluster.discovery_url)
self.assertEqual(expected_discovery_url, discovery_url)
@mock.patch('requests.get')
@ -407,19 +414,19 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
'http://etcd/test?size=%(size)d',
group='cluster')
mock_get.side_effect = req_exceptions.RequestException()
mock_bay = mock.MagicMock()
mock_bay.master_count = 10
mock_bay.discovery_url = None
mock_cluster = mock.MagicMock()
mock_cluster.master_count = 10
mock_cluster.discovery_url = None
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
self.assertRaises(exception.GetDiscoveryUrlFailed,
k8s_def.get_discovery_url, mock_bay)
k8s_def.get_discovery_url, mock_cluster)
def test_k8s_get_heat_param(self):
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
heat_param = k8s_def.get_heat_param(bay_attr='node_count')
heat_param = k8s_def.get_heat_param(cluster_attr='node_count')
self.assertEqual('number_of_minions', heat_param)
@mock.patch('requests.get')
@ -428,13 +435,13 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
mock_resp.text = ''
mock_get.return_value = mock_resp
fake_bay = mock.MagicMock()
fake_bay.discovery_url = None
fake_cluster = mock.MagicMock()
fake_cluster.discovery_url = None
self.assertRaises(
exception.InvalidDiscoveryURL,
k8sa_tdef.AtomicK8sTemplateDefinition().get_discovery_url,
fake_bay)
fake_cluster)
def _test_update_outputs_api_address(self, coe, params, tls=True):
@ -451,13 +458,14 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
]
mock_stack = mock.MagicMock()
mock_stack.to_dict.return_value = {'outputs': outputs}
mock_bay = mock.MagicMock()
mock_baymodel = mock.MagicMock()
mock_baymodel.tls_disabled = tls
mock_cluster = mock.MagicMock()
mock_cluster_template = mock.MagicMock()
mock_cluster_template.tls_disabled = tls
definition.update_outputs(mock_stack, mock_baymodel, mock_bay)
definition.update_outputs(mock_stack, mock_cluster_template,
mock_cluster)
self.assertEqual(expected_api_address, mock_bay.api_address)
self.assertEqual(expected_api_address, mock_cluster.api_address)
def test_update_k8s_outputs_api_address(self):
address = 'updated_address'
@ -481,7 +489,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
}
self._test_update_outputs_api_address('swarm', params)
def test_update_k8s_outputs_if_baymodel_is_secure(self):
def test_update_k8s_outputs_if_cluster_template_is_secure(self):
address = 'updated_address'
protocol = 'https'
port = '6443'
@ -492,7 +500,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
}
self._test_update_outputs_api_address('kubernetes', params, tls=False)
def test_update_swarm_outputs_if_baymodel_is_secure(self):
def test_update_swarm_outputs_if_cluster_template_is_secure(self):
address = 'updated_address'
protocol = 'tcp'
port = '2376'
@ -517,14 +525,15 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
]
mock_stack = mock.MagicMock()
mock_stack.to_dict.return_value = {'outputs': outputs}
mock_bay = mock.MagicMock()
mock_bay.api_address = 'none_api_address'
mock_baymodel = mock.MagicMock()
mock_baymodel.tls_disabled = tls
mock_cluster = mock.MagicMock()
mock_cluster.api_address = 'none_api_address'
mock_cluster_template = mock.MagicMock()
mock_cluster_template.tls_disabled = tls
definition.update_outputs(mock_stack, mock_baymodel, mock_bay)
definition.update_outputs(mock_stack, mock_cluster_template,
mock_cluster)
self.assertEqual('none_api_address', mock_bay.api_address)
self.assertEqual('none_api_address', mock_cluster.api_address)
def test_update_k8s_outputs_none_api_address(self):
protocol = 'http'
@ -550,14 +559,14 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
self._test_update_outputs_server_addrtess(
public_ip_output_key='kube_masters',
private_ip_output_key='kube_masters_private',
bay_attr='master_addresses',
cluster_attr='master_addresses',
)
def test_update_outputs_node_address(self):
self._test_update_outputs_server_addrtess(
public_ip_output_key='kube_minions',
private_ip_output_key='kube_minions_private',
bay_attr='node_addresses',
cluster_attr='node_addresses',
)
def test_update_outputs_master_address_fip_disabled(self):
@ -565,7 +574,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
floating_ip_enabled=False,
public_ip_output_key='kube_masters',
private_ip_output_key='kube_masters_private',
bay_attr='master_addresses',
cluster_attr='master_addresses',
)
def test_update_outputs_node_address_fip_disabled(self):
@ -573,7 +582,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase):
floating_ip_enabled=False,
public_ip_output_key='kube_minions',
private_ip_output_key='kube_minions_private',
bay_attr='node_addresses',
cluster_attr='node_addresses',
)
@ -586,11 +595,12 @@ class FedoraK8sIronicTemplateDefinitionTestCase(base.TestCase):
'kubernetes'
)
def assert_neutron_find(self, mock_neutron_v20_find, osc, baymodel):
def assert_neutron_find(self, mock_neutron_v20_find,
osc, cluster_template):
mock_neutron_v20_find.assert_called_once_with(
osc.neutron(),
'subnet',
baymodel.fixed_subnet
cluster_template.fixed_subnet
)
def assert_raises_from_get_fixed_network_id(
@ -601,14 +611,14 @@ class FedoraK8sIronicTemplateDefinitionTestCase(base.TestCase):
):
definition = self.get_definition()
osc = mock.MagicMock()
baymodel = mock.MagicMock()
cluster_template = mock.MagicMock()
mock_neutron_v20_find.side_effect = exeption_from_neutron_client
self.assertRaises(
expected_exception_class,
definition.get_fixed_network_id,
osc,
baymodel
cluster_template
)
@mock.patch('neutronclient.neutron.v2_0.find_resource_by_name_or_id')
@ -616,7 +626,7 @@ class FedoraK8sIronicTemplateDefinitionTestCase(base.TestCase):
expected_network_id = 'expected_network_id'
osc = mock.MagicMock()
baymodel = mock.MagicMock()
cluster_template = mock.MagicMock()
definition = self.get_definition()
mock_neutron_v20_find.return_value = {
'ip_version': 4,
@ -625,15 +635,15 @@ class FedoraK8sIronicTemplateDefinitionTestCase(base.TestCase):
self.assertEqual(
expected_network_id,
definition.get_fixed_network_id(osc, baymodel)
definition.get_fixed_network_id(osc, cluster_template)
)
self.assert_neutron_find(mock_neutron_v20_find, osc, baymodel)
self.assert_neutron_find(mock_neutron_v20_find, osc, cluster_template)
@mock.patch('neutronclient.neutron.v2_0.find_resource_by_name_or_id')
def test_get_fixed_network_id_with_invalid_ip_ver(self,
mock_neutron_v20_find):
osc = mock.MagicMock()
baymodel = mock.MagicMock()
cluster_template = mock.MagicMock()
definition = self.get_definition()
mock_neutron_v20_find.return_value = {
'ip_version': 6,
@ -644,7 +654,7 @@ class FedoraK8sIronicTemplateDefinitionTestCase(base.TestCase):
exception.InvalidSubnet,
definition.get_fixed_network_id,
osc,
baymodel
cluster_template
)
@mock.patch('neutronclient.neutron.v2_0.find_resource_by_name_or_id')
@ -697,12 +707,12 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
mock_get_discovery_url, mock_osc_class):
mock_context = mock.MagicMock()
mock_context.auth_token = 'AUTH_TOKEN'
mock_baymodel = mock.MagicMock()
mock_baymodel.tls_disabled = False
mock_baymodel.registry_enabled = False
mock_bay = mock.MagicMock()
mock_bay.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
del mock_bay.stack_id
mock_cluster_template = mock.MagicMock()
mock_cluster_template.tls_disabled = False
mock_cluster_template.registry_enabled = False
mock_cluster = mock.MagicMock()
mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
del mock_cluster.stack_id
mock_osc = mock.MagicMock()
mock_osc.magnum_url.return_value = 'http://127.0.0.1:9511/v1'
mock_osc_class.return_value = mock_osc
@ -713,14 +723,15 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
mock_context.user_name = 'fake_user'
mock_context.tenant = 'fake_tenant'
flannel_cidr = mock_baymodel.labels.get('flannel_network_cidr')
flannel_subnet = mock_baymodel.labels.get('flannel_network_subnetlen')
flannel_backend = mock_baymodel.labels.get('flannel_backend')
rexray_preempt = mock_baymodel.labels.get('rexray_preempt')
flannel_cidr = mock_cluster_template.labels.get('flannel_network_cidr')
flannel_subnet = mock_cluster_template.labels.get(
'flannel_network_subnetlen')
flannel_backend = mock_cluster_template.labels.get('flannel_backend')
rexray_preempt = mock_cluster_template.labels.get('rexray_preempt')
swarm_def = swarm_tdef.AtomicSwarmTemplateDefinition()
swarm_def.get_params(mock_context, mock_baymodel, mock_bay)
swarm_def.get_params(mock_context, mock_cluster_template, mock_cluster)
expected_kwargs = {'extra_params': {
'discovery_url': 'fake_discovery_url',
@ -730,8 +741,10 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
'flannel_network_subnetlen': flannel_subnet,
'auth_url': 'http://192.168.10.10:5000/v3',
'rexray_preempt': rexray_preempt}}
mock_get_params.assert_called_once_with(mock_context, mock_baymodel,
mock_bay, **expected_kwargs)
mock_get_params.assert_called_once_with(mock_context,
mock_cluster_template,
mock_cluster,
**expected_kwargs)
@mock.patch('requests.get')
def test_swarm_validate_discovery_url(self, mock_get):
@ -760,7 +773,7 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
mock_get.return_value = mock_resp
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
self.assertRaises(exception.InvalidBayDiscoveryURL,
self.assertRaises(exception.InvalidClusterDiscoveryURL,
k8s_def.validate_discovery_url,
'http://etcd/test', 1)
@ -786,14 +799,14 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
mock_resp = mock.MagicMock()
mock_resp.text = expected_discovery_url
mock_get.return_value = mock_resp
mock_bay = mock.MagicMock()
mock_bay.discovery_url = None
mock_cluster = mock.MagicMock()
mock_cluster.discovery_url = None
swarm_def = swarm_tdef.AtomicSwarmTemplateDefinition()
discovery_url = swarm_def.get_discovery_url(mock_bay)
discovery_url = swarm_def.get_discovery_url(mock_cluster)
mock_get.assert_called_once_with('http://etcd/test?size=1')
self.assertEqual(mock_bay.discovery_url, expected_discovery_url)
self.assertEqual(mock_cluster.discovery_url, expected_discovery_url)
self.assertEqual(discovery_url, expected_discovery_url)
@mock.patch('requests.get')
@ -802,18 +815,18 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
mock_resp.text = ''
mock_get.return_value = mock_resp
fake_bay = mock.MagicMock()
fake_bay.discovery_url = None
fake_cluster = mock.MagicMock()
fake_cluster.discovery_url = None
self.assertRaises(
exception.InvalidDiscoveryURL,
k8sa_tdef.AtomicK8sTemplateDefinition().get_discovery_url,
fake_bay)
fake_cluster)
def test_swarm_get_heat_param(self):
swarm_def = swarm_tdef.AtomicSwarmTemplateDefinition()
heat_param = swarm_def.get_heat_param(bay_attr='node_count')
heat_param = swarm_def.get_heat_param(cluster_attr='node_count')
self.assertEqual('number_of_nodes', heat_param)
def test_update_outputs(self):
@ -841,13 +854,14 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
]
mock_stack = mock.MagicMock()
mock_stack.to_dict.return_value = {'outputs': outputs}
mock_bay = mock.MagicMock()
mock_baymodel = mock.MagicMock()
mock_cluster = mock.MagicMock()
mock_cluster_template = mock.MagicMock()
swarm_def.update_outputs(mock_stack, mock_baymodel, mock_bay)
swarm_def.update_outputs(mock_stack, mock_cluster_template,
mock_cluster)
expected_api_address = "tcp://%s:2376" % expected_api_address
self.assertEqual(expected_api_address, mock_bay.api_address)
self.assertEqual(expected_node_addresses, mock_bay.node_addresses)
self.assertEqual(expected_api_address, mock_cluster.api_address)
self.assertEqual(expected_node_addresses, mock_cluster.node_addresses)
class UbuntuMesosTemplateDefinitionTestCase(base.TestCase):
@ -864,19 +878,20 @@ class UbuntuMesosTemplateDefinitionTestCase(base.TestCase):
mock_context.user_name = 'mesos_user'
mock_context.tenant = 'admin'
mock_context.domain_name = 'domainname'
mock_baymodel = mock.MagicMock()
mock_baymodel.tls_disabled = False
rexray_preempt = mock_baymodel.labels.get('rexray_preempt')
mesos_slave_isolation = mock_baymodel.labels.get(
mock_cluster_template = mock.MagicMock()
mock_cluster_template.tls_disabled = False
rexray_preempt = mock_cluster_template.labels.get('rexray_preempt')
mesos_slave_isolation = mock_cluster_template.labels.get(
'mesos_slave_isolation')
mesos_slave_work_dir = mock_baymodel.labels.get('mesos_slave_work_dir')
mesos_slave_image_providers = mock_baymodel.labels.get(
mesos_slave_work_dir = mock_cluster_template.labels.get(
'mesos_slave_work_dir')
mesos_slave_image_providers = mock_cluster_template.labels.get(
'image_providers')
mesos_slave_executor_env_variables = mock_baymodel.labels.get(
mesos_slave_executor_env_variables = mock_cluster_template.labels.get(
'mesos_slave_executor_env_variables')
mock_bay = mock.MagicMock()
mock_bay.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
del mock_bay.stack_id
mock_cluster = mock.MagicMock()
mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
del mock_cluster.stack_id
mock_osc = mock.MagicMock()
mock_osc.cinder_region_name.return_value = 'RegionOne'
mock_osc_class.return_value = mock_osc
@ -887,7 +902,7 @@ class UbuntuMesosTemplateDefinitionTestCase(base.TestCase):
mesos_def = mesos_tdef.UbuntuMesosTemplateDefinition()
mesos_def.get_params(mock_context, mock_baymodel, mock_bay,
mesos_def.get_params(mock_context, mock_cluster_template, mock_cluster,
scale_manager=mock_scale_manager)
expected_kwargs = {'extra_params': {
@ -903,16 +918,18 @@ class UbuntuMesosTemplateDefinitionTestCase(base.TestCase):
mesos_slave_executor_env_variables,
'mesos_slave_image_providers': mesos_slave_image_providers,
'slaves_to_remove': removal_nodes}}
mock_get_params.assert_called_once_with(mock_context, mock_baymodel,
mock_bay, **expected_kwargs)
mock_get_params.assert_called_once_with(mock_context,
mock_cluster_template,
mock_cluster,
**expected_kwargs)
def test_mesos_get_heat_param(self):
mesos_def = mesos_tdef.UbuntuMesosTemplateDefinition()
heat_param = mesos_def.get_heat_param(bay_attr='node_count')
heat_param = mesos_def.get_heat_param(cluster_attr='node_count')
self.assertEqual('number_of_slaves', heat_param)
heat_param = mesos_def.get_heat_param(bay_attr='master_count')
heat_param = mesos_def.get_heat_param(cluster_attr='master_count')
self.assertEqual('number_of_masters', heat_param)
def test_update_outputs(self):
@ -941,11 +958,13 @@ class UbuntuMesosTemplateDefinitionTestCase(base.TestCase):
]
mock_stack = mock.MagicMock()
mock_stack.to_dict.return_value = {'outputs': outputs}
mock_bay = mock.MagicMock()
mock_baymodel = mock.MagicMock()
mock_cluster = mock.MagicMock()
mock_cluster_template = mock.MagicMock()
mesos_def.update_outputs(mock_stack, mock_baymodel, mock_bay)
mesos_def.update_outputs(mock_stack, mock_cluster_template,
mock_cluster)
self.assertEqual(expected_api_address, mock_bay.api_address)
self.assertEqual(expected_node_addresses, mock_bay.node_addresses)
self.assertEqual(expected_master_addresses, mock_bay.master_addresses)
self.assertEqual(expected_api_address, mock_cluster.api_address)
self.assertEqual(expected_node_addresses, mock_cluster.node_addresses)
self.assertEqual(expected_master_addresses,
mock_cluster.master_addresses)

View File

@ -1,192 +0,0 @@
# Copyright 2015 OpenStack Foundation
# 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.
import mock
from oslo_utils import uuidutils
from testtools.matchers import HasLength
from magnum.common import exception
from magnum import objects
from magnum.tests.unit.db import base
from magnum.tests.unit.db import utils
class TestBayObject(base.DbTestCase):
def setUp(self):
super(TestBayObject, self).setUp()
self.fake_bay = utils.get_test_bay()
self.fake_bay['trust_id'] = 'trust_id'
self.fake_bay['trustee_username'] = 'trustee_user'
self.fake_bay['trustee_user_id'] = 'trustee_user_id'
self.fake_bay['trustee_password'] = 'password'
self.fake_bay['coe_version'] = 'fake-coe-version'
self.fake_bay['container_version'] = 'fake-container-version'
cluster_template_id = self.fake_bay['baymodel_id']
self.fake_cluster_template = objects.ClusterTemplate(
uuid=cluster_template_id)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_get_by_id(self, mock_cluster_template_get):
bay_id = self.fake_bay['id']
with mock.patch.object(self.dbapi, 'get_bay_by_id',
autospec=True) as mock_get_bay:
mock_cluster_template_get.return_value = self.fake_cluster_template
mock_get_bay.return_value = self.fake_bay
bay = objects.Bay.get(self.context, bay_id)
mock_get_bay.assert_called_once_with(self.context, bay_id)
self.assertEqual(self.context, bay._context)
self.assertEqual(bay.baymodel_id, bay.cluster_template.uuid)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_get_by_uuid(self, mock_cluster_template_get):
uuid = self.fake_bay['uuid']
with mock.patch.object(self.dbapi, 'get_bay_by_uuid',
autospec=True) as mock_get_bay:
mock_cluster_template_get.return_value = self.fake_cluster_template
mock_get_bay.return_value = self.fake_bay
bay = objects.Bay.get(self.context, uuid)
mock_get_bay.assert_called_once_with(self.context, uuid)
self.assertEqual(self.context, bay._context)
self.assertEqual(bay.baymodel_id, bay.cluster_template.uuid)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_get_by_name(self, mock_cluster_template_get):
name = self.fake_bay['name']
with mock.patch.object(self.dbapi, 'get_bay_by_name',
autospec=True) as mock_get_bay:
mock_cluster_template_get.return_value = self.fake_cluster_template
mock_get_bay.return_value = self.fake_bay
bay = objects.Bay.get_by_name(self.context, name)
mock_get_bay.assert_called_once_with(self.context, name)
self.assertEqual(self.context, bay._context)
self.assertEqual(bay.baymodel_id, bay.cluster_template.uuid)
def test_get_bad_id_and_uuid(self):
self.assertRaises(exception.InvalidIdentity,
objects.Bay.get, self.context, 'not-a-uuid')
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_list(self, mock_cluster_template_get):
with mock.patch.object(self.dbapi, 'get_bay_list',
autospec=True) as mock_get_list:
mock_get_list.return_value = [self.fake_bay]
mock_cluster_template_get.return_value = self.fake_cluster_template
bays = objects.Bay.list(self.context)
self.assertEqual(1, mock_get_list.call_count)
self.assertThat(bays, HasLength(1))
self.assertIsInstance(bays[0], objects.Bay)
self.assertEqual(self.context, bays[0]._context)
self.assertEqual(bays[0].baymodel_id,
bays[0].cluster_template.uuid)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_list_all(self, mock_cluster_template_get):
with mock.patch.object(self.dbapi, 'get_bay_list',
autospec=True) as mock_get_list:
mock_get_list.return_value = [self.fake_bay]
mock_cluster_template_get.return_value = self.fake_cluster_template
self.context.all_tenants = True
bays = objects.Bay.list(self.context)
mock_get_list.assert_called_once_with(
self.context, limit=None, marker=None, filters=None,
sort_dir=None, sort_key=None)
self.assertEqual(1, mock_get_list.call_count)
self.assertThat(bays, HasLength(1))
self.assertIsInstance(bays[0], objects.Bay)
self.assertEqual(self.context, bays[0]._context)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_list_with_filters(self, mock_cluster_template_get):
with mock.patch.object(self.dbapi, 'get_bay_list',
autospec=True) as mock_get_list:
mock_get_list.return_value = [self.fake_bay]
mock_cluster_template_get.return_value = self.fake_cluster_template
filters = {'name': 'bay1'}
bays = objects.Bay.list(self.context, filters=filters)
mock_get_list.assert_called_once_with(self.context, sort_key=None,
sort_dir=None,
filters=filters, limit=None,
marker=None)
self.assertEqual(1, mock_get_list.call_count)
self.assertThat(bays, HasLength(1))
self.assertIsInstance(bays[0], objects.Bay)
self.assertEqual(self.context, bays[0]._context)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_create(self, mock_cluster_template_get):
with mock.patch.object(self.dbapi, 'create_bay',
autospec=True) as mock_create_bay:
mock_cluster_template_get.return_value = self.fake_cluster_template
mock_create_bay.return_value = self.fake_bay
bay = objects.Bay(self.context, **self.fake_bay)
bay.create()
mock_create_bay.assert_called_once_with(self.fake_bay)
self.assertEqual(self.context, bay._context)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_destroy(self, mock_cluster_template_get):
uuid = self.fake_bay['uuid']
with mock.patch.object(self.dbapi, 'get_bay_by_uuid',
autospec=True) as mock_get_bay:
mock_get_bay.return_value = self.fake_bay
mock_cluster_template_get.return_value = self.fake_cluster_template
with mock.patch.object(self.dbapi, 'destroy_bay',
autospec=True) as mock_destroy_bay:
bay = objects.Bay.get_by_uuid(self.context, uuid)
bay.destroy()
mock_get_bay.assert_called_once_with(self.context, uuid)
mock_destroy_bay.assert_called_once_with(uuid)
self.assertEqual(self.context, bay._context)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_save(self, mock_cluster_template_get):
uuid = self.fake_bay['uuid']
with mock.patch.object(self.dbapi, 'get_bay_by_uuid',
autospec=True) as mock_get_bay:
mock_cluster_template_get.return_value = self.fake_cluster_template
mock_get_bay.return_value = self.fake_bay
with mock.patch.object(self.dbapi, 'update_bay',
autospec=True) as mock_update_bay:
bay = objects.Bay.get_by_uuid(self.context, uuid)
bay.node_count = 10
bay.master_count = 5
bay.save()
mock_get_bay.assert_called_once_with(self.context, uuid)
mock_update_bay.assert_called_once_with(
uuid, {'node_count': 10, 'master_count': 5,
'cluster_template': self.fake_cluster_template})
self.assertEqual(self.context, bay._context)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_refresh(self, mock_cluster_template_get):
uuid = self.fake_bay['uuid']
new_uuid = uuidutils.generate_uuid()
returns = [dict(self.fake_bay, uuid=uuid),
dict(self.fake_bay, uuid=new_uuid)]
expected = [mock.call(self.context, uuid),
mock.call(self.context, uuid)]
with mock.patch.object(self.dbapi, 'get_bay_by_uuid',
side_effect=returns,
autospec=True) as mock_get_bay:
mock_cluster_template_get.return_value = self.fake_cluster_template
bay = objects.Bay.get_by_uuid(self.context, uuid)
self.assertEqual(uuid, bay.uuid)
bay.refresh()
self.assertEqual(new_uuid, bay.uuid)
self.assertEqual(expected, mock_get_bay.call_args_list)
self.assertEqual(self.context, bay._context)

View File

@ -0,0 +1,195 @@
# Copyright 2015 OpenStack Foundation
# 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.
import mock
from oslo_utils import uuidutils
from testtools.matchers import HasLength
from magnum.common import exception
from magnum import objects
from magnum.tests.unit.db import base
from magnum.tests.unit.db import utils
class TestClusterObject(base.DbTestCase):
def setUp(self):
super(TestClusterObject, self).setUp()
self.fake_cluster = utils.get_test_cluster()
self.fake_cluster['trust_id'] = 'trust_id'
self.fake_cluster['trustee_username'] = 'trustee_user'
self.fake_cluster['trustee_user_id'] = 'trustee_user_id'
self.fake_cluster['trustee_password'] = 'password'
self.fake_cluster['coe_version'] = 'fake-coe-version'
self.fake_cluster['container_version'] = 'fake-container-version'
cluster_template_id = self.fake_cluster['cluster_template_id']
self.fake_cluster_template = objects.ClusterTemplate(
uuid=cluster_template_id)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_get_by_id(self, mock_cluster_template_get):
cluster_id = self.fake_cluster['id']
with mock.patch.object(self.dbapi, 'get_cluster_by_id',
autospec=True) as mock_get_cluster:
mock_cluster_template_get.return_value = self.fake_cluster_template
mock_get_cluster.return_value = self.fake_cluster
cluster = objects.Cluster.get(self.context, cluster_id)
mock_get_cluster.assert_called_once_with(self.context, cluster_id)
self.assertEqual(self.context, cluster._context)
self.assertEqual(cluster.cluster_template_id,
cluster.cluster_template.uuid)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_get_by_uuid(self, mock_cluster_template_get):
uuid = self.fake_cluster['uuid']
with mock.patch.object(self.dbapi, 'get_cluster_by_uuid',
autospec=True) as mock_get_cluster:
mock_cluster_template_get.return_value = self.fake_cluster_template
mock_get_cluster.return_value = self.fake_cluster
cluster = objects.Cluster.get(self.context, uuid)
mock_get_cluster.assert_called_once_with(self.context, uuid)
self.assertEqual(self.context, cluster._context)
self.assertEqual(cluster.cluster_template_id,
cluster.cluster_template.uuid)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_get_by_name(self, mock_cluster_template_get):
name = self.fake_cluster['name']
with mock.patch.object(self.dbapi, 'get_cluster_by_name',
autospec=True) as mock_get_cluster:
mock_cluster_template_get.return_value = self.fake_cluster_template
mock_get_cluster.return_value = self.fake_cluster
cluster = objects.Cluster.get_by_name(self.context, name)
mock_get_cluster.assert_called_once_with(self.context, name)
self.assertEqual(self.context, cluster._context)
self.assertEqual(cluster.cluster_template_id,
cluster.cluster_template.uuid)
def test_get_bad_id_and_uuid(self):
self.assertRaises(exception.InvalidIdentity,
objects.Cluster.get, self.context, 'not-a-uuid')
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_list(self, mock_cluster_template_get):
with mock.patch.object(self.dbapi, 'get_cluster_list',
autospec=True) as mock_get_list:
mock_get_list.return_value = [self.fake_cluster]
mock_cluster_template_get.return_value = self.fake_cluster_template
clusters = objects.Cluster.list(self.context)
self.assertEqual(1, mock_get_list.call_count)
self.assertThat(clusters, HasLength(1))
self.assertIsInstance(clusters[0], objects.Cluster)
self.assertEqual(self.context, clusters[0]._context)
self.assertEqual(clusters[0].cluster_template_id,
clusters[0].cluster_template.uuid)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_list_all(self, mock_cluster_template_get):
with mock.patch.object(self.dbapi, 'get_cluster_list',
autospec=True) as mock_get_list:
mock_get_list.return_value = [self.fake_cluster]
mock_cluster_template_get.return_value = self.fake_cluster_template
self.context.all_tenants = True
clusters = objects.Cluster.list(self.context)
mock_get_list.assert_called_once_with(
self.context, limit=None, marker=None, filters=None,
sort_dir=None, sort_key=None)
self.assertEqual(1, mock_get_list.call_count)
self.assertThat(clusters, HasLength(1))
self.assertIsInstance(clusters[0], objects.Cluster)
self.assertEqual(self.context, clusters[0]._context)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_list_with_filters(self, mock_cluster_template_get):
with mock.patch.object(self.dbapi, 'get_cluster_list',
autospec=True) as mock_get_list:
mock_get_list.return_value = [self.fake_cluster]
mock_cluster_template_get.return_value = self.fake_cluster_template
filters = {'name': 'cluster1'}
clusters = objects.Cluster.list(self.context, filters=filters)
mock_get_list.assert_called_once_with(self.context, sort_key=None,
sort_dir=None,
filters=filters, limit=None,
marker=None)
self.assertEqual(1, mock_get_list.call_count)
self.assertThat(clusters, HasLength(1))
self.assertIsInstance(clusters[0], objects.Cluster)
self.assertEqual(self.context, clusters[0]._context)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_create(self, mock_cluster_template_get):
with mock.patch.object(self.dbapi, 'create_cluster',
autospec=True) as mock_create_cluster:
mock_cluster_template_get.return_value = self.fake_cluster_template
mock_create_cluster.return_value = self.fake_cluster
cluster = objects.Cluster(self.context, **self.fake_cluster)
cluster.create()
mock_create_cluster.assert_called_once_with(self.fake_cluster)
self.assertEqual(self.context, cluster._context)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_destroy(self, mock_cluster_template_get):
uuid = self.fake_cluster['uuid']
with mock.patch.object(self.dbapi, 'get_cluster_by_uuid',
autospec=True) as mock_get_cluster:
mock_get_cluster.return_value = self.fake_cluster
mock_cluster_template_get.return_value = self.fake_cluster_template
with mock.patch.object(self.dbapi, 'destroy_cluster',
autospec=True) as mock_destroy_cluster:
cluster = objects.Cluster.get_by_uuid(self.context, uuid)
cluster.destroy()
mock_get_cluster.assert_called_once_with(self.context, uuid)
mock_destroy_cluster.assert_called_once_with(uuid)
self.assertEqual(self.context, cluster._context)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_save(self, mock_cluster_template_get):
uuid = self.fake_cluster['uuid']
with mock.patch.object(self.dbapi, 'get_cluster_by_uuid',
autospec=True) as mock_get_cluster:
mock_cluster_template_get.return_value = self.fake_cluster_template
mock_get_cluster.return_value = self.fake_cluster
with mock.patch.object(self.dbapi, 'update_cluster',
autospec=True) as mock_update_cluster:
cluster = objects.Cluster.get_by_uuid(self.context, uuid)
cluster.node_count = 10
cluster.master_count = 5
cluster.save()
mock_get_cluster.assert_called_once_with(self.context, uuid)
mock_update_cluster.assert_called_once_with(
uuid, {'node_count': 10, 'master_count': 5,
'cluster_template': self.fake_cluster_template})
self.assertEqual(self.context, cluster._context)
@mock.patch('magnum.objects.ClusterTemplate.get_by_uuid')
def test_refresh(self, mock_cluster_template_get):
uuid = self.fake_cluster['uuid']
new_uuid = uuidutils.generate_uuid()
returns = [dict(self.fake_cluster, uuid=uuid),
dict(self.fake_cluster, uuid=new_uuid)]
expected = [mock.call(self.context, uuid),
mock.call(self.context, uuid)]
with mock.patch.object(self.dbapi, 'get_cluster_by_uuid',
side_effect=returns,
autospec=True) as mock_get_cluster:
mock_cluster_template_get.return_value = self.fake_cluster_template
cluster = objects.Cluster.get_by_uuid(self.context, uuid)
self.assertEqual(uuid, cluster.uuid)
cluster.refresh()
self.assertEqual(new_uuid, cluster.uuid)
self.assertEqual(expected, mock_get_cluster.call_args_list)
self.assertEqual(self.context, cluster._context)

View File

@ -17,10 +17,10 @@ from oslo_versionedobjects.tests import test_fields
from magnum.objects import fields
class TestBayStatus(test_fields.TestField):
class TestClusterStatus(test_fields.TestField):
def setUp(self):
super(TestBayStatus, self).setUp()
self.field = fields.BayStatusField()
super(TestClusterStatus, self).setUp()
self.field = fields.ClusterStatusField()
self.coerce_good_values = [('CREATE_IN_PROGRESS',
'CREATE_IN_PROGRESS'),
('CREATE_FAILED', 'CREATE_FAILED'),
@ -71,10 +71,10 @@ class TestContainerStatus(test_fields.TestField):
self.assertRaises(ValueError, self.field.stringify, 'DELETED')
class TestBayType(test_fields.TestField):
class TestClusterType(test_fields.TestField):
def setUp(self):
super(TestBayType, self).setUp()
self.field = fields.BayTypeField()
super(TestClusterType, self).setUp()
self.field = fields.ClusterTypeField()
self.coerce_good_values = [('kubernetes', 'kubernetes'),
('swarm', 'swarm'),
('mesos', 'mesos'), ]

View File

@ -362,8 +362,8 @@ class TestObject(test_base.TestCase, _TestObject):
# For more information on object version testing, read
# http://docs.openstack.org/developer/magnum/objects.html
object_data = {
'Bay': '1.8-a6109e08d32dc59d3ad100697e06d8da',
'ClusterTemplate': '1.16-29dfb88bff54a412b05f9a651f4758a6',
'Cluster': '1.9-f9838e23eef5f1a7d9606c1ccce21800',
'ClusterTemplate': '1.17-65a95ef932dd08800a83871eb3cf312b',
'Certificate': '1.1-1924dc077daa844f0f9076332ef96815',
'MyObj': '1.0-b43567e512438205e32f4e95ca616697',
'MyObj': '1.0-34c4b1aadefd177b13f9a2f894cc23cd',

View File

@ -60,51 +60,33 @@ def create_test_cluster_template(context, **kw):
return cluster_template
def get_test_bay(context, **kw):
"""Return a Bay object with appropriate attributes.
def get_test_cluster(context, **kw):
"""Return a Cluster object with appropriate attributes.
NOTE: The object leaves the attributes marked as changed, such
that a create() could be used to commit it to the DB.
"""
db_bay = db_utils.get_test_bay(**kw)
db_cluster = db_utils.get_test_cluster(**kw)
# Let DB generate ID if it isn't specified explicitly
if 'id' not in kw:
del db_bay['id']
bay = objects.Bay(context)
for key in db_bay:
setattr(bay, key, db_bay[key])
return bay
def create_test_bay(context, **kw):
"""Create and return a test bay object.
Create a bay in the DB and return a Bay object with appropriate
attributes.
"""
bay = get_test_bay(context, **kw)
create_test_cluster_template(context, uuid=bay['baymodel_id'],
coe=kw.get('coe', 'swarm'))
bay.create()
return bay
def get_test_cluster(context, **kw):
"""Return a Cluster object with appropriate attributes.
NOTE: Object model is the same for Cluster and
Bay
"""
return get_test_bay(context, **kw)
del db_cluster['id']
cluster = objects.Cluster(context)
for key in db_cluster:
setattr(cluster, key, db_cluster[key])
return cluster
def create_test_cluster(context, **kw):
"""Create and return a test cluster object.
"""Create and return a test Cluster object.
NOTE: Object model is the same for Cluster and
Bay
Create a Cluster in the DB and return a Cluster object with appropriate
attributes.
"""
return create_test_bay(context, **kw)
cluster = get_test_cluster(context, **kw)
create_test_cluster_template(context, uuid=cluster['cluster_template_id'],
coe=kw.get('coe', 'swarm'))
cluster.create()
return cluster
def get_test_x509keypair(context, **kw):

View File

@ -19,7 +19,7 @@ from magnum.common import context
from magnum.common.rpc_service import CONF
from magnum.db.sqlalchemy import api as dbapi
from magnum import objects
from magnum.objects.fields import BayStatus as bay_status
from magnum.objects.fields import ClusterStatus as cluster_status
from magnum.service import periodic
from magnum.tests import base
from magnum.tests.unit.db import utils
@ -38,7 +38,7 @@ class PeriodicTestCase(base.TestCase):
ctx = context.make_admin_context()
# Can be identical for all bays.
# Can be identical for all clusters.
trust_attrs = {
'trustee_username': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
'trustee_password': 'ain7einaebooVaig6d',
@ -46,40 +46,43 @@ class PeriodicTestCase(base.TestCase):
}
trust_attrs.update({'id': 1, 'stack_id': '11',
'status': bay_status.CREATE_IN_PROGRESS})
bay1 = utils.get_test_bay(**trust_attrs)
'status': cluster_status.CREATE_IN_PROGRESS})
cluster1 = utils.get_test_cluster(**trust_attrs)
trust_attrs.update({'id': 2, 'stack_id': '22',
'status': bay_status.DELETE_IN_PROGRESS})
bay2 = utils.get_test_bay(**trust_attrs)
'status': cluster_status.DELETE_IN_PROGRESS})
cluster2 = utils.get_test_cluster(**trust_attrs)
trust_attrs.update({'id': 3, 'stack_id': '33',
'status': bay_status.UPDATE_IN_PROGRESS})
bay3 = utils.get_test_bay(**trust_attrs)
'status': cluster_status.UPDATE_IN_PROGRESS})
cluster3 = utils.get_test_cluster(**trust_attrs)
trust_attrs.update({'id': 4, 'stack_id': '44',
'status': bay_status.CREATE_COMPLETE})
bay4 = utils.get_test_bay(**trust_attrs)
'status': cluster_status.CREATE_COMPLETE})
cluster4 = utils.get_test_cluster(**trust_attrs)
trust_attrs.update({'id': 5, 'stack_id': '55',
'status': bay_status.ROLLBACK_IN_PROGRESS})
bay5 = utils.get_test_bay(**trust_attrs)
'status': cluster_status.ROLLBACK_IN_PROGRESS})
cluster5 = utils.get_test_cluster(**trust_attrs)
self.bay1 = objects.Bay(ctx, **bay1)
self.bay2 = objects.Bay(ctx, **bay2)
self.bay3 = objects.Bay(ctx, **bay3)
self.bay4 = objects.Bay(ctx, **bay4)
self.bay5 = objects.Bay(ctx, **bay5)
self.cluster1 = objects.Cluster(ctx, **cluster1)
self.cluster2 = objects.Cluster(ctx, **cluster2)
self.cluster3 = objects.Cluster(ctx, **cluster3)
self.cluster4 = objects.Cluster(ctx, **cluster4)
self.cluster5 = objects.Cluster(ctx, **cluster5)
@mock.patch.object(objects.Bay, 'list')
@mock.patch.object(objects.Cluster, 'list')
@mock.patch('magnum.common.clients.OpenStackClients')
@mock.patch.object(dbapi.Connection, 'destroy_bay')
@mock.patch.object(dbapi.Connection, 'update_bay')
def test_sync_bay_status_changes(self, mock_db_update, mock_db_destroy,
mock_oscc, mock_bay_list):
@mock.patch.object(dbapi.Connection, 'destroy_cluster')
@mock.patch.object(dbapi.Connection, 'update_cluster')
def test_sync_cluster_status_changes(self, mock_db_update, mock_db_destroy,
mock_oscc, mock_cluster_list):
mock_heat_client = mock.MagicMock()
stack1 = fake_stack(id='11', stack_status=bay_status.CREATE_COMPLETE,
stack_status_reason='fake_reason_11')
stack3 = fake_stack(id='33', stack_status=bay_status.UPDATE_COMPLETE,
stack_status_reason='fake_reason_33')
stack5 = fake_stack(id='55', stack_status=bay_status.ROLLBACK_COMPLETE,
stack_status_reason='fake_reason_55')
stack1 = fake_stack(
id='11', stack_status=cluster_status.CREATE_COMPLETE,
stack_status_reason='fake_reason_11')
stack3 = fake_stack(
id='33', stack_status=cluster_status.UPDATE_COMPLETE,
stack_status_reason='fake_reason_33')
stack5 = fake_stack(
id='55', stack_status=cluster_status.ROLLBACK_COMPLETE,
stack_status_reason='fake_reason_55')
mock_heat_client.stacks.list.return_value = [stack1, stack3, stack5]
get_stacks = {'11': stack1, '33': stack3, '55': stack5}
@ -91,35 +94,36 @@ class PeriodicTestCase(base.TestCase):
mock_heat_client.stacks.get.side_effect = stack_get_sideefect
mock_osc = mock_oscc.return_value
mock_osc.heat.return_value = mock_heat_client
mock_bay_list.return_value = [self.bay1, self.bay2, self.bay3,
self.bay5]
mock_cluster_list.return_value = [self.cluster1, self.cluster2,
self.cluster3, self.cluster5]
mock_keystone_client = mock.MagicMock()
mock_keystone_client.client.project_id = "fake_project"
mock_osc.keystone.return_value = mock_keystone_client
periodic.MagnumPeriodicTasks(CONF).sync_bay_status(None)
periodic.MagnumPeriodicTasks(CONF).sync_cluster_status(None)
self.assertEqual(bay_status.CREATE_COMPLETE, self.bay1.status)
self.assertEqual('fake_reason_11', self.bay1.status_reason)
mock_db_destroy.assert_called_once_with(self.bay2.uuid)
self.assertEqual(bay_status.UPDATE_COMPLETE, self.bay3.status)
self.assertEqual('fake_reason_33', self.bay3.status_reason)
self.assertEqual(bay_status.ROLLBACK_COMPLETE, self.bay5.status)
self.assertEqual('fake_reason_55', self.bay5.status_reason)
self.assertEqual(cluster_status.CREATE_COMPLETE, self.cluster1.status)
self.assertEqual('fake_reason_11', self.cluster1.status_reason)
mock_db_destroy.assert_called_once_with(self.cluster2.uuid)
self.assertEqual(cluster_status.UPDATE_COMPLETE, self.cluster3.status)
self.assertEqual('fake_reason_33', self.cluster3.status_reason)
self.assertEqual(cluster_status.ROLLBACK_COMPLETE,
self.cluster5.status)
self.assertEqual('fake_reason_55', self.cluster5.status_reason)
@mock.patch.object(objects.Bay, 'list')
@mock.patch.object(objects.Cluster, 'list')
@mock.patch('magnum.common.clients.OpenStackClients')
def test_sync_auth_fail(self, mock_oscc, mock_bay_list):
"""Tests handling for unexpected exceptions in _get_bay_stacks()
def test_sync_auth_fail(self, mock_oscc, mock_cluster_list):
"""Tests handling for unexpected exceptions in _get_cluster_stacks()
It does this by raising an a HTTPUnauthorized exception in Heat client.
The affected stack thus missing from the stack list should not lead to
bay state changing in this case. Likewise, subsequent bays should still
change state, despite the affected bay being skipped.
cluster state changing in this case. Likewise, subsequent clusters
should still change state, despite the affected cluster being skipped.
"""
stack1 = fake_stack(id='11',
stack_status=bay_status.CREATE_COMPLETE)
stack_status=cluster_status.CREATE_COMPLETE)
mock_heat_client = mock.MagicMock()
@ -130,23 +134,25 @@ class PeriodicTestCase(base.TestCase):
mock_heat_client.stacks.list.return_value = [stack1]
mock_osc = mock_oscc.return_value
mock_osc.heat.return_value = mock_heat_client
mock_bay_list.return_value = [self.bay1]
periodic.MagnumPeriodicTasks(CONF).sync_bay_status(None)
mock_cluster_list.return_value = [self.cluster1]
periodic.MagnumPeriodicTasks(CONF).sync_cluster_status(None)
self.assertEqual(bay_status.CREATE_IN_PROGRESS, self.bay1.status)
self.assertEqual(cluster_status.CREATE_IN_PROGRESS,
self.cluster1.status)
@mock.patch.object(objects.Bay, 'list')
@mock.patch.object(objects.Cluster, 'list')
@mock.patch('magnum.common.clients.OpenStackClients')
def test_sync_bay_status_not_changes(self, mock_oscc, mock_bay_list):
def test_sync_cluster_status_not_changes(self, mock_oscc,
mock_cluster_list):
mock_heat_client = mock.MagicMock()
stack1 = fake_stack(id='11',
stack_status=bay_status.CREATE_IN_PROGRESS)
stack_status=cluster_status.CREATE_IN_PROGRESS)
stack2 = fake_stack(id='22',
stack_status=bay_status.DELETE_IN_PROGRESS)
stack_status=cluster_status.DELETE_IN_PROGRESS)
stack3 = fake_stack(id='33',
stack_status=bay_status.UPDATE_IN_PROGRESS)
stack_status=cluster_status.UPDATE_IN_PROGRESS)
stack5 = fake_stack(id='55',
stack_status=bay_status.ROLLBACK_IN_PROGRESS)
stack_status=cluster_status.ROLLBACK_IN_PROGRESS)
get_stacks = {'11': stack1, '22': stack2, '33': stack3, '55': stack5}
def stack_get_sideefect(arg):
@ -159,63 +165,69 @@ class PeriodicTestCase(base.TestCase):
stack5]
mock_osc = mock_oscc.return_value
mock_osc.heat.return_value = mock_heat_client
mock_bay_list.return_value = [self.bay1, self.bay2, self.bay3,
self.bay5]
periodic.MagnumPeriodicTasks(CONF).sync_bay_status(None)
mock_cluster_list.return_value = [self.cluster1, self.cluster2,
self.cluster3, self.cluster5]
periodic.MagnumPeriodicTasks(CONF).sync_cluster_status(None)
self.assertEqual(bay_status.CREATE_IN_PROGRESS, self.bay1.status)
self.assertEqual(bay_status.DELETE_IN_PROGRESS, self.bay2.status)
self.assertEqual(bay_status.UPDATE_IN_PROGRESS, self.bay3.status)
self.assertEqual(bay_status.ROLLBACK_IN_PROGRESS, self.bay5.status)
self.assertEqual(cluster_status.CREATE_IN_PROGRESS,
self.cluster1.status)
self.assertEqual(cluster_status.DELETE_IN_PROGRESS,
self.cluster2.status)
self.assertEqual(cluster_status.UPDATE_IN_PROGRESS,
self.cluster3.status)
self.assertEqual(cluster_status.ROLLBACK_IN_PROGRESS,
self.cluster5.status)
@mock.patch.object(objects.Bay, 'list')
@mock.patch.object(objects.Cluster, 'list')
@mock.patch('magnum.common.clients.OpenStackClients')
@mock.patch.object(dbapi.Connection, 'destroy_bay')
@mock.patch.object(dbapi.Connection, 'update_bay')
def test_sync_bay_status_heat_not_found(self, mock_db_update,
mock_db_destroy, mock_oscc,
mock_bay_list):
@mock.patch.object(dbapi.Connection, 'destroy_cluster')
@mock.patch.object(dbapi.Connection, 'update_cluster')
def test_sync_cluster_status_heat_not_found(self, mock_db_update,
mock_db_destroy, mock_oscc,
mock_cluster_list):
mock_heat_client = mock.MagicMock()
mock_heat_client.stacks.list.return_value = []
mock_osc = mock_oscc.return_value
mock_osc.heat.return_value = mock_heat_client
mock_bay_list.return_value = [self.bay1, self.bay2, self.bay3]
mock_cluster_list.return_value = [self.cluster1, self.cluster2,
self.cluster3]
mock_keystone_client = mock.MagicMock()
mock_keystone_client.client.project_id = "fake_project"
mock_osc.keystone.return_value = mock_keystone_client
periodic.MagnumPeriodicTasks(CONF).sync_bay_status(None)
periodic.MagnumPeriodicTasks(CONF).sync_cluster_status(None)
self.assertEqual(bay_status.CREATE_FAILED, self.bay1.status)
self.assertEqual(cluster_status.CREATE_FAILED, self.cluster1.status)
self.assertEqual('Stack with id 11 not found in Heat.',
self.bay1.status_reason)
mock_db_destroy.assert_called_once_with(self.bay2.uuid)
self.assertEqual(bay_status.UPDATE_FAILED, self.bay3.status)
self.cluster1.status_reason)
mock_db_destroy.assert_called_once_with(self.cluster2.uuid)
self.assertEqual(cluster_status.UPDATE_FAILED, self.cluster3.status)
self.assertEqual('Stack with id 33 not found in Heat.',
self.bay3.status_reason)
self.cluster3.status_reason)
@mock.patch('magnum.conductor.monitors.create_monitor')
@mock.patch('magnum.objects.Bay.list')
@mock.patch('magnum.objects.Cluster.list')
@mock.patch('magnum.common.rpc.get_notifier')
@mock.patch('magnum.common.context.make_admin_context')
def test_send_bay_metrics(self, mock_make_admin_context, mock_get_notifier,
mock_bay_list, mock_create_monitor):
def test_send_cluster_metrics(self, mock_make_admin_context,
mock_get_notifier, mock_cluster_list,
mock_create_monitor):
"""Test if RPC notifier receives the expected message"""
mock_make_admin_context.return_value = self.context
notifier = mock.MagicMock()
mock_get_notifier.return_value = notifier
mock_bay_list.return_value = [self.bay1, self.bay2, self.bay3,
self.bay4]
mock_cluster_list.return_value = [self.cluster1, self.cluster2,
self.cluster3, self.cluster4]
monitor = mock.MagicMock()
monitor.get_metric_names.return_value = ['metric1', 'metric2']
monitor.compute_metric_value.return_value = 30
monitor.get_metric_unit.return_value = '%'
mock_create_monitor.return_value = monitor
periodic.MagnumPeriodicTasks(CONF)._send_bay_metrics(self.context)
periodic.MagnumPeriodicTasks(CONF)._send_cluster_metrics(self.context)
expected_event_type = 'magnum.bay.metrics.update'
expected_event_type = 'magnum.cluster.metrics.update'
expected_metrics = [
{
'name': 'metric1',
@ -229,9 +241,9 @@ class PeriodicTestCase(base.TestCase):
},
]
expected_msg = {
'user_id': self.bay4.user_id,
'project_id': self.bay4.project_id,
'resource_id': self.bay4.uuid,
'user_id': self.cluster4.user_id,
'project_id': self.cluster4.project_id,
'resource_id': self.cluster4.uuid,
'metrics': expected_metrics
}
@ -240,29 +252,29 @@ class PeriodicTestCase(base.TestCase):
self.context, expected_event_type, expected_msg)
@mock.patch('magnum.conductor.monitors.create_monitor')
@mock.patch('magnum.objects.Bay.list')
@mock.patch('magnum.objects.Cluster.list')
@mock.patch('magnum.common.rpc.get_notifier')
@mock.patch('magnum.common.context.make_admin_context')
def test_send_bay_metrics_compute_metric_raise(
self, mock_make_admin_context, mock_get_notifier, mock_bay_list,
mock_create_monitor):
def test_send_cluster_metrics_compute_metric_raise(
self, mock_make_admin_context, mock_get_notifier,
mock_cluster_list, mock_create_monitor):
mock_make_admin_context.return_value = self.context
notifier = mock.MagicMock()
mock_get_notifier.return_value = notifier
mock_bay_list.return_value = [self.bay4]
mock_cluster_list.return_value = [self.cluster4]
monitor = mock.MagicMock()
monitor.get_metric_names.return_value = ['metric1', 'metric2']
monitor.compute_metric_value.side_effect = Exception(
"error on computing metric")
mock_create_monitor.return_value = monitor
periodic.MagnumPeriodicTasks(CONF)._send_bay_metrics(self.context)
periodic.MagnumPeriodicTasks(CONF)._send_cluster_metrics(self.context)
expected_event_type = 'magnum.bay.metrics.update'
expected_event_type = 'magnum.cluster.metrics.update'
expected_msg = {
'user_id': self.bay4.user_id,
'project_id': self.bay4.project_id,
'resource_id': self.bay4.uuid,
'user_id': self.cluster4.user_id,
'project_id': self.cluster4.project_id,
'resource_id': self.cluster4.uuid,
'metrics': []
}
self.assertEqual(1, mock_create_monitor.call_count)
@ -270,39 +282,39 @@ class PeriodicTestCase(base.TestCase):
self.context, expected_event_type, expected_msg)
@mock.patch('magnum.conductor.monitors.create_monitor')
@mock.patch('magnum.objects.Bay.list')
@mock.patch('magnum.objects.Cluster.list')
@mock.patch('magnum.common.rpc.get_notifier')
@mock.patch('magnum.common.context.make_admin_context')
def test_send_bay_metrics_pull_data_raise(
self, mock_make_admin_context, mock_get_notifier, mock_bay_list,
mock_create_monitor):
def test_send_cluster_metrics_pull_data_raise(
self, mock_make_admin_context, mock_get_notifier,
mock_cluster_list, mock_create_monitor):
mock_make_admin_context.return_value = self.context
notifier = mock.MagicMock()
mock_get_notifier.return_value = notifier
mock_bay_list.return_value = [self.bay4]
mock_cluster_list.return_value = [self.cluster4]
monitor = mock.MagicMock()
monitor.pull_data.side_effect = Exception("error on pulling data")
mock_create_monitor.return_value = monitor
periodic.MagnumPeriodicTasks(CONF)._send_bay_metrics(self.context)
periodic.MagnumPeriodicTasks(CONF)._send_cluster_metrics(self.context)
self.assertEqual(1, mock_create_monitor.call_count)
self.assertEqual(0, notifier.info.call_count)
@mock.patch('magnum.conductor.monitors.create_monitor')
@mock.patch('magnum.objects.Bay.list')
@mock.patch('magnum.objects.Cluster.list')
@mock.patch('magnum.common.rpc.get_notifier')
@mock.patch('magnum.common.context.make_admin_context')
def test_send_bay_metrics_monitor_none(
self, mock_make_admin_context, mock_get_notifier, mock_bay_list,
mock_create_monitor):
def test_send_cluster_metrics_monitor_none(
self, mock_make_admin_context, mock_get_notifier,
mock_cluster_list, mock_create_monitor):
mock_make_admin_context.return_value = self.context
notifier = mock.MagicMock()
mock_get_notifier.return_value = notifier
mock_bay_list.return_value = [self.bay4]
mock_cluster_list.return_value = [self.cluster4]
mock_create_monitor.return_value = None
periodic.MagnumPeriodicTasks(CONF)._send_bay_metrics(self.context)
periodic.MagnumPeriodicTasks(CONF)._send_cluster_metrics(self.context)
self.assertEqual(1, mock_create_monitor.call_count)
self.assertEqual(0, notifier.info.call_count)