Uses glance to get image_id when creating a cluster
This PR uses glance to get a valid image_id when creating a cluster.
Clusters API currently checks the "image_id" column in "datastore_versions"
table, which has no valid image_id(NULL) since Victoria due to the
following code and docs change[1].
The original problem of this patch is that nova api throws BadRequest
exception with "Block Device Mapping is Invalid" message when creating
a cluster.
[1]: 1d24b65052
Task: 45004
Story: 2009982
Change-Id: I2a2932e261f47d9c8ec275bf9bd41b26983230c7
This commit is contained in:
parent
8182e3d93a
commit
2f52b2fddb
@ -260,14 +260,16 @@ class Cluster(object):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, context, name, datastore, datastore_version,
|
def create(cls, context, name, datastore, datastore_version,
|
||||||
instances, extended_properties, locality, configuration):
|
instances, extended_properties, locality, configuration,
|
||||||
|
image_id=None):
|
||||||
locality = srv_grp.ServerGroup.build_scheduler_hint(
|
locality = srv_grp.ServerGroup.build_scheduler_hint(
|
||||||
context, locality, name)
|
context, locality, name)
|
||||||
api_strategy = strategy.load_api_strategy(datastore_version.manager)
|
api_strategy = strategy.load_api_strategy(datastore_version.manager)
|
||||||
return api_strategy.cluster_class.create(context, name, datastore,
|
return api_strategy.cluster_class.create(context, name, datastore,
|
||||||
datastore_version, instances,
|
datastore_version, instances,
|
||||||
extended_properties,
|
extended_properties,
|
||||||
locality, configuration)
|
locality, configuration,
|
||||||
|
image_id)
|
||||||
|
|
||||||
def validate_cluster_available(self, valid_states=[ClusterTasks.NONE]):
|
def validate_cluster_available(self, valid_states=[ClusterTasks.NONE]):
|
||||||
if self.db_info.task_status not in valid_states:
|
if self.db_info.task_status not in valid_states:
|
||||||
@ -326,7 +328,18 @@ class Cluster(object):
|
|||||||
instance_type = instance_type.split(',')
|
instance_type = instance_type.split(',')
|
||||||
instance['instance_type'] = instance_type
|
instance['instance_type'] = instance_type
|
||||||
instances.append(instance)
|
instances.append(instance)
|
||||||
return self.grow(instances)
|
|
||||||
|
# Since Victoria, guest agent uses docker.
|
||||||
|
# Get image_id from glance if image_id in datastore_versions
|
||||||
|
# table is NULL.
|
||||||
|
image_id = self.ds_version.image_id
|
||||||
|
if not image_id:
|
||||||
|
glance_client = clients.create_glance_client(context)
|
||||||
|
image_id = common_glance.get_image_id(
|
||||||
|
glance_client, self.ds_version.image_id,
|
||||||
|
self.ds_version.image_tags)
|
||||||
|
return self.grow(instances, image_id)
|
||||||
|
|
||||||
elif action == 'shrink':
|
elif action == 'shrink':
|
||||||
context.notification = DBaaSClusterShrink(context, request=req)
|
context.notification = DBaaSClusterShrink(context, request=req)
|
||||||
instance_ids = [instance['id'] for instance in param]
|
instance_ids = [instance['id'] for instance in param]
|
||||||
@ -371,7 +384,7 @@ class Cluster(object):
|
|||||||
else:
|
else:
|
||||||
raise exception.BadRequest(_("Action %s not supported") % action)
|
raise exception.BadRequest(_("Action %s not supported") % action)
|
||||||
|
|
||||||
def grow(self, instances):
|
def grow(self, instances, image_id=None):
|
||||||
raise exception.BadRequest(_("Action 'grow' not supported"))
|
raise exception.BadRequest(_("Action 'grow' not supported"))
|
||||||
|
|
||||||
def shrink(self, instance_ids):
|
def shrink(self, instance_ids):
|
||||||
|
@ -20,7 +20,9 @@ from trove.cluster import models
|
|||||||
from trove.cluster import views
|
from trove.cluster import views
|
||||||
from trove.common import apischema
|
from trove.common import apischema
|
||||||
from trove.common import cfg
|
from trove.common import cfg
|
||||||
|
from trove.common import clients
|
||||||
from trove.common import exception
|
from trove.common import exception
|
||||||
|
from trove.common import glance as common_glance
|
||||||
from trove.common.i18n import _
|
from trove.common.i18n import _
|
||||||
from trove.common import notification
|
from trove.common import notification
|
||||||
from trove.common.notification import StartNotification
|
from trove.common.notification import StartNotification
|
||||||
@ -172,6 +174,16 @@ class ClusterController(wsgi.Controller):
|
|||||||
datastore, datastore_version = (
|
datastore, datastore_version = (
|
||||||
datastore_models.get_datastore_version(**datastore_args))
|
datastore_models.get_datastore_version(**datastore_args))
|
||||||
|
|
||||||
|
# Since Victoria, guest agent uses docker.
|
||||||
|
# Get image_id from glance if image_id in datastore_versions table
|
||||||
|
# is NULL.
|
||||||
|
image_id = None
|
||||||
|
if not datastore_version.image_id:
|
||||||
|
glance_client = clients.create_glance_client(context)
|
||||||
|
image_id = common_glance.get_image_id(
|
||||||
|
glance_client, datastore_version.image_id,
|
||||||
|
datastore_version.image_tags)
|
||||||
|
|
||||||
extended_properties = body['cluster'].get('extended_properties', {})
|
extended_properties = body['cluster'].get('extended_properties', {})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -228,7 +240,8 @@ class ClusterController(wsgi.Controller):
|
|||||||
cluster = models.Cluster.create(context, name, datastore,
|
cluster = models.Cluster.create(context, name, datastore,
|
||||||
datastore_version, instances,
|
datastore_version, instances,
|
||||||
extended_properties,
|
extended_properties,
|
||||||
locality, configuration)
|
locality, configuration,
|
||||||
|
image_id)
|
||||||
cluster.locality = locality
|
cluster.locality = locality
|
||||||
view = views.load_view(cluster, req=req, load_servers=False)
|
view = views.load_view(cluster, req=req, load_servers=False)
|
||||||
return wsgi.Result(view.data(), 200)
|
return wsgi.Result(view.data(), 200)
|
||||||
|
@ -81,7 +81,8 @@ class CassandraCluster(models.Cluster):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, context, name, datastore, datastore_version,
|
def create(cls, context, name, datastore, datastore_version,
|
||||||
instances, extended_properties, locality, configuration):
|
instances, extended_properties, locality, configuration,
|
||||||
|
image_id=None):
|
||||||
LOG.debug("Processing a request for creating a new cluster.")
|
LOG.debug("Processing a request for creating a new cluster.")
|
||||||
|
|
||||||
# Updating Cluster Task.
|
# Updating Cluster Task.
|
||||||
|
@ -78,7 +78,7 @@ class GaleraCommonCluster(cluster_models.Cluster):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def _create_instances(context, db_info, datastore, datastore_version,
|
def _create_instances(context, db_info, datastore, datastore_version,
|
||||||
instances, extended_properties, locality,
|
instances, extended_properties, locality,
|
||||||
configuration_id):
|
configuration_id, image_id):
|
||||||
member_config = {"id": db_info.id,
|
member_config = {"id": db_info.id,
|
||||||
"instance_type": "member"}
|
"instance_type": "member"}
|
||||||
name_index = int(time.time())
|
name_index = int(time.time())
|
||||||
@ -91,7 +91,8 @@ class GaleraCommonCluster(cluster_models.Cluster):
|
|||||||
return [Instance.create(context,
|
return [Instance.create(context,
|
||||||
instance['name'],
|
instance['name'],
|
||||||
instance['flavor_id'],
|
instance['flavor_id'],
|
||||||
datastore_version.image_id,
|
datastore_version.image_id
|
||||||
|
if datastore_version.image_id else image_id,
|
||||||
[], [],
|
[], [],
|
||||||
datastore, datastore_version,
|
datastore, datastore_version,
|
||||||
instance.get('volume_size', None),
|
instance.get('volume_size', None),
|
||||||
@ -111,7 +112,8 @@ class GaleraCommonCluster(cluster_models.Cluster):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, context, name, datastore, datastore_version,
|
def create(cls, context, name, datastore, datastore_version,
|
||||||
instances, extended_properties, locality, configuration):
|
instances, extended_properties, locality, configuration,
|
||||||
|
image_id=None):
|
||||||
LOG.debug("Initiating Galera cluster creation.")
|
LOG.debug("Initiating Galera cluster creation.")
|
||||||
ds_conf = CONF.get(datastore_version.manager)
|
ds_conf = CONF.get(datastore_version.manager)
|
||||||
# Check number of instances is at least min_cluster_member_count
|
# Check number of instances is at least min_cluster_member_count
|
||||||
@ -129,7 +131,7 @@ class GaleraCommonCluster(cluster_models.Cluster):
|
|||||||
|
|
||||||
cls._create_instances(context, db_info, datastore, datastore_version,
|
cls._create_instances(context, db_info, datastore, datastore_version,
|
||||||
instances, extended_properties, locality,
|
instances, extended_properties, locality,
|
||||||
configuration)
|
configuration, image_id)
|
||||||
|
|
||||||
# Calling taskmanager to further proceed for cluster-configuration
|
# Calling taskmanager to further proceed for cluster-configuration
|
||||||
task_api.load(context, datastore_version.manager).create_cluster(
|
task_api.load(context, datastore_version.manager).create_cluster(
|
||||||
@ -137,7 +139,7 @@ class GaleraCommonCluster(cluster_models.Cluster):
|
|||||||
|
|
||||||
return cls(context, db_info, datastore, datastore_version)
|
return cls(context, db_info, datastore, datastore_version)
|
||||||
|
|
||||||
def grow(self, instances):
|
def grow(self, instances, image_id=None):
|
||||||
LOG.debug("Growing cluster %s.", self.id)
|
LOG.debug("Growing cluster %s.", self.id)
|
||||||
|
|
||||||
self.validate_cluster_available()
|
self.validate_cluster_available()
|
||||||
@ -156,7 +158,7 @@ class GaleraCommonCluster(cluster_models.Cluster):
|
|||||||
configuration_id = self.db_info.configuration_id
|
configuration_id = self.db_info.configuration_id
|
||||||
new_instances = self._create_instances(
|
new_instances = self._create_instances(
|
||||||
context, db_info, datastore, datastore_version, instances,
|
context, db_info, datastore, datastore_version, instances,
|
||||||
None, locality, configuration_id)
|
None, locality, configuration_id, image_id)
|
||||||
|
|
||||||
task_api.load(context, datastore_version.manager).grow_cluster(
|
task_api.load(context, datastore_version.manager).grow_cluster(
|
||||||
db_info.id, [instance.id for instance in new_instances])
|
db_info.id, [instance.id for instance in new_instances])
|
||||||
|
@ -58,7 +58,8 @@ class MongoDbCluster(models.Cluster):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, context, name, datastore, datastore_version,
|
def create(cls, context, name, datastore, datastore_version,
|
||||||
instances, extended_properties, locality, configuration):
|
instances, extended_properties, locality, configuration,
|
||||||
|
image_id=None):
|
||||||
|
|
||||||
if configuration:
|
if configuration:
|
||||||
raise exception.ConfigurationNotSupported()
|
raise exception.ConfigurationNotSupported()
|
||||||
|
@ -103,7 +103,8 @@ class RedisCluster(models.Cluster):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, context, name, datastore, datastore_version,
|
def create(cls, context, name, datastore, datastore_version,
|
||||||
instances, extended_properties, locality, configuration):
|
instances, extended_properties, locality, configuration,
|
||||||
|
image_id=None):
|
||||||
LOG.debug("Initiating cluster creation.")
|
LOG.debug("Initiating cluster creation.")
|
||||||
|
|
||||||
if configuration:
|
if configuration:
|
||||||
|
@ -134,7 +134,8 @@ class VerticaCluster(models.Cluster):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, context, name, datastore, datastore_version,
|
def create(cls, context, name, datastore, datastore_version,
|
||||||
instances, extended_properties, locality, configuration):
|
instances, extended_properties, locality, configuration,
|
||||||
|
image_id=None):
|
||||||
LOG.debug("Initiating cluster creation.")
|
LOG.debug("Initiating cluster creation.")
|
||||||
|
|
||||||
if configuration:
|
if configuration:
|
||||||
|
@ -244,7 +244,7 @@ class TestClusterController(trove_testtools.TestCase):
|
|||||||
mock_cluster_create.assert_called_with(context, 'products',
|
mock_cluster_create.assert_called_with(context, 'products',
|
||||||
datastore, datastore_version,
|
datastore, datastore_version,
|
||||||
instances, {},
|
instances, {},
|
||||||
self.locality, None)
|
self.locality, None, None)
|
||||||
|
|
||||||
@patch.object(Cluster, 'load')
|
@patch.object(Cluster, 'load')
|
||||||
def test_show_cluster(self,
|
def test_show_cluster(self,
|
||||||
|
@ -159,7 +159,7 @@ class TestClusterController(trove_testtools.TestCase):
|
|||||||
self.controller.create(req, body, tenant_id)
|
self.controller.create(req, body, tenant_id)
|
||||||
mock_cluster_create.assert_called_with(context, 'products',
|
mock_cluster_create.assert_called_with(context, 'products',
|
||||||
datastore, datastore_version,
|
datastore, datastore_version,
|
||||||
instances, {}, None, None)
|
instances, {}, None, None, None)
|
||||||
|
|
||||||
@patch.object(Cluster, 'load')
|
@patch.object(Cluster, 'load')
|
||||||
def test_show_cluster(self,
|
def test_show_cluster(self,
|
||||||
|
@ -196,7 +196,7 @@ class TestClusterController(trove_testtools.TestCase):
|
|||||||
self.controller.create(req, body, tenant_id)
|
self.controller.create(req, body, tenant_id)
|
||||||
mock_cluster_create.assert_called_with(context, 'products',
|
mock_cluster_create.assert_called_with(context, 'products',
|
||||||
datastore, datastore_version,
|
datastore, datastore_version,
|
||||||
instances, {}, None, None)
|
instances, {}, None, None, None)
|
||||||
|
|
||||||
@patch.object(Cluster, 'load')
|
@patch.object(Cluster, 'load')
|
||||||
def test_show_cluster(self,
|
def test_show_cluster(self,
|
||||||
|
@ -159,7 +159,7 @@ class TestClusterController(trove_testtools.TestCase):
|
|||||||
self.controller.create(req, body, tenant_id)
|
self.controller.create(req, body, tenant_id)
|
||||||
mock_cluster_create.assert_called_with(context, 'products',
|
mock_cluster_create.assert_called_with(context, 'products',
|
||||||
datastore, datastore_version,
|
datastore, datastore_version,
|
||||||
instances, {}, None, None)
|
instances, {}, None, None, None)
|
||||||
|
|
||||||
@patch.object(Cluster, 'load')
|
@patch.object(Cluster, 'load')
|
||||||
def test_show_cluster(self,
|
def test_show_cluster(self,
|
||||||
|
Loading…
Reference in New Issue
Block a user