cfgupgrade: Add main() function
[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 import logging
37
38 from ganeti import utils
39 from ganeti import cli
40
41
42 options = None
43 args = None
44
45
46 class Error(Exception):
47   """Generic exception"""
48   pass
49
50
51 def ReadConfig(path):
52   """Reads configuration file.
53
54   """
55   f = open(path, 'r')
56   try:
57     return simplejson.load(f)
58   finally:
59     f.close()
60
61
62 def WriteConfig(path, data):
63   """Writes the configuration file.
64
65   """
66   if not options.dry_run:
67     utils.CreateBackup(path)
68
69   (fd, name) = tempfile.mkstemp(dir=os.path.dirname(path))
70   f = os.fdopen(fd, 'w')
71   try:
72     try:
73       simplejson.dump(data, f)
74       f.flush()
75       if options.dry_run:
76         os.unlink(name)
77       else:
78         os.rename(name, path)
79     except:
80       os.unlink(name)
81       raise
82   finally:
83     f.close()
84
85
86 def UpdateFromVersion2To3(cfg):
87   """Updates the configuration from version 2 to 3.
88
89   """
90   if cfg['cluster']['config_version'] != 2:
91     return
92
93   # Add port pool
94   if 'tcpudp_port_pool' not in cfg['cluster']:
95     cfg['cluster']['tcpudp_port_pool'] = []
96
97   # Add bridge settings
98   if 'default_bridge' not in cfg['cluster']:
99     cfg['cluster']['default_bridge'] = 'xen-br0'
100   for inst in cfg['instances'].values():
101     for nic in inst['nics']:
102       if 'bridge' not in nic:
103         nic['bridge'] = None
104
105   cfg['cluster']['config_version'] = 3
106
107
108 def SetupLogging():
109   """Configures the logging module.
110
111   """
112   formatter = logging.Formatter("%(asctime)s: %(message)s")
113
114   stderr_handler = logging.StreamHandler()
115   stderr_handler.setFormatter(formatter)
116   if options.debug:
117     stderr_handler.setLevel(logging.NOTSET)
118   elif options.verbose:
119     stderr_handler.setLevel(logging.INFO)
120   else:
121     stderr_handler.setLevel(logging.CRITICAL)
122
123   root_logger = logging.getLogger("")
124   root_logger.setLevel(logging.NOTSET)
125   root_logger.addHandler(stderr_handler)
126
127
128 def main():
129   """Main program.
130
131   """
132   global options, args
133
134   program = os.path.basename(sys.argv[0])
135
136   # Option parsing
137   parser = optparse.OptionParser(usage="%prog [options] <config-file>")
138   parser.add_option('--dry-run', dest='dry_run',
139                     action="store_true",
140                     help="Try to do the conversion, but don't write"
141                          " output file")
142   parser.add_option(cli.FORCE_OPT)
143   parser.add_option(cli.DEBUG_OPT)
144   parser.add_option('--verbose', dest='verbose',
145                     action="store_true",
146                     help="Verbose output")
147   (options, args) = parser.parse_args()
148
149   SetupLogging()
150
151   # Option checking
152   if args:
153     cfg_file = args[0]
154   else:
155     raise Error("Configuration file not specified")
156
157   if not options.force:
158     usertext = ("%s MUST run on the master node. Is this the master"
159                 " node?" % program)
160     if not cli.AskUser(usertext):
161       sys.exit(1)
162
163   config = ReadConfig(cfg_file)
164
165   if options.verbose:
166     import pprint
167     print "Before upgrade:"
168     pprint.pprint(config)
169     print
170
171   UpdateFromVersion2To3(config)
172
173   if options.verbose:
174     print "After upgrade:"
175     pprint.pprint(config)
176     print
177
178   WriteConfig(cfg_file, config)
179
180   print "The configuration file has been updated successfully. Please run"
181   print "  gnt-cluster copyfile %s" % cfg_file
182   print "now."
183
184
185 if __name__ == "__main__":
186   main()
187
188 # vim: set foldmethod=marker :