Get rid of confusing err=True option to invirt.remctl.remctl.
[invirt/packages/invirt-web.git] / code / controls.py
index 2ef8c9f..d03d4f9 100644 (file)
@@ -1,11 +1,6 @@
-"""
-Functions to perform remctls.
-"""
-
 import validation
 from invirt.common import CodeError, InvalidInput
 import random
 import validation
 from invirt.common import CodeError, InvalidInput
 import random
-import subprocess
 import sys
 import time
 import re
 import sys
 import time
 import re
@@ -14,6 +9,7 @@ import yaml
 
 from invirt.config import structs as config
 from invirt.database import Machine, Disk, Type, NIC, CDROM, session, meta
 
 from invirt.config import structs as config
 from invirt.database import Machine, Disk, Type, NIC, CDROM, session, meta
+from invirt.remctl import remctl as gen_remctl
 
 # ... and stolen from xend/uuid.py
 def randomUUID():
 
 # ... and stolen from xend/uuid.py
 def randomUUID():
@@ -27,39 +23,10 @@ def uuidToString(u):
                      "%02x" * 6]) % tuple(u)
 # end stolen code
 
                      "%02x" * 6]) % tuple(u)
 # end stolen code
 
-def kinit():
-    """Kinit with a given username and keytab"""
-    p = subprocess.Popen(['kinit', "-k", "-t", '/etc/invirt/keytab',
-                          'daemon/'+config.web.hostname],
-                         stderr=subprocess.PIPE)
-    e = p.wait()
-    if e:
-        raise CodeError("Error %s in kinit: %s" % (e, p.stderr.read()))
-
-def checkKinit():
-    """If we lack tickets, kinit."""
-    p = subprocess.Popen(['klist', '-s'])
-    if p.wait():
-        kinit()
-
-def remctl(*args, **kws):
-    """Perform a remctl and return the output.
-
-    kinits if necessary, and outputs errors to stderr.
-    """
-    checkKinit()
-    p = subprocess.Popen(['remctl', config.remote.hostname]
-                         + list(args),
-                         stdout=subprocess.PIPE,
-                         stderr=subprocess.PIPE)
-    v = p.wait()
-    if kws.get('err'):
-        return p.stdout.read(), p.stderr.read()
-    if v:
-        print >> sys.stderr, 'Error', v, 'on remctl', args, ':'
-        print >> sys.stderr, p.stderr.read()
-        raise CodeError('ERROR on remctl')
-    return p.stdout.read()
+def remctl(*args, **kwargs):
+    return gen_remctl(config.remote.hostname,
+                      principal='daemon/'+config.web.hostname,
+                      *args, **kwargs)
 
 def lvcreate(machine, disk):
     """Create a single disk for a machine"""
 
 def lvcreate(machine, disk):
     """Create a single disk for a machine"""
@@ -84,6 +51,7 @@ def lvinstall(machine, autoinstall):
     remctl('control', machine.name, 'install', 
            'dist=%s' % autoinstall.distribution,
            'mirror=%s' % autoinstall.mirror,
     remctl('control', machine.name, 'install', 
            'dist=%s' % autoinstall.distribution,
            'mirror=%s' % autoinstall.mirror,
+           'arch=%s' % autoinstall.arch,
            'imagesize=%s' % imagesize)
 
 def lvcopy(machine_orig_name, machine, rootpw):
            'imagesize=%s' % imagesize)
 
 def lvcopy(machine_orig_name, machine, rootpw):
@@ -96,16 +64,17 @@ def bootMachine(machine, cdtype):
     If cdtype is None, give no boot cd.  Otherwise, it is the string
     id of the CD (e.g. 'gutsy_i386')
     """
     If cdtype is None, give no boot cd.  Otherwise, it is the string
     id of the CD (e.g. 'gutsy_i386')
     """
-    if cdtype is not None:
-        out, err = remctl('control', machine.name, 'create', 
-                          cdtype, err=True)
-    else:
-        out, err = remctl('control', machine.name, 'create',
-                          err=True)
-    if 'already running' in err:
-        raise InvalidInput('action', 'create',
-                           'VM %s is already on' % machine.name)
-    elif err:
+    try:
+        if cdtype is not None:
+            out = remctl('control', machine.name, 'create', 
+                              cdtype)
+        else:
+            out = remctl('control', machine.name, 'create')
+    except CodeError, e:
+        if 'already running' in e.message:
+            raise InvalidInput('action', 'create',
+                               'VM %s is already on' % machine.name)
+        else:
         raise CodeError('"%s" on "control %s create %s' 
                         % (err, machine.name, cdtype))
 
         raise CodeError('"%s" on "control %s create %s' 
                         % (err, machine.name, cdtype))
 
@@ -120,7 +89,7 @@ def createVm(username, state, owner, contact, name, description, memory, disksiz
         machine.description = description
         machine.memory = memory
         machine.owner = owner
         machine.description = description
         machine.memory = memory
         machine.owner = owner
-        machine.administrator = owner
+        machine.administrator = None
         machine.contact = contact
         machine.uuid = uuidToString(randomUUID())
         machine.boot_off_cd = True
         machine.contact = contact
         machine.uuid = uuidToString(randomUUID())
         machine.boot_off_cd = True
@@ -142,11 +111,15 @@ def createVm(username, state, owner, contact, name, description, memory, disksiz
         session.rollback()
         raise
     makeDisks(machine)
         session.rollback()
         raise
     makeDisks(machine)
-    if autoinstall:
-        lvinstall(machine, autoinstall)
-    else:
-        # tell it to boot with cdrom
-        bootMachine(machine, cdrom)
+    try:
+        if autoinstall:
+            lvinstall(machine, autoinstall)
+        else:
+            # tell it to boot with cdrom
+            bootMachine(machine, cdrom)
+    except CodeError, e:
+        deleteVM(machine)
+        raise
     return machine
 
 def getList():
     return machine
 
 def getList():
@@ -184,29 +157,38 @@ def statusInfo(machine):
 
     Gets and parses xm list --long
     """
 
     Gets and parses xm list --long
     """
-    value_string, err_string = remctl('control', machine.name, 'list-long', 
-                                      err=True)
-    if 'Unknown command' in err_string:
-        raise CodeError("ERROR in remctl list-long %s is not registered" % 
-                        (machine.name,))
-    elif 'is not on' in err_string:
-        return None
-    elif err_string:
-        raise CodeError("ERROR in remctl list-long %s:  %s" % 
-                        (machine.name, err_string))
+    try:
+        value_string = remctl('control', machine.name, 'list-long')
+    except CodeError, e:
+        if 'is not on' in e.message:
+            return None
+        else:
+            raise
     status = parseStatus(value_string)
     return status
 
 def listHost(machine):
     """Return the host a machine is running on"""
     status = parseStatus(value_string)
     return status
 
 def listHost(machine):
     """Return the host a machine is running on"""
-    out, err = remctl('control', machine.name, 'listhost', err=True)
-    if err:
+    try:
+        out = remctl('control', machine.name, 'listhost')
+    except CodeError, e:
+        return None
+    return out.strip()
+
+def vnctoken(machine):
+    """Return a time-stamped VNC token"""
+    try:
+        out = remctl('control', machine.name, 'vnctoken')
+    except CodeError, e:
         return None
     return out.strip()
 
 def deleteVM(machine):
     """Delete a VM."""
         return None
     return out.strip()
 
 def deleteVM(machine):
     """Delete a VM."""
-    remctl('control', machine.name, 'destroy', err=True)
+    try:
+        remctl('control', machine.name, 'destroy')
+    except CodeError:
+        pass
     session.begin()
     delete_disk_pairs = [(machine.name, d.guest_device_name) 
                          for d in machine.disks]
     session.begin()
     delete_disk_pairs = [(machine.name, d.guest_device_name) 
                          for d in machine.disks]
@@ -236,20 +218,17 @@ def commandResult(username, state, fields):
                       'Delete VM'):
         raise CodeError("Invalid action '%s'" % action)
     if action == 'Reboot':
                       'Delete VM'):
         raise CodeError("Invalid action '%s'" % action)
     if action == 'Reboot':
-        if cdrom is not None:
-            out, err = remctl('control', machine.name, 'reboot', cdrom,
-                              err=True)
-        else:
-            out, err = remctl('control', machine.name, 'reboot',
-                              err=True)
-        if err:
-            if re.match("machine '.*' is not on", err):
+        try:
+            if cdrom is not None:
+                out = remctl('control', machine.name, 'reboot', cdrom)
+            else:
+                out = remctl('control', machine.name, 'reboot')
+        except CodeError, e:
+            if re.match("machine '.*' is not on", e.message):
                 raise InvalidInput("action", "reboot", 
                                    "Machine is not on")
             else:
                 raise InvalidInput("action", "reboot", 
                                    "Machine is not on")
             else:
-                print >> sys.stderr, 'Error on reboot:'
-                print >> sys.stderr, err
-                raise CodeError('ERROR on remctl')
+                raise
                 
     elif action == 'Power on':
         if validation.maxMemory(username, state, machine) < machine.memory:
                 
     elif action == 'Power on':
         if validation.maxMemory(username, state, machine) < machine.memory:
@@ -258,25 +237,23 @@ def commandResult(username, state, fields):
                                "to turn on this machine.")
         bootMachine(machine, cdrom)
     elif action == 'Power off':
                                "to turn on this machine.")
         bootMachine(machine, cdrom)
     elif action == 'Power off':
-        out, err = remctl('control', machine.name, 'destroy', err=True)
-        if err:
-            if re.match("machine '.*' is not on", err):
+        try:
+            out = remctl('control', machine.name, 'destroy')
+        except CodeError, e:
+            if re.match("machine '.*' is not on", e.message):
                 raise InvalidInput("action", "Power off", 
                                    "Machine is not on.")
             else:
                 raise InvalidInput("action", "Power off", 
                                    "Machine is not on.")
             else:
-                print >> sys.stderr, 'Error on power off:'
-                print >> sys.stderr, err
-                raise CodeError('ERROR on remctl')
+                raise
     elif action == 'Shutdown':
     elif action == 'Shutdown':
-        out, err = remctl('control', machine.name, 'shutdown', err=True)
-        if err:
-            if re.match("machine '.*' is not on", err):
+        try:
+            out = remctl('control', machine.name, 'shutdown')
+        except CodeError, e:
+            if re.match("machine '.*' is not on", e.message):
                 raise InvalidInput("action", "Shutdown", 
                                    "Machine is not on.")
             else:
                 raise InvalidInput("action", "Shutdown", 
                                    "Machine is not on.")
             else:
-                print >> sys.stderr, 'Error on Shutdown:'
-                print >> sys.stderr, err
-                raise CodeError('ERROR on remctl')
+                raise
     elif action == 'Delete VM':
         deleteVM(machine)
 
     elif action == 'Delete VM':
         deleteVM(machine)