allow executing XML files from daemon from Register Message

(like a Python script)
added start flag to xmlutils.opensessionxml(), 
XML file will be parsed into a live running session
(Boeing r1792)
This commit is contained in:
ahrenholz 2013-11-25 19:54:02 +00:00
parent 93f96c7707
commit 1e8abc4c1e
3 changed files with 44 additions and 34 deletions

View file

@ -121,11 +121,12 @@ def xmltypetonodeclass(session, type):
return None return None
class CoreDocumentParser(object): class CoreDocumentParser(object):
def __init__(self, session, filename): def __init__(self, session, filename, start=False):
self.session = session self.session = session
self.verbose = self.session.getcfgitembool('verbose', False) self.verbose = self.session.getcfgitembool('verbose', False)
self.filename = filename self.filename = filename
self.dom = parse(filename) self.dom = parse(filename)
self.start = start
#self.scenario = getoneelement(self.dom, "Scenario") #self.scenario = getoneelement(self.dom, "Scenario")
self.np = getoneelement(self.dom, "NetworkPlan") self.np = getoneelement(self.dom, "NetworkPlan")
@ -197,7 +198,7 @@ class CoreDocumentParser(object):
(name, type)) (name, type))
continue continue
n = self.session.addobj(cls = nodecls, objid = id, name = name, n = self.session.addobj(cls = nodecls, objid = id, name = name,
start = False) start = self.start)
if name in self.coords: if name in self.coords:
x, y, z = self.coords[name] x, y, z = self.coords[name]
n.setposition(x, y, z) n.setposition(x, y, z)
@ -227,7 +228,7 @@ class CoreDocumentParser(object):
else: else:
nodecls = pycore.nodes.CoreNode nodecls = pycore.nodes.CoreNode
n = self.session.addobj(cls = nodecls, objid = id, name = name, n = self.session.addobj(cls = nodecls, objid = id, name = name,
start = False) start = self.start)
if name in self.coords: if name in self.coords:
x, y, z = self.coords[name] x, y, z = self.coords[name]
n.setposition(x, y, z) n.setposition(x, y, z)
@ -763,10 +764,15 @@ class CoreDocumentWriter(Document):
addtextparamtoparent(self, meta, k, v) addtextparamtoparent(self, meta, k, v)
#addparamtoparent(self, meta, k, v) #addparamtoparent(self, meta, k, v)
def opensessionxml(session, filename): def opensessionxml(session, filename, start=False):
''' Import a session from the EmulationScript XML format. ''' Import a session from the EmulationScript XML format.
''' '''
doc = CoreDocumentParser(session, filename) doc = CoreDocumentParser(session, filename, start)
if start:
session.name = os.path.basename(filename)
session.filename = filename
session.node_count = str(session.getnodecount())
session.checkruntime()
def savesessionxml(session, filename): def savesessionxml(session, filename):
''' Export a session to the EmulationScript XML format. ''' Export a session to the EmulationScript XML format.

View file

@ -221,19 +221,16 @@ class Session(object):
self._time = time.time() self._time = time.time()
self._state = state self._state = state
replies = [] replies = []
if self.isconnected() and info:
if not self.isconnected():
return replies
if info:
statename = coreapi.state_name(state) statename = coreapi.state_name(state)
self._handlerslock.acquire() with self._handlerslock:
for handler in self._handlers: for handler in self._handlers:
handler.info("SESSION %s STATE %d: %s at %s" % \ handler.info("SESSION %s STATE %d: %s at %s" % \
(self.sessionid, state, statename, time.ctime())) (self.sessionid, state, statename,
self._handlerslock.release() time.ctime()))
self.writestate(state) self.writestate(state)
self.runhook(state) self.runhook(state)
if sendevent: if self.isconnected() and sendevent:
tlvdata = "" tlvdata = ""
tlvdata += coreapi.CoreEventTlv.pack(coreapi.CORE_TLV_EVENT_TYPE, tlvdata += coreapi.CoreEventTlv.pack(coreapi.CORE_TLV_EVENT_TYPE,
state) state)
@ -588,6 +585,24 @@ class Session(object):
# send a node status response message # send a node status response message
self.checkruntime() self.checkruntime()
def getnodecount(self):
''' Returns the number of CoreNodes and CoreNets, except for those
that are not considered in the GUI's node count.
'''
with self._objslock:
count = len(filter(lambda(x): \
not isinstance(x, (nodes.PtpNet, nodes.CtrlNet)),
self.objs()))
# on Linux, GreTapBridges are auto-created, not part of
# GUI's node count
if 'GreTapBridge' in globals():
count -= len(filter(lambda(x): \
isinstance(x, GreTapBridge) and not \
isinstance(x, nodes.TunnelNode),
self.objs()))
return count
def checkruntime(self): def checkruntime(self):
''' Check if we have entered the runtime state, that all nodes have been ''' Check if we have entered the runtime state, that all nodes have been
started and the emulation is running. Start the event loop once we started and the emulation is running. Start the event loop once we
@ -601,20 +616,7 @@ class Session(object):
if self.getstate() == coreapi.CORE_EVENT_RUNTIME_STATE: if self.getstate() == coreapi.CORE_EVENT_RUNTIME_STATE:
return return
session_node_count = int(self.node_count) session_node_count = int(self.node_count)
nc = 0 nc = self.getnodecount()
with self._objslock:
for obj in self.objs():
# these networks may be added by the daemon and are not
# considered in the GUI's node count
if isinstance(obj, (nodes.PtpNet, nodes.CtrlNet)):
continue
# on Linux, GreTapBridges are auto-created, not part of GUI's
# node count
if 'GreTapBridge' in globals():
if isinstance(obj, GreTapBridge) and \
not isinstance(obj, nodes.TunnelNode):
continue
nc += 1
# count booted nodes not emulated on this server # count booted nodes not emulated on this server
# TODO: let slave server determine RUNTIME and wait for Event Message # TODO: let slave server determine RUNTIME and wait for Event Message
# broker.getbootocunt() counts all CoreNodes from status reponse # broker.getbootocunt() counts all CoreNodes from status reponse

View file

@ -861,11 +861,9 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
''' Register Message Handler ''' Register Message Handler
''' '''
replies = [] replies = []
# execute a Python script or XML file
# execute a Python script
ex = msg.gettlv(coreapi.CORE_TLV_REG_EXECSRV) ex = msg.gettlv(coreapi.CORE_TLV_REG_EXECSRV)
if ex: if ex:
# TODO: load and execute XML files here
try: try:
self.info("executing '%s'" % ex) self.info("executing '%s'" % ex)
if isinstance(self.server, CoreUdpServer): if isinstance(self.server, CoreUdpServer):
@ -875,12 +873,16 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
if msg.flags & coreapi.CORE_API_STR_FLAG: if msg.flags & coreapi.CORE_API_STR_FLAG:
old_session_ids = set(server.getsessionids()) old_session_ids = set(server.getsessionids())
sys.argv = shlex.split(ex) sys.argv = shlex.split(ex)
scriptname = sys.argv[0] filename = sys.argv[0]
if os.path.splitext(filename)[1].lower() == '.xml':
session = server.getsession(useexisting=False)
opensessionxml(session, filename, start=True)
# TODO: Script may not return; run in separate thread here. # TODO: Script may not return; run in separate thread here.
# Wait for some configurable timeout period, then check # Wait for some configurable timeout period, then check
# for new session below. Wait for session to enter # for new session below. Wait for session to enter
# the runtime state, then send back the register message. # the runtime state, then send back the register message.
execfile(scriptname, {'server': server}) else:
execfile(filename, {'server': server})
if msg.flags & coreapi.CORE_API_STR_FLAG: if msg.flags & coreapi.CORE_API_STR_FLAG:
new_session_ids = set(server.getsessionids()) new_session_ids = set(server.getsessionids())
new_sid = new_session_ids.difference(old_session_ids) new_sid = new_session_ids.difference(old_session_ids)