def download_manifest(appid): manifest = {} app = get_app_by_id(g.user.uid, appid) if not app: log('The appid %s does not exist' % appid) return simplejson.dumps(False) 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) return 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 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 _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 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 _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 _create_nodes(kwargs): role = kwargs.pop('role') nodes_info = kwargs.pop('nodes_info') clouds = _get_cloud_list(nodes_info) app_id = kwargs.pop('app_id') user_id = kwargs.pop('user_id') nodes = None service_id = 0 if role == 'manager': vpn = kwargs.pop('vpn') controller = ManagerController(user_id, app_id, vpn) controller.generate_context(clouds) nodes = controller.create_nodes(nodes_info, clouds) if not kwargs.pop('ignore_status'): from cpsdirector.application import Application, get_app_by_id application = get_app_by_id(user_id, app_id) application.status = Application.A_RUNNING else: service_id = kwargs.pop('service_id') service_type = kwargs.pop('service_type') manager_ip = kwargs.pop('manager_ip') context = kwargs.pop('context') startup_script = kwargs.pop('startup_script') log('Create node called for service type: %s' % service_type) controller = AgentController(user_id, app_id, service_id, service_type, manager_ip) controller.generate_context(clouds, context, startup_script) nodes = controller.create_nodes(nodes_info, clouds) if nodes: for node in nodes: resource = Resource(vmid=node.vmid, ip=node.ip, app_id=app_id, service_id=service_id, role=role, cloud=node.cloud_name) db.session.add(resource) db.session.flush() db.session.commit() Credit().check_credits() return nodes
def download_manifest(appid): manifest = {} app = get_app_by_id(g.user.uid, appid) if not app: log('The appid %s does not exist' % appid) return simplejson.dumps(False) manifest['Services'] = [] manifest['Application'] = app.name for service in Service.query.filter_by(application_id=appid): svc_manifest = get_manifest_class( service.type)().get_service_manifest(service) manifest['Services'].append(svc_manifest) return simplejson.dumps(manifest)
def download_manifest(appid): manifest = {} app = get_app_by_id(g.user.uid, appid) if not app: log('The appid %s does not exist' % appid) return simplejson.dumps(False) manifest['Services'] = [] manifest['Application'] = app.name for service in Service.query.filter_by(application_id=appid): tmp = {} tmp['Type'] = service.type tmp['ServiceName'] = service.name tmp['Cloud'] = service.cloud manifest['Services'].append(tmp) return simplejson.dumps(manifest)
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'
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