cc1  v2.1
CC1 source code docs
 All Classes Namespaces Files Functions Variables Pages
mysql_migrate.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 # @COPYRIGHT_begin
3 #
4 # Copyright [2010-2014] Institute of Nuclear Physics PAN, Krakow, Poland
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 # @COPYRIGHT_end
19 
20 # -*- coding: utf-8 -*-
21 from datetime import datetime
22 from django.core.management.base import BaseCommand
23 import sys
24 import traceback
25 from django.conf import settings
26 from django.db import connections
27 from django.db import transaction
28 from optparse import make_option
29 
30 
31 tables = {
32  'admin': {
33  'name': 'cm_admin',
34  'rename_columns': {
35  'id': 'user_id'
36  }
37  },
38  'command': {
39  'name': 'cm_command',
40  'drop_column': ['kwargs']
41  },
42  'farm': {
43  'name': 'cm_farm',
44  'drop_column': ['public_key']
45  },
46  'user': {
47  'name': 'cm_user'
48  },
49  'vm': {
50  'name': 'cm_vm',
51  'rename_columns': {
52  'save': 'save_vm',
53  'image_id': 'system_image_id'
54  },
55  },
56  'node': {
57  'name': 'cm_node',
58  'drop_column': ['interface']
59  },
60  'template': {
61  'name': 'cm_template',
62  },
63  'storage': {
64  'name': 'cm_storage',
65  },
66  'image_group': {
67  'name': 'cm_systemimagegroup',
68  }
69 }
70 
71 MCURSOR = None
72 PCURSOR = None
73 
74 
75 def mselect(query):
76  # print "MYSQL: %s" % query
77  MCURSOR.execute(query)
78  return MCURSOR.fetchall()
79 
80 
81 def pinsert(query):
82  # print "POSTGRESQL: %s" % query
83  PCURSOR.execute(query)
84 
85 
86 def pselect(query):
87  # print "POSTGRESQL: %s" % query
88  PCURSOR.execute(query)
89  return PCURSOR.fetchall()
90 
91 
92 def prepare(row):
93  nrow = []
94  for i in row:
95  if i is None:
96  nrow.append('NULL')
97  elif type(i) == long:
98  nrow.append("%d" % i)
99  else:
100  #nrow.append("E'%s'" % str(i).replace("'", "\\'"))
101  nrow.append("E'%s'" % str(i).replace("'", "\\'").decode('utf-8'))
102  return ','.join(nrow)
103 
104 
105 class Command(BaseCommand):
106  args = ''
107  help = 'Run migration from version 1.7'
108  option_list = BaseCommand.option_list + (
109  make_option('--name',
110  action='store',
111  dest='name',
112  default='cm',
113  help='MySQL database name'),
114  make_option('--password',
115  action='store',
116  dest='password',
117  default='cc1',
118  help='MySQL database password'),
119  make_option('--user',
120  action='store',
121  dest='user',
122  default='cc1',
123  help='MySQL database user'),
124  make_option('--host',
125  action='store',
126  dest='host',
127  default='127.0.0.1',
128  help='MySQL database host'),
129  make_option('--port',
130  action='store',
131  dest='port',
132  default='3306',
133  help='MySQL database port'),
134  )
135 
136  def handle(self, *args, **options):
137  sys.stdout.write('Run migration at: %s\n' % datetime.now())
138 
139  settings.DATABASES.update({
140  'mysql': {
141  'ENGINE': 'django.db.backends.mysql',
142  'NAME': options['name'],
143  'USER': options['user'],
144  'PASSWORD': options['password'],
145  'HOST': options['host'],
146  'PORT': options['port'],
147  }
148  })
149  try:
150  global MCURSOR
151  MCURSOR = connections['mysql'].cursor()
152  except Exception, e:
153  print 'Cannot connect to MySQL database: %s' % e
154  sys.exit(1)
155 
156  try:
157  global PCURSOR
158  PCURSOR = connections['default'].cursor()
159  except Exception, e:
160  print 'Cannot connect to PostgresSQL database: %s' % e
161  sys.exit(1)
162 
163  with transaction.commit_manually():
164  try:
165  # migrate table from dictionary
166  for table, desc in tables.iteritems():
167  print 'Migrate table %s' % table
168  new_table = desc.get('name') or 'cm_%s' % table
169  old_cols = [i[0] for i in mselect("describe %s;" % table)]
170  for name in desc.get('drop_column', []):
171  old_cols.remove(name)
172  new_cols = old_cols[:]
173  rename_columns = desc.get('rename_columns')
174  if rename_columns:
175  for i, c in enumerate(old_cols):
176  if c in rename_columns:
177  new_cols[i] = rename_columns[c]
178 
179  values = mselect("select %s from %s;" % (','.join(old_cols), table))
180 
181  for row in values:
182  pinsert("insert into %s(%s) values (%s);" % (new_table, ','.join(new_cols), prepare(row)))
183 
184  seq_id_table = new_table + '_id_seq'
185  if pselect("select column_name from information_schema.columns where table_name='%s' and column_name='id';" % (new_table)):
186  pinsert("select setval('%s', (select max(id) from %s));" % (seq_id_table, new_table))
187  #SELECT setval('test_id_seq', (SELECT MAX(id) from "test"));
188  # STORAGE IMAGES - 1
189  values = mselect("select id,name,description,user_id,type,disk_dev,creation_date,platform,size,access,"
190  "state,vm_id,storage_id,network_device,video_device,disk_controller,progress "
191  "from image;")
192  for row in values:
193  row = list(row)
194  row[5] = ord(row[5][2]) - 96 # changing sda to 1, sdb to 2 and so on
195  if row[4] == 0: # change image type from numeric id to django model tag
196  row[4] = 'cm.isoimage'
197  elif row[4] == 1:
198  row[4] = 'cm.storageimage'
199  elif row[4] == 2:
200  row[4] = 'cm.systemimage'
201  pinsert("insert into cm_image (id,name,description,user_id,type,disk_dev,creation_date,"
202  "platform,size,access,state,vm_id,storage_id,network_device,video_device,"
203  "disk_controller,progress) values(%s);" % prepare(row))
204  pinsert("select setval('%s', (select max(id) from %s));" % ('cm_image_id_seq', 'cm_image'))
205  # PUBLIC IP
206  values = mselect("select id, ip, user_id from public_lease;")
207  for row in values:
208  pinsert("insert into cm_publicip (id, address, user_id) values(%s);" % prepare(row))
209  pinsert("select setval('%s', (select max(id) from %s));" % ('cm_publicip_id_seq', 'cm_publicip'))
210  transaction.commit()
211  except:
212  traceback.print_exc()
213 
214  transaction.rollback()
215  print "Migration complete"
216