Add a test opcode that sleeps for a given duration
[ganeti-local] / daemons / ganeti-noded
index e5afb37..f344474 100755 (executable)
@@ -38,6 +38,7 @@ from ganeti import constants
 from ganeti import objects
 from ganeti import errors
 from ganeti import ssconf
+from ganeti import utils
 
 from twisted.spread import pb
 from twisted.internet import reactor
@@ -96,11 +97,11 @@ class ServerObject(pb.Avatar):
     """Create a block device.
 
     """
-    bdev_s, size, on_primary, info = params
-    bdev = objects.ConfigObject.Loads(bdev_s)
+    bdev_s, size, owner, on_primary, info = params
+    bdev = objects.Disk.FromDict(bdev_s)
     if bdev is None:
       raise ValueError("can't unserialize data!")
-    return backend.CreateBlockDevice(bdev, size, on_primary, info)
+    return backend.CreateBlockDevice(bdev, size, owner, on_primary, info)
 
   @staticmethod
   def perspective_blockdev_remove(params):
@@ -108,19 +109,27 @@ class ServerObject(pb.Avatar):
 
     """
     bdev_s = params[0]
-    bdev = objects.ConfigObject.Loads(bdev_s)
+    bdev = objects.Disk.FromDict(bdev_s)
     return backend.RemoveBlockDevice(bdev)
 
   @staticmethod
+  def perspective_blockdev_rename(params):
+    """Remove a block device.
+
+    """
+    devlist = [(objects.Disk.FromDict(ds), uid) for ds, uid in params]
+    return backend.RenameBlockDevices(devlist)
+
+  @staticmethod
   def perspective_blockdev_assemble(params):
     """Assemble a block device.
 
     """
-    bdev_s, on_primary = params
-    bdev = objects.ConfigObject.Loads(bdev_s)
+    bdev_s, owner, on_primary = params
+    bdev = objects.Disk.FromDict(bdev_s)
     if bdev is None:
       raise ValueError("can't unserialize data!")
-    return backend.AssembleBlockDevice(bdev, on_primary)
+    return backend.AssembleBlockDevice(bdev, owner, on_primary)
 
   @staticmethod
   def perspective_blockdev_shutdown(params):
@@ -128,13 +137,13 @@ class ServerObject(pb.Avatar):
 
     """
     bdev_s = params[0]
-    bdev = objects.ConfigObject.Loads(bdev_s)
+    bdev = objects.Disk.FromDict(bdev_s)
     if bdev is None:
       raise ValueError("can't unserialize data!")
     return backend.ShutdownBlockDevice(bdev)
 
   @staticmethod
-  def perspective_blockdev_addchild(params):
+  def perspective_blockdev_addchildren(params):
     """Add a child to a mirror device.
 
     Note: this is only valid for mirror devices. It's the caller's duty
@@ -142,14 +151,14 @@ class ServerObject(pb.Avatar):
 
     """
     bdev_s, ndev_s = params
-    bdev = objects.ConfigObject.Loads(bdev_s)
-    ndev = objects.ConfigObject.Loads(ndev_s)
-    if bdev is None or ndev is None:
+    bdev = objects.Disk.FromDict(bdev_s)
+    ndevs = [objects.Disk.FromDict(disk_s) for disk_s in ndev_s]
+    if bdev is None or ndevs.count(None) > 0:
       raise ValueError("can't unserialize data!")
-    return backend.MirrorAddChild(bdev, ndev)
+    return backend.MirrorAddChildren(bdev, ndevs)
 
   @staticmethod
-  def perspective_blockdev_removechild(params):
+  def perspective_blockdev_removechildren(params):
     """Remove a child from a mirror device.
 
     This is only valid for mirror devices, of course. It's the callers
@@ -157,18 +166,18 @@ class ServerObject(pb.Avatar):
 
     """
     bdev_s, ndev_s = params
-    bdev = objects.ConfigObject.Loads(bdev_s)
-    ndev = objects.ConfigObject.Loads(ndev_s)
-    if bdev is None or ndev is None:
+    bdev = objects.Disk.FromDict(bdev_s)
+    ndevs = [objects.Disk.FromDict(disk_s) for disk_s in ndev_s]
+    if bdev is None or ndevs.count(None) > 0:
       raise ValueError("can't unserialize data!")
-    return backend.MirrorRemoveChild(bdev, ndev)
+    return backend.MirrorRemoveChildren(bdev, ndevs)
 
   @staticmethod
   def perspective_blockdev_getmirrorstatus(params):
     """Return the mirror status for a list of disks.
 
     """
-    disks = [objects.ConfigObject.Loads(dsk_s)
+    disks = [objects.Disk.FromDict(dsk_s)
             for dsk_s in params]
     return backend.GetMirrorStatus(disks)
 
@@ -179,7 +188,7 @@ class ServerObject(pb.Avatar):
     This will try to find but not activate a disk.
 
     """
-    disk = objects.ConfigObject.Loads(params[0])
+    disk = objects.Disk.FromDict(params[0])
     return backend.FindBlockDevice(disk)
 
   @staticmethod
@@ -191,7 +200,7 @@ class ServerObject(pb.Avatar):
     remove by calling the generic block device remove call.
 
     """
-    cfbd = objects.ConfigObject.Loads(params[0])
+    cfbd = objects.Disk.FromDict(params[0])
     return backend.SnapshotBlockDevice(cfbd)
 
   # export/import  --------------------------
@@ -201,9 +210,9 @@ class ServerObject(pb.Avatar):
     """Export a given snapshot.
 
     """
-    disk = objects.ConfigObject.Loads(params[0])
+    disk = objects.Disk.FromDict(params[0])
     dest_node = params[1]
-    instance = objects.ConfigObject.Loads(params[2])
+    instance = objects.Instance.FromDict(params[2])
     return backend.ExportSnapshot(disk, dest_node, instance)
 
   @staticmethod
@@ -211,8 +220,8 @@ class ServerObject(pb.Avatar):
     """Expose the finalize export functionality.
 
     """
-    instance = objects.ConfigObject.Loads(params[0])
-    snap_disks = [objects.ConfigObject.Loads(str_data)
+    instance = objects.Instance.FromDict(params[0])
+    snap_disks = [objects.Disk.FromDict(str_data)
                   for str_data in params[1]]
     return backend.FinalizeExport(instance, snap_disks)
 
@@ -284,7 +293,7 @@ class ServerObject(pb.Avatar):
 
     """
     inst_s, os_disk, swap_disk = params
-    inst = objects.ConfigObject.Loads(inst_s)
+    inst = objects.Instance.FromDict(inst_s)
     return backend.AddOSToInstance(inst, os_disk, swap_disk)
 
   @staticmethod
@@ -293,7 +302,7 @@ class ServerObject(pb.Avatar):
 
     """
     inst_s, old_name, os_disk, swap_disk = params
-    inst = objects.ConfigObject.Loads(inst_s)
+    inst = objects.Instance.FromDict(inst_s)
     return backend.RunRenameInstance(inst, old_name, os_disk, swap_disk)
 
   @staticmethod
@@ -302,7 +311,7 @@ class ServerObject(pb.Avatar):
 
     """
     inst_s, os_disk, swap_disk, src_node, src_image = params
-    inst = objects.ConfigObject.Loads(inst_s)
+    inst = objects.Instance.FromDict(inst_s)
     return backend.ImportOSIntoInstance(inst, os_disk, swap_disk,
                                         src_node, src_image)
 
@@ -311,7 +320,7 @@ class ServerObject(pb.Avatar):
     """Shutdown an instance.
 
     """
-    instance = objects.ConfigObject.Loads(params[0])
+    instance = objects.Instance.FromDict(params[0])
     return backend.ShutdownInstance(instance)
 
   @staticmethod
@@ -319,11 +328,21 @@ class ServerObject(pb.Avatar):
     """Start an instance.
 
     """
-    instance = objects.ConfigObject.Loads(params[0])
+    instance = objects.Instance.FromDict(params[0])
     extra_args = params[1]
     return backend.StartInstance(instance, extra_args)
 
   @staticmethod
+  def perspective_instance_reboot(params):
+    """Reboot an instance.
+
+    """
+    instance = objects.Instance.FromDict(params[0])
+    reboot_type = params[1]
+    extra_args = params[2]
+    return backend.RebootInstance(instance, reboot_type, extra_args)
+
+  @staticmethod
   def perspective_instance_info(params):
     """Query instance information.
 
@@ -347,6 +366,14 @@ class ServerObject(pb.Avatar):
   # node --------------------------
 
   @staticmethod
+  def perspective_node_tcp_ping(params):
+    """Do a TcpPing on the remote node.
+
+    """
+    return utils.TcpPing(params[0], params[1], params[2],
+                         timeout=params[3], live_port_needed=params[4])
+
+  @staticmethod
   def perspective_node_info(params):
     """Query node information.
 
@@ -424,23 +451,7 @@ class ServerObject(pb.Avatar):
     """Query detailed information about existing OSes.
 
     """
-    os_list = backend.DiagnoseOS()
-    if not os_list:
-      # this catches also return values of 'False',
-      # for which we can't iterate over
-      return os_list
-    result = []
-    for data in os_list:
-      if isinstance(data, objects.OS):
-        result.append(data.Dumps())
-      elif isinstance(data, errors.InvalidOS):
-        result.append(data.args)
-      else:
-        raise errors.ProgrammerError("Invalid result from backend.DiagnoseOS"
-                                     " (class %s, %s)" %
-                                     (str(data.__class__), data))
-
-    return result
+    return [os.ToDict() for os in backend.DiagnoseOS()]
 
   @staticmethod
   def perspective_os_get(params):
@@ -449,10 +460,10 @@ class ServerObject(pb.Avatar):
     """
     name = params[0]
     try:
-      os_obj = backend.OSFromDisk(name).Dumps()
+      os_obj = backend.OSFromDisk(name)
     except errors.InvalidOS, err:
-      os_obj = err.args
-    return os_obj
+      os_obj = objects.OS.FromInvalidOS(err)
+    return os_obj.ToDict()
 
   # hooks -----------------------
 
@@ -465,6 +476,16 @@ class ServerObject(pb.Avatar):
     hr = backend.HooksRunner()
     return hr.RunHooks(hpath, phase, env)
 
+  # test -----------------------
+
+  @staticmethod
+  def perspective_test_delay(params):
+    """Run test delay.
+
+    """
+    duration = params[0]
+    return utils.TestDelay(duration)
+
 
 class MyRealm:
   """Simple realm that forwards all requests to a ServerObject.
@@ -508,6 +529,7 @@ def main():
 
   """
   options, args = ParseOptions()
+  utils.debug = options.debug
   for fname in (constants.SSL_CERT_FILE,):
     if not os.path.isfile(fname):
       print "config %s not there, will not run." % fname
@@ -583,7 +605,7 @@ def createDaemon():
       os.close(fd)
     except OSError: # ERROR, fd wasn't open to begin with (ignored)
       pass
-  os.open(REDIRECT_TO, os.O_RDWR|os.O_CREAT|os.O_APPEND) # standard input (0)
+  os.open(REDIRECT_TO, os.O_RDWR|os.O_CREAT|os.O_APPEND, 0600)
   # Duplicate standard input to standard output and standard error.
   os.dup2(0, 1)     # standard output (1)
   os.dup2(0, 2)     # standard error (2)