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 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): # 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)