Python 2.4 support
[invirt/packages/invirt-web.git] / templates / main.py
index e2a88b3..642490f 100755 (executable)
@@ -13,7 +13,6 @@ import sha
 import hmac
 import datetime
 
-print 'Content-Type: text/html\n'
 sys.stderr = sys.stdout
 sys.path.append('/home/ecprice/.local/lib/python2.5/site-packages')
 
@@ -24,6 +23,14 @@ import random
 class MyException(Exception):
     pass
 
+def helppopup(subj):
+    return '<span class="helplink"><a href="help?subject='+subj+'&amp;simple=true" target="_blank" onclick="return helppopup(\''+subj+'\')">(?)</a></span>'
+
+
+global_dict = {}
+global_dict['helppopup'] = helppopup
+
+
 # ... and stolen from xend/uuid.py
 def randomUUID():
     """Generate a random UUID."""
@@ -41,11 +48,13 @@ def maxDisk(user, machine=None):
     return 10.0
 
 def haveAccess(user, machine):
-    return True
+    if user.username == 'moo':
+        return True
+    return machine.owner == user.username
 
 def error(op, user, fields, err):
     d = dict(op=op, user=user, errorMessage=str(err))
-    print Template(file='error.tmpl', searchList=d);
+    print Template(file='error.tmpl', searchList=[d, global_dict]);
 
 def validMachineName(name):
     """Check that name is valid for a machine name"""
@@ -54,7 +63,10 @@ def validMachineName(name):
     charset = string.ascii_letters + string.digits + '-_'
     if name[0] in '-_' or len(name) > 22:
         return False
-    return all(x in charset for x in name)
+    for x in name:
+        if x not in charset:
+            return False
+    return True
 
 def kinit(username = 'tabbott/extra', keytab = '/etc/tabbott.keytab'):
     """Kinit with a given username and keytab"""
@@ -212,36 +224,44 @@ def createVm(user, name, memory, disk, is_hvm, cdrom):
 
     return machine
 
-def create(user, fields):
-    name = fields.getfirst('name')
-    if not validMachineName(name):
-        raise MyException("Invalid name '%s'" % name)
-    name = user.username + '_' + name.lower()
-
-    if Machine.get_by(name=name):
-        raise MyException("A machine named '%s' already exists" % name)
-    
-    memory = fields.getfirst('memory')
+def validMemory(user, memory, machine=None):
     try:
         memory = int(memory)
         if memory <= 0:
             raise ValueError
     except ValueError:
         raise MyException("Invalid memory amount")
-    if memory > maxMemory(user):
+    if memory > maxMemory(user, machine):
         raise MyException("Too much memory requested")
-    
-    disk = fields.getfirst('disk')
+    return memory
+
+def validDisk(user, disk, machine=None):
     try:
         disk = float(disk)
-        if disk > maxDisk(user):
+        if disk > maxDisk(user, machine):
             raise MyException("Too much disk requested")
         disk = int(disk * 1024)
         if disk <= 0:
             raise ValueError
     except ValueError:
         raise MyException("Invalid disk amount")
+    return disk
+
+def create(user, fields):
+    name = fields.getfirst('name')
+    if not validMachineName(name):
+        raise MyException("Invalid name '%s'" % name)
+    name = user.username + '_' + name.lower()
+
+    if Machine.get_by(name=name):
+        raise MyException("A machine named '%s' already exists" % name)
+    
+    memory = fields.getfirst('memory')
+    memory = validMemory(user, memory)
     
+    disk = fields.getfirst('disk')
+    disk = validDisk(user, disk)
+
     vm_type = fields.getfirst('vmtype')
     if vm_type not in ('hvm', 'paravm'):
         raise MyException("Invalid vm type '%s'"  % vm_type)    
@@ -257,14 +277,21 @@ def create(user, fields):
     d = dict(user=user,
              machine=machine)
     print Template(file='create.tmpl',
-                   searchList=d);
+                   searchList=[d, global_dict]);
 
 def listVms(user, fields):
-    machines = Machine.select()
+    machines = [m for m in Machine.select() if haveAccess(user, m)]    
     on = {}
     has_vnc = {}
     uptimes = getUptimes(machines)
-    on = has_vnc = uptimes
+    on = uptimes
+    for m in machines:
+        if not on.get(m.name):
+            has_vnc[m.name] = 'Off'
+        elif m.type.hvm:
+            has_vnc[m.name] = True
+        else:
+            has_vnc[m.name] = "ParaVM"+helppopup("paravm_console")
     #     for m in machines:
     #         status = statusInfo(m)
     #         on[m.name] = status is not None
@@ -276,7 +303,7 @@ def listVms(user, fields):
              has_vnc=has_vnc,
              uptimes=uptimes,
              cdroms=CDROM.select())
-    print Template(file='list.tmpl', searchList=d)
+    print Template(file='list.tmpl', searchList=[d, global_dict])
 
 def testMachineId(user, machineId, exists=True):
     if machineId is None:
@@ -327,7 +354,7 @@ def vnc(user, fields):
              hostname=os.environ.get('SERVER_NAME', 'localhost'),
              authtoken=token)
     print Template(file='vnc.tmpl',
-                   searchList=d)
+                   searchList=[d, global_dict])
 
 def getNicInfo(data_dict, machine):
     data_dict['num_nics'] = len(machine.nics)
@@ -402,11 +429,32 @@ def command(user, fields):
     d = dict(user=user,
              command=action,
              machine=machine)
-    print Template(file="command.tmpl", searchList=d)
+    print Template(file="command.tmpl", searchList=[d, global_dict])
         
 def modify(user, fields):
     machine = testMachineId(user, fields.getfirst('machine_id'))
     
+def help(user, fields):
+    simple = fields.getfirst('simple')
+    subjects = fields.getlist('subject')
+    
+    mapping = dict(paravm_console="""
+ParaVM machines do not support console access over VNC.  To access
+these machines, you either need to boot with a liveCD and ssh in or
+hope that the sipb-xen maintainers add support for serial consoles.""",
+                   hvm_paravm="""
+HVM machines use the virtualization features of the processor, while
+ParaVM machines use Xen's emulation of virtualization features.  You
+want an HVM virtualized machine.""",
+                   cpu_weight="""Don't ask us!  We're as mystified as you are.""")
+    
+    d = dict(user=user,
+             simple=simple,
+             subjects=subjects,
+             mapping=mapping)
+    
+    print Template(file="help.tmpl", searchList=[d, global_dict])
+    
 
 def info(user, fields):
     machine = testMachineId(user, fields.getfirst('machine_id'))
@@ -426,13 +474,14 @@ def info(user, fields):
     display_fields = [('name', 'Name'),
                       ('owner', 'Owner'),
                       ('contact', 'Contact'),
+                      ('type', 'Type'),
                       'NIC_INFO',
                       ('uptime', 'uptime'),
                       ('cputime', 'CPU usage'),
                       ('memory', 'RAM'),
                       'DISK_INFO',
                       ('state', 'state (xen format)'),
-                      ('cpu_weight', 'CPU weight'),
+                      ('cpu_weight', 'CPU weight'+helppopup('cpu_weight')),
                       ('on_reboot', 'Action on VM reboot'),
                       ('on_poweroff', 'Action on VM poweroff'),
                       ('on_crash', 'Action on VM crash'),
@@ -442,6 +491,7 @@ def info(user, fields):
                       ]
     fields = []
     machine_info = {}
+    machine_info['type'] = machine.type.hvm and 'HVM' or 'ParaVM'
     machine_info['owner'] = machine.owner
     machine_info['contact'] = machine.contact
 
@@ -476,14 +526,15 @@ def info(user, fields):
              maxdisk=maxDisk(user, machine),
              fields = fields)
     print Template(file='info.tmpl',
-                   searchList=d)
+                   searchList=[d, global_dict])
 
 mapping = dict(list=listVms,
                vnc=vnc,
                command=command,
                modify=modify,
                info=info,
-               create=create)
+               create=create,
+               help=help)
 
 if __name__ == '__main__':
     start_time = time.time()
@@ -492,11 +543,22 @@ if __name__ == '__main__':
         username = "moo"
         email = 'moo@cow.com'
     u = User()
+    if 'SSL_CLIENT_S_DN_Email' in os.environ:
+        username = os.environ[ 'SSL_CLIENT_S_DN_Email'].split("@")[0]
+        u.username = username
+        u.email = os.environ[ 'SSL_CLIENT_S_DN_Email']
+    else:
+        u.username = 'nobody'
+        u.email = None
     connect('postgres://sipb-xen@sipb-xen-dev/sipb_xen')
     operation = os.environ.get('PATH_INFO', '')
+    #print 'Content-Type: text/plain\n'
+    #print operation
     if not operation:
-        pass
-        #XXX do redirect
+        print "Status: 301 Moved Permanently"
+        print 'Location: ' + os.environ['SCRIPT_NAME']+'/\n'
+        sys.exit(0)
+    print 'Content-Type: text/html\n'
 
     if operation.startswith('/'):
         operation = operation[1:]
@@ -507,6 +569,8 @@ if __name__ == '__main__':
                       lambda u, e:
                           error(operation, u, e,
                                 "Invalid operation '%s'" % operation))
+    if fun not in (help, ):
+        connect('postgres://sipb-xen@sipb-xen-dev/sipb_xen')
     try:
         fun(u, fields)
     except MyException, err: