From: Eric Price Date: Sun, 7 Oct 2007 07:31:36 +0000 (-0400) Subject: Initial import of web interface. X-Git-Tag: sipb-xen-www/1~92 X-Git-Url: http://xvm.mit.edu/gitweb/invirt/packages/invirt-web.git/commitdiff_plain/867613f209f2f414afd261258c73b6adf4bdd905 Initial import of web interface. svn path=/trunk/web/; revision=113 --- 867613f209f2f414afd261258c73b6adf4bdd905 diff --git a/templates/VncViewer.jar b/templates/VncViewer.jar new file mode 100644 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 index 0000000..af38122 --- /dev/null +++ b/templates/create.tmpl @@ -0,0 +1,15 @@ +#from skeleton import skeleton +#extends skeleton + +#def title +Created! +#end def + +#def body +

Created

+#if $machine +

Congratulations! You have a new machine named ${machine.name}.

+#else +

Odd... no error, but no machine.

+#end if +#end def diff --git a/templates/error.tmpl b/templates/error.tmpl new file mode 100644 index 0000000..a4f9fda --- /dev/null +++ b/templates/error.tmpl @@ -0,0 +1,12 @@ +#from skeleton import skeleton +#extends skeleton + +#def title +ERROR! +#end def + +#def body +

ERROR

+

$errorMessage in operation $op

+ +#end def diff --git a/templates/info.tmpl b/templates/info.tmpl new file mode 100644 index 0000000..f2ebe51 --- /dev/null +++ b/templates/info.tmpl @@ -0,0 +1,11 @@ +#from skeleton import skeleton +#extends skeleton + +#def title +Created! +#end def + +#def body +

Info

+

Info on ${machine.name}.

+#end def diff --git a/templates/list.tmpl b/templates/list.tmpl new file mode 100644 index 0000000..f820385 --- /dev/null +++ b/templates/list.tmpl @@ -0,0 +1,95 @@ +#from skeleton import skeleton +#extends skeleton + +#def title +List of your VMs +#end def + +#def body +#if not $machines + +#else +

You have the following VMs:

+ + + + + + + + + + + + #for $machine in $machines: + + + + +#if $machine.nics +#set $nic = $machine.nics[0] + + + +#else + + + +#end if + + + + + #end for +
NameMemoryownerIPMAC AddressHostnameStatusVNCRestart?
$machine.name${machine.memory}M$machine.owner$nic.ip$nic.mac_addr$nic.hostnameGood!Console +
+ + +
+
+#end if + +

Create a new VM:

+
+ + + + + + + #set $maxmem=256 + + + + + #set $maxdisk=1.5 + + + + + + + + + + + +
Name
Memory megabytes ($maxmem max)
Disk gigabytes ($maxdisk max)
HVM/ParaVM + HVM + ParaVM +
Initial Install + +
+ +
+ +#end def diff --git a/templates/main.py b/templates/main.py new file mode 100755 index 0000000..d4ac4e6 --- /dev/null +++ b/templates/main.py @@ -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 index 0000000..5a83921 --- /dev/null +++ b/templates/mainpage.py @@ -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(''' +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(''' + +

[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('''.]

+

+''') + 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('''

+

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:

+ +
+Served by Online Store v1.0 + + +''') + + ######################################## + ## 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 index 0000000..4e9846d --- /dev/null +++ b/templates/mainpage.tmpl @@ -0,0 +1,25 @@ + +Status for order #$order.id + +

[You are logged in as $user.]

+

+#if ($order.hasShipped()) + Your order has shipped. Your tracking number is $order.trackingNumber. +#else + Your order has not yet shipped. +#end if +

+

Order #$order.id contains the following items:

+ +
+Served by Online Store v1.0 + + diff --git a/templates/skeleton.py b/templates/skeleton.py new file mode 100644 index 0000000..01debf9 --- /dev/null +++ b/templates/skeleton.py @@ -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(''' +''') + _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(''' + +

[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('''.]

+''') + _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(''' +
+Questions? Contact sipb-xen-dev@mit.edu. + + +''') + + ######################################## + ## 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 index 0000000..9c1c891 --- /dev/null +++ b/templates/skeleton.tmpl @@ -0,0 +1,9 @@ + +$title + +

[You are logged in as $user.username.]

+$body +
+Questions? Contact sipb-xen-dev@mit.edu. + + diff --git a/templates/vnc.tmpl b/templates/vnc.tmpl new file mode 100644 index 0000000..752f784 --- /dev/null +++ b/templates/vnc.tmpl @@ -0,0 +1,22 @@ +#from skeleton import skeleton +#extends skeleton + +#def title +Console to $machine.name +#end def + +#def body +

Console

+

Here is a console to ${machine.name}.

+ + + + + + + + +#end def diff --git a/xen-ips b/xen-ips new file mode 100755 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] + " " + +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)