Exemple #1
0
	def delete(self, project_id = None):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))
		
		# pull the entry from the db
		project = Project.get_by_id(long(project_id))

		# if we found it and own it
		if project and project.owner == user_info.key:
			# patch all wisps using project to stock
			Wisp.patch_to_stock(project.key)

			# delete the project
			project.key.delete()

			self.add_message('Project successfully deleted!', 'success')
		else:
			self.add_message('Project was not deleted.  Something went horribly wrong somewhere!', 'warning')

		# hangout for a second
		time.sleep(1)

		# use the channel to tell the browser we are done and reload
		channel_token = self.request.get('channel_token')
		channel.send_message(channel_token, 'reload')
		return
	def delete(self, wisp_id = None):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))
		
		# pull the entry from the db
		wisp = Wisp.get_by_id(long(wisp_id))

		# if we found it and own it, delete
		if wisp and wisp.owner == user_info.key:
			# delete any associated bids, if they exist
			InstanceBid.delete_by_wisp(wisp.key)

			# delete the wisp
			wisp.key.delete()

			self.add_message('Wisp successfully deleted!', 'success')
		else:
			self.add_message('Wisp was not deleted.  Something went horribly wrong somewhere!', 'warning')

		# hangout for a second
		time.sleep(1)

		# setup channel to do page refresh
		channel_token = user_info.key.urlsafe()
		refresh_channel = channel.create_channel(channel_token)
		channel.send_message(channel_token, 'reload')

		return
Exemple #3
0
	def get(self):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))

		# look up wisps
		wisps = Wisp.get_by_user(user_info.key)

		# redirect if we don't have any wisps
		if not wisps:
			return self.redirect_to('account-wisps-new')

		# setup channel to do page refresh
		channel_token = user_info.key.urlsafe()
		refresh_channel = channel.create_channel(channel_token)

		# params build out
		params = {
			'wisps': wisps, 
			'refresh_channel': refresh_channel,
			'channel_token': channel_token 
		}

		# check for default
		default = False
		for wisp in wisps:
			if wisp.default:
				default = True
		if not default:
			print "wtf"
			self.add_message("Please set a wisp to be default!", "error")

		return self.render_template('wisp/wisps.html', **params)
Exemple #4
0
    def get(self):
        # get older anonymous wisps to delete
        wisps = Wisp.get_expired_anonymous()

        if wisps:
            # remove wisps
            for wisp in wisps:
                # delete wisp
                wisp.key.delete()

        return
Exemple #5
0
	def get(self):
		# get older anonymous wisps to delete
		wisps = Wisp.get_expired_anonymous()

		if wisps:
			# remove wisps
			for wisp in wisps:
				# delete wisp
				wisp.key.delete()

		return
	def get(self):
		# basics
		ip = self.request.remote_addr

		# setup channel to do page refresh
		channel_token = generate_token()
		refresh_channel = channel.create_channel(channel_token)

		# various pulldown initialization
		self.form.flavor.choices=[]
		self.form.wisp.choices=[]
		self.form.cloud.choices=[]

		# add list of user's flavors, if any
		flavors = Flavor.flavors_with_instances_on_sale()
		for flavor in flavors:
			self.form.flavor.choices.insert(0, (flavor.name, flavor.description))

		# used for determining element layout
		wisp = None
		cloud = None

		# if the user is logged in, we build out the list of their wisps
		if self.user_id:
			# lookup user's auth info and wisps
			user_info = User.get_by_id(long(self.user_id))
			wisps = Wisp.get_by_user(user_info.key)
			for wisp in wisps:
				self.form.wisp.choices.insert(0, (wisp.key.id(), wisp.name))
		
			# load clouds
			clouds = Cloud.get_by_user(user_info.key)

			# create default cloud if none
			if not clouds:
				cloud = Cloud.create_default(user_info.key)
				clouds.append(cloud)
				self.add_message("Default cloud created.", 'success')

			for cloud in clouds:
				self.form.cloud.choices.insert(0, (cloud.key.id(), cloud.name))

		# params build out (injects the last wisp, if there was one)
		params = {
			'remote_ip': ip,
			'wisp': wisp,
			'cloud': cloud,
			'refresh_channel': refresh_channel,
			'channel_token': channel_token 
		}

		return self.render_template('lab/launcher.html', **params)
Exemple #7
0
	def get(self, wisp_id = None):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))
		
		# get the wisp in question
		wisp = Wisp.get_by_id(long(wisp_id))

		# if doesn't exist, redirect
		if not wisp:
			return self.redirect_to('account-wisps')

		# insert images into list for wisp
		self.form.image.choices=[('custom', "Dynamic Image URL")]
		images = Image.get_all()
		for image in images:
			self.form.image.choices.insert(0, (str(image.key.id()), image.description))

		# load form values
		self.form.name.data = wisp.name
		self.form.ssh_key.data = wisp.ssh_key
		self.form.dynamic_image_url.data = wisp.dynamic_image_url
		self.form.post_creation.data = wisp.post_creation
		self.form.callback_url.data = wisp.callback_url
		self.form.default.data = wisp.default

		# hack up the form a bit
		if wisp.callback_url:
			self.form.callback.data = "custom"
		if wisp.dynamic_image_url:
			self.form.image.data = "custom"
		else:
			self.form.image.data = str(wisp.image.id())

		# check if the owner is this user
		if wisp and wisp.owner == user_info.key:
			# setup channel to do page refresh
			channel_token = user_info.key.urlsafe()
			refresh_channel = channel.create_channel(channel_token)

			# params build out
			params = {
				'wisp': wisp,
				'image': image,
				'refresh_channel': refresh_channel,
				'channel_token': channel_token 
			}

			return self.render_template('wisp/wisp_detail.html', **params)
		
		else:
			return self.redirect_to('account-wisps')
Exemple #8
0
	def get(self, token=None):
		# paramters, assume failure, response type
		# response, type, cross posting
		params = {}
		params['response'] = "error"
		self.response.headers['Content-Type'] = "application/json"
		self.response.headers['Access-Control-Allow-Origin'] = '*'

		# look for instance bid first
		wisp = Wisp.get_by_token(token)
		
		# if no instance, then show error
		if not wisp:
			params['message'] = "Wisp not found."
			self.response.set_status(404)
			return self.render_template('api/response.json', **params)
		else:
			params['respose'] = "success"
			params['wisp'] = wisp
			
		return self.render_template('api/wisp.json', **params)
	def get(self, wisp_id = None, file = None):
		# get wisp
		wisp = Wisp.get_by_id(long(wisp_id))
		try:
			# get the project
			project = wisp.project.get()

			# params build out
			params = {
				'project_name': project.name,
				'project_url': project.url,
				'donation_address': project.address,
				'port': project.port,
				'state': 1,
				'ipv4_address': '127.0.0.1',
				'ipv6_address': '::1'
			}

			# pull out the meta data from the instance and build into key/values
			# for key,value in instance.meta_data
			# params[key] = value
			
			# also add api_url
			#'api_url': '%s/api/v1/instance/' 

			if project:
				# return proxied github content
				if file == 'README.md':
					return self.render_url(project.readme_url, **params)

				elif file == 'install.sh':
					return self.render_url(project.install_url, **params)
		except:
			pass
		
		# default response is we don't have it
		self.response.set_status(404)
		return
    def get(self):
        # lookup user's auth info
        user_info = User.get_by_id(long(self.user_id))

        # look up wisps
        wisps = Wisp.get_by_user(user_info.key)
        if len(wisps) > 0:
            wisps_exist = True
        else:
            wisps_exist = False

        # setup channel to do page refresh
        channel_token = user_info.key.urlsafe()
        refresh_channel = channel.create_channel(channel_token)

        # params build out
        params = {
            'wisps_exist': wisps_exist,
            'refresh_channel': refresh_channel,
            'channel_token': channel_token
        }

        return self.render_template('user/status.html', **params)
Exemple #11
0
	def delete(self, wisp_id = None):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))
		
		# pull the entry from the db
		wisp = Wisp.get_by_id(long(wisp_id))

		# check if wisp is in use by a cloud

		# if we found it and own it, delete
		if wisp and wisp.owner == user_info.key:
			wisp.key.delete()
			self.add_message('Wisp successfully deleted!', 'success')
		else:
			self.add_message('Wisp was not deleted.  Something went horribly wrong somewhere!', 'warning')

		# hangout for a second
		time.sleep(1)

		# use the channel to tell the browser we are done and reload
		channel_token = self.request.get('channel_token')
		channel.send_message(channel_token, 'reload')
		return
Exemple #12
0
	def get(self):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))

		# look up wisps
		wisps = Wisp.get_by_user(user_info.key)
		if len(wisps) > 0:
			wisps_exist = True
		else:
			wisps_exist = False
			
		# setup channel to do page refresh
		channel_token = user_info.key.urlsafe()
		refresh_channel = channel.create_channel(channel_token)

		# params build out
		params = {
			'wisps_exist': wisps_exist,
			'refresh_channel': refresh_channel,
			'channel_token': channel_token 
		}

		return self.render_template('user/status.html', **params)
Exemple #13
0
	def post(self, instance_name):
		# paramters, assume failure, response type
		params = {}
		params['response'] = "error"
		self.response.headers['Content-Type'] = "application/json"

		# request basics
		ip = self.request.remote_addr

		try:
			body = json.loads(self.request.body)
			instance_schema = schemas['InstanceSchema'](**body['instance'])
			appliance_schema = schemas['ApplianceSchema'](**body['appliance'])

			# try to authenticate appliance
			if not Appliance.authenticate(appliance_schema.apitoken.as_dict()):
				logging.error("%s is using an invalid token(%s) or appliance deactivated."
					% (ip, appliance_schema.apitoken.as_dict()))
				return error_response(self, "Token is not valid.", 401, params)

			# fetch appliance and instance
			appliance = Appliance.get_by_token(appliance_schema.apitoken.as_dict())

			instance = Instance.get_by_name_appliance(
				instance_schema.name.as_dict(), 
				appliance.key
			)

			# if instance doesn't already exist, create it
			if not instance:
				wisp = Wisp.get_user_default(appliance.owner)
				if not wisp:
					wisp = Wisp.get_system_default()
				instance = Instance(wisp=wisp.key)

			# wrap instance into api shim in order to translate values from structure
			# of api to structure of model. I hope at some point in the future the two
			# models are similar enough so we can entirely drop this shim
			instance_shim = InstanceApiShim(instance)

			# update instance with values from post
			ApiSchemaHelper.fill_object_from_schema(
				instance_schema, instance_shim)

			# associate instance with it's appliance
			instance_shim.appliance = appliance

		except Exception as e:
			return error_response(self, 'Error in creating or updating instance from '
				'post data, with message {0}'.format(str(e)), 500, {})


		# update local instance
		instance.put()

		# update appliance ip address hint
		if instance.state > 3 and instance.ipv4_address:
			appliance.ipv4enabled = True
		if instance.state > 3 and instance.ipv6_address:
			appliance.ipv6enabled = True
		appliance.put()

		# sleep for dev
		if config.debug:
			time.sleep(1)

		# send update information to channel
		if instance.token:

			output = {
				"name": instance.name,
				"token": instance.token,
				"state": instance.state,
			}
			channel.send_message(instance.token, json.dumps(output))		

		# pop a reload just in case user is on their cloud page
		if instance.owner:
			user_info = User.get_by_id(long(instance.owner.id()))
			channel.send_message(user_info.key.urlsafe(), "reload")

		# convert bid to instance
		# check if there is an instance bid reservation on this instance
		instancebid = InstanceBid.get_by_instance(instance.key)
		if instancebid:
			# check for a bid callback_url (entered in the callback field on the launcher)
			if instancebid.callback_url > "":
				# put the callback into the instance
				instance.callback_url = instancebid.callback_url
			
			elif instancebid.wisp:
				# otherwise, get the wisp's callback URL	
				callback_url = instancebid.wisp.get().callback_url
			
				# if the wisp has an empty callback URL, populate the instance with the wisp's bid details
				if callback_url == "" or callback_url == None:
					instance.wisp = instancebid.wisp
					instance.owner = instancebid.wisp.get().owner
					instance.cloud = instancebid.cloud
				else:
					# we have a custom callback in the wisp itself, so move to instance
					instance.callback_url = callback_url

			# update the instance
			instance.put()

			# delete the instance reservation
			instancebid.key.delete()

		# proxy custom callback
	
		"""
		BEGIN CODE CALLOUT
		"""
		# August 24, 2014
		#
		# The following code retrieves content from a remote server and proxies it to 
		# an appliance for starting an instance. It is at this point an anonymous user's
		# callback pattern is most venerable to being monitored and manipulated.
		# 
		# The author of this software issues a warrant canary tweet to @stackape which 
		# should appear on the 1st of each month indicating the absence of a gag order
		# having been issued to StackMonkey, Utter.io, or Kord Campbell.
		#
		# Please monitor the code block between BEGIN CODE CALLOUT and END CODE CALLOUT 
		# if the canary tweet does not appear on schedule. Please monitor any callback
		# file's retrieval patterns if the canary tweet does not appear on schedule.
		# Please report any findings to the community sections of the project/site.
		#
		# Remember, the code is Open Source. Use that fact to the community's advantage.
		# 
		# The warrant canary will likely be your only indication a change has possibly
		# taken place to the system.  These changes may or may not enable a government 
		# agency to intercept and monitor instances using a custom URL callback.
		#
		# Kord Campbell
		#
		if instance.callback_url:
			try:
				result = urlfetch.fetch(instance.callback_url, deadline=5)
			except Exception as ex:
				logging.error("Error fetching callback URL content.")
				instance.console_output = "Error fetching callback url=(%s)'s' content. %s" % (instance.callback_url, ex)
				instance.put()

				# user may be sitting on an instance reservation here, so reload the page
				# this will force the handler to redirect the user to the instance page
				channel.send_message(instance.token, "reload")
				return error_response(self, "Error fetching callback URL content.", 401, params)

			# return content retrieved from callback URL if the JSON returned by this method includes
			# a callback_url in the data, the appliance will follow the URL and will not call this API 
			# again during the life of the instance.
			self.response.headers['Content-Type'] = 'application/json'
			self.response.write(json.dumps(json.loads(result.content), sort_keys=True, indent=2))
			
			# return from here	
			return

		"""
		END CODE CALLOUT
		"""

		# at this point we have one of two scenarios:
		# 1. an external instance start (registered user with appliance, sans instancebid)
		# 2. registered user using a normal wisp WITHOUT a callback_url

		# grab the instance's wisp
		if instance.wisp:
			# if instance is using a wisp
			wisp = Wisp.get_by_id(instance.wisp.id())
		else:
			# no wisp on instance
			wisp = Wisp.get_user_default(instance.owner)

		# deliver default system wisp if none (external instance start)
		if not wisp:
			wisp = Wisp.get_system_default()

		# load wisp image
		if not wisp.use_dynamic_image:
			image = wisp.image.get()
		else:
			image = wisp.get_dynamic_image()

		# pop the ssh_key into an array
		if wisp.ssh_key:
			ssh_keys = []
			for line in iter(wisp.ssh_key.splitlines()):
				ssh_keys.append(line)
		else:
			ssh_keys = [""]

		# 
		# pop the post creation script into an array
		if wisp.post_creation:
			post_creation = []
			for line in iter(wisp.post_creation.splitlines()):
				post_creation.append(line)
		else:
			post_creation = [""]

		# some of replay's magic - need docs on this
		start_params = schemas['InstanceStartParametersSchema']()
		data = {
			'image': image,
			'callback_url': wisp.callback_url if wisp.callback_url else "",
			'ssh_keys': ssh_keys,
			'post_create': post_creation}
		ApiSchemaHelper.fill_schema_from_object(start_params, data)

		self.response.set_status(200)
		self.response.headers['Content-Type'] = 'application/json'

		# write dictionary as json string
		self.response.out.write(json.dumps(
				# retrieve dict from schema
				start_params.as_dict()))
Exemple #14
0
	def post(self, instance_name):
		# paramters, assume failure, response type
		params = {}
		params['response'] = "fail"
		self.response.headers['Content-Type'] = "application/json"

		# get appliance variables
		try:
			packet = json.loads(self.request.body)
			apitoken = packet['appliance']['apitoken']
		except:
			params['message'] = "You must submit a valid JSON object with a token."
			self.response.set_status(401)
			return self.render_template('api/response.json', **params)	
		
		# load the appliance
		appliance = Appliance.get_by_token(apitoken)

		if not appliance:
			params['message'] = "Token is not valid."
			self.response.set_status(401)
			return self.render_template('api/response.json', **params)

		if appliance.activated == False:
			# appliance not activated
			params['message'] = "Appliance has been disabled by pool controller. Please contact support."
			self.response.set_status(409)
			return self.render_template('api/response.json', **params)

		# pull out the appliance's instance
		try:
			appliance_instance = packet['instance']
		except:
			params['response'] = "fail"
			params['result'] = "JSON instance data not found."
			self.response.set_status(404)
			return self.render_template('api/response.json', **params)
		
		# grab the instance name and check the url
		try:
			name = appliance_instance['name']
			# same name?
			if instance_name != name:
				raise
		except:
			params['response'] = "fail"
			params['result'] = "JSON instance name needs to match resource URI."
			self.response.set_status(401)
			self.response.headers['Content-Type'] = 'application/json'
			return self.render_template('api/response.json', **params)			

		# grab the rest of the instance info
		try:
			# grab the rest of appliance POST data
			flavor_name = appliance_instance['flavor']
			ask = appliance_instance['ask']
			expires = datetime.fromtimestamp(appliance_instance['expires'])
			address = appliance_instance['address'] # bitcoin address
		except:
			params['response'] = "fail"
			params['result'] = "JSON instance data not found.  Flavor, ask, expires or address missing."
			self.response.set_status(404)
			return self.render_template('api/response.json', **params)

		# look up the pool's version of this instance
		instance = Instance.get_by_name_appliance(name, appliance.key)

		# create a new instance for this appliance because we've never seen it
		if not instance:
			instance = Instance().push(appliance_instance, appliance)
			wisp = Wisp.get_user_default(appliance.owner)
			instance.wisp = wisp.key
			instance.put()

		# grab the instance's wisp
		if instance.wisp:
			wisp = Wisp.get_by_id(instance.wisp.id())
		else:
			# we need a decent fallback for how to boot an image without a wisp
			wisp = Wisp.get_user_default(instance.owner)

		# get the value or return None if not present
		dynamic_image_url = wisp.dynamic_image_url if wisp.dynamic_image_url > "" else None
		callback_url = wisp.callback_url if wisp.callback_url > "" else None
		image = wisp.image.get().name if wisp.image else None
		
		# pop the ssh_key script into an array
		if wisp.ssh_key:
			ssh_key = []
			for line in iter(wisp.ssh_key.splitlines()):
				ssh_key.append(line)
		else:
			ssh_key = [""]

		# pop the post creation script into an array
		if wisp.post_creation:
			post_creation = []
			for line in iter(wisp.post_creation.splitlines()):
				post_creation.append(line)
		else:
			post_creation = [""]

		# load the instance info back into the response
		params = {
			'response': "success",
			'instance_name': name,
			'image': image,
			'dynamic_image_url': dynamic_image_url,
			'callback_url': callback_url,
			'ssh_key': ssh_key,
			'post_creation': post_creation 
		}

		self.response.headers['Content-Type'] = 'application/json'
		return self.render_template('api/instances.json', **params)
Exemple #15
0
	def post(self):
		# request basics
		ip = self.request.remote_addr

		# response, type, cross posting
		params = {}
		self.response.headers['Content-Type'] = "application/json"
		self.response.headers['Access-Control-Allow-Origin'] = '*'

		# check if this IP has any other bids open
		instancebid = InstanceBid.get_incomplete_by_ip(ip)


		# check we have an instancebid already
		if instancebid:
			# validate wisp
			if instancebid.wisp == None:
				instancebid.key.delete()
				return error_response(self, "Deleting bid because no wisp was associated.", 403, params)

			# load the payment address
			if instancebid.instance:
				instancebid.address = instancebid.instance.get().address
				instancebid.ask = instancebid.instance.get().ask
			else:
				# we should have an instance assosciated, so bail on this one
				instancebid.key.delete()
				return error_response(self, "Deleting bid because no instance was associated.", 403, params)

			params['response'] = "error"
			params['message'] = "The calling IP address already has an instance reservation in progress."
			params['instancebid'] = instancebid
			self.response.set_status(403)
			return self.render_template('api/bid.json', **params)	

		# load POSTed JSON
		try:
			request = json.loads(self.request.body)
		except Exception as ex:
			return error_response(self, "Failure in parsing request JSON.", 403, params)

		# load optional values or defaults
		# ipv4 (allow default)
		if 'requires_ipv4' in request:
			requires_ipv4 = request['requires_ipv4']
		else:
			requires_ipv4 = 0
		
		# ipv6 (allow default)
		if 'requires_ipv6' in request:
			requires_ipv6 = request['requires_ipv6']
		else:
			requires_ipv6 = 0

		# providers (allow default)
		if 'providers' in request:
			providers = request['providers']
		else:
			providers = [{u'id': 1, u'name': u'All Providers'}]		

		# flavors (required)
		if 'flavor' in request:
			flavor_name = request['flavor']
			flavor = Flavor.get_by_name(flavor_name)

			# check if flavor was found
			if not flavor:
				return error_response(self, "Flavor not found.", 403, params)

		else:
			return error_response(self, "Flavor name is required.", 403, params)

		# cloud (optional)
		if 'cloud_id' in request:
			cloud_id = request['cloud_id']
			cloud = Cloud.get_by_id(long(cloud_id))

			# check if cloud was found
			if not cloud:
				return error_response(self, "Cloud ID not found.", 403, params)
		else:
			cloud = None

		# disallow both a wisp and a callback_url
		if 'wisp_id' in request and 'callback_url' in request:
			return error_response(self, "A wisp and a callback URL may not be used together.", 403, params)

		# require either a wisp or a callback_url
		if 'wisp_id' not in request and 'callback_url' not in request:
			return error_response(self, "A valid wisp or a callback URL is required.", 403, params)

		# load the wisp, if there is one
		if 'wisp_id' in request:
			wisp_id = request['wisp_id']
			wisp = Wisp.get_by_id(long(wisp_id))
		else:
			wisp = None
		
		# load the callback URL, if there is one
		if 'callback_url' in request:
			callback_url = request['callback_url']
		elif wisp:
			callback_url = wisp.callback_url
		else:
			callback_url = ""

		# test we have a callback_url or a valid image in the wisp
		if callback_url > "":
			try:
				result = urlfetch.fetch(callback_url, deadline=5)
				if result.status_code > 399:
					return error_response(self, "The callback URL is unreachable.", 403, params)
				# test result's image URL
			except Exception as ex:
				return error_response(self, "The callback URL is unreachable.", 403, params)
		elif wisp:
			if wisp.image == None and wisp.dynamic_image_url == None and wisp.project == None:
				return error_response(self, "A valid wisp or a callback URL is required.", 403, params)

		# grab a new bid hash to use for the new bid
		token = generate_token(size=16)
		name = "smr-%s" % generate_token(size=8)

		# create a new bid
		instancebid = InstanceBid()
		instancebid.token = token
		instancebid.name = name
		instancebid.need_ipv4_address = bool(requires_ipv4)
		instancebid.need_ipv6_address = bool(requires_ipv6)
		instancebid.flavor = flavor.key
		instancebid.remote_ip = ip
		instancebid.appliances = providers # providers is already JSON
		instancebid.status = 0
		instancebid.callback_url = callback_url

		# expires in 5 minutes
		epoch_time = int(time.time())
		instancebid.expires = datetime.fromtimestamp(epoch_time+300)

		# add wisp, if present
		if wisp:
			instancebid.wisp = wisp.key
		
		# add cloud, if present
		if cloud:
			instancebid.cloud = cloud.key

		# update
		instancebid.put()

		# sleep for dev
		if config.debug:
			time.sleep(2)

		# reserve the instance
		InstanceBid.reserve_instance_by_token(instancebid.token)

		# get the address, if you got an instance
		if instancebid.instance:
			address = instancebid.instance.get().address
			ask = instancebid.instance.get().ask
		else:
			# no instance was reserved
			instancebid.key.delete()
			return error_response(self, "No valid instances were returned.", 403, params)
			
		# hack address and ask into instancebid object for template (not stored)
		instancebid.address = address
		instancebid.ask = ask

		# build out the response
		params['response'] = "success"
		params['message'] = "A new instance bid has been created."	
		params['instancebid'] = instancebid

		# return response and include cross site POST headers
		self.response.set_status(201)

		return self.render_template('api/bid.json', **params)
Exemple #16
0
	def post(self):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))

		# insert images into list for wisp
		self.form.image.choices=[('custom', "Dynamic Image URL")]
		images = Image.get_all()
		for image in images:
			self.form.image.choices.insert(0, (str(image.key.id()), image.description))

		# check what was returned from form validates
		if not self.form.validate():          
			self.add_message("The new wisp form did not validate.", "error")
			return self.get()

		# load form values
		name = self.form.name.data.strip()
		ssh_key = self.form.ssh_key.data.strip()
		dynamic_image_url = self.form.dynamic_image_url.data.strip()
		post_creation = self.form.post_creation.data.strip()
		callback_url = self.form.callback_url.data.strip()
		default = self.form.default.data # no strip cause bool

		# hack up form to deal with custom image
		if self.form.image.data.strip() == "custom":
			image = None
		else:
			image = Image.get_by_id(int(self.form.image.data.strip())).key
		
		# hack up form to deal with custom callback
		if self.form.callback.data.strip() == "custom":
			image = None
			ssh_key = None
			dynamic_image_url = None
			post_creation = None
		else:
			callback_url = None
			
		# check if we have it already
		if Wisp.get_by_user_name(user_info.key, name):
			self.add_message("A wisp with that name already exists in this account!", "error")
			return self.redirect_to('account-wisps')		

		# save the new wisp in our database            
		wisp = Wisp(
			name = name,
			owner = user_info.key,
			image = image,
			ssh_key = ssh_key,
			dynamic_image_url = dynamic_image_url,
			post_creation = post_creation,
			callback_url = callback_url,
		)
		wisp.put()

		# set default if true
		if default:
			Wisp.set_default(wisp)

		# log to alert
		self.add_message("Wisp %s successfully created!" % name, "success")

		# give it a few seconds to update db, then redirect
		time.sleep(1)
		return self.redirect_to('account-wisps')
Exemple #17
0
	def post(self, wisp_id = None):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))

		# load the wisp in question
		wisp = Wisp.get_by_id(long(wisp_id))

		# if doesn't exist, redirect
		if not wisp:
			return self.redirect_to('account-wisps')

		# insert images into list for wisp
		self.form.image.choices=[('custom', "Dynamic Image URL")]
		images = Image.get_all()
		for image in images:
			self.form.image.choices.insert(0, (str(image.key.id()), image.description))

		# check what was returned from form validates
		if not self.form.validate():          
			self.add_message("The new wisp form did not validate.", "error")
			return self.get(wisp_id = wisp_id)

		# load form values
		name = self.form.name.data.strip()
		ssh_key = self.form.ssh_key.data.strip()
		dynamic_image_url = self.form.dynamic_image_url.data.strip()
		post_creation = self.form.post_creation.data.strip()
		callback_url = self.form.callback_url.data.strip()
		default = self.form.default.data

		# hack up form to deal with custom image
		if self.form.image.data.strip() == "custom":
			image = None
		else:
			image = Image.get_by_id(int(self.form.image.data.strip())).key

		# hack up form to deal with custom callback
		if self.form.callback.data.strip() == "custom":
			image = None
			ssh_key = None
			dynamic_image_url = None
			post_creation = None
		else:
			callback_url = None

		# check if the wisp owner is this user
		if wisp and wisp.owner == user_info.key:
			# save the new wisp in our database            
			wisp.name = name
			wisp.image = image
			wisp.ssh_key = ssh_key
			wisp.dynamic_image_url = dynamic_image_url
			wisp.post_creation = post_creation
			wisp.callback_url = callback_url
			wisp.put()

			# set default if true, or turn it off if false
			if default:
				Wisp.set_default(wisp)
			else:
				wisp.default = False
				wisp.put()

			# log to alert
			self.add_message("Wisp %s updated!" % name, "success")

			# give it a few seconds to update db, then redirect
			time.sleep(1)
		else:
			# log to alert
			self.add_message("Wisp was not updated!", "error")
		
		return self.redirect_to('account-wisps')
	def get(self, wisp_id = None):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))
		
		# get the wisp in question
		wisp = Wisp.get_by_id(long(wisp_id))

		# if doesn't exist, redirect
		if not wisp:
			return self.redirect_to('account-wisps')

		# load projects pulldown
		self.form.project.choices = []
		projects = Project.get_available(user_info.key)
		for project in projects:
			self.form.project.choices.insert(0, (str(project.key.id()), project.name))

		# insert images into list for wisp
		self.form.image.choices=[('custom', "Dynamic Image URL")]
		images = Image.get_all()
		for image in images:
			self.form.image.choices.insert(0, (str(image.key.id()), image.description))

		# load values out of db to show in form
		self.form.name.data = wisp.name
		self.form.ssh_key.data = wisp.ssh_key
		self.form.dynamic_image_url.data = wisp.dynamic_image_url
		self.form.image_disk_format.data = wisp.image_disk_format
		self.form.image_container_format.data = wisp.image_container_format
		self.form.post_creation.data = wisp.post_creation
		self.form.callback_url.data = wisp.callback_url
		self.form.default.data = wisp.default

		# adjust the form's pulldown settings
		self.form.wisp_type.data = "stock"
		if wisp.image:
			self.form.image.data = str(wisp.image.id())
		if wisp.callback_url:
			self.form.wisp_type.data = "custom"
		if wisp.project:
			self.form.wisp_type.data = "project"
			self.form.project.data = str(wisp.project.id())
		if wisp.dynamic_image_url:
			self.form.wisp_type.data = "stock"
			self.form.image.data = "custom"

		# check if the owner is this user
		if wisp and wisp.owner == user_info.key:
			# setup channel to do page refresh
			channel_token = user_info.key.urlsafe()
			refresh_channel = channel.create_channel(channel_token)

			# params build out
			params = {
				'wisp': wisp,
				'refresh_channel': refresh_channel,
				'channel_token': channel_token 
			}

			return self.render_template('wisp/edit.html', **params)
		
		else:
			return self.redirect_to('account-wisps')
	def post(self):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))

		# load projects pulldown
		self.form.project.choices = []

		# public + private
		projects = Project.get_available(user_info.key)
		for project in projects:
			self.form.project.choices.insert(0, (str(project.key.id()), project.name))

		# insert images into list for wisp
		self.form.image.choices=[('custom', "Dynamic Image URL")]
		images = Image.get_all()
		for image in images:
			self.form.image.choices.insert(0, (str(image.key.id()), image.description))

		# check what was returned from form validates
		if not self.form.validate():          
			self.add_message("The new wisp form did not validate.", "error")
			return self.get()

		# load form values
		name = self.form.name.data.strip()
		ssh_key = self.form.ssh_key.data.strip()
		dynamic_image_url = self.form.dynamic_image_url.data.strip()
		image_container_format = self.form.image_container_format.data.strip()
		image_disk_format = self.form.image_disk_format.data.strip()
		post_creation = self.form.post_creation.data.strip()
		callback_url = self.form.callback_url.data.strip()
		default = self.form.default.data # no strip cause bool

		# check if project is selected
		if self.form.wisp_type.data.strip() == 'project':
			project = Project.get_by_id(long(self.form.project.data.strip())).key
		else:
			project = None		

		# hack up form to deal with custom image
		if self.form.image.data.strip() == "custom":
			image = None
		else:
			image = Image.get_by_id(long(self.form.image.data.strip())).key

		# hack up form to deal with custom callback
		if self.form.wisp_type.data.strip() == "custom":
			image = None
			ssh_key = None
			dynamic_image_url = None
			post_creation = None
		elif self.form.wisp_type.data.strip() == "project":
			image = None
			dynamic_image_url = None
			post_creation = None
		else:
			callback_url = None

		# check if we have it already
		if Wisp.get_by_user_name(user_info.key, name):
			self.add_message("A wisp with that name already exists in this account!", "error")
			return self.redirect_to('account-wisps')		
		
		# check if we need to force default setting for first new wisp
		if not Wisp.get_by_user(user_info.key):
			default = True

		# save the new wisp in our database            
		wisp = Wisp(
			name = name,
			owner = user_info.key,
			image = image,
			ssh_key = ssh_key,
			dynamic_image_url = dynamic_image_url,
			image_container_format = image_container_format,
			image_disk_format = image_disk_format,
			post_creation = post_creation,
			callback_url = callback_url,
			project = project
		)
		wisp.put()

		# set default if true
		if default:
			Wisp.set_default(wisp)

		# log to alert
		self.add_message("Wisp %s successfully created!" % name, "success")

		# give it a few seconds to update db, then redirect
		time.sleep(1)
		return self.redirect_to('account-wisps-detail', wisp_id=wisp.key.id())
Exemple #20
0
	def post(self):
		# try to pull get user info from a browser based session
		if self.user_id:
			user_info = User.get_by_id(long(self.user_id))
		else:
			user_info = None

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

		# response headers
		self.response.headers['Content-Type'] = "application/json"
		self.response.headers['Access-Control-Allow-Origin'] = '*'

		# load various variables
		body = json.loads(self.request.body)
		
		# SSH key (not required)
		try:
			ssh_key = body['ssh_key']
		except:
			ssh_key = ""

		# load project if we have it
		try:
			project_id = body['project_id']
			project = Project.get_by_id(long(project_id))
		except:
			project = None

		# handle project wisps differently
		if project:
			wisp = Wisp().from_project(
				ssh_key,
				project,
				user_info
			)
		else:
			try:
				post_creation = body['post_creation']
			except:
				post_creation = ""

			try:
				image_id = body['image_id']
				image = Image.get_by_id(long(image_id))
			except:
				try:
					dynamic_image_url = body['dynamic_image_url']
				except:
					# we don't have an image or a URL, so nothing can do
					params['message'] = "Wisps require an image to boot."
					self.response.set_status(401)
					return self.render_template('api/response.json', **params)

			# disk and container formats if they were sent (usually qcow/bare)
			try:
				image_disk_format = body['image_disk_format']
			except:
				image_disk_format = "qcow2"
			try:
				image_container_format = body['image_container_format']
			except:
				image_container_format = "bare"

			# create an anonymous wisp if we don't have it already
			wisp = Wisp().from_stock(
				ssh_key, 
				post_creation, 
				dynamic_image_url, 
				image_disk_format, 
				image_container_format,
				user_info
			)

		if wisp:	
			# return JSON response
			params['response'] = "success"
			params['wisp'] = wisp
			
			return self.render_template('api/wisp.json', **params)
		else:
			params['message'] = "Wisp creation failed."
			self.response.set_status(401)
			return self.render_template('api/response.json', **params)