def upload_manifest(): json = request.values.get('manifest') if not json: log('"manifest" is a required argument') return build_response(simplejson.dumps(False)) log('User %s has uploaded the following manifest %s' % (g.user.username, json)) if not check_manifest(json): return simplejson.dumps(False) if request.values.get('thread'): log('Starting a new process for the manifest') p = Process(target=new_manifest, args=(json,)) p.start() log('Process started, now return') return simplejson.dumps(True) msg = new_manifest(json) if msg is not 'ok': return build_response(jsonify({ 'error' : True, 'msg' : msg })) log('Manifest created') return simplejson.dumps(True)
def stop(serviceid): """eg: POST /stop/3 POSTed values must contain username and password. Returns a boolean value. True in case of successful authentication and proper service termination. False otherwise. """ log('User %s attempting to stop service %s' % (g.user.uid, serviceid)) # Test if a service with id 'serviceid' exists and user is the owner service = get_service(g.user.uid, serviceid) if not service: return build_response(simplejson.dumps(False)) # Try to cleanly terminate the service try: # If the service is in INIT or STOPPED state, we can just kill # the manager VM res = callmanager(serviceid, "get_service_info", False, {}) if res['state'] == 'INIT' or res['state'] == 'STOPPED': service.stop() else: # Else, we should ask the manager to cleanly shut down itself callmanager(serviceid, "delete", True, {}) # If this fails, forcefully terminate the manager VM except: service.stop() return build_response(simplejson.dumps(True))
def upload_manifest(): json = request.values.get('manifest') if not json: log('"manifest" is a required argument') return build_response(simplejson.dumps(False)) log('User %s has uploaded the following manifest %s' % (g.user.username, json)) if not check_manifest(json): return simplejson.dumps(False) if request.values.get('thread'): log('Starting a new process for the manifest') p = Process(target=new_manifest, args=(json, )) p.start() log('Process started, now return') return simplejson.dumps(True) msg = new_manifest(json) if msg != 'ok': return build_response(jsonify({'error': True, 'msg': msg})) log('Manifest created') return simplejson.dumps(True)
def createapp(): app_name = request.values.get('name') if not app_name: log('"name" is a required argument') return build_response(simplejson.dumps(False)) return build_response(_createapp(app_name))
def createapp(): app_name = request.values.get('name') if not app_name: log('"name" is a required argument') return build_response(simplejson.dumps(False)) return build_response(_createapp(app_name))
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 decorated(*args, **kwargs): g.cert = {} if os.environ.get('DIRECTOR_TESTING'): # No SSL certificate check if we are testing. Trust what the # client is sending. g.cert['UID'] = request.values.get('uid') g.cert['role'] = request.values.get('role') # g.cert['serviceLocator'] = request.values.get('sid') g.cert['serviceLocator'] = request.values.get('aid') else: cert = request.environ['SSL_CLIENT_CERT'] for key in 'serviceLocator', 'UID', 'role': g.cert[key] = https.x509.get_x509_dn_field(cert, key) try: uid = int(g.cert['UID']) except (AttributeError, ValueError, TypeError): error_msg = 'cert_required: client certificate does NOT provide UID' log(error_msg) return make_response(error_msg, 401) # Getting user data from DB g.user = User.query.get(uid) if not g.user: # authentication failed return build_response(simplejson.dumps(False)) if self.role == 'manager': # manager cert required try: service_locator = int(g.cert['serviceLocator']) except (AttributeError, ValueError): error_msg = 'cert_required: client certificate does NOT provide serviceLocator' log(error_msg) # Return HTTP_UNAUTHORIZED return make_response(error_msg, 401) # check if the service is actually owned by the user # from cpsdirector.service import get_service # g.service = get_service(uid, service_locator) # if not g.service: # return build_response(simplejson.dumps(False)) from cpsdirector.application import get_app_by_id g.application = get_app_by_id(uid, service_locator) if not g.application: return build_response(simplejson.dumps(False)) log('cert_required: valid certificate (user %s, application %s)' % (uid, service_locator)) return fn(*args, **kwargs)
def new_user(): values = {} required_fields = ('username', 'fname', 'lname', 'email', 'affiliation', 'password', 'credit') log('New user "%s <%s>" creation attempt' % (request.values.get('username'), request.values.get('email'))) # check for presence of mandatory fields for field in required_fields: values[field] = request.values.get(field) if not values[field]: log('Missing required field: %s' % field) return build_response( jsonify({ 'error': True, 'msg': '%s is a required field' % field })) # check if the provided username already exists if User.query.filter_by(username=values['username']).first(): log('User %s already exists' % values['username']) return build_response( jsonify({ 'error': True, 'msg': 'Username "%s" already taken' % values['username'] })) # check if the provided email already exists if User.query.filter_by(email=values['email']).first(): log('Duplicate email: %s' % values['email']) return build_response( jsonify({ 'error': True, 'msg': 'E-mail "%s" already registered' % values['email'] })) 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 error_msg = 'Error upon user creation: %s -> %s' % (type(err), err) log(error_msg) return build_response(jsonify({'error': True, 'msg': error_msg}))
def credit(): """POST /callback/decrementUserCredit.php POSTed values must contain sid and decrement. Returns a dictionary with the 'error' attribute set to False if the user had enough credit, True otherwise. """ app_id = int(request.values.get('aid', -1)) decrement = int(request.values.get('decrement', 1)) success = _deduct_credit(app_id, decrement) if success: return build_response(jsonify({'error': False})) return build_response(jsonify({'error': True}))
def _start(servicetype, cloudname, appid): log('User %s creating a new %s service inside application %s' % ( g.user.username, servicetype, appid)) # Check if we got a valid service type if servicetype not in valid_services: error_msg = 'Unknown service type: %s' % servicetype log(error_msg) return build_response(jsonify({ 'error': True, 'msg': error_msg })) app = get_app_by_id(g.user.uid, appid) if not app: return build_response(jsonify({ 'error': True, 'msg': "Application not found" })) # Do we have to assign a VPN subnet to this service? vpn = app.get_available_vpn_subnet() # Default name if servicetype == 'galera': defaultname = 'New MySQL service'; else: defaultname = "New %s service" % servicetype # New service with default name, proper servicetype and user relationship s = Service(name=defaultname, type=servicetype, user=g.user, application=app, subnet=vpn) db.session.add(s) # flush() is needed to get auto-incremented sid db.session.flush() try: s.manager, s.manager_port, s.vmid, s.cloud = manager_controller.start( servicetype, s.sid, g.user.uid, cloudname, appid, vpn) except Exception, err: try: db.session.delete(s) db.session.commit() except InvalidRequestError: db.session.rollback() 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)) error_msg = 'Error upon service creation: %s' % err log(error_msg) return build_response(jsonify({ 'error': True, 'msg': error_msg }))
def user_config(): """ Returns all information about a user identified by a certificate. """ user = g.user.to_dict() user.pop('password', None) return build_response(simplejson.dumps(user))
def renameapp(appid): newname = request.values.get('name') if not newname: log('"name" is a required argument') return build_response(simplejson.dumps(False)) return _renameapp(appid, newname)
def decorated_view(*args, **kwargs): username = request.values.get('username', '') password = request.values.get('password', '') uuid = request.values.get('uuid', '') if uuid == '<none>': uuid = '' # Getting user data from DB through username and password if len(username.strip()): log('authentication attempt for <%s, %s> ' % (username, password) ) 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('authentication attempt for <%s> ' % (uuid) ) g.user = get_user_by_uuid(uuid) if g.user: # user authenticated through uuid return fn(*args, **kwargs) # authentication failed return build_response(simplejson.dumps(False))
def remove(): """Terminate the service whose id matches the one provided in the manager certificate.""" app_id = request.values.get('app_id') service_id = request.values.get('service_id') return build_response(jsonify(_remove(app_id, service_id)))
def rename(serviceid): newname = request.values.get('name') if not newname: log('"name" is a required argument') return build_response(simplejson.dumps(False)) return _rename(serviceid, newname)
def decorated(*args, **kwargs): g.cert = {} if os.environ.get('DIRECTOR_TESTING'): # No SSL certificate check if we are testing. Trust what the # client is sending. g.cert['UID'] = request.values.get('uid') g.cert['role'] = request.values.get('role') g.cert['serviceLocator'] = request.values.get('sid') else: cert = request.environ['SSL_CLIENT_CERT'] for key in 'serviceLocator', 'UID', 'role': g.cert[key] = https.x509.get_x509_dn_field(cert, key) try: uid = int(g.cert['UID']) except (AttributeError, ValueError, TypeError): error_msg = 'cert_required: client certificate does NOT provide UID' log(error_msg) return make_response(error_msg, 401) # Getting user data from DB g.user = User.query.get(uid) if not g.user: # authentication failed return build_response(simplejson.dumps(False)) if self.role == 'manager': # manager cert required try: service_locator = int(g.cert['serviceLocator']) except (AttributeError, ValueError): error_msg = 'cert_required: client certificate does NOT provide serviceLocator' log(error_msg) # Return HTTP_UNAUTHORIZED return make_response(error_msg, 401) # check if the service is actually owned by the user from cpsdirector.service import get_service g.service = get_service(uid, service_locator) if not g.service: return build_response(simplejson.dumps(False)) log('cert_required: valid certificate (user %s, service %s)' % (uid, service_locator)) return fn(*args, **kwargs)
def _start(servicetype, cloudname, appid): log('User %s creating a new %s service inside application %s' % (g.user.username, servicetype, appid)) # Check if we got a valid service type if servicetype not in valid_services: error_msg = 'Unknown service type: %s' % servicetype log(error_msg) return build_response(jsonify({'error': True, 'msg': error_msg})) app = get_app_by_id(g.user.uid, appid) if not app: return build_response( jsonify({ 'error': True, 'msg': "Application not found" })) # Do we have to assign a VPN subnet to this service? vpn = app.get_available_vpn_subnet() # New service with default name, proper servicetype and user relationship s = Service(name="New %s service" % servicetype, type=servicetype, user=g.user, application=app, subnet=vpn) db.session.add(s) # flush() is needed to get auto-incremented sid db.session.flush() try: s.manager, s.vmid, s.cloud = manager_controller.start( servicetype, s.sid, g.user.uid, cloudname, appid, vpn) except Exception, err: try: db.session.delete(s) db.session.commit() except InvalidRequestError: db.session.rollback() 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)) error_msg = 'Error upon service creation: %s %s' % (type(err), err) log(error_msg) return build_response(jsonify({'error': True, 'msg': error_msg}))
def stop(serviceid): """eg: POST /stop/3 POSTed values must contain username and password. Returns a boolean value. True in case of successful authentication and proper service termination. False otherwise. """ log('User %s attempting to stop service %s' % (g.user.uid, serviceid)) service = get_service(g.user.uid, serviceid) if not service: return build_response(simplejson.dumps(False)) # If a service with id 'serviceid' exists and user is the owner service.stop() return build_response(simplejson.dumps(True))
def list_all_services(): """POST /list List running ConPaaS services under a specific application if the user is authenticated. Return False otherwise. """ return build_response( simplejson.dumps([ser.to_dict() for ser in g.user.services.all()]))
def available_clouds(): """GET /available_clouds""" clouds = ['default'] if config_parser.has_option('iaas','OTHER_CLOUDS'): clouds.extend([cloud_name for cloud_name in config_parser.get('iaas', 'OTHER_CLOUDS').split(',') if config_parser.has_section(cloud_name)]) return build_response(simplejson.dumps(clouds))
def list_applications(): """POST /listapp List all the ConPaaS applications if the user is authenticated. Return False otherwise. """ return build_response( simplejson.dumps([app.to_dict() for app in g.user.applications.all()]))
def stop(serviceid): """eg: POST /stop/3 POSTed values must contain username and password. Returns a boolean value. True in case of successful authentication and proper service termination. False otherwise. """ log('User %s attempting to stop service %s' % (g.user.uid, serviceid)) service = get_service(g.user.uid, serviceid) if not service: return build_response(simplejson.dumps(False)) # If a service with id 'serviceid' exists and user is the owner service.stop() return build_response(simplejson.dumps(True))
def list_all_services(): """POST /list List running ConPaaS services under all applications if the user is authenticated. Return False otherwise. """ return build_response(simplejson.dumps([ ser.to_dict() for ser in Service.query.join(Application).filter_by(user_id=g.user.uid) ]))
def list_applications(): """POST /listapp List all the ConPaaS applications if the user is authenticated. Return False otherwise. """ return build_response(simplejson.dumps([ app.to_dict() for app in g.user.applications.all() ]))
def list_services(appid): """POST /list/2 List running ConPaaS services under a specific application if the user is authenticated. Return False otherwise. """ return build_response(simplejson.dumps([ ser.to_dict() for ser in Service.query.filter_by(application_id=appid) ]))
def list_resources(): from cpsdirector.application import Application res = [res.to_dict() for res in Resource.query.join(Application).filter_by(user_id=g.user.uid)] for row in res: if row['cloud'] == 'iaas': row['cloud'] = 'default' return build_response(simplejson.dumps(res))
def list_all_services(): """POST /list List running ConPaaS services under a specific application if the user is authenticated. Return False otherwise. """ return build_response(simplejson.dumps([ ser.to_dict() for ser in g.user.services.all() ]))
def new_user(): values = {} required_fields = ( 'username', 'fname', 'lname', 'email', 'affiliation', 'password', 'credit' ) log('New user "%s <%s>" creation attempt' % ( request.values.get('username'), request.values.get('email'))) # check for presence of mandatory fields for field in required_fields: values[field] = request.values.get(field) if not values[field]: log('Missing required field: %s' % field) return build_response(jsonify({ 'error': True, 'msg': '%s is a required field' % field })) # check if the provided username already exists if User.query.filter_by(username=values['username']).first(): log('User %s already exists' % values['username']) return build_response(jsonify({ 'error': True, 'msg': 'Username "%s" already taken' % values['username'] })) # check if the provided email already exists if User.query.filter_by(email=values['email']).first(): log('Duplicate email: %s' % values['email']) return build_response(jsonify({ 'error': True, 'msg': 'E-mail "%s" already registered' % values['email'] })) 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 error_msg = 'Error upon user creation: %s -> %s' % (type(err), err) log(error_msg) return build_response(jsonify({ 'error': True, 'msg': error_msg }))
def _renameapp(appid, newname): log('User %s attempting to rename application %s' % (g.user.uid, appid)) app = get_app_by_id(g.user.uid, appid) if not app: return build_response(simplejson.dumps(False)) app.name = newname db.session.commit() return simplejson.dumps(True)
def delete(appid): """eg: POST /delete/3 POSTed values must contain username and password. Returns a boolean value. True in case of successful authentication and proper service termination. False otherwise. """ log('User %s attempting to delete application %s' % (g.user.uid, appid)) return build_response(simplejson.dumps(deleteapp(g.user.uid, appid)))
def delete(appid): """eg: POST /delete/3 POSTed values must contain username and password. Returns a boolean value. True in case of successful authentication and proper service termination. False otherwise. """ log('User %s attempting to delete application %s' % (g.user.uid, appid)) return build_response(simplejson.dumps(deleteapp(g.user.uid, appid)))
def _renameapp(appid, newname): log('User %s attempting to rename application %s' % (g.user.uid, appid)) app = get_app_by_id(g.user.uid, appid) if not app: return build_response(simplejson.dumps(False)) app.name = newname db.session.commit() return simplejson.dumps(True)
def list_services(appid): """POST /list/2 List running ConPaaS services under a specific application if the user is authenticated. Return False otherwise. """ return build_response( simplejson.dumps([ ser.to_dict() for ser in Service.query.filter_by(application_id=appid) ]))
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 decorated_view(*args, **kwargs): username = request.values.get('username', '') password = request.values.get('password', '') # Getting user data from DB g.user = get_user(username, password) if g.user: # user authenticated return fn(*args, **kwargs) # authentication failed return build_response(simplejson.dumps(False))
def decorated_view(*args, **kwargs): username = request.values.get('username', '') password = request.values.get('password', '') # Getting user data from DB g.user = get_user(username, password) if g.user: # user authenticated return fn(*args, **kwargs) # authentication failed return build_response(simplejson.dumps(False))
def destroy_volume(): """POST /destroy_volume""" volume_id = str(request.values.get('volume_id')) cloud = str(request.values.get('cloud')) controller = Controller() controller.setup_default() controller.destroy_volume(volume_id, cloud) log('Destroyed volume %s (cloud: %s)' % (volume_id, cloud)) return build_response(simplejson.dumps({}))
def add(servicetype): """eg: POST /start/php POSTed values might contain 'appid' to specify that the service to be created has to belong to a specific application. If 'appid' is omitted, the service will belong to the default application. Returns a dictionary with service data (manager's vmid and IP address, service name and ID) in case of successful authentication and correct service creation. False is returned otherwise. """ appid = request.values.get('appid') return build_response(jsonify(_add(servicetype, appid)))
def delete(appid): """eg: POST /delete/3 POSTed values must contain username and password. Returns a boolean value. True in case of successful authentication and proper service termination. False otherwise. """ log('User %s attempting to delete application %s' % (g.user.uid, appid)) app = get_app_by_id(g.user.uid, appid) if not app: return build_response(simplejson.dumps(False)) # If an application with id 'appid' exists and user is the owner for service in Service.query.filter_by(application_id=appid): callmanager(service.sid, "shutdown", True, {}) stop(service.sid) db.session.delete(app) db.session.commit() return build_response(simplejson.dumps(True))
def _rename(serviceid, newname): log('User %s attempting to rename service %s' % (g.user.uid, serviceid)) service = get_service(g.user.uid, serviceid) if not service: return make_response(simplejson.dumps(False)) if not newname: log('"name" is a required argument') return build_response(simplejson.dumps(False)) service.name = newname db.session.commit() return simplejson.dumps(True)
def _rename(serviceid, newname): log('User %s attempting to rename service %s' % (g.user.uid, serviceid)) service = get_service(g.user.uid, serviceid) if not service: return make_response(simplejson.dumps(False)) if not newname: log('"name" is a required argument') return build_response(simplejson.dumps(False)) service.name = newname db.session.commit() return simplejson.dumps(True)
def delete(appid): """eg: POST /delete/3 POSTed values must contain username and password. Returns a boolean value. True in case of successful authentication and proper service termination. False otherwise. """ log('User %s attempting to delete application %s' % (g.user.uid, appid)) app = get_app_by_id(g.user.uid, appid) if not app: return build_response(simplejson.dumps(False)) # If an application with id 'appid' exists and user is the owner for service in Service.query.filter_by(application_id=appid): callmanager(service.sid, "shutdown", True, {}) stop(service.sid) db.session.delete(app) db.session.commit() return build_response(simplejson.dumps(True))
def attach_volume(): """POST /attach_volume""" vm_id =str(request.values.get('vm_id')) volume_id = str(request.values.get('volume_id')) device_name = str(request.values.get('device_name')) cloud = str(request.values.get('cloud')) controller = Controller() controller.setup_default() controller.attach_volume(vm_id, volume_id, device_name, cloud) log('Attached volume %s to vm %s (cloud: %s)' % (volume_id, vm_id, cloud)) return build_response(simplejson.dumps({}))
def create_volume(): """GET /create_nodes""" size = int(request.values.get('size')) name = str(request.values.get('name')) vm_id =str(request.values.get('vm_id')) cloud = str(request.values.get('cloud')) controller = Controller() controller.setup_default() volume = controller.create_volume(size, name, vm_id, cloud) log('Created volume %s ' % volume.id) return build_response(simplejson.dumps({'volume_id':volume.id }))
def remove_nodes(): """GET /create_nodes""" nodes = simplejson.loads(request.values.get('nodes')) log('Deleting %s nodes' % len(nodes)) serv_nodes = [ServiceNode(node['vmid'], node['ip'],node['private_ip'],node['cloud_name'],node['weight_backend']) for node in nodes] controller = Controller() controller.setup_default() controller.delete_nodes(serv_nodes) for node in nodes: res = get_resource_by_id(node['vmid']) res.remove() return build_response(simplejson.dumps({}))
def login(): log('Successful login for user %s' % g.user.username) # return user data return build_response(simplejson.dumps(g.user.to_dict()))
try: db.session.delete(s) db.session.commit() except InvalidRequestError: db.session.rollback() 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)) error_msg = 'Error upon service creation: %s %s' % (type(err), err) log(error_msg) return build_response(jsonify({'error': True, 'msg': error_msg})) db.session.commit() log('%s (id=%s) created properly' % (s.name, s.sid)) return build_response(jsonify(s.to_dict())) @service_page.route("/start/<servicetype>", methods=['POST']) @service_page.route("/start/<servicetype>/<cloudname>", methods=['POST']) @cert_required(role='user') def start(servicetype, cloudname="default"): """eg: POST /start/php POSTed values might contain 'appid' to specify that the service to be created has to belong to a specific application. If 'appid' is omitted, the service will belong to the default application. Returns a dictionary with service data (manager's vmid and IP address, service name and ID) in case of successful authentication and correct service creation. False is returned otherwise.
def version(): version = pkg_resources.require("cpsdirector")[0].version return build_response(version)