# HG changeset patch
# User emellor@ewan
# Node ID 70d5bfbf23d4c7ba21b4029ad63471959f854b86
# Parent a73ab0ddf990f2e3c341a43e3aa3d7d0e3a7cc61
Move XendVnet from using DBMap etc to using xstransact. This is the last
dependency upon xsnode, xsobj, and xsresource, so these can all go.
Signed-off-by: Ewan Mellor <ewan@xxxxxxxxxxxxx>
diff -r a73ab0ddf990 -r 70d5bfbf23d4 tools/python/xen/xend/XendVnet.py
--- a/tools/python/xen/xend/XendVnet.py Sun Oct 2 17:21:01 2005
+++ b/tools/python/xen/xend/XendVnet.py Sun Oct 2 17:22:22 2005
@@ -13,6 +13,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (C) 2005 XenSource Ltd
#============================================================================
"""Handler for vnet operations.
@@ -22,7 +23,8 @@
from xen.xend import sxp
from xen.xend.XendError import XendError
from xen.xend.XendLogging import log
-from xen.xend.xenstore import XenNode, DBMap, DBVar
+from xen.xend.xenstore.xstransact import xstransact
+
def vnet_cmd(cmd):
out = None
@@ -39,39 +41,40 @@
vifctl_ops = {'up': 'vif.add', 'down': 'vif.del'}
- __exports__ = [
- DBVar('id', ty='str'),
- DBVar('dbid', ty='str'),
- DBVar('config', ty='sxpr'),
- ]
-
- def __init__(self, db, config=None):
+ def __init__(self, dbpath, config=None):
if config:
- self.id = sxp.child_value(config, 'id')
- self.id = str(self.id)
+ self.id = str(sxp.child_value(config, 'id'))
self.dbid = self.id.replace(':', '-')
- self.db = db.addChild(self.dbid)
+ self.dbpath = dbpath + '/' + self.dbid
self.config = config
else:
- self.db = db
+ self.dbpath = dbpath
self.importFromDB()
- config = self.config
- self.bridge = sxp.child_value(config, 'bridge')
+ self.bridge = sxp.child_value(self.config, 'bridge')
if not self.bridge:
self.bridge = "vnet%s" % self.id
- self.vnetif = sxp.child_value(config, 'vnetif')
+ self.vnetif = sxp.child_value(self.config, 'vnetif')
if not self.vnetif:
self.vnetif = "vnif%s" % self.id
- def saveToDB(self, save=False, sync=False):
- self.db.saveDB(save=save, sync=sync)
def exportToDB(self, save=False, sync=False):
- self.db.exportToDB(self, fields=self.__exports__, save=save, sync=sync)
+ to_store = {
+ 'id' : self.id,
+ 'dbid' : self.dbid,
+ 'config' : sxp.to_string
+ }
+ xstransact.Write(self.dbpath, to_store)
+
def importFromDB(self):
- self.db.importFromDB(self, fields=self.__exports__)
+ (self.id, self.dbid, c) = xstransact.Gather(self.dbpath,
+ ('id', str),
+ ('dbid', str),
+ ('config', str))
+ self.config = sxp.from_string(c)
+
def sxpr(self):
return self.config
@@ -88,7 +91,7 @@
Brctl.vif_bridge_rem({'bridge': self.bridge, 'vif': self.vnetif})
Brctl.bridge_del(self.bridge)
val = vnet_cmd(['vnet.del', self.id])
- self.db.delete()
+ xstransact.Remove(self.dbpath)
return val
def vifctl(self, op, vif, vmac):
@@ -107,18 +110,17 @@
def __init__(self):
# Table of vnet info indexed by vnet id.
self.vnet = {}
- self.db = DBMap(db=XenNode(self.dbpath))
- self.db.readDB()
- for vnetdb in self.db.values():
+ listing = xstransact.List(self.dbpath)
+ for entry in listing:
try:
- info = XendVnetInfo(vnetdb)
+ info = XendVnetInfo(self.dbpath + '/' + entry)
self.vnet[info.id] = info
info.configure()
except XendError, ex:
log.warning("Failed to configure vnet %s: %s", str(info.id),
str(ex))
except Exception, ex:
log.exception("Vnet error")
- vnetdb.delete()
+ xstransact.Remove(self.dbpath + '/' + entry)
def vnet_of_bridge(self, bridge):
"""Get the vnet for a bridge (if any).
@@ -155,9 +157,9 @@
@param config: config
"""
- info = XendVnetInfo(self.db, config=config)
+ info = XendVnetInfo(self.dbpath, config=config)
self.vnet[info.id] = info
- info.saveToDB()
+ info.exportToDB()
info.configure()
def vnet_delete(self, id):
diff -r a73ab0ddf990 -r 70d5bfbf23d4 tools/python/xen/xend/xenstore/__init__.py
--- a/tools/python/xen/xend/xenstore/__init__.py Sun Oct 2 17:21:01 2005
+++ b/tools/python/xen/xend/xenstore/__init__.py Sun Oct 2 17:22:22 2005
@@ -14,5 +14,3 @@
#============================================================================
# Copyright (C) 2005 Mike Wray <mike.wray@xxxxxx>
#============================================================================
-from xsnode import *
-from xsobj import *
diff -r a73ab0ddf990 -r 70d5bfbf23d4 tools/python/xen/xend/xenstore/xsnode.py
--- a/tools/python/xen/xend/xenstore/xsnode.py Sun Oct 2 17:21:01 2005
+++ /dev/null Sun Oct 2 17:22:22 2005
@@ -1,477 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray@xxxxxx>
-#============================================================================
-import errno
-import os
-import os.path
-import select
-import socket
-import sys
-import threading
-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):
- if event and event.startswith("/"):
- event = event[1:]
- return os.path.join("/event", event)
-
-def getEventIdPath(event):
- return os.path.join(getEventPath(event), "@eid")
-
-class Subscription:
-
- def __init__(self, path, fn, sid):
- self.path = path
- self.watcher = None
- self.fn = fn
- self.sid = sid
-
- def getPath(self):
- return self.path
-
- def getSid(self):
- return self.sid
-
- def watch(self, watcher):
- self.watcher = watcher
- watcher.addSubs(self)
-
- def unwatch(self):
- watcher = self.watcher
- if watcher:
- self.watcher = None
- watcher.delSubs(self)
- return watcher
-
- def notify(self, token, path, val):
- try:
- self.fn(self, token, path, val)
- except SystemExit:
- raise
- except Exception, ex:
- pass
-
-class Watcher:
-
- def __init__(self, store, path):
- self.path = path
- store.mkdirs(self.path)
- self.xs = None
- self.subscriptions = []
-
- def fileno(self):
- if self.xs:
- return self.xs.fileno()
- else:
- return -1
-
- def getPath(self):
- return self.path
-
- def getToken(self):
- return self.path
-
- def addSubs(self, subs):
- self.subscriptions.append(subs)
- self.watch()
-
- def delSubs(self, subs):
- self.subscriptions.remove(subs)
- if len(self.subscriptions) == 0:
- self.unwatch()
-
- def watch(self):
- if self.xs: return
- self.xs = xs.open()
- self.xs.watch(path=self.getPath(), token=self.getToken())
-
- def unwatch(self):
- if self.xs:
-## Possibly crashes xenstored.
-## try:
-## self.xs.unwatch(path=self.getPath(), token=self.getToken())
-## except Exception, ex:
-## print 'Watcher>unwatch>', ex
- try:
- self.xs.close()
- except Exception, ex:
- pass
- self.xs = None
-
- def watching(self):
- return self.xs is not None
-
- def getNotification(self):
- p = self.xs.read_watch()
- self.xs.acknowledge_watch(p[1])
- return p
-
- def notify(self):
- try:
- (path, token) = self.getNotification()
- if path.endswith("@eid"):
- pass
- else:
- val = self.xs.read(path)
- for subs in self.subscriptions:
- subs.notify(token, path, val)
- except SystemExit:
- raise
- except Exception, ex:
- raise
-
-class EventWatcher(Watcher):
-
- def __init__(self, store, path, event):
- Watcher.__init__(self, store, path)
- self.event = event
- self.eidPath = getEventIdPath(event)
- if not store.exists(self.eidPath):
- store.write(self.eidPath, str(0))
-
- def getEvent(self):
- return self.event
-
- def getToken(self):
- return self.event
-
-class XenStore:
-
- xs = None
- watchThread = None
- subscription_id = 1
-
- def __init__(self):
- self.subscriptions = {}
- self.watchers = {}
- 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 SystemExit:
- raise
- except Exception, ex:
- print >>sys.stderr, "Exception connecting to xenstored:",
ex
- print >>sys.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 RuntimeError(ex.args[0],
- ex.args[1] +
- (', in exists(%s)' % (str(path))))
-
- 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, "")
-
- 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):
- self.write(path, "")
-
- def write(self, path, data):
- try:
- self.getxs().write(path, data)
- except RuntimeError, ex:
- raise RuntimeError(ex.args[0],
- ex.args[1] +
- (', while writing %s : %s' % (str(path),
- str(data))))
-
- def begin(self):
- self.getxs().transaction_start()
-
- def commit(self, abandon=False):
- self.getxs().transaction_end(abort=abandon)
-
- def watch(self, path, fn):
- watcher = self.watchers.get(path)
- if not watcher:
- watcher = self.addWatcher(Watcher(self, path))
- return self.addSubscription(watcher, fn)
-
- def unwatch(self, sid):
- s = self.subscriptions.get(sid)
- if not s: return
- del self.subscriptions[s.sid]
- watcher = s.unwatch()
- if watcher and not watcher.watching():
- try:
- del self.watchers[watcher.getPath()]
- except:
- pass
-
- def subscribe(self, event, fn):
- path = getEventPath(event)
- watcher = self.watchers.get(path)
- if not watcher:
- watcher = self.addWatcher(EventWatcher(self, path, event))
- return self.addSubscription(watcher, fn)
-
- unsubscribe = unwatch
-
- def sendEvent(self, event, data):
- eventPath = getEventPath(event)
- eidPath = getEventIdPath(event)
- try:
- #self.begin(eventPath)
- self.mkdirs(eventPath)
- eid = 1
- if self.exists(eidPath):
- try:
- eid = int(self.read(eidPath))
- eid += 1
- except Exception, ex:
- pass
- self.write(eidPath, str(eid))
- self.write(os.path.join(eventPath, str(eid)), data)
- finally:
- #self.commit()
- pass
-
- def addWatcher(self, watcher):
- self.watchers[watcher.getPath()] = watcher
- self.watchStart()
- return watcher
-
- def addSubscription(self, watcher, fn):
- self.subscription_id += 1
- subs = Subscription(watcher.getPath(), fn, self.subscription_id)
- self.subscriptions[subs.sid] = subs
- subs.watch(watcher)
- return subs.sid
-
- def watchStart(self):
- if self.watchThread: return
- self.watchThread = threading.Thread(name="Watcher",
- target=self.watchMain)
- self.watchThread.setDaemon(True)
- self.watchThread.start()
-
- def watchMain(self):
- try:
- while True:
- if self.watchThread is None: return
- if not self.watchers:
- return
- rd = self.watchers.values()
- try:
- (srd, swr, ser) = select.select(rd, [], [], SELECT_TIMEOUT)
- for watcher in srd:
- watcher.notify()
- except socket.error, ex:
- if ex.args[0] in (EAGAIN, EINTR):
- pass
- else:
- raise
- finally:
- self.watchThread = None
-
-def getXenStore():
- global xenstore
- try:
- return xenstore
- except:
- xenstore = XenStore()
- return xenstore
-
-def sendEvent(event, val):
- getXenStore.sendEvent(event, val)
-
-def subscribe(event, fn):
- return getXenStore().subscribe(event, fn)
-
-def unsubscribe(sid):
- getXenStore().unsubscribe(sid)
-
-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 getStore(self):
- return self.store
-
- 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=""):
- return self.store.write(self.relPath(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 watch(self, fn, path=""):
- """Watch a path for changes. The path is relative
- to the node and defaults to the node itself.
- """
- return self.store.watch(self.relPath(path), fn)
-
- def unwatch(self, sid):
- return self.store.unwatch(sid)
-
- def subscribe(self, event, fn):
- return self.store.subscribe(event, fn)
-
- def unsubscribe(self, sid):
- self.store.unsubscribe(sid)
-
- def sendEvent(self, event, data):
- return self.store.sendEvent(event, data)
-
- def __repr__(self):
- return "<XenNode %s>" % self.path
-
-
diff -r a73ab0ddf990 -r 70d5bfbf23d4 tools/python/xen/xend/xenstore/xsobj.py
--- a/tools/python/xen/xend/xenstore/xsobj.py Sun Oct 2 17:21:01 2005
+++ /dev/null Sun Oct 2 17:22:22 2005
@@ -1,537 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray@xxxxxx>
-#============================================================================
-import string
-import types
-
-from xen.xend.XendLogging import log
-
-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):
- try:
- if isinstance(obj, dict):
- return obj.get(attr)
- else:
- return getattr(obj, attr, None)
- except AttributeError:
- return None
- except LookupError:
- return None
-
-def setAttr(obj, attr, val):
- if isinstance(obj, dict):
- obj[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 exportTypeToDB(cls, db, path, val, ty=None):
- return cls.getConverter(ty).exportToDB(db, path, val)
-
- exportTypeToDB = classmethod(exportTypeToDB)
-
- def importTypeFromDB(cls, db, path, ty=None):
- return cls.getConverter(ty).importFromDB(db, path)
-
- importTypeFromDB = classmethod(importTypeFromDB)
-
- # 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 exportToDB(self, db, path, val):
- if val is None:
- return
- try:
- data = self.toDB(val)
- except Exception, ex:
- raise
- setattr(db, path, data)
-
- def importFromDB(self, db, path):
- data = getAttr(db, path)
- if data is None:
- val = None
- else:
- try:
- val = self.fromDB(data.getData())
- except Exception, ex:
- raise
- return val
-
- 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):
- val = self.getObj(obj)
- DBConverter.exportTypeToDB(db, self.path, val, ty=self.ty)
-
- def importFromDB(self, db, obj):
- val = DBConverter.importTypeFromDB(db, self.path, ty=self.ty)
- self.setObj(obj, val)
-
- 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)
-
-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 watch(self, fn, path=""):
- return self.__db__.watch(fn, path=path)
-
- def unwatch(self, sid):
- return self.__db__.unwatch(sid)
-
- def subscribe(self, event, fn):
- return self.__db__.subscribe(event, fn)
-
- def unsubscribe(self, sid):
- return self.__db__.unsubscribe(sid)
-
- def sendEvent(self, event, val):
- return self.__db__.sendEvent(event, val)
-
- 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 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()
- l = self.__db__.ls()
- if l:
- for k in l:
- 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)
diff -r a73ab0ddf990 -r 70d5bfbf23d4
tools/python/xen/xend/xenstore/xsresource.py
--- a/tools/python/xen/xend/xenstore/xsresource.py Sun Oct 2 17:21:01 2005
+++ /dev/null Sun Oct 2 17:22:22 2005
@@ -1,149 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2005 Mike Wray <mike.wray@xxxxxx>
-#============================================================================
-# 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()
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|