bitkeeper revision 1.1108.35.2 (4108f181qIC17s1k7tUAzAMnlIZwBA)

Add support for getting the xend log.
Needed response headers and mime-types in the xend client code.
Add command groups in xm help.
This commit is contained in:
mjw@wray-m-3.hpl.hp.com committed 2004-07-29 12:45:53 +00:00
1 parent 08aa92db57
commit 7aeeeea161
9 files changed
+179 -80

No files matched your search

+35 -48
View File
@@ -130,7 +130,6 @@ class XendRequest:
class XendClientProtocol:
"""Abstract class for xend clients.
"""
def xendRequest(self, url, method, args=None):
"""Make a request to xend.
Implement in a subclass.
@@ -176,6 +175,9 @@ class XendClientProtocol:
"""Handle the data returned in response to the request.
"""
if data is None: return None
type = self.getHeader('Content-Type')
if type != sxp.mime_type:
return data
try:
pin = sxp.Parser()
pin.input(data);
@@ -194,11 +196,22 @@ class XendClientProtocol:
"""
raise err
def getHeader(self, key):
"""Get a header from the response.
Case is ignored in the key.
@param key: header key
@return: header
"""
raise NotImplementedError()
class SynchXendClientProtocol(XendClientProtocol):
"""A synchronous xend client. This will make a request, wait for
the reply and return the result.
"""
resp = None
def xendRequest(self, url, method, args=None):
"""Make a request to xend.
@@ -211,6 +224,7 @@ class SynchXendClientProtocol(XendClientProtocol):
if DEBUG: conn.set_debuglevel(1)
conn.request(method, url.fullpath(), self.request.data, self.request.headers)
resp = conn.getresponse()
self.resp = resp
val = self.handleStatus(resp.version, resp.status, resp.reason)
if val is None:
data = None
@@ -220,6 +234,10 @@ class SynchXendClientProtocol(XendClientProtocol):
val = self.handleResponse(data)
return val
def getHeader(self, key):
return self.resp.getheader(key)
class AsynchXendClient(http.HTTPClient):
"""A subclass of twisted's HTTPClient to deal with a connection to xend.
Makes the request when connected, and delegates handling responses etc.
@@ -245,6 +263,9 @@ class AsynchXendClient(http.HTTPClient):
def handleStatus(self, version, status, message):
return self.protocol.handleStatus(version, status, message)
def handleHeader(self, key, val):
return self.protocol.handleHeader(key, val)
def handleResponse(self, data):
return self.protocol.handleResponse(data)
@@ -257,47 +278,7 @@ class AsynchXendClientProtocol(XendClientProtocol):
"""
def __init__(self):
self.err = None
def xendRequest(self, url, method, args=None):
"""Make a request to xend. The returned deferred is called when
the result is available.
@param url: xend request url
@param method: http method: POST or GET
@param args: request arguments (dict)
@return: deferred
"""
request = XendRequest(url, method, args)
self.deferred = Deferred()
clientCreator = ClientCreator(reactor, AsynchXendClient, self, request)
clientCreator.connectTCP(url.host, url.port)
return self.deferred
def callErrback(self, err):
if not self.deferred.called:
self.err = err
self.deferred.errback(err)
return err
def callCallback(self, val):
if not self.deferred.called:
self.deferred.callback(val)
return val
def handleException(self, err):
return self.callErrback(err)
def handleResponse(self, data):
if self.err: return self.err
val = XendClientProtocol.handleResponse(self, data)
if isinstance(val, Exception):
self.callErrback(val)
else:
self.callCallback(val)
return val
def __init__(self):
self.err = None
self.headers = {}
def xendRequest(self, url, method, args=None):
"""Make a request to xend. The returned deferred is called when
@@ -328,6 +309,12 @@ class AsynchXendClientProtocol(XendClientProtocol):
def handleException(self, err):
return self.callErrback(err)
def handleHeader(self, key, val):
self.headers[key.lower()] = val
def getHeader(self, key):
return self.headers.get(key.lower())
def handleResponse(self, data):
if self.err: return self.err
val = XendClientProtocol.handleResponse(self, data)
@@ -397,9 +384,6 @@ class Xend:
def eventurl(self, id=''):
return self.url.relative('event/' + str(id))
def dmesgurl(self, id=''):
return self.url.relative('node/dmesg/' + str(id))
def xend(self):
return self.xendGet(self.url)
@@ -408,14 +392,17 @@ class Xend:
def xend_node_shutdown(self):
return self.xendPost(self.nodeurl(),
{'op' : 'shutdown'})
{'op' : 'shutdown'})
def xend_node_restart(self):
return self.xendPost(self.nodeurl(),
{'op' : 'reboot'})
{'op' : 'reboot'})
def xend_node_dmesg(self):
return self.xendGet(self.dmesgurl())
return self.xendGet(self.nodeurl('dmesg'))
def xend_node_log(self):
return self.xendGet(self.nodeurl('log'))
def xend_node_cpu_rrobin_slice_set(self, slice):
return self.xendPost(self.nodeurl(),
+2 -2
View File
@@ -1,4 +1,4 @@
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
"""Get dmesg output for this node.
"""
@@ -11,7 +11,7 @@ class XendDmesg:
self.xc = xen.lowlevel.xc.new()
def info(self):
return [ self.xc.readconsolering() ]
return self.xc.readconsolering()
def instance():
+4
View File
@@ -44,6 +44,7 @@ class XendLogging:
mode='a',
maxBytes=self.maxBytes,
backupCount=self.backupCount)
self.logfilename = filename
self.logfile.setFormatter(Formatter(self.logFileFormat, self.dateFormat))
log = self.getLogger()
log.addHandler(self.logfile)
@@ -51,6 +52,9 @@ class XendLogging:
def getLogFile(self):
return self.logfile
def getLogFilename(self):
return self.logfilename
def initLogStderr(self):
self.logstderr = StreamHandler()
self.logstderr.setFormatter(Formatter(self.logStderrFormat, self.dateFormat))
+7 -5
View File
@@ -1,10 +1,12 @@
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
import os
from SrvDir import SrvDir
from xen.xend import sxp
from xen.xend import XendDmesg
from SrvDir import SrvDir
class SrvDmesg(SrvDir):
"""Xen Dmesg output.
"""
@@ -16,13 +18,13 @@ class SrvDmesg(SrvDir):
def render_GET(self, req):
try:
if self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
sxp.show(['dmesg'] + self.info(), out=req)
req.setHeader("Content-Type", "text/plain")
req.write(self.info())
else:
req.write('<html><head></head><body>')
req.write('<pre>')
self.print_path(req)
req.write(self.info()[0])
req.write('<pre>')
req.write(self.info())
req.write('</pre></body></html>')
return ''
except Exception, ex:
+4 -1
View File
@@ -1,6 +1,7 @@
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
import os
from SrvDir import SrvDir
from xen.xend import sxp
from xen.xend import XendNode
@@ -14,6 +15,7 @@ class SrvNode(SrvDir):
SrvDir.__init__(self)
self.xn = XendNode.instance()
self.add('dmesg', 'SrvDmesg')
self.add('log', 'SrvXendLog')
def op_shutdown(self, op, req):
val = self.xn.shutdown()
@@ -58,7 +60,8 @@ class SrvNode(SrvDir):
req.write('<ul>')
for d in self.info():
req.write('<li> %10s: %s' % (d[0], str(d[1])))
req.write('<li><a href="' + url + 'dmesg">Xen dmesg output</a>')
req.write('<li><a href="%sdmesg">Xen dmesg output</a>' % url)
req.write('<li><a href="%slog>Xend log</a>' % url)
req.write('</ul>')
req.write('</body></html>')
return ''
@@ -0,0 +1,24 @@
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
from twisted.web import static
from xen.xend import XendRoot
from SrvDir import SrvDir
class SrvXendLog(SrvDir):
"""Xend log.
"""
def __init__(self):
SrvDir.__init__(self)
logging = XendRoot.instance().get_logging()
self.logfile = static.File(logging.getLogFilename(), defaultType="text/plain")
self.logfile.type = "text/plain"
self.logfile.encoding = None
def render_GET(self, req):
try:
return self.logfile.render(req)
except Exception, ex:
self._perform_err(ex, req)
+97 -21
View File
@@ -13,6 +13,39 @@ from xen.xend.XendClient import XendError, server
from xen.xend.XendClient import main as xend_client_main
from xen.xm import create, destroy, shutdown
class Group:
name = ""
info = ""
def __init__(self, xm):
self.xm = xm
self.progs = {}
def addprog(self, prog):
self.progs[prog.name] = prog
def getprog(self, name):
return self.progs.get(name)
def proglist(self):
kl = self.progs.keys()
kl.sort()
return [ self.getprog(k) for k in kl ]
def help(self, args):
if self.info:
print
print self.info
print
else:
print
def shortHelp(self, args):
self.help(args)
for p in self.proglist():
p.shortHelp(args)
class Prog:
"""Base class for sub-programs.
"""
@@ -61,6 +94,7 @@ class Xm:
self.name = 'xm'
self.unknown = ProgUnknown(self)
self.progs = {}
self.groups = {}
def err(self, msg):
print >>sys.stderr, "Error:", msg
@@ -101,6 +135,7 @@ class Xm:
"""
p = pklass(self)
self.progs[p.name] = p
self.getgroup(p.group).addprog(p)
return p
def getprog(self, name, val=None):
@@ -123,26 +158,57 @@ class Xm:
return self.progs.get(match, val)
def proglist(self):
"""Get a list of sub-programs, ordered by group.
"""
groups = {}
for p in self.progs.values():
l = groups.get(p.group, [])
l.append(p)
groups[p.group] = l
kl = groups.keys()
def group(self, klass):
g = klass(self)
self.groups[g.name] = g
return g
def getgroup(self, name):
return self.groups[name]
def grouplist(self):
kl = self.groups.keys()
kl.sort()
pl = []
for k in kl:
l = groups[k]
l.sort()
pl += l
return pl
return [ self.getgroup(k) for k in kl ]
# Create the application object, then add the sub-program classes.
xm = Xm()
class GroupAll(Group):
name = "all"
info = ""
xm.group(GroupAll)
class GroupDomain(Group):
name = "domain"
info = "Commands on domains:"
xm.group(GroupDomain)
class GroupScheduler(Group):
name = "scheduler"
info = "Comands controlling scheduling:"
xm.group(GroupScheduler)
class GroupHost(Group):
name = "host"
info = "Commands related to the xen host (node):"
xm.group(GroupHost)
class GroupConsole(Group):
name = "console"
info = "Commands related to consoles:"
xm.group(GroupConsole)
class ProgHelp(Prog):
name = "help"
@@ -157,8 +223,8 @@ class ProgHelp(Prog):
else:
print '%s: Unknown command: %s' % (self.name, name)
else:
for p in self.xm.proglist():
p.shortHelp(args)
for g in self.xm.grouplist():
g.shortHelp(args)
print "\nTry '%s help CMD' for help on CMD" % self.xm.name
main = help
@@ -220,7 +286,7 @@ xm.prog(ProgRestore)
class ProgList(Prog):
group = 'domain'
name = "list"
info = """List info about domains."""
info = """List information about domains."""
short_options = 'l'
long_options = ['long']
@@ -512,7 +578,7 @@ class ProgConsole(Prog):
info = """Open a console to a domain."""
def help(self, args):
print "console DOM"
print args[0], "DOM"
print "\nOpen a console to domain DOM."
def main(self, args):
@@ -533,7 +599,7 @@ class ProgCall(Prog):
info = "Call xend api functions."
def help (self, args):
print "call fn argss..."
print args[0], "function args..."
print """
Call a xend HTTP API function. The leading 'xend_' on the function
can be omitted. See xen.xend.XendClient for the API functions.
@@ -550,9 +616,19 @@ class ProgDmesg(Prog):
info = """Print Xen boot output."""
def main(self, args):
print server.xend_node_dmesg()[1]
print server.xend_node_dmesg()
xm.prog(ProgDmesg)
class ProgLog(Prog):
group = 'host'
name = "log"
info = """Print the xend log."""
def main(self, args):
print server.xend_node_log()
xm.prog(ProgLog)
def main(args):
xm.main(args)
+5 -3
View File
@@ -9,7 +9,8 @@ import time
from xen.xend.XendClient import server
from xen.xm.opts import *
DOM0 = 'Domain-0'
DOM0_NAME = 'Domain-0'
DOM0_ID = '0'
gopts = Opts(use="""[options] [DOM]
@@ -38,8 +39,9 @@ gopts.opt('reboot', short='R',
def shutdown(opts, doms, mode, wait):
if doms == None: doms = server.xend_domains()
if DOM0 in doms:
doms.remove(DOM0)
for x in [DOM0_NAME, DOM0_ID]:
if x in doms:
doms.remove(x)
for d in doms:
server.xend_domain_shutdown(d, mode)
if wait:
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.