(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:
parent
b3454da6df
commit
f717fcc0dd
4 changed files with 160 additions and 77 deletions
|
@ -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:
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue