summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nova/compute/api.py10
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py49
-rw-r--r--nova/tests/compute/test_compute.py22
-rw-r--r--nova/tests/test_migrations.py67
4 files changed, 147 insertions, 1 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 4961827fd..a9d0a1bdd 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -508,6 +508,13 @@ class API(base.Base):
availability_zone, forced_host = self._handle_availability_zone(
availability_zone)
+ system_metadata = {}
+ instance_type_props = ['id', 'name', 'memory_mb', 'vcpus',
+ 'root_gb', 'ephemeral_gb', 'flavorid',
+ 'swap', 'rxtx_factor', 'vcpu_weight']
+ for k in instance_type_props:
+ system_metadata["instance_type_%s" % k] = instance_type[k]
+
base_options = {
'reservation_id': reservation_id,
'image_ref': image_href,
@@ -537,7 +544,8 @@ class API(base.Base):
'access_ip_v6': access_ip_v6,
'availability_zone': availability_zone,
'root_device_name': root_device_name,
- 'progress': 0}
+ 'progress': 0,
+ 'system_metadata': system_metadata}
options_from_image = self._inherit_properties_from_image(
image, auto_disk_config)
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py b/nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py
new file mode 100644
index 000000000..20e75a6eb
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py
@@ -0,0 +1,49 @@
+# Copyright 2013 IBM Corp.
+#
+# 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.
+
+from sqlalchemy import MetaData, select, Table
+
+
+def upgrade(migrate_engine):
+ meta = MetaData()
+ meta.bind = migrate_engine
+ instances = Table('instances', meta, autoload=True)
+ instance_types = Table('instance_types', meta, autoload=True)
+ sys_meta = Table('instance_system_metadata', meta, autoload=True)
+
+ # Taken from nova/compute/api.py
+ instance_type_props = ['id', 'name', 'memory_mb', 'vcpus',
+ 'root_gb', 'ephemeral_gb', 'flavorid',
+ 'swap', 'rxtx_factor', 'vcpu_weight']
+
+ select_columns = [instances.c.uuid]
+ select_columns += [getattr(instance_types.c, name)
+ for name in instance_type_props]
+
+ q = select(select_columns, from_obj=instances.join(
+ instance_types,
+ instances.c.instance_type_id == instance_types.c.id))
+
+ i = sys_meta.insert()
+ for values in q.execute():
+ for index in range(0, len(instance_type_props)):
+ i.execute({"key": "instance_type_%s" % instance_type_props[index],
+ "value": str(values[index + 1]),
+ "instance_uuid": values[0]})
+
+
+def downgrade(migration_engine):
+ # This migration only touches data, and only metadata at that. No need
+ # to go through and delete old metadata items.
+ pass
diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py
index be0f6740a..7b284779e 100644
--- a/nova/tests/compute/test_compute.py
+++ b/nova/tests/compute/test_compute.py
@@ -3785,6 +3785,28 @@ class ComputeAPITestCase(BaseTestCase):
finally:
db.instance_destroy(self.context, ref[0]['uuid'])
+ def test_create_saves_type_in_system_metadata(self):
+ instance_type = instance_types.get_default_instance_type()
+ (ref, resv_id) = self.compute_api.create(
+ self.context,
+ instance_type=instance_type,
+ image_href=None)
+ try:
+ sys_metadata = db.instance_system_metadata_get(self.context,
+ ref[0]['uuid'])
+
+ instance_type_props = ['name', 'memory_mb', 'vcpus', 'root_gb',
+ 'ephemeral_gb', 'flavorid', 'swap',
+ 'rxtx_factor', 'vcpu_weight']
+ for key in instance_type_props:
+ sys_meta_key = "instance_type_%s" % key
+ self.assertTrue(sys_meta_key in sys_metadata)
+ self.assertEqual(str(instance_type[key]),
+ str(sys_metadata[sys_meta_key]))
+
+ finally:
+ db.instance_destroy(self.context, ref[0]['uuid'])
+
def test_create_instance_associates_security_groups(self):
# Make sure create associates security groups.
group = self._create_group()
diff --git a/nova/tests/test_migrations.py b/nova/tests/test_migrations.py
index 3b67e6439..8c18d5511 100644
--- a/nova/tests/test_migrations.py
+++ b/nova/tests/test_migrations.py
@@ -24,6 +24,7 @@ properly both upgrading and downgrading, and that no data loss occurs
if possible.
"""
+import collections
import commands
import ConfigParser
import os
@@ -452,3 +453,69 @@ class TestMigrations(test.TestCase):
self.assertEqual("", volume.deleted)
volume = volumes.select(volumes.c.id == "second").execute().first()
self.assertEqual(volume.id, volume.deleted)
+
+ # migration 153, copy flavor information into system_metadata
+ def _prerun_153(self, engine):
+ fake_types = [
+ dict(id=10, name='type1', memory_mb=128, vcpus=1,
+ root_gb=10, ephemeral_gb=0, flavorid="1", swap=0,
+ rxtx_factor=1.0, vcpu_weight=1, disabled=False,
+ is_public=True),
+ dict(id=11, name='type2', memory_mb=512, vcpus=1,
+ root_gb=10, ephemeral_gb=5, flavorid="2", swap=0,
+ rxtx_factor=1.5, vcpu_weight=2, disabled=False,
+ is_public=True),
+ dict(id=12, name='type3', memory_mb=128, vcpus=1,
+ root_gb=10, ephemeral_gb=0, flavorid="3", swap=0,
+ rxtx_factor=1.0, vcpu_weight=1, disabled=False,
+ is_public=False),
+ dict(id=13, name='type4', memory_mb=128, vcpus=1,
+ root_gb=10, ephemeral_gb=0, flavorid="4", swap=0,
+ rxtx_factor=1.0, vcpu_weight=1, disabled=True,
+ is_public=True),
+ dict(id=14, name='type5', memory_mb=128, vcpus=1,
+ root_gb=10, ephemeral_gb=0, flavorid="5", swap=0,
+ rxtx_factor=1.0, vcpu_weight=1, disabled=True,
+ is_public=False),
+ ]
+
+ fake_instances = [
+ dict(uuid='m153-uuid1', instance_type_id=10),
+ dict(uuid='m153-uuid2', instance_type_id=11),
+ dict(uuid='m153-uuid3', instance_type_id=12),
+ dict(uuid='m153-uuid4', instance_type_id=13),
+ # NOTE(danms): no use of type5
+ ]
+
+ instances = get_table(engine, 'instances')
+ instance_types = get_table(engine, 'instance_types')
+ engine.execute(instance_types.insert(), fake_types)
+ engine.execute(instances.insert(), fake_instances)
+
+ return fake_types, fake_instances
+
+ def _check_153(self, engine, data):
+ fake_types, fake_instances = data
+ # NOTE(danms): Fetch all the tables and data from scratch after change
+ instances = get_table(engine, 'instances')
+ instance_types = get_table(engine, 'instance_types')
+ sys_meta = get_table(engine, 'instance_system_metadata')
+
+ # Collect all system metadata, indexed by instance_uuid
+ metadata = collections.defaultdict(dict)
+ for values in sys_meta.select().execute():
+ metadata[values['instance_uuid']][values['key']] = values['value']
+
+ # Taken from nova/compute/api.py
+ instance_type_props = ['id', 'name', 'memory_mb', 'vcpus',
+ 'root_gb', 'ephemeral_gb', 'flavorid',
+ 'swap', 'rxtx_factor', 'vcpu_weight']
+
+ for instance in fake_instances:
+ inst_sys_meta = metadata[instance['uuid']]
+ inst_type = fake_types[instance['instance_type_id'] - 10]
+ for prop in instance_type_props:
+ prop_name = 'instance_type_%s' % prop
+ self.assertIn(prop_name, inst_sys_meta)
+ self.assertEqual(str(inst_sys_meta[prop_name]),
+ str(inst_type[prop]))