Statistics
| Branch: | Tag: | Revision:

root / tools / cfgupgrade @ aeb0c953

History | View | Annotate | Download (6.3 kB)

1 0006af7d Michael Hanselmann
#!/usr/bin/python
2 0006af7d Michael Hanselmann
#
3 0006af7d Michael Hanselmann
4 a421fdeb Iustin Pop
# Copyright (C) 2007, 2008, 2009 Google Inc.
5 0006af7d Michael Hanselmann
#
6 0006af7d Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 0006af7d Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 0006af7d Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 0006af7d Michael Hanselmann
# (at your option) any later version.
10 0006af7d Michael Hanselmann
#
11 0006af7d Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 0006af7d Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 0006af7d Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 0006af7d Michael Hanselmann
# General Public License for more details.
15 0006af7d Michael Hanselmann
#
16 0006af7d Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 0006af7d Michael Hanselmann
# along with this program; if not, write to the Free Software
18 0006af7d Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 0006af7d Michael Hanselmann
# 02110-1301, USA.
20 0006af7d Michael Hanselmann
21 0006af7d Michael Hanselmann
22 0006af7d Michael Hanselmann
"""Tool to upgrade the configuration file.
23 0006af7d Michael Hanselmann
24 a421fdeb Iustin Pop
This code handles only the types supported by simplejson. As an
25 a421fdeb Iustin Pop
example, 'set' is a 'list'.
26 0006af7d Michael Hanselmann
27 0006af7d Michael Hanselmann
"""
28 0006af7d Michael Hanselmann
29 0006af7d Michael Hanselmann
30 0006af7d Michael Hanselmann
import os
31 0006af7d Michael Hanselmann
import os.path
32 0006af7d Michael Hanselmann
import sys
33 0006af7d Michael Hanselmann
import optparse
34 eda37a5a Michael Hanselmann
import logging
35 95e4a814 Michael Hanselmann
import errno
36 0006af7d Michael Hanselmann
37 95e4a814 Michael Hanselmann
from ganeti import constants
38 95e4a814 Michael Hanselmann
from ganeti import serializer
39 319856a9 Michael Hanselmann
from ganeti import utils
40 f97c7901 Michael Hanselmann
from ganeti import cli
41 a421fdeb Iustin Pop
from ganeti import bootstrap
42 ac4d25b6 Iustin Pop
from ganeti import config
43 0006af7d Michael Hanselmann
44 0006af7d Michael Hanselmann
45 319856a9 Michael Hanselmann
options = None
46 319856a9 Michael Hanselmann
args = None
47 0006af7d Michael Hanselmann
48 ac4d25b6 Iustin Pop
# Dictionary with instance old keys, and new hypervisor keys
49 ac4d25b6 Iustin Pop
INST_HV_CHG = {
50 ac4d25b6 Iustin Pop
  'hvm_pae': constants.HV_PAE,
51 ac4d25b6 Iustin Pop
  'vnc_bind_address': constants.HV_VNC_BIND_ADDRESS,
52 ac4d25b6 Iustin Pop
  'initrd_path': constants.HV_INITRD_PATH,
53 ac4d25b6 Iustin Pop
  'hvm_nic_type': constants.HV_NIC_TYPE,
54 ac4d25b6 Iustin Pop
  'kernel_path': constants.HV_KERNEL_PATH,
55 ac4d25b6 Iustin Pop
  'hvm_acpi': constants.HV_ACPI,
56 ac4d25b6 Iustin Pop
  'hvm_cdrom_image_path': constants.HV_CDROM_IMAGE_PATH,
57 ac4d25b6 Iustin Pop
  'hvm_boot_order': constants.HV_BOOT_ORDER,
58 ac4d25b6 Iustin Pop
  'hvm_disk_type': constants.HV_DISK_TYPE,
59 ac4d25b6 Iustin Pop
  }
60 ac4d25b6 Iustin Pop
61 ac4d25b6 Iustin Pop
# Instance beparams changes
62 ac4d25b6 Iustin Pop
INST_BE_CHG = {
63 ac4d25b6 Iustin Pop
  'vcpus': constants.BE_VCPUS,
64 ac4d25b6 Iustin Pop
  'memory': constants.BE_MEMORY,
65 ac4d25b6 Iustin Pop
  'auto_balance': constants.BE_AUTO_BALANCE,
66 ac4d25b6 Iustin Pop
  }
67 0006af7d Michael Hanselmann
68 6f285030 Iustin Pop
# Field names
69 6f285030 Iustin Pop
F_SERIAL = 'serial_no'
70 6f285030 Iustin Pop
71 6f285030 Iustin Pop
72 319856a9 Michael Hanselmann
class Error(Exception):
73 319856a9 Michael Hanselmann
  """Generic exception"""
74 319856a9 Michael Hanselmann
  pass
75 0006af7d Michael Hanselmann
76 0006af7d Michael Hanselmann
77 eda37a5a Michael Hanselmann
def SetupLogging():
78 eda37a5a Michael Hanselmann
  """Configures the logging module.
79 eda37a5a Michael Hanselmann
80 eda37a5a Michael Hanselmann
  """
81 eda37a5a Michael Hanselmann
  formatter = logging.Formatter("%(asctime)s: %(message)s")
82 eda37a5a Michael Hanselmann
83 eda37a5a Michael Hanselmann
  stderr_handler = logging.StreamHandler()
84 eda37a5a Michael Hanselmann
  stderr_handler.setFormatter(formatter)
85 eda37a5a Michael Hanselmann
  if options.debug:
86 eda37a5a Michael Hanselmann
    stderr_handler.setLevel(logging.NOTSET)
87 eda37a5a Michael Hanselmann
  elif options.verbose:
88 eda37a5a Michael Hanselmann
    stderr_handler.setLevel(logging.INFO)
89 eda37a5a Michael Hanselmann
  else:
90 eda37a5a Michael Hanselmann
    stderr_handler.setLevel(logging.CRITICAL)
91 eda37a5a Michael Hanselmann
92 eda37a5a Michael Hanselmann
  root_logger = logging.getLogger("")
93 eda37a5a Michael Hanselmann
  root_logger.setLevel(logging.NOTSET)
94 eda37a5a Michael Hanselmann
  root_logger.addHandler(stderr_handler)
95 eda37a5a Michael Hanselmann
96 eda37a5a Michael Hanselmann
97 6d691282 Michael Hanselmann
def main():
98 6d691282 Michael Hanselmann
  """Main program.
99 6d691282 Michael Hanselmann
100 6d691282 Michael Hanselmann
  """
101 6d691282 Michael Hanselmann
  global options, args
102 6d691282 Michael Hanselmann
103 319856a9 Michael Hanselmann
  program = os.path.basename(sys.argv[0])
104 319856a9 Michael Hanselmann
105 0006af7d Michael Hanselmann
  # Option parsing
106 95e4a814 Michael Hanselmann
  parser = optparse.OptionParser(usage="%prog [--debug|--verbose] [--force]")
107 60edf71e Michael Hanselmann
  parser.add_option('--dry-run', dest='dry_run',
108 60edf71e Michael Hanselmann
                    action="store_true",
109 f4bc1f2c Michael Hanselmann
                    help="Try to do the conversion, but don't write"
110 f4bc1f2c Michael Hanselmann
                         " output file")
111 f97c7901 Michael Hanselmann
  parser.add_option(cli.FORCE_OPT)
112 eda37a5a Michael Hanselmann
  parser.add_option(cli.DEBUG_OPT)
113 9cdb9578 Iustin Pop
  parser.add_option(cli.VERBOSE_OPT)
114 ac4d25b6 Iustin Pop
  parser.add_option('--path', help="Convert configuration in this"
115 ac4d25b6 Iustin Pop
                    " directory instead of '%s'" % constants.DATA_DIR,
116 ac4d25b6 Iustin Pop
                    default=constants.DATA_DIR, dest="data_dir")
117 0006af7d Michael Hanselmann
  (options, args) = parser.parse_args()
118 0006af7d Michael Hanselmann
119 ac4d25b6 Iustin Pop
  # We need to keep filenames locally because they might be renamed between
120 ac4d25b6 Iustin Pop
  # versions.
121 ac4d25b6 Iustin Pop
  options.CONFIG_DATA_PATH = options.data_dir + "/config.data"
122 ac4d25b6 Iustin Pop
  options.SERVER_PEM_PATH = options.data_dir + "/server.pem"
123 ac4d25b6 Iustin Pop
  options.KNOWN_HOSTS_PATH = options.data_dir + "/known_hosts"
124 ac4d25b6 Iustin Pop
  options.RAPI_CERT_FILE = options.data_dir + "/rapi.pem"
125 aeb0c953 Michael Hanselmann
  options.HMAC_CLUSTER_KEY = options.data_dir + "/hmac.key"
126 ac4d25b6 Iustin Pop
127 eda37a5a Michael Hanselmann
  SetupLogging()
128 eda37a5a Michael Hanselmann
129 0006af7d Michael Hanselmann
  # Option checking
130 0006af7d Michael Hanselmann
  if args:
131 95e4a814 Michael Hanselmann
    raise Error("No arguments expected")
132 0006af7d Michael Hanselmann
133 319856a9 Michael Hanselmann
  if not options.force:
134 a421fdeb Iustin Pop
    usertext = ("%s MUST be run on the master node. Is this the master"
135 a421fdeb Iustin Pop
                " node and are ALL instances down?" % program)
136 f97c7901 Michael Hanselmann
    if not cli.AskUser(usertext):
137 319856a9 Michael Hanselmann
      sys.exit(1)
138 319856a9 Michael Hanselmann
139 95e4a814 Michael Hanselmann
  # Check whether it's a Ganeti configuration directory
140 ac4d25b6 Iustin Pop
  if not (os.path.isfile(options.CONFIG_DATA_PATH) and
141 ac4d25b6 Iustin Pop
          os.path.isfile(options.SERVER_PEM_PATH) or
142 ac4d25b6 Iustin Pop
          os.path.isfile(options.KNOWN_HOSTS_PATH)):
143 95e4a814 Michael Hanselmann
    raise Error(("%s does not seem to be a known Ganeti configuration"
144 ac4d25b6 Iustin Pop
                 " directory") % options.data_dir)
145 95e4a814 Michael Hanselmann
146 11c31f5c Michael Hanselmann
  config_data = serializer.LoadJson(utils.ReadFile(options.CONFIG_DATA_PATH))
147 a421fdeb Iustin Pop
148 11c31f5c Michael Hanselmann
  try:
149 11c31f5c Michael Hanselmann
    config_version = config_data["version"]
150 11c31f5c Michael Hanselmann
  except KeyError:
151 11c31f5c Michael Hanselmann
    raise Error("Unable to determine configuration version")
152 0006af7d Michael Hanselmann
153 11c31f5c Michael Hanselmann
  (config_major, config_minor, config_revision) = \
154 11c31f5c Michael Hanselmann
    constants.SplitVersion(config_version)
155 319856a9 Michael Hanselmann
156 11c31f5c Michael Hanselmann
  logging.info("Found configuration version %s (%d.%d.%d)",
157 11c31f5c Michael Hanselmann
               config_version, config_major, config_minor, config_revision)
158 319856a9 Michael Hanselmann
159 11c31f5c Michael Hanselmann
  if "config_version" in config_data["cluster"]:
160 11c31f5c Michael Hanselmann
    raise Error("Inconsistent configuration: found config_version in"
161 11c31f5c Michael Hanselmann
                " configuration file")
162 95e4a814 Michael Hanselmann
163 aeb0c953 Michael Hanselmann
  if config_major == 2 and config_minor == 0:
164 aeb0c953 Michael Hanselmann
    if config_revision != 0:
165 aeb0c953 Michael Hanselmann
      logging.warning("Config revision is not 0")
166 aeb0c953 Michael Hanselmann
167 aeb0c953 Michael Hanselmann
    config_data["version"] = constants.BuildVersion(2, 1, 0)
168 aeb0c953 Michael Hanselmann
169 11c31f5c Michael Hanselmann
  try:
170 11c31f5c Michael Hanselmann
    logging.info("Writing configuration file to %s", options.CONFIG_DATA_PATH)
171 11c31f5c Michael Hanselmann
    utils.WriteFile(file_name=options.CONFIG_DATA_PATH,
172 11c31f5c Michael Hanselmann
                    data=serializer.DumpJson(config_data),
173 11c31f5c Michael Hanselmann
                    mode=0600,
174 11c31f5c Michael Hanselmann
                    dry_run=options.dry_run,
175 11c31f5c Michael Hanselmann
                    backup=True)
176 a421fdeb Iustin Pop
177 a421fdeb Iustin Pop
    if not options.dry_run:
178 ac4d25b6 Iustin Pop
      if not os.path.exists(options.RAPI_CERT_FILE):
179 11c31f5c Michael Hanselmann
        logging.debug("Writing RAPI certificate to %s", options.RAPI_CERT_FILE)
180 cd34faf2 Michael Hanselmann
        bootstrap.GenerateSelfSignedSslCert(options.RAPI_CERT_FILE)
181 a421fdeb Iustin Pop
182 aeb0c953 Michael Hanselmann
      if not os.path.exists(options.HMAC_CLUSTER_KEY):
183 aeb0c953 Michael Hanselmann
        logging.debug("Writing HMAC key to %s", options.HMAC_CLUSTER_KEY)
184 aeb0c953 Michael Hanselmann
        bootstrap.GenerateHmacKey(options.HMAC_CLUSTER_KEY)
185 aeb0c953 Michael Hanselmann
186 95e4a814 Michael Hanselmann
  except:
187 11c31f5c Michael Hanselmann
    logging.critical("Writing configuration failed. It is probably in an"
188 95e4a814 Michael Hanselmann
                     " inconsistent state and needs manual intervention.")
189 95e4a814 Michael Hanselmann
    raise
190 0006af7d Michael Hanselmann
191 ac4d25b6 Iustin Pop
  # test loading the config file
192 ac4d25b6 Iustin Pop
  if not options.dry_run:
193 ac4d25b6 Iustin Pop
    logging.info("Testing the new config file...")
194 ac4d25b6 Iustin Pop
    cfg = config.ConfigWriter(cfg_file=options.CONFIG_DATA_PATH,
195 ac4d25b6 Iustin Pop
                              offline=True)
196 ac4d25b6 Iustin Pop
    # if we reached this, it's all fine
197 ac4d25b6 Iustin Pop
    vrfy = cfg.VerifyConfig()
198 ac4d25b6 Iustin Pop
    if vrfy:
199 ac4d25b6 Iustin Pop
      logging.error("Errors after conversion:")
200 ac4d25b6 Iustin Pop
      for item in vrfy:
201 ac4d25b6 Iustin Pop
        logging.error(" - %s" % item)
202 ac4d25b6 Iustin Pop
    del cfg
203 ac4d25b6 Iustin Pop
    logging.info("File loaded successfully")
204 ac4d25b6 Iustin Pop
205 6d691282 Michael Hanselmann
206 6d691282 Michael Hanselmann
if __name__ == "__main__":
207 6d691282 Michael Hanselmann
  main()
208 6d691282 Michael Hanselmann
209 319856a9 Michael Hanselmann
# vim: set foldmethod=marker :