def get(self, sid=None): # lookup user's auth info user_info = User.get_by_id(long(self.user_id)) # look up streams streams = Stream.get_all() params = {'streams': streams} return self.render_template('admin/streams.html', **params)
def post(self): if not self.form.validate(): self.add_message('Form did not validate. Try again!', 'error') return self.get() # pull the github token out of the social user db user_info = User.get_by_id(long(self.user_id)) # load values out of the form, including whether the gist should be public or not sid = self.form.sid.data.strip() name = self.form.name.data.strip() description = self.form.description.data.strip() tgzfile = self.form.tgzfile.data.strip() fusion_version = self.form.fusion_version.data.strip() instance_size = self.form.instance_size.data.strip() github_repo = self.form.github_repo.data.strip() app_stub = self.form.app_stub.data.strip() labs_link = self.form.labs_link.data.strip() # save the stream stream = Stream(sid=sid, name=name, description=description, tgzfile=tgzfile, fusion_version=fusion_version, instance_size=int(instance_size), github_repo=github_repo, app_stub=app_stub, labs_link=labs_link) stream.put() # give the db a second or two to update time.sleep(1) self.add_message('Stream %s successfully created!' % name, 'success') params = {} return self.redirect_to('admin-streams', **params)
def get(self, name): # lookup user's auth info user_info = User.get_by_id(long(self.user_id)) # look up user's instances instance = Instance.get_by_name(name) if not instance: params = {} return self.redirect_to('instances-list', **params) if instance.renamed == None: instance.renamed = "" # remap so template can address if instance.created < (datetime.datetime.now() - datetime.timedelta(0, 600)): instance.expired = True else: instance.expired = False stream = Stream.get_by_id(instance.stream.id()) if utils.read_cookie(self, "guide") == "closed": guide = False else: guide = True if instance.size == 1: instance_cores = 8 instance_memory = 30 elif instance.size == 2: instance_cores = 16 instance_memory = 60 else: instance_cores = 4 instance_memory = 15 params = { 'guide': guide, 'instance': instance, 'stream': stream, 'user_info': user_info, 'instance_cores': instance_cores, 'instance_memory': instance_memory } return self.render_template('instance/detail.html', **params)
def delete(self, stream_id=None): # delete the entry from the db stream = Stream.get_by_id(long(stream_id)) sid = stream.sid if stream: stream.key.delete() self.add_message('Stream successfully deleted!', 'success') else: self.add_message('Something went horribly wrong somewhere!', 'warning') # hangout for a second if config.isdev: time.sleep(1) params = {"response": "success", "message": "stream %s deleted" % sid} return self.render_template('api/response.json', **params)
def get(self, sid=None): # check token token = self.request.get('token') if token != "" or True: #TODO FIX BOX ACCESS user_info = User.get_by_token(token) # look up streams stream = Stream.get_by_sid(sid) params = {'stream': stream} self.response.headers['Content-Type'] = "application/json" return self.render_template('api/stream.json', **params) # no token, no user, no data params = { "response": "fail", "message": "must include [token] parameter with a valid token" } return self.render_template('api/response.json', **params)
def get(self, name=None): # check token token = self.request.get('token') if token != "": user_info = User.get_by_token(token) if user_info: templates = Stream.get_all() params = {'templates': templates} self.response.headers['Content-Type'] = "application/json" return self.render_template('api/templates.json', **params) # no token, no user, no data params = { "response": "fail", "message": "must include [token] parameter with a valid token" } self.response.status = '402 Payment Required' self.response.status_int = 402 self.response.headers['Content-Type'] = "application/json" return self.render_template('api/response.json', **params)
def get(self, sid=None): # lookup user's auth info user_info = User.get_by_id(long(self.user_id)) # redirect to a POST if we have a sid in the URL if sid and user_info.email: return self.post(sid) try: if not user_info.email or not user_info.name or not user_info.company: need_more_info = True else: need_more_info = False except: need_more_info = True # look up user's instances db_instances = Instance.get_all() # work around index warning/errors using a .filter() in models.py instances = [] for db_instance in db_instances: # limit to instances the user has started if db_instance.user == user_info.key: if db_instance.renamed == None: db_instance.renamed = "" instances.append(db_instance) streams = Stream.get_all() params = { 'instances': instances, 'num_instances': len(instances), 'streams': streams, 'user_id': self.user_id, 'user_info': user_info, 'sid': sid, 'need_more_info': need_more_info } return self.render_template('instance/list.html', **params)
def post(self, sid=None): # a POST here is a create instance event # know the user user_info = User.get_by_id(long(self.user_id)) if sid and user_info.email: # get form values stream = Stream.get_by_sid(sid) try: size = stream.instance_size except: size = 0 # look up user's instances db_instances = Instance.get_all() # check the user's limits instance_count = 0 for db_instance in db_instances: # limit to instances the user has started if db_instance.user == user_info.key: instance_count = instance_count + 1 # warn and redirect if limit is reached if (instance_count + 1) > user_info.max_instances: self.add_message( 'Instance limit reached. This account may only start %s instances. Please delete an existing instance to start a new one!' % user_info.max_instances, 'warning') return self.redirect_to('instances-list') ## HOT START # check for a hot start instances = Instance.get_hotstarts() for instance in instances: # fiveminutesago depends on number of seconds at end of this *** fiveminutesago = datetime.datetime.now() - datetime.timedelta( 0, 900) # if this hotstart instance has a matching sid, assign and redirect to it if instance.created < fiveminutesago and instance.stream.get( ).sid == stream.sid and instance.status == "RUNNING": # map to user instance.user = user_info.key instance.hotstart = False instance.put() self.add_message( 'Instance assigned! Use login buttons to access %s.' % stream.name, 'success') slack.slack_message("Instance type %s assigned for %s!" % (stream.name, user_info.username)) return self.redirect_to('instance-detail', name=instance.name) # ## TRATS TOH # make the instance call handle http = httplib2.Http(timeout=10) # where and who created it (labels for google cloud console) if config.isdev: iuser = "******" % ("dev", user_info.username.lower()) else: iuser = "******" % ("prod", user_info.username.lower()) # build url to create new instance from stream url = '%s/api/stream/%s?token=%s&user=%s&size=%s' % ( config.fastener_host_url, sid, config.fastener_api_token, iuser, size) try: # pull the response back TODO add error handling response, content = http.request(url, 'POST', None, headers={}) gcinstance = json.loads(content) name = gcinstance['instance'] password = gcinstance['password'] if name == "failed": raise Exception("Instance start failed.") # set up an instance instance = Instance(name=name, status="PROVISIONING", user=user_info.key, stream=stream.key, size=size, password=password, expires=datetime.datetime.now() + datetime.timedelta(0, 604800), started=datetime.datetime.now()) instance.put() slack.slack_message("Instance type %s created for %s!" % (stream.name, user_info.username)) # give the db a second to update if config.isdev: time.sleep(1) self.add_message( 'Instance created! Grab some coffee and wait for %s to start.' % stream.name, 'success') params = {'name': name} return self.redirect_to('instance-detail', **params) except: self.add_message( 'The system is currently busy with other instances. Please try again in a few minutes.', 'warning') return self.redirect_to('instances-list') else: # email update sumbission if not self.form.validate(): self.add_message( "There were errors validating your email address.", "error") return self.get() email = self.form.email.data.strip() user_info = User.get_by_id(long(self.user_id)) user_info.email = email.strip() user_info.put() if len(email) > 3 and not config.isdev: name = user_info.name try: mc = MarketoClient(config.munchkin_id, config.mclient_id, config.mclient_secret) try: first = name.split()[0] except: first = "" try: last = name.split()[1] except: last = "" try: company = user_info.company except: company = "None" leads = [{ "email": user_info.email, "firstName": first, "lastName": last, "company": company, "leadSource": config.mclient_leadSource }] lead = mc.execute( method='push_lead', leads=leads, lookupField='email', programName=config.mclient_programName, programStatus=config.mclient_programStatus) except Exception as ex: slack.slack_message( "Marketo lead create failed because %s." % ex) slack.slack_message( "We got %s to update their email for instance launch!" % user_info.username) self.add_message("Thank you! Your email has been updated.", 'success') # redirect back to GET on list, but with a sid AND email in place this time to create if sid: return self.redirect_to('streams-start3', sid=sid) else: return self.redirect_to('instances-list')
def get(self, sid): # know the user user_info = User.get_by_id(long(self.user_id)) # check if we have their email if not user_info.email: self.add_message( 'Please update your email address before starting an instance!', 'warning') return self.redirect_to('account-settings') # look up user's instances db_instances = Instance.get_all() # check the user's limits instance_count = 0 for db_instance in db_instances: # limit to instances the user has started if db_instance.user == user_info.key: instance_count = instance_count + 1 # warn and redirect if limit is reached if (instance_count + 1) > user_info.max_instances: self.add_message( 'Instance limit reached. This account may only start %s instances. Please delete an existing instance to start a new one!' % user_info.max_instances, 'warning') return self.redirect_to('instances-list') # get stream stream = Stream.get_by_sid(sid) try: size = stream.instance_size except: size = 0 ## HOT START # check for a hot start instances = Instance.get_hotstarts() for instance in instances: # fiveminutesago depends on number of seconds at end of this *** fiveminutesago = datetime.datetime.now() - datetime.timedelta( 0, 900) # if this hotstart instance has a matching sid, assign and redirect to it if instance.created < fiveminutesago and instance.stream.get( ).sid == stream.sid and instance.status == "RUNNING": # map to user instance.user = user_info.key instance.hotstart = False instance.put() self.add_message( 'Instance assigned! Use login buttons to access %s.' % stream.name, 'success') slack.slack_message("Instance type %s assigned for %s!" % (stream.name, user_info.username)) return self.redirect_to('instance-detail', name=instance.name) # ## TOH TRATS # make the instance call to the control box http = httplib2.Http(timeout=10) # where and who created it if config.isdev: iuser = "******" % ("dev", user_info.username) else: iuser = "******" % ("prod", user_info.username) url = '%s/api/stream/%s?token=%s&user=%s&size=%s' % ( config.fastener_host_url, sid, config.fastener_api_token, iuser, size) try: # pull the response back TODO add error handling response, content = http.request(url, 'POST', None, headers={}) gcinstance = json.loads(content) name = gcinstance['instance'] password = gcinstance['password'] if name == "failed": raise Exception("Instance start failed.") # set up an instance (note there are two ways to create an instance - see below) instance = Instance(name=name, status="PROVISIONING", user=user_info.key, stream=stream.key, size=size, password=password, expires=datetime.datetime.now() + datetime.timedelta(0, 604800), started=datetime.datetime.now()) instance.put() slack.slack_message("Instance type %s created for %s!" % (stream.name, user_info.username)) # give the db a second to update if config.isdev: time.sleep(1) self.add_message( 'Instance created! Give the system a few minutes to start %s.' % stream.name, 'success') params = {'name': name} return self.redirect_to('instance-detail', **params) except: self.add_message( 'The system is currently busy with other instances. Please try again in a few minutes.', 'warning') return self.redirect_to('instances-list')
def get(self): # list of streams from db streams = Stream.get_all() # get list of host start instances from db instances = Instance.get_hotstarts() # for return of started/deleted instances sinstances = [] dinstances = [] # blast old ones for instance in instances: fiveminutesago = datetime.datetime.now() - datetime.timedelta( 0, 14400) # not five minutes, people if instance.created < fiveminutesago: # this instance is SO less (older) than some epoch seconds ago ^ dinstances.append(instance) instance.key.delete() slack.slack_message( "Hotstart instance %s deleted for being at risk for preemption!" % instance.name) if instance.status == "TERMINATED": # if this instance was started and then preempted dinstances.append(instance) instance.key.delete() slack.slack_message( "Hotstart instance %s deleted due to being terminated!" % instance.name) # for return of started instances sinstances = [] # loop over the 'templates' (streams) for stream in streams: running = 0 # check to see if some are running for instance in instances: if instance.stream.get().sid == stream.sid: running = running + 1 try: hot_starts = stream.hot_starts except: hot_starts = 0 try: size = stream.instance_size except: size = 0 if running < hot_starts: # start up an extra instance for this stream (max starts 1 per minute per template) # make the instance call handler http = httplib2.Http(timeout=10) # where and who created it (labels for google cloud console) if config.isdev: iuser = "******" % ("dev", "hotstart") else: iuser = "******" % ("prod", "hotstart") # build url to call create new instance from stream on fastener box (our instance) url = '%s/api/stream/%s?token=%s&user=%s&size=%s' % ( config.fastener_host_url, stream.sid, config.fastener_api_token, iuser, size) try: # pull the response back TODO add more better error handling response, content = http.request(url, 'POST', None, headers={}) gcinstance = json.loads(content) name = gcinstance['instance'] password = gcinstance['password'] if name == "failed": raise Exception("Instance start failed.") # set up an instance instance = Instance(name=name, status="PROVISIONING", stream=stream.key, size=size, hotstart=True, password=password, expires=datetime.datetime.now() + datetime.timedelta(0, 604800), started=datetime.datetime.now()) instance.put() # for return sinstances.append(instance) slack.slack_message( "Instance type %s created for HOTSTART!" % stream.name) except Exception as ex: print ex params = {"sinstances": sinstances, "dinstances": dinstances} self.response.headers['Content-Type'] = "application/json" return self.render_template('api/hotstarts.json', **params)
def post(self, sid=None): # topic (stackexchange subdomain, for now) topic = self.request.get('topic') if not topic: topic = "ai" # region region = self.request.get('region') if not region: region = "any" # preemptible request (add check user perms) preemptible = self.request.get('preemptible') if not preemptible: preemptible = 1 # preemptible else: if preemptible == "False" or preemptible == "false" or int( preemptible) == 0: preemptible = 0 # not preemptible else: preemptible = 1 # check token token = self.request.get('token') if token != "": user_info = User.get_by_token(token) if user_info: # look up streams stream = Stream.get_by_sid(sid) if not stream: params = { "response": "fail", "message": "stream %s does not exist on these endpoints" % sid } return self.render_template('api/response.json', **params) try: size = stream.instance_size except: size = 0 # look up user's instances db_instances = Instance.get_all() # check the user's limits instance_count = 0 for db_instance in db_instances: # limit to instances the user has started (doing it this way because can't figure out ndb indexing) if db_instance.user == user_info.key: instance_count = instance_count + 1 # check preemtibility ability if preemptible == 0: if user_info.superuser == False: # if the user can't start preemptible tell them params = { "response": "fail", "message": "token may not create non-preemptible instance" } return self.render_template('api/response.json', **params) # warn and redirect if limit is reached if (instance_count + 1) > user_info.max_instances: params = { "response": "fail", "message": "max instances reached for provided token" } return self.render_template('api/response.json', **params) # make the instance call to the control box http = httplib2.Http(timeout=10) # where and who created it if config.isdev: iuser = "******" % ("dev", user_info.username) else: iuser = "******" % ("prod", user_info.username) url = '%s/api/stream/%s?token=%s&user=%s&topic=%s®ion=%s&preemptible=%s&size=%s' % ( config.fastener_host_url, sid, config.fastener_api_token, iuser, topic, region, preemptible, size) try: # pull the response back TODO add error handling # CREATE HAPPENS HERE response, content = http.request(url, 'POST', None, headers={}) gcinstance = json.loads(content) name = gcinstance['instance'] password = gcinstance['password'] if name == "failed": raise Exception( "Instance start was delayed due to quota. Try again in a few minutes." ) # set up an instance instance = Instance(name=name, status="PROVISIONING", user=user_info.key, stream=stream.key, size=size, region=region, topic=topic, preemptible=bool(preemptible), password=password, expires=datetime.datetime.now() + datetime.timedelta(0, 604800), started=datetime.datetime.now()) instance.put() try: slack.slack_message( "Instance type %s created for %s!" % (stream.name, user_info.username)) except: print "slack failing" # give the db a second to update if config.isdev: time.sleep(3) params = {'instance': instance} self.response.headers['Content-Type'] = "application/json" return self.render_template('api/instance.json', **params) except Exception as ex: # the horror params = { "response": "fail", "message": "exception thrown: %s" % ex } return self.render_template('api/response.json', **params) # no token, no user, no data self.response.status = '402 Payment Required' self.response.status_int = 402 self.response.headers['Content-Type'] = "application/json" params = { "response": "fail", "message": "must include [token] with a valid token" } return self.render_template('api/response.json', **params)