(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:
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:

View file

@ -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):

View file

@ -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',

View file

@ -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: