예제 #1
0
	def post(self):
		if not self.form.validate():          
			self.add_message("The form did not validate.", 'error')
			return self.get()

		# load values out of the form
		name = self.form.name.data.strip()
		vpus = self.form.vpus.data
		memory = self.form.memory.data
		disk = self.form.disk.data
		network_down = self.form.network_down.data
		network_up = self.form.network_up.data
		rate = self.form.rate.data

		# save the flavor in our database
		flavor = Flavor(
			name = name,
			vpus = vpus,
			memory = memory,
			disk = disk,
			network_down = network_down,
			network_up = network_up,
			rate = rate, # current market rate
			launches = 0, # number of total launches
			hot = 2 # suggest minimum two instance addresses hot
		)
		flavor.put()

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

		# give it a few seconds to update db, then redirect
		time.sleep(1)
		return self.redirect_to('admin-flavors')
예제 #2
0
    def post(self):
        if not self.form.validate():
            self.add_message("The form did not validate.", 'error')
            return self.get()

        # load values out of the form
        name = self.form.name.data.strip()
        description = self.form.description.data.strip()
        vpus = self.form.vpus.data
        memory = self.form.memory.data
        disk = self.form.disk.data
        network = self.form.network.data
        rate = self.form.rate.data

        # save the flavor in our database
        flavor = Flavor(
            name=name,
            description=description,
            vpus=vpus,
            memory=memory,
            disk=disk,
            network=network,
            rate=rate,  # current market rate
            launches=0,  # number of total launches
            hot=2  # suggest minimum two instance addresses hot
        )
        flavor.put()

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

        # give it a few seconds to update db, then redirect
        time.sleep(1)
        return self.redirect_to('admin-flavors')
예제 #3
0
	def post(self, action):
		self.response.headers['Content-Type'] = 'application/json'
		self.response.set_status(200)
		# write dictionary as json string
		self.response.out.write(json.dumps(
				# retrieve flavors as schema and convert schema to dict
				Flavor.as_schema_list(
					# pass get_all method as query object
					Flavor.query()).as_dict()))
예제 #4
0
	def post(self):
		# get current flavors
		flavors = Flavor().get_all()
		
		# build parameter list
		params = {
			'flavors': flavors
		}

		# return images via template
		self.response.headers['Content-Type'] = 'application/json'
		return self.render_template('api/flavors.json', **params)
예제 #5
0
	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)
예제 #6
0
    def get(self):
        # lookup user's auth info
        user_info = User.get_by_id(long(self.user_id))

        # look up user's articles
        flavors = Flavor.get_all()

        # setup channel to do page refresh
        channel_token = user_info.key.urlsafe()
        refresh_channel = channel.create_channel(channel_token)
        params = {
            'flavors': flavors,
            'refresh_channel': refresh_channel,
            'channel_token': channel_token
        }

        return self.render_template('admin/flavors.html', **params)
예제 #7
0
	def get(self):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))

		# look up user's articles
		flavors = Flavor.get_all()

		# setup channel to do page refresh
		channel_token = user_info.key.urlsafe()
		refresh_channel = channel.create_channel(channel_token)
		params = {
			'flavors': flavors, 
			'refresh_channel': refresh_channel,
			'channel_token': channel_token 
		}

		return self.render_template('admin/flavors.html', **params)
예제 #8
0
	def delete(self, flavor_id = None):
		# delete the entry from the db
		flavor = Flavor.get_by_id(long(flavor_id))

		if flavor:
			flavor.key.delete()
			self.add_message('Flavor successfully deleted!', 'success')
		else:
			self.add_message('Flavor 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
예제 #9
0
    def put(self, flavor_id=None):
        flavor = Flavor.get_by_id(long(flavor_id))

        # get the enable/active state
        enable = self.request.get("enable")

        if flavor:
            if enable == '1':
                flavor.active = True
                flavor.put()
            else:
                flavor.active = False
                flavor.put()

        # hangout for a second
        time.sleep(1)

        return
예제 #10
0
	def put(self, flavor_id = None):
		flavor = Flavor.get_by_id(long(flavor_id))

		# get the enable/active state
		enable = self.request.get("enable")
		
		if flavor:
			if enable == '1':
				flavor.active = True
				flavor.put()
			else:
				flavor.active = False
				flavor.put()
		
		# hangout for a second
		time.sleep(1)
		
		return
예제 #11
0
    def delete(self, flavor_id=None):
        # delete the entry from the db
        flavor = Flavor.get_by_id(long(flavor_id))

        if flavor:
            flavor.key.delete()
            self.add_message('Flavor successfully deleted!', 'success')
        else:
            self.add_message(
                'Flavor 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
예제 #12
0
	def prepare_flavor(self, flavor_specs):
		flavor = Flavor.get_by_merge(**flavor_specs)
		return [
			('flavor', flavor.key),
			('ask', flavor_specs['ask']),]
예제 #13
0
	def get(self, project_id = None):
		project = Project.get_by_id(long(project_id))
		# if no project
		if not project:
			return self.redirect_to('projects')

		# assume this user is not owner
		owner = False

		# print self.render_url(project.json_url, {})

		# determine if we can show the project
		if not project.public:
			# see if we have a user
			try:
				user_info = User.get_by_id(long(self.user_id))
				if user_info.key != project.owner:
					raise Exception
				else:
					owner = True

			except:
				self.add_message("You must be the owner to do this.", "fail")
				return self.redirect_to('projects')
		else:
			try:
				user_info = User.get_by_id(long(self.user_id))
				if user_info.key == project.owner:
					owner = True

			except:
				user_info = None

		# define minimum specifications for the instance
		specs = {
			'vpus': project.vpus,
			'memory': project.memory,
			'disk': project.disk
		}

		# empty forms
		self.form.provider.choices = []
		self.form.flavor.choices = []

		# plenty?
		plenty = False

		# dict of providers
		providers = {}

		# find the all public provider's appliances and add to providers object
		appliances = Appliance.get_by_group(None)
		for appliance in appliances:
			providers[appliance.key.id()] = {
				'name': "%s (Public)" % appliance.name,
				'location': [appliance.location.lat, appliance.location.lon],
				'flavors': []
			}

		# if there is a user, find his groups and do the same with appliances in those groups
		if user_info:
			groups = Group.get_by_owner(user_info.key)
			for group in groups:
				appliances = Appliance.get_by_group(group.key)
				for appliance in appliances:
					providers[str(appliance.key.id())] = {
						'name': "%s of %s (Hybrid Group)" % (appliance.name, group.name),
						'location': [appliance.location.lat, appliance.location.lon],
						'flavors': []
					}

		# iterate over the dictionary of providers
		for provider in providers:
			# find the list of flavors for this provider which support this project
			flavors = Flavor.flavors_with_min_specs_by_appliance_on_sale(
				specs, 
				ndb.Key('Appliance', long(provider))
			)

			# add provider to the form and the flavors to provider object if flavors exist
			if flavors:
				plenty = True
				# insert this provider's appliance into the form
				self.form.provider.choices.insert(0, (provider, providers[provider]['name']))

				# insert flavors into object
				for flavor in flavors:
					providers[provider]['flavors'].append(
						{
							'id': str(flavor.key.id()),
							'name': flavor.name,
							'description': flavor.description
						}
					)

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

		# params build out
		params = {
			'project': project,
			'providers': json.dumps(providers),
			'plenty': plenty,
			'owner': owner,
			'refresh_channel': refresh_channel,
			'channel_token': channel_token 
		}

		return self.render_template('project/view.html', **params)
예제 #14
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)