mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 18:21:39 +01:00
Merged.
This commit is contained in:
commit
3bd89f2ebf
12 files changed
+122
-88
No files matched your search
@@ -36,6 +36,7 @@ from xen.xend import XendCheckpoint
|
||||
from xen.xend.XendError import XendError
|
||||
from xen.xend.XendLogging import log
|
||||
from xen.xend.server import relocate
|
||||
from xen.xend.xenstore.xswatch import xswatch
|
||||
|
||||
|
||||
xc = xen.lowlevel.xc.new()
|
||||
@@ -58,9 +59,11 @@ class XendDomain:
|
||||
# to import XendDomain from XendDomainInfo causes unbounded recursion.
|
||||
# So we stuff the XendDomain instance (self) into xroot's components.
|
||||
xroot.add_component("xen.xend.XendDomain", self)
|
||||
|
||||
self.domains = {}
|
||||
self.domains_lock = threading.RLock()
|
||||
self.watchReleaseDomain()
|
||||
|
||||
xswatch("@releaseDomain", self.onReleaseDomain)
|
||||
|
||||
self.domains_lock.acquire()
|
||||
try:
|
||||
@@ -112,11 +115,7 @@ class XendDomain:
|
||||
self.refresh()
|
||||
finally:
|
||||
self.domains_lock.release()
|
||||
|
||||
|
||||
def watchReleaseDomain(self):
|
||||
from xen.xend.xenstore.xswatch import xswatch
|
||||
self.releaseDomain = xswatch("@releaseDomain", self.onReleaseDomain)
|
||||
return 1
|
||||
|
||||
|
||||
def xen_domains(self):
|
||||
|
||||
@@ -29,6 +29,12 @@ DEVICE_CREATE_TIMEOUT = 5
|
||||
HOTPLUG_STATUS_NODE = "hotplug-status"
|
||||
HOTPLUG_STATUS_ERROR = "error"
|
||||
|
||||
Connected = 1
|
||||
Died = 2
|
||||
Error = 3
|
||||
Missing = 4
|
||||
Timeout = 5
|
||||
|
||||
xenbusState = {
|
||||
'Unknown' : 0,
|
||||
'Initialising' : 1,
|
||||
@@ -87,18 +93,28 @@ class DevController:
|
||||
def waitForDevice(self, devid):
|
||||
log.debug("Waiting for %s.", devid)
|
||||
|
||||
status, fn_ret = self.waitForBackend(devid)
|
||||
if status:
|
||||
self.destroyDevice(devid)
|
||||
raise VmError( ("Device %s (%s) could not be connected. "
|
||||
"Hotplug scripts not working")
|
||||
% (devid, self.deviceClass))
|
||||
status = self.waitForBackend(devid)
|
||||
|
||||
elif fn_ret == HOTPLUG_STATUS_ERROR:
|
||||
if status == Timeout:
|
||||
self.destroyDevice(devid)
|
||||
raise VmError( ("Device %s (%s) could not be connected. "
|
||||
"Backend device not found!")
|
||||
% (devid, self.deviceClass))
|
||||
raise VmError("Device %s (%s) could not be connected. "
|
||||
"Hotplug scripts not working" %
|
||||
(devid, self.deviceClass))
|
||||
|
||||
elif status == Error:
|
||||
self.destroyDevice(devid)
|
||||
raise VmError("Device %s (%s) could not be connected. "
|
||||
"Backend device not found" %
|
||||
(devid, self.deviceClass))
|
||||
|
||||
elif status == Missing:
|
||||
raise VmError("Device %s (%s) could not be connected. "
|
||||
"Device not found" % (devid, self.deviceClass))
|
||||
|
||||
elif status == Died:
|
||||
self.destroyDevice(devid)
|
||||
raise VmError("Device %s (%s) could not be connected. "
|
||||
"Device has died" % (devid, self.deviceClass))
|
||||
|
||||
|
||||
def reconfigureDevice(self, devid, config):
|
||||
@@ -302,35 +318,22 @@ class DevController:
|
||||
raise
|
||||
|
||||
|
||||
def waitForBackend(self,devid):
|
||||
ev = Event()
|
||||
def waitForBackend(self, devid):
|
||||
|
||||
def hotplugStatus():
|
||||
log.debug("hotplugStatus %d", devid)
|
||||
|
||||
try:
|
||||
status = self.readBackend(devid, HOTPLUG_STATUS_NODE)
|
||||
except VmError:
|
||||
status = "died"
|
||||
if status is not None:
|
||||
watch.xs.unwatch(backpath, watch)
|
||||
hotplugStatus.value = status
|
||||
ev.set()
|
||||
|
||||
hotplugStatus.value = None
|
||||
frontpath = self.frontendPath(devid)
|
||||
backpath = xstransact.Read(frontpath, "backend")
|
||||
|
||||
if backpath:
|
||||
watch = xswatch(backpath, hotplugStatus)
|
||||
statusPath = backpath + '/' + HOTPLUG_STATUS_NODE
|
||||
ev = Event()
|
||||
result = { 'status': Timeout }
|
||||
|
||||
xswatch(statusPath, hotplugStatusCallback, statusPath, ev, result)
|
||||
|
||||
ev.wait(DEVICE_CREATE_TIMEOUT)
|
||||
if ev.isSet():
|
||||
return (0, hotplugStatus.value)
|
||||
else:
|
||||
return (-1, hotplugStatus.value)
|
||||
return result['status']
|
||||
else:
|
||||
return (-1, "missing")
|
||||
return Missing
|
||||
|
||||
|
||||
def backendPath(self, backdom, devid):
|
||||
@@ -352,3 +355,25 @@ class DevController:
|
||||
def frontendMiscPath(self):
|
||||
return "%s/device-misc/%s" % (self.vm.getDomainPath(),
|
||||
self.deviceClass)
|
||||
|
||||
|
||||
def hotplugStatusCallback(statusPath, ev, result):
|
||||
log.debug("hotplugStatusCallback %s.", statusPath)
|
||||
|
||||
try:
|
||||
status = xstransact.Read(statusPath)
|
||||
|
||||
if status is not None:
|
||||
if status == HOTPLUG_STATUS_ERROR:
|
||||
result['status'] = Error
|
||||
else:
|
||||
result['status'] = Connected
|
||||
else:
|
||||
return 1
|
||||
except VmError:
|
||||
result['status'] = Died
|
||||
|
||||
log.debug("hotplugStatusCallback %d.", result['status'])
|
||||
|
||||
ev.set()
|
||||
return 0
|
||||
@@ -177,18 +177,15 @@ class xstransact:
|
||||
(key, fn, defval) = tup
|
||||
|
||||
val = self._read(key)
|
||||
# If fn is str, then this will successfully convert None to
|
||||
# 'None'. If it is int, then it will throw TypeError on None, or
|
||||
# on any other non-integer value. We have to, therefore, both
|
||||
# check explicitly for None, and catch TypeError. Either failure
|
||||
# will result in defval being used instead.
|
||||
# If fn is str, then this will successfully convert None to 'None'
|
||||
# (which we don't want). If it is int or float, then it will
|
||||
# throw ValueError on any non-convertible value. We check
|
||||
# explicitly for None, using defval instead, but allow ValueError
|
||||
# to propagate.
|
||||
if val is None:
|
||||
val = defval
|
||||
else:
|
||||
try:
|
||||
val = fn(val)
|
||||
except TypeError:
|
||||
val = defval
|
||||
val = fn(val)
|
||||
ret.append(val)
|
||||
if len(ret) == 1:
|
||||
return ret[0]
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
# Public License. See the file "COPYING" in the main directory of
|
||||
# this archive for more details.
|
||||
|
||||
import select
|
||||
import threading
|
||||
from xen.lowlevel import xs
|
||||
from xen.xend.xenstore.xsutil import xshandle
|
||||
|
||||
from xen.xend.XendLogging import log
|
||||
@@ -15,42 +13,45 @@ from xen.xend.XendLogging import log
|
||||
|
||||
class xswatch:
|
||||
|
||||
watchThread = None
|
||||
xs = None
|
||||
xslock = threading.Lock()
|
||||
|
||||
def __init__(self, path, fn, *args, **kwargs):
|
||||
self.path = path
|
||||
self.fn = fn
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
xswatch.watchStart()
|
||||
xswatch.xs.watch(path, self)
|
||||
watchStart()
|
||||
xs.watch(path, self)
|
||||
|
||||
def watchStart(cls):
|
||||
cls.xslock.acquire()
|
||||
if cls.watchThread:
|
||||
cls.xslock.release()
|
||||
|
||||
watchThread = None
|
||||
xs = None
|
||||
xslock = threading.Lock()
|
||||
|
||||
def watchStart():
|
||||
global watchThread
|
||||
global xs
|
||||
|
||||
xslock.acquire()
|
||||
try:
|
||||
if watchThread:
|
||||
return
|
||||
cls.xs = xshandle()
|
||||
cls.watchThread = threading.Thread(name="Watcher",
|
||||
target=cls.watchMain)
|
||||
cls.watchThread.setDaemon(True)
|
||||
cls.watchThread.start()
|
||||
cls.xslock.release()
|
||||
|
||||
watchStart = classmethod(watchStart)
|
||||
|
||||
def watchMain(cls):
|
||||
while True:
|
||||
try:
|
||||
we = cls.xs.read_watch()
|
||||
watch = we[1]
|
||||
watch.fn(*watch.args, **watch.kwargs)
|
||||
except:
|
||||
log.exception("read_watch failed")
|
||||
# Ignore this exception -- there's no point throwing it
|
||||
# further on because that will just kill the watcher thread,
|
||||
# which achieves nothing.
|
||||
xs = xshandle()
|
||||
watchThread = threading.Thread(name="Watcher", target=watchMain)
|
||||
watchThread.setDaemon(True)
|
||||
watchThread.start()
|
||||
finally:
|
||||
xslock.release()
|
||||
|
||||
|
||||
watchMain = classmethod(watchMain)
|
||||
def watchMain():
|
||||
while True:
|
||||
try:
|
||||
we = xs.read_watch()
|
||||
watch = we[1]
|
||||
res = watch.fn(*watch.args, **watch.kwargs)
|
||||
if not res:
|
||||
xs.unwatch(watch.path, watch)
|
||||
except:
|
||||
log.exception("read_watch failed")
|
||||
# Ignore this exception -- there's no point throwing it
|
||||
# further on because that will just kill the watcher thread,
|
||||
# which achieves nothing.
|
||||