diff --git a/software/demoapp/demoapp.py b/software/demoapp/demoapp.py new file mode 100755 index 0000000000000000000000000000000000000000..ced865cd715507a38ad37de8de40280c4c4fa167 --- /dev/null +++ b/software/demoapp/demoapp.py @@ -0,0 +1,197 @@ +#! /bin/python + +import cgi +import os +import posixpath +import sys +import shutil +import subprocess +import tempfile +import urllib +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + +from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler + +def get_disk_quota_report(): + show_disk_quota_script = """ + Set objWMIService = GetObject("winmgmts:\\\\.\\root\\cimv2") + Set colDiskQuotas = objWMIService.ExecQuery("Select * from Win32_DiskQuota") + + For Each objQuota in colDiskQuotas + Wscript.Echo "<p>User: " & objQuota.User & "</p>" + Wscript.Echo "<p>Disk Space Used: " & objQuota.DiskSpaceUsed & "</p>" + Wscript.Echo "<p>Limit: " & objQuota.Limit & "</p>" + Wscript.Echo "<p>Quota Volume: " & objQuota.QuotaVolume & "</p>" + Wscript.Echo "<p>Status: " & objQuota.Status & "</p>" + Wscript.Echo "<p>Warning Limit: " & objQuota.WarningLimit & "</p>" + Wscript.Echo "<p></p>" + Next + """ + + f, filename = tempfile.mkstemp(suffix='.vbs') + os.write(f, show_disk_quota_script) + os.close(f) + cmdlist = ('cyg_wscript', filename, '//Nologo') + output = subprocess.check_output(cmdlist) + os.unlink(filename) + return output + +class DemoHTTPRequestHandler(BaseHTTPRequestHandler): + + def do_GET(self): + """Serve a GET request.""" + f = self.send_head() + if f: + shutil.copyfileobj(f, self.wfile) + f.close() + + def do_HEAD(self): + """Serve a HEAD request.""" + f = self.send_head() + if f: + f.close() + + def send_head(self): + """Common code for GET and HEAD commands. + + This sends the response code and MIME headers. + + Return value is either a file object (which has to be copied + to the outputfile by the caller unless the command was HEAD, + and must be closed by the caller under all circumstances), or + None, in which case the caller has nothing further to do. + + """ + path = self.translate_path(self.path) + f = None + if os.path.isdir(path): + if not self.path.endswith('/'): + # redirect browser - doing basically what apache does + self.send_response(301) + self.send_header("Location", self.path + "/") + self.end_headers() + return None + for index in "index.html", "index.htm": + index = os.path.join(path, index) + if os.path.exists(index): + path = index + break + else: + return self.show_disk_quota(path) + ctype = 'text/plain' + try: + # Always read in binary mode. Opening files in text mode may cause + # newline translations, making the actual size of the content + # transmitted *less* than the content-length! + f = open(path, 'rb') + except IOError: + self.send_error(404, "File not found") + return None + self.send_response(200) + self.send_header("Content-type", ctype) + fs = os.fstat(f.fileno()) + self.send_header("Content-Length", str(fs[6])) + self.send_header("Last-Modified", self.date_time_string(fs.st_mtime)) + self.end_headers() + return f + + def translate_path(self, path): + """Translate a /-separated PATH to the local filename syntax. + + Components that mean special things to the local file system + (e.g. drive or directory names) are ignored. (XXX They should + probably be diagnosed.) + + """ + # abandon query parameters + path = path.split('?',1)[0] + path = path.split('#',1)[0] + path = posixpath.normpath(urllib.unquote(path)) + words = path.split('/') + words = filter(None, words) + path = os.getcwd() + for word in words: + drive, word = os.path.splitdrive(word) + head, word = os.path.split(word) + if word in (os.curdir, os.pardir): continue + path = os.path.join(path, word) + return path + + def list_directory(self, path): + """Helper to produce a directory listing (absent index.html). + + Return value is either a file object, or None (indicating an + error). In either case, the headers are sent, making the + interface the same as for send_head(). + + """ + try: + list = os.listdir(path) + except os.error: + self.send_error(404, "No permission to list directory") + return None + list.sort(key=lambda a: a.lower()) + f = StringIO() + displaypath = cgi.escape(urllib.unquote(self.path)) + f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">') + f.write("<html>\n<title>Directory listing for %s</title>\n" % displaypath) + f.write("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath) + f.write("<hr>\n<ul>\n") + for name in list: + fullname = os.path.join(path, name) + displayname = linkname = name + # Append / for directories or @ for symbolic links + if os.path.isdir(fullname): + displayname = name + "/" + linkname = name + "/" + if os.path.islink(fullname): + displayname = name + "@" + # Note: a link to a directory displays with @ and links with / + f.write('<li><a href="%s">%s</a>\n' + % (urllib.quote(linkname), cgi.escape(displayname))) + f.write("</ul>\n<hr>\n</body>\n</html>\n") + length = f.tell() + f.seek(0) + self.send_response(200) + encoding = sys.getfilesystemencoding() + self.send_header("Content-type", "text/html; charset=%s" % encoding) + self.send_header("Content-Length", str(length)) + self.end_headers() + return f + + def show_disk_quota(self, path): + f = StringIO() + f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">') + f.write("<html>\n<title>SlapOS Demo For Windows</title>\n") + f.write("<body>\n<h2>Disk Quota List</h2>\n") + f.write("<hr>\n") + output = get_disk_quota_report() + f.write(output) + f.write("<hr>\n</body>\n</html>\n") + length = f.tell() + f.seek(0) + self.send_response(200) + encoding = sys.getfilesystemencoding() + self.send_header("Content-type", "text/html; charset=%s" % encoding) + self.send_header("Content-Length", str(length)) + self.end_headers() + return f + +class HTTPServerV6(HTTPServer): + address_family = 23 # socket.AF_INET6 + +def run(server_class=HTTPServerV6, + handler_class=DemoHTTPRequestHandler, + addr='::', + port=18000): + server_address = (addr, port) + httpd = server_class(server_address, handler_class) + httpd.serve_forever() + +if __name__ == '__main__': + run() + sys.exit(0) + diff --git a/software/demoapp/instance.cfg.in b/software/demoapp/instance.cfg.in new file mode 100644 index 0000000000000000000000000000000000000000..43db242321bf97e35313f35edf41e2d4410921ca --- /dev/null +++ b/software/demoapp/instance.cfg.in @@ -0,0 +1,34 @@ +[buildout] +parts = + rootdirectory + basedirectory + main + +eggs-directory = ${buildout:eggs-directory} +develop-eggs-directory = ${buildout:develop-eggs-directory} +offline = true + +[rootdirectory] +recipe = slapos.cookbook:mkdirectory +etc = $${buildout:directory}/etc +var = $${buildout:directory}/var +srv = $${buildout:directory}/srv +bin = $${buildout:directory}/bin +tmp = $${buildout:directory}/tmp + +[basedirectory] +recipe = slapos.cookbook:mkdirectory +log = $${rootdirectory:var}/log +services = $${rootdirectory:etc}/service +scripts = $${rootdirectory:etc}/run +run = $${rootdirectory:var}/run +backup = $${rootdirectory:srv}/backup +promises = $${rootdirectory:etc}/promise + +[main] +recipe = hexagonit.recipe.download +url = ${buildout:directory}/demoapp.py +destination = $${basedirectory:scripts} +filename = demoapp +download-only = true +mode = 0750 diff --git a/software/demoapp/software.cfg b/software/demoapp/software.cfg new file mode 100644 index 0000000000000000000000000000000000000000..78ad51020166c108e4df0b0f278261169fa4d6fd --- /dev/null +++ b/software/demoapp/software.cfg @@ -0,0 +1,111 @@ +[buildout] +ignore-existing = true +extends = + ../../stack/slapos.cfg + +parts = + slapos-cookbook + demoapp + instance-template + +[demoapp] +recipe = hexagonit.recipe.download +url = ${:_profile_base_location_}/demoapp.py +destination = ${buildout:directory} +download-only = true + +#---------------- +#-- Instance-level buildout profiles. + +[instance-template] +recipe = slapos.recipe.template +url = ${:_profile_base_location_}/instance.cfg.in +output = ${buildout:directory}/instance.cfg +mode = 0644 + +[versions] +Jinja2 = 2.6 +MySQL-python = 1.2.4 +Werkzeug = 0.8.3 +apache-libcloud = 0.12.3 +async = 0.6.1 +buildout-versions = 1.7 +gitdb = 0.5.4 +hexagonit.recipe.cmmi = 1.6 +inotifyx = 0.2.0 +lxml = 3.1.1 +meld3 = 0.6.10 +netaddr = 0.7.10 +pycrypto = 2.6 +pytz = 2013b +rdiff-backup = 1.0.5 +slapos.cookbook = 0.76.0 +slapos.recipe.build = 0.11.6 +slapos.recipe.download = 1.0.dev-r4053 +slapos.recipe.template = 2.4.2 +slapos.toolbox = 0.34.0 +smmap = 0.8.2 + +# Required by: +# slapos.core==0.35.1 +# slapos.toolbox==0.34.0 +Flask = 0.9 + +# Required by: +# slapos.toolbox==0.34.0 +GitPython = 0.3.2.RC1 + +# Required by: +# slapos.toolbox==0.34.0 +atomize = 0.1.1 + +# Required by: +# slapos.toolbox==0.34.0 +feedparser = 5.1.3 + +# Required by: +# slapos.core==0.35.1 +netifaces = 0.8 + +# Required by: +# slapos.toolbox==0.34.0 +paramiko = 1.10.0 + +# Required by: +# slapos.toolbox==0.34.0 +psutil = 0.6.1 + +# Required by: +# slapos.core==0.35.1 +pyflakes = 0.6.1 + +# Required by: +# hexagonit.recipe.download==1.6nxd002 +# slapos.cookbook==0.76.0 +# slapos.core==0.35.1 +# slapos.toolbox==0.34.0 +# supervisor==3.0b1 +# zc.buildout==1.6.0-dev-SlapOS-010 +# zope.interface==4.0.5 +setuptools = 0.6c12dev-r88846 + +# Required by: +# slapos.toolbox==0.34.0 +slapos.core = 0.35.1 + +# Required by: +# slapos.core==0.35.1 +supervisor = 3.0b1 + +# Required by: +# slapos.core==0.35.1 +unittest2 = 0.5.1 + +# Required by: +# slapos.toolbox==0.34.0 +xml-marshaller = 0.9.7 + +# Required by: +# slapos.core==0.35.1 +zope.interface = 4.0.5 +