(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,6 +214,7 @@ 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:
if len(s._starttime) > 0:
try: try:
t = float(s._starttime) t = float(s._starttime)
if t > 0.0: if t > 0.0:
@ -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,6 +319,10 @@ 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)
if len(validate_cmds) == 0:
# doesn't have a validate command
status = 0
else:
for cmd in validate_cmds: for cmd in validate_cmds:
if node.verbose: if node.verbose:
node.info("validating service %s using: %s" % (s._name, cmd)) node.info("validating service %s using: %s" % (s._name, cmd))
@ -330,6 +335,8 @@ class CoreServices(ConfigurableManager):
node.exception(coreapi.CORE_EXCP_LEVEL_ERROR, node.exception(coreapi.CORE_EXCP_LEVEL_ERROR,
"service:%s" % s._name, "service:%s" % s._name,
"validate command failed: %s" % cmd) "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.
''' '''
status = ""
if len(s._shutdown) == 0:
# doesn't have a shutdown command
status += "0"
else:
for cmd in s._shutdown: for cmd in s._shutdown:
try: try:
# NOTE: this wait=False can be problematic! tmp = node.cmd(shlex.split(cmd), wait = True)
node.cmd(shlex.split(cmd), wait = False) status += "%s" % (tmp)
except: except:
node.warn("error running stop command %s" % cmd) 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)
if len(cmds) > 0:
for cmd in cmds: for cmd in cmds:
try: try:
node.cmd(shlex.split(cmd), wait = False) #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: except:
node.warn("error starting command %s" % cmd) 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)
if len(cfgfiles) > 0:
for filename in cfgfiles: for filename in cfgfiles:
if filename[:7] == "file:///": if filename[:7] == "file:///":
raise NotImplementedError # TODO raise NotImplementedError # TODO
cfg = self.getservicefiledata(s, filename) cfg = self.getservicefiledata(s, filename)
if cfg is None: if cfg is None:
cfg = s.generateconfig(node, filename, services) cfg = s.generateconfig(node, filename, services)
try:
node.nodefile(filename, cfg) 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,40 +685,41 @@ class Session(object):
''' '''
return (self.sessionid >> 8) ^ (self.sessionid & ((1 << 8) - 1)) return (self.sessionid >> 8) ^ (self.sessionid & ((1 << 8) - 1))
def bootnodes(self, handler): def sendnodeemuid(self, handler, nodenum):
''' Invoke the boot() procedure for all nodes and send back node ''' Send back node messages to the GUI for node messages that had
messages to the GUI for node messages that had the status the status request flag.
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: if handler is None:
continue return
if nodenum in handler.nodestatusreq: if nodenum in handler.nodestatusreq:
tlvdata = "" tlvdata = ""
tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_NUMBER, tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_NUMBER,
nodenum) nodenum)
tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_EMUID, tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_EMUID,
n.objid) nodenum)
reply = coreapi.CoreNodeMessage.pack(coreapi.CORE_API_ADD_FLAG \ reply = coreapi.CoreNodeMessage.pack(coreapi.CORE_API_ADD_FLAG \
| coreapi.CORE_API_LOC_FLAG, | coreapi.CORE_API_LOC_FLAG,
tlvdata) tlvdata)
try: try:
handler.request.sendall(reply) handler.request.sendall(reply)
except Exception, e: except Exception, e:
self.warn("sendall() error: %s" % e) self.warn("sendall() for node: %d error: %s" % (nodenum, e))
del handler.nodestatusreq[nodenum] del handler.nodestatusreq[nodenum]
self.updatectrlifhosts()
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.
'''
with self._objslock:
for n in self.objs():
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): def validatenodes(self):
with self._objslock: with self._objslock:
@ -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,9 +442,12 @@ 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: if msg.flags & coreapi.CORE_API_STR_FLAG:
self.nodestatusreq[nodenum] = True self.nodestatusreq[nodenum] = True
self.session.sendnodeemuid(self, nodenum)
elif msg.flags & coreapi.CORE_API_STR_FLAG:
self.nodestatusreq[nodenum] = True
elif msg.flags & coreapi.CORE_API_DEL_FLAG: elif msg.flags & coreapi.CORE_API_DEL_FLAG:
n = None n = None