aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAlexandru DAMIAN <alexandru.damian@intel.com>2013-06-17 12:11:51 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2013-06-17 16:08:30 +0100
commit4de9ee21f1fa4d04937cc7430fb1fc8b7a8f61e2 (patch)
tree47f2564af429444e3338d7f42dd1e4c6bf5d8eb7 /lib
parentd48e8bcb24e8fa5d4fd60fd2c9927a95976d8d8b (diff)
downloadbitbake-4de9ee21f1fa4d04937cc7430fb1fc8b7a8f61e2.tar.gz
knotty, xmlrpc: add observer-only mode
I add an observer only mode for the knotty UI and the XMLRPC server that will allow the UI to register a callback with a server in order to receive events. The observer-UI is able to send read-only commands to the server, and also is able to register as an event handler. Read-only commands are the commands that do not change the state of the server and have been marked as such in the command module. The observer can switch to a full client if it calls addClient at any time, and the server has no other client running. Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/bb/command.py7
-rw-r--r--lib/bb/server/xmlrpc.py26
-rw-r--r--lib/bb/ui/knotty.py29
-rw-r--r--lib/bb/ui/uievent.py1
4 files changed, 42 insertions, 21 deletions
diff --git a/lib/bb/command.py b/lib/bb/command.py
index ab6950111..5f696c2ae 100644
--- a/lib/bb/command.py
+++ b/lib/bb/command.py
@@ -59,11 +59,14 @@ class Command:
# FIXME Add lock for this
self.currentAsyncCommand = None
- def runCommand(self, commandline):
+ def runCommand(self, commandline, ro_only = False):
command = commandline.pop(0)
if hasattr(CommandsSync, command):
# Can run synchronous commands straight away
command_method = getattr(self.cmds_sync, command)
+ if ro_only:
+ if not hasattr(command_method, 'readonly') or False == getattr(command_method, 'readonly'):
+ return None, "Not able to execute not readonly commands in readonly mode"
try:
result = command_method(self, commandline)
except CommandError as exc:
@@ -153,6 +156,7 @@ class CommandsSync:
expand = params[1]
return command.cooker.data.getVar(varname, expand)
+ getVariable.readonly = True
def setVariable(self, command, params):
"""
@@ -200,6 +204,7 @@ class CommandsSync:
Get the CPU count on the bitbake server
"""
return bb.utils.cpu_count()
+ getCpuCount.readonly = True
def matchFile(self, command, params):
fMatch = params[0]
diff --git a/lib/bb/server/xmlrpc.py b/lib/bb/server/xmlrpc.py
index 5045e55ae..026415efd 100644
--- a/lib/bb/server/xmlrpc.py
+++ b/lib/bb/server/xmlrpc.py
@@ -93,7 +93,7 @@ class BitBakeServerCommands():
"""
Run a cooker command on the server
"""
- return self.cooker.command.runCommand(command)
+ return self.cooker.command.runCommand(command, self.server.readonly)
def terminateServer(self):
"""
@@ -124,7 +124,7 @@ class BitBakeServerCommands():
# ("service unavailable") is returned to the client.
class BitBakeXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
def __init__(self, request, client_address, server):
- self.connection_token = server.connection_token
+ self.server = server
SimpleXMLRPCRequestHandler.__init__(self, request, client_address, server)
def do_POST(self):
@@ -132,9 +132,13 @@ class BitBakeXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
remote_token = self.headers["Bitbake-token"]
except:
remote_token = None
- if remote_token != self.connection_token:
+ if remote_token != self.server.connection_token and remote_token != "observer":
self.report_503()
else:
+ if remote_token == "observer":
+ self.server.readonly = True
+ else:
+ self.server.readonly = False
SimpleXMLRPCRequestHandler.do_POST(self)
def report_503(self):
@@ -283,13 +287,17 @@ class XMLRPCServer(SimpleXMLRPCServer, BaseImplServer):
self.connection_token = token
class BitBakeXMLRPCServerConnection(BitBakeBaseServerConnection):
- def __init__(self, serverImpl, clientinfo=("localhost", 0)):
+ def __init__(self, serverImpl, clientinfo=("localhost", 0), observer_only = False):
self.connection, self.transport = _create_server(serverImpl.host, serverImpl.port)
self.clientinfo = clientinfo
self.serverImpl = serverImpl
+ self.observer_only = observer_only
def connect(self):
- token = self.connection.addClient()
+ if not self.observer_only:
+ token = self.connection.addClient()
+ else:
+ token = "observer"
if token is None:
return None
self.transport.set_connection_token(token)
@@ -299,7 +307,8 @@ class BitBakeXMLRPCServerConnection(BitBakeBaseServerConnection):
return self
def removeClient(self):
- self.connection.removeClient()
+ if not self.observer_only:
+ self.connection.removeClient()
def terminate(self):
# Don't wait for server indefinitely
@@ -331,7 +340,8 @@ class BitBakeServer(BitBakeBaseServer):
class BitBakeXMLRPCClient(BitBakeBaseServer):
- def __init__(self):
+ def __init__(self, observer_only = False):
+ self.observer_only = observer_only
pass
def saveConnectionDetails(self, remote):
@@ -354,7 +364,7 @@ class BitBakeXMLRPCClient(BitBakeBaseServer):
except:
return None
self.serverImpl = XMLRPCProxyServer(host, port)
- self.connection = BitBakeXMLRPCServerConnection(self.serverImpl, (ip, 0))
+ self.connection = BitBakeXMLRPCServerConnection(self.serverImpl, (ip, 0), self.observer_only)
return self.connection.connect()
def endSession(self):
diff --git a/lib/bb/ui/knotty.py b/lib/bb/ui/knotty.py
index 389c3cc64..c6a1d3f98 100644
--- a/lib/bb/ui/knotty.py
+++ b/lib/bb/ui/knotty.py
@@ -216,21 +216,25 @@ class TerminalFilter(object):
fd = sys.stdin.fileno()
self.termios.tcsetattr(fd, self.termios.TCSADRAIN, self.stdinbackup)
-def main(server, eventHandler, params, tf = TerminalFilter):
-
+def _log_settings_from_server(server):
# Get values of variables which control our output
includelogs, error = server.runCommand(["getVariable", "BBINCLUDELOGS"])
if error:
logger.error("Unable to get the value of BBINCLUDELOGS variable: %s" % error)
- return 1
+ raise BaseException(error)
loglines, error = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"])
if error:
logger.error("Unable to get the value of BBINCLUDELOGS_LINES variable: %s" % error)
- return 1
+ raise BaseException(error)
consolelogfile, error = server.runCommand(["getVariable", "BB_CONSOLELOG"])
if error:
logger.error("Unable to get the value of BB_CONSOLELOG variable: %s" % error)
- return 1
+ raise BaseException(error)
+ return includelogs, loglines, consolelogfile
+
+def main(server, eventHandler, params, tf = TerminalFilter):
+
+ includelogs, loglines, consolelogfile = _log_settings_from_server(server)
if sys.stdin.isatty() and sys.stdout.isatty():
log_exec_tty = True
@@ -254,7 +258,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
consolelog.setFormatter(conlogformat)
logger.addHandler(consolelog)
- try:
+ if not params.observe_only:
params.updateFromServer(server)
cmdline = params.parseActions()
if not cmdline:
@@ -271,9 +275,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
elif ret != True:
logger.error("Command '%s' failed: returned %s" % (cmdline, ret))
return 1
- except xmlrpclib.Fault as x:
- logger.error("XMLRPC Fault getting commandline:\n %s" % x)
- return 1
+
parseprogress = None
cacheprogress = None
@@ -320,7 +322,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
elif event.levelno == format.WARNING:
warnings = warnings + 1
# For "normal" logging conditions, don't show note logs from tasks
- # but do show them if the user has changed the default log level to
+ # but do show them if the user has changed the default log level to
# include verbose/debug messages
if event.taskpid != 0 and event.levelno <= format.NOTE:
continue
@@ -469,12 +471,15 @@ def main(server, eventHandler, params, tf = TerminalFilter):
pass
except KeyboardInterrupt:
termfilter.clearFooter()
- if main.shutdown == 1:
+ if params.observe_only:
+ print("\nKeyboard Interrupt, exiting observer...")
+ main.shutdown = 2
+ if not params.observe_only and main.shutdown == 1:
print("\nSecond Keyboard Interrupt, stopping...\n")
_, error = server.runCommand(["stateStop"])
if error:
logger.error("Unable to cleanly stop: %s" % error)
- if main.shutdown == 0:
+ if not params.observe_only and main.shutdown == 0:
print("\nKeyboard Interrupt, closing down...\n")
interrupted = True
_, error = server.runCommand(["stateShutdown"])
diff --git a/lib/bb/ui/uievent.py b/lib/bb/ui/uievent.py
index 0b9a836d0..038029fcf 100644
--- a/lib/bb/ui/uievent.py
+++ b/lib/bb/ui/uievent.py
@@ -84,6 +84,7 @@ class BBUIEventQueue:
def startCallbackHandler(self):
+ self.server.timeout = 1
while not self.server.quit:
self.server.handle_request()
self.server.server_close()