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:
Hirotaka Wakabayashi 2022-04-22 13:41:05 +09:00
parent 8182e3d93a
commit 2f52b2fddb
11 changed files with 51 additions and 19 deletions

View File

@ -260,14 +260,16 @@ class Cluster(object):
@classmethod
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(
context, locality, name)
api_strategy = strategy.load_api_strategy(datastore_version.manager)
return api_strategy.cluster_class.create(context, name, datastore,
datastore_version, instances,
extended_properties,
locality, configuration)
locality, configuration,
image_id)
def validate_cluster_available(self, valid_states=[ClusterTasks.NONE]):
if self.db_info.task_status not in valid_states:
@ -326,7 +328,18 @@ class Cluster(object):
instance_type = instance_type.split(',')
instance['instance_type'] = instance_type
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':
context.notification = DBaaSClusterShrink(context, request=req)
instance_ids = [instance['id'] for instance in param]
@ -371,7 +384,7 @@ class Cluster(object):
else:
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"))
def shrink(self, instance_ids):

View File

@ -20,7 +20,9 @@ from trove.cluster import models
from trove.cluster import views
from trove.common import apischema
from trove.common import cfg
from trove.common import clients
from trove.common import exception
from trove.common import glance as common_glance
from trove.common.i18n import _
from trove.common import notification
from trove.common.notification import StartNotification
@ -172,6 +174,16 @@ class ClusterController(wsgi.Controller):
datastore, datastore_version = (
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', {})
try:
@ -228,7 +240,8 @@ class ClusterController(wsgi.Controller):
cluster = models.Cluster.create(context, name, datastore,
datastore_version, instances,
extended_properties,
locality, configuration)
locality, configuration,
image_id)
cluster.locality = locality
view = views.load_view(cluster, req=req, load_servers=False)
return wsgi.Result(view.data(), 200)

View File

@ -81,7 +81,8 @@ class CassandraCluster(models.Cluster):
@classmethod
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.")
# Updating Cluster Task.

View File

@ -78,7 +78,7 @@ class GaleraCommonCluster(cluster_models.Cluster):
@staticmethod
def _create_instances(context, db_info, datastore, datastore_version,
instances, extended_properties, locality,
configuration_id):
configuration_id, image_id):
member_config = {"id": db_info.id,
"instance_type": "member"}
name_index = int(time.time())
@ -91,7 +91,8 @@ class GaleraCommonCluster(cluster_models.Cluster):
return [Instance.create(context,
instance['name'],
instance['flavor_id'],
datastore_version.image_id,
datastore_version.image_id
if datastore_version.image_id else image_id,
[], [],
datastore, datastore_version,
instance.get('volume_size', None),
@ -111,7 +112,8 @@ class GaleraCommonCluster(cluster_models.Cluster):
@classmethod
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.")
ds_conf = CONF.get(datastore_version.manager)
# 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,
instances, extended_properties, locality,
configuration)
configuration, image_id)
# Calling taskmanager to further proceed for cluster-configuration
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)
def grow(self, instances):
def grow(self, instances, image_id=None):
LOG.debug("Growing cluster %s.", self.id)
self.validate_cluster_available()
@ -156,7 +158,7 @@ class GaleraCommonCluster(cluster_models.Cluster):
configuration_id = self.db_info.configuration_id
new_instances = self._create_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(
db_info.id, [instance.id for instance in new_instances])

View File

@ -58,7 +58,8 @@ class MongoDbCluster(models.Cluster):
@classmethod
def create(cls, context, name, datastore, datastore_version,
instances, extended_properties, locality, configuration):
instances, extended_properties, locality, configuration,
image_id=None):
if configuration:
raise exception.ConfigurationNotSupported()

View File

@ -103,7 +103,8 @@ class RedisCluster(models.Cluster):
@classmethod
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.")
if configuration:

View File

@ -134,7 +134,8 @@ class VerticaCluster(models.Cluster):
@classmethod
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.")
if configuration:

View File

@ -244,7 +244,7 @@ class TestClusterController(trove_testtools.TestCase):
mock_cluster_create.assert_called_with(context, 'products',
datastore, datastore_version,
instances, {},
self.locality, None)
self.locality, None, None)
@patch.object(Cluster, 'load')
def test_show_cluster(self,

View File

@ -159,7 +159,7 @@ class TestClusterController(trove_testtools.TestCase):
self.controller.create(req, body, tenant_id)
mock_cluster_create.assert_called_with(context, 'products',
datastore, datastore_version,
instances, {}, None, None)
instances, {}, None, None, None)
@patch.object(Cluster, 'load')
def test_show_cluster(self,

View File

@ -196,7 +196,7 @@ class TestClusterController(trove_testtools.TestCase):
self.controller.create(req, body, tenant_id)
mock_cluster_create.assert_called_with(context, 'products',
datastore, datastore_version,
instances, {}, None, None)
instances, {}, None, None, None)
@patch.object(Cluster, 'load')
def test_show_cluster(self,

View File

@ -159,7 +159,7 @@ class TestClusterController(trove_testtools.TestCase):
self.controller.create(req, body, tenant_id)
mock_cluster_create.assert_called_with(context, 'products',
datastore, datastore_version,
instances, {}, None, None)
instances, {}, None, None, None)
@patch.object(Cluster, 'load')
def test_show_cluster(self,