def _renameapp(appid, newname): log("User '%s' is attempting to rename application %s" % (g.user.username, appid)) if not newname: msg = '"name" is a required argument' log_error(msg) return error_response(msg) app = get_app_by_id(g.user.uid, appid) if not app: msg = 'Application not found' log_error(msg) return error_response(msg) # check if the new name is already taken if check_app_exists(newname): msg = 'Application name "%s" is already taken' % newname log_error(msg) return error_response(msg) app.name = newname db.session.commit() log("Application %s renamed successfully" % appid) return {}
def _rename(app_id, serviceid, newname): log("User '%s' is attempting to rename service %s from application %s" % (g.user.username, serviceid, app_id)) try: app_id = int(app_id) serviceid = int(serviceid) except: msg = 'Bad specification of application or service IDs' log_error(msg) return error_response(msg) if not newname: msg = '"name" is a required argument' log_error(msg) return error_response(msg) service = get_service(g.user.uid, app_id, serviceid) if not service: msg = 'Invalid service_id' log_error(msg) return error_response(msg) service.name = newname db.session.commit() log('Service renamed successfully') return {}
def _createapp(app_name): log("User '%s' is attempting to create a new application '%s'" % (g.user.username, app_name)) if not app_name: msg = '"name" is a required argument' log_error(msg) return error_response(msg) # check if the application already exists if check_app_exists(app_name): msg = 'Application name "%s" is already taken' % app_name log_error(msg) return error_response(msg) a = Application(name=app_name, user=g.user) db.session.add(a) # flush() is needed to get auto-incremented sid db.session.flush() db.session.commit() log('Application %s created successfully' % (a.aid)) return a.to_dict()
def upload_manifest(): json = request.values.get('manifest') if not json: msg = '"manifest" is a required argument' log_error(msg) return build_response(jsonify(error_response(msg))) log("User '%s' has uploaded the following manifest: %s" % (g.user.username, json)) if not check_manifest(json): msg = 'The uploded manifest is not valid' return build_response(jsonify(error_response(msg))) try: parse = simplejson.loads(json) except: msg = 'Error parsing json' log_error(msg) return build_response(jsonify(error_response(msg))) msg, appid = create_manifest_app(parse) if msg != 'ok': log_error(msg) return build_response(jsonify(error_response(msg))) if not parse.get('Services'): log('Manifest: Application not started, as no services are defined.') return build_response(jsonify({})) app = get_app_by_id(g.user.uid, appid) app.status = Application.A_PROLOGUE db.session.commit() cloud = request.values.get('cloud') if not cloud or cloud == 'None': cloud = 'default' if request.values.get('thread'): log('Starting a new process for the manifest') p = Process(target=start_manifest_app, args=(parse, appid, cloud)) p.start() log('Process started, now return') return build_response(jsonify({ 'aid': appid })) else: msg = start_manifest_app(parse, appid, cloud) if msg != 'ok': log_error(msg) return build_response(jsonify(error_response(msg))) return build_response(jsonify({ 'aid': appid }))
def download_manifest(appid): manifest = {} app = get_app_by_id(g.user.uid, appid) if not app: msg = 'The appid %s does not exist' % appid log_error(msg) return build_response(jsonify(error_response(msg))) manifest['Services'] = [] manifest['Application'] = app.name do_delete = False for service in Service.query.filter_by(application_id=appid): if service.type == "xtreemfs": do_delete = True svc_manifest = get_manifest_class( service.type)().get_service_manifest(service) manifest['Services'].append(svc_manifest) if do_delete: log("Deleting application %s, it contains an XtreemFS service" % appid) deleteapp(g.user.uid, appid, True) return build_response(simplejson.dumps(manifest))
def callmanager(app_id, service_id, method, post, data, files=[]): """Call the manager API. 'service_id': an integer holding the service id of the manager. 'method': a string representing the API method name. 'post': boolean value. True for POST method, false for GET. 'data': a dictionary representing the data to be sent to the director. 'files': sequence of (name, filename, value) tuples for data to be uploaded as files. callmanager loads the manager JSON response and returns it as a Python object. """ client.conpaas_init_ssl_ctx('/etc/cpsdirector/certs', 'director') application = get_app_by_id(g.user.uid, app_id) if application is None: msg = "Application %s not found." % app_id log_error(msg) return error_response(msg) elif application.to_dict()['manager'] is None: msg = "Application %s has not started. Try to start it first." % app_id log_error(msg) return error_response(msg) application = application.to_dict() # File upload if files: data['service_id'] = service_id res = client.https_post(application['manager'], 443, '/', data, files) # POST elif post: res = client.jsonrpc_post(application['manager'], 443, '/', method, service_id, data) # GET else: res = client.jsonrpc_get(application['manager'], 443, '/', method, service_id, data) if res[0] == 200: try: data = simplejson.loads(res[1]) except simplejson.decoder.JSONDecodeError: # Not JSON, simply return what we got return res[1] return data.get('result', data) raise Exception, "Call to method %s on %s failed: %s.\nParams = %s" % (method, application['manager'], res[1], data)
def _startapp(user_id, app_id, cloud_name, new_thread=True, ignore_status=False): log("User '%s' is attempting to start application %s" % (g.user.username, app_id)) app = get_app_by_id(user_id, app_id) if not app: msg = 'Application not found' log_error(msg) return error_response(msg) if not ignore_status and app.status not in (Application.A_INIT, Application.A_STOPPED): msg = 'Application already started' log_error(msg) return error_response(msg) if g.user.credit <= 0: msg = 'Insufficient credits' log_error(msg) return error_response(msg) try: app.status = Application.A_PROLOGUE db.session.commit() vpn = app.get_available_vpn_subnet() man_args = { 'role' : 'manager', 'user_id' : user_id, 'app_id' : app_id, 'vpn' : vpn, 'nodes_info' : [{ 'cloud' : cloud_name }], 'ignore_status': ignore_status } if new_thread: Thread(target=create_nodes, args=[man_args]).start() log('Application %s is starting' % (app_id)) else: res = create_nodes(man_args) log('Application %s has started' % (app_id)) return {} except Exception, err: app.status = Application.A_STOPPED exc_type, exc_value, exc_traceback = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_traceback) log(''.join('!! ' + line for line in lines)) msg = 'Error upon application starting: %s %s' % (type(err), err) log_error(msg) return error_response(msg)
def _add(service_type, app_id): log("User '%s' is attempting to add a new %s service to application %s" % (g.user.username, service_type, app_id)) # Use default application id if no appid was specified if not app_id: app = get_default_app(g.user.uid) if not app: msg = "No existing applications" log_error(msg) return error_response(msg) else: app_id = app.aid else: app = get_app_by_id(g.user.uid, app_id) # Check if we got a valid service type if service_type not in valid_services: msg = "Unknown service type '%s'" % service_type log_error(msg) return error_response(msg) data = { 'service_type': service_type } res = callmanager(app_id, 0, "add_service", True, data) if 'service_id' in res: sid = res['service_id'] s = Service(sid=sid, name="New %s service" % service_type, type=service_type, user=g.user, application=app, manager=app.to_dict()['manager']) db.session.add(s) db.session.commit() log('Service created successfully') return s.to_dict() return res
def decorated_view(*args, **kwargs): username = request.values.get('username', '') password = request.values.get('password', '') uuid = request.values.get('uuid', '') if uuid == '<none>': uuid = '' openid = request.values.get('openid', '') if openid == '<none>': openid = '' # Getting user data from DB through username and password if len(username.strip()): log("User '%s' is attempting to authenticate with " "username and password" % username) g.user = get_user(username, password) if g.user: # user authenticated through username and passwword return fn(*args, **kwargs) # authentication failed, try uuid # Getting user data from DB through uuid if len(uuid.strip()): log("User is attempting to authenticate with uuid '%s'" % uuid) g.user = get_user_by_uuid(uuid) if g.user: # user authenticated through uuid return fn(*args, **kwargs) # authentication failed, try openid # Getting user data from DB through openid if len(openid.strip()): log("User is attempting to authenticate with openid '%s'" % openid) g.user = get_user_by_openid(openid) if g.user: # user authenticated through openid return fn(*args, **kwargs) # authentication failed msg = "User authentication failed" log_error(msg) return build_response(jsonify(error_response(msg)))
def _deleteapp(user_id, app_id, del_app_entry): app = get_app_by_id(user_id, app_id) if not app: msg = 'Application not found' log_error(msg) return error_response(msg) # stop all services # we could ask the manager to kill the agents or kill them right here # if app.manager: # res = callmanager(app_id, 0, "stopall", True, {}) res_to_delete = [] for resource in Resource.query.filter_by(app_id=app_id): res_to_delete.append(ServiceNode(resource.vmid, resource.ip,'',resource.cloud,'')) resource.remove() Thread(target=delete_nodes, args=[res_to_delete]).start() # delete them from database (no need to remove them from application manager) for service in Service.query.filter_by(application_id=app_id): service.remove() # stop the application manager # if app.manager: # app.stop() app.status = Application.A_STOPPED # delete the applciation from the database if del_app_entry: db.session.delete(app) msg = "Application %s was deleted successfully" % app_id else: msg = "Application %s was stopped successfully" % app_id db.session.commit() log(msg) return {}
def _remove(app_id, service_id): log("User '%s' is attempting to remove service %s from application %s" % (g.user.username, service_id, app_id)) try: app_id = int(app_id) service_id = int(service_id) except: msg = 'Bad specification of application or service IDs' log_error(msg) return error_response(msg) data = { 'service_id': service_id } res = callmanager(app_id, 0, "remove_service", True, data) if 'error' in res: return res service = get_service(g.user.uid, app_id, service_id) service.remove() log('Service removed successfully') return {}
def create_nodes(): """GET /create_nodes""" app_id = request.values.get('app_id') service_id = request.values.get('service_id') service_type = request.values.get('service_type') manager_ip = request.values.get('manager_ip') startup_script = request.values.get('startup_script', None) # role = request.values.get('role') # log('startup_script :%s' % startup_script) # FIXME: make this get driectly a json nodes_info = simplejson.loads(request.values.get('nodes_info').replace("u'", '"').replace("'", '"')) context = simplejson.loads(request.values.get('context').replace("'", "\"")) # inst_type = request.values.get('inst_type') if g.user.credit <= 0: return build_response(jsonify(error_response('Insufficient credits'))) nodes = _create_nodes({ 'role':'agent', 'app_id':app_id, 'user_id':'%s'%g.user.uid, 'service_id':service_id, 'service_type':service_type, 'nodes_info':nodes_info, 'manager_ip':manager_ip, 'context':context, 'startup_script':startup_script }) return build_response(simplejson.dumps([node.to_dict() for node in nodes]))
def new_user(): values = {} all_fields = ('username', 'fname', 'lname', 'email', 'affiliation', 'password', 'credit', 'uuid', 'openid') required_fields = ('username', 'email', 'password') log('New user "%s <%s>" creation attempt' % ( request.values.get('username'), request.values.get('email'))) # check for presence of mandatory fields for field in all_fields: values[field] = request.values.get(field) if field == 'uuid' and values[field] == '<none>': values[field] = '' for field in required_fields: if not values[field]: msg = "Missing required field: '%s'" % field log_error(msg) return build_response(jsonify(error_response(msg))) # check if the provided username already exists if User.query.filter_by(username=values['username']).first(): msg = "Username '%s' is already taken" % values['username'] log_error(msg) return build_response(jsonify(error_response(msg))) # check if the provided email already exists if User.query.filter_by(email=values['email']).first(): msg = "E-mail '%s' is already registered" % values['email'] log_error(msg) return build_response(jsonify(error_response(msg))) # check that the requested credit does not exceed the maximum if config_parser.has_option('conpaas', 'MAX_CREDIT'): max_credit = config_parser.get('conpaas', 'MAX_CREDIT') try: max_credit = int(max_credit) except ValueError: log_error("Parameter MAX_CREDIT '%s' is not a valid integer." " Defaulting to maximum credit %s." % (max_credit, default_max_credit)) max_credit = default_max_credit if max_credit < 0: log_error("Parameter MAX_CREDIT '%s' cannot be a negative number." " Defaulting to maximum credit %s." % (max_credit, default_max_credit)) max_credit = default_max_credit else: max_credit = default_max_credit try: req_credit = int(values['credit']) except ValueError: msg = "Required credit '%s' is not a valid integer." % values['credit'] log_error(msg) return build_response(jsonify(error_response(msg))) if req_credit < 0: msg = "Required credit %s cannot be a negative integer." % values['credit'] log_error(msg) return build_response(jsonify(error_response(msg))) if req_credit > max_credit: msg = "Cannot allocate %s credit for a new user (max credit %s)." % (values['credit'], max_credit) log_error(msg) return build_response(jsonify(error_response(msg))) try: user = create_user(**values) # successful creation log("User '%s' created successfully" % user.username) return build_response(simplejson.dumps(user.to_dict())) except Exception, err: # something went wrong msg = 'Error upon user creation: %s -> %s' % (type(err), err) log_error(msg) return build_response(jsonify(error_response(msg)))