Ejemplo n.º 1
0
    def delete(self, group_id=None):
        # lookup user's auth info
        user_info = User.get_by_id(long(self.user_id))

        # find the the entry
        group = Group.get_by_id(long(group_id))

        # this member's membership
        membership = GroupMembers.get_by_userid_groupid(
            user_info.key, group.key)

        # list of users that have the group enabled
        members = GroupMembers.get_group_users(group.key)

        # remove this user's membership
        membership.key.delete()

        # if this user is not the group owner, we simply notify we are done
        if not group or group.owner != user_info.key:
            # use the channel to tell the browser we are done and reload
            self.add_message('Group was removed from account.', 'success')
            channel_token = self.request.get('channel_token')
            channel.send_message(channel_token, 'reload')
            return

        # was there more than just this member?
        if len(members) > 1:
            # find the next user by date and assign them as owner
            entry = GroupMembers.get_new_owner(user_info.key, group.key)
            print "new owner is %s" % entry.member
            new_owner = entry.member
            group.owner = new_owner
            group.put()

            # find member's appliances that match this group and remove
            appliances = Appliance.get_by_user_group(user_info.key, group.key)
            for appliance in appliances:
                appliance.group = None  # public group
                appliance.put()

        else:
            # no more members, so delete the group
            group.key.delete()
            self.add_message('Group successfully deleted!', 'success')

            # remove group from any and all appliances (heavy handed)
            appliances = Appliance.get_by_group(group.key)
            for appliance in appliances:
                appliance.group = None  # public group
                appliance.put()

        # 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
Ejemplo n.º 2
0
	def delete(self, group_id = None):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))

		# find the the entry
		group = Group.get_by_id(long(group_id))

		# this member's membership
		membership = GroupMembers.get_by_userid_groupid(user_info.key, group.key)

		# list of users that have the group enabled
		members = GroupMembers.get_group_users(group.key)

		# remove this user's membership
		membership.key.delete()
		
		# if this user is not the group owner, we simply notify we are done
		if not group or group.owner != user_info.key:
			# use the channel to tell the browser we are done and reload
			self.add_message('Group was removed from account.', 'success')
			channel_token = self.request.get('channel_token')
			channel.send_message(channel_token, 'reload')
			return

		# was there more than just this member?
		if len(members) > 1:
			# find the next user by date and assign them as owner
			entry = GroupMembers.get_new_owner(user_info.key, group.key)
			print "new owner is %s" % entry.member
			new_owner = entry.member
			group.owner = new_owner
			group.put()
		
			# find member's appliances that match this group and remove
			appliances = Appliance.get_by_user_group(user_info.key, group.key)
			for appliance in appliances:
				appliance.group = None # public group
				appliance.put()
		
		else:
			# no more members, so delete the group
			group.key.delete()
			self.add_message('Group successfully deleted!', 'success')

			# remove group from any and all appliances (heavy handed)
			appliances = Appliance.get_by_group(group.key)
			for appliance in appliances:
				appliance.group = None # public group
				appliance.put()

		# 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
Ejemplo n.º 3
0
    def get(self, appliance_id=None):
        # lookup user's auth info
        user_info = User.get_by_id(long(self.user_id))

        # lookup the appliance
        appliance = Appliance.get_by_id(long(appliance_id))

        # group choices pulldown
        self.form.group.choices = []

        # add list of user's groups, if any
        groups = GroupMembers.get_user_groups(user_info.key)
        for group in groups:
            self.form.group.choices.insert(0, (group.key.id(), group.name))

            # public group
        self.form.group.choices.insert(0, ("public", "Public"))

        self.form.name.data = appliance.name
        self.form.token.data = appliance.token

        # hacking the form pulldown with javascript because I'm in a hurry
        if appliance.group:
            group_id = appliance.group.get().key.id()
        else:
            group_id = "public"

            # this should work, but doesn't - see javascript in appliance_edit.html
        self.form.group.data = group_id

        # render new appliance page
        parms = {"appliance": appliance, "group_id": group_id, "gform": self.gform}
        return self.render_template("appliance/edit.html", **parms)
Ejemplo n.º 4
0
	def get(self):
		geopoints = Appliance().get_geopoints()

		# return JSON response
		params = {
			'geopoints': geopoints
		}
		self.response.headers['Content-Type'] = "application/json"
		return self.render_template('api/geopoints.json', **params)
Ejemplo n.º 5
0
	def post(self):
		# paramters, assume failure, response type
		params = {}
		params['response'] = "error"
		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)

		# update appliance info
		latitude = float(packet['appliance']['location']['latitude'])
		longitude = float(packet['appliance']['location']['longitude'])
		appliance.location = ndb.GeoPt(latitude, longitude)
		appliance.dynamicimages = bool(packet['appliance']['dynamicimages'])			
		appliance.put()

		# loop through instances being advertised for sale
		for appliance_instance in packet['instances']:
			# pass in appliance_instance and appliance object
			#logging.info("instance: %s" % appliance_instance['name'])
			instance = Instance.push(appliance_instance, appliance)

		# build parameter list
		params = {}
		params['response'] = "success"
		params['message'] = "Instances accepted for sale."
		self.response.headers['Content-Type'] = 'application/json'
		
		return self.render_template('api/response.json', **params)
Ejemplo n.º 6
0
    def get(self):
        # lookup user's auth info
        user_info = User.get_by_id(long(self.user_id))

        # look up appliances
        appliances = Appliance.get_by_user(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 = {"appliances": appliances, "refresh_channel": refresh_channel, "channel_token": channel_token}

        return self.render_template("appliance/list.html", **params)
Ejemplo n.º 7
0
    def get(self, group_id=None):
        # lookup user's auth info
        user_info = User.get_by_id(long(self.user_id))

        # get the group in question
        group = Group.get_by_id(long(group_id))

        # scan if this user is a member and/or admin
        if group.owner == user_info.key:
            is_admin = True
            is_member = True  # obvious
        else:
            is_admin = False
            is_member = GroupMembers.is_member(user_info.key, group.key)

        # bail if group doesn't exist or user isn't in the membership list
        if not group or not is_member:
            return self.redirect_to('account-groups')

        # get the members
        members = GroupMembers.get_group_users(group.key)

        # create an object with appliance counts per user
        appliance_count = {}
        for member in members:
            # get the appliance counts per user for this group
            count = Appliance.get_appliance_count_by_user_group(
                member.key, group.key)
            appliance_count[member.key.id()] = count

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

        # params build out - ugly cause instructions/admin stuff
        params = {
            'is_admin': is_admin,
            'is_member': is_member,
            'group': group,
            'members': members,
            'appliance_count': appliance_count,
            'num_members': len(members),
            'gmform': self.gmform,
            'refresh_channel': refresh_channel,
            'channel_token': channel_token
        }

        return self.render_template('groups/group_manage.html', **params)
Ejemplo n.º 8
0
	def get(self):
		appliances = Appliance().appliances_with_instances_on_sale()

		# add gravatar URLs
		for appliance in appliances:
			email = appliance.owner.get().email
			gravatar_hash = md5.new(email.lower().strip()).hexdigest()
			appliance.gravatar_url = "https://www.gravatar.com/avatar/%s" % gravatar_hash

		# return JSON response
		params = {
			'appliances': appliances,
			'message': "This is a list of all active appliances with instances for sale."
		}
		self.response.headers['Content-Type'] = "application/json"
		return self.render_template('api/appliances.json', **params)
Ejemplo n.º 9
0
	def get(self, group_id = None):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))
		
		# get the group in question
		group = Group.get_by_id(long(group_id))

		# scan if this user is a member and/or admin
		if group.owner == user_info.key:
			is_admin = True
			is_member = True # obvious
		else:
			is_admin = False
			is_member = GroupMembers.is_member(user_info.key, group.key)

		# bail if group doesn't exist or user isn't in the membership list
		if not group or not is_member:
			return self.redirect_to('account-groups')

		# get the members
		members = GroupMembers.get_group_users(group.key)

		# create an object with appliance counts per user
		appliance_count = {}
		for member in members:
			# get the appliance counts per user for this group
			count = Appliance.get_appliance_count_by_user_group(member.key, group.key)
			appliance_count[member.key.id()] = count

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

		# params build out - ugly cause instructions/admin stuff
		params = {
			'is_admin': is_admin,
			'is_member': is_member,
			'group': group,
			'members': members,
			'appliance_count': appliance_count,
			'num_members': len(members),
			'gmform': self.gmform,
			'refresh_channel': refresh_channel,
			'channel_token': channel_token 
		}

		return self.render_template('groups/edit.html', **params)
Ejemplo n.º 10
0
    def get(self, appliance_id=None):
        # lookup user's auth info
        user_info = User.get_by_id(long(self.user_id))

        # seek out the appliance in question
        appliance = Appliance.get_by_id(long(appliance_id))

        # bail if appliance doesn't exist user isn't the owner
        if not appliance or appliance.owner != user_info.key:
            return self.redirect_to("account-appliances")

            # find instances associated with this appliance
        instances = Instance.get_by_appliance(appliance.key)

        # render new appliance page
        parms = {"appliance": appliance, "instances": instances}
        return self.render_template("appliance/view.html", **parms)
Ejemplo n.º 11
0
    def delete(self, appliance_id=None):
        # delete the entry from the db
        appliance = Appliance.get_by_id(long(appliance_id))

        if appliance:
            appliance.key.delete()
            self.add_message("Appliance successfully deleted!", "success")
        else:
            self.add_message("Appliance 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
Ejemplo n.º 12
0
	def delete(self, appliance_id = None):
		# delete the entry from the db
		appliance = Appliance.get_by_id(long(appliance_id))

		if appliance:
			appliance.key.delete()
			self.add_message('Appliance successfully deleted!', 'success')
		else:
			self.add_message('Appliance 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
Ejemplo n.º 13
0
    def get(self, appliance_id=None):
        # lookup user's auth info
        user_info = User.get_by_id(long(self.user_id))

        # seek out the appliance in question
        appliance = Appliance.get_by_id(long(appliance_id))

        # bail if appliance doesn't exist user isn't the owner
        if not appliance or appliance.owner != user_info.key:
            return self.redirect_to('account-appliances')

        # find instances associated with this appliance
        instances = Instance.get_by_appliance(appliance.key)

        # render new appliance page
        parms = {'appliance': appliance, 'instances': instances}
        return self.render_template('appliance/view.html', **parms)
Ejemplo n.º 14
0
    def get(self):
        # lookup user's auth info
        user_info = User.get_by_id(long(self.user_id))

        # look up appliances
        appliances = Appliance.get_by_user(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 = {
            'appliances': appliances,
            'refresh_channel': refresh_channel,
            'channel_token': channel_token
        }

        return self.render_template('appliance/list.html', **params)
	def get(self):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))

		# look up appliances
		appliances = Appliance.get_by_user(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 = {
			'appliances': appliances, 
			'refresh_channel': refresh_channel,
			'channel_token': channel_token 
		}

		return self.render_template('appliance/appliances.html', **params)
Ejemplo n.º 16
0
	def post(self):
		# 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)

		# update appliance info
		latitude = float(packet['appliance']['location']['latitude'])
		longitude = float(packet['appliance']['location']['longitude'])
		appliance.location = ndb.GeoPt(latitude, longitude)
		appliance.dynamicimages = bool(packet['appliance']['dynamicimages'])			
		appliance.put()

		# respond with success
		params['response'] = "success"
		params['message'] = "Appliance token authenticated."
		return self.render_template('api/response.json', **params)
Ejemplo n.º 17
0
    def delete(self, group_id=None, member_id=None):
        # lookup user's auth info
        user_info = User.get_by_id(long(self.user_id))

        # get the group in question
        group = Group.get_by_id(long(group_id))
        member = User.get_by_id(long(member_id))

        # get this user's admin rights
        is_admin = False
        if group.owner == user_info.key:
            is_admin = True

        # bail if group doesn't exist or user is not admin
        if not group or not is_admin:
            # log to alert
            self.add_message("You may not remove this user from group.",
                             "error")
        else:
            # look up the other user's group membership
            membership = GroupMembers.get_by_userid_groupid(
                member.key, group.key)

            # kill the membership
            membership.key.delete()

            # find member's appliances that match that group and remove
            appliances = Appliance.get_by_user_group(member.key, group.key)
            for appliance in appliances:
                appliance.group = None  # public group
                appliance.put()

            # log to alert
            self.add_message("User removed from group!", "success")

        # 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
Ejemplo n.º 18
0
	def get(self, appliance_id = None):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))

		# lookup the appliance
		appliance = Appliance.get_by_id(long(appliance_id))

		# group choices pulldown
		self.form.group.choices=[]
		
		# add list of user's groups, if any
		groups = GroupMembers.get_user_groups(user_info.key)
		for group in groups:
			print group.key.id()
			self.form.group.choices.insert(0, (group.key.id(), group.name))

		# public group
		self.form.group.choices.insert(0, ('public', "Public"))

		self.form.name.data = appliance.name
		self.form.token.data = appliance.token

		# hacking the form pulldown with javascript because I'm in a hurry
		if appliance.group:
			group_id = appliance.group.get().key.id()
		else:
			group_id = "public"

		# this should work, but doesn't - see javascript in appliance_edit.html
		self.form.group.data = group_id

		# render new appliance page
		parms = {
			'appliance': appliance,
			'group_id': group_id,
			'gform': self.gform
		}
		return self.render_template('appliance/appliance_edit.html', **parms)
Ejemplo n.º 19
0
	def delete(self, group_id = None, member_id = None):
		# lookup user's auth info
		user_info = User.get_by_id(long(self.user_id))
		
		# get the group in question
		group = Group.get_by_id(long(group_id))
		member = User.get_by_id(long(member_id))

		# get this user's admin rights
		is_admin = False
		if group.owner == user_info.key:
			is_admin = True

		# bail if group doesn't exist or user is not admin
		if not group or not is_admin:
			# log to alert
			self.add_message("You may not remove this user from group.", "error")
		else:	
			# look up the other user's group membership
			membership = GroupMembers.get_by_userid_groupid(member.key, group.key)

			# kill the membership
			membership.key.delete()

			# find member's appliances that match that group and remove
			appliances = Appliance.get_by_user_group(member.key, group.key)
			for appliance in appliances:
				appliance.group = None # public group
				appliance.put()

			# log to alert
			self.add_message("User removed from group!", "success")
			
		# 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
Ejemplo n.º 20
0
    def post(self):
        # lookup user's auth info
        user_info = User.get_by_id(long(self.user_id))

        # initialize form choices for group
        self.form.group.choices = []

        # add list of user's groups, if any
        groups = GroupMembers.get_user_groups(user_info.key)
        for group in groups:
            self.form.group.choices.insert(0, (str(group.key.id()), group.name))

            # public group
        self.form.group.choices.insert(0, ("public", "Public"))

        # check if we are getting a custom group entry
        if self.form.group.data == "custom":
            # check if the group exists
            if Group.get_by_name(self.form.custom.data.strip()):
                self.add_message("A group with that name already exists!", "error")
                return self.redirect_to("account-appliances")

                # make the new group
            group = Group(name=self.form.custom.data.strip(), owner=user_info.key)
            group.put()
            group_key = group.key

            # create the group member entry
            groupmember = GroupMembers(
                group=group_key, member=user_info.key, invitor=user_info.key, active=True  # same same
            )
            groupmember.put()

            # hack the form with new group
            self.form.group.choices.insert(0, ("custom", "Custom"))
        else:
            # grab an existing group
            if self.form.group.data.strip() == "public":
                # no group for public appliances
                group_key = None
            else:
                # check membership
                group = Group.get_by_id(int(self.form.group.data.strip()))
                if GroupMembers.is_member(user_info.key, group.key):
                    group_key = group.key
                else:
                    group_key = None

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

            # load form values
        name = self.form.name.data.strip()
        token = self.form.token.data.strip()

        # check if we have it already - all that work bitches?
        if Appliance.get_by_token(token):
            self.add_message("An appliance with that token already exists!", "error")
            return self.redirect_to("account-appliances")

            # save the new appliance in our database
        appliance = Appliance(name=name, token=token, group=group_key, owner=user_info.key)
        appliance.put()

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

        # give it a few seconds to update db, then redirect
        time.sleep(1)
        return self.redirect_to("account-appliances")
Ejemplo n.º 21
0
    def post(self):
        # lookup user's auth info
        user_info = User.get_by_id(long(self.user_id))

        # initialize form choices for group
        self.form.group.choices = []

        # add list of user's groups, if any
        groups = GroupMembers.get_user_groups(user_info.key)
        for group in groups:
            self.form.group.choices.insert(0,
                                           (str(group.key.id()), group.name))

        # public group
        self.form.group.choices.insert(0, ('public', "Public"))

        # check if we are getting a custom group entry
        if self.form.group.data == "custom":
            # check if the group exists
            if Group.get_by_name(self.form.custom.data.strip()):
                self.add_message("A group with that name already exists!",
                                 "error")
                return self.redirect_to('account-appliances')

            # make the new group
            group = Group(name=self.form.custom.data.strip(),
                          owner=user_info.key)
            group.put()
            group_key = group.key

            # create the group member entry
            groupmember = GroupMembers(
                group=group_key,
                member=user_info.key,
                invitor=user_info.key,  # same same
                active=True)
            groupmember.put()

            # hack the form with new group
            self.form.group.choices.insert(0, ('custom', "Custom"))
        else:
            # grab an existing group
            if self.form.group.data.strip() == 'public':
                # no group for public appliances
                group_key = None
            else:
                # check membership
                group = Group.get_by_id(int(self.form.group.data.strip()))
                if GroupMembers.is_member(user_info.key, group.key):
                    group_key = group.key
                else:
                    group_key = None

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

        # load form values
        name = self.form.name.data.strip()
        token = self.form.token.data.strip()

        # check if we have it already - all that work bitches?
        if Appliance.get_by_token(token):
            self.add_message("An appliance with that token already exists!",
                             "error")
            return self.redirect_to('account-appliances')

        # save the new appliance in our database
        appliance = Appliance(name=name,
                              token=token,
                              group=group_key,
                              owner=user_info.key)
        appliance.put()

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

        # give it a few seconds to update db, then redirect
        time.sleep(1)
        return self.redirect_to('account-appliances')
Ejemplo n.º 22
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)
Ejemplo n.º 23
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)
Ejemplo n.º 24
0
	def prepare_appliance(self, val):
		appliance = Appliance.get_by_token(val.token)
		return [
			('appliance', appliance.key),
			('owner', appliance.owner),
			('group', appliance.group),]
Ejemplo n.º 25
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()))