def update_catalogue(workspace_id, catalogue_id, catalogue_data): """ Updates a specific catalogue by its id. The catalogue applies the given name and url, that are in the json parameter. :param workspace_id: The Workspace ID :param catalogue_id: The Catalogue ID :return: The updated Catalogue descriptor """ catalogue_name = shlex.quote(catalogue_data['name']) catalogue_url = shlex.quote(catalogue_data['url']) session = db_session() workspace = session.query(Workspace).filter(Workspace.id == workspace_id).first() if workspace is None: raise NotFound("workspace with id {} could not be found".format(workspace_id)) catalogue = session.query(Catalogue). \ filter(Catalogue.workspace == workspace). \ filter(Catalogue.id == catalogue_id). \ first() if catalogue is None: raise NotFound("catalogue with id {} could not be found".format(catalogue_id)) if catalogue_name != catalogue.name: existing_catalogues = session.query(catalogue). \ filter(catalogue.workspace == workspace). \ filter(catalogue.name == catalogue_data['name']). \ all() if len(existing_catalogues) > 0: raise NameConflict("catalogue with name {} already exists".format(catalogue_data['name'])) catalogue.name = catalogue_name catalogue.url = catalogue_url session.commit() update_workspace_descriptor(catalogue.workspace) return catalogue.as_dict()
def delete(workspace_id: int, platform_id: int) -> dict: """ Deletes the platform from the workspace :param workspace_id: :param platform_id: :return: the deleted platform description """ session = db_session() workspace = session.query(Workspace).filter( Workspace.id == workspace_id).first() if workspace is None: raise NotFound( "workspace with id {} could not be found".format(workspace_id)) platform = session.query(Platform). \ filter(Platform.workspace == workspace). \ filter(Platform.id == platform_id). \ first() if platform is None: raise NotFound( "Platform with id {} could not be found".format(platform_id)) session.delete(platform) update_workspace_descriptor(platform.workspace) session.commit() return platform.as_dict()
def delete_image_file(ws_id, project_id, vnf_id, filename): """ Deletes the image file with the given name :param ws_id: The workspace ID :param project_id: The project ID :param vnf_id: The VNF ID :param filename: The name of the file to delete :return: A success message :raises NotFound: if the image file could not be located """ session = db_session() function = session.query(Function). \ join(Project). \ join(Workspace). \ filter(Workspace.id == ws_id). \ filter(Project.id == project_id). \ filter(Function.id == vnf_id).first() if function: save_name = secure_filename(filename) if not save_name == get_file_name(function): file_path = get_file_path("vnf", function).replace( get_file_name(function), save_name) if os.path.exists(file_path): os.remove(file_path) return "File {} was deleted".format(save_name) else: raise NotFound("File {} not found!".format(save_name)) else: raise NotFound("Function with id " + vnf_id + " does not exist")
def delete_service(project_id: int, service_id: int) -> dict: """ Deletes the service from the Database and from the disk :param project_id: The Projects ID :param service_id: The Services ID :return: The descriptor of the deleted service """ session = db_session() project = session.query(Project).filter(Project.id == project_id).first() if project is None: raise NotFound("Could not delete service: project with id {} not found".format(service_id)) service = session.query(Service). \ filter(Service.id == service_id). \ filter(Service.project == project). \ first() if service is None: raise NotFound("Could not delete service: service with id {} not found".format(service_id)) refs = get_references(service, session) if refs: session.rollback() ref_str = ",\n".join(ref.uid for ref in refs) raise StillReferenced("Could not delete service because it is still referenced by \n" + ref_str) session.delete(service) try: os.remove(get_file_path("nsd", service)) except: session.rollback() logger.exception("Could not delete service:") raise session.commit() return service.as_dict()
def find_by_priority(user_data, ws_id, project_id, vendor, name, version, is_vnf): """ Tries to find vnf / network services by descending priority 1. project 2. private catalogue 3. public catalogues. :param user_data: Information about the current user :param ws_id: The Workspace ID :param project_id: The project ID :param vendor: The descriptors vendor :param name: The descriptors name :param version: The descriptors versions :param is_vnf: if the descriptor is a VNF :return: The descriptor if found """ # 1. Try to find in project project = get_project(project_id) if project is None: raise NotFound("No project with id {} found.".format(project_id)) function = get_function(project.functions, vendor, name, version) if is_vnf else get_function( project.services, vendor, name, version) if function is not None: return function.as_dict() # 2. Try to find in private catalogue # private catalogue funcs/nss are cached in db function = query_private_nsfs(ws_id, vendor, name, version, is_vnf) if function is not None: return function.as_dict() # 3. Try to find in public catalogue catalogues = get_catalogues(ws_id) for catalogue in catalogues: try: function_list = get_all_in_catalogue(user_data, ws_id, catalogue['id'], is_vnf) except: continue for func in function_list: if func['vendor'] == vendor and func['name'] == name and func[ 'version'] == version: function = func return function.as_dict() # If none found, raise exception raise NotFound("VNF" if is_vnf else "NS" + " {}:{}:{} not found".format(vendor, name, version))
def get_image_files(ws_id, project_id, function_id): """ Returns a list of image file names located in the vnf folder :param ws_id: The Workspace ID :param project_id: The project ID :param function_id: The function ID :return: A List of image file names for this VNF """ session = db_session() function = session.query(Function). \ join(Project). \ join(Workspace). \ filter(Workspace.id == ws_id). \ filter(Project.id == project_id). \ filter(Function.id == function_id).first() if function: folder_path = get_file_path("vnf", function).replace(get_file_name(function), "") image_files = [] for filename in os.listdir(folder_path): if not Path(os.path.join(folder_path, filename)).is_dir(): if not filename == get_file_name(function): image_files.append(filename) return image_files else: raise NotFound("Function with id " + function_id + " does not exist")
def create_catalogue(workspace_id: int, catalogue_data): """ Creates a catalgoue in the given workspace. A catalogue is defined by its name and url. These are given as json data :param workspace_id: Workspace ID of the target workspace, where the catalogue should get created. :return: Catalogue descriptor """ catalogue_name = shlex.quote(catalogue_data['name']) catalogue_url = shlex.quote(catalogue_data['url']) session = db_session() workspace = session.query(Workspace).filter(Workspace.id == workspace_id).first() if workspace is None: raise NotFound("workspace with id {} could not be found".format(workspace_id)) existing_catalogues = session.query(Catalogue). \ filter(Catalogue.workspace == workspace). \ filter(Catalogue.name == catalogue_data['name']). \ all() if len(existing_catalogues) > 0: raise NameConflict("catalogue with name {} already exists".format(catalogue_data['name'])) catalogue = Catalogue(name=catalogue_name, url=catalogue_url, workspace=workspace) session.add(catalogue) session.commit() update_workspace_descriptor(catalogue.workspace) return catalogue.as_dict()
def create_platform(workspace_id: int, platform_data) -> dict: """ Create a new platform entry :param workspace_id: :param platform_data: :return: """ platform_name = shlex.quote(platform_data['name']) platform_url = shlex.quote(platform_data['url']) session = db_session() workspace = session.query(Workspace).filter( Workspace.id == workspace_id).first() if workspace is None: raise NotFound( "workspace with id {} could not be found".format(workspace_id)) existing_platforms = session.query(Platform). \ filter(Platform.workspace == workspace). \ filter(Platform.name == platform_data['name']). \ all() if len(existing_platforms) > 0: raise NameConflict("Platform with name {} already exists".format( platform_data['name'])) platform = Platform(name=platform_name, url=platform_url, workspace=workspace) session.add(platform) update_workspace_descriptor(platform.workspace) session.commit() return platform.as_dict()
def delete_function(ws_id: int, project_id: int, function_id: int) -> dict: """ Deletes the function :param ws_id: :param project_id: :param function_id: :return: the deleted function """ session = db_session() function = session.query(Function). \ join(Project). \ join(Workspace). \ filter(Workspace.id == ws_id). \ filter(Project.id == project_id). \ filter(Function.id == function_id).first() if function is not None: session.delete(function) else: session.rollback() raise NotFound("Function with id " + function_id + " does not exist") try: os.remove(get_file_path("vnf", function)) except: session.rollback() logger.exception("Could not delete function:") raise session.commit() return function.as_dict()
def save_image_file(ws_id, project_id, function_id, file): """ Saves the vnf image file into the vnfs folder :param ws_id: The workspace ID :param project_id: The project ID :param function_id: The function ID :param file: The image file :return: A success message """ if file.filename == '': raise InvalidArgument("No file attached!") if file: filename = secure_filename(file.filename) session = db_session() function = session.query(Function). \ join(Project). \ join(Workspace). \ filter(Workspace.id == ws_id). \ filter(Project.id == project_id). \ filter(Function.id == function_id).first() if function is not None: file_path = get_file_path("vnf", function) file_path = file_path.replace(get_file_name(function), filename) file.save(file_path) return "File {} successfully uploaded!".format(filename) else: raise NotFound("Function with id " + function_id + " does not exist")
def update_project(project_data, project_id): """ Update the Project :param project_data: :param project_id: :return: """ session = db_session() project = session.query(Project).filter(Project.id == project_id).first() if project is None: raise NotFound("Project with id {} could not be found".format(project_id)) # Update name if 'name' in project_data and project_data['name'] != project.name: if os.path.exists(get_project_path(project.workspace.path, project.rel_path)): new_name = shlex.quote(project_data['name']) old_path = get_project_path(project.workspace.path, project.rel_path) new_path = rreplace(old_path, project.name, new_name, 1) if os.path.exists(new_path): raise NameConflict("Invalid name parameter, workspace '{}' already exists".format(new_name)) # Do not allow move directories outside of the workspaces_dir if not new_path.startswith(WORKSPACES_DIR): raise Exception("Invalid path parameter, you are not allowed to break out of {}".format(WORKSPACES_DIR)) else: # Move the directory shutil.move(old_path, new_path) project.name = new_name project.rel_path = new_name set_data(project, project_data) sync_project_descriptor(project) db_session.commit() return project.as_dict()
def check_access(request): """ checks if the current user is allowed to access a given resource. Session will be invalidated if the login information cannot be found :param request: The http request made to the server :return: nothing if access granted :raises UnauthorizedException: if user not logged in """ if not all(key in session for key in ['user_data', 'access_token']): session.clear() raise UnauthorizedException( "Session invalid. Please try logging in again") # Access parsed values of the url # Check if wsID was in the url if request.view_args is None: return if 'ws_id' in request.view_args: ws_id = request.view_args['ws_id'] data_session = db_session() ws = data_session.query(Workspace).filter_by(id=ws_id).first() # Get current user user = get_user(session['user_data']['login']) # If the requested workspace is in his workspaces, he is allowed to access it if ws in user.workspaces: if 'project_id' in request.view_args: pj_id = request.view_args['project_id'] pj = data_session.query(Project).filter( Project.id == pj_id).first() if pj in ws.projects: return else: raise NotFound("Project not found") elif 'parent_id' in request.view_args and PROJECTS in request.url.split( "/"): pj_id = request.view_args['parent_id'] pj = data_session.query(Project).filter( Project.id == pj_id).first() if pj in ws.projects: return else: raise NotFound("Project not found") return raise NotFound("Workspace not found") return
def get_service(service_id): """Returns a service with the given service id""" session = db_session() service = session.query(Service).filter(Service.id == service_id).first() # Check if the function could be retrieved if not service: raise NotFound("Service with id '{}' does not exist".format(service_id)) return service
def get_function(function_id): """ Returns a function with the given function id""" session = db_session() function = session.query(Function).filter(Function.id == function_id).first() # Check if the function could be retrieved if not function: raise NotFound("Function with id '{}' does not exist".format(function_id)) return function
def create_service(ws_id: int, project_id: int, service_data: dict) -> dict: """ Creates a service in the given project :param ws_id: The Workspace of the project :param project_id: The Project of the Service :param service_data: the service descriptor :return: The created service descriptor """ session = db_session() project = session.query(Project).filter_by(id=project_id).first() if project: # Retrieve post parameters try: service_name = shlex.quote(service_data['descriptor']["name"]) vendor_name = shlex.quote(service_data['descriptor']["vendor"]) version = shlex.quote(service_data['descriptor']["version"]) except KeyError as ke: raise InvalidArgument("Missing key {} in service data".format( str(ke))) existing_services = list( session.query(Service).join(Project).join(Workspace).filter( Workspace.id == ws_id).filter( Service.project == project).filter( Service.name == service_name).filter( Service.vendor == vendor_name).filter( Service.version == version)) if len(existing_services) > 0: raise NameConflict( "A service with this name/vendor/version already exists") # validate service descriptor workspace = session.query(Workspace).filter( Workspace.id == ws_id).first() validate_service_descriptor(workspace.ns_schema_index, service_data["descriptor"]) # Create db object service = Service(name=service_name, vendor=vendor_name, version=version, project=project, descriptor=json.dumps(service_data["descriptor"]), meta=json.dumps(service_data["meta"])) session.add(service) try: write_ns_vnf_to_disk("nsd", service) except: logger.exception("Could not create service:") session.rollback() raise session.commit() return service.as_dict() else: session.rollback() raise NotFound("Project with id '{}‘ not found".format(project_id))
def get_project(project_id): """ Retrieves the project which matches the given project id. Otherwise it raises NotFound Exception """ session = db_session() current_project = session.query(Project).filter( Project.id == project_id).first() if current_project is not None: return current_project else: raise NotFound("Project {} does not exist".format(project_id))
def update_function(ws_id: int, prj_id: int, func_id: int, func_data: dict) -> dict: """ Update the function descriptor :param ws_id: :param prj_id: :param func_id: :param func_data: :return: The updated function descriptor """ session = db_session() ws = session.query(Workspace).filter(Workspace.id == ws_id).first() validate_vnf(ws.vnf_schema_index, func_data) # test if ws Name exists in database function = session.query(Function). \ join(Project). \ join(Workspace). \ filter(Workspace.id == ws_id). \ filter(Project.id == prj_id). \ filter(Function.id == func_id).first() if function is None: session.rollback() raise NotFound("Function with id {} does not exist".format(func_id)) function.descriptor = json.dumps(func_data) old_file_name = get_file_path("vnf", function) old_folder_path = old_file_name.replace(get_file_name(function), "") try: function.name = shlex.quote(func_data["name"]) function.vendor = shlex.quote(func_data["vendor"]) function.version = shlex.quote(func_data["version"]) except KeyError as ke: session.rollback() raise InvalidArgument("Missing key {} in function data".format(str(ke))) try: new_file_name = get_file_path("vnf", function) new_folder_path = new_file_name.replace(get_file_name(function), "") if old_folder_path != new_folder_path: # move old files to new location os.makedirs(new_folder_path) for file in os.listdir(old_folder_path): if not old_file_name == os.path.join(old_folder_path, file): # don't move descriptor yet shutil.move(os.path.join(old_folder_path, file), os.path.join(new_folder_path, file)) if not new_file_name == old_file_name: shutil.move(old_file_name, new_file_name) if old_folder_path != new_folder_path: # cleanup old folder shutil.rmtree(old_folder_path) write_ns_vnf_to_disk("vnf", function) except: session.rollback() logger.exception("Could not update descriptor file:") raise session.commit() return function.as_dict()
def delete_image_file(ws_id, project_id, vnf_id, filename): session = db_session() function = session.query(Function). \ join(Project). \ join(Workspace). \ filter(Workspace.id == ws_id). \ filter(Project.id == project_id). \ filter(Function.id == vnf_id).first() if function: save_name = secure_filename(filename) if not save_name == get_file_name(function): file_path = get_file_path("vnf", function).replace(get_file_name(function), save_name) if os.path.exists(file_path): os.remove(file_path) return "File {} was deleted".format(save_name) else: raise NotFound("File {} not found!".format(save_name)) else: raise NotFound("Function with id " + vnf_id + " does not exist")
def get_workspace(ws_id: int) -> Workspace: """ Returns the workspace model of the given workspace :param ws_id: The workspace ID :return: The corresponding workspace model """ workspace = db_session().query(Workspace).filter(Workspace.id == ws_id).first() if not workspace: raise NotFound("Could not find workspace with id {}".format(ws_id)) return workspace
def update_service(ws_id, project_id, service_id, service_data): """ Update the service using the service data from the request :param ws_id: :param project_id: :param service_id: :param service_data: :return: """ session = db_session() service = session.query(Service). \ join(Project). \ join(Workspace). \ filter(Workspace.id == ws_id). \ filter(Project.id == project_id). \ filter(Service.id == service_id).first() if service: old_file_name = get_file_path("nsd", service) # Parse parameters and update record if 'descriptor' in service_data: # validate service descriptor workspace = session.query(Workspace).filter( Workspace.id == ws_id).first() validate_service_descriptor(workspace.ns_schema_index, service_data["descriptor"]) service.descriptor = json.dumps(service_data["descriptor"]) try: service.name = shlex.quote(service_data["descriptor"]["name"]) service.vendor = shlex.quote( service_data["descriptor"]["vendor"]) service.version = shlex.quote( service_data["descriptor"]["version"]) except KeyError as ke: raise InvalidArgument("Missing key {} in function data".format( str(ke))) if 'meta' in service_data: service.meta = json.dumps(service_data["meta"]) new_file_name = get_file_path("nsd", service) try: if not old_file_name == new_file_name: shutil.move(old_file_name, new_file_name) write_ns_vnf_to_disk("nsd", service) except: logger.exception("Could not update descriptor file:") raise session.commit() return service.as_dict() else: raise NotFound( "Could not update service '{}', because no record was found". format(service_id))
def get_catalogue(catalogue_id): """ Retrieves a catalogue by given id :param catalogue_id: int :return: """ session = db_session() catalogue = session.query(Catalogue).filter(Catalogue.id == catalogue_id).first() # Check if catalogue exists if not catalogue: raise NotFound("Catalogue with id '{}' could not be found".format(catalogue_id)) return catalogue
def get_project(ws_id, pj_id): session = db_session() project = session.query(Project). \ join(Workspace). \ filter(Workspace.id == ws_id). \ filter(Project.id == pj_id). \ first() session.commit() if project: return project.as_dict() else: raise NotFound("No project with id {} could be found".format(pj_id))
def get_catalogue(catalogue_id): """ Retrieves a catalogue by its id :param catalogue_id: :return: """ session = db_session() catalogue = session.query(Catalogue).filter(Catalogue.id == catalogue_id).first() session.commit() if catalogue is None: raise NotFound("catalogue with id {} could not be found".format(catalogue_id)) return catalogue.as_dict()
def create_function(ws_id: int, project_id: int, function_data: dict) -> dict: """ Creates a new vnf in the project :param ws_id: The workspace ID :param project_id: The Project ID :param function_data: The function data to create :return: The created function as a dict """ try: function_name = shlex.quote(function_data['descriptor']["name"]) vendor_name = shlex.quote(function_data['descriptor']["vendor"]) version = shlex.quote(function_data['descriptor']["version"]) except KeyError as ke: raise InvalidArgument("Missing key {} in function data".format( str(ke))) session = db_session() ws = session.query(Workspace).filter( Workspace.id == ws_id).first() # type: Workspace validate_vnf(ws.schema_index, function_data['descriptor']) # test if function Name exists in database existing_functions = list( session.query(Function).join(Project).join(Workspace).filter( Workspace.id == ws_id).filter( Function.project_id == project_id).filter( Function.vendor == vendor_name).filter( Function.name == function_name).filter( Function.version == version)) if len(existing_functions) > 0: raise NameConflict("Function with name " + function_name + " already exists") project = session.query(Project).filter(Project.id == project_id).first() if project is None: raise NotFound("No project with id " + project_id + " was found") function = Function(name=function_name, project=project, vendor=vendor_name, version=version, descriptor=json.dumps(function_data['descriptor'])) session.add(function) try: write_ns_vnf_to_disk("vnf", function) except: logger.exception("Could not write data to disk:") session.rollback() raise session.commit() return function.as_dict()
def get_project(ws_id, pj_id: int, session=db_session()) -> Project: """ Returns a project and raises 404, when project not found. :param ws_id: Workspace id :param pj_id: Project id :param db session :return: Project model """ project = session.query(Project).join(Workspace) \ .filter(Workspace.id == ws_id) \ .filter(Project.id == pj_id).first() if not project: raise NotFound("Could not find project with id {}".format(pj_id)) return project
def get_services(ws_id: int, project_id: int) -> list: """ Get a list of all services in this Project :param ws_id: :param project_id: The project ID :return: A list of service descriptors as dicts """ session = db_session() project = session.query(Project).filter_by(id=project_id).first() session.commit() if project: return list(map(lambda x: x.as_dict(), project.services)) else: raise NotFound("No project matching id {}".format(project_id))
def get_workspace(ws_id: int) -> dict: """ Get a workspace by ID :param ws_id: :return: A dictionary wich contains the Workspace configuration """ session = db_session() workspace = session.query(Workspace). \ filter(Workspace.id == ws_id).first() session.commit() if workspace is not None: return workspace.as_dict() else: raise NotFound("No workspace with id " + ws_id + " exists")
def get_platform(platform_id: int) -> dict: """ Get the platform definition :param platform_id: :return: The platform information """ session = db_session() platform = session.query(Platform).filter( Platform.id == platform_id).first() session.commit() if platform is None: raise NotFound( "Platform with id {} could not be found".format(platform_id)) return platform.as_dict()
def delete(workspace_id, catalogue_id): """ Deletes a catalogue by its id :param workspace_id: :param catalogue_id: :return: """ session = db_session() workspace = session.query(Workspace).filter(Workspace.id == workspace_id).first() if workspace is None: raise NotFound("workspace with id {} could not be found".format(workspace_id)) catalogue = session.query(Catalogue). \ filter(Catalogue.workspace == workspace). \ filter(Catalogue.id == catalogue_id). \ first() if catalogue is None: raise NotFound("catalogue with id {} could not be found".format(catalogue_id)) session.delete(catalogue) session.commit() update_workspace_descriptor(catalogue.workspace) return catalogue.as_dict()
def get_service(ws_id, parent_id, service_id): """ Get the service by ID :param ws_id: The workspace ID of the Project :param parent_id: The project ID :param service_id: the Service ID :return: """ session = db_session() service = session.query(Service).filter_by(id=service_id).first() session.commit() if service: return service.as_dict() else: raise NotFound("No Service matching id {}".format(parent_id))