cfgupgrade: Add logging module
[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 # Main program
129 if __name__ == "__main__":
130   program = os.path.basename(sys.argv[0])
131
132   # Option parsing
133   parser = optparse.OptionParser(usage="%prog [options] <config-file>")
134   parser.add_option('--dry-run', dest='dry_run',
135                     action="store_true",
136                     help="Try to do the conversion, but don't write"
137                          " output file")
138   parser.add_option(cli.FORCE_OPT)
139   parser.add_option(cli.DEBUG_OPT)
140   parser.add_option('--verbose', dest='verbose',
141                     action="store_true",
142                     help="Verbose output")
143   (options, args) = parser.parse_args()
144
145   SetupLogging()
146
147   # Option checking
148   if args:
149     cfg_file = args[0]
150   else:
151     raise Error("Configuration file not specified")
152
153   if not options.force:
154     usertext = ("%s MUST run on the master node. Is this the master"
155                 " node?" % program)
156     if not cli.AskUser(usertext):
157       sys.exit(1)
158
159   config = ReadConfig(cfg_file)
160
161   if options.verbose:
162     import pprint
163     print "Before upgrade:"
164     pprint.pprint(config)
165     print
166
167   UpdateFromVersion2To3(config)
168
169   if options.verbose:
170     print "After upgrade:"
171     pprint.pprint(config)
172     print
173
174   WriteConfig(cfg_file, config)
175
176   print "The configuration file has been updated successfully. Please run"
177   print "  gnt-cluster copyfile %s" % cfg_file
178   print "now."
179
180 # vim: set foldmethod=marker :