[Pkg-ganeti-devel] [SCM] Ganeti packaging branch, master, updated. debian/2.0.6-2-20-g7fef725

Iustin Pop iustin at debian.org
Sat Apr 17 22:21:28 UTC 2010


The following commit has been merged in the master branch:
commit 99ca99ebea74e0e3f1f54f10a38cffe99e98b4d7
Author: Iustin Pop <iustin at debian.org>
Date:   Sat Apr 17 17:01:37 2010 +0200

    Import cfgupgrade12 from upstream git

diff --git a/debian/changelog b/debian/changelog
index 3249362..7b6083c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+ganeti (2.1.1-1) unstable; urgency=low
+
+  * New upstream version
+
+ -- Iustin Pop <iustin at debian.org>  Sat, 17 Apr 2010 17:01:11 +0200
+
 ganeti (2.0.6-2) unstable; urgency=low
 
   * Cherry-pick three patches from upstream:
diff --git a/debian/patches/import-cfgupgrade12.patch b/debian/patches/import-cfgupgrade12.patch
new file mode 100644
index 0000000..c2b1464
--- /dev/null
+++ b/debian/patches/import-cfgupgrade12.patch
@@ -0,0 +1,467 @@
+From: Iustin Pop <iustin at google.com>
+Date: Wed, 14 Apr 2010 16:27:03 +0000 (+0200)
+Subject: Forward-port the ganeti 2.0 cfgupgrade
+X-Git-Url: http://git.ganeti.org/?p=ganeti.git;a=commitdiff_plain;h=b5672ea0712e91e1a45bb53413f0223b718bf1e6
+
+Forward-port the ganeti 2.0 cfgupgrade
+
+2.1's cfgupgrade doesn't support upgrading from 1.2, only from 2.0.
+However, it's trivial to forward-port the 2.0 cfgupgrade to work with
+2.1, thus providing an upgrade path for 1.2 users directly to 2.1,
+without the intermediate step of installing 2.0.
+
+The new cfgupgrade12 file has just a few trivial changes from 2.0, and
+skipping the load of the config file.
+
+Signed-off-by: Iustin Pop <iustin at google.com>
+Reviewed-by: René Nussbaumer <rn at google.com>
+
+(Modified slightly for Debian:
+ - quilt refresh to apply cleanly without fuzz
+ - removed doc/admin.rst changes to not need doc rebuild
+ - modified Makefile.in to not require re-running autoconf
+)
+
+---
+
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -233,6 +233,7 @@
+ 	tools/burnin \
+ 	tools/cfgshell \
+ 	tools/cfgupgrade \
++	tools/cfgupgrade12 \
+ 	tools/cluster-merge \
+ 	tools/lvmstrap
+ 
+--- /dev/null
++++ b/tools/cfgupgrade12
+@@ -0,0 +1,418 @@
++#!/usr/bin/python
++#
++
++# Copyright (C) 2007, 2008, 2009 Google Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful, but
++# WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++# General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++# 02110-1301, USA.
++
++# pylint: disable-msg=C0103,E1103
++
++# C0103: invalid name NoDefault
++# E1103: Instance of 'foor' has no 'bar' member (but some types could
++# not be inferred)
++
++
++"""Tool to upgrade the configuration file.
++
++This code handles only the types supported by simplejson. As an
++example, 'set' is a 'list'.
++
++ at note: this has lots of duplicate content with C{cfgupgrade}. Ideally, it
++should be merged.
++
++"""
++
++
++import os
++import os.path
++import sys
++import optparse
++import logging
++import errno
++
++from ganeti import constants
++from ganeti import serializer
++from ganeti import utils
++from ganeti import cli
++from ganeti import bootstrap
++
++
++options = None
++args = None
++
++# Unique object to identify calls without default value
++NoDefault = object()
++
++# Dictionary with instance old keys, and new hypervisor keys
++INST_HV_CHG = {
++  'hvm_pae': constants.HV_PAE,
++  'vnc_bind_address': constants.HV_VNC_BIND_ADDRESS,
++  'initrd_path': constants.HV_INITRD_PATH,
++  'hvm_nic_type': constants.HV_NIC_TYPE,
++  'kernel_path': constants.HV_KERNEL_PATH,
++  'hvm_acpi': constants.HV_ACPI,
++  'hvm_cdrom_image_path': constants.HV_CDROM_IMAGE_PATH,
++  'hvm_boot_order': constants.HV_BOOT_ORDER,
++  'hvm_disk_type': constants.HV_DISK_TYPE,
++  }
++
++# Instance beparams changes
++INST_BE_CHG = {
++  'vcpus': constants.BE_VCPUS,
++  'memory': constants.BE_MEMORY,
++  'auto_balance': constants.BE_AUTO_BALANCE,
++  }
++
++# Field names
++F_SERIAL = 'serial_no'
++
++
++class Error(Exception):
++  """Generic exception"""
++  pass
++
++
++def SsconfName(key):
++  """Returns the file name of an (old) ssconf key.
++
++  """
++  return "%s/ssconf_%s" % (options.data_dir, key)
++
++
++def ReadFile(file_name, default=NoDefault):
++  """Reads a file.
++
++  """
++  logging.debug("Reading %s", file_name)
++  try:
++    fh = open(file_name, 'r')
++  except IOError, err:
++    if default is not NoDefault and err.errno == errno.ENOENT:
++      return default
++    raise
++
++  try:
++    return fh.read()
++  finally:
++    fh.close()
++
++
++def WriteFile(file_name, data):
++  """Writes a configuration file.
++
++  """
++  logging.debug("Writing %s", file_name)
++  utils.WriteFile(file_name=file_name, data=data, mode=0600,
++                  dry_run=options.dry_run, backup=True)
++
++
++def GenerateSecret(all_secrets):
++  """Generate an unique DRBD secret.
++
++  This is a copy from ConfigWriter.
++
++  """
++  retries = 64
++  while retries > 0:
++    secret = utils.GenerateSecret()
++    if secret not in all_secrets:
++      break
++    retries -= 1
++  else:
++    raise Error("Can't generate unique DRBD secret")
++  return secret
++
++
++def SetupLogging():
++  """Configures the logging module.
++
++  """
++  formatter = logging.Formatter("%(asctime)s: %(message)s")
++
++  stderr_handler = logging.StreamHandler()
++  stderr_handler.setFormatter(formatter)
++  if options.debug:
++    stderr_handler.setLevel(logging.NOTSET)
++  elif options.verbose:
++    stderr_handler.setLevel(logging.INFO)
++  else:
++    stderr_handler.setLevel(logging.CRITICAL)
++
++  root_logger = logging.getLogger("")
++  root_logger.setLevel(logging.NOTSET)
++  root_logger.addHandler(stderr_handler)
++
++
++def Cluster12To20(cluster):
++  """Upgrades the cluster object from 1.2 to 2.0.
++
++  """
++  logging.info("Upgrading the cluster object")
++  # Upgrade the configuration version
++  if 'config_version' in cluster:
++    del cluster['config_version']
++
++  # Add old ssconf keys back to config
++  logging.info(" - importing ssconf keys")
++  for key in ('master_node', 'master_ip', 'master_netdev', 'cluster_name'):
++    if key not in cluster:
++      cluster[key] = ReadFile(SsconfName(key)).strip()
++
++  if 'default_hypervisor' not in cluster:
++    old_hyp = ReadFile(SsconfName('hypervisor')).strip()
++    if old_hyp == "xen-3.0":
++      hyp = "xen-pvm"
++    elif old_hyp == "xen-hvm-3.1":
++      hyp = "xen-hvm"
++    elif old_hyp == "fake":
++      hyp = "fake"
++    else:
++      raise Error("Unknown old hypervisor name '%s'" % old_hyp)
++
++    logging.info("Setting the default and enabled hypervisor")
++    cluster['default_hypervisor'] = hyp
++    cluster['enabled_hypervisors'] = [hyp]
++
++  # hv/be params
++  if 'hvparams' not in cluster:
++    logging.info(" - adding hvparams")
++    cluster['hvparams'] = constants.HVC_DEFAULTS
++  if 'beparams' not in cluster:
++    logging.info(" - adding beparams")
++    cluster['beparams'] = {constants.PP_DEFAULT: constants.BEC_DEFAULTS}
++
++  # file storage
++  if 'file_storage_dir' not in cluster:
++    cluster['file_storage_dir'] = constants.DEFAULT_FILE_STORAGE_DIR
++
++  # candidate pool size
++  if 'candidate_pool_size' not in cluster:
++    cluster['candidate_pool_size'] = constants.MASTER_POOL_SIZE_DEFAULT
++
++
++def Node12To20(node):
++  """Upgrades a node from 1.2 to 2.0.
++
++  """
++  logging.info("Upgrading node %s", node['name'])
++  if F_SERIAL not in node:
++    node[F_SERIAL] = 1
++  if 'master_candidate' not in node:
++    node['master_candidate'] = True
++  for key in 'offline', 'drained':
++    if key not in node:
++      node[key] = False
++
++
++def Instance12To20(drbd_minors, secrets, hypervisor, instance):
++  """Upgrades an instance from 1.2 to 2.0.
++
++  """
++  if F_SERIAL not in instance:
++    instance[F_SERIAL] = 1
++
++  if 'hypervisor' not in instance:
++    instance['hypervisor'] = hypervisor
++
++  # hvparams changes
++  if 'hvparams' not in instance:
++    instance['hvparams'] = hvp = {}
++  for old, new in INST_HV_CHG.items():
++    if old in instance:
++      if (instance[old] is not None and
++          instance[old] != constants.VALUE_DEFAULT and # no longer valid in 2.0
++          new in constants.HVC_DEFAULTS[hypervisor]):
++        hvp[new] = instance[old]
++      del instance[old]
++
++  # beparams changes
++  if 'beparams' not in instance:
++    instance['beparams'] = bep = {}
++  for old, new in INST_BE_CHG.items():
++    if old in instance:
++      if instance[old] is not None:
++        bep[new] = instance[old]
++      del instance[old]
++
++  # disk changes
++  for disk in instance['disks']:
++    Disk12To20(drbd_minors, secrets, disk)
++
++  # other instance changes
++  if 'status' in instance:
++    instance['admin_up'] = instance['status'] == 'up'
++    del instance['status']
++
++
++def Disk12To20(drbd_minors, secrets, disk):
++  """Upgrades a disk from 1.2 to 2.0.
++
++  """
++  if 'mode' not in disk:
++    disk['mode'] = constants.DISK_RDWR
++  if disk['dev_type'] == constants.LD_DRBD8:
++    old_lid = disk['logical_id']
++    for node in old_lid[:2]:
++      if node not in drbd_minors:
++        raise Error("Can't find node '%s' while upgrading disk" % node)
++      drbd_minors[node] += 1
++      minor = drbd_minors[node]
++      old_lid.append(minor)
++    old_lid.append(GenerateSecret(secrets))
++    del disk['physical_id']
++  if disk['children']:
++    for child in disk['children']:
++      Disk12To20(drbd_minors, secrets, child)
++
++
++def main():
++  """Main program.
++
++  """
++  # pylint: disable-msg=W0603
++  global options, args
++
++  program = os.path.basename(sys.argv[0])
++
++  # Option parsing
++  parser = optparse.OptionParser(usage="%prog [--debug|--verbose] [--force]")
++  parser.add_option('--dry-run', dest='dry_run',
++                    action="store_true",
++                    help="Try to do the conversion, but don't write"
++                         " output file")
++  parser.add_option(cli.FORCE_OPT)
++  parser.add_option(cli.DEBUG_OPT)
++  parser.add_option(cli.VERBOSE_OPT)
++  parser.add_option('--path', help="Convert configuration in this"
++                    " directory instead of '%s'" % constants.DATA_DIR,
++                    default=constants.DATA_DIR, dest="data_dir")
++  (options, args) = parser.parse_args()
++
++  # We need to keep filenames locally because they might be renamed between
++  # versions.
++  options.CONFIG_DATA_PATH = options.data_dir + "/config.data"
++  options.SERVER_PEM_PATH = options.data_dir + "/server.pem"
++  options.KNOWN_HOSTS_PATH = options.data_dir + "/known_hosts"
++  options.RAPI_CERT_FILE = options.data_dir + "/rapi.pem"
++
++  SetupLogging()
++
++  # Option checking
++  if args:
++    raise Error("No arguments expected")
++
++  if not options.force:
++    usertext = ("%s MUST be run on the master node. Is this the master"
++                " node and are ALL instances down?" % program)
++    if not cli.AskUser(usertext):
++      sys.exit(1)
++
++  # Check whether it's a Ganeti configuration directory
++  if not (os.path.isfile(options.CONFIG_DATA_PATH) and
++          os.path.isfile(options.SERVER_PEM_PATH) or
++          os.path.isfile(options.KNOWN_HOSTS_PATH)):
++    raise Error(("%s does not seem to be a known Ganeti configuration"
++                 " directory") % options.data_dir)
++
++  config_version = ReadFile(SsconfName('config_version'), "1.2").strip()
++  logging.info("Found configuration version %s", config_version)
++
++  config_data = serializer.LoadJson(ReadFile(options.CONFIG_DATA_PATH))
++
++  # Ganeti 1.2?
++  if config_version == "1.2":
++    logging.info("Found a Ganeti 1.2 configuration")
++
++    cluster = config_data["cluster"]
++
++    old_config_version = cluster.get("config_version", None)
++    logging.info("Found old configuration version %s", old_config_version)
++    if old_config_version not in (3, ):
++      raise Error("Unsupported configuration version: %s" %
++                  old_config_version)
++    if 'version' not in config_data:
++      config_data['version'] = constants.BuildVersion(2, 0, 0)
++    if F_SERIAL not in config_data:
++      config_data[F_SERIAL] = 1
++
++    # Make sure no instance uses remote_raid1 anymore
++    remote_raid1_instances = []
++    for instance in config_data["instances"].values():
++      if instance["disk_template"] == "remote_raid1":
++        remote_raid1_instances.append(instance["name"])
++    if remote_raid1_instances:
++      for name in remote_raid1_instances:
++        logging.error("Instance %s still using remote_raid1 disk template",
++                      name)
++      raise Error("Unable to convert configuration as long as there are"
++                  " instances using remote_raid1 disk template")
++
++    # Build content of new known_hosts file
++    cluster_name = ReadFile(SsconfName('cluster_name')).rstrip()
++    cluster_key = cluster['rsahostkeypub']
++    known_hosts = "%s ssh-rsa %s\n" % (cluster_name, cluster_key)
++
++    Cluster12To20(cluster)
++
++    # Add node attributes
++    logging.info("Upgrading nodes")
++    # stable-sort the names to have repeatable runs
++    for node_name in utils.NiceSort(config_data['nodes'].keys()):
++      Node12To20(config_data['nodes'][node_name])
++
++    # Instance changes
++    logging.info("Upgrading instances")
++    drbd_minors = dict.fromkeys(config_data['nodes'], 0)
++    secrets = set()
++    # stable-sort the names to have repeatable runs
++    for instance_name in utils.NiceSort(config_data['instances'].keys()):
++      Instance12To20(drbd_minors, secrets, cluster['default_hypervisor'],
++                     config_data['instances'][instance_name])
++
++  else:
++    logging.info("Found a Ganeti 2.0 configuration")
++
++    if "config_version" in config_data["cluster"]:
++      raise Error("Inconsistent configuration: found config_data in"
++                  " configuration file")
++
++    known_hosts = None
++
++  try:
++    logging.info("Writing configuration file")
++    WriteFile(options.CONFIG_DATA_PATH, serializer.DumpJson(config_data))
++
++    if known_hosts is not None:
++      logging.info("Writing SSH known_hosts file (%s)", known_hosts.strip())
++      WriteFile(options.KNOWN_HOSTS_PATH, known_hosts)
++
++    if not options.dry_run:
++      if not os.path.exists(options.RAPI_CERT_FILE):
++        logging.debug("Writing RAPI certificate to %s", options.RAPI_CERT_FILE)
++        bootstrap.GenerateSelfSignedSslCert(options.RAPI_CERT_FILE)
++
++  except:
++    logging.critical("Writing configuration failed. It is probably in an"
++                     " inconsistent state and needs manual intervention.")
++    raise
++
++  logging.info("Configuration file updated.")
++
++
++if __name__ == "__main__":
++  main()
++
++# vim: set foldmethod=marker :
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -393,6 +393,7 @@
+ 	tools/burnin \
+ 	tools/cfgshell \
+ 	tools/cfgupgrade \
++	tools/cfgupgrade12 \
+ 	tools/cluster-merge \
+ 	tools/lvmstrap
+ 
diff --git a/debian/patches/series b/debian/patches/series
index 76e4e02..7145454 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -4,3 +4,4 @@ fix-startup-with-old-config.patch
 fix-http-loops.patch
 fix-kvm-bridging.patch
 fix-python-2.6.5.patch
+import-cfgupgrade12.patch
diff --git a/debian/rules b/debian/rules
index 2592379..6c4b201 100755
--- a/debian/rules
+++ b/debian/rules
@@ -20,7 +20,7 @@ build-stamp:
 	  --with-os-search-path=/srv/ganeti/os,/usr/local/lib/ganeti/os,/usr/lib/ganeti/os,/usr/share/ganeti/os \
 	  --docdir=/usr/share/doc/ganeti2
 
-	#$(MAKE)
+	$(MAKE)
 
 	touch $@
 
@@ -55,6 +55,7 @@ install: build
 	  $(CURDIR)/debian/ganeti2/etc/bash_completion.d/ganeti
 	install -m 0644 $(CURDIR)/debian/ganeti2.overrides \
 	  $(CURDIR)/debian/ganeti2/usr/share/lintian/overrides/ganeti2
+
 	rmdir debian/ganeti2/var/run/ganeti
 	rmdir debian/ganeti2/var/run
 

-- 
Ganeti packaging



More information about the Pkg-ganeti-devel mailing list