Statistics
| Branch: | Tag: | Revision:

root / tools / cfgupgrade @ ea2bcb82

History | View | Annotate | Download (12 kB)

1 0006af7d Michael Hanselmann
#!/usr/bin/python
2 0006af7d Michael Hanselmann
#
3 0006af7d Michael Hanselmann
4 93fd9bb1 Iustin Pop
# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 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 7939f60c Michael Hanselmann
import time
36 7939f60c Michael Hanselmann
from cStringIO import StringIO
37 0006af7d Michael Hanselmann
38 95e4a814 Michael Hanselmann
from ganeti import constants
39 95e4a814 Michael Hanselmann
from ganeti import serializer
40 319856a9 Michael Hanselmann
from ganeti import utils
41 f97c7901 Michael Hanselmann
from ganeti import cli
42 a421fdeb Iustin Pop
from ganeti import bootstrap
43 ac4d25b6 Iustin Pop
from ganeti import config
44 011974df Michael Hanselmann
from ganeti import netutils
45 09bf5d24 Michael Hanselmann
from ganeti import pathutils
46 0006af7d Michael Hanselmann
47 0006af7d Michael Hanselmann
48 319856a9 Michael Hanselmann
options = None
49 319856a9 Michael Hanselmann
args = None
50 0006af7d Michael Hanselmann
51 6f285030 Iustin Pop
52 93fd9bb1 Iustin Pop
#: Target major version we will upgrade to
53 93fd9bb1 Iustin Pop
TARGET_MAJOR = 2
54 93fd9bb1 Iustin Pop
#: Target minor version we will upgrade to
55 93fd9bb1 Iustin Pop
TARGET_MINOR = 6
56 93fd9bb1 Iustin Pop
57 93fd9bb1 Iustin Pop
58 319856a9 Michael Hanselmann
class Error(Exception):
59 319856a9 Michael Hanselmann
  """Generic exception"""
60 319856a9 Michael Hanselmann
  pass
61 0006af7d Michael Hanselmann
62 0006af7d Michael Hanselmann
63 eda37a5a Michael Hanselmann
def SetupLogging():
64 eda37a5a Michael Hanselmann
  """Configures the logging module.
65 eda37a5a Michael Hanselmann
66 eda37a5a Michael Hanselmann
  """
67 eda37a5a Michael Hanselmann
  formatter = logging.Formatter("%(asctime)s: %(message)s")
68 eda37a5a Michael Hanselmann
69 eda37a5a Michael Hanselmann
  stderr_handler = logging.StreamHandler()
70 eda37a5a Michael Hanselmann
  stderr_handler.setFormatter(formatter)
71 eda37a5a Michael Hanselmann
  if options.debug:
72 eda37a5a Michael Hanselmann
    stderr_handler.setLevel(logging.NOTSET)
73 eda37a5a Michael Hanselmann
  elif options.verbose:
74 eda37a5a Michael Hanselmann
    stderr_handler.setLevel(logging.INFO)
75 eda37a5a Michael Hanselmann
  else:
76 011974df Michael Hanselmann
    stderr_handler.setLevel(logging.WARNING)
77 eda37a5a Michael Hanselmann
78 eda37a5a Michael Hanselmann
  root_logger = logging.getLogger("")
79 eda37a5a Michael Hanselmann
  root_logger.setLevel(logging.NOTSET)
80 eda37a5a Michael Hanselmann
  root_logger.addHandler(stderr_handler)
81 eda37a5a Michael Hanselmann
82 eda37a5a Michael Hanselmann
83 011974df Michael Hanselmann
def CheckHostname(path):
84 011974df Michael Hanselmann
  """Ensures hostname matches ssconf value.
85 011974df Michael Hanselmann
86 011974df Michael Hanselmann
  @param path: Path to ssconf file
87 011974df Michael Hanselmann
88 011974df Michael Hanselmann
  """
89 011974df Michael Hanselmann
  ssconf_master_node = utils.ReadOneLineFile(path)
90 011974df Michael Hanselmann
  hostname = netutils.GetHostname().name
91 011974df Michael Hanselmann
92 011974df Michael Hanselmann
  if ssconf_master_node == hostname:
93 011974df Michael Hanselmann
    return True
94 011974df Michael Hanselmann
95 011974df Michael Hanselmann
  logging.warning("Warning: ssconf says master node is '%s', but this"
96 011974df Michael Hanselmann
                  " machine's name is '%s'; this tool must be run on"
97 011974df Michael Hanselmann
                  " the master node", ssconf_master_node, hostname)
98 011974df Michael Hanselmann
  return False
99 011974df Michael Hanselmann
100 3c286190 Dimitris Aragiorgis
101 58bf877f Dimitris Aragiorgis
def UpgradeNetworks(config_data):
102 58bf877f Dimitris Aragiorgis
  networks = config_data.get("networks", None)
103 58bf877f Dimitris Aragiorgis
  if not networks:
104 58bf877f Dimitris Aragiorgis
    config_data["networks"] = {}
105 58bf877f Dimitris Aragiorgis
106 58bf877f Dimitris Aragiorgis
107 58bf877f Dimitris Aragiorgis
def UpgradeGroups(config_data):
108 58bf877f Dimitris Aragiorgis
  for group in config_data["nodegroups"].values():
109 58bf877f Dimitris Aragiorgis
    networks = group.get("networks", None)
110 58bf877f Dimitris Aragiorgis
    if not networks:
111 58bf877f Dimitris Aragiorgis
      group["networks"] = {}
112 58bf877f Dimitris Aragiorgis
113 011974df Michael Hanselmann
114 6d691282 Michael Hanselmann
def main():
115 6d691282 Michael Hanselmann
  """Main program.
116 6d691282 Michael Hanselmann
117 6d691282 Michael Hanselmann
  """
118 b459a848 Andrea Spadaccini
  global options, args # pylint: disable=W0603
119 6d691282 Michael Hanselmann
120 0006af7d Michael Hanselmann
  # Option parsing
121 95e4a814 Michael Hanselmann
  parser = optparse.OptionParser(usage="%prog [--debug|--verbose] [--force]")
122 3ccb3a64 Michael Hanselmann
  parser.add_option("--dry-run", dest="dry_run",
123 60edf71e Michael Hanselmann
                    action="store_true",
124 f4bc1f2c Michael Hanselmann
                    help="Try to do the conversion, but don't write"
125 f4bc1f2c Michael Hanselmann
                         " output file")
126 f97c7901 Michael Hanselmann
  parser.add_option(cli.FORCE_OPT)
127 eda37a5a Michael Hanselmann
  parser.add_option(cli.DEBUG_OPT)
128 9cdb9578 Iustin Pop
  parser.add_option(cli.VERBOSE_OPT)
129 011974df Michael Hanselmann
  parser.add_option("--ignore-hostname", dest="ignore_hostname",
130 011974df Michael Hanselmann
                    action="store_true", default=False,
131 011974df Michael Hanselmann
                    help="Don't abort if hostname doesn't match")
132 3ccb3a64 Michael Hanselmann
  parser.add_option("--path", help="Convert configuration in this"
133 09bf5d24 Michael Hanselmann
                    " directory instead of '%s'" % pathutils.DATA_DIR,
134 09bf5d24 Michael Hanselmann
                    default=pathutils.DATA_DIR, dest="data_dir")
135 7939f60c Michael Hanselmann
  parser.add_option("--confdir",
136 7939f60c Michael Hanselmann
                    help=("Use this directory instead of '%s'" %
137 7939f60c Michael Hanselmann
                          pathutils.CONF_DIR),
138 7939f60c Michael Hanselmann
                    default=pathutils.CONF_DIR, dest="conf_dir")
139 02e1292d Michael Hanselmann
  parser.add_option("--no-verify",
140 02e1292d Michael Hanselmann
                    help="Do not verify configuration after upgrade",
141 02e1292d Michael Hanselmann
                    action="store_true", dest="no_verify", default=False)
142 0006af7d Michael Hanselmann
  (options, args) = parser.parse_args()
143 0006af7d Michael Hanselmann
144 ac4d25b6 Iustin Pop
  # We need to keep filenames locally because they might be renamed between
145 ac4d25b6 Iustin Pop
  # versions.
146 0cddd44d Iustin Pop
  options.data_dir = os.path.abspath(options.data_dir)
147 ac4d25b6 Iustin Pop
  options.CONFIG_DATA_PATH = options.data_dir + "/config.data"
148 ac4d25b6 Iustin Pop
  options.SERVER_PEM_PATH = options.data_dir + "/server.pem"
149 ac4d25b6 Iustin Pop
  options.KNOWN_HOSTS_PATH = options.data_dir + "/known_hosts"
150 ac4d25b6 Iustin Pop
  options.RAPI_CERT_FILE = options.data_dir + "/rapi.pem"
151 b6267745 Andrea Spadaccini
  options.SPICE_CERT_FILE = options.data_dir + "/spice.pem"
152 b6267745 Andrea Spadaccini
  options.SPICE_CACERT_FILE = options.data_dir + "/spice-ca.pem"
153 fdd9ac5b Michael Hanselmann
  options.RAPI_USERS_FILE = options.data_dir + "/rapi/users"
154 fdd9ac5b Michael Hanselmann
  options.RAPI_USERS_FILE_PRE24 = options.data_dir + "/rapi_users"
155 6b7d5878 Michael Hanselmann
  options.CONFD_HMAC_KEY = options.data_dir + "/hmac.key"
156 fc0726b9 Michael Hanselmann
  options.CDS_FILE = options.data_dir + "/cluster-domain-secret"
157 011974df Michael Hanselmann
  options.SSCONF_MASTER_NODE = options.data_dir + "/ssconf_master_node"
158 a292020f Michael Hanselmann
  options.WATCHER_STATEFILE = options.data_dir + "/watcher.data"
159 7939f60c Michael Hanselmann
  options.FILE_STORAGE_PATHS_FILE = options.conf_dir + "/file-storage-paths"
160 ac4d25b6 Iustin Pop
161 eda37a5a Michael Hanselmann
  SetupLogging()
162 eda37a5a Michael Hanselmann
163 0006af7d Michael Hanselmann
  # Option checking
164 0006af7d Michael Hanselmann
  if args:
165 95e4a814 Michael Hanselmann
    raise Error("No arguments expected")
166 0006af7d Michael Hanselmann
167 011974df Michael Hanselmann
  # Check master name
168 011974df Michael Hanselmann
  if not (CheckHostname(options.SSCONF_MASTER_NODE) or options.ignore_hostname):
169 011974df Michael Hanselmann
    logging.error("Aborting due to hostname mismatch")
170 011974df Michael Hanselmann
    sys.exit(constants.EXIT_FAILURE)
171 011974df Michael Hanselmann
172 319856a9 Michael Hanselmann
  if not options.force:
173 011974df Michael Hanselmann
    usertext = ("Please make sure you have read the upgrade notes for"
174 011974df Michael Hanselmann
                " Ganeti %s (available in the UPGRADE file and included"
175 011974df Michael Hanselmann
                " in other documentation formats). Continue with upgrading"
176 011974df Michael Hanselmann
                " configuration?" % constants.RELEASE_VERSION)
177 f97c7901 Michael Hanselmann
    if not cli.AskUser(usertext):
178 a9221f09 Michael Hanselmann
      sys.exit(constants.EXIT_FAILURE)
179 319856a9 Michael Hanselmann
180 95e4a814 Michael Hanselmann
  # Check whether it's a Ganeti configuration directory
181 ac4d25b6 Iustin Pop
  if not (os.path.isfile(options.CONFIG_DATA_PATH) and
182 30acff6c Michael Hanselmann
          os.path.isfile(options.SERVER_PEM_PATH) and
183 ac4d25b6 Iustin Pop
          os.path.isfile(options.KNOWN_HOSTS_PATH)):
184 a9221f09 Michael Hanselmann
    raise Error(("%s does not seem to be a Ganeti configuration"
185 ac4d25b6 Iustin Pop
                 " directory") % options.data_dir)
186 95e4a814 Michael Hanselmann
187 7939f60c Michael Hanselmann
  if not os.path.isdir(options.conf_dir):
188 7939f60c Michael Hanselmann
    raise Error("Not a directory: %s" % options.conf_dir)
189 7939f60c Michael Hanselmann
190 11c31f5c Michael Hanselmann
  config_data = serializer.LoadJson(utils.ReadFile(options.CONFIG_DATA_PATH))
191 a421fdeb Iustin Pop
192 11c31f5c Michael Hanselmann
  try:
193 11c31f5c Michael Hanselmann
    config_version = config_data["version"]
194 11c31f5c Michael Hanselmann
  except KeyError:
195 11c31f5c Michael Hanselmann
    raise Error("Unable to determine configuration version")
196 0006af7d Michael Hanselmann
197 11c31f5c Michael Hanselmann
  (config_major, config_minor, config_revision) = \
198 11c31f5c Michael Hanselmann
    constants.SplitVersion(config_version)
199 319856a9 Michael Hanselmann
200 11c31f5c Michael Hanselmann
  logging.info("Found configuration version %s (%d.%d.%d)",
201 11c31f5c Michael Hanselmann
               config_version, config_major, config_minor, config_revision)
202 319856a9 Michael Hanselmann
203 11c31f5c Michael Hanselmann
  if "config_version" in config_data["cluster"]:
204 11c31f5c Michael Hanselmann
    raise Error("Inconsistent configuration: found config_version in"
205 11c31f5c Michael Hanselmann
                " configuration file")
206 95e4a814 Michael Hanselmann
207 a91f69c4 Michael Hanselmann
  # Upgrade from 2.0/2.1/2.2/2.3 to 2.4
208 93fd9bb1 Iustin Pop
  if config_major == 2 and config_minor in (0, 1, 2, 3, 4, 5):
209 aeb0c953 Michael Hanselmann
    if config_revision != 0:
210 a9221f09 Michael Hanselmann
      logging.warning("Config revision is %s, not 0", config_revision)
211 aeb0c953 Michael Hanselmann
212 93fd9bb1 Iustin Pop
    config_data["version"] = constants.BuildVersion(TARGET_MAJOR,
213 93fd9bb1 Iustin Pop
                                                    TARGET_MINOR, 0)
214 a9221f09 Michael Hanselmann
215 904910c4 Iustin Pop
    if "instances" not in config_data:
216 904910c4 Iustin Pop
      raise Error("Can't find the 'instances' key in the configuration!")
217 904910c4 Iustin Pop
    for instance, iobj in config_data["instances"].items():
218 904910c4 Iustin Pop
      if "disks" not in iobj:
219 904910c4 Iustin Pop
        raise Error("Instance '%s' doesn't have a disks entry?!" % instance)
220 904910c4 Iustin Pop
      disks = iobj["disks"]
221 904910c4 Iustin Pop
      for idx, dobj in enumerate(disks):
222 904910c4 Iustin Pop
        expected = "disk/%s" % idx
223 904910c4 Iustin Pop
        current = dobj.get("iv_name", "")
224 904910c4 Iustin Pop
        if current != expected:
225 904910c4 Iustin Pop
          logging.warning("Updating iv_name for instance %s/disk %s"
226 904910c4 Iustin Pop
                          " from '%s' to '%s'",
227 904910c4 Iustin Pop
                          instance, idx, current, expected)
228 904910c4 Iustin Pop
          dobj["iv_name"] = expected
229 904910c4 Iustin Pop
230 93fd9bb1 Iustin Pop
  elif config_major == TARGET_MAJOR and config_minor == TARGET_MINOR:
231 a9221f09 Michael Hanselmann
    logging.info("No changes necessary")
232 a9221f09 Michael Hanselmann
233 a9221f09 Michael Hanselmann
  else:
234 a9221f09 Michael Hanselmann
    raise Error("Configuration version %d.%d.%d not supported by this tool" %
235 a9221f09 Michael Hanselmann
                (config_major, config_minor, config_revision))
236 aeb0c953 Michael Hanselmann
237 87c80992 Michael Hanselmann
  if (os.path.isfile(options.RAPI_USERS_FILE_PRE24) and
238 87c80992 Michael Hanselmann
      not os.path.islink(options.RAPI_USERS_FILE_PRE24)):
239 87c80992 Michael Hanselmann
    if os.path.exists(options.RAPI_USERS_FILE):
240 87c80992 Michael Hanselmann
      raise Error("Found pre-2.4 RAPI users file at %s, but another file"
241 87c80992 Michael Hanselmann
                  " already exists at %s" %
242 87c80992 Michael Hanselmann
                  (options.RAPI_USERS_FILE_PRE24, options.RAPI_USERS_FILE))
243 fdd9ac5b Michael Hanselmann
    logging.info("Found pre-2.4 RAPI users file at %s, renaming to %s",
244 fdd9ac5b Michael Hanselmann
                 options.RAPI_USERS_FILE_PRE24, options.RAPI_USERS_FILE)
245 87c80992 Michael Hanselmann
    if not options.dry_run:
246 87c80992 Michael Hanselmann
      utils.RenameFile(options.RAPI_USERS_FILE_PRE24, options.RAPI_USERS_FILE,
247 87c80992 Michael Hanselmann
                       mkdir=True, mkdir_mode=0750)
248 fdd9ac5b Michael Hanselmann
249 fdd9ac5b Michael Hanselmann
  # Create a symlink for RAPI users file
250 87c80992 Michael Hanselmann
  if (not (os.path.islink(options.RAPI_USERS_FILE_PRE24) or
251 87c80992 Michael Hanselmann
           os.path.isfile(options.RAPI_USERS_FILE_PRE24)) and
252 87c80992 Michael Hanselmann
      os.path.isfile(options.RAPI_USERS_FILE)):
253 fdd9ac5b Michael Hanselmann
    logging.info("Creating symlink from %s to %s",
254 fdd9ac5b Michael Hanselmann
                 options.RAPI_USERS_FILE_PRE24, options.RAPI_USERS_FILE)
255 87c80992 Michael Hanselmann
    if not options.dry_run:
256 87c80992 Michael Hanselmann
      os.symlink(options.RAPI_USERS_FILE, options.RAPI_USERS_FILE_PRE24)
257 fdd9ac5b Michael Hanselmann
258 a292020f Michael Hanselmann
  # Remove old watcher state file if it exists
259 a292020f Michael Hanselmann
  if os.path.exists(options.WATCHER_STATEFILE):
260 a292020f Michael Hanselmann
    logging.info("Removing watcher state file %s", options.WATCHER_STATEFILE)
261 a292020f Michael Hanselmann
    if not options.dry_run:
262 a292020f Michael Hanselmann
      utils.RemoveFile(options.WATCHER_STATEFILE)
263 a292020f Michael Hanselmann
264 7939f60c Michael Hanselmann
  # Write file storage paths
265 7939f60c Michael Hanselmann
  if not os.path.exists(options.FILE_STORAGE_PATHS_FILE):
266 7939f60c Michael Hanselmann
    cluster = config_data["cluster"]
267 7939f60c Michael Hanselmann
    file_storage_dir = cluster.get("file_storage_dir")
268 7939f60c Michael Hanselmann
    shared_file_storage_dir = cluster.get("shared_file_storage_dir")
269 7939f60c Michael Hanselmann
    del cluster
270 7939f60c Michael Hanselmann
271 7939f60c Michael Hanselmann
    logging.info("Ganeti 2.7 and later only allow whitelisted directories"
272 7939f60c Michael Hanselmann
                 " for file storage; writing existing configuration values"
273 7939f60c Michael Hanselmann
                 " into '%s'",
274 7939f60c Michael Hanselmann
                 options.FILE_STORAGE_PATHS_FILE)
275 7939f60c Michael Hanselmann
276 7939f60c Michael Hanselmann
    if file_storage_dir:
277 7939f60c Michael Hanselmann
      logging.info("File storage directory: %s", file_storage_dir)
278 7939f60c Michael Hanselmann
    if shared_file_storage_dir:
279 7939f60c Michael Hanselmann
      logging.info("Shared file storage directory: %s",
280 7939f60c Michael Hanselmann
                   shared_file_storage_dir)
281 7939f60c Michael Hanselmann
282 7939f60c Michael Hanselmann
    buf = StringIO()
283 7939f60c Michael Hanselmann
    buf.write("# List automatically generated from configuration by\n")
284 7939f60c Michael Hanselmann
    buf.write("# cfgupgrade at %s\n" % time.asctime())
285 7939f60c Michael Hanselmann
    if file_storage_dir:
286 7939f60c Michael Hanselmann
      buf.write("%s\n" % file_storage_dir)
287 7939f60c Michael Hanselmann
    if shared_file_storage_dir:
288 7939f60c Michael Hanselmann
      buf.write("%s\n" % shared_file_storage_dir)
289 7939f60c Michael Hanselmann
    utils.WriteFile(file_name=options.FILE_STORAGE_PATHS_FILE,
290 7939f60c Michael Hanselmann
                    data=buf.getvalue(),
291 7939f60c Michael Hanselmann
                    mode=0600,
292 7939f60c Michael Hanselmann
                    dry_run=options.dry_run,
293 7939f60c Michael Hanselmann
                    backup=True)
294 7939f60c Michael Hanselmann
295 58bf877f Dimitris Aragiorgis
  UpgradeNetworks(config_data)
296 58bf877f Dimitris Aragiorgis
  UpgradeGroups(config_data)
297 58bf877f Dimitris Aragiorgis
298 11c31f5c Michael Hanselmann
  try:
299 11c31f5c Michael Hanselmann
    logging.info("Writing configuration file to %s", options.CONFIG_DATA_PATH)
300 11c31f5c Michael Hanselmann
    utils.WriteFile(file_name=options.CONFIG_DATA_PATH,
301 11c31f5c Michael Hanselmann
                    data=serializer.DumpJson(config_data),
302 11c31f5c Michael Hanselmann
                    mode=0600,
303 11c31f5c Michael Hanselmann
                    dry_run=options.dry_run,
304 11c31f5c Michael Hanselmann
                    backup=True)
305 a421fdeb Iustin Pop
306 a421fdeb Iustin Pop
    if not options.dry_run:
307 5ae4945a Iustin Pop
      bootstrap.GenerateClusterCrypto(
308 5ae4945a Iustin Pop
        False, False, False, False, False,
309 5ae4945a Iustin Pop
        nodecert_file=options.SERVER_PEM_PATH,
310 5ae4945a Iustin Pop
        rapicert_file=options.RAPI_CERT_FILE,
311 5ae4945a Iustin Pop
        spicecert_file=options.SPICE_CERT_FILE,
312 5ae4945a Iustin Pop
        spicecacert_file=options.SPICE_CACERT_FILE,
313 5ae4945a Iustin Pop
        hmackey_file=options.CONFD_HMAC_KEY,
314 5ae4945a Iustin Pop
        cds_file=options.CDS_FILE)
315 aeb0c953 Michael Hanselmann
316 a9221f09 Michael Hanselmann
  except Exception:
317 11c31f5c Michael Hanselmann
    logging.critical("Writing configuration failed. It is probably in an"
318 95e4a814 Michael Hanselmann
                     " inconsistent state and needs manual intervention.")
319 95e4a814 Michael Hanselmann
    raise
320 0006af7d Michael Hanselmann
321 ac4d25b6 Iustin Pop
  # test loading the config file
322 02e1292d Michael Hanselmann
  if not (options.dry_run or options.no_verify):
323 ac4d25b6 Iustin Pop
    logging.info("Testing the new config file...")
324 ac4d25b6 Iustin Pop
    cfg = config.ConfigWriter(cfg_file=options.CONFIG_DATA_PATH,
325 959b6fe5 Apollon Oikonomopoulos
                              accept_foreign=options.ignore_hostname,
326 ac4d25b6 Iustin Pop
                              offline=True)
327 ac4d25b6 Iustin Pop
    # if we reached this, it's all fine
328 ac4d25b6 Iustin Pop
    vrfy = cfg.VerifyConfig()
329 ac4d25b6 Iustin Pop
    if vrfy:
330 ac4d25b6 Iustin Pop
      logging.error("Errors after conversion:")
331 ac4d25b6 Iustin Pop
      for item in vrfy:
332 07b8a2b5 Iustin Pop
        logging.error(" - %s", item)
333 ac4d25b6 Iustin Pop
    del cfg
334 ac4d25b6 Iustin Pop
    logging.info("File loaded successfully")
335 ac4d25b6 Iustin Pop
336 66a66fa7 Michael Hanselmann
  cli.ToStderr("Configuration successfully upgraded for version %s.",
337 66a66fa7 Michael Hanselmann
               constants.RELEASE_VERSION)
338 66a66fa7 Michael Hanselmann
339 6d691282 Michael Hanselmann
340 6d691282 Michael Hanselmann
if __name__ == "__main__":
341 6d691282 Michael Hanselmann
  main()