Exemplo n.º 1
0
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))
Exemplo n.º 2
0
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()
Exemplo n.º 3
0
def check_manifest(json):
    try:
        parse = simplejson.loads(json)
    except:
        log_error('The uploaded manifest is not valid json')
        return False

    for service in parse.get('Services'):
        if not service.get('Type'):
            log_error('The "Type" field is mandatory')
            return False

    return True
Exemplo n.º 4
0
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)
Exemplo n.º 5
0
def _deduct_credit(decrement):

    # Require decrement to be a positive integer
    if decrement <= 0:
        log_error('Decrement should be a positive integer')
        return False

    log('Decrement user credit: uid=%s, old_credit=%s, decrement=%s' % (g.user.uid, g.user.credit, decrement))
    g.user.credit -= decrement
    if g.user.credit > -1:
        # User has enough credit
        db.session.commit()
        log('New credit for user %s: %s' % (g.user.uid, g.user.credit))
        return True

    db.session.rollback()
    log_error('User %s does not have enough credit' % g.user.uid)
    return False
Exemplo n.º 6
0
    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)))
Exemplo n.º 7
0
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 }))
Exemplo n.º 8
0
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 {}
Exemplo n.º 9
0
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 {}
Exemplo n.º 10
0
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 {}
Exemplo n.º 11
0
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 {}
Exemplo n.º 12
0
def start_manifest_app(parse, appid, cloud='default'):

    res = startapp(g.user.uid, appid, cloud, new_thread=False, ignore_status=True)
    # res = startapp(g.user.uid, appid, cloud, ignore_status=True)
    if 'error' in res:
        return res['error']

    app = get_app_by_id(g.user.uid, appid)

    # #FIXME: add a timeout here
    # while app.status != Application.A_RUNNING:
    #     # log('application is in status:%s, manager:%s' % (app.status, app.manager))
    #     time.sleep(8)
    #     app = get_app_by_id(g.user.uid, appid)
    #     db.session.refresh(app)
    #     # app = get_app_by_id(g.user.uid, appid)

    log('Now start adding services for application %s' % appid)
    app.status = Application.A_ADAPTING
    db.session.commit()

    for service in parse.get('Services'):
        try:
            cls = get_manifest_class(service.get('Type'))
        except Exception:
            return 'Service %s does not exists' % service.get('Type')

        msg = cls().start(service, appid, cloud)
        if msg is not 'ok':
            log_error('Error starting %s service -> %s' % (service, msg))
            return msg

    log('All services of application %s are now running' % appid)
    app.status = Application.A_RUNNING
    db.session.commit()

    return 'ok'
Exemplo n.º 13
0
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
Exemplo n.º 14
0
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)
Exemplo n.º 15
0
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)))