Example #1
0
	def action():
		"""
		Performs a sync from the pool's list of flavors to the appliance.

		Cron: Every 15 minutes.
		"""
		# get the appliance for api token (not required, but sent if we have it)
		appliance = db.session.query(Appliance).first()

		# sync the flavors
		flavors = Flavors()
		response = flavors.sync(appliance)
Example #2
0
    def action():
        """
		Performs a sync from the pool's list of flavors to the appliance.

		Cron: Every 15 minutes.
		"""
        # get the appliance for api token (not required, but sent if we have it)
        appliance = db.session.query(Appliance).first()

        # sync the flavors
        flavors = Flavors()
        response = flavors.sync(appliance)
Example #3
0
    def action(ip=('i', default_ip)):
        """
		Restores the appliance to factory default settings.
		"""
        try:
            if ip == default_ip:
                print "Please enter the appliance's IP address."
                print "Usage: ./manage.py reset -i x.x.x.x"
                return action

            # double check they want to do this
            if query_yes_no("Are you sure you want to reset the appliance?"):

                # initialize database
                path = os.path.dirname(os.path.abspath(__file__))
                os.system('sqlite3 "%s/utterio.db" < "%s/schema.sql"' %
                          (path, path))

                # initialize the appliance object
                appliance = Appliance()
                appliance.initialize(ip)

                # sync with pool database
                images = Images()
                iresponse = images.sync(appliance)

                flavors = Flavors()
                fresponse = flavors.sync(appliance)

                if iresponse['response'] != "success":
                    print iresponse['result']
                elif fresponse['response'] != "success":
                    print iresponse['result']
                else:
                    print "The database has been cleared and a new API token has been generated."
                    configure_blurb()

        except ValueError as ex:
            print ex
Example #4
0
	def action(ip=('i', default_ip)):
		"""
		Restores the appliance to factory default settings.
		"""
		try:
			if ip == default_ip:
				print "Please enter the appliance's IP address."
				print "Usage: ./manage.py reset -i x.x.x.x"
				return action

			# double check they want to do this	
			if query_yes_no("Are you sure you want to reset the appliance?"):

				# initialize database
				path = os.path.dirname(os.path.abspath(__file__))
				os.system('sqlite3 "%s/utterio.db" < "%s/schema.sql"' % (path, path))

				# initialize the appliance object
				appliance = Appliance()
				appliance.initialize(ip)

				# sync with pool database
				images = Images()
				iresponse = images.sync(appliance)

				flavors = Flavors()
				fresponse = flavors.sync(appliance)

				if iresponse['response'] != "success":
					print iresponse['result']
				elif fresponse['response'] != "success":
					print iresponse['result']
				else:
					print "The database has been cleared and a new API token has been generated."
					configure_blurb()

		except ValueError as ex:
			print ex
Example #5
0
    def action(ip=('i', default_ip)):
        """
		Installs a new database configuration for the appliance.
		"""
        # run database reset script - use current path to run file
        path = os.path.dirname(os.path.abspath(__file__))

        # initialize database
        os.system('sqlite3 "%s/utterio.db" < "%s/schema.sql"' % (path, path))

        # initialize the appliance object
        appliance = Appliance()
        appliance.initialize(ip)

        # sync to remote database
        images = Images()
        response = images.sync(appliance)

        flavors = Flavors()
        response = flavors.sync(appliance)

        # configure output
        configure_blurb()
Example #6
0
	def action(ip=('i', default_ip)):
		"""
		Installs a new database configuration for the appliance.
		"""
		# run database reset script - use current path to run file
		path = os.path.dirname(os.path.abspath(__file__))

		# initialize database
		os.system('sqlite3 "%s/utterio.db" < "%s/schema.sql"' % (path, path))
		
		# initialize the appliance object
		appliance = Appliance()
		appliance.initialize(ip)
		
		# sync to remote database
		images = Images()
		response = images.sync(appliance)

		flavors = Flavors()
		response = flavors.sync(appliance)

		# configure output
		configure_blurb()
Example #7
0
    def action(ip=('i', default_ip)):
        """
		Installs a new database configuration for the appliance.
		"""

        # create all tables
        db.create_all()

        if not Appliance.get():
            # initialize the appliance object
            appliance = Appliance()
            appliance.initialize(ip)

        # sync flavors from pool (openstack sync comes later when we have a user)
        flavors = Flavors().sync()

        # configure output
        configure_blurb()
Example #8
0
    def action(ip=('i', default_ip)):
        """
		Restores the appliance to factory default settings.
		"""
        try:
            if ip == default_ip:
                print "Please enter the appliance's IP address."
                print "Usage: ./manage.py reset -i x.x.x.x"
                return action

            # double check they want to do this
            if query_yes_no("Are you sure you want to reset the appliance?"):

                # initialize database
                path = os.path.dirname(os.path.abspath(__file__))
                os.system('cp "%s/utterio.db" "%s/utterio_backup.db"' %
                          (path, path))

                # delete, then create all tables
                db.drop_all()
                db.create_all()

                # initialize the appliance object
                appliance = Appliance()
                appliance.initialize(ip)

                # sync with pool database
                flavors = Flavors().sync()

                if flavors['response'] != "success":
                    print flavors['result']
                else:
                    print "The database has been cleared and a new API token has been generated."
                    configure_blurb()

        except ValueError as ex:
            print ex
Example #9
0
def configure_twitter():
    # check configuration
    settings = Status().check_settings()

    # get the forms for the page
    form = TwitterForm(request.form)
    mrof = BotForm(request.form)

    # blow the flavors into a list
    flavor_list = []
    flavors = Flavors.get_all()
    for flavor in flavors:
        flavor_list.append((flavor.id, flavor.description))

    mrof.flavor.choices = flavor_list

    # twitter bot credentials
    bot = TwitterBot.get()

    # initialize the bot if it's not
    if not bot:
        bot = oauth_initialize()
    else:
        if bot.complete == 0:
            bot = oauth_initialize()

        if bot.complete == 1 and request.method == "GET":
            # ensure we don't use stale creds
            bot = oauth_initialize()

        elif bot.complete == 1 and request.method == "POST":
            if form.validate_on_submit():
                pin = request.form["pin"]
                bot = oauth_complete(pin)
                if bot:
                    flash("Authentication with Twitter complete.", "success")
                else:
                    flash("Authentication with Twitter failed.", "error")
                    bot = TwitterBot.get()
                    bot.delete(bot)
                    return redirect(url_for(".configure_twitter"))
            else:
                # form was not valid, so show errors
                flash("There were form errors. Please check your entries and try again.", "error")

        elif request.method == "POST":
            if mrof.validate_on_submit():
                bot.flavor_id = mrof.flavor.data
                bot.announce = mrof.announce.data
                bot.max_instances = mrof.max_instances.data
                bot.updated = int(time.time())
                bot.update()

                if bot.announce > 0:
                    # announce (requires 'settings' in comment to reload stream bot)
                    tweet_status(
                        "Appliance settings updated. Now serving up to (%s) %s instances via '@%s !status'"
                        % (bot.max_instances, bot.flavor.name, bot.screen_name)
                    )
                flash("Bot settings updated.", "success")
            else:
                # form was not valid, so show errors
                flash("There were form errors. Please check your entries and try again.", "error")

                # no bot not hot
    if not bot:
        flash("Twitterbot failed to contact Twitter or get credentials.", "error")
        bot = None

    else:
        # set default form values
        mrof.flavor.data = bot.flavor_id
        mrof.announce.data = bot.announce

    return render_template("configure/twitter.html", bot=bot, settings=settings, form=form, mrof=mrof)
Example #10
0
	def check_settings(self):
		status = db.session.query(Status).first()
		
		# calculate cache timeout (120 seconds)
		epoch_time = int(time.time())
		try:
			if (status.updated + 900) < epoch_time:
				# it's been 15 minutes so we are hot
				check = True
			else:
				check = False
		except:
			# need to create a new entry
			check = True
			status = Status()

		# objects
		appliance = Appliance().get()
		openstack = OpenStack()
		flavors = Flavors()

		# if the cache time has been a while, or we are on
		# the configuration page, check settings and cache
		if check:
			app.logger.info("Running full status check.")
			
			# openstack connected?
			openstack_check = openstack.check()
			status.openstack_check = openstack_check['result']

			# coinbase tokens working?
			coinbase_check = coinbase_checker(appliance)
			status.coinbase_check = coinbase_check

			# token valid?
			response = pool_connect(method='authorization', appliance=appliance)

			if response['response'] == "success":
				token_check = True
			else:
				token_check = False
			status.token_check = token_check

			# update database
			status.updated = epoch_time

			# ngrok connection
			ngrok_check = ngrok_checker(appliance)
			status.ngrok_check = ngrok_check
			
			# one flavor installed?
			flavors_check = flavors.check()
			status.flavors_check = flavors_check

			status.update()
		
		else:
			# app.logger.info("Running partial status check.")
			
			# stuff we check all the time
			# openstack connected?
			openstack_check = openstack.check()
			status.openstack_check = openstack_check['result']

			# ngrok connection
			ngrok_check = ngrok_checker(appliance)
			status.ngrok_check = ngrok_check

			# one flavor installed?
			flavors_check = flavors.check()
			status.flavors_check = flavors_check

			# update
			status.update()

		# build the response object
		settings = {
			"flavors": status.flavors_check,
			"openstack": status.openstack_check,
			"coinbase": status.coinbase_check,
			"ngrok": status.ngrok_check,
			"token": status.token_check,
		}
		
		return settings
Example #11
0
	def start(self):
		from webapp.libs.openstack import flavor_verify_install
		from webapp.libs.openstack import image_verify_install
		from webapp.libs.openstack import instance_start
	
		# build the response
		response = {"response": "success", "result": {"message": ""}}

		# appliance
		appliance = Appliance().get()

		# load the callback url (expected to be None)
		callback_url = self.callback_url
		
		# check if instance needs to reset
		epoch_time = int(time.time())
		if self.expires < epoch_time:
			# instance time expired, so don't start
			self.state = 1
			self.update()
			response['response'] = "error"
			response['result']['message'] = "Instance payment is expired.  Now waiting on payment."

		# we run a maximum of 7 callback checks
		for loop_count in range(7):
			# make a call to the callback url to get instance details
			next_state = 3 # hack the expected next state into the pool packet
			pool_response = pool_instance(url=callback_url, instance=self, next_state=next_state, appliance=appliance)

			# check for a failure to contact the callback server
			if pool_response['response'] == "error":
				self.message = pool_response['result']['message']
				self.message_count = self.message_count + 1
				self.update()
				return pool_response

			# look and see if we have a callback_url in the response
			try:
				callback_url = pool_response['result']['instance']['callback_url']
				# run the loop again to call the callback url
				continue 
			except:
				# break out
				break
		
		# for else returns a depth error
		else:
			response['response'] = "error"
			response['result']['message'] = "Callback depth exceeded."
			self.message = response['result']['message']
			self.message_count = self.message_count + 1
			self.update()
			return response
		
		# and lo, callback_url is saved
		self.callback_url = callback_url
		self.update()

		# get the image name if it exists in the response 
		try:
			image_name = pool_response['result']['instance']['image']
			image = db.session.query(Images).filter_by(name=image_name).first()
			self.image_id = image.id
			self.update()
		except:
			image_name = None
			# get the dynamic image url if it exists in the response
			try:
				dynamic_image_url = pool_response['result']['instance']['dynamic_image_url']
				self.dynamic_image_url = dynamic_image_url
				self.update()
			except:
				# not good, but we can use a default
				image = db.session.query(Images).first()
				self.image_id = image.id
				self.update()

		# post creation file is blank to start
		post_creation_ssh_key_combo = ""
		
		# load the parser to unencode jinja2 template escaping from appliance
		h = HTMLParser()

		# ssh_key unrolling
		try:
			ssh_key = pool_response['result']['instance']['ssh_key'] # an array

			# loop through both strings and cat onto post_creation_ssh_key_combo
			# using prefered method of injecting keys with cloud-init
			post_creation_ssh_key_combo += "#cloud-config\n"
			post_creation_ssh_key_combo += "ssh_authorized_keys:\n"
			for line in ssh_key:
				post_creation_ssh_key_combo += " - %s\n" % h.unescape(line)
			post_creation_ssh_key_combo += "\n"

		except:
			# do nothing on various key failure
			pass

		# post creation configuration handling
		try:
			post_creation = pool_response['result']['instance']['post_creation'] # an array

			for line in post_creation:
				# import what the user put in the textbox for their wisp
				post_creation_ssh_key_combo += "%s\n" % h.unescape(line)

		except:
			# do nothing on post creation failure
			pass

		# update the instance with post creation
		self.post_creation = post_creation_ssh_key_combo
		self.update()

		# take the instance's flavor and verify install
		flavor = Flavors().get_by_id(self.flavor.id)
		osflavor = flavor_verify_install(flavor)

		if osflavor['response'] == "error":
			# we've failed to install flavor, so we disable it
			flavor.osid = ""
			flavor.active = 0
			flavor.update()

			# now we disable the other instances using the flavor
			instances = Instances()
			instances.toggle(flavor.id, 0)

			# disable this instance
			self.state = 0
			self.expires = self.created # zeros out the payment
			self.update()

			# log it
			app.logger.error("Disabling all instances using flavor=(%s) due to OpenStack failure." % flavor.name)

			# build the response and return
			response['response'] = "error"
			response['result']['message'] = "Error creating flavor inside OpenStack."
			return response

		# deal with creating dynamic image or use predefined one
		if self.dynamic_image_url:
			image = Images().get_or_create_by_instance(self)
		else:
			image = Images().get_by_id(self.image.id)

		if not image:
			response['response'] = "error"
			response['result']['message'] = "Error creating dynamic image."
			return response
		else:
			self.image = image
			self.update()

		# take the image and verify install
		osimage = image_verify_install(self.image)

			# handle failures of either flavor or image
		if osimage['response'] == "error":
			response['response'] = "error"
			response['result']['message'] = "Error creating image."
			return response

		# tell openstack to start the instance
		cluster_response = instance_start(self)

		# process response
		if cluster_response['response'] == "success":
			server = cluster_response['result']['server']
			self.osid = server.id # assign openstack instance id
			self.state = 3 # mark as starting
			self.update()
			response['result'] = cluster_response['result']
		else:
			response = cluster_response

		return response
Example #12
0
def configure_twitter():
    # check configuration
    settings = Status().check_settings()

    # get the forms for the page
    form = TwitterForm(request.form)
    mrof = BotForm(request.form)

    # blow the flavors into a list
    flavor_list = []
    flavors = Flavors.get_all()
    for flavor in flavors:
        flavor_list.append((flavor.id, flavor.description))

    mrof.flavor.choices = flavor_list

    # twitter bot credentials
    bot = TwitterBot.get()

    # initialize the bot if it's not
    if not bot:
        bot = oauth_initialize()
    else:
        if bot.complete == 0:
            bot = oauth_initialize()

        if bot.complete == 1 and request.method == 'GET':
            # ensure we don't use stale creds
            bot = oauth_initialize()

        elif bot.complete == 1 and request.method == 'POST':
            if form.validate_on_submit():
                pin = request.form['pin']
                bot = oauth_complete(pin)
                if bot:
                    flash("Authentication with Twitter complete.", "success")
                else:
                    flash("Authentication with Twitter failed.", "error")
                    bot = TwitterBot.get()
                    bot.delete(bot)
                    return redirect(url_for(".configure_twitter"))
            else:
                # form was not valid, so show errors
                flash(
                    "There were form errors. Please check your entries and try again.",
                    "error")

        elif request.method == 'POST':
            if mrof.validate_on_submit():
                bot.flavor_id = mrof.flavor.data
                bot.announce = mrof.announce.data
                bot.max_instances = mrof.max_instances.data
                bot.updated = int(time.time())
                bot.update()

                if bot.announce > 0:
                    # announce (requires 'settings' in comment to reload stream bot)
                    tweet_status(
                        "Appliance settings updated. Now serving up to (%s) %s instances via '@%s !status'"
                        %
                        (bot.max_instances, bot.flavor.name, bot.screen_name))
                flash("Bot settings updated.", "success")
            else:
                # form was not valid, so show errors
                flash(
                    "There were form errors. Please check your entries and try again.",
                    "error")

    # no bot not hot
    if not bot:
        flash("Twitterbot failed to contact Twitter or get credentials.",
              "error")
        bot = None

    else:
        # set default form values
        mrof.flavor.data = bot.flavor_id
        mrof.announce.data = bot.announce

    return render_template('configure/twitter.html',
                           bot=bot,
                           settings=settings,
                           form=form,
                           mrof=mrof)
Example #13
0
    def start(self):
        from webapp.libs.openstack import flavor_verify_install
        from webapp.libs.openstack import image_verify_install
        from webapp.libs.openstack import instance_start

        # build the response
        response = {"response": "success", "result": {"message": ""}}

        # appliance
        appliance = Appliance().get()

        # load the callback url (expected to be None)
        callback_url = self.callback_url

        # check if instance needs to reset
        epoch_time = int(time.time())
        if self.expires < epoch_time:
            # instance time expired, so don't start
            self.state = 1
            self.update()
            response['response'] = "error"
            response['result'][
                'message'] = "Instance payment is expired.  Now waiting on payment."

        # we run a maximum of 7 callback checks
        for loop_count in range(7):
            # make a call to the callback url to get instance details
            next_state = 3  # hack the expected next state into the pool packet
            pool_response = pool_instance(url=callback_url,
                                          instance=self,
                                          next_state=next_state,
                                          appliance=appliance)

            # check for a failure to contact the callback server
            if pool_response['response'] == "error":
                self.message = pool_response['result']['message']
                self.message_count = self.message_count + 1
                self.update()
                return pool_response

            # look and see if we have a callback_url in the response
            try:
                callback_url = pool_response['result']['instance'][
                    'callback_url']
                # run the loop again to call the callback url
                continue
            except:
                # break out
                break

        # for else returns a depth error
        else:
            response['response'] = "error"
            response['result']['message'] = "Callback depth exceeded."
            self.message = response['result']['message']
            self.message_count = self.message_count + 1
            self.update()
            return response

        # and lo, callback_url is saved
        self.callback_url = callback_url
        self.update()

        # get the image name if it exists in the response
        try:
            image_name = pool_response['result']['instance']['image']
            image = db.session.query(Images).filter_by(name=image_name).first()
            self.image_id = image.id
            self.update()
        except:
            image_name = None
            # get the dynamic image url if it exists in the response
            try:
                dynamic_image_url = pool_response['result']['instance'][
                    'dynamic_image_url']
                self.dynamic_image_url = dynamic_image_url
                self.update()
            except:
                # not good, but we can use a default
                image = db.session.query(Images).first()
                self.image_id = image.id
                self.update()

        # post creation file is blank to start
        post_creation_ssh_key_combo = ""

        # load the parser to unencode jinja2 template escaping from appliance
        h = HTMLParser()

        # ssh_key unrolling
        try:
            ssh_key = pool_response['result']['instance'][
                'ssh_key']  # an array

            # loop through both strings and cat onto post_creation_ssh_key_combo
            # using prefered method of injecting keys with cloud-init
            post_creation_ssh_key_combo += "#cloud-config\n"
            post_creation_ssh_key_combo += "ssh_authorized_keys:\n"
            for line in ssh_key:
                post_creation_ssh_key_combo += " - %s\n" % h.unescape(line)
            post_creation_ssh_key_combo += "\n"

        except:
            # do nothing on various key failure
            pass

        # post creation configuration handling
        try:
            post_creation = pool_response['result']['instance'][
                'post_creation']  # an array

            for line in post_creation:
                # import what the user put in the textbox for their wisp
                post_creation_ssh_key_combo += "%s\n" % h.unescape(line)

        except:
            # do nothing on post creation failure
            pass

        # update the instance with post creation
        self.post_creation = post_creation_ssh_key_combo
        self.update()

        # take the instance's flavor and verify install
        flavor = Flavors().get_by_id(self.flavor.id)
        osflavor = flavor_verify_install(flavor)

        if osflavor['response'] == "error":
            # we've failed to install flavor, so we disable it
            flavor.osid = ""
            flavor.active = 0
            flavor.update()

            # now we disable the other instances using the flavor
            instances = Instances()
            instances.toggle(flavor.id, 0)

            # disable this instance
            self.state = 0
            self.expires = self.created  # zeros out the payment
            self.update()

            # log it
            app.logger.error(
                "Disabling all instances using flavor=(%s) due to OpenStack failure."
                % flavor.name)

            # build the response and return
            response['response'] = "error"
            response['result'][
                'message'] = "Error creating flavor inside OpenStack."
            return response

        # deal with creating dynamic image or use predefined one
        if self.dynamic_image_url:
            image = Images().get_or_create_by_instance(self)
        else:
            image = Images().get_by_id(self.image.id)

        if not image:
            response['response'] = "error"
            response['result']['message'] = "Error creating dynamic image."
            return response
        else:
            self.image = image
            self.update()

        # take the image and verify install
        osimage = image_verify_install(self.image)

        # handle failures of either flavor or image
        if osimage['response'] == "error":
            response['response'] = "error"
            response['result']['message'] = "Error creating image."
            return response

        # tell openstack to start the instance
        cluster_response = instance_start(self)

        # process response
        if cluster_response['response'] == "success":
            server = cluster_response['result']['server']
            self.osid = server.id  # assign openstack instance id
            self.state = 3  # mark as starting
            self.update()
            response['result'] = cluster_response['result']
        else:
            response = cluster_response

        return response