Initial import of web interface.
authorEric Price <ecprice@mit.edu>
Sun, 7 Oct 2007 07:31:36 +0000 (03:31 -0400)
committerEric Price <ecprice@mit.edu>
Sun, 7 Oct 2007 07:31:36 +0000 (03:31 -0400)
svn path=/trunk/web/; revision=113

12 files changed:
templates/VncViewer.jar [new file with mode: 0644]
templates/create.tmpl [new file with mode: 0644]
templates/error.tmpl [new file with mode: 0644]
templates/info.tmpl [new file with mode: 0644]
templates/list.tmpl [new file with mode: 0644]
templates/main.py [new file with mode: 0755]
templates/mainpage.py [new file with mode: 0644]
templates/mainpage.tmpl [new file with mode: 0644]
templates/skeleton.py [new file with mode: 0644]
templates/skeleton.tmpl [new file with mode: 0644]
templates/vnc.tmpl [new file with mode: 0644]
xen-ips [new file with mode: 0755]

diff --git a/templates/VncViewer.jar b/templates/VncViewer.jar
new file mode 100644 (file)
index 0000000..7d9d145
Binary files /dev/null and b/templates/VncViewer.jar differ
diff --git a/templates/create.tmpl b/templates/create.tmpl
new file mode 100644 (file)
index 0000000..af38122
--- /dev/null
@@ -0,0 +1,15 @@
+#from skeleton import skeleton
+#extends skeleton
+
+#def title
+Created!
+#end def
+
+#def body
+<h1>Created</h1>
+#if $machine
+<p>Congratulations!  You have a new machine named ${machine.name}.</p>
+#else
+<p>Odd... no error, but no machine.</p>
+#end if
+#end def
diff --git a/templates/error.tmpl b/templates/error.tmpl
new file mode 100644 (file)
index 0000000..a4f9fda
--- /dev/null
@@ -0,0 +1,12 @@
+#from skeleton import skeleton
+#extends skeleton
+
+#def title
+ERROR!
+#end def
+
+#def body
+<h1>ERROR</h1>
+<p>$errorMessage in operation $op</p>
+
+#end def
diff --git a/templates/info.tmpl b/templates/info.tmpl
new file mode 100644 (file)
index 0000000..f2ebe51
--- /dev/null
@@ -0,0 +1,11 @@
+#from skeleton import skeleton
+#extends skeleton
+
+#def title
+Created!
+#end def
+
+#def body
+<h1>Info</h1>
+<p>Info on ${machine.name}.</p>
+#end def
diff --git a/templates/list.tmpl b/templates/list.tmpl
new file mode 100644 (file)
index 0000000..f820385
--- /dev/null
@@ -0,0 +1,95 @@
+#from skeleton import skeleton
+#extends skeleton
+
+#def title
+List of your VMs
+#end def
+
+#def body
+#if not $machines
+   
+#else
+    <p>You have the following VMs:</p>
+    <table>
+      <tr>
+       <td>Name</td>
+       <td>Memory</td>
+       <td>owner</td>
+       <td>IP</td>
+       <td>MAC Address</td>
+       <td>Hostname</td>
+       <td>Status</td>
+       <td>VNC</td>
+       <td>Restart?</td>
+      #for $machine in $machines:
+      <tr> 
+       <td><a href="info?machine_id=$machine.machine_id">$machine.name</a></td>
+       <td>${machine.memory}M</td>
+       <td>$machine.owner</td>
+#if $machine.nics
+#set $nic = $machine.nics[0]
+       <td>$nic.ip</td>
+       <td>$nic.mac_addr</td>
+       <td>$nic.hostname</td>
+#else
+       <td></td>
+       <td></td>
+       <td></td>
+#end if
+       <td>Good!</td>
+       <td><a href="vnc?machine_id=$machine.machine_id">Console</a></td>
+       <td>
+         <form action="restart">
+           <input type="hidden" name="machine_id"
+                  value="$machine.machine_id"/>
+           <input type="submit" class="button"
+                  value="restart"/>
+         </form>
+       </td>
+      </tr>
+      #end for
+    </table>
+#end if
+
+    <p>Create a new VM:</p>
+    <form action="create">
+      <table>
+       <tr>
+         <td>Name</td>
+         <td><input type="text" name="name" value="$user.username"/></td>
+       </tr>
+       <tr>
+         #set $maxmem=256
+         <td>Memory</td>
+         <td><input type="text" name="memory" value="$maxmem" size=3/> megabytes ($maxmem max)</td>
+       </tr>
+       <tr>
+         #set $maxdisk=1.5
+         <td>Disk</td>
+         <td><input type="text" name="disk" value="$maxdisk" size=3/> gigabytes ($maxdisk max)</td>
+       </tr>
+       <tr>
+         <td>HVM/ParaVM</td>
+         <td>
+           <input checked type="radio" name="vmtype" value="hvm">HVM</input>
+           <input type="radio" name="vmtype" value="paravm">ParaVM</input>
+         </td>
+       </tr>
+       <tr>
+         <td>Initial Install</td>
+         <td>
+           <select name="cdrom">
+             <option selected value="">None</option>
+             #for $cdrom in $cdroms
+             <option value="$cdrom.cdrom_id">
+               $cdrom.description
+             </option>
+             #end for
+           </select>
+         </td>
+       </tr>
+      </table>
+      <input type="submit" class="button" value="Create it!"/>
+    </form>
+
+#end def
diff --git a/templates/main.py b/templates/main.py
new file mode 100755 (executable)
index 0000000..d4ac4e6
--- /dev/null
@@ -0,0 +1,249 @@
+#!/usr/bin/python
+
+import sys
+import cgi
+import os
+import string
+import subprocess
+
+print 'Content-Type: text/html\n'
+sys.stderr = sys.stdout
+sys.path.append('/home/ecprice/.local/lib/python2.5/site-packages')
+
+from Cheetah.Template import Template
+from sipb_xen_database import *
+import random
+
+# ... and stolen from xend/uuid.py
+def randomUUID():
+    """Generate a random UUID."""
+
+    return [ random.randint(0, 255) for _ in range(0, 16) ]
+
+def uuidToString(u):
+    return "-".join(["%02x" * 4, "%02x" * 2, "%02x" * 2, "%02x" * 2,
+                     "%02x" * 6]) % tuple(u)
+
+
+def maxMemory(user):
+    return 256
+
+def haveAccess(user, machine):
+    return True
+
+
+def error(op, user, fields, errorMessage):
+    d = dict(op=op,
+             user=user,
+             errorMessage=errorMessage)
+    print Template(file='error.tmpl',
+                   searchList=d);
+
+def validMachineName(name):
+    if not name:
+        return False
+    charset = string.ascii_letters + string.digits + '-'
+    if name[0] == '-' or len(name) > 22:
+        return False
+    return all(x in charset for x in name)
+
+def kinit():
+    keytab = '/etc/tabbott.keytab'
+    username = 'tabbott/extra'
+    p = subprocess.Popen(['kinit', "-k", "-t", keytab, 
+                          username])
+    p.wait()
+
+def checkKinit():
+    p = subprocess.Popen(['klist', '-s'])
+    if p.wait():
+        kinit()
+
+def remctl(*args):
+    checkKinit()
+    p = subprocess.Popen(['remctl', 'black-mesa.mit.edu']
+                         + list(args),
+                         stdout=subprocess.PIPE,
+                         stderr=subprocess.PIPE)
+    if p.wait():
+        print >> sys.stderr, 'ERROR on remctl ', args
+        print >> sys.stderr, p.stderr.read()
+
+def makeDisks():
+    remctl('lvcreate','all')
+
+def bootMachine(machine, cdtype):
+    if cdtype is not None:
+        remctl('vmboot', 'cdrom', str(machine.name),
+               cdtype)
+    else:
+        remctl('vmboot', 'cdrom', str(machine.name))
+
+def createVm(user, name, memory, disk, is_hvm, cdrom):
+    # put stuff in the table
+    transaction = ctx.current.create_transaction()
+    try:
+        res = meta.engine.execute('select nextval(\'"machines_machine_id_seq"\')')
+        id = res.fetchone()[0]
+        machine = Machine()
+        machine.machine_id = id
+        machine.name = name
+        machine.memory = memory
+        machine.owner = user.username
+        machine.contact = user.email
+        machine.uuid = uuidToString(randomUUID())
+        machine.boot_off_cd = True
+        machine_type = Type.get_by(hvm=is_hvm)
+        machine.type_id = machine_type.type_id
+        ctx.current.save(machine)
+        disk = Disk(machine.machine_id, 
+                    'hda', disk)
+        open = NIC.select_by(machine_id=None)
+        if not open: #No IPs left!
+            return "No IP addresses left!  Contact sipb-xen-dev@mit.edu"
+        nic = open[0]
+        nic.machine_id = machine.machine_id
+        nic.hostname = name
+        ctx.current.save(nic)    
+        ctx.current.save(disk)
+        transaction.commit()
+    except:
+        transaction.rollback()
+        raise
+    makeDisks()
+    # tell it to boot with cdrom
+    bootMachine(machine, cdrom)
+
+    return machine
+
+def create(user, fields):
+    name = fields.getfirst('name')
+    if not validMachineName(name):
+        return error('create', user, fields,
+                     "Invalid name '%s'" % name)
+    name = name.lower()
+
+    if Machine.get_by(name=name):
+        return error('create', user, fields,
+                     "A machine named '%s' already exists" % name)
+    
+    memory = fields.getfirst('memory')
+    try:
+        memory = int(memory)
+        if memory <= 0:
+            raise ValueError
+    except ValueError:
+        return error('create', user, fields,
+                     "Invalid memory amount")
+    if memory > maxMemory(user):
+        return error('create', user, fields,
+                     "Too much memory requested")
+    
+    disk = fields.getfirst('disk')
+    try:
+        disk = float(disk)
+        disk = int(disk * 1024)
+        if disk <= 0:
+            raise ValueError
+    except ValueError:
+        return error('create', user, fields,
+                     "Invalid disk amount")
+    
+    vm_type = fields.getfirst('vmtype')
+    if vm_type not in ('hvm', 'paravm'):
+        return error('create', user, fields,
+                     "Invalid vm type '%s'"  % vm_type)    
+    is_hvm = (vm_type == 'hvm')
+
+    cdrom = fields.getfirst('cdrom')
+    if cdrom is not None and not CDROM.get(cdrom):
+        return error('create', user, fields,
+                     "Invalid cdrom type '%s'" % cdrom)    
+    
+    machine = createVm(user, name, memory, disk, is_hvm, cdrom)
+    if isinstance(machine, basestring):
+        return error('create', user, fields,
+                     machine)
+    d = dict(user=user,
+             machine=machine)
+    print Template(file='create.tmpl',
+                   searchList=d);
+
+def listVms(user, fields):
+    machines = Machine.select()
+    d = dict(user=user,
+             machines=machines,
+             cdroms=CDROM.select())
+
+    print Template(file='list.tmpl', searchList=d)
+
+def testMachineId(user, machineId, exists=True):
+    if machineId is None:
+        error('vnc', user, fields,
+              "No machine ID specified")
+        return False
+    try:
+        machineId = int(machineId)
+    except ValueError:
+        error('vnc', user, fields,
+              "Invalid machine ID '%s'" 
+              % machineId)
+        return False
+    machine = Machine.get(machineId)
+    if exists and machine is None:
+        error('vnc', user, fields,
+              "No such machine ID '%s'" 
+              % machineId)
+        return False
+    if not haveAccess(user, machine):
+        error('vnc', user, fields,
+              "No access to machine ID '%s'" 
+              % machineId)
+        return False
+    return machine
+
+def vnc(user, fields):
+    machine = testMachineId(user, fields.getfirst('machine_id'))
+    if machine is None: #gave error page already
+        return
+    token = 'quentin'
+    d = dict(user=user,
+             machine=machine,
+             hostname='localhost',
+             authtoken=token)
+    print Template(file='vnc.tmpl',
+                   searchList=d)
+
+def info(user, fields):
+    machine = testMachineId(user, fields.getfirst('machine_id'))
+    if machine is None: #gave error page already
+        return
+    
+    d = dict(user=user,
+             machine=machine)
+    print Template(file='info.tmpl',
+                   searchList=d)
+
+mapping = dict(list=listVms,
+               vnc=vnc,
+               info=info,
+               create=create)
+
+if __name__ == '__main__':
+    fields = cgi.FieldStorage()
+    class C:
+        username = "moo"
+        email = 'moo@cow.com'
+    u = C()
+    connect('postgres://sipb-xen@sipb-xen-dev/sipb_xen')
+    operation = os.environ.get('PATH_INFO', '')
+    if operation.startswith('/'):
+        operation = operation[1:]
+    if not operation:
+        operation = 'list'
+    
+    fun = mapping.get(operation, 
+                      lambda u, e:
+                          error(operation, u, e,
+                                "Invalid operation '%'" % operation))
+    fun(u, fields)
diff --git a/templates/mainpage.py b/templates/mainpage.py
new file mode 100644 (file)
index 0000000..5a83921
--- /dev/null
@@ -0,0 +1,176 @@
+#!/usr/bin/env python
+
+
+
+
+##################################################
+## DEPENDENCIES
+import sys
+import os
+import os.path
+from os.path import getmtime, exists
+import time
+import types
+import __builtin__
+from Cheetah.Version import MinCompatibleVersion as RequiredCheetahVersion
+from Cheetah.Version import MinCompatibleVersionTuple as RequiredCheetahVersionTuple
+from Cheetah.Template import Template
+from Cheetah.DummyTransaction import DummyTransaction
+from Cheetah.NameMapper import NotFound, valueForName, valueFromSearchList, valueFromFrameOrSearchList
+from Cheetah.CacheRegion import CacheRegion
+import Cheetah.Filters as Filters
+import Cheetah.ErrorCatchers as ErrorCatchers
+
+##################################################
+## MODULE CONSTANTS
+try:
+    True, False
+except NameError:
+    True, False = (1==1), (1==0)
+VFFSL=valueFromFrameOrSearchList
+VFSL=valueFromSearchList
+VFN=valueForName
+currentTime=time.time
+__CHEETAH_version__ = '2.0rc8'
+__CHEETAH_versionTuple__ = (2, 0, 0, 'candidate', 8)
+__CHEETAH_genTime__ = 1191715796.9141691
+__CHEETAH_genTimestamp__ = 'Sat Oct  6 20:09:56 2007'
+__CHEETAH_src__ = 'mainpage.tmpl'
+__CHEETAH_srcLastModified__ = 'Sat Oct  6 20:09:44 2007'
+__CHEETAH_docstring__ = 'Autogenerated by CHEETAH: The Python-Powered Template Engine'
+
+if __CHEETAH_versionTuple__ < RequiredCheetahVersionTuple:
+    raise AssertionError(
+      'This template was compiled with Cheetah version'
+      ' %s. Templates compiled before version %s must be recompiled.'%(
+         __CHEETAH_version__, RequiredCheetahVersion))
+
+##################################################
+## CLASSES
+
+class mainpage(Template):
+
+    ##################################################
+    ## CHEETAH GENERATED METHODS
+
+
+    def __init__(self, *args, **KWs):
+
+        Template.__init__(self, *args, **KWs)
+        if not self._CHEETAH__instanceInitialized:
+            cheetahKWArgs = {}
+            allowedKWs = 'searchList namespaces filter filtersLib errorCatcher'.split()
+            for k,v in KWs.items():
+                if k in allowedKWs: cheetahKWArgs[k] = v
+            self._initCheetahInstance(**cheetahKWArgs)
+        
+
+    def respond(self, trans=None):
+
+
+
+        ## CHEETAH: main method generated for this template
+        if (not trans and not self._CHEETAH__isBuffering and not callable(self.transaction)):
+            trans = self.transaction # is None unless self.awake() was called
+        if not trans:
+            trans = DummyTransaction()
+            _dummyTrans = True
+        else: _dummyTrans = False
+        write = trans.response().write
+        SL = self._CHEETAH__searchList
+        _filter = self._CHEETAH__currentFilter
+        
+        ########################################
+        ## START - generated method body
+        
+        write('''<html>
+<head><title>Status for order #''')
+        _v = VFFSL(SL,"order.id",True) # '$order.id' on line 2, col 32
+        if _v is not None: write(_filter(_v, rawExpr='$order.id')) # from line 2, col 32.
+        write('''</title></head>
+<body>
+<p>[You are logged in as ''')
+        _v = VFN(VFFSL(SL,"user",True),"getFullName",False)() # '$user.getFullName()' on line 4, col 26
+        if _v is not None: write(_filter(_v, rawExpr='$user.getFullName()')) # from line 4, col 26.
+        write('''.]</p>
+<p>
+''')
+        if (VFN(VFFSL(SL,"order",True),"hasShipped",False)()): # generated from line 6, col 1
+            write(''' Your order has shipped. Your tracking number is ''')
+            _v = VFFSL(SL,"order.trackingNumber",True) # '$order.trackingNumber' on line 7, col 50
+            if _v is not None: write(_filter(_v, rawExpr='$order.trackingNumber')) # from line 7, col 50.
+            write('''.
+''')
+        else: # generated from line 8, col 1
+            write(''' Your order has not yet shipped.
+''')
+        write('''</p>
+<p>Order #''')
+        _v = VFFSL(SL,"order.id",True) # '$order.id' on line 12, col 11
+        if _v is not None: write(_filter(_v, rawExpr='$order.id')) # from line 12, col 11.
+        write(''' contains the following items:</p>
+<ul>
+''')
+        for purchased, quantity in VFN(VFFSL(SL,"order.purchased",True),"items",False)(): # generated from line 14, col 1
+            write(''' <li>''')
+            _v = VFFSL(SL,"purchased.name",True) # '$purchased.name' on line 15, col 6
+            if _v is not None: write(_filter(_v, rawExpr='$purchased.name')) # from line 15, col 6.
+            write(''': ''')
+            _v = VFFSL(SL,"quantity",True) # '$quantity' on line 15, col 23
+            if _v is not None: write(_filter(_v, rawExpr='$quantity')) # from line 15, col 23.
+            write(''' unit''')
+            if (VFFSL(SL,"quantity",True) != 1): # generated from line 16, col 1
+                write('''s
+''')
+            write('''</li>
+''')
+        write('''</ul>
+<hr />
+Served by Online Store v1.0
+</body>
+</html>
+''')
+        
+        ########################################
+        ## END - generated method body
+        
+        return _dummyTrans and trans.response().getvalue() or ""
+        
+    ##################################################
+    ## CHEETAH GENERATED ATTRIBUTES
+
+
+    _CHEETAH__instanceInitialized = False
+
+    _CHEETAH_version = __CHEETAH_version__
+
+    _CHEETAH_versionTuple = __CHEETAH_versionTuple__
+
+    _CHEETAH_genTime = __CHEETAH_genTime__
+
+    _CHEETAH_genTimestamp = __CHEETAH_genTimestamp__
+
+    _CHEETAH_src = __CHEETAH_src__
+
+    _CHEETAH_srcLastModified = __CHEETAH_srcLastModified__
+
+    _mainCheetahMethod_for_mainpage= 'respond'
+
+## END CLASS DEFINITION
+
+if not hasattr(mainpage, '_initCheetahAttributes'):
+    templateAPIClass = getattr(mainpage, '_CHEETAH_templateClass', Template)
+    templateAPIClass._addCheetahPlumbingCodeToClass(mainpage)
+
+
+# CHEETAH was developed by Tavis Rudd and Mike Orr
+# with code, advice and input from many other volunteers.
+# For more information visit http://www.CheetahTemplate.org/
+
+##################################################
+## if run from command line:
+if __name__ == '__main__':
+    from Cheetah.TemplateCmdLineIface import CmdLineIface
+    CmdLineIface(templateObj=mainpage()).run()
+
+
diff --git a/templates/mainpage.tmpl b/templates/mainpage.tmpl
new file mode 100644 (file)
index 0000000..4e9846d
--- /dev/null
@@ -0,0 +1,25 @@
+<html>
+<head><title>Status for order #$order.id</title></head>
+<body>
+<p>[You are logged in as $user.]</p>
+<p>
+#if ($order.hasShipped())
+ Your order has shipped. Your tracking number is $order.trackingNumber.
+#else
+ Your order has not yet shipped.
+#end if
+</p>
+<p>Order #$order.id contains the following items:</p>
+<ul>
+#for $purchased, $quantity in $order.purchased:
+ <li>$purchased: $quantity unit#slurp
+#if ($quantity != 1)
+s
+#end if
+</li>
+#end for
+</ul>
+<hr />
+Served by Online Store v1.0
+</body>
+</html>
diff --git a/templates/skeleton.py b/templates/skeleton.py
new file mode 100644 (file)
index 0000000..01debf9
--- /dev/null
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+
+
+
+
+##################################################
+## DEPENDENCIES
+import sys
+import os
+import os.path
+from os.path import getmtime, exists
+import time
+import types
+import __builtin__
+from Cheetah.Version import MinCompatibleVersion as RequiredCheetahVersion
+from Cheetah.Version import MinCompatibleVersionTuple as RequiredCheetahVersionTuple
+from Cheetah.Template import Template
+from Cheetah.DummyTransaction import DummyTransaction
+from Cheetah.NameMapper import NotFound, valueForName, valueFromSearchList, valueFromFrameOrSearchList
+from Cheetah.CacheRegion import CacheRegion
+import Cheetah.Filters as Filters
+import Cheetah.ErrorCatchers as ErrorCatchers
+
+##################################################
+## MODULE CONSTANTS
+try:
+    True, False
+except NameError:
+    True, False = (1==1), (1==0)
+VFFSL=valueFromFrameOrSearchList
+VFSL=valueFromSearchList
+VFN=valueForName
+currentTime=time.time
+__CHEETAH_version__ = '2.0rc8'
+__CHEETAH_versionTuple__ = (2, 0, 0, 'candidate', 8)
+__CHEETAH_genTime__ = 1191718104.9039481
+__CHEETAH_genTimestamp__ = 'Sat Oct  6 20:48:24 2007'
+__CHEETAH_src__ = 'skeleton.tmpl'
+__CHEETAH_srcLastModified__ = 'Sat Oct  6 20:18:06 2007'
+__CHEETAH_docstring__ = 'Autogenerated by CHEETAH: The Python-Powered Template Engine'
+
+if __CHEETAH_versionTuple__ < RequiredCheetahVersionTuple:
+    raise AssertionError(
+      'This template was compiled with Cheetah version'
+      ' %s. Templates compiled before version %s must be recompiled.'%(
+         __CHEETAH_version__, RequiredCheetahVersion))
+
+##################################################
+## CLASSES
+
+class skeleton(Template):
+
+    ##################################################
+    ## CHEETAH GENERATED METHODS
+
+
+    def __init__(self, *args, **KWs):
+
+        Template.__init__(self, *args, **KWs)
+        if not self._CHEETAH__instanceInitialized:
+            cheetahKWArgs = {}
+            allowedKWs = 'searchList namespaces filter filtersLib errorCatcher'.split()
+            for k,v in KWs.items():
+                if k in allowedKWs: cheetahKWArgs[k] = v
+            self._initCheetahInstance(**cheetahKWArgs)
+        
+
+    def respond(self, trans=None):
+
+
+
+        ## CHEETAH: main method generated for this template
+        if (not trans and not self._CHEETAH__isBuffering and not callable(self.transaction)):
+            trans = self.transaction # is None unless self.awake() was called
+        if not trans:
+            trans = DummyTransaction()
+            _dummyTrans = True
+        else: _dummyTrans = False
+        write = trans.response().write
+        SL = self._CHEETAH__searchList
+        _filter = self._CHEETAH__currentFilter
+        
+        ########################################
+        ## START - generated method body
+        
+        write('''<html>
+<head><title>''')
+        _v = VFFSL(SL,"title",True) # '$title' on line 2, col 14
+        if _v is not None: write(_filter(_v, rawExpr='$title')) # from line 2, col 14.
+        write('''</title></head>
+<body>
+<p>[You are logged in as ''')
+        _v = VFFSL(SL,"user.username",True) # '$user.username' on line 4, col 26
+        if _v is not None: write(_filter(_v, rawExpr='$user.username')) # from line 4, col 26.
+        write('''.]</p>
+''')
+        _v = VFFSL(SL,"body",True) # '$body' on line 5, col 1
+        if _v is not None: write(_filter(_v, rawExpr='$body')) # from line 5, col 1.
+        write('''
+<hr />
+Questions? Contact <a href="mailto:sipb-xen-dev@mit.edu">sipb-xen-dev@mit.edu</a>.
+</body>
+</html>
+''')
+        
+        ########################################
+        ## END - generated method body
+        
+        return _dummyTrans and trans.response().getvalue() or ""
+        
+    ##################################################
+    ## CHEETAH GENERATED ATTRIBUTES
+
+
+    _CHEETAH__instanceInitialized = False
+
+    _CHEETAH_version = __CHEETAH_version__
+
+    _CHEETAH_versionTuple = __CHEETAH_versionTuple__
+
+    _CHEETAH_genTime = __CHEETAH_genTime__
+
+    _CHEETAH_genTimestamp = __CHEETAH_genTimestamp__
+
+    _CHEETAH_src = __CHEETAH_src__
+
+    _CHEETAH_srcLastModified = __CHEETAH_srcLastModified__
+
+    _mainCheetahMethod_for_skeleton= 'respond'
+
+## END CLASS DEFINITION
+
+if not hasattr(skeleton, '_initCheetahAttributes'):
+    templateAPIClass = getattr(skeleton, '_CHEETAH_templateClass', Template)
+    templateAPIClass._addCheetahPlumbingCodeToClass(skeleton)
+
+
+# CHEETAH was developed by Tavis Rudd and Mike Orr
+# with code, advice and input from many other volunteers.
+# For more information visit http://www.CheetahTemplate.org/
+
+##################################################
+## if run from command line:
+if __name__ == '__main__':
+    from Cheetah.TemplateCmdLineIface import CmdLineIface
+    CmdLineIface(templateObj=skeleton()).run()
+
+
diff --git a/templates/skeleton.tmpl b/templates/skeleton.tmpl
new file mode 100644 (file)
index 0000000..9c1c891
--- /dev/null
@@ -0,0 +1,9 @@
+<html>
+<head><title>$title</title></head>
+<body>
+<p>[You are logged in as $user.username.]</p>
+$body
+<hr />
+Questions? Contact <a href="mailto:sipb-xen-dev@mit.edu">sipb-xen-dev@mit.edu</a>.
+</body>
+</html>
diff --git a/templates/vnc.tmpl b/templates/vnc.tmpl
new file mode 100644 (file)
index 0000000..752f784
--- /dev/null
@@ -0,0 +1,22 @@
+#from skeleton import skeleton
+#extends skeleton
+
+#def title
+Console to $machine.name
+#end def
+
+#def body
+<h1>Console</h1>
+<p>Here is a console to ${machine.name}.</p>
+<APPLET CODE="VncViewer.class" ARCHIVE="../VncViewer.jar"
+        WIDTH="800" HEIGHT="632">
+<PARAM NAME="PORT" VALUE="10003">
+<PARAM NAME="HOST" VALUE="$hostname">
+<PARAM NAME="VMNAME" VALUE="$machine.name">
+<PARAM NAME="AUTHTOKEN" VALUE="$authtoken">
+<PARAM NAME="SocketFactory" VALUE="VNCProxyConnectSocketFactory">
+</APPLET>
+<!-- 
+java VncViewer HOST black-mesa PORT 10003 VMNAME tabbott_test AUTHTOKEN quentin SocketFactory VNCProxyConnectSocketFactory
+-->
+#end def
diff --git a/xen-ips b/xen-ips
new file mode 100755 (executable)
index 0000000..a56b402
--- /dev/null
+++ b/xen-ips
@@ -0,0 +1,52 @@
+#!/usr/bin/python
+import random
+from sipb_xen_database import *
+import sys
+
+# stolen directly from xend/server/netif.py
+def randomMAC():
+    """Generate a random MAC address.
+
+    Uses OUI (Organizationally Unique Identifier) 00-16-3E, allocated to
+    Xensource, Inc. The OUI list is available at
+    http://standards.ieee.org/regauth/oui/oui.txt.
+
+    The remaining 3 fields are random, with the first bit of the first
+    random field set 0.
+
+    @return: MAC address string
+    """
+    mac = [ 0x00, 0x16, 0x3e,
+            random.randint(0x00, 0x7f),
+            random.randint(0x00, 0xff),
+            random.randint(0x00, 0xff) ]
+    return ':'.join(map(lambda x: "%02x" % x, mac))
+
+# ... and stolen from xend/uuid.py
+def randomUUID():
+    """Generate a random UUID."""
+
+    return [ random.randint(0, 255) for _ in range(0, 16) ]
+
+def uuidToString(u):
+    return "-".join(["%02x" * 4, "%02x" * 2, "%02x" * 2, "%02x" * 2,
+                     "%02x" * 6]) % tuple(u)
+
+
+def usage():
+    print >> sys.stderr, "USAGE: " + sys.argv[0] + " <ip>"
+
+def addip(ip):
+    n = NIC(None, randomMAC(), ip, None)
+    ctx.current.save(n)
+    ctx.current.flush()
+
+
+if __name__ == '__main__':
+    if len(sys.argv) == 2:
+        ip = sys.argv[1]
+    else:
+        usage()
+        sys.exit(1)
+    connect('postgres://sipb-xen@sipb-xen-dev/sipb_xen')
+    addip(ip)