Example #1
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)

        self.response.headers['Content-Type'] = "text/plain"

        if not instance:
            params = {"contents": "Waiting on serial console output..."}
            return self.render_template('instance/console.txt', **params)

        try:
            # update list of instances we have
            http = httplib2.Http()
            url = '%s/api/instance/%s/console?token=%s' % (
                config.fastener_host_url, name, config.fastener_api_token)
            response, content = http.request(url, 'GET')
            stuff = json.loads(content)

            params = {"contents": stuff['contents']}
        except Exception as ex:
            params = {"contents": "Waiting on serial console output..."}

        return self.render_template('instance/console.txt', **params)
Example #2
0
	def get(self, instance_name = None):

		# get the instance, build the response type
		instance = Instance.get_by_name(instance_name)
		self.response.headers['Content-Type'] = "application/json"

		# if no instance, then show error
		if not instance:
			params['message'] = "Instance not found."
			self.response.set_status(404)
			return self.render_template('api/response.json', **params)

		# load the instance's meta data, if any
		if instance.meta:
			meta = json.loads(instance.meta)
		else:
			meta = json.loads('{}')

		# build response
		params = {
			"instance": instance,
			"meta": meta
		}

		params['response'] = "success"
		self.response.headers['Content-Type'] = 'application/json'
		
		return self.render_template('api/instance.json', **params)
Example #3
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:
                instance = Instance.get_by_name(name)

                try:
                    if instance.user == user_info.key:

                        # make the instance call to the control box
                        http = httplib2.Http(timeout=10)
                        url = '%s/api/instance/%s/start?token=%s' % (
                            config.fastener_host_url, name,
                            config.fastener_api_token)

                        # pull the response back TODO add error handling
                        response, content = http.request(url,
                                                         'GET',
                                                         None,
                                                         headers={})

                        # update if google returns pending
                        if json.loads(content)['status'] == "PENDING":
                            instance.status = "STAGING"
                            instance.started = datetime.datetime.now()
                            instance.put()

                        params = {'instance': instance}

                        self.response.headers[
                            'Content-Type'] = "application/json"
                        return self.render_template('api/instance.json',
                                                    **params)

                except Exception as ex:
                    print "error %s" % ex
                    print "instance %s not found or not in TERMINATED state" % name

                params = {
                    "response":
                    "fail",
                    "message":
                    "[token] read access denied or instance not TERMINATED"
                }
                return self.render_template('api/response.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)
Example #4
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)
Example #5
0
	def get(self, instance_name = None):

		# get the instance, build the response type
		instance = Instance.get_by_name(instance_name)
		self.response.headers['Content-Type'] = "application/json"

		# if no instance, then show error
		if not instance:
			params['message'] = "Instance not found."
			self.response.set_status(404)
			return self.render_template('api/response.json', **params)

		params = {}
		params['response'] = "success"
		
		self.response.headers['Content-Type'] = 'application/json'
		
		return self.render_template('api/instance.json', **params)
Example #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:
                instance = Instance.get_by_name(name)

                try:
                    if instance.user == user_info.key:
                        params = {'instance': instance}
                        self.response.headers[
                            'Content-Type'] = "application/json"
                        return self.render_template('api/instance.json',
                                                    **params)
                except Exception as ex:
                    print "error %s" % ex
                    print "instance %s not found" % name

                params = {
                    "response": "fail",
                    "message": "[token] read access denied"
                }
                return self.render_template('api/response.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)
Example #7
0
    def get(self, name, command):
        # lookup user's auth info
        user_info = User.get_by_id(long(self.user_id))

        # get instance
        instance = Instance.get_by_name(name)

        if not instance:
            params = {}
            return self.redirect_to('instances-list', **params)
            slack.slack_message(
                "request for an instance we can't find - SPAMSPAMSPAM")

        else:
            # check user owns it or user is admin
            if user_info.admin != True and long(instance.user.id()) != long(
                    self.user_id):
                params = {
                    "response": "failure",
                    "message":
                    "instance %s not modifiable by calling user" % name
                }
                self.response.set_status(500)
                slack.slack_message("%s doesn't own %s" %
                                    (user_info.username, name))

            else:
                # start the instance
                if command == "start" and instance.status != "RUNNING":
                    slack.slack_message("firing up %s" % instance.name)
                    try:
                        instance.started = datetime.datetime.now()
                        instance.tender_action = "START"
                        instance.put()

                        params = {
                            "response":
                            "success",
                            "message":
                            "Instance %s marked to be started." % instance.name
                        }
                        slack.slack_message(
                            "updated db for %s with %s" %
                            (instance.name, instance.tender_action))
                    except Exception as ex:
                        params = {"response": "failure", "message": "%s" % ex}

                    self.response.headers['Content-Type'] = "application/json"
                    return self.render_template('api/response.json', **params)

                # add ssh_key to instance
                elif command == "addkey":
                    # make the instance call to the control box
                    http = httplib2.Http(timeout=10)
                    url = '%s/api/instance/%s/addkey?token=%s&ssh_key=%s&username=%s' % (
                        config.fastener_host_url, name,
                        config.fastener_api_token,
                        urllib.quote(user_info.ssh_key), user_info.username)

                    try:
                        # pull the response back TODO add error handling
                        response, content = http.request(url,
                                                         'GET',
                                                         None,
                                                         headers={})

                        # delete if google returns pending
                        if json.loads(content)['status'] == "SUCCESS":
                            params = {
                                "response": "success",
                                "message":
                                "instance %s updated with key" % name
                            }
                        else:
                            params = {
                                "response": "failure",
                                "message":
                                "instance %s operation failure" % name
                            }
                            response.set_status(500)
                    except:
                        params = {
                            "response": "failure",
                            "message": "instance %s failure" % name
                        }

                    self.response.headers['Content-Type'] = "application/json"
                    return self.render_template('api/response.json', **params)

                # just the status
                elif command == "status":
                    params = {"instance": instance}
                    self.response.headers['Content-Type'] = "application/json"
                    return self.render_template('api/instance.json', **params)

                # delete the instance - C'est la vie
                elif command == "delete":
                    instance.key.delete()  # let the tender script delete it
                    params = {
                        "response": "success",
                        "message": "Instance marked to be deleted."
                    }

                    self.response.headers['Content-Type'] = "application/json"
                    return self.render_template('api/response.json', **params)

                # rename it
                elif command == "rename":
                    renamed = self.request.get('renamed')
                    instance.renamed = renamed
                    instance.put()

                    params = {"instance": instance}
                    self.response.headers['Content-Type'] = "application/json"
                    return self.render_template('api/instance.json', **params)

                else:
                    params = {
                        "response": "failure",
                        "message": "bad command, skippy"
                    }
                    self.response.set_status(500)
                    self.response.headers['Content-Type'] = "application/json"
                    return self.render_template('api/response.json', **params)
Example #8
0
    def get(self):
        try:
            # grab a list of instances from the Fastener API
            http = httplib2.Http(timeout=30)
            url = '%s/api/instance/list?token=%s' % (config.fastener_host_url,
                                                     config.fastener_api_token)
            response, content = http.request(url, 'GET')

            # list of instances from Google Cloud (see ./fastener/sample-output.json)
            gcinstances = json.loads(content)

            if len(gcinstances) > 0:
                message = "ok"
            else:
                message = "no instances were returned from fastener API"

        except Exception as ex:
            gcinstances = []
            slack.slack_message(
                "Tender::Exception with list query to fastener box.")
            message = "failed to contact fastener API"

        # list of instances from db
        instances = Instance.get_all()

        # bail if we didn't get any instances from Google
        if len(gcinstances) == 0:
            params = {
                "message": message,
                "gc_count": len(gcinstances),
                "db_count": len(instances)
            }

            slack.slack_message("Tender::No instances from Google?")

            self.response.headers['Content-Type'] = "application/json"
            return self.render_template('api/tender.json', **params)
            ######

        # loop through list of instances in local or production DB
        for instance in instances:
            name = instance.name
            found = False

            # loop through the instances we got from google
            for gcinstance in gcinstances:

                # check if the names match
                if name == gcinstance['name']:
                    # got a match
                    found = True

                    try:
                        # grab the IP address and status
                        instance.ip = gcinstance['networkInterfaces'][0][
                            'accessConfigs'][0]['natIP']
                    except:
                        # got limited or no data about instance
                        instance.ip = "None"

                    # leave commented out
                    slack.slack_message("Tender::%s has status %s" %
                                        (instance.name, instance.status))

                    # if not BUILDING then update status right from google
                    if instance.status not in ("BUILDING"):
                        instance.status = gcinstance['status']

                    # at this point if the instance.status is NOT BUILDING, then we grab
                    # whatever google says the instance is doing. if it's RUNNING, then
                    # we do an instance link test to ensure the fusion service is running
                    # if Fusion does not respond, we set it to CONFIGURING

                    # BUILDING state is kept until an update of BUILDING state is done
                    # see APIs

                    # are we running?
                    if instance.status == "RUNNING":
                        # check if the box is running fusion admin yet (CONFIGURING if NOT)
                        try:
                            # fast fail connection for checking if fusion is up
                            http_test = httplib2.Http(timeout=2)
                            test_url = 'http://%s:8764' % instance.ip
                            response, content = http_test.request(
                                test_url, 'GET')
                            test_status = response['status']
                        except:
                            slack.slack_message(
                                "Tender::%s FAILED Fusion port test." %
                                (instance.name))
                            test_status = "404"

                        # set admin_link if box is running and test comes back 200
                        if test_status == "200":
                            instance.admin_link = test_url

                            # build app link and update, if it exists
                            try:
                                if instance.stream.get().app_stub:
                                    app_stub = instance.stream.get().app_stub
                                    instance.app_link = "http://%s%s" % (
                                        instance.ip, app_stub)
                                else:
                                    instance.app_link = None
                            except:
                                instance.app_link = None

                        else:
                            # show the box is in CONFIGURING
                            instance.status = "CONFIGURING"
                            instance.admin_link = None
                            instance.app_link = None
                            instance.put()

                    else:  # NOT RUNNING STATUS (FROM GOOGLE) OR BUILDING (FROM DEPLOY SCRIPT)
                        # should we start it?
                        if instance.tender_action == "START":
                            # try to start it
                            http = httplib2.Http(timeout=10)
                            url = '%s/api/instance/%s/start?token=%s' % (
                                config.fastener_host_url, name,
                                config.fastener_api_token)
                            try:
                                # pull the response back TODO add error handling
                                response, content = http.request(url,
                                                                 'GET',
                                                                 None,
                                                                 headers={})

                                # update if google returns pending
                                if json.loads(content)[
                                        'status'] == "PENDING" or json.loads(
                                            content)['status'] == "DONE":
                                    params = {
                                        "response": "success",
                                        "message": "instance %s started" % name
                                    }
                                    instance.status = "PROVISIONING"
                                    instance.tender_action = "NONE"
                                    instance.started = datetime.datetime.now()
                                    instance.put()

                                    slack.slack_message(
                                        "Tender::%s wanted and got a START" %
                                        (instance.name))
                                else:
                                    slack.slack_message(
                                        "Tender::%s wanted START but google reported %s"
                                        % (instance.name,
                                           json.loads(content)['status']))

                            except Exception as ex:
                                slack.slack_message(
                                    "Tender::Exception %s with %s" %
                                    (ex, instance.name))

                        else:
                            # slack.slack_message("Tender::%s not requesting any actions." % instance.name)
                            pass

                    # instance has been terminated
                    if instance.status == "TERMINATED":
                        # set start time to far in the past
                        instance.started = instance.created - datetime.timedelta(
                            0, 604800)

                    # make sure we write all changes out
                    instance.put()
                    break  # no need to keep looking

                else:
                    # instance doesn't match the one we're working on
                    pass

            if not found:
                # box wasn't found on GCP (via fastener LIST call)
                slack.slack_message(
                    "Instance %s noted not being on GCP - looking" % name)

                http = httplib2.Http(timeout=10)
                url = '%s/api/instance/%s/status?token=%s' % (
                    config.fastener_host_url, name, config.fastener_api_token)

                # pull the response back
                response, content = http.request(url, 'GET', None, headers={})

                result = json.loads(content)
                if not result:
                    # we could not verify box was or wasn't running (fastener might not be running)
                    slack.slack_message("Can't tell what is going on.")
                    pass
                else:
                    try:
                        if result['error'] == "NOTFOUND":
                            slack.slack_message(
                                "Deleting instance %s from DB for not being on GCP."
                                % name)
                            instance.key.delete()
                    except:
                        # no error
                        # why are we here, we got a response this box is running
                        pass

        else:
            # no instances in db
            pass

        # cleanup stray and EOL instances
        for gcinstance in gcinstances:
            instance = Instance.get_by_name(gcinstance['name'])

            if instance:
                name = instance.name

                # if instance is expired, end it
                if instance.expires < datetime.datetime.now():
                    # make the instance call to the control box
                    try:
                        http = httplib2.Http(timeout=10)
                        url = '%s/api/instance/%s/delete?token=%s' % (
                            config.fastener_host_url, name,
                            config.fastener_api_token)

                        # pull the response back
                        response, content = http.request(url,
                                                         'GET',
                                                         None,
                                                         headers={})
                        if content['status'] == "PENDING":
                            instance.key.delete()
                            slack.slack_message(
                                "DELETING instance %s's from GCP because expired."
                                % name)

                    except:
                        slack.slack_message(
                            "ERROR: failed deleting instance %s's from GCP because expired."
                            % name)

            else:
                # instance wasn't found in db
                name = gcinstance['name']

                # make sure we don't delete non-demo or prod instances
                if 'button' in name and config.isdev == False:  # i.e. put 'button' in an instance name & this will delete the instance
                    slack.slack_message(
                        "Not found in DB. Will try to delete instance %s's from Google Cloud."
                        % name)

                    # make the instance call to the control box
                    # THIS IS THE DANGEROUS BITS
                    try:
                        http = httplib2.Http(timeout=10)
                        url = '%s/api/instance/%s/delete?token=%s' % (
                            config.fastener_host_url, name,
                            config.fastener_api_token)

                        # pull the response back
                        response, content = http.request(url,
                                                         'GET',
                                                         None,
                                                         headers={})

                        if content['status'] == "PENDING":
                            slack.slack_message(
                                "DELETING instance %s's from Google Cloud." %
                                name)
                        else:
                            slack.slack_message(
                                "ERROR: funky content returned while deleting instance %s's from Google Cloud."
                                % name)

                    except:
                        slack.slack_message(
                            "ERROR: failed deleting instance %s from Google Cloud."
                            % name)

        else:
            # no instances from cloud - this should never run
            pass

        params = {
            "message": message,
            "gc_count": len(gcinstances),
            "db_count": len(instances)
        }

        self.response.headers['Content-Type'] = "application/json"
        return self.render_template('api/tender.json', **params)
Example #9
0
	def put(self, instance_name = None):
		# disable csrf check in basehandler
		csrf_exempt = True

		# paramters, assume failure, response type
		params = {}
		params['response'] = "error"
		self.response.headers['Content-Type'] = "application/json"

		# get the instance, build the response type
		instance = Instance.get_by_name(instance_name)
		self.response.headers['Content-Type'] = "application/json"		

		# if no instance, then show error
		if not instance:
			params['message'] = "Instance not found."
			self.response.set_status(404)
			return self.render_template('api/response.json', **params)
		else:
			# load the instance's meta data, if any
			if instance.meta:
				meta = json.loads(instance.meta)
			else:
				meta = json.loads('{}')

		# load the json from the call
		try:
			body = json.loads(self.request.body)

			# loop through key space and set meta data
			for key in body:
				meta[key] = body[key]

			# dump back into the db
			instance.meta = json.dumps(meta)
			instance.put()

		except Exception as e:
			params['message'] = "An error was encountered with parsing meta key values: %s." % str(e)
			self.response.set_status(500)
			return self.render_template('api/response.json', **params)

		# send update information to channel
		if instance.token:
			output = {
				"name": instance.name,
				"token": instance.token,
				"state": instance.state,
				"meta": meta
			}
			channel.send_message(instance.token, json.dumps(output))	

		# build response
		params = {
			"instance": instance,
			"meta": json.loads(instance.meta)
		}
		params['response'] = "success"
		self.response.headers['Content-Type'] = 'application/json'
		
		return self.render_template('api/instance.json', **params)