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@xensource.com>
This commit is contained in:
emellor@ewan committed 2005-10-02 18:22:22 +01:00
1 parent ec7bb10f8e
commit c8a89eae6b
5 files changed
+29 -1192

No files matched your search

+29 -27
View File
@@ -13,6 +13,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
# Copyright (C) 2005 XenSource Ltd
#============================================================================
"""Handler for vnet operations.
@@ -22,7 +23,8 @@ from xen.util import Brctl
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 @@ class XendVnetInfo:
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 @@ class XendVnetInfo:
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 @@ class XendVnet:
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 @@ class XendVnet:
@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):
@@ -14,5 +14,3 @@
#============================================================================
# Copyright (C) 2005 Mike Wray <mike.wray@hp.com>
#============================================================================
from xsnode import *
from xsobj import *
-477
View File
@@ -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@hp.com>
#============================================================================
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
-537
View File
@@ -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@hp.com>
#============================================================================
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)
@@ -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@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.