bitkeeper revision 1.1662.1.18 (42a5a348BpHwgoiWQI1wI9LMej7F3w)

setup.py:
  Add xen.xend.xenstore.
xsresource.py, xsobj.py, xsnode.py, __init__.py:
  new file
Signed-off-by: Mike Wray <mike.wray@hp.com>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
This commit is contained in:
cl349@firebug.cl.cam.ac.uk committed 2005-06-07 13:38:16 +00:00
1 parent 3a834bf165
commit 7fef173569
6 files changed
+1044

No files matched your search

+1
View File
@@ -48,6 +48,7 @@ setup(name = 'xen',
'xen.util',
'xen.xend',
'xen.xend.server',
'xen.xend.xenstore',
'xen.xm',
'xen.web',
],
@@ -0,0 +1,2 @@
from xsnode import *
from xsobj import *
+382
View File
@@ -0,0 +1,382 @@
import errno
import os
import os.path
import select
import sys
import time
from xen.lowlevel import xs
from xen.xend import sxp
from xen.xend.PrettyPrint import prettyprint
SELECT_TIMEOUT = 2.0
def getEventPath(event):
return os.path.join("/_event", event)
def getEventIdPath(event):
return os.path.join(eventPath(event), "@eid")
class Subscription:
def __init__(self, event, fn, id):
self.event = event
self.watcher = None
self.fn = fn
self.id = id
def watch(self, watcher):
self.watcher = watcher
watcher.addSubs(self)
def unwatch(self):
watcher = self.watcher
if watcher:
self.watcher = None
watcher.delSubs(self)
def notify(self, event):
try:
self.fn(event, id)
except SystemExitException:
raise
except:
pass
class Watcher:
def __init__(self, store, event):
self.path = getEventPath(event)
self.eidPath = getEventIdPath(event)
store.mkdirs(self.path)
if not store.exists(self.eidPath):
store.writeInt(self.eidPath, 0)
self.xs = None
self.subs = []
def __getattr__(self, k, v):
if k == "fileno":
if self.xs:
return self.xs.fileno
else:
return -1
else:
return self.__dict__.get(k, v)
def addSubs(self, subs):
self.subs.append(subs)
self.watch()
def delSubs(self, subs):
self.subs.remove(subs)
if len(self.subs) == 0:
self.unwatch()
def getEvent(self):
return self.event
def watch(self):
if self.xs: return
self.xs = xs.open()
self.xs.watch(path)
def unwatch(self):
if self.xs:
self.xs.unwatch(self.path)
self.xs.close()
self.xs = None
def watching(self):
return self.xs is not None
def getNotification(self):
p = self.xs.read_watch()
self.xs.acknowledge_watch()
eid = self.xs.readInt(self.eidPath)
return p
def notify(self, subs):
p = self.getNotification()
for s in subs:
s.notify(p)
class XenStore:
def __init__(self):
self.xs = None
#self.xs = xs.open()
self.subscription = {}
self.subscription_id = 0
self.events = {}
self.write("/", "")
def getxs(self):
if self.xs is None:
ex = None
for i in range(0,20):
try:
self.xs = xs.open()
ex = None
break
except Exception, ex:
print >>stderr, "Exception connecting to xsdaemon:", ex
print >>stderr, "Trying again..."
time.sleep(1)
else:
raise ex
#todo would like to reconnect if xs conn closes (e.g. daemon restart).
return self.xs
def dump(self, path="/", out=sys.stdout):
print 'dump>', path
val = ['node']
val.append(['path', path])
## perms = ['perms']
## for p in self.getPerms(path):
## l = ['perm']
## l.append('dom', p.get['dom'])
## for k in ['read', 'write', 'create', 'owner']:
## v = p.get(k)
## l.append([k, v])
## perms.append(l)
## val.append(perms)
data = self.read(path)
if data:
val.append(['data', data])
children = ['children']
for x in self.lsPaths(path):
print 'dump>', 'child=', x
children.append(self.dump(x))
if len(children) > 1:
val.append(children)
prettyprint(val, out=out)
return val
def getPerms(self, path):
return self.getxs().get_permissions(path)
def ls(self, path="/"):
return self.getxs().ls(path)
def lsPaths(self, path="/"):
return [ os.path.join(path, x) for x in self.ls(path) ]
def lsr(self, path="/", list=None):
if list is None:
list = []
list.append(path)
for x in self.lsPaths(path):
list.append(x)
self.lsr(x, list=list)
return list
def rm(self, path):
try:
#for x in self.lsPaths():
# self.getxs().rm(x)
self.getxs().rm(path)
except:
pass
def exists(self, path):
try:
self.getxs().ls(path)
return True
except RuntimeError, ex:
if ex.args[0] == errno.ENOENT:
return False
else:
raise
def mkdirs(self, path):
if self.exists(path):
return
elts = path.split("/")
p = "/"
for x in elts:
if x == "": continue
p = os.path.join(p, x)
if not self.exists(p):
self.getxs().write(p, "", create=True)
def read(self, path):
try:
return self.getxs().read(path)
except RuntimeError, ex:
if ex.args[0] == errno.EISDIR:
return None
else:
raise
def create(self, path, excl=False):
self.write(path, "", create=True, excl=excl)
def write(self, path, data, create=True, excl=False):
self.mkdirs(path)
self.getxs().write(path, data, create=create, excl=excl)
def begin(self, path):
self.getxs().begin_transaction(path)
def commit(self, abandon=False):
self.getxs().end_transaction(abort=abandon)
def subscribe(self, event, fn):
watcher = self.watchEvent(event)
self.subscription_id += 1
subs = Subscription(event, fn, self.subscription_id)
self.subscription[subs.id] = subs
subs.watch(watcher)
return subs.id
def unsubscribe(self, sid):
s = self.subscription.get(sid)
if not s: return
del self.subscription[s.id]
s.unwatch()
unwatchEvent(s.event)
def sendEvent(self, event, data):
eventPath = getEventPath(event)
eidPath = getEventIdPath(event)
try:
self.begin(eventPath)
self.mkdirs(eventPath)
if self.exists(eidPath):
eid = self.readInt(eidPath)
eid += 1
else:
eid = 1
self.writeInt(eidPath, eid)
self.write(os.path.join(eventPath, str(eid)), data)
finally:
self.commit()
def watchEvent(self, event):
if event in self.events:
return
watcher = Watcher(event)
self.watchers[watcher.getEvent()] = watcher
self.watchStart()
return watcher
def unwatchEvent(self, event):
watcher = self.watchers.get(event)
if not watcher:
return
if not watcher.watching():
del self.watchers[event]
def watchStart(self):
if self.watchThread: return
def watchMain(self):
try:
while True:
if self.watchThread is None: return
if not self.events:
return
rd = self.watchers.values()
try:
(rd, wr, er) = select.select(rd, [], [], SELECT_TIMEOUT)
for watcher in rd:
watcher.notify()
except socket.error, ex:
if ex.args[0] in (EAGAIN, EINTR):
pass
else:
raise
finally:
self.watchThread = None
def introduceDomain(self, dom, page, evtchn, path):
self.getxs().introduce_domain(dom, page, evtchn.port1, path)
def releaseDomain(self, dom):
self.getxs().release_domain(dom)
def getXenStore():
global xenstore
try:
return xenstore
except:
xenstore = XenStore()
return xenstore
class XenNode:
def __init__(self, path="/", create=True):
self.store = getXenStore()
self.path = path
if not self.store.exists(path):
if create:
self.store.create(path)
else:
raise ValueError("path does not exist: '%s'" % path)
def relPath(self, path=""):
if not path:
return self.path
if path and path.startswith("/"):
path = path[1:]
return os.path.join(self.path, path)
def delete(self, path=""):
self.store.rm(self.relPath(path))
def exists(self, path=""):
return self.store.exists(self.relPath(path))
def getNode(self, path="", create=True):
if path == "":
return self
else:
return XenNode(self.relPath(path=path), create=create)
getChild = getNode
def getData(self, path=""):
path = self.relPath(path)
try:
return self.store.read(path)
except:
return None
def setData(self, data, path=""):
path = self.relPath(path)
#print 'XenNode>setData>', 'path=', path, 'data=', data
return self.store.write(path, data)
def getLock(self):
return None
def lock(self, lockid):
return None
def unlock(self, lockid):
return None
def deleteChild(self, name):
self.delete(name)
def deleteChildren(self):
for name in self.ls():
self.deleteChild(name)
def getChildren(self):
return [ self.getNode(name) for name in self.ls() ]
def ls(self):
return self.store.ls(self.path)
def introduceDomain(self, dom, page, evtchn, path):
self.store.introduceDomain(dom, page, evtchn, path)
def releaseDomain(self, dom):
self.store.releaseDomain(dom)
def __repr__(self):
return "<XenNode %s>" % self.path
+519
View File
@@ -0,0 +1,519 @@
import string
import types
from xen.xend import sxp
from xsnode import XenNode
from xen.util.mac import macToString, macFromString
VALID_KEY_CHARS = string.ascii_letters + string.digits + "_-@"
def hasAttr(obj, attr):
if isinstance(obj, dict):
return obj.contains(attr)
else:
return hasattr(obj, attr)
def getAttr(obj, attr):
if isinstance(obj, dict):
return dict.get(attr)
else:
return getattr(obj, attr, None)
def setAttr(obj, attr, val):
if isinstance(obj, dict):
dict[attr] = val
else:
setattr(obj, attr, val)
class DBConverter:
"""Conversion of values to and from strings in xenstore.
"""
converters = {}
def checkType(cls, ty):
if ty is None or ty in cls.converters:
return
raise ValueError("invalid converter type: '%s'" % ty)
checkType = classmethod(checkType)
def getConverter(cls, ty=None):
if ty is None:
ty = "str"
conv = cls.converters.get(ty)
if not conv:
raise ValueError("no converter for type: '%s'" % ty)
return conv
getConverter = classmethod(getConverter)
def convertToDB(cls, val, ty=None):
return cls.getConverter(ty).toDB(val)
convertToDB = classmethod(convertToDB)
def convertFromDB(cls, val, ty=None):
return cls.getConverter(ty).fromDB(val)
convertFromDB = classmethod(convertFromDB)
# Must define in subclass.
name = None
def __init__(self):
self.register()
def register(self):
if not self.name:
raise ValueError("invalid converter name: '%s'" % self.name)
self.converters[self.name] = self
def toDB(self, val):
raise NotImplementedError()
def fromDB(self, val):
raise NotImplementedError()
class StrConverter(DBConverter):
name = "str"
def toDB(self, val):
# Convert True/False to 1/0, otherwise they convert to
# 'True' and 'False' rather than '1' and '0', even though
# isinstance(True/False, int) is true.
if isinstance(val, bool):
val = int(val)
return str(val)
def fromDB(self, data):
return data
StrConverter()
class BoolConverter(DBConverter):
name = "bool"
def toDB(self, val):
return str(int(bool(val)))
def fromDB(self, data):
return bool(int(data))
BoolConverter()
class SxprConverter(DBConverter):
name = "sxpr"
def toDB(self, val):
return sxp.to_string(val)
def fromDB(self, data):
return sxp.from_string(data)
SxprConverter()
class IntConverter(DBConverter):
name = "int"
def toDB(self, val):
return str(int(val))
def fromDB(self, data):
return int(data)
IntConverter()
class FloatConverter(DBConverter):
name = "float"
def toDB(self, val):
return str(float(val))
def fromDB(self, data):
return float(data)
FloatConverter()
class LongConverter(DBConverter):
name = "long"
def toDB(self, val):
return str(long(val))
def fromDB(self, data):
return long(data)
LongConverter()
class MacConverter(DBConverter):
name = "mac"
def toDB(self, val):
return macToString(val)
def fromDB(self, data):
return macFromString(data)
MacConverter()
class DBVar:
def __init__(self, var, ty=None, path=None):
DBConverter.checkType(ty)
if path is None:
path = var
self.var = var
self.ty = ty
self.path = path
varpath = filter(bool, self.var.split())
self.attrpath = varpath[:-1]
self.attr = varpath[-1]
def exportToDB(self, db, obj):
self.setDB(db, self.getObj(obj))
def importFromDB(self, db, obj):
self.setObj(obj, self.getDB(db))
def getObj(self, obj):
o = obj
for x in self.attrpath:
o = getAttr(o, x)
if o is None:
return None
return getAttr(o, self.attr)
def setObj(self, obj, val):
o = obj
for x in self.attrpath:
o = getAttr(o, x)
# Don't set obj attr if val is None.
if val is None and hasAttr(o, self.attr):
return
setAttr(o, self.attr, val)
def getDB(self, db):
data = getattr(db, self.path)
return DBConverter.convertFromDB(data, ty=self.ty)
def setDB(self, db, val):
# Don't set in db if val is None.
#print 'DBVar>setDB>', self.path, 'val=', val
if val is None:
return
data = DBConverter.convertToDB(val, ty=self.ty)
#print 'DBVar>setDB>', self.path, 'data=', data
setattr(db, self.path, data)
class DBMap(dict):
"""A persistent map. Extends dict with persistence.
Set and get values using the usual map syntax:
m[k], m.get(k)
m[k] = v
Also supports being treated as an object with attributes.
When 'k' is a legal identifier you may also use
m.k, getattr(m, k)
m.k = v, setattr(m, k)
k in m, hasattr(m, k)
When setting you can pass in a normal value, for example
m.x = 3
Getting works too:
m.x ==> 3
while m['x'] will return the map for x.
m['x'].getData() ==> 3
To get values from subdirs use get() to get the subdir first:
get(m, 'foo').x
m['foo'].x
instead of m.foo.x, because m.foo will return the data for field foo,
not the directory.
You can assign values into a subdir by passing a map:
m.foo = {'x': 1, 'y':2 }
You can also use paths as keys:
m['foo/x'] = 1
sets field x in subdir foo.
"""
__db__ = None
__data__ = None
__perms__ = None
__parent__ = None
__name__ = ""
__transaction__ = False
# True if value set since saved (or never saved).
__dirty__ = True
def __init__(self, parent=None, name="", db=None):
if parent is None:
self.__name__ = name
else:
if not isinstance(parent, DBMap):
raise ValueError("invalid parent")
self.__parent__ = parent
self.__name__ = name
db = self.__parent__.getChildDB(name)
self.setDB(db)
def getName(self):
return self.__name__
def getPath(self):
return self.__db__ and self.__db__.relPath()
def introduceDomain(self, dom, page, evtchn, path=None):
db = self.__db__
if path is None:
path = db.relPath()
print 'DBMap>introduceDomain>', dom, page, evtchn, path
try:
db.introduceDomain(dom, page, evtchn, path)
except Exception, ex:
import traceback
traceback.print_exc()
print 'DBMap>introduceDomain>', ex
pass # todo: don't ignore
def releaseDomain(self, dom):
db = self.__db__
print 'DBMap>releaseDomain>', dom
try:
db.releaseDomain(dom)
except Exception, ex:
import traceback
traceback.print_exc()
print 'DBMap>releaseDomain>', ex
pass # todo: don't ignore
def transactionBegin(self):
# Begin a transaction.
pass
def transactionCommit(self):
# Commit writes to db.
pass
def transactionFail(self):
# Fail a transaction.
# We have changed values, what do we do?
pass
def watch(self, fn):
pass
def unwatch(self, watch):
pass
def checkName(self, k):
if k == "":
raise ValueError("invalid key, empty string")
for c in k:
if c in VALID_KEY_CHARS: continue
raise ValueError("invalid key char '%s'" % c)
def _setData(self, v):
#print 'DBMap>_setData>', self.getPath(), 'data=', v
if v != self.__data__:
self.__dirty__ = True
self.__data__ = v
def setData(self, v):
if isinstance(v, dict):
for (key, val) in v.items():
self[key] = val
else:
self._setData(v)
def getData(self):
return self.__data__
def _set(self, k, v):
dict.__setitem__(self, k, v)
def _get(self, k):
try:
return dict.__getitem__(self, k)
except:
return None
def _del(self, k, v):
try:
dict.__delitem__(self, k)
except:
pass
def _contains(self, k):
return dict.__contains__(self, k)
def __setitem__(self, k, v, save=False):
node = self.addChild(k)
node.setData(v)
if save:
node.saveDB()
def __getitem__(self, k):
if self._contains(k):
v = self._get(k)
else:
v = self.readChildDB(k)
self._set(k, v)
return v
def __delitem__(self, k):
self._del(k)
self.deleteChildDB(k)
def __repr__(self):
if len(self):
return dict.__repr__(self)
else:
return repr(self.__data__)
def __setattr__(self, k, v):
if k.startswith("__"):
object.__setattr__(self, k, v)
else:
self.__setitem__(k, v, save=True)
return v
def __getattr__(self, k):
if k.startswith("__"):
v = object.__getattr__(self, k)
else:
try:
v = self.__getitem__(k).getData()
except LookupError, ex:
raise AttributeError(ex.args)
return v
def __delattr__(self, k):
return self.__delitem__(k)
def delete(self):
dict.clear(self)
self.__data__ = None
if self.__db__:
self.__db__.delete()
def clear(self):
dict.clear(self)
if self.__db__:
self.__db__.deleteChildren()
def getChild(self, k):
return self._get(k)
def getChildDB(self, k):
self.checkName(k)
return self.__db__ and self.__db__.getChild(k)
def deleteChildDB(self, k):
if self.__db__:
self.__db__.deleteChild(k)
def _addChild(self, k):
kid = self._get(k)
if kid is None:
kid = DBMap(parent=self, name=k, db=self.getChildDB(k))
self._set(k, kid)
return kid
def addChild(self, path):
l = path.split("/")
n = self
for x in l:
if x == "": continue
n = n._addChild(x)
return n
def setDB(self, db):
if (db is not None) and not isinstance(db, XenNode):
raise ValueError("invalid db")
self.__db__ = db
for (k, v) in self.items():
if v is None: continue
if isinstance(v, DBMap):
v._setDB(self.addChild(k), restore)
def readDB(self):
if self.__db__ is None:
return
self.__data__ = self.__db__.getData()
for k in self.__db__.ls():
n = self.addChild(k)
n.readDB()
self.__dirty__ = False
def readChildDB(self, k):
if self.__db__ and (k in self.__db__.ls()):
n = self.addChild(k)
n.readDB()
raise LookupError("invalid key '%s'" % k)
def saveDB(self, sync=False, save=False):
"""Save unsaved data to db.
If save or sync is true, saves whether dirty or not.
If sync is true, removes db entries not in the map.
"""
if self.__db__ is None:
#print 'DBMap>saveDB>',self.getPath(), 'no db'
return
# Write data.
#print 'DBMap>saveDB>', self.getPath(), 'dirty=', self.__dirty__, 'data=', self.__data__
if ((self.__data__ is not None)
and (sync or save or self.__dirty__)):
self.__db__.setData(self.__data__)
self.__dirty__ = False
else:
#print 'DBMap>saveDB>', self.getPath(), 'not written'
pass
# Write children.
for (name, node) in self.items():
if not isinstance(node, DBMap): continue
node.saveDB(sync=sync, save=save)
# Remove db nodes not in children.
if sync:
for name in self.__db__.ls():
if name not in self:
self.__db__.delete(name)
def importFromDB(self, obj, fields):
"""Set fields in obj from db fields.
"""
for f in fields:
f.importFromDB(self, obj)
def exportToDB(self, obj, fields, save=False, sync=False):
"""Set fields in db from obj fields.
"""
for f in fields:
f.exportToDB(self, obj)
self.saveDB(save=save, sync=sync)
@@ -0,0 +1,136 @@
#============================================================================
# Copyright (C) 2005 Mike Wray <mike.wray@hp.com>
#============================================================================
# HTTP interface onto xenstore (read-only).
# Mainly intended for testing.
import os
import os.path
from xen.web.httpserver import HttpServer, UnixHttpServer
from xen.web.SrvBase import SrvBase
from xen.web.SrvDir import SrvDir
from xen.xend.Args import FormFn
from xen.xend.xenstore import XenNode
def pathurl(req):
url = req.prePathURL()
if not url.endswith('/'):
url += '/'
return url
def writelist(req, l):
req.write('(')
for k in l:
req.write(' ' + k)
req.write(')')
def lsData(dbnode, req, url):
v = dbnode.getData()
if v is None:
req.write('<p>No data')
else:
req.write('<p>Data: <pre>')
req.write(str(v))
req.write('</pre>')
v = dbnode.getLock()
if v is None:
req.write("<p>Unlocked")
else:
req.write("<p>Lock = %s" % v)
def lsChildren(dbnode, req, url):
l = dbnode.ls()
if l:
req.write('<p>Children: <ul>')
for key in l:
child = dbnode.getChild(key)
data = child.getData()
if data is None: data = ""
req.write('<li><a href="%(url)s%(key)s">%(key)s</a> %(data)s</li>'
% { "url": url, "key": key, "data": data })
req.write('</ul>')
else:
req.write('<p>No children')
class DBDataResource(SrvBase):
"""Resource for the node data.
"""
def __init__(self, dbnode):
SrvBase.__init__(self)
self.dbnode = dbnode
def render_GET(self, req):
req.write('<html><head></head><body>')
self.print_path(req)
req.write("<pre>")
req.write(self.getData() or self.getNoData())
req.write("</pre>")
req.write('</body></html>')
def getContentType(self):
# Use content-type from metadata.
return "text/plain"
def getData(self):
v = self.dbnode.getData()
if v is None: return v
return str(v)
def getNoData(self):
return ""
class DBNodeResource(SrvDir):
"""Resource for a DB node.
"""
def __init__(self, dbnode):
SrvDir.__init__(self)
self.dbnode = dbnode
def get(self, x):
val = None
if x == "__data__":
val = DBDataResource(self.dbnode)
else:
if self.dbnode.exists(x):
child = self.dbnode.getChild(x, create=False)
else:
child = None
if child is not None:
val = DBNodeResource(child)
return val
def render_POST(self, req):
return self.perform(req)
def ls(self, req, use_sxp=0):
if use_sxp:
writelist(req, self.dbnode.getChildren())
else:
url = pathurl(req)
req.write("<fieldset>")
lsData(self.dbnode, req, url)
lsChildren(self.dbnode, req, url)
req.write("</fieldset>")
def form(self, req):
url = req.prePathURL()
pass
class DBRootResource(DBNodeResource):
"""Resource for the root of a DB.
"""
def __init__(self):
DBNodeResource.__init__(self, XenNode())
def main(argv):
root = SrvDir()
root.putChild('xenstore', DBRootResource())
interface = ''
port = 8003
server = HttpServer(root=root, interface=interface, port=port)
server.run()
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.