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 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 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 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 _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 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 get_manager_cert(): log('Certificate request from manager %s (user %s)' % ( g.cert['serviceLocator'], g.cert['UID'])) csr = crypto.load_certificate_request(crypto.FILETYPE_PEM, request.files['csr'].read()) return x509cert.create_x509_cert(config_parser.get('conpaas', 'CERT_DIR'), csr)
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 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 _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 get_service_manifest(self, service): tmp = MGeneral.get_service_manifest(self, service) self.set_persistent(service.sid) log('Calling get_service_snapshot') snapshot = callmanager(service.sid, 'get_service_snapshot', True, {}) if 'StartupInstances' not in tmp: tmp['StartupInstances'] = {} tmp['StartupInstances']['resume'] = [] for node in snapshot: node_filename = self.__get_node_archive_filename(node) data = base64.b64decode(node.pop('data')) open(node_filename, 'wb').write(data) log('%s created' % node_filename) node['archive'] = '%s/download_data/%s' % (get_director_url(), basename(node_filename)) tmp['StartupInstances']['resume'].append(node) return tmp
def get_user_certs(): # Creates new certificates for this user certs = x509cert.generate_certificate( cert_dir=config_parser.get('conpaas', 'CERT_DIR'), uid=str(g.user.uid), sid='0', role='user', email=g.user.email, cn=g.user.username, org='Contrail' ) # In-memory zip file zipdata = StringIO() archive = zipfile.ZipFile(zipdata, mode='w') # Add key.pem, cert.pem and ca_cert.pem to the zip file for name, data in certs.items(): archive.writestr(name + '.pem', data) archive.close() zipdata.seek(0) log('New certificates for user %s created' % g.user.username) # Send zip archive to the client return helpers.send_file(zipdata, mimetype="application/zip", as_attachment=True, attachment_filename='certs.zip')
def get_user_certs(): # Creates new certificates for this user certs = x509cert.generate_certificate(cert_dir=config_parser.get( 'conpaas', 'CERT_DIR'), uid=str(g.user.uid), sid='0', role='user', email=g.user.email, cn=g.user.username, org='Contrail') # In-memory zip file zipdata = StringIO() archive = zipfile.ZipFile(zipdata, mode='w') # Add key.pem, cert.pem and ca_cert.pem to the zip file for name, data in certs.items(): archive.writestr(name + '.pem', data) archive.close() zipdata.seek(0) log('New certificates for user %s created' % g.user.username) # Send zip archive to the client return helpers.send_file(zipdata, mimetype="application/zip", as_attachment=True, attachment_filename='certs.zip')
def get_service_manifest(self, service): tmp = MGeneral.get_service_manifest(self, service) self.set_persistent(service.sid) log('Calling get_service_snapshot') snapshot = callmanager(service.sid, 'get_service_snapshot', True, {}) if 'StartupInstances' not in tmp: tmp['StartupInstances'] = {} tmp['StartupInstances']['resume'] = {} tmp['StartupInstances']['resume']['nodes'] = [] for node in snapshot['nodes']: node_filename = self.__get_node_archive_filename(node) data = base64.b64decode(node.pop('data')) open(node_filename, 'wb').write(data) log('%s created' % node_filename) node['archive'] = '%s/download_data/%s' % (get_director_url(), basename(node_filename)) tmp['StartupInstances']['resume']['nodes'].append(node) tmp['StartupInstances']['resume']['manager'] = snapshot['manager'] return tmp
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 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 get_manager_cert(): log('Certificate request from manager %s (user %s)' % (g.cert['serviceLocator'], g.cert['UID'])) csr = crypto.load_certificate_request(crypto.FILETYPE_PEM, request.files['csr'].read()) return x509cert.create_x509_cert(config_parser.get('conpaas', 'CERT_DIR'), csr)
def start(self, json, appid): try: to_resume = { 'nodes': json['StartupInstances']['resume']['nodes'], 'manager' : json['StartupInstances']['resume']['manager'] } except KeyError: to_resume = {} # Set the resuming flag if necessary self.resuming = to_resume != {} sid = MGeneral.start(self, json, appid) if type(sid) != int: # Error! return sid if json.get('VolumeStartup'): name = json.get('VolumeStartup').get('volumeName') owner = json.get('VolumeStartup').get('owner') # Wait few seconds so that the new node is up. time.sleep(20) if name != "" and owner != "": res = self.createvolume(sid, name, owner) if 'error' in res: return res['error'] if json.get('StartupInstances'): params = { 'osd': 1 } if json.get('StartupInstances').get('osd'): params['osd'] = int(json.get('StartupInstances').get('osd')) # We have started the service already, so one OSD node is there # for sure. params['osd'] -= 1 params['resuming'] = to_resume res = self.add_nodes(sid, params) if 'error' in res: return res['error'] if to_resume: log('Resuming the following xtreemfs nodes: %s' % to_resume) self.wait_for_state(sid, 'RUNNING') res = callmanager(sid, "set_service_snapshot", True, to_resume) if 'error' in res: return res['error'] else: log('No xtreemfs node to be resumed') return 'ok'
def download(): """GET /download/ConPaaS.tar.gz Returns ConPaaS tarball. """ log('ConPaaS tarball downloaded') return helpers.send_from_directory(common.config_parser.get('conpaas', 'CONF_DIR'), "ConPaaS.tar.gz")
def stop(self, vmid): log('Trying to stop service %s on cloud %s' % (vmid, self.cloud_name)) cloud = self.get_cloud_by_name(self.cloud_name) if not cloud.connected: cloud._connect() cloud.kill_instance(ServiceNode(vmid, None, None, self.cloud_name)) self._stop_reservation_timer()
def shutdown(self, service_id): res = callmanager(service_id, "get_service_info", False, {}) if res['state'] == "RUNNING": res = callmanager(service_id, "shutdown", True, {}) else: log("Service is in '%(state)s' state. We can not stop it." % res) return res
def save_dump(self, service_id): res = callmanager(service_id, 'sqldump', False, {}) if type(res) is dict and 'error' in res: log('Error getting SQL dump: %s' % res['error']) return '' _, temp_path = mkstemp(dir=get_userdata_dir()) open(temp_path, 'w').write(res) return '%s/download_data/%s' % (get_director_url(), basename(temp_path))
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 set_persistent(self, service_id): res = callmanager(service_id, 'get_service_info', False, {}) if res['persistent']: log('Service %s is already persistent' % service_id) else: res = callmanager(service_id, 'toggle_persistent', True, {}) log('Service %s is now persistent' % service_id) return res['persistent']
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 terminate(): """Terminate the service whose id matches the one provided in the manager certificate.""" log('User %s attempting to terminate service %s' % (g.user.uid, g.service.sid)) if g.service.stop(): return jsonify({ 'error': False }) return jsonify({ 'error': True })
def stop(self): controller = manager_controller.ManagerController(self.type, self.sid, self.user_id, self.cloud, self.application_id, self.subnet) controller.stop(self.vmid) db.session.delete(self) db.session.commit() log('Service %s stopped properly' % self.sid) return True
def stop(self): controller = manager_controller.ManagerController( self.type, self.sid, self.user_id, self.cloud, self.application_id, self.subnet) controller.stop(self.vmid) db.session.delete(self) db.session.commit() log('Service %s stopped properly' % self.sid) return True
def terminate(): """Terminate the service whose id matches the one provided in the manager certificate.""" log('User %s attempting to terminate service %s' % (g.user.uid, g.service.sid)) if g.service.stop(): return jsonify({'error': False}) return jsonify({'error': True})
def start(self, json, appid): try: to_resume = {'nodes': json['StartupInstances']['resume']} except KeyError: to_resume = {} # Set the resuming flag if necessary self.resuming = to_resume != {} sid = MGeneral.start(self, json, appid) if type(sid) != int: # Error! return sid if json.get('VolumeStartup'): name = json.get('VolumeStartup').get('volumeName') owner = json.get('VolumeStartup').get('owner') # Wait few seconds so that the new node is up. time.sleep(20) if name != "" and owner != "": res = self.createvolume(sid, name, owner) if 'error' in res: return res['error'] if json.get('StartupInstances'): params = {'osd': 1} if json.get('StartupInstances').get('osd'): params['osd'] = int(json.get('StartupInstances').get('osd')) # We have started the service already, so one OSD node is there # for sure. params['osd'] -= 1 params['resuming'] = to_resume res = self.add_nodes(sid, params) if 'error' in res: return res['error'] if to_resume: log('Resuming the following xtreemfs nodes: %s' % to_resume) self.wait_for_state(sid, 'RUNNING') res = callmanager(sid, "set_service_snapshot", True, to_resume) if 'error' in res: return res['error'] else: log('No xtreemfs node to be resumed') return 'ok'
def get_app_by_name(user_id, app_name): app = Application.query.filter_by(name=app_name).first() if not app: log('Application %s does not exist' % app_name) return if app.user_id != user_id: log('Application %s is not owned by user %s' % (app_name, user_id)) return return app
def get_service(user_id, service_id): service = Service.query.filter_by(sid=service_id).first() if not service: log('Service %s does not exist' % service_id) return if service.user_id != user_id: log('Service %s is not owned by user %s' % (service_id, user_id)) return return service
def list_services(appid): """POST /list/2 List running ConPaaS services under a specific application if the user is authenticated. Return False otherwise. """ services = [ser.to_dict() for ser in Service.query.filter_by(application_id=appid)] try: services = __manager_port_map(services) except Exception,e: log("Service mapping port failed as %s"%e)
def get_app_by_id(user_id, app_id): app = Application.query.filter_by(aid=app_id).first() if not app: log('Application %s does not exist' % app_id) return if int(app.user_id) != int(user_id): log('Application %s is not owned by user %s' % (app_id, user_id)) return return app
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 check_manifest(json): try: parse = simplejson.loads(json) except: log('The uploaded manifest is not valid json') return False for service in parse.get('Services'): if not service.get('Type'): log('The "Type" field is mandatory') return False return True
def start(self, json, appid, cloud): #start = json.get('Start') #this is to prevent startup being called without passing the manifest, should be changed #json['Start'] = 0 sid = MGeneral.start(self, json, appid, cloud) #json['Start'] = start #if not json.get('Start') or json.get('Start') == 0: # return sid # Start == 1 #res = self.startup(sid, json) #if 'error' in res: # return res['error'] #self.wait_for_state(sid, 'RUNNING') #return sid if json.get('Archive'): res = self.upload_code(appid, sid, json.get('Archive')) if 'error' in res: return res['error'] res = self.enable_code(appid, sid, res['codeVersionId']); if 'error' in res: return res['error'] self.wait_for_state(sid, 'RUNNING') if json.get('StartupInstances'): instances = json.get('StartupInstances') nr_instances = 0 for role in instances: nr_instances += int(instances[role]) if nr_instances: start_role = '*' if json.get('StartRole'): start_role = json.get('StartRole') params = { "nodes" : instances, "start_role" : start_role } res = self.add_nodes(sid, params) if 'error' in res: log('generic.start: error calling add_nodes -> %s' % res) return res['error'] return 'ok'
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 deduct_credit(self, value): uid = self.config_parser.get("manager", "USER_ID") service_id = self.config_parser.get("manager", "SERVICE_ID") user = User.query.filter_by(uid=uid).one() log('Decrement user %s credit: sid=%s, old_credit=%s, decrement=%s' % (uid, service_id, user.credit, value)) user.credit -= value if user.credit > -1: db.session.commit() log('New credit for user %s: %s' % (uid, user.credit)) return True db.session.rollback() return False
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 new_manifest(json): try: parse = simplejson.loads(json) except: return 'Error parsing json' # 'Application' has to be defined app_name = parse.get('Application') if not app_name: return 'Application is not defined' if not check_app_exists(app_name): # Create application if it does not exist yet res = createapp(app_name) appid = simplejson.loads(res.data).get('aid') else: # Try different application names for i in range(2, 99): new_name = "%s (%d)" % (app_name, i) if not check_app_exists(new_name): res = createapp(new_name) appid = simplejson.loads(res.data).get('aid') break # If all the applications exists, then exit if i is 99: return 'Application can not be created' if not parse.get('Services'): return 'ok' 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) if msg is not 'ok': log('new_manifest: error starting %s service -> %s' % (service, msg)) return msg return 'ok'
def start(self, json, appid): sid = MGeneral.start(self, json, appid, need_env=True) if type(sid) != int: # Error! return sid if json.get('Archive'): res = self.upload_code(sid, json.get('Archive')) if 'error' in res: return res['error'] res = self.enable_code(sid, res['codeVersionId']) if 'error' in res: return res['error'] self.wait_for_state(sid, 'RUNNING') if json.get('StartupInstances'): params = {'proxy': 1, 'web': 1, 'backend': 1} if json.get('StartupInstances').get('proxy'): params['proxy'] = int( json.get('StartupInstances').get('proxy')) params['proxy'] -= 1 if json.get('StartupInstances').get('web'): params['web'] = int(json.get('StartupInstances').get('web')) params['web'] -= 1 if json.get('StartupInstances').get('backend'): params['backend'] = int( json.get('StartupInstances').get('backend')) params['backend'] -= 1 if params['proxy'] or params['web'] or params['backend']: # Add nodes only if at least one additional node has been # requested res = self.add_nodes(sid, params) if 'error' in res: log('PHP.start: error calling add_nodes -> %s' % res) return res['error'] return 'ok'
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 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. """ service_id = int(request.values.get('sid', -1)) decrement = int(request.values.get('decrement', 0)) log('Decrement user credit: sid=%s, old_credit=%s, decrement=%s' % (service_id, g.service.user.credit, decrement)) # Decrement user's credit g.service.user.credit -= decrement if g.service.user.credit > -1: # User has enough credit db.session.commit() log('New credit for user %s: %s' % (g.service.user.uid, g.service.user.credit)) return jsonify({'error': False}) # User does not have enough credit db.session.rollback() log('User %s does not have enough credit' % g.service.user.uid) return jsonify({'error': 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 _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 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 _createapp(app_name): log('User %s creating a new application %s' % (g.user.username, app_name)) # check if the application already exists if check_app_exists(app_name): log('Application name %s already exists' % app_name) return jsonify({ 'error': True, 'msg': 'Application name "%s" already taken' % app_name }) 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 properly' % (a.aid)) return jsonify(a.to_dict())