refactored service methods to be shorter, updated some logging to debug, added some more service tests
This commit is contained in:
parent
8186f3716c
commit
bb533406a6
23 changed files with 226 additions and 112 deletions
|
@ -5,7 +5,6 @@ socket server request handlers leveraged by core servers.
|
||||||
import Queue
|
import Queue
|
||||||
import SocketServer
|
import SocketServer
|
||||||
import os
|
import os
|
||||||
import pprint
|
|
||||||
import shlex
|
import shlex
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
@ -1526,19 +1525,19 @@ class CoreHandler(SocketServer.BaseRequestHandler):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if event_type == EventTypes.STOP.value or event_type == EventTypes.RESTART.value:
|
if event_type == EventTypes.STOP.value or event_type == EventTypes.RESTART.value:
|
||||||
status = self.session.services.stop_node_service(node, service)
|
status = self.session.services.stop_service(node, service)
|
||||||
if status:
|
if status:
|
||||||
fail += "Stop %s," % service.name
|
fail += "Stop %s," % service.name
|
||||||
if event_type == EventTypes.START.value or event_type == EventTypes.RESTART.value:
|
if event_type == EventTypes.START.value or event_type == EventTypes.RESTART.value:
|
||||||
status = self.session.services.node_service_startup(node, service)
|
status = self.session.services.startup_service(node, service)
|
||||||
if status:
|
if status:
|
||||||
fail += "Start %s(%s)," % service.name
|
fail += "Start %s(%s)," % service.name
|
||||||
if event_type == EventTypes.PAUSE.value:
|
if event_type == EventTypes.PAUSE.value:
|
||||||
status = self.session.services.validate_node_service(node, service)
|
status = self.session.services.validate_service(node, service)
|
||||||
if status:
|
if status:
|
||||||
fail += "%s," % service.name
|
fail += "%s," % service.name
|
||||||
if event_type == EventTypes.RECONFIGURE.value:
|
if event_type == EventTypes.RECONFIGURE.value:
|
||||||
self.session.services.node_service_reconfigure(node, service)
|
self.session.services.service_reconfigure(node, service)
|
||||||
|
|
||||||
fail_data = ""
|
fail_data = ""
|
||||||
if len(fail) > 0:
|
if len(fail) > 0:
|
||||||
|
@ -1679,6 +1678,7 @@ class CoreHandler(SocketServer.BaseRequestHandler):
|
||||||
Return API messages that describe the current session.
|
Return API messages that describe the current session.
|
||||||
"""
|
"""
|
||||||
# find all nodes and links
|
# find all nodes and links
|
||||||
|
|
||||||
nodes_data = []
|
nodes_data = []
|
||||||
links_data = []
|
links_data = []
|
||||||
with self.session._objects_lock:
|
with self.session._objects_lock:
|
||||||
|
@ -1692,21 +1692,17 @@ class CoreHandler(SocketServer.BaseRequestHandler):
|
||||||
links_data.append(link_data)
|
links_data.append(link_data)
|
||||||
|
|
||||||
# send all nodes first, so that they will exist for any links
|
# send all nodes first, so that they will exist for any links
|
||||||
logger.info("sending nodes:")
|
|
||||||
for node_data in nodes_data:
|
for node_data in nodes_data:
|
||||||
logger.info(pprint.pformat(dict(node_data._asdict())))
|
|
||||||
self.session.broadcast_node(node_data)
|
self.session.broadcast_node(node_data)
|
||||||
|
|
||||||
logger.info("sending links:")
|
|
||||||
for link_data in links_data:
|
for link_data in links_data:
|
||||||
logger.info(pprint.pformat(dict(link_data._asdict())))
|
|
||||||
self.session.broadcast_link(link_data)
|
self.session.broadcast_link(link_data)
|
||||||
|
|
||||||
# send mobility model info
|
# send mobility model info
|
||||||
for node_id in self.session.mobility.nodes():
|
for node_id in self.session.mobility.nodes():
|
||||||
node = self.session.get_object(node_id)
|
node = self.session.get_object(node_id)
|
||||||
for model_class, config in self.session.mobility.get_models(node):
|
for model_class, config in self.session.mobility.get_models(node):
|
||||||
logger.info("mobility config: node(%s) class(%s) values(%s)", node_id, model_class, config)
|
logger.debug("mobility config: node(%s) class(%s) values(%s)", node_id, model_class, config)
|
||||||
config_data = ConfigShim.config_data(0, node_id, ConfigFlags.UPDATE.value, model_class, config)
|
config_data = ConfigShim.config_data(0, node_id, ConfigFlags.UPDATE.value, model_class, config)
|
||||||
self.session.broadcast_config(config_data)
|
self.session.broadcast_config(config_data)
|
||||||
|
|
||||||
|
@ -1714,7 +1710,7 @@ class CoreHandler(SocketServer.BaseRequestHandler):
|
||||||
for node_id in self.session.emane.nodes():
|
for node_id in self.session.emane.nodes():
|
||||||
node = self.session.get_object(node_id)
|
node = self.session.get_object(node_id)
|
||||||
for model_class, config in self.session.emane.get_models(node):
|
for model_class, config in self.session.emane.get_models(node):
|
||||||
logger.info("emane config: node(%s) class(%s) values(%s)", node_id, model_class, config)
|
logger.debug("emane config: node(%s) class(%s) values(%s)", node_id, model_class, config)
|
||||||
config_data = ConfigShim.config_data(0, node_id, ConfigFlags.UPDATE.value, model_class, config)
|
config_data = ConfigShim.config_data(0, node_id, ConfigFlags.UPDATE.value, model_class, config)
|
||||||
self.session.broadcast_config(config_data)
|
self.session.broadcast_config(config_data)
|
||||||
|
|
||||||
|
|
|
@ -515,7 +515,7 @@ class EmuSession(Session):
|
||||||
if self.state == EventTypes.RUNTIME_STATE.value and is_boot_node:
|
if self.state == EventTypes.RUNTIME_STATE.value and is_boot_node:
|
||||||
self.write_objects()
|
self.write_objects()
|
||||||
self.add_remove_control_interface(node=node, remove=False)
|
self.add_remove_control_interface(node=node, remove=False)
|
||||||
self.services.boot_node_services(node)
|
self.services.boot_services(node)
|
||||||
|
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
|
|
@ -50,8 +50,8 @@ class ServiceShim(object):
|
||||||
valmap = [service.dirs, service.configs, start_index, service.startup,
|
valmap = [service.dirs, service.configs, start_index, service.startup,
|
||||||
service.shutdown, service.validate, service.meta, start_time]
|
service.shutdown, service.validate, service.meta, start_time]
|
||||||
if not service.custom:
|
if not service.custom:
|
||||||
valmap[1] = service.getconfigfilenames(node)
|
valmap[1] = service.get_configs(node)
|
||||||
valmap[3] = service.getstartup(node)
|
valmap[3] = service.get_startup(node)
|
||||||
vals = map(lambda a, b: "%s=%s" % (a, str(b)), cls.keys, valmap)
|
vals = map(lambda a, b: "%s=%s" % (a, str(b)), cls.keys, valmap)
|
||||||
return "|".join(vals)
|
return "|".join(vals)
|
||||||
|
|
||||||
|
@ -217,7 +217,15 @@ class CoreServices(object):
|
||||||
self.default_services.clear()
|
self.default_services.clear()
|
||||||
self.custom_services.clear()
|
self.custom_services.clear()
|
||||||
|
|
||||||
def node_boot_paths(self, services):
|
def create_boot_paths(self, services):
|
||||||
|
"""
|
||||||
|
Create boot paths for starting up services based on dependencies. All services provided and their dependencies
|
||||||
|
must exist within this set of services, to be valid.
|
||||||
|
|
||||||
|
:param list[CoreService] services: service to create boot paths for
|
||||||
|
:return: list of boot paths for services
|
||||||
|
:rtype: list[list[CoreService]]
|
||||||
|
"""
|
||||||
# generate service map and find starting points
|
# generate service map and find starting points
|
||||||
node_services = {service.name: service for service in services}
|
node_services = {service.name: service for service in services}
|
||||||
is_dependency = set()
|
is_dependency = set()
|
||||||
|
@ -398,7 +406,7 @@ class CoreServices(object):
|
||||||
|
|
||||||
return files
|
return files
|
||||||
|
|
||||||
def boot_node_services(self, node):
|
def boot_services(self, node):
|
||||||
"""
|
"""
|
||||||
Start all services on a node.
|
Start all services on a node.
|
||||||
|
|
||||||
|
@ -408,9 +416,9 @@ class CoreServices(object):
|
||||||
pool = ThreadPool()
|
pool = ThreadPool()
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
boot_paths = self.node_boot_paths(node.services)
|
boot_paths = self.create_boot_paths(node.services)
|
||||||
for boot_path in boot_paths:
|
for boot_path in boot_paths:
|
||||||
result = pool.apply_async(self._boot_node_paths, (node, boot_path))
|
result = pool.apply_async(self._start_boot_paths, (node, boot_path))
|
||||||
results.append(result)
|
results.append(result)
|
||||||
|
|
||||||
pool.close()
|
pool.close()
|
||||||
|
@ -418,7 +426,7 @@ class CoreServices(object):
|
||||||
for result in results:
|
for result in results:
|
||||||
result.get()
|
result.get()
|
||||||
|
|
||||||
def _boot_node_paths(self, node, boot_path):
|
def _start_boot_paths(self, node, boot_path):
|
||||||
"""
|
"""
|
||||||
Start all service boot paths found, based on dependencies.
|
Start all service boot paths found, based on dependencies.
|
||||||
|
|
||||||
|
@ -428,9 +436,9 @@ class CoreServices(object):
|
||||||
"""
|
"""
|
||||||
logger.debug("booting node service dependencies: %s", boot_path)
|
logger.debug("booting node service dependencies: %s", boot_path)
|
||||||
for service in boot_path:
|
for service in boot_path:
|
||||||
self.boot_node_service(node, service)
|
self.boot_service(node, service)
|
||||||
|
|
||||||
def boot_node_service(self, node, service):
|
def boot_service(self, node, service):
|
||||||
"""
|
"""
|
||||||
Start a service on a node. Create private dirs, generate config
|
Start a service on a node. Create private dirs, generate config
|
||||||
files, and execute startup commands.
|
files, and execute startup commands.
|
||||||
|
@ -446,11 +454,11 @@ class CoreServices(object):
|
||||||
node.privatedir(directory)
|
node.privatedir(directory)
|
||||||
|
|
||||||
# create service files
|
# create service files
|
||||||
self.node_service_files(node, service)
|
self.create_service_files(node, service)
|
||||||
|
|
||||||
# run startup
|
# run startup
|
||||||
wait = service.validation_mode == ServiceMode.BLOCKING
|
wait = service.validation_mode == ServiceMode.BLOCKING
|
||||||
status = self.node_service_startup(node, service, wait)
|
status = self.startup_service(node, service, wait)
|
||||||
if status:
|
if status:
|
||||||
raise ServiceBootError("node(%s) service(%s) error during startup" % (node.name, service.name))
|
raise ServiceBootError("node(%s) service(%s) error during startup" % (node.name, service.name))
|
||||||
|
|
||||||
|
@ -461,7 +469,7 @@ class CoreServices(object):
|
||||||
|
|
||||||
# run validation commands, if present and not timer mode
|
# run validation commands, if present and not timer mode
|
||||||
if service.validation_mode != ServiceMode.TIMER:
|
if service.validation_mode != ServiceMode.TIMER:
|
||||||
status = self.validate_node_service(node, service)
|
status = self.validate_service(node, service)
|
||||||
if status:
|
if status:
|
||||||
raise ServiceBootError("node(%s) service(%s) failed validation" % (node.name, service.name))
|
raise ServiceBootError("node(%s) service(%s) failed validation" % (node.name, service.name))
|
||||||
|
|
||||||
|
@ -486,7 +494,7 @@ class CoreServices(object):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def validate_node_service(self, node, service):
|
def validate_service(self, node, service):
|
||||||
"""
|
"""
|
||||||
Run the validation command(s) for a service.
|
Run the validation command(s) for a service.
|
||||||
|
|
||||||
|
@ -498,7 +506,7 @@ class CoreServices(object):
|
||||||
logger.info("validating node(%s) service(%s)", node.name, service.name)
|
logger.info("validating node(%s) service(%s)", node.name, service.name)
|
||||||
cmds = service.validate
|
cmds = service.validate
|
||||||
if not service.custom:
|
if not service.custom:
|
||||||
cmds = service.getvalidate(node)
|
cmds = service.get_validate(node)
|
||||||
|
|
||||||
status = 0
|
status = 0
|
||||||
for cmd in cmds:
|
for cmd in cmds:
|
||||||
|
@ -511,7 +519,7 @@ class CoreServices(object):
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def stop_node_services(self, node):
|
def stop_services(self, node):
|
||||||
"""
|
"""
|
||||||
Stop all services on a node.
|
Stop all services on a node.
|
||||||
|
|
||||||
|
@ -519,9 +527,9 @@ class CoreServices(object):
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
for service in node.services:
|
for service in node.services:
|
||||||
self.stop_node_service(node, service)
|
self.stop_service(node, service)
|
||||||
|
|
||||||
def stop_node_service(self, node, service):
|
def stop_service(self, node, service):
|
||||||
"""
|
"""
|
||||||
Stop a service on a node.
|
Stop a service on a node.
|
||||||
|
|
||||||
|
@ -558,7 +566,7 @@ class CoreServices(object):
|
||||||
if service.custom:
|
if service.custom:
|
||||||
config_files = service.configs
|
config_files = service.configs
|
||||||
else:
|
else:
|
||||||
config_files = service.getconfigfilenames(node)
|
config_files = service.get_configs(node)
|
||||||
|
|
||||||
if filename not in config_files:
|
if filename not in config_files:
|
||||||
raise ValueError("unknown service(%s) config file: %s", service_name, filename)
|
raise ValueError("unknown service(%s) config file: %s", service_name, filename)
|
||||||
|
@ -566,7 +574,7 @@ class CoreServices(object):
|
||||||
# get the file data
|
# get the file data
|
||||||
data = service.config_data.get(filename)
|
data = service.config_data.get(filename)
|
||||||
if data is None:
|
if data is None:
|
||||||
data = "%s" % service.generateconfig(node, filename)
|
data = "%s" % service.generate_config(node, filename)
|
||||||
else:
|
else:
|
||||||
data = "%s" % data
|
data = "%s" % data
|
||||||
|
|
||||||
|
@ -579,7 +587,7 @@ class CoreServices(object):
|
||||||
data=data
|
data=data
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_service_file(self, node_id, service_name, filename, data):
|
def set_service_file(self, node_id, service_name, file_name, data):
|
||||||
"""
|
"""
|
||||||
Receive a File Message from the GUI and store the customized file
|
Receive a File Message from the GUI and store the customized file
|
||||||
in the service config. The filename must match one from the list of
|
in the service config. The filename must match one from the list of
|
||||||
|
@ -587,7 +595,7 @@ class CoreServices(object):
|
||||||
|
|
||||||
:param int node_id: node id to set service file
|
:param int node_id: node id to set service file
|
||||||
:param str service_name: service name to set file for
|
:param str service_name: service name to set file for
|
||||||
:param str filename: file name to set
|
:param str file_name: file name to set
|
||||||
:param data: data for file to set
|
:param data: data for file to set
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
|
@ -597,19 +605,19 @@ class CoreServices(object):
|
||||||
# retrieve custom service
|
# retrieve custom service
|
||||||
service = self.get_service(node_id, service_name)
|
service = self.get_service(node_id, service_name)
|
||||||
if service is None:
|
if service is None:
|
||||||
logger.warn("received filename for unknown service: %s", service_name)
|
logger.warn("received file name for unknown service: %s", service_name)
|
||||||
return
|
return
|
||||||
|
|
||||||
# validate file being set is valid
|
# validate file being set is valid
|
||||||
cfgfiles = service.configs
|
config_files = service.configs
|
||||||
if filename not in cfgfiles:
|
if file_name not in config_files:
|
||||||
logger.warn("received unknown file '%s' for service '%s'", filename, service_name)
|
logger.warn("received unknown file(%s) for service(%s)", file_name, service_name)
|
||||||
return
|
return
|
||||||
|
|
||||||
# set custom service file data
|
# set custom service file data
|
||||||
service.config_data[filename] = data
|
service.config_data[file_name] = data
|
||||||
|
|
||||||
def node_service_startup(self, node, service, wait=False):
|
def startup_service(self, node, service, wait=False):
|
||||||
"""
|
"""
|
||||||
Startup a node service.
|
Startup a node service.
|
||||||
|
|
||||||
|
@ -622,7 +630,7 @@ class CoreServices(object):
|
||||||
|
|
||||||
cmds = service.startup
|
cmds = service.startup
|
||||||
if not service.custom:
|
if not service.custom:
|
||||||
cmds = service.getstartup(node)
|
cmds = service.get_startup(node)
|
||||||
|
|
||||||
status = 0
|
status = 0
|
||||||
for cmd in cmds:
|
for cmd in cmds:
|
||||||
|
@ -636,7 +644,7 @@ class CoreServices(object):
|
||||||
status = -1
|
status = -1
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def node_service_files(self, node, service):
|
def create_service_files(self, node, service):
|
||||||
"""
|
"""
|
||||||
Creates node service files.
|
Creates node service files.
|
||||||
|
|
||||||
|
@ -646,16 +654,16 @@ class CoreServices(object):
|
||||||
"""
|
"""
|
||||||
logger.info("node(%s) service(%s) creating config files", node.name, service.name)
|
logger.info("node(%s) service(%s) creating config files", node.name, service.name)
|
||||||
# get values depending on if custom or not
|
# get values depending on if custom or not
|
||||||
file_names = service.configs
|
config_files = service.configs
|
||||||
if not service.custom:
|
if not service.custom:
|
||||||
file_names = service.getconfigfilenames(node)
|
config_files = service.get_configs(node)
|
||||||
|
|
||||||
for file_name in file_names:
|
for file_name in config_files:
|
||||||
logger.debug("generating service config: %s", file_name)
|
logger.debug("generating service config: %s", file_name)
|
||||||
if service.custom:
|
if service.custom:
|
||||||
cfg = service.config_data.get(file_name)
|
cfg = service.config_data.get(file_name)
|
||||||
if cfg is None:
|
if cfg is None:
|
||||||
cfg = service.generateconfig(node, file_name)
|
cfg = service.generate_config(node, file_name)
|
||||||
|
|
||||||
# cfg may have a file:/// url for copying from a file
|
# cfg may have a file:/// url for copying from a file
|
||||||
try:
|
try:
|
||||||
|
@ -665,11 +673,11 @@ class CoreServices(object):
|
||||||
logger.exception("error copying service file: %s", file_name)
|
logger.exception("error copying service file: %s", file_name)
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
cfg = service.generateconfig(node, file_name)
|
cfg = service.generate_config(node, file_name)
|
||||||
|
|
||||||
node.nodefile(file_name, cfg)
|
node.nodefile(file_name, cfg)
|
||||||
|
|
||||||
def node_service_reconfigure(self, node, service):
|
def service_reconfigure(self, node, service):
|
||||||
"""
|
"""
|
||||||
Reconfigure a node service.
|
Reconfigure a node service.
|
||||||
|
|
||||||
|
@ -677,18 +685,18 @@ class CoreServices(object):
|
||||||
:param CoreService service: service to reconfigure
|
:param CoreService service: service to reconfigure
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
file_names = service.configs
|
config_files = service.configs
|
||||||
if not service.custom:
|
if not service.custom:
|
||||||
file_names = service.getconfigfilenames(node)
|
config_files = service.get_configs(node)
|
||||||
|
|
||||||
for file_name in file_names:
|
for file_name in config_files:
|
||||||
if file_name[:7] == "file:///":
|
if file_name[:7] == "file:///":
|
||||||
# TODO: implement this
|
# TODO: implement this
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
cfg = service.config_data.get(file_name)
|
cfg = service.config_data.get(file_name)
|
||||||
if cfg is None:
|
if cfg is None:
|
||||||
cfg = service.generateconfig(node, file_name)
|
cfg = service.generate_config(node, file_name)
|
||||||
|
|
||||||
node.nodefile(file_name, cfg)
|
node.nodefile(file_name, cfg)
|
||||||
|
|
||||||
|
@ -760,7 +768,7 @@ class CoreService(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getconfigfilenames(cls, node):
|
def get_configs(cls, node):
|
||||||
"""
|
"""
|
||||||
Return the tuple of configuration file filenames. This default method
|
Return the tuple of configuration file filenames. This default method
|
||||||
returns the cls._configs tuple, but this method may be overriden to
|
returns the cls._configs tuple, but this method may be overriden to
|
||||||
|
@ -773,7 +781,7 @@ class CoreService(object):
|
||||||
return cls.configs
|
return cls.configs
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Generate configuration file given a node object. The filename is
|
Generate configuration file given a node object. The filename is
|
||||||
provided to allow for multiple config files.
|
provided to allow for multiple config files.
|
||||||
|
@ -787,7 +795,7 @@ class CoreService(object):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getstartup(cls, node):
|
def get_startup(cls, node):
|
||||||
"""
|
"""
|
||||||
Return the tuple of startup commands. This default method
|
Return the tuple of startup commands. This default method
|
||||||
returns the cls.startup tuple, but this method may be
|
returns the cls.startup tuple, but this method may be
|
||||||
|
@ -801,7 +809,7 @@ class CoreService(object):
|
||||||
return cls.startup
|
return cls.startup
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getvalidate(cls, node):
|
def get_validate(cls, node):
|
||||||
"""
|
"""
|
||||||
Return the tuple of validate commands. This default method
|
Return the tuple of validate commands. This default method
|
||||||
returns the cls.validate tuple, but this method may be
|
returns the cls.validate tuple, but this method may be
|
||||||
|
|
|
@ -19,7 +19,7 @@ class Bird(CoreService):
|
||||||
validate = ("pidof bird",)
|
validate = ("pidof bird",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Return the bird.conf file contents.
|
Return the bird.conf file contents.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -123,7 +123,7 @@ class DockerService(CoreService):
|
||||||
image = ""
|
image = ""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Returns a string having contents of a docker.sh script that
|
Returns a string having contents of a docker.sh script that
|
||||||
can be modified to start a specific docker image.
|
can be modified to start a specific docker image.
|
||||||
|
|
|
@ -21,7 +21,7 @@ class NrlService(CoreService):
|
||||||
shutdown = ()
|
shutdown = ()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -52,7 +52,7 @@ class MgenSinkService(NrlService):
|
||||||
shutdown = ("killall mgen",)
|
shutdown = ("killall mgen",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
cfg = "0.0 LISTEN UDP 5000\n"
|
cfg = "0.0 LISTEN UDP 5000\n"
|
||||||
for ifc in node.netifs():
|
for ifc in node.netifs():
|
||||||
name = utils.sysctl_devname(ifc.name)
|
name = utils.sysctl_devname(ifc.name)
|
||||||
|
@ -60,7 +60,7 @@ class MgenSinkService(NrlService):
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getstartup(cls, node):
|
def get_startup(cls, node):
|
||||||
cmd = cls.startup[0]
|
cmd = cls.startup[0]
|
||||||
cmd += " output /tmp/mgen_%s.log" % node.name
|
cmd += " output /tmp/mgen_%s.log" % node.name
|
||||||
return cmd,
|
return cmd,
|
||||||
|
@ -77,7 +77,7 @@ class NrlNhdp(NrlService):
|
||||||
validate = ("pidof nrlnhdp",)
|
validate = ("pidof nrlnhdp",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getstartup(cls, node):
|
def get_startup(cls, node):
|
||||||
"""
|
"""
|
||||||
Generate the appropriate command-line based on node interfaces.
|
Generate the appropriate command-line based on node interfaces.
|
||||||
"""
|
"""
|
||||||
|
@ -111,7 +111,7 @@ class NrlSmf(NrlService):
|
||||||
configs = ("startsmf.sh",)
|
configs = ("startsmf.sh",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename, ):
|
def generate_config(cls, node, filename, ):
|
||||||
"""
|
"""
|
||||||
Generate a startup script for SMF. Because nrlsmf does not
|
Generate a startup script for SMF. Because nrlsmf does not
|
||||||
daemonize, it can cause problems in some situations when launched
|
daemonize, it can cause problems in some situations when launched
|
||||||
|
@ -162,7 +162,7 @@ class NrlOlsr(NrlService):
|
||||||
validate = ("pidof nrlolsrd",)
|
validate = ("pidof nrlolsrd",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getstartup(cls, node):
|
def get_startup(cls, node):
|
||||||
"""
|
"""
|
||||||
Generate the appropriate command-line based on node interfaces.
|
Generate the appropriate command-line based on node interfaces.
|
||||||
"""
|
"""
|
||||||
|
@ -196,7 +196,7 @@ class NrlOlsrv2(NrlService):
|
||||||
validate = ("pidof nrlolsrv2",)
|
validate = ("pidof nrlolsrv2",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getstartup(cls, node):
|
def get_startup(cls, node):
|
||||||
"""
|
"""
|
||||||
Generate the appropriate command-line based on node interfaces.
|
Generate the appropriate command-line based on node interfaces.
|
||||||
"""
|
"""
|
||||||
|
@ -233,7 +233,7 @@ class OlsrOrg(NrlService):
|
||||||
validate = ("pidof olsrd",)
|
validate = ("pidof olsrd",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getstartup(cls, node):
|
def get_startup(cls, node):
|
||||||
"""
|
"""
|
||||||
Generate the appropriate command-line based on node interfaces.
|
Generate the appropriate command-line based on node interfaces.
|
||||||
"""
|
"""
|
||||||
|
@ -247,7 +247,7 @@ class OlsrOrg(NrlService):
|
||||||
return cmd,
|
return cmd,
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Generate a default olsrd config file to use the broadcast address of 255.255.255.255.
|
Generate a default olsrd config file to use the broadcast address of 255.255.255.255.
|
||||||
"""
|
"""
|
||||||
|
@ -591,7 +591,7 @@ class MgenActor(NrlService):
|
||||||
shutdown = ("killall mgen",)
|
shutdown = ("killall mgen",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Generate a startup script for MgenActor. Because mgenActor does not
|
Generate a startup script for MgenActor. Because mgenActor does not
|
||||||
daemonize, it can cause problems in some situations when launched
|
daemonize, it can cause problems in some situations when launched
|
||||||
|
@ -623,7 +623,7 @@ class Arouted(NrlService):
|
||||||
validate = ("pidof arouted",)
|
validate = ("pidof arouted",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Return the Quagga.conf or quaggaboot.sh file contents.
|
Return the Quagga.conf or quaggaboot.sh file contents.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -23,7 +23,7 @@ class Zebra(CoreService):
|
||||||
validate = ("pidof zebra",)
|
validate = ("pidof zebra",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Return the Quagga.conf or quaggaboot.sh file contents.
|
Return the Quagga.conf or quaggaboot.sh file contents.
|
||||||
"""
|
"""
|
||||||
|
@ -259,7 +259,7 @@ class QuaggaService(CoreService):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -14,7 +14,7 @@ class SdnService(CoreService):
|
||||||
group = "SDN"
|
group = "SDN"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ class OvsService(SdnService):
|
||||||
shutdown = ('killall ovs-vswitchd', 'killall ovsdb-server')
|
shutdown = ('killall ovs-vswitchd', 'killall ovsdb-server')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
# Check whether the node is running zebra
|
# Check whether the node is running zebra
|
||||||
has_zebra = 0
|
has_zebra = 0
|
||||||
for s in node.services:
|
for s in node.services:
|
||||||
|
@ -101,7 +101,7 @@ class RyuService(SdnService):
|
||||||
shutdown = ('killall ryu-manager',)
|
shutdown = ('killall ryu-manager',)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Return a string that will be written to filename, or sent to the
|
Return a string that will be written to filename, or sent to the
|
||||||
GUI for user customization.
|
GUI for user customization.
|
||||||
|
|
|
@ -18,7 +18,7 @@ class VPNClient(CoreService):
|
||||||
custom_needed = True
|
custom_needed = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Return the client.conf and vpnclient.sh file contents to
|
Return the client.conf and vpnclient.sh file contents to
|
||||||
"""
|
"""
|
||||||
|
@ -44,7 +44,7 @@ class VPNServer(CoreService):
|
||||||
custom_needed = True
|
custom_needed = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Return the sample server.conf and vpnserver.sh file contents to
|
Return the sample server.conf and vpnserver.sh file contents to
|
||||||
GUI for user customization.
|
GUI for user customization.
|
||||||
|
@ -70,7 +70,7 @@ class IPsec(CoreService):
|
||||||
custom_needed = True
|
custom_needed = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Return the ipsec.conf and racoon.conf file contents to
|
Return the ipsec.conf and racoon.conf file contents to
|
||||||
GUI for user customization.
|
GUI for user customization.
|
||||||
|
@ -96,7 +96,7 @@ class Firewall(CoreService):
|
||||||
custom_needed = True
|
custom_needed = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Return the firewall rule examples to GUI for user customization.
|
Return the firewall rule examples to GUI for user customization.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Ucarp(CoreService):
|
||||||
validate = ("pidof ucarp",)
|
validate = ("pidof ucarp",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Return the default file contents
|
Return the default file contents
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -24,7 +24,7 @@ class UtilService(CoreService):
|
||||||
shutdown = ()
|
shutdown = ()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class IPForwardService(UtilService):
|
||||||
startup = ("sh ipforward.sh",)
|
startup = ("sh ipforward.sh",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
if os.uname()[0] == "Linux":
|
if os.uname()[0] == "Linux":
|
||||||
return cls.generateconfiglinux(node, filename)
|
return cls.generateconfiglinux(node, filename)
|
||||||
else:
|
else:
|
||||||
|
@ -69,7 +69,7 @@ class DefaultRouteService(UtilService):
|
||||||
startup = ("sh defaultroute.sh",)
|
startup = ("sh defaultroute.sh",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
cfg = "#!/bin/sh\n"
|
cfg = "#!/bin/sh\n"
|
||||||
cfg += "# auto-generated by DefaultRoute service (utility.py)\n"
|
cfg += "# auto-generated by DefaultRoute service (utility.py)\n"
|
||||||
for ifc in node.netifs():
|
for ifc in node.netifs():
|
||||||
|
@ -103,7 +103,7 @@ class DefaultMulticastRouteService(UtilService):
|
||||||
startup = ("sh defaultmroute.sh",)
|
startup = ("sh defaultmroute.sh",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
cfg = "#!/bin/sh\n"
|
cfg = "#!/bin/sh\n"
|
||||||
cfg += "# auto-generated by DefaultMulticastRoute service (utility.py)\n"
|
cfg += "# auto-generated by DefaultMulticastRoute service (utility.py)\n"
|
||||||
cfg += "# the first interface is chosen below; please change it "
|
cfg += "# the first interface is chosen below; please change it "
|
||||||
|
@ -129,7 +129,7 @@ class StaticRouteService(UtilService):
|
||||||
custom_needed = True
|
custom_needed = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
cfg = "#!/bin/sh\n"
|
cfg = "#!/bin/sh\n"
|
||||||
cfg += "# auto-generated by StaticRoute service (utility.py)\n#\n"
|
cfg += "# auto-generated by StaticRoute service (utility.py)\n#\n"
|
||||||
cfg += "# NOTE: this service must be customized to be of any use\n"
|
cfg += "# NOTE: this service must be customized to be of any use\n"
|
||||||
|
@ -170,7 +170,7 @@ class SshService(UtilService):
|
||||||
validate = ()
|
validate = ()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Use a startup script for launching sshd in order to wait for host
|
Use a startup script for launching sshd in order to wait for host
|
||||||
key generation.
|
key generation.
|
||||||
|
@ -238,7 +238,7 @@ class DhcpService(UtilService):
|
||||||
validate = ("pidof dhcpd",)
|
validate = ("pidof dhcpd",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Generate a dhcpd config file using the network address of
|
Generate a dhcpd config file using the network address of
|
||||||
each interface.
|
each interface.
|
||||||
|
@ -300,7 +300,7 @@ class DhcpClientService(UtilService):
|
||||||
validate = ("pidof dhclient",)
|
validate = ("pidof dhclient",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Generate a script to invoke dhclient on all interfaces.
|
Generate a script to invoke dhclient on all interfaces.
|
||||||
"""
|
"""
|
||||||
|
@ -332,7 +332,7 @@ class FtpService(UtilService):
|
||||||
validate = ("pidof vsftpd",)
|
validate = ("pidof vsftpd",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Generate a vsftpd.conf configuration file.
|
Generate a vsftpd.conf configuration file.
|
||||||
"""
|
"""
|
||||||
|
@ -368,7 +368,7 @@ class HttpService(UtilService):
|
||||||
APACHEVER22, APACHEVER24 = (22, 24)
|
APACHEVER22, APACHEVER24 = (22, 24)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Generate an apache2.conf configuration file.
|
Generate an apache2.conf configuration file.
|
||||||
"""
|
"""
|
||||||
|
@ -577,7 +577,7 @@ class PcapService(UtilService):
|
||||||
meta = "logs network traffic to pcap packet capture files"
|
meta = "logs network traffic to pcap packet capture files"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Generate a startpcap.sh traffic logging script.
|
Generate a startpcap.sh traffic logging script.
|
||||||
"""
|
"""
|
||||||
|
@ -615,7 +615,7 @@ class RadvdService(UtilService):
|
||||||
validate = ("pidof radvd",)
|
validate = ("pidof radvd",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Generate a RADVD router advertisement daemon config file
|
Generate a RADVD router advertisement daemon config file
|
||||||
using the network address of each interface.
|
using the network address of each interface.
|
||||||
|
@ -674,7 +674,7 @@ class AtdService(UtilService):
|
||||||
shutdown = ("pkill atd",)
|
shutdown = ("pkill atd",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
return """
|
return """
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
echo 00001 > /var/spool/cron/atjobs/.SEQ
|
echo 00001 > /var/spool/cron/atjobs/.SEQ
|
||||||
|
|
|
@ -21,7 +21,7 @@ class XorpRtrmgr(CoreService):
|
||||||
validate = ("pidof xorp_rtrmgr",)
|
validate = ("pidof xorp_rtrmgr",)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Returns config.boot configuration file text. Other services that
|
Returns config.boot configuration file text. Other services that
|
||||||
depend on this will have generatexorpconfig() hooks that are
|
depend on this will have generatexorpconfig() hooks that are
|
||||||
|
@ -150,7 +150,7 @@ class XorpService(CoreService):
|
||||||
return "0.0.0.0"
|
return "0.0.0.0"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -673,7 +673,7 @@ class Session(object):
|
||||||
for obj in self.objects.itervalues():
|
for obj in self.objects.itervalues():
|
||||||
# TODO: determine if checking for CoreNode alone is ok
|
# TODO: determine if checking for CoreNode alone is ok
|
||||||
if isinstance(obj, nodes.PyCoreNode):
|
if isinstance(obj, nodes.PyCoreNode):
|
||||||
self.services.stop_node_services(obj)
|
self.services.stop_services(obj)
|
||||||
|
|
||||||
# shutdown emane
|
# shutdown emane
|
||||||
self.emane.shutdown()
|
self.emane.shutdown()
|
||||||
|
@ -727,7 +727,7 @@ class Session(object):
|
||||||
# add a control interface if configured
|
# add a control interface if configured
|
||||||
logger.info("booting node: %s", obj.name)
|
logger.info("booting node: %s", obj.name)
|
||||||
self.add_remove_control_interface(node=obj, remove=False)
|
self.add_remove_control_interface(node=obj, remove=False)
|
||||||
result = pool.apply_async(self.services.boot_node_services, (obj,))
|
result = pool.apply_async(self.services.boot_services, (obj,))
|
||||||
results.append(result)
|
results.append(result)
|
||||||
|
|
||||||
pool.close()
|
pool.close()
|
||||||
|
|
|
@ -370,7 +370,7 @@ class CoreDocumentParser0(object):
|
||||||
filename = file.getAttribute("name")
|
filename = file.getAttribute("name")
|
||||||
files.append(filename)
|
files.append(filename)
|
||||||
data = xmlutils.get_text_child(file)
|
data = xmlutils.get_text_child(file)
|
||||||
self.session.services.set_service_file(node_id=n.objid, service_name=name, filename=filename, data=data)
|
self.session.services.set_service_file(node_id=n.objid, service_name=name, file_name=filename, data=data)
|
||||||
|
|
||||||
if len(files):
|
if len(files):
|
||||||
values.append("files=%s" % files)
|
values.append("files=%s" % files)
|
||||||
|
|
|
@ -651,7 +651,7 @@ class CoreDocumentParser1(object):
|
||||||
self.session.services.set_service_file(
|
self.session.services.set_service_file(
|
||||||
node_id=node.objid,
|
node_id=node.objid,
|
||||||
service_name=svcname,
|
service_name=svcname,
|
||||||
filename=filename,
|
file_name=filename,
|
||||||
data=data
|
data=data
|
||||||
)
|
)
|
||||||
return str(name)
|
return str(name)
|
||||||
|
|
|
@ -694,7 +694,7 @@ class DeviceElement(NamedXmlElement):
|
||||||
f.setAttribute("name", fn)
|
f.setAttribute("name", fn)
|
||||||
# all file names are added to determine when a file has been deleted
|
# all file names are added to determine when a file has been deleted
|
||||||
s.appendChild(f)
|
s.appendChild(f)
|
||||||
data = svc.configtxt.get(fn)
|
data = svc.config_data.get(fn)
|
||||||
if data is None:
|
if data is None:
|
||||||
# this includes only customized file contents and skips
|
# this includes only customized file contents and skips
|
||||||
# the auto-generated files
|
# the auto-generated files
|
||||||
|
|
|
@ -29,7 +29,7 @@ class MyService(CoreService):
|
||||||
shutdown = ()
|
shutdown = ()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generateconfig(cls, node, filename):
|
def generate_config(cls, node, filename):
|
||||||
"""
|
"""
|
||||||
Return a string that will be written to filename, or sent to the
|
Return a string that will be written to filename, or sent to the
|
||||||
GUI for user customization.
|
GUI for user customization.
|
||||||
|
|
|
@ -160,7 +160,7 @@ def main():
|
||||||
n.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"])
|
n.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"])
|
||||||
if options.services is not None:
|
if options.services is not None:
|
||||||
session.services.add_services(n, "", options.services.split("|"))
|
session.services.add_services(n, "", options.services.split("|"))
|
||||||
session.services.boot_node_services(n)
|
session.services.boot_services(n)
|
||||||
nodelist.append(n)
|
nodelist.append(n)
|
||||||
if i % 25 == 0:
|
if i % 25 == 0:
|
||||||
print "\n%s nodes created " % i,
|
print "\n%s nodes created " % i,
|
||||||
|
|
|
@ -88,7 +88,7 @@ ip forwarding
|
||||||
|
|
||||||
def boot(self):
|
def boot(self):
|
||||||
self.config()
|
self.config()
|
||||||
self.session.services.boot_node_services(self)
|
self.session.services.boot_services(self)
|
||||||
|
|
||||||
def bootscript(self):
|
def bootscript(self):
|
||||||
return """\
|
return """\
|
||||||
|
|
|
@ -421,7 +421,7 @@ class Experiment(object):
|
||||||
tmp.newnetif(self.net, [addr])
|
tmp.newnetif(self.net, [addr])
|
||||||
self.nodes.append(tmp)
|
self.nodes.append(tmp)
|
||||||
self.session.services.add_services(tmp, "router", "IPForward")
|
self.session.services.add_services(tmp, "router", "IPForward")
|
||||||
self.session.services.boot_node_services(tmp)
|
self.session.services.boot_services(tmp)
|
||||||
self.staticroutes(i, prefix, numnodes)
|
self.staticroutes(i, prefix, numnodes)
|
||||||
|
|
||||||
# link each node in a chain, with the previous node
|
# link each node in a chain, with the previous node
|
||||||
|
@ -463,7 +463,7 @@ class Experiment(object):
|
||||||
|
|
||||||
for i in xrange(1, numnodes + 1):
|
for i in xrange(1, numnodes + 1):
|
||||||
tmp = self.nodes[i - 1]
|
tmp = self.nodes[i - 1]
|
||||||
self.session.services.boot_node_services(tmp)
|
self.session.services.boot_services(tmp)
|
||||||
self.staticroutes(i, prefix, numnodes)
|
self.staticroutes(i, prefix, numnodes)
|
||||||
|
|
||||||
def setnodes(self):
|
def setnodes(self):
|
||||||
|
|
|
@ -10,10 +10,20 @@ class MyService(CoreService):
|
||||||
group = "Utility"
|
group = "Utility"
|
||||||
configs = ("myservice.sh",)
|
configs = ("myservice.sh",)
|
||||||
startup = ("sh myservice.sh",)
|
startup = ("sh myservice.sh",)
|
||||||
|
shutdown = ("sh myservice.sh",)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def generate_config(cls, node, filename):
|
||||||
|
return "# test file"
|
||||||
|
|
||||||
|
|
||||||
class MyService2(CoreService):
|
class MyService2(MyService):
|
||||||
name = "MyService2"
|
name = "MyService2"
|
||||||
group = "Utility"
|
group = "Utility"
|
||||||
configs = ("myservice.sh",)
|
configs = ("myservice2.sh",)
|
||||||
startup = ("sh myservice.sh",)
|
startup = ("sh myservice2.sh",)
|
||||||
|
shutdown = ("sh myservice2.sh",)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def generate_config(cls, node, filename):
|
||||||
|
return "exit 1"
|
||||||
|
|
|
@ -40,6 +40,91 @@ class ServiceF(CoreService):
|
||||||
|
|
||||||
|
|
||||||
class TestServices:
|
class TestServices:
|
||||||
|
def test_service_file(self, session):
|
||||||
|
# given
|
||||||
|
ServiceManager.add_services(_SERVICES_PATH)
|
||||||
|
my_service = ServiceManager.get("MyService")
|
||||||
|
node = session.add_node()
|
||||||
|
file_name = my_service.configs[0]
|
||||||
|
file_path = node.hostfilename(file_name)
|
||||||
|
|
||||||
|
# when
|
||||||
|
session.services.create_service_files(node, my_service)
|
||||||
|
|
||||||
|
# then
|
||||||
|
assert os.path.exists(file_path)
|
||||||
|
|
||||||
|
def test_service_startup(self, session):
|
||||||
|
# given
|
||||||
|
ServiceManager.add_services(_SERVICES_PATH)
|
||||||
|
my_service = ServiceManager.get("MyService")
|
||||||
|
node = session.add_node()
|
||||||
|
session.services.create_service_files(node, my_service)
|
||||||
|
|
||||||
|
# when
|
||||||
|
status = session.services.startup_service(node, my_service, wait=True)
|
||||||
|
|
||||||
|
# then
|
||||||
|
assert not status
|
||||||
|
|
||||||
|
def test_service_startup_error(self, session):
|
||||||
|
# given
|
||||||
|
ServiceManager.add_services(_SERVICES_PATH)
|
||||||
|
my_service = ServiceManager.get("MyService2")
|
||||||
|
node = session.add_node()
|
||||||
|
session.services.create_service_files(node, my_service)
|
||||||
|
|
||||||
|
# when
|
||||||
|
status = session.services.startup_service(node, my_service, wait=True)
|
||||||
|
|
||||||
|
# then
|
||||||
|
assert status
|
||||||
|
|
||||||
|
def test_service_stop(self, session):
|
||||||
|
# given
|
||||||
|
ServiceManager.add_services(_SERVICES_PATH)
|
||||||
|
my_service = ServiceManager.get("MyService")
|
||||||
|
node = session.add_node()
|
||||||
|
session.services.create_service_files(node, my_service)
|
||||||
|
|
||||||
|
# when
|
||||||
|
status = session.services.stop_service(node, my_service)
|
||||||
|
|
||||||
|
# then
|
||||||
|
assert not status
|
||||||
|
|
||||||
|
def test_service_stop_error(self, session):
|
||||||
|
# given
|
||||||
|
ServiceManager.add_services(_SERVICES_PATH)
|
||||||
|
my_service = ServiceManager.get("MyService2")
|
||||||
|
node = session.add_node()
|
||||||
|
session.services.create_service_files(node, my_service)
|
||||||
|
|
||||||
|
# when
|
||||||
|
status = session.services.stop_service(node, my_service)
|
||||||
|
|
||||||
|
# then
|
||||||
|
assert status
|
||||||
|
|
||||||
|
def test_service_set_file(self, session):
|
||||||
|
# given
|
||||||
|
ServiceManager.add_services(_SERVICES_PATH)
|
||||||
|
my_service = ServiceManager.get("MyService")
|
||||||
|
node = session.add_node()
|
||||||
|
file_name = my_service.configs[0]
|
||||||
|
file_path = node.hostfilename(file_name)
|
||||||
|
file_data = "# custom file"
|
||||||
|
session.services.set_service_file(node.objid, my_service.name, file_name, file_data)
|
||||||
|
custom_service = session.services.get_service(node.objid, my_service.name)
|
||||||
|
|
||||||
|
# when
|
||||||
|
session.services.create_service_files(node, custom_service)
|
||||||
|
|
||||||
|
# then
|
||||||
|
assert os.path.exists(file_path)
|
||||||
|
with open(file_path, "r") as custom_file:
|
||||||
|
assert custom_file.read() == file_data
|
||||||
|
|
||||||
def test_service_import(self):
|
def test_service_import(self):
|
||||||
"""
|
"""
|
||||||
Test importing a custom service.
|
Test importing a custom service.
|
||||||
|
@ -48,8 +133,23 @@ class TestServices:
|
||||||
assert ServiceManager.get("MyService")
|
assert ServiceManager.get("MyService")
|
||||||
assert ServiceManager.get("MyService2")
|
assert ServiceManager.get("MyService2")
|
||||||
|
|
||||||
def test_service_defaults(self):
|
def test_service_setget(self, session):
|
||||||
pass
|
# given
|
||||||
|
ServiceManager.add_services(_SERVICES_PATH)
|
||||||
|
service_name = "MyService"
|
||||||
|
my_service = ServiceManager.get(service_name)
|
||||||
|
node = session.add_node()
|
||||||
|
|
||||||
|
# when
|
||||||
|
no_service = session.services.get_service(node.objid, service_name)
|
||||||
|
default_service = session.services.get_service(node.objid, service_name, default_service=True)
|
||||||
|
session.services.set_service(node.objid, service_name)
|
||||||
|
custom_service = session.services.get_service(node.objid, service_name, default_service=True)
|
||||||
|
|
||||||
|
# then
|
||||||
|
assert no_service is None
|
||||||
|
assert default_service == my_service
|
||||||
|
assert custom_service and custom_service != my_service
|
||||||
|
|
||||||
def test_services_dependencies(self, session):
|
def test_services_dependencies(self, session):
|
||||||
# given
|
# given
|
||||||
|
@ -62,7 +162,7 @@ class TestServices:
|
||||||
]
|
]
|
||||||
|
|
||||||
# when
|
# when
|
||||||
startups = session.services.node_boot_paths(services)
|
startups = session.services.create_boot_paths(services)
|
||||||
|
|
||||||
# then
|
# then
|
||||||
assert len(startups) == 2
|
assert len(startups) == 2
|
||||||
|
@ -78,7 +178,7 @@ class TestServices:
|
||||||
|
|
||||||
# when
|
# when
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
session.services.node_boot_paths(services)
|
session.services.create_boot_paths(services)
|
||||||
|
|
||||||
def test_services_dependencies_cycle(self, session):
|
def test_services_dependencies_cycle(self, session):
|
||||||
# given
|
# given
|
||||||
|
@ -94,4 +194,4 @@ class TestServices:
|
||||||
|
|
||||||
# when
|
# when
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
session.services.node_boot_paths(services)
|
session.services.create_boot_paths(services)
|
||||||
|
|
|
@ -61,7 +61,7 @@ def wifisession(opt):
|
||||||
node.newnetif(wifi, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
|
node.newnetif(wifi, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
|
||||||
nodes.append(node)
|
nodes.append(node)
|
||||||
session.services.add_services(node, "router", services_str.split("|"))
|
session.services.add_services(node, "router", services_str.split("|"))
|
||||||
session.services.boot_node_services(node)
|
session.services.boot_services(node)
|
||||||
session.setuprandomwalkmobility(bounds=(1000.0, 750.0, 0))
|
session.setuprandomwalkmobility(bounds=(1000.0, 750.0, 0))
|
||||||
|
|
||||||
# PHY tracing
|
# PHY tracing
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue