instance.name should be blank if instance.id is not set

By default the ability to generate instance.name depends on the
instance.id field. However the value for this field comes from the
autoincrement id column in the instance table. This means that if the
instance has not been written to a database, as will be the case before
scheduling in cellsv2, there is no way to properly determine what the
instance name will be.

In that situation the instance name will now be returned as '' if the
vm_state and task_state match the pre-scheduled instance case. If the
instance does not have the right vm_state/task_state set an error will
be logged and the instance uuid will be returned as the name. Using uuid
matches what happens for template failures.

Change-Id: I4a743c61a619af6f91a102a219fc0ec49df19d9d
This commit is contained in:
Andrew Laski 2016-06-08 17:21:41 -04:00
parent 32076267f6
commit 4e85f1de8a
2 changed files with 35 additions and 0 deletions

View File

@ -25,6 +25,8 @@ from sqlalchemy.orm import joinedload
from nova.cells import opts as cells_opts
from nova.cells import rpcapi as cells_rpcapi
from nova.cells import utils as cells_utils
from nova.compute import task_states
from nova.compute import vm_states
from nova import db
from nova.db.sqlalchemy import api as db_api
from nova.db.sqlalchemy import models
@ -274,6 +276,21 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
base_name = CONF.instance_name_template % info
except KeyError:
base_name = self.uuid
except exception.ObjectActionError:
# This indicates self.id was not set and could not be lazy loaded.
# What this means is the instance has not been persisted to a db
# yet, which should indicate it has not been scheduled yet. In this
# situation it will have a blank name.
if (self.vm_state == vm_states.BUILDING and
self.task_state == task_states.SCHEDULING):
base_name = ''
else:
# If the vm/task states don't indicate that it's being booted
# then we have a bug here. Log an error and attempt to return
# the uuid which is what an error above would return.
LOG.error(_LE('Could not lazy-load instance.id while '
'attempting to generate the instance name.'))
base_name = self.uuid
return base_name
def _flavor_from_db(self, db_flavor):

View File

@ -23,6 +23,8 @@ from oslo_utils import timeutils
from nova.cells import rpcapi as cells_rpcapi
from nova.compute import flavors
from nova.compute import task_states
from nova.compute import vm_states
from nova import context
from nova import db
from nova import exception
@ -1192,6 +1194,22 @@ class _TestInstanceObject(object):
self.assertEqual('foo-%s' % db_inst['uuid'], inst.name)
self.assertFalse(inst.obj_attr_is_set('fault'))
def test_name_blank_if_no_id_pre_scheduling(self):
# inst.id is not set and can't be lazy loaded
inst = objects.Instance(context=self.context,
vm_state=vm_states.BUILDING,
task_state=task_states.SCHEDULING)
self.assertEqual('', inst.name)
def test_name_uuid_if_no_id_post_scheduling(self):
# inst.id is not set and can't be lazy loaded
inst = objects.Instance(context=self.context,
uuid=uuids.instance,
vm_state=vm_states.ACTIVE,
task_state=None)
self.assertEqual(uuids.instance, inst.name)
def test_from_db_object_not_overwrite_info_cache(self):
info_cache = instance_info_cache.InstanceInfoCache()
inst = objects.Instance(context=self.context,