Merge branch 'stable-2.11' into master
authorKlaus Aehlig <aehlig@google.com>
Mon, 7 Apr 2014 11:02:43 +0000 (13:02 +0200)
committerKlaus Aehlig <aehlig@google.com>
Mon, 7 Apr 2014 11:37:33 +0000 (13:37 +0200)
* stable-2.11
  (no changes)

* stable-2.10
  KVM: use running HVPs to calc blockdev options
  KVM: reserve a PCI slot for the SCSI controller
  Check for LVM-based verification results only when enabled
  Fix "existing" typos
  Fix output of gnt-instance info after migration
  Verify configuration version number before parsing

Conflicts:
lib/config.py: manually apply 2dc0acb98
    to the version on master

Signed-off-by: Klaus Aehlig <aehlig@google.com>
Reviewed-by: Hrvoje Ribicic <riba@google.com>

1  2 
lib/client/gnt_instance.py
lib/cmdlib/cluster.py
lib/config.py
lib/hypervisor/hv_kvm/__init__.py

Simple merge
Simple merge
diff --cc lib/config.py
@@@ -2472,129 -2333,60 +2473,126 @@@ class ConfigWriter(object)
      """Returns all objects with uuid attributes.
  
      """
 -    return (self._config_data.instances.values() +
 -            self._config_data.nodes.values() +
 -            self._config_data.nodegroups.values() +
 -            self._config_data.networks.values() +
 +    return (self._ConfigData().instances.values() +
 +            self._ConfigData().nodes.values() +
 +            self._ConfigData().nodegroups.values() +
 +            self._ConfigData().networks.values() +
              self._AllDisks() +
              self._AllNICs() +
 -            [self._config_data.cluster])
 +            [self._ConfigData().cluster])
 +
 +  def GetConfigManager(self, shared=False):
 +    """Returns a ConfigManager, which is suitable to perform a synchronized
 +    block of configuration operations.
 +
 +    WARNING: This blocks all other configuration operations, so anything that
 +    runs inside the block should be very fast, preferably not using any IO.
 +    """
 +
 +    return ConfigManager(self, shared)
 +
 +  def _AddLockCount(self, count):
 +    self._lock_count += count
 +    return self._lock_count
 +
 +  def _LockCount(self):
 +    return self._lock_count
  
 -  def _OpenConfig(self, accept_foreign):
 -    """Read the config data from disk.
 +  def _OpenConfig(self, shared):
 +    """Read the config data from WConfd or disk.
  
      """
 -    raw_data = utils.ReadFile(self._cfg_file)
 +    if self._AddLockCount(1) > 1:
 +      if self._lock_current_shared and not shared:
 +        self._AddLockCount(-1)
 +        raise errors.ConfigurationError("Can't request an exclusive"
 +                                        " configuration lock while holding"
 +                                        " shared")
 +      else:
 +        return # we already have the lock, do nothing
 +    else:
 +      self._lock_current_shared = shared
 +    # Read the configuration data. If offline, read the file directly.
 +    # If online, call WConfd.
 +    if self._offline:
 +      raw_data = utils.ReadFile(self._cfg_file)
-       try:
-         dict_data = serializer.Load(raw_data)
++        data_dict = serializer.Load(raw_data)
++        # Make sure the configuration has the right version
++        _ValidateConfig(data_dict)
++        data = objects.ConfigData.FromDict(data_dict)
++      except errors.ConfigVersionMismatch:
++        raise
 +      except Exception, err:
 +        raise errors.ConfigurationError(err)
-       self._cfg_id = utils.GetFileID(path=self._cfg_file)
 +
-       try:
-         data = objects.ConfigData.FromDict(dict_data)
-       except Exception, err:
-         raise errors.ConfigurationError(err)
-       # Make sure the configuration has the right version
-       _ValidateConfig(data)
++      self._cfg_id = utils.GetFileID(path=self._cfg_file)
 +
 +      if (not hasattr(data, "cluster") or
 +          not hasattr(data.cluster, "rsahostkeypub")):
 +        raise errors.ConfigurationError("Incomplete configuration"
 +                                        " (missing cluster.rsahostkeypub)")
 +
 +      if not data.cluster.master_node in data.nodes:
 +        msg = ("The configuration denotes node %s as master, but does not"
 +               " contain information about this node" %
 +               data.cluster.master_node)
 +        raise errors.ConfigurationError(msg)
 +
 +      master_info = data.nodes[data.cluster.master_node]
 +      if master_info.name != self._my_hostname and not self._accept_foreign:
 +        msg = ("The configuration denotes node %s as master, while my"
 +               " hostname is %s; opening a foreign configuration is only"
 +               " possible in accept_foreign mode" %
 +               (master_info.name, self._my_hostname))
 +        raise errors.ConfigurationError(msg)
 +
 +      self._SetConfigData(data)
 +
 +      # Upgrade configuration if needed
 +      self._UpgradeConfig(saveafter=True)
 +    else:
 +      # poll until we acquire the lock
 +      while True:
 +        dict_data = \
 +          self._wconfd.LockConfig(self._GetWConfdContext(), bool(shared))
 +        logging.debug("Received '%s' from WConfd.LockConfig [shared=%s]",
 +                      str(dict_data), bool(shared))
 +        if dict_data is not None:
 +          break
 +        time.sleep(random.random())
 +
 +      try:
 +        self._SetConfigData(objects.ConfigData.FromDict(dict_data))
 +      except Exception, err:
 +        raise errors.ConfigurationError(err)
 +
 +      # Transitional fix until ConfigWriter is completely rewritten into
 +      # Haskell
 +      self._UpgradeConfig()
  
 +  def _CloseConfig(self, save):
 +    """Release resources relating the config data.
 +
 +    """
 +    if self._AddLockCount(-1) > 0:
 +      return # we still have the lock, do nothing
      try:
 -      data_dict = serializer.Load(raw_data)
 -      # Make sure the configuration has the right version
 -      _ValidateConfig(data_dict)
 -      data = objects.ConfigData.FromDict(data_dict)
 -    except errors.ConfigVersionMismatch:
 -      raise
 +      if save:
 +        self._WriteConfig()
      except Exception, err:
 -      raise errors.ConfigurationError(err)
 -
 -    if (not hasattr(data, "cluster") or
 -        not hasattr(data.cluster, "rsahostkeypub")):
 -      raise errors.ConfigurationError("Incomplete configuration"
 -                                      " (missing cluster.rsahostkeypub)")
 -
 -    if not data.cluster.master_node in data.nodes:
 -      msg = ("The configuration denotes node %s as master, but does not"
 -             " contain information about this node" %
 -             data.cluster.master_node)
 -      raise errors.ConfigurationError(msg)
 -
 -    master_info = data.nodes[data.cluster.master_node]
 -    if master_info.name != self._my_hostname and not accept_foreign:
 -      msg = ("The configuration denotes node %s as master, while my"
 -             " hostname is %s; opening a foreign configuration is only"
 -             " possible in accept_foreign mode" %
 -             (master_info.name, self._my_hostname))
 -      raise errors.ConfigurationError(msg)
 -
 -    self._config_data = data
 -    # reset the last serial as -1 so that the next write will cause
 -    # ssconf update
 -    self._last_cluster_serial = -1
 -
 -    # Upgrade configuration if needed
 -    self._UpgradeConfig()
 -
 -    self._cfg_id = utils.GetFileID(path=self._cfg_file)
 -
 -  def _UpgradeConfig(self):
 +      logging.critical("Can't write the configuration: %s", str(err))
 +      raise
 +    finally:
 +      if not self._offline:
 +        try:
 +          self._wconfd.UnlockConfig(self._GetWConfdContext())
 +        except AttributeError:
 +          # If the configuration hasn't been initialized yet, just ignore it.
 +          pass
 +        logging.debug("Configuration in WConfd unlocked")
 +
 +  # TODO: To WConfd
 +  def _UpgradeConfig(self, saveafter=False):
      """Run any upgrade steps.
  
      This method performs both in-object upgrades and also update some data
Simple merge