Synergy enhancements
- serializer.py: improved serialization - manager.py: Managers are now serializable - command.py, shell.py: improved command shell by using the 'tabulate' module - service.py: listManagers, startManager, stopManager and getManagerStatus methods now use the Managers serialization - requirements.txt, test-requirements.txt: 'tabulate' module dependence added - test_synergy.py, test_manager_abstract.py: updated unit tests - setup.cfg: changed entry points Change-Id: I657af749aa3fcb32c27b516c2b9f836c5ba0c690
This commit is contained in:
parent
07c15e9c93
commit
3c33d51dd4
@ -15,3 +15,4 @@ eventlet
|
|||||||
oslo.config>=2.4.0,<3.0.0
|
oslo.config>=2.4.0,<3.0.0
|
||||||
oslo.messaging>=2.5.0,<3.0.0
|
oslo.messaging>=2.5.0,<3.0.0
|
||||||
python-dateutil
|
python-dateutil
|
||||||
|
tabulate>=0.7.2,<0.8.0
|
||||||
|
@ -26,13 +26,10 @@ scripts =
|
|||||||
|
|
||||||
[entry_points]
|
[entry_points]
|
||||||
synergy.managers =
|
synergy.managers =
|
||||||
timer = synergy.examples.timer_manager:TimerManager
|
TimerManager = synergy.examples.timer_manager:TimerManager
|
||||||
|
|
||||||
synergy.commands =
|
synergy.commands =
|
||||||
list = synergy.client.command:List
|
manager = synergy.client.command:ManagerCommand
|
||||||
status = synergy.client.command:Status
|
|
||||||
start = synergy.client.command:Start
|
|
||||||
stop = synergy.client.command:Stop
|
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
source-dir = doc/source
|
source-dir = doc/source
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import json
|
import json
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
from synergy.common import utils
|
||||||
|
from tabulate import tabulate
|
||||||
|
|
||||||
|
|
||||||
__author__ = "Lisa Zangrando"
|
__author__ = "Lisa Zangrando"
|
||||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||||
@ -31,10 +35,21 @@ class HTTPCommand(object):
|
|||||||
def configureParser(self, subparser):
|
def configureParser(self, subparser):
|
||||||
raise NotImplementedError("not implemented!")
|
raise NotImplementedError("not implemented!")
|
||||||
|
|
||||||
def log(self):
|
def objectHookHandler(self, parsed_dict):
|
||||||
raise NotImplementedError("not implemented!")
|
if "synergy_object" in parsed_dict:
|
||||||
|
synergy_object = parsed_dict["synergy_object"]
|
||||||
|
try:
|
||||||
|
objClass = utils.import_class(synergy_object["name"])
|
||||||
|
|
||||||
def sendRequest(self, synergy_url, payload=None):
|
objInstance = objClass()
|
||||||
|
return objInstance.deserialize(parsed_dict)
|
||||||
|
except Exception as ex:
|
||||||
|
print(ex)
|
||||||
|
raise ex
|
||||||
|
else:
|
||||||
|
return parsed_dict
|
||||||
|
|
||||||
|
def execute(self, synergy_url, payload=None):
|
||||||
request = requests.get(synergy_url, params=payload)
|
request = requests.get(synergy_url, params=payload)
|
||||||
|
|
||||||
if request.status_code != requests.codes.ok:
|
if request.status_code != requests.codes.ok:
|
||||||
@ -44,180 +59,98 @@ class HTTPCommand(object):
|
|||||||
|
|
||||||
self.results = request.json()
|
self.results = request.json()
|
||||||
|
|
||||||
return request
|
try:
|
||||||
|
return json.loads(request.text, object_hook=self.objectHookHandler)
|
||||||
|
except Exception:
|
||||||
|
return request.json()
|
||||||
|
|
||||||
def getResults(self):
|
def getResults(self):
|
||||||
return self.results
|
return self.results
|
||||||
|
|
||||||
|
|
||||||
class List(HTTPCommand):
|
class ManagerCommand(HTTPCommand):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(List, self).__init__("list")
|
super(ManagerCommand, self).__init__("Manager")
|
||||||
|
|
||||||
def configureParser(self, subparser):
|
def configureParser(self, subparser):
|
||||||
subparser.add_parser("list", add_help=True, help="list the managers")
|
manager_parser = subparser.add_parser('manager')
|
||||||
|
manager_parsers = manager_parser.add_subparsers(dest="command")
|
||||||
|
|
||||||
def sendRequest(self, synergy_url, args=None):
|
manager_parsers.add_parser(
|
||||||
super(List, self).sendRequest(synergy_url + "/synergy/list")
|
"list", add_help=True, help="list the managers")
|
||||||
|
|
||||||
def log(self):
|
status_parser = manager_parsers.add_parser(
|
||||||
results = self.getResults()
|
"status", add_help=True, help="show the managers status")
|
||||||
|
|
||||||
max_project_id = max(len(max(results, key=len)), len("manager"))
|
status_parser.add_argument(
|
||||||
separator_str = "-" * (max_project_id + 4) + "\n"
|
"manager", nargs='*', help="the managers list")
|
||||||
format_str = "| {0:%ss} |\n" % (max_project_id)
|
|
||||||
|
|
||||||
msg = separator_str
|
start_parser = manager_parsers.add_parser(
|
||||||
msg += format_str.format("manager")
|
"start", add_help=True, help="start the manager")
|
||||||
msg += separator_str
|
|
||||||
|
|
||||||
for manager in results:
|
start_parser.add_argument(
|
||||||
msg += format_str.format(manager)
|
"manager", nargs='+', help="the managers list")
|
||||||
|
|
||||||
msg += separator_str
|
stop_parser = manager_parsers.add_parser(
|
||||||
print(msg)
|
"stop", add_help=True, help="stop the manager")
|
||||||
|
|
||||||
|
stop_parser.add_argument(
|
||||||
|
"manager", nargs='+', help="the managers list")
|
||||||
|
|
||||||
|
def execute(self, synergy_url, args=None):
|
||||||
|
table = []
|
||||||
|
headers = []
|
||||||
|
url = synergy_url
|
||||||
|
|
||||||
|
if args.command == "list":
|
||||||
|
headers.append("manager")
|
||||||
|
url += "/synergy/list"
|
||||||
|
|
||||||
|
managers = super(ManagerCommand, self).execute(url)
|
||||||
|
|
||||||
|
for manager in managers:
|
||||||
|
table.append([manager.getName()])
|
||||||
|
else:
|
||||||
|
headers.append("manager")
|
||||||
|
headers.append("status")
|
||||||
|
headers.append("rate (min)")
|
||||||
|
url += "/synergy/" + args.command
|
||||||
|
|
||||||
|
managers = super(ManagerCommand, self).execute(
|
||||||
|
url, {"manager": args.manager})
|
||||||
|
|
||||||
|
if args.command == "status":
|
||||||
|
for manager in managers:
|
||||||
|
table.append([manager.getName(),
|
||||||
|
manager.getStatus(),
|
||||||
|
manager.getRate()])
|
||||||
|
else:
|
||||||
|
headers.append("details")
|
||||||
|
|
||||||
|
for manager in managers:
|
||||||
|
msg = manager.get("message")
|
||||||
|
|
||||||
|
table.append([manager.getName(),
|
||||||
|
manager.getStatus() + " (%s)" % msg,
|
||||||
|
manager.getRate()])
|
||||||
|
|
||||||
|
print(tabulate(table, headers, tablefmt="fancy_grid"))
|
||||||
|
|
||||||
|
|
||||||
class Start(HTTPCommand):
|
class ExecuteCommand(HTTPCommand):
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super(Start, self).__init__("start")
|
|
||||||
|
|
||||||
def configureParser(self, subparser):
|
|
||||||
parser = subparser.add_parser("start",
|
|
||||||
add_help=True,
|
|
||||||
help="start the managers")
|
|
||||||
|
|
||||||
parser.add_argument("manager", help="the manager to be started")
|
|
||||||
|
|
||||||
def sendRequest(self, synergy_url, args):
|
|
||||||
super(Start, self).sendRequest(synergy_url + "/synergy/start",
|
|
||||||
{"manager": args.manager})
|
|
||||||
|
|
||||||
def log(self):
|
|
||||||
results = self.getResults()
|
|
||||||
|
|
||||||
max_manager = max(len(max(results.keys(), key=len)), len("manager"))
|
|
||||||
|
|
||||||
max_status = len("status")
|
|
||||||
max_msg = len("message")
|
|
||||||
|
|
||||||
for result in results.values():
|
|
||||||
max_status = max(len(str(result["status"])), max_status)
|
|
||||||
max_msg = max(len(str(result["message"])), max_msg)
|
|
||||||
|
|
||||||
separator_str = "-" * (max_manager + max_status + max_msg + 10) + "\n"
|
|
||||||
|
|
||||||
format_str = "| {0:%ss} | {1:%ss} | {2:%ss} |\n" % (max_manager,
|
|
||||||
max_status,
|
|
||||||
max_msg)
|
|
||||||
|
|
||||||
msg = separator_str
|
|
||||||
msg += format_str.format("manager", "status", "message")
|
|
||||||
msg += separator_str
|
|
||||||
|
|
||||||
for manager, values in results.items():
|
|
||||||
msg += format_str.format(manager,
|
|
||||||
values["status"],
|
|
||||||
values["message"])
|
|
||||||
|
|
||||||
msg += separator_str
|
|
||||||
print(msg)
|
|
||||||
|
|
||||||
|
|
||||||
class Stop(HTTPCommand):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super(Stop, self).__init__("stop")
|
|
||||||
|
|
||||||
def configureParser(self, subparser):
|
|
||||||
parser = subparser.add_parser("stop",
|
|
||||||
add_help=True,
|
|
||||||
help="stop the managers")
|
|
||||||
|
|
||||||
parser.add_argument("manager", help="the manager to be stopped")
|
|
||||||
|
|
||||||
def sendRequest(self, synergy_url, args):
|
|
||||||
super(Stop, self).sendRequest(synergy_url + "/synergy/stop",
|
|
||||||
{"manager": args.manager})
|
|
||||||
|
|
||||||
def log(self):
|
|
||||||
results = self.getResults()
|
|
||||||
|
|
||||||
max_manager = max(len(max(results.keys(), key=len)), len("manager"))
|
|
||||||
max_status = len("status")
|
|
||||||
max_msg = len("message")
|
|
||||||
|
|
||||||
for result in results.values():
|
|
||||||
max_status = max(len(str(result["status"])), max_status)
|
|
||||||
max_msg = max(len(str(result["message"])), max_msg)
|
|
||||||
|
|
||||||
separator_str = "-" * (max_manager + max_status + max_msg + 10) + "\n"
|
|
||||||
format_str = "| {0:%ss} | {1:%ss} | {2:%ss} |\n" % (max_manager,
|
|
||||||
max_status,
|
|
||||||
max_msg)
|
|
||||||
|
|
||||||
msg = separator_str
|
|
||||||
msg += format_str.format("manager", "status", "message")
|
|
||||||
msg += separator_str
|
|
||||||
|
|
||||||
for manager, values in results.items():
|
|
||||||
msg += format_str.format(manager,
|
|
||||||
values["status"],
|
|
||||||
values["message"])
|
|
||||||
|
|
||||||
msg += separator_str
|
|
||||||
print(msg)
|
|
||||||
|
|
||||||
|
|
||||||
class Status(HTTPCommand):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super(Status, self).__init__("status")
|
|
||||||
|
|
||||||
def configureParser(self, subparser):
|
|
||||||
parser = subparser.add_parser("status",
|
|
||||||
add_help=True,
|
|
||||||
help="retrieve the manager's status")
|
|
||||||
|
|
||||||
parser.add_argument("manager", nargs='*', help="the managers list")
|
|
||||||
|
|
||||||
def sendRequest(self, synergy_url, args):
|
|
||||||
super(Status, self).sendRequest(synergy_url + "/synergy/status",
|
|
||||||
{"manager": args.manager})
|
|
||||||
|
|
||||||
def log(self):
|
|
||||||
results = self.getResults()
|
|
||||||
|
|
||||||
max_project_id = max(len(max(results.keys(), key=len)), len("manager"))
|
|
||||||
max_value = max(len(max(results.values(), key=len)), len("status"))
|
|
||||||
separator_str = "-" * (max_project_id + max_value + 7) + "\n"
|
|
||||||
format_str = "| {0:%ss} | {1:%ss} |\n" % (max_project_id, max_value)
|
|
||||||
|
|
||||||
msg = separator_str
|
|
||||||
msg += format_str.format("manager", "status")
|
|
||||||
msg += separator_str
|
|
||||||
|
|
||||||
for manager, status in results.items():
|
|
||||||
msg += format_str.format(manager, status)
|
|
||||||
|
|
||||||
msg += separator_str
|
|
||||||
print(msg)
|
|
||||||
|
|
||||||
|
|
||||||
class Execute(HTTPCommand):
|
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
super(Execute, self).__init__(name)
|
super(ExecuteCommand, self).__init__(name)
|
||||||
|
|
||||||
def sendRequest(self, synergy_url, manager, command, args=None):
|
def execute(self, synergy_url, manager, command, args=None):
|
||||||
if args is None:
|
if args is None:
|
||||||
args = {}
|
args = {}
|
||||||
|
|
||||||
|
url = synergy_url + "/synergy/execute"
|
||||||
|
|
||||||
payload = {"manager": manager,
|
payload = {"manager": manager,
|
||||||
"command": command,
|
"command": command,
|
||||||
"args": json.dumps(args)}
|
"args": json.dumps(args)}
|
||||||
|
|
||||||
super(Execute, self).sendRequest(synergy_url + "/synergy/execute",
|
return super(ExecuteCommand, self).execute(url, payload)
|
||||||
payload)
|
|
||||||
|
@ -175,8 +175,8 @@ def main():
|
|||||||
if command_name not in commands:
|
if command_name not in commands:
|
||||||
print("command %r not found!" % command_name)
|
print("command %r not found!" % command_name)
|
||||||
|
|
||||||
commands[command_name].sendRequest(synergy_url, args)
|
commands[command_name].execute(synergy_url, args)
|
||||||
commands[command_name].log()
|
# commands[command_name].log()
|
||||||
except KeyboardInterrupt as e:
|
except KeyboardInterrupt as e:
|
||||||
print("Shutting down synergyclient")
|
print("Shutting down synergyclient")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
from serializer import SynergyObject
|
||||||
from threading import Condition
|
from threading import Condition
|
||||||
from threading import Event
|
from threading import Event
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
|
|
||||||
__author__ = "Lisa Zangrando"
|
__author__ = "Lisa Zangrando"
|
||||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||||
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
__copyright__ = """Copyright (c) 2015 INFN - INDIGO-DataCloud
|
||||||
@ -21,18 +23,17 @@ See the License for the specific language governing
|
|||||||
permissions and limitations under the License."""
|
permissions and limitations under the License."""
|
||||||
|
|
||||||
|
|
||||||
class Manager(Thread):
|
class Manager(SynergyObject, Thread):
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name=None):
|
||||||
super(Manager, self).__init__()
|
super(Manager, self).__init__()
|
||||||
self.setDaemon(True)
|
|
||||||
self.stop_event = Event()
|
|
||||||
self.config_opts = []
|
|
||||||
self.condition = Condition()
|
self.condition = Condition()
|
||||||
self.name = name
|
self.stop_event = Event()
|
||||||
self.status = "CREATED"
|
self.setDaemon(True)
|
||||||
self.autostart = False
|
self.setName(name)
|
||||||
self.rate = -1
|
self.setStatus("CREATED")
|
||||||
|
self.setRate(-1)
|
||||||
|
self.config_opts = []
|
||||||
self.paused = True # start out paused
|
self.paused = True # start out paused
|
||||||
self.managers = {}
|
self.managers = {}
|
||||||
|
|
||||||
@ -61,24 +62,30 @@ class Manager(Thread):
|
|||||||
if manager.getName() != manager_name:
|
if manager.getName() != manager_name:
|
||||||
manager.doOnEvent(event_type, *args, **kargs)
|
manager.doOnEvent(event_type, *args, **kargs)
|
||||||
|
|
||||||
def getName(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def getOptions(self):
|
def getOptions(self):
|
||||||
return self.config_opts
|
return self.config_opts
|
||||||
|
|
||||||
|
def getStatus(self):
|
||||||
|
return self.get("status")
|
||||||
|
|
||||||
|
def setStatus(self, status):
|
||||||
|
with self.condition:
|
||||||
|
self.set("status", status)
|
||||||
|
|
||||||
|
self.condition.notifyAll()
|
||||||
|
|
||||||
def isAutoStart(self):
|
def isAutoStart(self):
|
||||||
return self.autostart
|
return self.get("autostart")
|
||||||
|
|
||||||
def setAutoStart(self, autostart):
|
def setAutoStart(self, autostart):
|
||||||
self.autostart = autostart
|
self.set("autostart", autostart)
|
||||||
self.paused = not self.autostart
|
self.paused = not autostart
|
||||||
|
|
||||||
def getRate(self):
|
def getRate(self):
|
||||||
return self.rate
|
return self.get("rate")
|
||||||
|
|
||||||
def setRate(self, rate):
|
def setRate(self, rate):
|
||||||
self.rate = rate
|
self.set("rate", rate)
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
"""Manager initialization
|
"""Manager initialization
|
||||||
@ -93,15 +100,6 @@ class Manager(Thread):
|
|||||||
def destroy(self):
|
def destroy(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def getStatus(self):
|
|
||||||
return self.status
|
|
||||||
|
|
||||||
def setStatus(self, status):
|
|
||||||
with self.condition:
|
|
||||||
self.status = status
|
|
||||||
|
|
||||||
self.condition.notifyAll()
|
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
if self.isAlive():
|
if self.isAlive():
|
||||||
# set event to signal thread to terminate
|
# set event to signal thread to terminate
|
||||||
@ -124,13 +122,13 @@ class Manager(Thread):
|
|||||||
while not self.stop_event.isSet():
|
while not self.stop_event.isSet():
|
||||||
with self.condition:
|
with self.condition:
|
||||||
if self.paused:
|
if self.paused:
|
||||||
self.status = "ACTIVE"
|
self.setStatus("ACTIVE")
|
||||||
self.condition.wait()
|
self.condition.wait()
|
||||||
else:
|
else:
|
||||||
self.status = "RUNNING"
|
self.setStatus("RUNNING")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.task()
|
self.task()
|
||||||
self.condition.wait(self.rate * 60)
|
self.condition.wait(self.getRate() * 60)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
print("task %r: %s" % (self.name, ex))
|
print("task %r: %s" % (self.getName(), ex))
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
try:
|
import datetime
|
||||||
import oslo_messaging
|
from json import JSONEncoder
|
||||||
except ImportError:
|
|
||||||
import oslo.messaging as oslo_messaging
|
|
||||||
|
|
||||||
from synergy.common import context as ctx
|
|
||||||
from synergy.common import utils
|
from synergy.common import utils
|
||||||
|
|
||||||
|
|
||||||
@ -35,128 +31,136 @@ class SynergyObject(object):
|
|||||||
necessary "get" classmethod routines as well as "set" object methods
|
necessary "get" classmethod routines as well as "set" object methods
|
||||||
as appropriate.
|
as appropriate.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
VERSION = "1.0"
|
VERSION = "1.0"
|
||||||
|
|
||||||
def __init__(self, name=None):
|
def __init__(self):
|
||||||
|
super(SynergyObject, self).__init__()
|
||||||
|
|
||||||
self.attributes = {}
|
self.attributes = {}
|
||||||
|
|
||||||
if name:
|
def getId(self):
|
||||||
self.attributes["name"] = name
|
return self.get("id")
|
||||||
|
|
||||||
|
def setId(self, id):
|
||||||
|
self.set("id", id)
|
||||||
|
|
||||||
def getName(self):
|
def getName(self):
|
||||||
return self.attributes["name"]
|
return self.get("name")
|
||||||
|
|
||||||
def setName(self, name):
|
def setName(self, name):
|
||||||
self.attributes["name"] = name
|
self.set("name", name)
|
||||||
|
|
||||||
def get(self, field=None):
|
def get(self, field):
|
||||||
return self.attributes.get(field, None)
|
return self.attributes.get(field, None)
|
||||||
|
|
||||||
def set(self, field, value):
|
def set(self, field, value):
|
||||||
self.attributes[field] = value
|
if isinstance(value, unicode):
|
||||||
|
self.attributes[field] = str(value)
|
||||||
def setContext(self, context):
|
else:
|
||||||
self.context = context
|
self.attributes[field] = value
|
||||||
|
|
||||||
def setAttributes(self, attributes):
|
def setAttributes(self, attributes):
|
||||||
if attributes:
|
if attributes:
|
||||||
self.attributes = attributes
|
self.attributes = attributes
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def deserialize(cls, context, entity):
|
def deserialize(cls, entity):
|
||||||
if "synergy_object.namespace" not in entity:
|
if "synergy_object" not in entity:
|
||||||
raise Exception("synergy_object.namespace nof defined!")
|
raise Exception("it seems not a Synergy object!")
|
||||||
|
|
||||||
if "synergy_object.name" not in entity:
|
synergy_object = entity["synergy_object"]
|
||||||
raise Exception("synergy_object.name nof defined!")
|
|
||||||
|
|
||||||
if "synergy_object.version" not in entity:
|
if "namespace" not in synergy_object:
|
||||||
raise Exception("synergy_object.version nof defined!")
|
raise Exception("synergy_object.namespace not defined!")
|
||||||
|
|
||||||
if entity["synergy_object.namespace"] != 'synergy':
|
if "name" not in synergy_object:
|
||||||
|
raise Exception("synergy_object.name not defined!")
|
||||||
|
|
||||||
|
if "version" not in synergy_object:
|
||||||
|
raise Exception("synergy_object.version mismatch!")
|
||||||
|
|
||||||
|
if synergy_object["version"] != cls.VERSION:
|
||||||
|
raise Exception("synergy_object.version mis!")
|
||||||
|
|
||||||
|
if synergy_object["namespace"] != "synergy":
|
||||||
raise Exception("unsupported object objtype='%s.%s"
|
raise Exception("unsupported object objtype='%s.%s"
|
||||||
% (entity["synergy_object.namespace"],
|
% (synergy_object["namespace"],
|
||||||
entity["synergy_object.name"]))
|
synergy_object["name"]))
|
||||||
|
|
||||||
objName = entity['synergy_object.name']
|
objInstance = None
|
||||||
# objVer = entity['synergy_object.version']
|
|
||||||
objClass = utils.import_class(objName)
|
|
||||||
|
|
||||||
# objInstance = objClass(context=context, data=entity)
|
try:
|
||||||
|
objName = synergy_object["name"]
|
||||||
|
# objVer = synergy_object['version']
|
||||||
|
objClass = utils.import_class(objName)
|
||||||
|
objInstance = objClass()
|
||||||
|
except Exception as ex:
|
||||||
|
print(ex)
|
||||||
|
raise Exception("error on deserializing the object %r: %s"
|
||||||
|
% (objName, ex))
|
||||||
|
|
||||||
objInstance = objClass(name=None)
|
del entity["synergy_object"]
|
||||||
objInstance.setContext(context)
|
|
||||||
objInstance.setAttributes(entity)
|
for key, value in entity.items():
|
||||||
|
if isinstance(value, dict):
|
||||||
|
if "synergy_object" in value:
|
||||||
|
objInstance.set(key, SynergyObject.deserialize(value))
|
||||||
|
else:
|
||||||
|
objInstance.set(key, value)
|
||||||
|
elif isinstance(value, list):
|
||||||
|
l = []
|
||||||
|
|
||||||
|
objInstance.set(key, l)
|
||||||
|
|
||||||
|
for item in value:
|
||||||
|
if isinstance(item, dict) and "synergy_object" in item:
|
||||||
|
l.append(SynergyObject.deserialize(item))
|
||||||
|
else:
|
||||||
|
l.append(item)
|
||||||
|
else:
|
||||||
|
objInstance.set(key, value)
|
||||||
|
|
||||||
return objInstance
|
return objInstance
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
name = self.__class__.__module__ + "." + self.__class__.__name__
|
name = self.__class__.__module__ + "." + self.__class__.__name__
|
||||||
self.attributes['synergy_object.name'] = name
|
|
||||||
self.attributes['synergy_object.version'] = self.VERSION
|
|
||||||
self.attributes['synergy_object.namespace'] = 'synergy'
|
|
||||||
|
|
||||||
return self.attributes
|
result = {"synergy_object": {}}
|
||||||
"""
|
result["synergy_object"]["name"] = name
|
||||||
def log(self):
|
result["synergy_object"]["version"] = self.VERSION
|
||||||
|
result["synergy_object"]["namespace"] = "synergy"
|
||||||
|
|
||||||
for key, value in self.attributes.items():
|
for key, value in self.attributes.items():
|
||||||
LOG.info("%s = %s" % (key, value))
|
if isinstance(value, SynergyObject):
|
||||||
"""
|
result[key] = value.serialize()
|
||||||
|
elif isinstance(value, dict):
|
||||||
|
result[key] = {}
|
||||||
|
|
||||||
|
for k, v in value.items():
|
||||||
|
if isinstance(v, SynergyObject):
|
||||||
|
result[key][k] = v.serialize()
|
||||||
|
else:
|
||||||
|
result[key][k] = v
|
||||||
|
elif isinstance(value, list):
|
||||||
|
result[key] = []
|
||||||
|
|
||||||
class SynergySerializer(oslo_messaging.Serializer):
|
for item in value:
|
||||||
def __init__(self):
|
if isinstance(item, SynergyObject):
|
||||||
super(SynergySerializer, self).__init__()
|
result[key].append(item.serialize())
|
||||||
|
else:
|
||||||
def serialize_entity(self, context, entity):
|
result[key].append(item)
|
||||||
if not entity:
|
elif isinstance(value, datetime.datetime):
|
||||||
return entity
|
result[key] = value.isoformat()
|
||||||
|
|
||||||
if isinstance(entity, SynergyObject):
|
|
||||||
entity = entity.serialize()
|
|
||||||
elif isinstance(entity, dict):
|
|
||||||
result = {}
|
|
||||||
|
|
||||||
for key, value in entity.items():
|
|
||||||
result[key] = self.serialize_entity(context, value)
|
|
||||||
|
|
||||||
entity = result
|
|
||||||
|
|
||||||
return entity
|
|
||||||
|
|
||||||
def deserialize_entity(self, context, entity):
|
|
||||||
if isinstance(entity, dict):
|
|
||||||
if 'synergy_object.name' in entity:
|
|
||||||
entity = SynergyObject.deserialize(context, entity)
|
|
||||||
else:
|
else:
|
||||||
result = {}
|
result[key] = value
|
||||||
|
|
||||||
for key, value in entity.items():
|
return result
|
||||||
result[key] = self.deserialize_entity(context, value)
|
|
||||||
|
|
||||||
entity = result
|
|
||||||
|
|
||||||
return entity
|
|
||||||
|
|
||||||
def serialize_context(self, context):
|
|
||||||
return context.toDict()
|
|
||||||
|
|
||||||
def deserialize_context(self, context):
|
|
||||||
return ctx.RequestContext.fromDict(context)
|
|
||||||
|
|
||||||
|
|
||||||
class RequestContextSerializer(oslo_messaging.Serializer):
|
class SynergyEncoder(JSONEncoder):
|
||||||
def __init__(self):
|
def default(self, obj):
|
||||||
pass
|
if isinstance(obj, SynergyObject):
|
||||||
|
return obj.serialize()
|
||||||
def serialize_entity(self, context, entity):
|
else:
|
||||||
return entity
|
return JSONEncoder.default(self, obj)
|
||||||
|
|
||||||
def deserialize_entity(self, context, entity):
|
|
||||||
return entity
|
|
||||||
|
|
||||||
def serialize_context(self, context):
|
|
||||||
return context.toDict()
|
|
||||||
|
|
||||||
def deserialize_context(self, context):
|
|
||||||
return ctx.RequestContext.fromDict(context)
|
|
||||||
|
@ -15,8 +15,11 @@ except ImportError:
|
|||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
|
|
||||||
from synergy.common import config
|
from synergy.common import config
|
||||||
from synergy.common import service
|
from synergy.common.manager import Manager
|
||||||
from synergy.common import wsgi
|
from synergy.common.serializer import SynergyEncoder
|
||||||
|
from synergy.common.service import Service
|
||||||
|
from synergy.common.wsgi import Server
|
||||||
|
|
||||||
|
|
||||||
__author__ = "Lisa Zangrando"
|
__author__ = "Lisa Zangrando"
|
||||||
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
__email__ = "lisa.zangrando[AT]pd.infn.it"
|
||||||
@ -76,7 +79,7 @@ def setLogger(name):
|
|||||||
logger.addHandler(handler)
|
logger.addHandler(handler)
|
||||||
|
|
||||||
|
|
||||||
class Synergy(service.Service):
|
class Synergy(Service):
|
||||||
"""Service object for binaries running on hosts.
|
"""Service object for binaries running on hosts.
|
||||||
|
|
||||||
A service takes a manager and enables rpc by listening to queues based
|
A service takes a manager and enables rpc by listening to queues based
|
||||||
@ -98,8 +101,7 @@ class Synergy(service.Service):
|
|||||||
manager_class = entry.load()
|
manager_class = entry.load()
|
||||||
|
|
||||||
manager_obj = manager_class(*args, **kwargs)
|
manager_obj = manager_class(*args, **kwargs)
|
||||||
LOG.info("manager instance %r created!", entry.name)
|
manager_obj.setName(entry.name)
|
||||||
|
|
||||||
manager_obj.setAutoStart(CONF.get(entry.name).autostart)
|
manager_obj.setAutoStart(CONF.get(entry.name).autostart)
|
||||||
manager_obj.setRate(CONF.get(entry.name).rate)
|
manager_obj.setRate(CONF.get(entry.name).rate)
|
||||||
|
|
||||||
@ -137,14 +139,18 @@ class Synergy(service.Service):
|
|||||||
result = []
|
result = []
|
||||||
|
|
||||||
for name, manager in self.managers.items():
|
for name, manager in self.managers.items():
|
||||||
result.append(name)
|
m = Manager(name)
|
||||||
|
m.setStatus(manager.getStatus())
|
||||||
|
m.setRate(manager.getRate())
|
||||||
|
|
||||||
|
result.append(m)
|
||||||
|
|
||||||
start_response("200 OK", [("Content-Type", "text/html")])
|
start_response("200 OK", [("Content-Type", "text/html")])
|
||||||
return ["%s" % json.dumps(result)]
|
return ["%s" % json.dumps(result, cls=SynergyEncoder)]
|
||||||
|
|
||||||
def getManagerStatus(self, environ, start_response):
|
def getManagerStatus(self, environ, start_response):
|
||||||
manager_list = None
|
manager_list = None
|
||||||
result = {}
|
result = []
|
||||||
|
|
||||||
query = environ.get("QUERY_STRING", None)
|
query = environ.get("QUERY_STRING", None)
|
||||||
|
|
||||||
@ -165,14 +171,20 @@ class Synergy(service.Service):
|
|||||||
manager_name = escape(manager_name)
|
manager_name = escape(manager_name)
|
||||||
|
|
||||||
if manager_name in self.managers:
|
if manager_name in self.managers:
|
||||||
result[manager_name] = self.managers[manager_name].getStatus()
|
manager = self.managers[manager_name]
|
||||||
|
|
||||||
|
m = Manager(manager_name)
|
||||||
|
m.setStatus(manager.getStatus())
|
||||||
|
m.setRate(manager.getRate())
|
||||||
|
|
||||||
|
result.append(m)
|
||||||
|
|
||||||
if len(manager_list) == 1 and len(result) == 0:
|
if len(manager_list) == 1 and len(result) == 0:
|
||||||
start_response("404 NOT FOUND", [("Content-Type", "text/plain")])
|
start_response("404 NOT FOUND", [("Content-Type", "text/plain")])
|
||||||
return ["manager %r not found!" % manager_list[0]]
|
return ["manager %r not found!" % manager_list[0]]
|
||||||
|
|
||||||
start_response("200 OK", [("Content-Type", "text/html")])
|
start_response("200 OK", [("Content-Type", "text/html")])
|
||||||
return ["%s" % json.dumps(result)]
|
return ["%s" % json.dumps(result, cls=SynergyEncoder)]
|
||||||
|
|
||||||
def executeCommand(self, environ, start_response):
|
def executeCommand(self, environ, start_response):
|
||||||
manager_name = None
|
manager_name = None
|
||||||
@ -215,16 +227,8 @@ class Synergy(service.Service):
|
|||||||
try:
|
try:
|
||||||
result = manager.execute(command=command, **manager_args)
|
result = manager.execute(command=command, **manager_args)
|
||||||
|
|
||||||
if not isinstance(result, dict):
|
|
||||||
try:
|
|
||||||
result = result.toDict()
|
|
||||||
except Exception:
|
|
||||||
result = result.__dict__
|
|
||||||
|
|
||||||
LOG.debug("execute command: result=%s" % result)
|
|
||||||
|
|
||||||
start_response("200 OK", [("Content-Type", "text/html")])
|
start_response("200 OK", [("Content-Type", "text/html")])
|
||||||
return ["%s" % json.dumps(result)]
|
return ["%s" % json.dumps(result, cls=SynergyEncoder)]
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
LOG.debug("execute command: error=%s" % ex)
|
LOG.debug("execute command: error=%s" % ex)
|
||||||
start_response("500 INTERNAL SERVER ERROR",
|
start_response("500 INTERNAL SERVER ERROR",
|
||||||
@ -233,7 +237,7 @@ class Synergy(service.Service):
|
|||||||
|
|
||||||
def startManager(self, environ, start_response):
|
def startManager(self, environ, start_response):
|
||||||
manager_list = None
|
manager_list = None
|
||||||
result = {}
|
result = []
|
||||||
|
|
||||||
query = environ.get("QUERY_STRING", None)
|
query = environ.get("QUERY_STRING", None)
|
||||||
|
|
||||||
@ -258,9 +262,11 @@ class Synergy(service.Service):
|
|||||||
if manager_name not in self.managers:
|
if manager_name not in self.managers:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
result[manager_name] = {}
|
|
||||||
|
|
||||||
manager = self.managers[manager_name]
|
manager = self.managers[manager_name]
|
||||||
|
m = Manager(manager_name)
|
||||||
|
m.setRate(manager.getRate())
|
||||||
|
|
||||||
|
result.append(m)
|
||||||
|
|
||||||
if manager.getStatus() == "ACTIVE":
|
if manager.getStatus() == "ACTIVE":
|
||||||
LOG.info("starting the %r manager" % (manager_name))
|
LOG.info("starting the %r manager" % (manager_name))
|
||||||
@ -270,25 +276,25 @@ class Synergy(service.Service):
|
|||||||
LOG.info("%r manager started! (rate=%s min)"
|
LOG.info("%r manager started! (rate=%s min)"
|
||||||
% (manager_name, manager.getRate()))
|
% (manager_name, manager.getRate()))
|
||||||
|
|
||||||
result[manager_name]["status"] = "RUNNING"
|
m.setStatus("RUNNING")
|
||||||
result[manager_name]["message"] = "started successfully"
|
m.set("message", "started successfully")
|
||||||
elif manager.getStatus() == "RUNNING":
|
elif manager.getStatus() == "RUNNING":
|
||||||
result[manager_name]["status"] = "RUNNING"
|
m.setStatus("RUNNING")
|
||||||
result[manager_name]["message"] = "WARN: already started"
|
m.set("message", "WARN: already started")
|
||||||
elif manager.getStatus() == "ERROR":
|
elif manager.getStatus() == "ERROR":
|
||||||
result[manager_name]["status"] = "ERROR"
|
m.setStatus("ERROR")
|
||||||
result[manager_name]["message"] = "wrong state"
|
m.set("message", "wrong state")
|
||||||
|
|
||||||
if len(manager_list) == 1 and len(result) == 0:
|
if len(manager_list) == 1 and len(result) == 0:
|
||||||
start_response("404 NOT FOUND", [("Content-Type", "text/plain")])
|
start_response("404 NOT FOUND", [("Content-Type", "text/plain")])
|
||||||
return ["manager %r not found!" % manager_list[0]]
|
return ["manager %r not found!" % manager_list[0]]
|
||||||
|
|
||||||
start_response("200 OK", [("Content-Type", "text/html")])
|
start_response("200 OK", [("Content-Type", "text/html")])
|
||||||
return ["%s" % json.dumps(result)]
|
return ["%s" % json.dumps(result, cls=SynergyEncoder)]
|
||||||
|
|
||||||
def stopManager(self, environ, start_response):
|
def stopManager(self, environ, start_response):
|
||||||
manager_list = None
|
manager_list = None
|
||||||
result = {}
|
result = []
|
||||||
|
|
||||||
query = environ.get("QUERY_STRING", None)
|
query = environ.get("QUERY_STRING", None)
|
||||||
|
|
||||||
@ -313,10 +319,13 @@ class Synergy(service.Service):
|
|||||||
if manager_name not in self.managers:
|
if manager_name not in self.managers:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
result[manager_name] = {}
|
|
||||||
|
|
||||||
manager = self.managers[manager_name]
|
manager = self.managers[manager_name]
|
||||||
|
|
||||||
|
m = Manager(manager_name)
|
||||||
|
m.setRate(manager.getRate())
|
||||||
|
|
||||||
|
result.append(m)
|
||||||
|
|
||||||
if manager.getStatus() == "RUNNING":
|
if manager.getStatus() == "RUNNING":
|
||||||
LOG.info("stopping the %r manager" % (manager_name))
|
LOG.info("stopping the %r manager" % (manager_name))
|
||||||
|
|
||||||
@ -324,21 +333,21 @@ class Synergy(service.Service):
|
|||||||
|
|
||||||
LOG.info("%r manager stopped!" % (manager_name))
|
LOG.info("%r manager stopped!" % (manager_name))
|
||||||
|
|
||||||
result[manager_name]["status"] = "ACTIVE"
|
m.setStatus("ACTIVE")
|
||||||
result[manager_name]["message"] = "stopped successfully"
|
m.set("message", "stopped successfully")
|
||||||
elif manager.getStatus() == "ACTIVE":
|
elif manager.getStatus() == "ACTIVE":
|
||||||
result[manager_name]["status"] = "ACTIVE"
|
m.setStatus("ACTIVE")
|
||||||
result[manager_name]["message"] = "WARN: already stopped"
|
m.set("message", "WARN: already stopped")
|
||||||
elif manager.getStatus() == "ERROR":
|
elif manager.getStatus() == "ERROR":
|
||||||
result[manager_name]["status"] = "ERROR"
|
m.setStatus("ERROR")
|
||||||
result[manager_name]["message"] = "wrong state"
|
m.set("message", "wrong state")
|
||||||
|
|
||||||
if len(manager_list) == 1 and len(result) == 0:
|
if len(manager_list) == 1 and len(result) == 0:
|
||||||
start_response("404 NOT FOUND", [("Content-Type", "text/plain")])
|
start_response("404 NOT FOUND", [("Content-Type", "text/plain")])
|
||||||
return ["manager %r not found!" % manager_list[0]]
|
return ["manager %r not found!" % manager_list[0]]
|
||||||
|
|
||||||
start_response("200 OK", [("Content-Type", "text/html")])
|
start_response("200 OK", [("Content-Type", "text/html")])
|
||||||
return ["%s" % json.dumps(result)]
|
return ["%s" % json.dumps(result, cls=SynergyEncoder)]
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.model_disconnected = False
|
self.model_disconnected = False
|
||||||
@ -357,7 +366,7 @@ class Synergy(service.Service):
|
|||||||
manager.setStatus("ERROR")
|
manager.setStatus("ERROR")
|
||||||
raise ex
|
raise ex
|
||||||
|
|
||||||
self.wsgi_server = wsgi.Server(
|
self.wsgi_server = Server(
|
||||||
name="WSGI server",
|
name="WSGI server",
|
||||||
host_name=CONF.WSGI.host,
|
host_name=CONF.WSGI.host,
|
||||||
host_port=CONF.WSGI.port,
|
host_port=CONF.WSGI.port,
|
||||||
|
@ -23,6 +23,7 @@ import sys
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from mock import Mock
|
from mock import Mock
|
||||||
|
from synergy.common import utils
|
||||||
from synergy.service import Synergy
|
from synergy.service import Synergy
|
||||||
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
@ -47,6 +48,21 @@ def getLogger(name):
|
|||||||
return logger
|
return logger
|
||||||
|
|
||||||
|
|
||||||
|
def objectHookHandler(parsed_dict):
|
||||||
|
if "synergy_object" in parsed_dict:
|
||||||
|
synergy_object = parsed_dict["synergy_object"]
|
||||||
|
try:
|
||||||
|
objClass = utils.import_class(synergy_object["name"])
|
||||||
|
|
||||||
|
objInstance = objClass()
|
||||||
|
return objInstance.deserialize(parsed_dict)
|
||||||
|
except Exception as ex:
|
||||||
|
print(ex)
|
||||||
|
raise ex
|
||||||
|
else:
|
||||||
|
return parsed_dict
|
||||||
|
|
||||||
|
|
||||||
class SynergyTests(unittest.TestCase):
|
class SynergyTests(unittest.TestCase):
|
||||||
|
|
||||||
@mock.patch('synergy.service.LOG', LOG)
|
@mock.patch('synergy.service.LOG', LOG)
|
||||||
@ -66,53 +82,66 @@ class SynergyTests(unittest.TestCase):
|
|||||||
start_response = Mock()
|
start_response = Mock()
|
||||||
result = self.synergy.listManagers(environ={},
|
result = self.synergy.listManagers(environ={},
|
||||||
start_response=start_response)
|
start_response=start_response)
|
||||||
result = json.loads(result[0])
|
|
||||||
|
|
||||||
self.assertEqual(result, ["TimerManager"])
|
result = json.loads(result[0], object_hook=objectHookHandler)
|
||||||
|
self.assertEqual(len(result), 1)
|
||||||
|
self.assertEqual(result[0].getName(), "TimerManager")
|
||||||
|
|
||||||
@mock.patch('synergy.service.LOG', LOG)
|
@mock.patch('synergy.service.LOG', LOG)
|
||||||
def test_getManagerStatus(self):
|
def test_getManagerStatus(self):
|
||||||
start_response = Mock()
|
start_response = Mock()
|
||||||
result = self.synergy.getManagerStatus(environ={},
|
result = self.synergy.getManagerStatus(environ={},
|
||||||
start_response=start_response)
|
start_response=start_response)
|
||||||
result = json.loads(result[0])
|
|
||||||
|
|
||||||
self.assertEqual(result, {'TimerManager': 'ACTIVE'})
|
result = json.loads(result[0], object_hook=objectHookHandler)
|
||||||
|
|
||||||
|
self.assertEqual(result[0].getStatus(), 'ACTIVE')
|
||||||
|
|
||||||
@mock.patch('synergy.service.LOG', LOG)
|
@mock.patch('synergy.service.LOG', LOG)
|
||||||
def test_startManager(self):
|
def test_startManager(self):
|
||||||
environ = {'QUERY_STRING': 'manager=TimerManager'}
|
|
||||||
start_response = Mock()
|
start_response = Mock()
|
||||||
|
environ = {'QUERY_STRING': 'manager=NONE'}
|
||||||
|
|
||||||
result = self.synergy.startManager(environ, start_response)
|
result = self.synergy.startManager(environ, start_response)
|
||||||
result = json.loads(result[0])
|
|
||||||
|
|
||||||
self.assertEqual(result, {'TimerManager': {
|
self.assertEqual(result[0], "manager 'NONE' not found!")
|
||||||
'message': 'started successfully', 'status': 'RUNNING'}})
|
|
||||||
|
environ = {'QUERY_STRING': 'manager=TimerManager'}
|
||||||
|
|
||||||
|
result = self.synergy.startManager(environ, start_response)
|
||||||
|
result = json.loads(result[0], object_hook=objectHookHandler)
|
||||||
|
|
||||||
|
self.assertEqual(result[0].getStatus(), 'RUNNING')
|
||||||
|
self.assertEqual(result[0].get("message"), 'started successfully')
|
||||||
|
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
result = self.synergy.startManager(environ, start_response)
|
result = self.synergy.startManager(environ, start_response)
|
||||||
result = json.loads(result[0])
|
result = json.loads(result[0], object_hook=objectHookHandler)
|
||||||
|
|
||||||
self.assertEqual(result, {'TimerManager': {
|
self.assertEqual(result[0].getStatus(), 'RUNNING')
|
||||||
'message': 'WARN: already started', 'status': 'RUNNING'}})
|
self.assertEqual(result[0].get("message"), 'WARN: already started')
|
||||||
|
|
||||||
@mock.patch('synergy.service.LOG', LOG)
|
@mock.patch('synergy.service.LOG', LOG)
|
||||||
def test_stopManager(self):
|
def test_stopManager(self):
|
||||||
environ = {'QUERY_STRING': 'manager=TimerManager'}
|
stop_response = Mock()
|
||||||
start_response = Mock()
|
environ = {'QUERY_STRING': 'manager=NONE'}
|
||||||
|
|
||||||
result = self.synergy.startManager(environ, start_response)
|
result = self.synergy.startManager(environ, stop_response)
|
||||||
|
|
||||||
|
self.assertEqual(result[0], "manager 'NONE' not found!")
|
||||||
|
|
||||||
|
environ = {'QUERY_STRING': 'manager=TimerManager'}
|
||||||
|
|
||||||
|
result = self.synergy.startManager(environ, stop_response)
|
||||||
|
result = json.loads(result[0], object_hook=objectHookHandler)
|
||||||
|
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
result = self.synergy.stopManager(environ, start_response)
|
result = self.synergy.stopManager(environ, stop_response)
|
||||||
|
result = json.loads(result[0], object_hook=objectHookHandler)
|
||||||
|
|
||||||
result = json.loads(result[0])
|
self.assertEqual(result[0].getStatus(), 'ACTIVE')
|
||||||
|
|
||||||
self.assertEqual(result, {'TimerManager': {
|
|
||||||
'message': 'stopped successfully', 'status': 'ACTIVE'}})
|
|
||||||
|
|
||||||
@mock.patch('synergy.service.LOG', LOG)
|
@mock.patch('synergy.service.LOG', LOG)
|
||||||
def test_executeCommand(self):
|
def test_executeCommand(self):
|
||||||
|
@ -27,6 +27,7 @@ class TestManager(base.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestManager, self).setUp()
|
super(TestManager, self).setUp()
|
||||||
self.manager = Manager(name="dummy_manager")
|
self.manager = Manager(name="dummy_manager")
|
||||||
|
self.manager.setAutoStart(False)
|
||||||
|
|
||||||
def test_get_name(self):
|
def test_get_name(self):
|
||||||
self.assertEqual("dummy_manager", self.manager.getName())
|
self.assertEqual("dummy_manager", self.manager.getName())
|
||||||
|
@ -13,3 +13,5 @@ testrepository>=0.0.18
|
|||||||
testscenarios>=0.4
|
testscenarios>=0.4
|
||||||
testtools>=1.4.0
|
testtools>=1.4.0
|
||||||
mock==2.0.0
|
mock==2.0.0
|
||||||
|
tabulate>=0.7.2,<0.8.0
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user