Merge branch 'master' into next
authorGuido Trotter <ultrotter@google.com>
Wed, 20 May 2009 13:13:56 +0000 (14:13 +0100)
committerGuido Trotter <ultrotter@google.com>
Wed, 20 May 2009 13:14:34 +0000 (14:14 +0100)
Signed-off-by: Guido Trotter <ultrotter@google.com>

NEWS
README
configure.ac
daemons/ganeti-watcher
doc/rapi.rst
lib/cmdlib.py
lib/hypervisor/hv_kvm.py
lib/rapi/rlib2.py
man/gnt-instance.sgml
qa/qa_instance.py
scripts/gnt-instance

diff --git a/NEWS b/NEWS
index dc8cc90..768dc72 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+Version 2.0 release candidate 5
+  - fix a couple of bugs (validation, argument checks)
+  - fix gnt-cluster getmaster on non-master nodes (regression)
+  - some small improvements to RAPI and IAllocator
+  - make watcher automatically start the master daemon if down
+
 Version 2.0 release candidate 4
   - change the OS list to not require locks; this helps with big
     clusters
diff --git a/README b/README
index 1d8b883..0b05252 100644 (file)
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
-Ganeti 1.2
+Ganeti 2.0
 ==========
 
-For installation instructions, read the INSTALL and the doc/install.pdf
+For installation instructions, read the INSTALL and the doc/install.html
 files.
 
 For a brief introduction, read the ganeti(7) manpage and the other pages
index 75e3531..19e0bf3 100644 (file)
@@ -2,7 +2,7 @@
 m4_define([gnt_version_major], [2])
 m4_define([gnt_version_minor], [0])
 m4_define([gnt_version_revision], [0])
-m4_define([gnt_version_suffix], [~rc4])
+m4_define([gnt_version_suffix], [~rc5])
 m4_define([gnt_version_full],
           m4_format([%d.%d.%d%s],
                     gnt_version_major, gnt_version_minor,
index 64eda10..3cf96e5 100755 (executable)
@@ -39,6 +39,7 @@ from ganeti import serializer
 from ganeti import errors
 from ganeti import opcodes
 from ganeti import cli
+from ganeti import luxi
 
 
 MAXTRIES = 5
@@ -69,6 +70,16 @@ def Indent(s, prefix='| '):
   return "%s%s\n" % (prefix, ('\n' + prefix).join(s.splitlines()))
 
 
+def StartMaster():
+  """Try to start the master daemon.
+
+  """
+  result = utils.RunCmd(['ganeti-masterd'])
+  if result.failed:
+    logging.error("Can't start the master daemon: output '%s'", result.output)
+  return not result.failed
+
+
 class WatcherState(object):
   """Interface to a state file recording restart attempts.
 
@@ -448,6 +459,7 @@ def main():
   utils.SetupLogging(constants.LOG_WATCHER, debug=options.debug,
                      stderr_logging=options.debug)
 
+  update_file = True
   try:
     notepad = WatcherState()
     try:
@@ -455,7 +467,17 @@ def main():
         client = cli.GetClient()
       except errors.OpPrereqError:
         # this is, from cli.GetClient, a not-master case
+        logging.debug("Not on master, exiting")
         sys.exit(constants.EXIT_SUCCESS)
+      except luxi.NoMasterError, err:
+        logging.warning("Master seems to be down (%s), trying to restart",
+                        str(err))
+        if not StartMaster():
+          logging.critical("Can't start the master, exiting")
+          update_file = False
+          sys.exit(constants.EXIT_FAILURE)
+        # else retry the connection
+        client = cli.GetClient()
 
       try:
         watcher = Watcher(options, notepad)
@@ -465,7 +487,10 @@ def main():
 
       watcher.Run()
     finally:
-      notepad.Save()
+      if update_file:
+        notepad.Save()
+      else:
+        logging.debug("Not updating status file due to failure")
   except SystemExit:
     raise
   except NotMasterError:
index c2ed7c4..8dc8f3b 100644 (file)
@@ -49,7 +49,7 @@ Python
 ::
 
   import urllib2
-  f = urllib2.urlopen('https://CLUSTERNAME:5080/info')
+  f = urllib2.urlopen('https://CLUSTERNAME:5080/2/info')
   print f.read()
 
 
@@ -63,7 +63,7 @@ JavaScript
 
 ::
 
-  var url = 'https://CLUSTERNAME:5080/info';
+  var url = 'https://CLUSTERNAME:5080/2/info';
   var info;
   var xmlreq = new XMLHttpRequest();
   xmlreq.onreadystatechange = function () {
index 1a9e85f..a71c5d7 100644 (file)
@@ -1417,7 +1417,7 @@ class LUSetClusterParams(LogicalUnit):
   _OP_REQP = []
   REQ_BGL = False
 
-  def CheckParameters(self):
+  def CheckArguments(self):
     """Check parameters
 
     """
@@ -1426,7 +1426,7 @@ class LUSetClusterParams(LogicalUnit):
     if self.op.candidate_pool_size is not None:
       try:
         self.op.candidate_pool_size = int(self.op.candidate_pool_size)
-      except ValueError, err:
+      except (ValueError, TypeError), err:
         raise errors.OpPrereqError("Invalid candidate_pool_size value: %s" %
                                    str(err))
       if self.op.candidate_pool_size < 1:
@@ -5939,7 +5939,7 @@ class LUSetInstanceParams(LogicalUnit):
         self.warn.append("Can't get info from primary node %s" % pnode)
       else:
         if not instance_info.failed and instance_info.data:
-          current_mem = instance_info.data['memory']
+          current_mem = int(instance_info.data['memory'])
         else:
           # Assume instance not running
           # (there is a slight race condition here, but it's not very probable,
@@ -6752,6 +6752,8 @@ class IAllocator(object):
         "disk_template": iinfo.disk_template,
         "hypervisor": iinfo.hypervisor,
         }
+      pir["disk_space_total"] = _ComputeDiskSize(iinfo.disk_template,
+                                                 pir["disks"])
       instance_data[iinfo.name] = pir
 
     data["instances"] = instance_data
index ee33894..3dec178 100644 (file)
@@ -194,9 +194,9 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     while arg_list:
       arg =  arg_list.pop(0)
       if arg == '-m':
-        memory = arg_list.pop(0)
+        memory = int(arg_list.pop(0))
       elif arg == '-smp':
-        vcpus = arg_list.pop(0)
+        vcpus = int(arg_list.pop(0))
 
     return (instance_name, pid, memory, vcpus, stat, times)
 
index 9e617bf..79b95da 100644 (file)
@@ -34,6 +34,7 @@ I_FIELDS = ["name", "admin_state", "os",
             "pnode", "snodes",
             "disk_template",
             "nic.ips", "nic.macs", "nic.bridges",
+            "network_port",
             "disk.sizes", "disk_usage",
             "beparams", "hvparams",
             "oper_state", "oper_ram", "status",
index edf267e..8ca11de 100644 (file)
                   initrd to boot the instance with. Xen PVM instances
                   can use this always, while for KVM if this option is
                   only used if the <option>kernel_path</option> option
-                  is also specified.
+                  is also specified. You can pass here either an
+                  absolute filename (the path to the initrd) if you
+                  want to use an initrd, or use the format
+                  <userinput>no_initrd_path</userinput> for no initrd.
                 </para>
               </listitem>
             </varlistentry>
index fe5dfb5..af3afeb 100644 (file)
@@ -170,7 +170,7 @@ def TestInstanceModify(instance):
     ["-H", "%s=%s" % (constants.HV_KERNEL_PATH, test_kernel)],
     ["-H", "%s=%s" % (constants.HV_KERNEL_PATH, constants.VALUE_DEFAULT)],
     ["-H", "%s=%s" % (constants.HV_INITRD_PATH, test_initrd)],
-    ["-H", "%s=%s" % (constants.HV_INITRD_PATH, constants.VALUE_NONE)],
+    ["-H", "no_%s" % (constants.HV_INITRD_PATH, )],
     ["-H", "%s=%s" % (constants.HV_INITRD_PATH, constants.VALUE_DEFAULT)],
 
     # TODO: bridge tests
index 7b93e3b..a54672c 100755 (executable)
@@ -154,29 +154,6 @@ def _ConfirmOperation(inames, text):
   return choice
 
 
-def _TransformPath(user_input):
-  """Transform a user path into a canonical value.
-
-  This function transforms the a path passed as textual information
-  into the constants that the LU code expects.
-
-  """
-  if user_input:
-    if user_input.lower() == "default":
-      result_path = constants.VALUE_DEFAULT
-    elif user_input.lower() == "none":
-      result_path = constants.VALUE_NONE
-    else:
-      if not os.path.isabs(user_input):
-        raise errors.OpPrereqError("Path '%s' is not an absolute filename" %
-                                   user_input)
-      result_path = user_input
-  else:
-    result_path = constants.VALUE_DEFAULT
-
-  return result_path
-
-
 def _EnsureInstancesExist(client, names):
   """Check for and ensure the given instance names exist.