[bitbake-devel] [PATCH] knotty, xmlrpc: add observer-only mode

Alex Damian alex.r.damian at gmail.com
Thu Jun 13 15:23:13 UTC 2013


On 06/12/2013 02:11 PM, Richard Purdie wrote:
> On Fri, 2013-06-07 at 16:42 +0100, Alex DAMIAN wrote:
>> From: Alexandru DAMIAN <alexandru.damian at intel.com>
>>
>> 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 will not send any commands to the
>> server apart from registering as an event handler.
>>
>> Signed-off-by: Alexandru DAMIAN <alexandru.damian at intel.com>
>> ---
>>   bin/bitbake             |  8 +++++++-
>>   lib/bb/server/xmlrpc.py | 18 ++++++++++++------
>>   lib/bb/ui/knotty.py     | 29 +++++++++++++++++------------
>>   lib/bb/ui/uievent.py    |  1 +
>>   4 files changed, 37 insertions(+), 19 deletions(-)
>>
>> diff --git a/bin/bitbake b/bin/bitbake
>> index d263cbd..ef0c5d8 100755
>> --- a/bin/bitbake
>> +++ b/bin/bitbake
>> @@ -197,6 +197,9 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
>>           parser.add_option("", "--remote-server", help = "Connect to the specified server",
>>                      action = "store", dest = "remote_server", default = False)
>>   
>> +        parser.add_option("", "--observe-only", help = "Connect to a server as an observing-only client",
>> +                   action = "store_true", dest = "observe_only", default = False)
>> +
>>           options, targets = parser.parse_args(sys.argv)
>>           return options, targets[1:]
>>   
>> @@ -269,6 +272,9 @@ def main():
>>       if configParams.remote_server and configParams.servertype != "xmlrpc":
>>           sys.exit("FATAL: If '--remote-server' is defined, we must set the servertype as 'xmlrpc'.\n")
>>   
>> +    if configParams.observe_only and (not configParams.remote_server or configParams.bind):
>> +        sys.exit("FATAL: '--observe-only' can only be used by UI clients connecting to a server.\n")
>> +
>>       if "BBDEBUG" in os.environ:
>>           level = int(os.environ["BBDEBUG"])
>>           if level > configuration.debug:
>> @@ -295,7 +301,7 @@ def main():
>>           server = start_server(servermodule, configParams, configuration)
>>       else:
>>           # we start a stub server that is actually a XMLRPClient to
>> -        server = servermodule.BitBakeXMLRPCClient()
>> +        server = servermodule.BitBakeXMLRPCClient(configParams.observe_only)
>>           server.saveConnectionDetails(configParams.remote_server)
>>   
>>       logger.removeHandler(handler)
>> diff --git a/lib/bb/server/xmlrpc.py b/lib/bb/server/xmlrpc.py
>> index 0b51ebd..1b3502e 100644
>> --- a/lib/bb/server/xmlrpc.py
>> +++ b/lib/bb/server/xmlrpc.py
>> @@ -214,7 +214,7 @@ class BitBakeXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
>>               remote_token = self.headers["Bitbake-token"]
>>           except:
>>               remote_token = None
>> -        if remote_token != self.connection_token:
>> +        if remote_token != self.connection_token and remote_token != "observer":
>>               self.report_503()
>>           else:
>>               SimpleXMLRPCRequestHandler.do_POST(self)
>> @@ -424,13 +424,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)
>> @@ -440,7 +444,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
>> @@ -472,7 +477,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):
>> @@ -495,7 +501,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 389c3cc..465203f 100644
>> --- a/lib/bb/ui/knotty.py
>> +++ b/lib/bb/ui/knotty.py
>> @@ -216,21 +216,28 @@ 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 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 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 error
>> +    return includelogs, loglines, consolelogfile
>> +
>> +def main(server, eventHandler, params, tf = TerminalFilter):
>> +
>> +    if params.observe_only:
>> +        includelogs, loglines, consolelogfile = None, None, None
>> +    else:
>> +        includelogs, loglines, consolelogfile = _log_settings_from_server(server)
> This doesn't look right. Even in observe mode, I'd expect to see the
> same console output.
>
> This raises the question, even in observe only mode, can't we run sync
> commands, just not async commands or write commands?
>
>>       if sys.stdin.isatty() and sys.stdout.isatty():
>>           log_exec_tty = True
>> @@ -254,7 +261,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 +278,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 +325,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 +474,12 @@ def main(server, eventHandler, params, tf = TerminalFilter):
>>                   pass
>>           except KeyboardInterrupt:
>>               termfilter.clearFooter()
>> -            if main.shutdown == 1:
>> +            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 0b9a836..038029f 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()
> Why? The commit message doesn't mention timeouts.
It's an implementation detail. If not there, than the server will hang 
indefinitely waiting for a command, and not ever processing the 
self.server.quit variable in the while.

>
> Cheers,
>
> Richard
>
> _______________________________________________
> bitbake-devel mailing list
> bitbake-devel at lists.openembedded.org
> http://lists.openembedded.org/mailman/listinfo/bitbake-devel




More information about the bitbake-devel mailing list