Correct the incomplete fix from r1155
[invirt/packages/invirt-web.git] / code / controls.py
index d20f5f0..7b4558e 100644 (file)
@@ -1,11 +1,6 @@
-"""
-Functions to perform remctls.
-"""
-
 import validation
 import validation
-from webcommon import CodeError, InvalidInput
+from invirt.common import CodeError, InvalidInput
 import random
 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"""
@@ -78,10 +45,14 @@ def getswap(disksize, memsize):
 def lvinstall(machine, autoinstall):
     disksize = machine.disks[0].size
     memsize = machine.memory
 def lvinstall(machine, autoinstall):
     disksize = machine.disks[0].size
     memsize = machine.memory
-    imagesize = disksize - getswap(disksize, memsize)
+    swapsize = getswap(disksize, memsize)
+    imagesize = disksize - swapsize
     ip = machine.nics[0].ip
     ip = machine.nics[0].ip
-    remctl('web', 'install', machine.name, autoinstall.distribution,
-           autoinstall.mirror, str(imagesize), ip)
+    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):
     """Copy a golden image onto a machine's disk"""
 
 def lvcopy(machine_orig_name, machine, rootpw):
     """Copy a golden image onto a machine's disk"""
@@ -109,45 +80,41 @@ def bootMachine(machine, cdtype):
 def createVm(username, state, owner, contact, name, description, memory, disksize, machine_type, cdrom, autoinstall):
     """Create a VM and put it in the database"""
     # put stuff in the table
 def createVm(username, state, owner, contact, name, description, memory, disksize, machine_type, cdrom, autoinstall):
     """Create a VM and put it in the database"""
     # put stuff in the table
-    transaction = ctx.current.create_transaction()
+    session.begin()
     try:
         validation.Validate(username, state, name=name, description=description, owner=owner, memory=memory, disksize=disksize/1024.)
     try:
         validation.Validate(username, state, name=name, description=description, owner=owner, memory=memory, disksize=disksize/1024.)
-        res = meta.engine.execute('select nextval('
-                                  '\'"machines_machine_id_seq"\')')
-        id = res.fetchone()[0]
         machine = Machine()
         machine = Machine()
-        machine.machine_id = id
         machine.name = name
         machine.description = description
         machine.memory = memory
         machine.owner = owner
         machine.name = name
         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
-        machine.type_id = machine_type.type_id
-        ctx.current.save(machine)
-        disk = Disk(machine_id=machine.machine_id,
+        machine.type = machine_type
+        session.save_or_update(machine)
+        disk = Disk(machine=machine,
                     guest_device_name='hda', size=disksize)
                     guest_device_name='hda', size=disksize)
-        open_nics = NIC.select_by(machine_id=None)
-        if not open_nics: #No IPs left!
+        nic = NIC.query().filter_by(machine_id=None).first()
+        if not nic: #No IPs left!
             raise CodeError("No IP addresses left!  "
                             "Contact %s." % config.web.errormail)
             raise CodeError("No IP addresses left!  "
                             "Contact %s." % config.web.errormail)
-        nic = open_nics[0]
-        nic.machine_id = machine.machine_id
+        nic.machine = machine
         nic.hostname = name
         nic.hostname = name
-        ctx.current.save(nic)
-        ctx.current.save(disk)
+        session.save_or_update(nic)
+        session.save_or_update(disk)
         cache_acls.refreshMachine(machine)
         cache_acls.refreshMachine(machine)
-        transaction.commit()
+        session.commit()
     except:
     except:
-        transaction.rollback()
+        session.rollback()
         raise
     makeDisks(machine)
     if autoinstall:
         lvinstall(machine, autoinstall)
         raise
     makeDisks(machine)
     if autoinstall:
         lvinstall(machine, autoinstall)
-    # tell it to boot with cdrom
-    bootMachine(machine, cdrom)
+    else:
+        # tell it to boot with cdrom
+        bootMachine(machine, cdrom)
     return machine
 
 def getList():
     return machine
 
 def getList():
@@ -205,33 +172,40 @@ def listHost(machine):
         return None
     return out.strip()
 
         return None
     return out.strip()
 
+def vnctoken(machine):
+    """Return a time-stamped VNC token"""
+    out, err = remctl('control', machine.name, 'vnctoken', err=True)
+    if err:
+        return None
+    return out.strip()
+
 def deleteVM(machine):
     """Delete a VM."""
     remctl('control', machine.name, 'destroy', err=True)
 def deleteVM(machine):
     """Delete a VM."""
     remctl('control', machine.name, 'destroy', err=True)
-    transaction = ctx.current.create_transaction()
+    session.begin()
     delete_disk_pairs = [(machine.name, d.guest_device_name) 
                          for d in machine.disks]
     try:
     delete_disk_pairs = [(machine.name, d.guest_device_name) 
                          for d in machine.disks]
     try:
+        for mname, dname in delete_disk_pairs:
+            remctl('web', 'lvremove', mname, dname)
         for nic in machine.nics:
             nic.machine_id = None
             nic.hostname = None
         for nic in machine.nics:
             nic.machine_id = None
             nic.hostname = None
-            ctx.current.save(nic)
+            session.save_or_update(nic)
         for disk in machine.disks:
         for disk in machine.disks:
-            ctx.current.delete(disk)
-        ctx.current.delete(machine)
-        transaction.commit()
+            session.delete(disk)
+        session.delete(machine)
+        session.commit()
     except:
     except:
-        transaction.rollback()
+        session.rollback()
         raise
         raise
-    for mname, dname in delete_disk_pairs:
-        remctl('web', 'lvremove', mname, dname)
 
 def commandResult(username, state, fields):
     start_time = 0
     machine = validation.Validate(username, state, machine_id=fields.getfirst('machine_id')).machine
     action = fields.getfirst('action')
     cdrom = fields.getfirst('cdrom')
 
 def commandResult(username, state, fields):
     start_time = 0
     machine = validation.Validate(username, state, machine_id=fields.getfirst('machine_id')).machine
     action = fields.getfirst('action')
     cdrom = fields.getfirst('cdrom')
-    if cdrom is not None and not CDROM.get(cdrom):
+    if cdrom is not None and not CDROM.query().filter_by(cdrom_id=cdrom).one():
         raise CodeError("Invalid cdrom type '%s'" % cdrom)    
     if action not in ('Reboot', 'Power on', 'Power off', 'Shutdown', 
                       'Delete VM'):
         raise CodeError("Invalid cdrom type '%s'" % cdrom)    
     if action not in ('Reboot', 'Power on', 'Power off', 'Shutdown', 
                       'Delete VM'):