(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)
This commit is contained in:
ahrenholz 2014-03-05 16:28:32 +00:00
parent b3454da6df
commit f717fcc0dd
4 changed files with 160 additions and 77 deletions

View file

@ -131,6 +131,12 @@ class PyCoreObj(object):
if hasattr(self, "server") and self.server is not None: if hasattr(self, "server") and self.server is not None:
tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_EMUSRV, tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_EMUSRV,
self.server) 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: if x is not None:

View file

@ -214,14 +214,15 @@ class CoreServices(ConfigurableManager):
services = sorted(node.services, services = sorted(node.services,
key=lambda service: service._startindex) key=lambda service: service._startindex)
for s in services: for s in services:
try: if len(s._starttime) > 0:
t = float(s._starttime) try:
if t > 0.0: t = float(s._starttime)
fn = self.bootnodeservice if t > 0.0:
self.session.evq.add_event(t, fn, node, s, services) fn = self.bootnodeservice
continue self.session.evq.add_event(t, fn, node, s, services)
except ValueError: continue
pass except ValueError:
pass
self.bootnodeservice(node, s, services) self.bootnodeservice(node, s, services)
def bootnodeservice(self, node, s, services): def bootnodeservice(self, node, s, services):
@ -283,8 +284,8 @@ class CoreServices(ConfigurableManager):
try: try:
# NOTE: this wait=False can be problematic! # NOTE: this wait=False can be problematic!
node.cmd(shlex.split(cmd), wait = False) node.cmd(shlex.split(cmd), wait = False)
except: except Exception, e:
node.warn("error starting command %s" % cmd) node.warn("error starting command %s: %s" % (cmd, e))
def copyservicefile(self, node, filename, cfg): def copyservicefile(self, node, filename, cfg):
''' Given a configured service filename and config, determine if the ''' Given a configured service filename and config, determine if the
@ -318,18 +319,24 @@ class CoreServices(ConfigurableManager):
validate_cmds = s._validate validate_cmds = s._validate
else: else:
validate_cmds = s.getvalidate(node, services) validate_cmds = s.getvalidate(node, services)
for cmd in validate_cmds: if len(validate_cmds) == 0:
if node.verbose: # doesn't have a validate command
node.info("validating service %s using: %s" % (s._name, cmd)) status = 0
try: else:
(status, result) = node.cmdresult(shlex.split(cmd)) for cmd in validate_cmds:
if status != 0: if node.verbose:
raise ValueError, "non-zero exit status" node.info("validating service %s using: %s" % (s._name, cmd))
except: try:
node.warn("validation command '%s' failed" % cmd) (status, result) = node.cmdresult(shlex.split(cmd))
node.exception(coreapi.CORE_EXCP_LEVEL_ERROR, if status != 0:
"service:%s" % s._name, raise ValueError, "non-zero exit status"
"validate command failed: %s" % cmd) 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): def stopnodeservices(self, node):
''' Stop all services on a node. ''' Stop all services on a node.
@ -342,12 +349,19 @@ class CoreServices(ConfigurableManager):
def stopnodeservice(self, node, s): def stopnodeservice(self, node, s):
''' Stop a service on a node. ''' Stop a service on a node.
''' '''
for cmd in s._shutdown: status = ""
try: if len(s._shutdown) == 0:
# NOTE: this wait=False can be problematic! # doesn't have a shutdown command
node.cmd(shlex.split(cmd), wait = False) status += "0"
except: else:
node.warn("error running stop command %s" % cmd) 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): def configure_request(self, msg):
@ -387,7 +401,10 @@ class CoreServices(ConfigurableManager):
"unknown node %s" % (svc._name, nodenum)) "unknown node %s" % (svc._name, nodenum))
return None return None
servicesstring = opaque.split(':') 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: if len(services) < 1:
return None return None
if len(servicesstring) == 3: if len(servicesstring) == 3:
@ -466,7 +483,10 @@ class CoreServices(ConfigurableManager):
# store service customized config in self.customservices[] # store service customized config in self.customservices[]
if nodenum is None: if nodenum is None:
return 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: if len(services) < 1:
return None return None
svc = services[0] svc = services[0]
@ -477,6 +497,7 @@ class CoreServices(ConfigurableManager):
''' Build a list of services from an opaque data string. ''' Build a list of services from an opaque data string.
''' '''
services = [] services = []
unknown = []
servicesstring = opaque.split(':') servicesstring = opaque.split(':')
if servicesstring[0] != "service": if servicesstring[0] != "service":
return [] return []
@ -485,10 +506,10 @@ class CoreServices(ConfigurableManager):
s = self.getservicebyname(name) s = self.getservicebyname(name)
s = self.getcustomservice(objid, s) s = self.getcustomservice(objid, s)
if s is None: if s is None:
self.session.warn("Request for unknown service '%s'" % name) unknown.append(name)
return [] else:
services.append(s) services.append(s)
return services return services,unknown
def buildgroups(self, servicelist): def buildgroups(self, servicelist):
''' Build a string of groups for use in a configuration message given ''' Build a string of groups for use in a configuration message given
@ -608,36 +629,80 @@ class CoreServices(ConfigurableManager):
"'%s'" % (name, nodenum)) "'%s'" % (name, nodenum))
return return
services = self.servicesfromopaque(name, nodenum) fail = ""
services,unknown = self.servicesfromopaque(name, nodenum)
for s in services: for s in services:
if eventtype == coreapi.CORE_EVENT_STOP or \ if eventtype == coreapi.CORE_EVENT_STOP or \
eventtype == coreapi.CORE_EVENT_RESTART: 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 \ if eventtype == coreapi.CORE_EVENT_START or \
eventtype == coreapi.CORE_EVENT_RESTART: eventtype == coreapi.CORE_EVENT_RESTART:
if s._custom: if s._custom:
cmds = s._startup cmds = s._startup
else: else:
cmds = s.getstartup(node, services) cmds = s.getstartup(node, services)
for cmd in cmds: if len(cmds) > 0:
try: for cmd in cmds:
node.cmd(shlex.split(cmd), wait = False) try:
except: #node.cmd(shlex.split(cmd), wait = False)
node.warn("error starting command %s" % cmd) 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: 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 eventtype == coreapi.CORE_EVENT_RECONFIGURE:
if s._custom: if s._custom:
cfgfiles = s._configs cfgfiles = s._configs
else: else:
cfgfiles = s.getconfigfilenames(node.objid, services) cfgfiles = s.getconfigfilenames(node.objid, services)
for filename in cfgfiles: if len(cfgfiles) > 0:
if filename[:7] == "file:///": for filename in cfgfiles:
raise NotImplementedError # TODO if filename[:7] == "file:///":
cfg = self.getservicefiledata(s, filename) raise NotImplementedError # TODO
if cfg is None: cfg = self.getservicefiledata(s, filename)
cfg = s.generateconfig(node, filename, services) if cfg is None:
node.nodefile(filename, cfg) 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): class CoreService(object):

View file

@ -685,41 +685,42 @@ class Session(object):
''' '''
return (self.sessionid >> 8) ^ (self.sessionid & ((1 << 8) - 1)) 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): def bootnodes(self, handler):
''' Invoke the boot() procedure for all nodes and send back node ''' Invoke the boot() procedure for all nodes and send back node
messages to the GUI for node messages that had the status messages to the GUI for node messages that had the status
request flag. request flag.
''' '''
#self.addremovectrlif(node=None, remove=False)
with self._objslock: with self._objslock:
for n in self.objs(): for n in self.objs():
if not isinstance(n, nodes.PyCoreNode): if isinstance(n, nodes.PyCoreNode) and \
continue not isinstance(n, nodes.RJ45Node):
if isinstance(n, nodes.RJ45Node): # add a control interface if configured
continue self.addremovectrlif(node=n, remove=False)
# add a control interface if configured n.boot()
self.addremovectrlif(node=n, remove=False) self.sendnodeemuid(handler, n.objid)
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]
self.updatectrlifhosts() self.updatectrlifhosts()
def validatenodes(self): def validatenodes(self):
with self._objslock: with self._objslock:
for n in self.objs(): for n in self.objs():
@ -766,6 +767,11 @@ class Session(object):
updown_script = self.cfg['controlnet_updown_script'] updown_script = self.cfg['controlnet_updown_script']
except KeyError: except KeyError:
pass 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() prefixes = prefix.split()
if len(prefixes) > 1: if len(prefixes) > 1:
@ -985,6 +991,8 @@ class SessionConfig(ConfigurableManager, Configurable):
_confmatrix = [ _confmatrix = [
("controlnet", coreapi.CONF_DATA_TYPE_STRING, '', '', ("controlnet", coreapi.CONF_DATA_TYPE_STRING, '', '',
'Control network'), 'Control network'),
("controlnet_updown_script", coreapi.CONF_DATA_TYPE_STRING, '', '',
'Control network script'),
("enablerj45", coreapi.CONF_DATA_TYPE_BOOL, '1', 'On,Off', ("enablerj45", coreapi.CONF_DATA_TYPE_BOOL, '1', 'On,Off',
'Enable RJ45s'), 'Enable RJ45s'),
("preservedir", coreapi.CONF_DATA_TYPE_BOOL, '0', 'On,Off', ("preservedir", coreapi.CONF_DATA_TYPE_BOOL, '0', 'On,Off',

View file

@ -432,7 +432,8 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
services_str = msg.gettlv(coreapi.CORE_TLV_NODE_SERVICES) services_str = msg.gettlv(coreapi.CORE_TLV_NODE_SERVICES)
self.session.services.addservicestonode(n, model, services_str, self.session.services.addservicestonode(n, model, services_str,
self.verbose) 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 self.session.getstate() == coreapi.CORE_EVENT_RUNTIME_STATE:
if isinstance(n, pycore.nodes.PyCoreNode) and \ if isinstance(n, pycore.nodes.PyCoreNode) and \
not isinstance(n, pycore.nodes.RJ45Node): not isinstance(n, pycore.nodes.RJ45Node):
@ -441,8 +442,11 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
n.boot() n.boot()
# self.session.updatectrlifhosts() # self.session.updatectrlifhosts()
# n.validate() # 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 self.nodestatusreq[nodenum] = True
elif msg.flags & coreapi.CORE_API_DEL_FLAG: elif msg.flags & coreapi.CORE_API_DEL_FLAG: