def script(self, object_id, script, args=None, timeout=None): """ Execute SA script against ManagedObject :param object: Managed Object id :param script: Script name (Eighter with or without profile) :param args: Dict with input arguments :param timeout: Script timeout in seconds """ # Resolve object data data = yield self.service.get_executor("db").submit( self.get_object_data, object_id) # Find pool name pool = self.service.get_pool_name(data["pool_id"]) if not pool: metrics["error", ("type", "pool_not_found")] += 1 raise APIError("Pool not found") # Check script is exists script_name = "%s.%s" % (data["profile"], script) if not loader.has_script(script_name): metrics["error", ("type", "invalid_scripts_request")] += 1 raise APIError("Invalid script") # url = yield self.get_activator_url(pool) if not url: raise APIError("No active activators for pool '%s'" % pool) self.redirect(url, "script", [ script_name, data["credentials"], data["capabilities"], data["version"], args, timeout ])
def set_dashboard(self, config): """ Save dashboard config. :param config: :return: datshboard id """ if "id" in config: d = self._get_dashboard(config["id"], access_level=1) if not d: metrics["error", ("type", "dashboard_not_found")] += 1 raise APIError("Dashboard not found") else: d = Dashboard.objects.filter(title=config.get("title")).first() if d: metrics["error", ("type", "bad_dashboard_name")] += 1 raise APIError("Dashboard name exists") d = Dashboard(id=str(bson.ObjectId()), owner=self.handler.current_user) d.format = config.get("format", 1) config["id"] = str(d.id) d.config = zlib.compress(ujson.dumps(config)) d.changed = datetime.datetime.now() d.title = config.get("title") # @todo: Generate title d.description = config.get("description") d.tags = config.get("tags", []) d.save() return str(d.id)
def script( self, name, credentials, capabilities=None, version=None, args=None, timeout=None, session=None, session_idle_timeout=None, ): """ Execute SA script :param name: Script name (with profile) :param credentials: Dict containing following fields * cli_protocol - CLI protocol (telnet, ssh) * address - IP address * cli_port (optional) - Non-standard CLI port * user (optional) - Login as user * password (optional) - User password * super_password (optional) - Enable password * snmp_version (optional) - Use SNMP version (None, v2c) * snmp_ro (optional) - Use SNMP R/O community * path (optional) - unstructured path * snmp_rate_limit (optional) - limit of outgoing snmp requests (float, in requests per second) :param capabilities: Dict of discovered capabilities :param version: Dict of discovered version :param timeout: Script timeout, in seconds :param session: Unique session id to share CLI stream :param session_idle_timeout: Hold CLI stream up to session_idle_timeout seconds after script completion """ script_class = loader.get_script(name) if not script_class: metrics["error", ("type", "invalid_script")] += 1 raise APIError("Invalid script: %s" % name) script = script_class( service=self.service, credentials=credentials, args=args, capabilities=capabilities, version=version, timeout=timeout, name=name, session=session, session_idle_timeout=session_idle_timeout, ) try: result = script.run() except script.ScriptError as e: metrics["error", ("type", "script_error")] += 1 raise APIError("Script error: %s" % e.__doc__) return result
def query(self, query): """ Perform query and return result :param query: Dict containing fields datasource - name of datasource see model.query for the rest :return: """ if "datasource" not in query: metrics["error", ("type", "query_no_datasource")] += 1 raise APIError("No datasource") model = self.get_model(query["datasource"]) if not model: metrics["error", ("type", "query_invalid_datasource")] += 1 raise APIError("Invalid datasource") return model.query(query, self.handler.current_user)
def _set_dashboard_access(self, id, items, acc_limit=""): """ :param id: Dashboard ID :param items: Dictionary rights :param acc_limit: User or Group only set :return: """ self.logger.info("Settings dashboard access") d = self._get_dashboard(id) if not d: self.logger.error("Dashboards not find %s", id) metrics["error", ("type", "dashboard_not_found")] += 1 raise APIError("Dashboard not found") if d.get_user_access(self.handler.current_user) < DAL_ADMIN: self.logger.error("Access for user Dashboards %s", self.handler.current_user) metrics["error", ("type", "no_permissions_to_set_permissions")] += 1 raise APIError("User have no permission to set permissions") access = [] if acc_limit == "user": access = [x for x in d.access if x.user] elif acc_limit == "group": access = [x for x in d.access if x.group] if not items: # @todo Clear rights (protect Admin rights?) return True try: items = I_VALID.clean(items) except ValueError as e: self.logger.error("Validation items with rights", e) metrics["error", ("type", "validation")] += 1 raise APIError("Validation error %s" % e) for i in items: da = DashboardAccess(level=i.get("level", -1)) if i.get("user"): da.user = User.objects.get(id=i["user"]["id"]) if i.get("group"): da.group = Group.objects.get(id=i["group"]["id"]) access += [da] d.access = access d.save() return True
async def get_credentials(self, object_id): # Resolve object data data = await self.service.run_in_executor("db", self.get_object_data, object_id) # Find pool name pool = self.service.get_pool_name(data["pool_id"]) if not pool: metrics["error", ("type", "pool_not_found")] += 1 raise APIError("Pool not found") data["pool"] = pool return data
def set_dashboard_access(self, id, items): """ :param id: :param items: :return: """ if not id.get("id"): metrics["error", ("type", "wrong_json")] += 1 raise APIError("Not id field in JSON") return self._set_dashboard_access(id.get("id"), items.get("items"))
def get_credentials(self, object_id): # Resolve object data data = yield self.service.get_executor("db").submit( self.get_object_data, object_id) # Find pool name pool = self.service.get_pool_name(data["pool_id"]) if not pool: metrics["error", ("type", "pool_not_found")] += 1 raise APIError("Pool not found") data["pool"] = pool raise tornado.gen.Return(data)
def get_dashboard(self, id): """ Returns dashboard config by id :param id: :return: """ d = self._get_dashboard(id) if d: return ujson.loads(zlib.decompress(d.config)) else: metrics["error", ("type", "dashboard_not_found")] += 1 raise APIError("Dashboard not found")
def remove_dashboard(self, id): """ Remove user dashboard :param id: :return: """ d = self._get_dashboard(id, access_level=2) if d: d.delete() return True else: metrics["error", ("type", "dashboard_not_found")] += 1 raise APIError("Dashboard not found")
def get_dashboard(self, id): """ Returns dashboard config by id :param id: :return: """ d = self._get_dashboard(id) if d: config = orjson.loads(zlib.decompress(smart_bytes(d.config))) config["id"] = str(d.id) config["title"] = d.title config["owner"] = d.owner.username if d.owner else DEFAULT_USER config["description"] = d.description return config else: metrics["error", ("type", "dashboard_not_found")] += 1 raise APIError("Dashboard not found")
def get_datasource_info(self, name): """ Returns datasource metadata as a dict of * name * description * tags * fields - list of dicts * name * description * type :param name: :return: """ for ds in self.get_datasources(): if ds["name"] == name: return ds metrics["error", ("type", "info_invalid_datasource")] += 1 raise APIError("Invalid datasource")
def _get_dashboard(self, id, access_level=DAL_RO): """ Returns dashboard or None :param id: :return: """ user = self.handler.current_user groups = user.groups.values_list("id", flat=True) d = Dashboard.objects.filter(id=id).first() if not d: return None if d.owner == user or user.is_superuser: return d # @todo: Filter by groups for i in d.access: if i.user == user and i.level >= access_level: return d elif i.group and i.group.id in groups and i.level >= access_level: return d # No access metrics["error", ("type", "no_permission")] += 1 raise APIError("User have no permission to access dashboard")
def get_object_data(self, object_id): """ Worker to resolve credentials """ object_id = int(object_id) # Get Object's attributes with self.service.get_pg_connect() as connection: cursor = connection.cursor() cursor.execute(self.RUN_SQL, [object_id, object_id]) data = cursor.fetchall() if not data: metrics["error", ("type", "object_not_found")] += 1 raise APIError("Object is not found") # Build capabilities capabilities = ObjectCapabilities.get_capabilities(object_id) # Get object credentials ( name, is_managed, profile, vendor, platform, version, scheme, address, port, user, password, super_password, remote_path, snmp_ro, pool_id, sw_image, auth_profile_id, ap_user, ap_password, ap_super_password, ap_snmp_ro, ap_snmp_rw, privilege_policy, snmp_rate_limit, p_privilege_policy, p_snmp_rate_limit, access_preference, p_access_preference, beef_storage_id, beef_path_template_id, attrs, ) = data[0] # Check object is managed if not is_managed: metrics["error", ("type", "object_not_managed")] += 1 raise APIError("Object is not managed") if auth_profile_id: user = ap_user password = ap_password super_password = ap_super_password snmp_ro = ap_snmp_ro snmp_rw = ap_snmp_rw # noqa just to be # if privilege_policy == "E": raise_privileges = True elif privilege_policy == "P": raise_privileges = p_privilege_policy == "E" else: raise_privileges = False if access_preference == "P": access_preference = p_access_preference if not snmp_rate_limit: snmp_rate_limit = p_snmp_rate_limit # Build credentials credentials = { "name": name, "address": address, "user": user, "password": password, "super_password": super_password, "path": remote_path, "raise_privileges": raise_privileges, "access_preference": access_preference, "snmp_rate_limit": snmp_rate_limit, } if snmp_ro: credentials["snmp_ro"] = snmp_ro if capabilities.get("SNMP | v2c"): credentials["snmp_version"] = "v2c" elif capabilities.get("SNMP | v1"): credentials["snmp_version"] = "v1" if scheme in CLI_PROTOCOLS: credentials["cli_protocol"] = PROTOCOLS[scheme] if port: credentials["cli_port"] = port elif scheme in HTTP_PROTOCOLS: credentials["http_protocol"] = PROTOCOLS[scheme] if port: credentials["http_port"] = port # Build version if vendor and platform and version: vendor = Vendor.get_by_id(vendor) version = { "vendor": vendor.code[0] if vendor.code else vendor.name, "platform": Platform.get_by_id(platform).name, "version": Firmware.get_by_id(version).version, } if sw_image: version["image"] = sw_image if attrs: version["attributes"] = attrs else: version = None # Beef processing if scheme == BEEF and beef_storage_id and beef_path_template_id: mo = ManagedObject.get_by_id(object_id) tpl = Template.get_by_id(beef_path_template_id) beef_path = tpl.render_subject(object=mo) if beef_path: storage = ExtStorage.get_by_id(beef_storage_id) credentials["beef_storage_url"] = storage.url credentials["beef_path"] = beef_path return dict( profile=Profile.get_by_id(profile).name, pool_id=pool_id, credentials=credentials, capabilities=capabilities, version=version, )
def get_hierarchy(self, params): """ Get Hierarchy data for field :param params: :return: """ def search_parent(node, p_id): if p_id is None: return node if node and node["id"] == p_id: return node else: if node and "children" in node: for child in node["children"]: _searched = search_parent(child, p_id) if _searched: return _searched else: return None def sort_children(node): if "children" not in set(node): return else: node["children"] = sorted(node["children"], key=lambda x: x["text"]) for n in node["children"]: sort_children(n) if "datasource" not in params: metrics["error", ("type", "get_hierarchy_no_datasource")] += 1 raise APIError("No datasource") if "dic_name" not in params: metrics["error", ("type", "get_hierarchy_no_dict_name")] += 1 raise APIError("No dictionary name") if "field_name" not in params: metrics["error", ("type", "get_hierarchy_no_field_name")] += 1 raise APIError("No field name") model = loader[params["datasource"]] if not model: metrics["error", ("type", "get_hierarchy_invalid_datasource")] += 1 raise APIError("Invalid datasource") query = { "fields": [ { "expr": { "$names": [params["dic_name"], params["field_name"]] }, "alias": "names" }, { "expr": { "$hierarchy": [params["dic_name"], { "$field": params["field_name"] }] }, "alias": "ids", }, { "expr": params["field_name"], "group": 0 }, ], "datasource": params["datasource"], } if "limit" in params: query["limit"] = params["limit"] if "filter" in params: query["filter"] = { "$like": [ { "$lower": { "$field": "arrayElement(names,1)" } }, { "$lower": "%" + params["filter"] + "%" }, ] } result = model.query(query, self.handler.current_user) tree = {} for row in result["result"]: names = reversed([x[1:-1] for x in row[0][1:-1].split(",")]) ids = reversed([str(x) for x in row[1][1:-1].split(",")]) parent_id = None for id, text in zip(ids, names): searched = search_parent(tree, parent_id) parent_id = id if searched: if searched["id"] != id: if "children" not in searched: searched["children"] = [] if id not in [x["id"] for x in searched["children"]]: searched["children"] += [{"id": id, "text": text}] else: # starting point tree = {"id": id, "text": text, "children": []} sort_children(tree) return tree