Merge lp:~rackspace-titan/nova/postgres-instance-type-id into lp:~hudson-openstack/nova/trunk

Proposed by Mark Washenberger
Status: Merged
Approved by: Dan Prince
Approved revision: 1045
Merged at revision: 1080
Proposed branch: lp:~rackspace-titan/nova/postgres-instance-type-id
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 84 lines (+69/-1)
2 files modified
nova/db/sqlalchemy/migrate_repo/versions/017_make_instance_type_id_an_integer.py (+68/-0)
nova/db/sqlalchemy/models.py (+1/-1)
To merge this branch: bzr merge lp:~rackspace-titan/nova/postgres-instance-type-id
Reviewer Review Type Date Requested Status
Dan Prince (community) Approve
Rick Harris (community) Approve
Review via email: mp+60859@code.launchpad.net

Description of the change

Convert instance_type_ids in the instances table from strings to integers to enable joins with instance_types. This in particular fixes a problem when using postgresql.

To post a comment you must log in.
Revision history for this message
Rick Harris (rconradharris) wrote :

Looks great.

Tested upgrade and downgrade paths with good and bad data. All worked as expected.

Just a thought:

Would it be useful to log at the error-level any instances that weren't properly converted over, e.g.

  LOG.error("Instance %s did not have instance_type_id converted to an int because its value is" % (instance.id, instance.instance_type_id))

review: Approve
Revision history for this message
Dan Prince (dan-prince) wrote :

So hey Mark. Kind of unfortunate Postgres doesn't cast this automatically within the alter table command. I just tinkered with a simple Postgres table and I have to do something like this to get it to work:

  ALTER TABLE instances ALTER COLUMN instance_type_id TYPE integer USING instance_type_id::int;

Initially I just tried a simple:

  ALTER TABLE instances ALTER COLUMN instance_type_id TYPE integer;

The second command gives a casting error.

In any case it looks like what you have done is the best we can do in terms of converting data in a database agnostic fashion.

Looks good.

review: Approve
Revision history for this message
Dan Prince (dan-prince) wrote :

Hey Mark,

Heads up. Your quote limit branch just went in so you need to bump the migration version from 016 to 017.

review: Needs Fixing
Revision history for this message
Mark Washenberger (markwash) wrote :

Bumped the version and added some error logging. Should be good to go now, although if any of the other db migrations go in before this I suppose I will have to change filenames again.

Revision history for this message
Dan Prince (dan-prince) wrote :

Hey Mark.

Looks good now.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'nova/db/sqlalchemy/migrate_repo/versions/017_make_instance_type_id_an_integer.py'
--- nova/db/sqlalchemy/migrate_repo/versions/017_make_instance_type_id_an_integer.py 1970-01-01 00:00:00 +0000
+++ nova/db/sqlalchemy/migrate_repo/versions/017_make_instance_type_id_an_integer.py 2011-05-17 16:37:31 +0000
@@ -0,0 +1,68 @@
1from sqlalchemy import Column, Integer, MetaData, String, Table
2from nova import log as logging
3
4meta = MetaData()
5
6
7def upgrade(migrate_engine):
8 meta.bind = migrate_engine
9 instances = Table('instances', meta, autoload=True,
10 autoload_with=migrate_engine)
11
12 types = {}
13 for instance in migrate_engine.execute(instances.select()):
14 if instance.instance_type_id is None:
15 types[instance.id] = None
16 continue
17 try:
18 types[instance.id] = int(instance.instance_type_id)
19 except ValueError:
20 logging.warn("Instance %s did not have instance_type_id "
21 "converted to an integer because its value is %s" %
22 (instance.id, instance.instance_type_id))
23 types[instance.id] = None
24
25 integer_column = Column('instance_type_id_int', Integer(), nullable=True)
26 string_column = instances.c.instance_type_id
27
28 integer_column.create(instances)
29 for instance_id, instance_type_id in types.iteritems():
30 update = instances.update().\
31 where(instances.c.id == instance_id).\
32 values(instance_type_id_int=instance_type_id)
33 migrate_engine.execute(update)
34
35 string_column.alter(name='instance_type_id_str')
36 integer_column.alter(name='instance_type_id')
37 string_column.drop()
38
39
40def downgrade(migrate_engine):
41 meta.bind = migrate_engine
42 instances = Table('instances', meta, autoload=True,
43 autoload_with=migrate_engine)
44
45 integer_column = instances.c.instance_type_id
46 string_column = Column('instance_type_id_str',
47 String(length=255, convert_unicode=False,
48 assert_unicode=None, unicode_error=None,
49 _warn_on_bytestring=False),
50 nullable=True)
51
52 types = {}
53 for instance in migrate_engine.execute(instances.select()):
54 if instance.instance_type_id is None:
55 types[instance.id] = None
56 else:
57 types[instance.id] = str(instance.instance_type_id)
58
59 string_column.create(instances)
60 for instance_id, instance_type_id in types.iteritems():
61 update = instances.update().\
62 where(instances.c.id == instance_id).\
63 values(instance_type_id_str=instance_type_id)
64 migrate_engine.execute(update)
65
66 integer_column.alter(name='instance_type_id_int')
67 string_column.alter(name='instance_type_id')
68 integer_column.drop()
069
=== modified file 'nova/db/sqlalchemy/models.py'
--- nova/db/sqlalchemy/models.py 2011-05-12 06:27:47 +0000
+++ nova/db/sqlalchemy/models.py 2011-05-17 16:37:31 +0000
@@ -209,7 +209,7 @@
209 hostname = Column(String(255))209 hostname = Column(String(255))
210 host = Column(String(255)) # , ForeignKey('hosts.id'))210 host = Column(String(255)) # , ForeignKey('hosts.id'))
211211
212 instance_type_id = Column(String(255))212 instance_type_id = Column(Integer)
213213
214 user_data = Column(Text)214 user_data = Column(Text)
215215