Merge "Metadata-API fails to retrieve avz for instances created before Pike" into stable/pike
This commit is contained in:
commit
d39a4d3c2a
|
@ -668,6 +668,11 @@ class DbCommands(object):
|
|||
quotas_obj.migrate_quota_limits_to_api_db,
|
||||
# Added in Pike
|
||||
quotas_obj.migrate_quota_classes_to_api_db,
|
||||
# Added in Rocky
|
||||
# NOTE(tssurya): This online migration is going to be backported to
|
||||
# Queens and Pike since instance.avz of instances before Pike
|
||||
# need to be populated if it was not specified during boot time.
|
||||
instance_obj.populate_missing_availability_zones,
|
||||
)
|
||||
|
||||
def __init__(self):
|
||||
|
|
|
@ -25,6 +25,7 @@ from sqlalchemy.orm import joinedload
|
|||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.sql import null
|
||||
|
||||
from nova import availability_zones as avail_zone
|
||||
from nova.cells import opts as cells_opts
|
||||
from nova.cells import rpcapi as cells_rpcapi
|
||||
from nova.cells import utils as cells_utils
|
||||
|
@ -1204,6 +1205,20 @@ def _make_instance_list(context, inst_list, db_inst_list, expected_attrs):
|
|||
return inst_list
|
||||
|
||||
|
||||
@db_api.pick_context_manager_writer
|
||||
def populate_missing_availability_zones(context, count):
|
||||
instances = (context.session.query(models.Instance).
|
||||
filter_by(availability_zone=None).limit(count).all())
|
||||
count_all = len(instances)
|
||||
count_hit = 0
|
||||
for instance in instances:
|
||||
az = avail_zone.get_instance_availability_zone(context, instance)
|
||||
instance.availability_zone = az
|
||||
instance.save(context.session)
|
||||
count_hit += 1
|
||||
return count_all, count_hit
|
||||
|
||||
|
||||
@base.NovaObjectRegistry.register
|
||||
class InstanceList(base.ObjectListBase, base.NovaObject):
|
||||
# Version 2.0: Initial Version
|
||||
|
|
|
@ -10,8 +10,11 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from nova.compute import vm_states
|
||||
from nova import context
|
||||
from nova import db
|
||||
from nova import objects
|
||||
from nova import test
|
||||
|
||||
|
@ -40,3 +43,48 @@ class InstanceObjectTestCase(test.TestCase):
|
|||
self.context, self.context.project_id, self.context.user_id,
|
||||
vm_states.ACTIVE)
|
||||
self.assertEqual(1, count)
|
||||
|
||||
def test_populate_missing_availability_zones(self):
|
||||
# create two instances once with avz set and other not set.
|
||||
inst1 = self._create_instance(host="fake-host1")
|
||||
uuid1 = inst1.uuid
|
||||
inst2 = self._create_instance(availability_zone="fake",
|
||||
host="fake-host2")
|
||||
self.assertIsNone(inst1.availability_zone)
|
||||
self.assertEqual("fake", inst2.availability_zone)
|
||||
count_all, count_hit = (objects.instance.
|
||||
populate_missing_availability_zones(self.context, 10))
|
||||
# we get only the instance whose avz was None.
|
||||
self.assertEqual(1, count_all)
|
||||
self.assertEqual(1, count_hit)
|
||||
inst1 = objects.Instance.get_by_uuid(self.context, uuid1)
|
||||
# since instance.host was None, avz is set to
|
||||
# CONF.default_availability_zone i.e 'nova' which is the default zone
|
||||
# for compute services.
|
||||
self.assertEqual('nova', inst1.availability_zone)
|
||||
|
||||
# create an instance with avz as None on a host that has avz.
|
||||
host = 'fake-host'
|
||||
agg_meta = {'name': 'az_agg', 'uuid': uuidutils.generate_uuid(),
|
||||
'metadata': {'availability_zone': 'nova-test'}}
|
||||
agg = objects.Aggregate(self.context, **agg_meta)
|
||||
agg.create()
|
||||
agg = objects.Aggregate.get_by_id(self.context, agg.id)
|
||||
values = {
|
||||
'binary': 'nova-compute',
|
||||
'host': host,
|
||||
'topic': 'compute',
|
||||
'disabled': False,
|
||||
}
|
||||
service = db.service_create(self.context, values)
|
||||
agg.add_host(service['host'])
|
||||
inst3 = self._create_instance(host=host)
|
||||
uuid3 = inst3.uuid
|
||||
self.assertIsNone(inst3.availability_zone)
|
||||
count_all, count_hit = (objects.instance.
|
||||
populate_missing_availability_zones(self.context, 10))
|
||||
# we get only the instance whose avz was None i.e inst3.
|
||||
self.assertEqual(1, count_all)
|
||||
self.assertEqual(1, count_hit)
|
||||
inst3 = objects.Instance.get_by_uuid(self.context, uuid3)
|
||||
self.assertEqual('nova-test', inst3.availability_zone)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
upgrade:
|
||||
- |
|
||||
A new online data migration has been added to populate missing
|
||||
instance.availability_zone values for instances older than Pike whose
|
||||
availability_zone was not specified during boot time. This can be run
|
||||
during the normal ``nova-manage db online_data_migrations`` routine.
|
||||
This fixes `Bug 1768876`_
|
||||
|
||||
.. _Bug 1768876: https://bugs.launchpad.net/nova/+bug/1768876
|
Loading…
Reference in New Issue