From b1d3bbcc0eb4c7e267004c7a7c7b58274ec5aff6 Mon Sep 17 00:00:00 2001 From: itsikkes Date: Sun, 29 May 2016 14:32:06 +0300 Subject: [PATCH] more generic approach for job types --- .../cc/admin/ui/js/monkeysb-admin.js | 13 ++-- monkey_business/cc/connectors/__init__.py | 18 ++++- monkey_business/cc/connectors/demo.py | 11 ++- monkey_business/cc/connectors/vcenter.py | 18 ++++- monkey_business/cc/main.py | 76 ++++++++++++++----- 5 files changed, 104 insertions(+), 32 deletions(-) diff --git a/monkey_business/cc/admin/ui/js/monkeysb-admin.js b/monkey_business/cc/admin/ui/js/monkeysb-admin.js index c67fdd13f..6ff40cf3d 100644 --- a/monkey_business/cc/admin/ui/js/monkeysb-admin.js +++ b/monkey_business/cc/admin/ui/js/monkeysb-admin.js @@ -160,18 +160,19 @@ function createNewJob() { type: "object", title: "Job", properties: { - vlan: { - title: "Vlan", - type: "integer", - $ref: "/info?type=vlans" - }, + job: { + title: "Type", + $ref: "/jobcreate", + } }, options: { - "collapsed": true + "collapsed": false }, }, ajax: true, disable_edit_json: false, + disable_collapse: true, + disable_properties: true, }); } diff --git a/monkey_business/cc/connectors/__init__.py b/monkey_business/cc/connectors/__init__.py index ad185812a..4eeedfc9e 100644 --- a/monkey_business/cc/connectors/__init__.py +++ b/monkey_business/cc/connectors/__init__.py @@ -1,7 +1,7 @@ class NetControllerConnector(object): def __init__(self): - _properties = {} + self._properties = {} def _load_prop_dict(self, target, prop): for property in prop: @@ -36,3 +36,19 @@ class NetControllerConnector(object): def disconnect(self): return +class NetControllerJob(object): + connector = NetControllerConnector + + def __init__(self): + self._properties = { + # property: [value, enumerating_function] + } + + def get_job_properties(self): + return self._properties + + def set_job_properties(self, properties): + return {} + + def run(self): + raise NotImplementedError() \ No newline at end of file diff --git a/monkey_business/cc/connectors/demo.py b/monkey_business/cc/connectors/demo.py index d37a66c2e..15a61e0ab 100644 --- a/monkey_business/cc/connectors/demo.py +++ b/monkey_business/cc/connectors/demo.py @@ -1,4 +1,4 @@ -from connectors import NetControllerConnector +from connectors import NetControllerJob, NetControllerConnector demo_state = { 501: ["Machine A", "Machine B"], @@ -7,7 +7,6 @@ demo_state = { 514: ["Machine E", "Machine F"], } - class DemoConnector(NetControllerConnector): def __init__(self): self._conn = None @@ -34,3 +33,11 @@ class DemoConnector(NetControllerConnector): if (demo_state.has_key(vlanid)): return demo_state[vlanid] return [] + +class DemoJob(NetControllerJob): + connector = DemoConnector + + def __init__(self): + self._properties = { + "vlan": [0, "get_vlans_list"], + } diff --git a/monkey_business/cc/connectors/vcenter.py b/monkey_business/cc/connectors/vcenter.py index 49f743f63..1cdf8db7c 100644 --- a/monkey_business/cc/connectors/vcenter.py +++ b/monkey_business/cc/connectors/vcenter.py @@ -1,8 +1,7 @@ -from connectors import NetControllerConnector +from connectors import NetControllerJob, NetControllerConnector from pyVmomi import vim from pyVim.connect import SmartConnect, Disconnect - class VCenterConnector(NetControllerConnector): def __init__(self): self._service_instance = None @@ -21,6 +20,9 @@ class VCenterConnector(NetControllerConnector): "resource_pool": "" } } + self._job_properties = { + + } def connect(self): self._service_instance = SmartConnect(host=self._properties["address"], @@ -123,4 +125,14 @@ class VCenterConnector(NetControllerConnector): obj = c break - return obj \ No newline at end of file + return obj + + +class VCenterJob(NetControllerJob): + connector = VCenterConnector + + def __init__(self): + self._properties = { + "vlan": [0, "get_vlans_list"], + } + diff --git a/monkey_business/cc/main.py b/monkey_business/cc/main.py index 96896e10f..0723b22fd 100644 --- a/monkey_business/cc/main.py +++ b/monkey_business/cc/main.py @@ -1,4 +1,5 @@ import os +import sys from flask import Flask, request, abort, send_from_directory from flask.ext import restful from flask.ext.pymongo import PyMongo @@ -7,8 +8,8 @@ import bson.json_util import json from datetime import datetime import dateutil.parser -from connectors.vcenter import VCenterConnector -from connectors.demo import DemoConnector +from connectors.vcenter import VCenterJob, VCenterConnector +from connectors.demo import DemoJob, DemoConnector MONGO_URL = os.environ.get('MONGO_URL') if not MONGO_URL: @@ -18,7 +19,7 @@ app = Flask(__name__) app.config['MONGO_URI'] = MONGO_URL mongo = PyMongo(app) -available_connectors=[VCenterConnector, DemoConnector] +available_jobs = [VCenterJob, DemoJob] active_connectors = {} @@ -92,15 +93,49 @@ class Connector(restful.Resource): {"$set": settings_json}, upsert=True) -class Info(restful.Resource): +class JobCreation(restful.Resource): def get(self, **kw): - type = request.args.get('type') - if type == "vlans": + jobtype = request.args.get('type') + if not jobtype: + res = [] update_connectors() - vlans = set() - for con in active_connectors: - vlans.update(active_connectors[con].get_vlans_list()) - return {"enum": list(vlans)} + for con in available_jobs: + if con.connector.__name__ in active_connectors: + res.append({"title": con.__name__, "$ref": "/jobcreate?type=" + con.__name__}) + return {"oneOf": res} + + job = None + for jobclass in available_jobs: + if jobclass.__name__ == jobtype: + job = jobclass() + + if job and job.connector.__name__ in active_connectors.keys(): + properties = dict() + job_prop = job.get_job_properties() + + for prop in job_prop: + properties[prop] = dict({}) + if type(job_prop[prop][0]) is int: + properties[prop]["type"] = "number" + elif type(job_prop[prop][0]) is bool: + properties[prop]["type"] = "boolean" + else: + properties[prop]["type"] = "string" + if job_prop[prop][1]: + properties[prop]["enum"] = list(active_connectors[job.connector.__name__].__getattribute__(job_prop[prop][1])()) + + res = dict({ + "title": "%s Job" % jobtype, + "type": "object", + "options": { + "disable_collapse": True, + "disable_properties": True, + }, + "properties": properties + }) + return res + + return {} def normalize_obj(obj): @@ -136,18 +171,19 @@ def refresh_connector_config(name): def update_connectors(): - for con in available_connectors: - if con.__name__ not in active_connectors: - active_connectors[con.__name__] = con() + for con in available_jobs: + connector_name = con.connector.__name__ + if connector_name not in active_connectors: + active_connectors[connector_name] = con.connector() - if not active_connectors[con.__name__ ].is_connected(): - refresh_connector_config(con.__name__) + if not active_connectors[connector_name].is_connected(): + refresh_connector_config(connector_name) try: - active_connectors[con.__name__].connect() - app.logger.info("Trying to activate connector: %s" % con.__name__) + active_connectors[connector_name].connect() + app.logger.info("Trying to activate connector: %s" % connector_name) except Exception, e: - active_connectors.pop(con.__name__) - app.logger.info("Error activating connector: %s, reason: %s" % (con.__name__, e)) + active_connectors.pop(connector_name) + app.logger.info("Error activating connector: %s, reason: %s" % (connector_name, e)) @@ -162,7 +198,7 @@ api.representations = DEFAULT_REPRESENTATIONS api.add_resource(Root, '/api') api.add_resource(Job, '/job') api.add_resource(Connector, '/connector') -api.add_resource(Info, '/info') +api.add_resource(JobCreation, '/jobcreate') if __name__ == '__main__': app.run(host='0.0.0.0', debug=True, ssl_context=('server.crt', 'server.key'))