Remove support for Pickle configuration files
[ganeti-local] / tools / cfgupgrade
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2007, 2008 Google Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21
22 """Tool to upgrade the configuration file.
23
24 This code handles only the types supported by simplejson. As an example, "set"
25 is a "list".
26
27 """
28
29
30 import os
31 import os.path
32 import sys
33 import optparse
34 import tempfile
35 import simplejson
36
37 from ganeti import utils
38 from ganeti import cli
39
40
41 options = None
42 args = None
43
44
45 class Error(Exception):
46   """Generic exception"""
47   pass
48
49
50 def ReadConfig(path):
51   """Reads configuration file.
52
53   """
54   f = open(path, 'r')
55   try:
56     return simplejson.load(f)
57   finally:
58     f.close()
59
60
61 def WriteConfig(path, data):
62   """Writes the configuration file.
63
64   """
65   if not options.dry_run:
66     utils.CreateBackup(path)
67
68   (fd, name) = tempfile.mkstemp(dir=os.path.dirname(path))
69   f = os.fdopen(fd, 'w')
70   try:
71     try:
72       simplejson.dump(data, f)
73       f.flush()
74       if options.dry_run:
75         os.unlink(name)
76       else:
77         os.rename(name, path)
78     except:
79       os.unlink(name)
80       raise
81   finally:
82     f.close()
83
84
85 def UpdateFromVersion2To3(cfg):
86   """Updates the configuration from version 2 to 3.
87
88   """
89   if cfg['cluster']['config_version'] != 2:
90     return
91
92   # Add port pool
93   if 'tcpudp_port_pool' not in cfg['cluster']:
94     cfg['cluster']['tcpudp_port_pool'] = []
95
96   # Add bridge settings
97   if 'default_bridge' not in cfg['cluster']:
98     cfg['cluster']['default_bridge'] = 'xen-br0'
99   for inst in cfg['instances'].values():
100     for nic in inst['nics']:
101       if 'bridge' not in nic:
102         nic['bridge'] = None
103
104   cfg['cluster']['config_version'] = 3
105
106
107 # Main program
108 if __name__ == "__main__":
109   program = os.path.basename(sys.argv[0])
110
111   # Option parsing
112   parser = optparse.OptionParser(usage="%prog [options] <config-file>")
113   parser.add_option('--dry-run', dest='dry_run',
114                     action="store_true",
115                     help="Try to do the conversion, but don't write"
116                          " output file")
117   parser.add_option(cli.FORCE_OPT)
118   parser.add_option('--verbose', dest='verbose',
119                     action="store_true",
120                     help="Verbose output")
121   (options, args) = parser.parse_args()
122
123   # Option checking
124   if args:
125     cfg_file = args[0]
126   else:
127     raise Error("Configuration file not specified")
128
129   if not options.force:
130     usertext = ("%s MUST run on the master node. Is this the master"
131                 " node?" % program)
132     if not cli.AskUser(usertext):
133       sys.exit(1)
134
135   config = ReadConfig(cfg_file)
136
137   if options.verbose:
138     import pprint
139     print "Before upgrade:"
140     pprint.pprint(config)
141     print
142
143   UpdateFromVersion2To3(config)
144
145   if options.verbose:
146     print "After upgrade:"
147     pprint.pprint(config)
148     print
149
150   WriteConfig(cfg_file, config)
151
152   print "The configuration file has been updated successfully. Please run"
153   print "  gnt-cluster copyfile %s" % cfg_file
154   print "now."
155
156 # vim: set foldmethod=marker :