From 2ef4e2e53e9c5d946de24f4d12afc4ea9cd15ab8 Mon Sep 17 00:00:00 2001 From: "ahrenholz@gmail.com" Date: Wed, 5 Mar 2014 16:28:32 +0000 Subject: [PATCH] (commit by Kelly Bunn) session.py: Created method (sendnodeemuid) to send node status response message, so all nodes can call it. Added per session updown script option. service.py: Added test for _starttime before calling float() in bootnodeservices(). Changed servicesfromopaque code to collect unknown services and return with valid services. Changed handleevent to send a message with posible failed and unknown services. coreobj.py: Added code to put nodes actual configured services in tonodemsg. core-daemon: Added call to self.session.sendnodeemuid if in running state in handlenodemsg (Boeing r1824,1825) --- trunk/daemon/core/coreobj.py | 6 ++ trunk/daemon/core/service.py | 163 ++++++++++++++++++++++++---------- trunk/daemon/core/session.py | 60 +++++++------ trunk/daemon/sbin/core-daemon | 8 +- 4 files changed, 160 insertions(+), 77 deletions(-) diff --git a/trunk/daemon/core/coreobj.py b/trunk/daemon/core/coreobj.py index ec7587db..0a51d3da 100644 --- a/trunk/daemon/core/coreobj.py +++ b/trunk/daemon/core/coreobj.py @@ -131,6 +131,12 @@ class PyCoreObj(object): if hasattr(self, "server") and self.server is not None: tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_EMUSRV, self.server) + if hasattr(self, "services") and len(self.services) != 0: + nodeservices = [] + for s in self.services: + nodeservices.append(s._name) + tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_SERVICES, + "|".join(nodeservices)) if x is not None: diff --git a/trunk/daemon/core/service.py b/trunk/daemon/core/service.py index d7113279..a1cd59f3 100644 --- a/trunk/daemon/core/service.py +++ b/trunk/daemon/core/service.py @@ -214,14 +214,15 @@ class CoreServices(ConfigurableManager): services = sorted(node.services, key=lambda service: service._startindex) for s in services: - try: - t = float(s._starttime) - if t > 0.0: - fn = self.bootnodeservice - self.session.evq.add_event(t, fn, node, s, services) - continue - except ValueError: - pass + if len(s._starttime) > 0: + try: + t = float(s._starttime) + if t > 0.0: + fn = self.bootnodeservice + self.session.evq.add_event(t, fn, node, s, services) + continue + except ValueError: + pass self.bootnodeservice(node, s, services) def bootnodeservice(self, node, s, services): @@ -283,8 +284,8 @@ class CoreServices(ConfigurableManager): try: # NOTE: this wait=False can be problematic! node.cmd(shlex.split(cmd), wait = False) - except: - node.warn("error starting command %s" % cmd) + except Exception, e: + node.warn("error starting command %s: %s" % (cmd, e)) def copyservicefile(self, node, filename, cfg): ''' Given a configured service filename and config, determine if the @@ -318,18 +319,24 @@ class CoreServices(ConfigurableManager): validate_cmds = s._validate else: validate_cmds = s.getvalidate(node, services) - for cmd in validate_cmds: - if node.verbose: - node.info("validating service %s using: %s" % (s._name, cmd)) - try: - (status, result) = node.cmdresult(shlex.split(cmd)) - if status != 0: - raise ValueError, "non-zero exit status" - except: - node.warn("validation command '%s' failed" % cmd) - node.exception(coreapi.CORE_EXCP_LEVEL_ERROR, - "service:%s" % s._name, - "validate command failed: %s" % cmd) + if len(validate_cmds) == 0: + # doesn't have a validate command + status = 0 + else: + for cmd in validate_cmds: + if node.verbose: + node.info("validating service %s using: %s" % (s._name, cmd)) + try: + (status, result) = node.cmdresult(shlex.split(cmd)) + if status != 0: + raise ValueError, "non-zero exit status" + except: + node.warn("validation command '%s' failed" % cmd) + node.exception(coreapi.CORE_EXCP_LEVEL_ERROR, + "service:%s" % s._name, + "validate command failed: %s" % cmd) + status = -1 + return status def stopnodeservices(self, node): ''' Stop all services on a node. @@ -342,12 +349,19 @@ class CoreServices(ConfigurableManager): def stopnodeservice(self, node, s): ''' Stop a service on a node. ''' - for cmd in s._shutdown: - try: - # NOTE: this wait=False can be problematic! - node.cmd(shlex.split(cmd), wait = False) - except: - node.warn("error running stop command %s" % cmd) + status = "" + if len(s._shutdown) == 0: + # doesn't have a shutdown command + status += "0" + else: + for cmd in s._shutdown: + try: + tmp = node.cmd(shlex.split(cmd), wait = True) + status += "%s" % (tmp) + except: + node.warn("error running stop command %s" % cmd) + status += "-1" + return status def configure_request(self, msg): @@ -387,7 +401,10 @@ class CoreServices(ConfigurableManager): "unknown node %s" % (svc._name, nodenum)) return None servicesstring = opaque.split(':') - services = self.servicesfromopaque(opaque, n.objid) + services,unknown = self.servicesfromopaque(opaque, n.objid) + for u in unknown: + self.session.warn("Request for unknown service '%s'" % u) + if len(services) < 1: return None if len(servicesstring) == 3: @@ -466,7 +483,10 @@ class CoreServices(ConfigurableManager): # store service customized config in self.customservices[] if nodenum is None: return None - services = self.servicesfromopaque(opaque, nodenum) + services,unknown = self.servicesfromopaque(opaque, nodenum) + for u in unknown: + self.session.warn("Request for unknown service '%s'" % u) + if len(services) < 1: return None svc = services[0] @@ -477,6 +497,7 @@ class CoreServices(ConfigurableManager): ''' Build a list of services from an opaque data string. ''' services = [] + unknown = [] servicesstring = opaque.split(':') if servicesstring[0] != "service": return [] @@ -485,10 +506,10 @@ class CoreServices(ConfigurableManager): s = self.getservicebyname(name) s = self.getcustomservice(objid, s) if s is None: - self.session.warn("Request for unknown service '%s'" % name) - return [] - services.append(s) - return services + unknown.append(name) + else: + services.append(s) + return services,unknown def buildgroups(self, servicelist): ''' Build a string of groups for use in a configuration message given @@ -608,36 +629,80 @@ class CoreServices(ConfigurableManager): "'%s'" % (name, nodenum)) return - services = self.servicesfromopaque(name, nodenum) + fail = "" + services,unknown = self.servicesfromopaque(name, nodenum) for s in services: if eventtype == coreapi.CORE_EVENT_STOP or \ eventtype == coreapi.CORE_EVENT_RESTART: - self.stopnodeservice(node, s) + status = self.stopnodeservice(node, s) + if status != "0": + fail += "Stop %s," % (s._name) if eventtype == coreapi.CORE_EVENT_START or \ eventtype == coreapi.CORE_EVENT_RESTART: if s._custom: cmds = s._startup else: cmds = s.getstartup(node, services) - for cmd in cmds: - try: - node.cmd(shlex.split(cmd), wait = False) - except: - node.warn("error starting command %s" % cmd) + if len(cmds) > 0: + for cmd in cmds: + try: + #node.cmd(shlex.split(cmd), wait = False) + status = node.cmd(shlex.split(cmd), wait = True) + if status != 0: + fail += "Start %s(%s)," % (s._name, cmd) + except: + node.warn("error starting command %s" % cmd) + fail += "Start %s," % (s._name) if eventtype == coreapi.CORE_EVENT_PAUSE: - self.validatenodeservice(node, s, services) + status = self.validatenodeservice(node, s, services) + if status != 0: + fail += "%s," % (s._name) if eventtype == coreapi.CORE_EVENT_RECONFIGURE: if s._custom: cfgfiles = s._configs else: cfgfiles = s.getconfigfilenames(node.objid, services) - for filename in cfgfiles: - if filename[:7] == "file:///": - raise NotImplementedError # TODO - cfg = self.getservicefiledata(s, filename) - if cfg is None: - cfg = s.generateconfig(node, filename, services) - node.nodefile(filename, cfg) + if len(cfgfiles) > 0: + for filename in cfgfiles: + if filename[:7] == "file:///": + raise NotImplementedError # TODO + cfg = self.getservicefiledata(s, filename) + if cfg is None: + cfg = s.generateconfig(node, filename, services) + try: + node.nodefile(filename, cfg) + except: + self.warn("error in configure file: %s" % filename) + fail += "%s," % (s._name) + + fdata = "" + if len(fail) > 0: + fdata += "Fail:" + fail + udata = "" + num = len(unknown) + if num > 0: + for u in unknown: + udata += u + if num > 1: + udata += ", " + num -= 1 + self.session.warn("Event requested for unknown service(s): %s" % udata); + udata = "Unknown:" + udata + + tlvdata = "" + tlvdata += coreapi.CoreEventTlv.pack(coreapi.CORE_TLV_EVENT_NODE, + nodenum) + tlvdata += coreapi.CoreEventTlv.pack(coreapi.CORE_TLV_EVENT_TYPE, + eventtype) + tlvdata += coreapi.CoreEventTlv.pack(coreapi.CORE_TLV_EVENT_NAME, + name) + tlvdata += coreapi.CoreEventTlv.pack(coreapi.CORE_TLV_EVENT_DATA, + fdata + ";" + udata) + msg = coreapi.CoreEventMessage.pack(0, tlvdata) + try: + self.session.broadcastraw(None, msg) + except Exception, e: + self.warn("Error sending Event Message: %s" % e) class CoreService(object): diff --git a/trunk/daemon/core/session.py b/trunk/daemon/core/session.py index 4d0ba026..f08f98a0 100644 --- a/trunk/daemon/core/session.py +++ b/trunk/daemon/core/session.py @@ -685,41 +685,42 @@ class Session(object): ''' return (self.sessionid >> 8) ^ (self.sessionid & ((1 << 8) - 1)) + def sendnodeemuid(self, handler, nodenum): + ''' Send back node messages to the GUI for node messages that had + the status request flag. + ''' + if handler is None: + return + if nodenum in handler.nodestatusreq: + tlvdata = "" + tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_NUMBER, + nodenum) + tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_EMUID, + nodenum) + reply = coreapi.CoreNodeMessage.pack(coreapi.CORE_API_ADD_FLAG \ + | coreapi.CORE_API_LOC_FLAG, + tlvdata) + try: + handler.request.sendall(reply) + except Exception, e: + self.warn("sendall() for node: %d error: %s" % (nodenum, e)) + del handler.nodestatusreq[nodenum] + def bootnodes(self, handler): ''' Invoke the boot() procedure for all nodes and send back node messages to the GUI for node messages that had the status request flag. ''' - #self.addremovectrlif(node=None, remove=False) with self._objslock: for n in self.objs(): - if not isinstance(n, nodes.PyCoreNode): - continue - if isinstance(n, nodes.RJ45Node): - continue - # add a control interface if configured - self.addremovectrlif(node=n, remove=False) - n.boot() - nodenum = n.objid - if handler is None: - continue - if nodenum in handler.nodestatusreq: - tlvdata = "" - tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_NUMBER, - nodenum) - tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_EMUID, - n.objid) - reply = coreapi.CoreNodeMessage.pack(coreapi.CORE_API_ADD_FLAG \ - | coreapi.CORE_API_LOC_FLAG, - tlvdata) - try: - handler.request.sendall(reply) - except Exception, e: - self.warn("sendall() error: %s" % e) - del handler.nodestatusreq[nodenum] + if isinstance(n, nodes.PyCoreNode) and \ + not isinstance(n, nodes.RJ45Node): + # add a control interface if configured + self.addremovectrlif(node=n, remove=False) + n.boot() + self.sendnodeemuid(handler, n.objid) self.updatectrlifhosts() - def validatenodes(self): with self._objslock: for n in self.objs(): @@ -766,6 +767,11 @@ class Session(object): updown_script = self.cfg['controlnet_updown_script'] except KeyError: pass + # Check if session option set, overwrite if so + if hasattr(self.options, 'controlnet_updown_script'): + new_uds = self.options.controlnet_updown_script + if new_uds: + updown_script = new_uds prefixes = prefix.split() if len(prefixes) > 1: @@ -985,6 +991,8 @@ class SessionConfig(ConfigurableManager, Configurable): _confmatrix = [ ("controlnet", coreapi.CONF_DATA_TYPE_STRING, '', '', 'Control network'), + ("controlnet_updown_script", coreapi.CONF_DATA_TYPE_STRING, '', '', + 'Control network script'), ("enablerj45", coreapi.CONF_DATA_TYPE_BOOL, '1', 'On,Off', 'Enable RJ45s'), ("preservedir", coreapi.CONF_DATA_TYPE_BOOL, '0', 'On,Off', diff --git a/trunk/daemon/sbin/core-daemon b/trunk/daemon/sbin/core-daemon index d67c1ad3..7b716725 100755 --- a/trunk/daemon/sbin/core-daemon +++ b/trunk/daemon/sbin/core-daemon @@ -432,7 +432,8 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): services_str = msg.gettlv(coreapi.CORE_TLV_NODE_SERVICES) self.session.services.addservicestonode(n, model, services_str, self.verbose) - # boot nodes if they are added after runtime (like session.bootnodes()) + # boot nodes if they are added after runtime (like + # session.bootnodes()) if self.session.getstate() == coreapi.CORE_EVENT_RUNTIME_STATE: if isinstance(n, pycore.nodes.PyCoreNode) and \ not isinstance(n, pycore.nodes.RJ45Node): @@ -441,8 +442,11 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): n.boot() # self.session.updatectrlifhosts() # n.validate() + if msg.flags & coreapi.CORE_API_STR_FLAG: + self.nodestatusreq[nodenum] = True + self.session.sendnodeemuid(self, nodenum) - if msg.flags & coreapi.CORE_API_STR_FLAG: + elif msg.flags & coreapi.CORE_API_STR_FLAG: self.nodestatusreq[nodenum] = True elif msg.flags & coreapi.CORE_API_DEL_FLAG: