예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
    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)
예제 #4
0
    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)
예제 #5
0
    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)
예제 #6
0
    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)
예제 #7
0
    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)
예제 #8
0
    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')
예제 #9
0
    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')
예제 #10
0
    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)
예제 #11
0
    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&region=%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)