コード例 #1
0
ファイル: destroy.py プロジェクト: johnsca/conjure-up
def main():
    opts = parse_options(sys.argv[1:])

    if os.geteuid() == 0:
        utils.info("")
        utils.info("This should _not_ be run as root or with sudo.")
        utils.info("")
        sys.exit(1)

    if not os.path.isdir(opts.cache_dir):
        os.makedirs(opts.cache_dir)

    # Application Config
    app.config = {'metadata': None}
    app.argv = opts
    app.log = setup_logging("conjure-down",
                            os.path.join(opts.cache_dir, 'conjure-down.log'),
                            opts.debug)

    app.env = os.environ.copy()

    if app.argv.controller and app.argv.model:
        app.headless = True
        app.ui = None
        app.env['CONJURE_UP_HEADLESS'] = "1"
        _start()

    app.ui = ConjureUI()
    EventLoop.build_loop(app.ui, STYLES, unhandled_input=unhandled_input)
    EventLoop.set_alarm_in(0.05, _start)
    EventLoop.run()
コード例 #2
0
 def update(self, *args, **kwargs):
     if self.pv is None:
         self.pv = PlacementView(
             display_controller=self,
             placement_controller=self.placement_controller,
             config=self.config,
             do_deploy_cb=self.done_cb)
         self.set_header(
             title="Bundle Editor"
         )
         self.set_body(self.pv)
     self.pv.update()
     EventLoop.set_alarm_in(1, self.update)
コード例 #3
0
ファイル: gui.py プロジェクト: graywen24/conjure-up
 def update(self, *args):
     for w in self.all_step_widgets:
         w.update()
     EventLoop.set_alarm_in(1, self.update)
コード例 #4
0
ファイル: gui.py プロジェクト: mnama/conjure-up
 def update(self, *args):
     for w in self.all_step_widgets:
         w.update()
     EventLoop.set_alarm_in(1, self.update)
コード例 #5
0
ファイル: placerview.py プロジェクト: johnsca/conjure-up
 def update(self, *args, **kwargs):
     self.pv.update()
     EventLoop.set_alarm_in(1, self.update)
コード例 #6
0
def main():
    if os.geteuid() == 0:
        utils.info("")
        utils.info("This should _not_ be run as root or with sudo.")
        utils.info("")
        sys.exit(1)

    opts = parse_options(sys.argv[1:])
    spell = os.path.basename(os.path.abspath(opts.spell))

    if not os.path.isdir(opts.cache_dir):
        os.makedirs(opts.cache_dir)

    # Application Config
    app.config = {'metadata': None}
    app.argv = opts
    app.log = setup_logging("conjure-up/{}".format(spell),
                            os.path.join(opts.cache_dir, 'conjure-up.log'),
                            opts.debug)

    # Grab current LXD and Juju versions
    app.log.debug("LXD version: {}, Juju version: {}".format(
        utils.lxd_version(), utils.juju_version()))

    # Setup proxy
    apply_proxy()

    app.session_id = os.getenv('CONJURE_TEST_SESSION_ID', str(uuid.uuid4()))

    global_config_filename = app.argv.global_config_file
    if not os.path.exists(global_config_filename):
        # fallback to source tree location
        global_config_filename = os.path.join(os.path.dirname(__file__),
                                              "../etc/conjure-up.conf")
        if not os.path.exists(global_config_filename):
            utils.error("Could not find {}.".format(global_config_filename))
            sys.exit(1)

    with open(global_config_filename) as fp:
        global_conf = yaml.safe_load(fp.read())
        app.global_config = global_conf

    spells_dir = app.argv.spells_dir

    app.config['spells-dir'] = spells_dir
    spells_index_path = os.path.join(app.config['spells-dir'],
                                     'spells-index.yaml')
    spells_registry_branch = os.getenv('CONJUREUP_REGISTRY_BRANCH', 'stable')

    if not app.argv.nosync:
        if not os.path.exists(spells_dir):
            utils.info("No spells found, syncing from registry, please wait.")
        try:
            download_or_sync_registry(app.global_config['registry']['repo'],
                                      spells_dir,
                                      branch=spells_registry_branch)
        except subprocess.CalledProcessError as e:
            if not os.path.exists(spells_dir):
                utils.error("Could not load from registry")
                sys.exit(1)

            app.log.debug('Could not sync spells from github: {}'.format(e))
    else:
        if not os.path.exists(spells_index_path):
            utils.error(
                "You opted to not sync from the spells registry, however, "
                "we could not find any suitable spells in: "
                "{}".format(spells_dir))
            sys.exit(1)

    with open(spells_index_path) as fp:
        app.spells_index = yaml.safe_load(fp.read())

    spell_name = spell
    app.endpoint_type = detect_endpoint(opts.spell)

    if app.endpoint_type == EndpointType.LOCAL_SEARCH:
        spells = utils.find_spells_matching(opts.spell)

        if len(spells) == 0:
            utils.error("Can't find a spell matching '{}'".format(opts.spell))
            sys.exit(1)

        # One result means it was a direct match and we can copy it
        # now. Changing the endpoint type then stops us from showing
        # the picker UI. More than one result means we need to show
        # the picker UI and will defer the copy to
        # SpellPickerController.finish(), so nothing to do here.
        if len(spells) == 1:
            app.log.debug("found spell {}".format(spells[0][1]))
            spell = spells[0][1]
            utils.set_chosen_spell(spell_name,
                                   os.path.join(opts.cache_dir, spell['key']))
            download_local(
                os.path.join(app.config['spells-dir'], spell['key']),
                app.config['spell-dir'])
            utils.set_spell_metadata()
            app.endpoint_type = EndpointType.LOCAL_DIR

    # download spell if necessary
    elif app.endpoint_type == EndpointType.LOCAL_DIR:
        if not os.path.isdir(opts.spell):
            utils.warning("Could not find spell {}".format(opts.spell))
            sys.exit(1)

        if not os.path.exists(os.path.join(opts.spell, "metadata.yaml")):
            utils.warning("'{}' does not appear to be a spell. "
                          "{}/metadata.yaml was not found.".format(
                              opts.spell, opts.spell))
            sys.exit(1)

        spell_name = os.path.basename(os.path.abspath(spell))
        utils.set_chosen_spell(spell_name, path.join(opts.cache_dir,
                                                     spell_name))
        download_local(opts.spell, app.config['spell-dir'])
        utils.set_spell_metadata()

    elif app.endpoint_type in [EndpointType.VCS, EndpointType.HTTP]:

        utils.set_chosen_spell(spell, path.join(opts.cache_dir, spell))
        remote = get_remote_url(opts.spell)

        if remote is None:
            utils.warning("Can't guess URL matching '{}'".format(opts.spell))
            sys.exit(1)

        download(remote, app.config['spell-dir'], True)
        utils.set_spell_metadata()

    app.env = os.environ.copy()
    app.env['CONJURE_UP_CACHEDIR'] = app.argv.cache_dir
    app.env['CONJURE_UP_SPELL'] = spell_name

    if app.argv.show_env:
        if not app.argv.cloud:
            utils.error("You must specify a cloud for headless mode.")
            sys.exit(1)
        if app.endpoint_type in [None, EndpointType.LOCAL_SEARCH]:
            utils.error("Please specify a spell for headless mode.")
            sys.exit(1)

        show_env()

    os_string = "{}-{}".format("-".join(platform.linux_distribution()),
                               platform.processor())
    track_event("OS", os_string, "")
    if app.argv.cloud:
        if app.endpoint_type in [None, EndpointType.LOCAL_SEARCH]:
            utils.error("Please specify a spell for headless mode.")
            sys.exit(1)

        app.headless = True
        app.ui = None
        app.env['CONJURE_UP_HEADLESS'] = "1"
        _start()

    else:
        if EventLoop.rows() < 43 or EventLoop.columns() < 132:
            print("")
            utils.warning(
                "conjure-up is best viewed with a terminal geometry of "
                "at least 132x43. Please increase the size of your terminal "
                "before starting conjure-up.")
            print("")
            acknowledge = input("Do you wish to continue? [Y/n] ")
            if 'N' in acknowledge or 'n' in acknowledge:
                sys.exit(1)
        app.ui = ConjureUI()
        EventLoop.build_loop(app.ui, STYLES, unhandled_input=unhandled_input)
        EventLoop.set_alarm_in(0.05, _start)
        EventLoop.run()
コード例 #7
0
ファイル: gui.py プロジェクト: benluteijn/conjure-up
def __refresh(*args):
    this.view.refresh_nodes()
    EventLoop.set_alarm_in(1, __refresh)
コード例 #8
0
 def update(self, *args):
     self.update_now()
     self.alarm = EventLoop.set_alarm_in(1, self.update)
コード例 #9
0
ファイル: charmstore.py プロジェクト: sincereuk/conjure-up
 def enqueue_search(self):
     if self.search_delay_alarm:
         EventLoop.remove_alarm(self.search_delay_alarm)
     self.search_delay_alarm = EventLoop.set_alarm_in(
         0.5, self.really_search)
コード例 #10
0
def main():
    opts = parse_options(sys.argv[1:])
    spell = os.path.basename(os.path.abspath(opts.spell))

    if not os.path.isdir(opts.cache_dir):
        os.makedirs(opts.cache_dir)

    if os.geteuid() == 0:
        utils.info("")
        utils.info("This should _not_ be run as root or with sudo.")
        utils.info("")
        sys.exit(1)

    # Application Config
    app.config = {'metadata': None}
    app.argv = opts
    app.log = setup_logging("conjure-up/{}".format(spell),
                            os.path.join(opts.cache_dir, 'conjure-up.log'),
                            opts.debug)

    # Setup proxy
    apply_proxy()

    app.session_id = os.getenv('CONJURE_TEST_SESSION_ID',
                               str(uuid.uuid4()))

    global_config_filename = app.argv.global_config_file
    if not os.path.exists(global_config_filename):
        # fallback to source tree location
        global_config_filename = os.path.join(os.path.dirname(__file__),
                                              "../etc/conjure-up.conf")
        if not os.path.exists(global_config_filename):
            utils.error("Could not find {}.".format(global_config_filename))
            sys.exit(1)

    with open(global_config_filename) as fp:
        global_conf = yaml.safe_load(fp.read())
        app.global_config = global_conf

    spells_dir = app.argv.spells_dir

    app.config['spells-dir'] = spells_dir
    spells_registry_branch = os.getenv('CONJUREUP_REGISTRY_BRANCH', 'master')
    if not os.path.exists(spells_dir):
        utils.info("No spells found, syncing from registry, please wait.")
        download_or_sync_registry(
            app.global_config['registry']['repo'],
            spells_dir, branch=spells_registry_branch)
    else:
        app.log.debug("Refreshing spell registry")
        download_or_sync_registry(
            app.global_config['registry']['repo'],
            spells_dir, update=True, branch=spells_registry_branch)

    spells_index_path = os.path.join(app.config['spells-dir'],
                                     'spells-index.yaml')
    with open(spells_index_path) as fp:
        app.spells_index = yaml.safe_load(fp.read())

    spell_name = spell
    app.endpoint_type = detect_endpoint(opts.spell)

    if app.endpoint_type == EndpointType.LOCAL_SEARCH:
        spells = utils.find_spells_matching(opts.spell)

        if len(spells) == 0:
            utils.error("Can't find a spell matching '{}'".format(opts.spell))
            sys.exit(1)

        # One result means it was a direct match and we can copy it
        # now. Changing the endpoint type then stops us from showing
        # the picker UI. More than one result means we need to show
        # the picker UI and will defer the copy to
        # SpellPickerController.finish(), so nothing to do here.
        if len(spells) == 1:
            app.log.debug("found spell {}".format(spells[0]))
            spell = spells[0]
            utils.set_chosen_spell(spell_name,
                                   os.path.join(opts.cache_dir,
                                                spell['key']))
            download_local(os.path.join(app.config['spells-dir'],
                                        spell['key']),
                           app.config['spell-dir'])
            utils.set_spell_metadata()
            app.endpoint_type = EndpointType.LOCAL_DIR

    # download spell if necessary
    elif app.endpoint_type == EndpointType.LOCAL_DIR:
        if not os.path.isdir(opts.spell):
            utils.warning("Could not find spell {}".format(opts.spell))
            sys.exit(1)

        if not os.path.exists(os.path.join(opts.spell,
                                           "metadata.yaml")):
            utils.warning("'{}' does not appear to be a spell. "
                          "{}/metadata.yaml was not found.".format(
                              opts.spell, opts.spell))
            sys.exit(1)

        spell_name = os.path.basename(os.path.abspath(spell))
        utils.set_chosen_spell(spell_name,
                               path.join(opts.cache_dir, spell_name))
        download_local(opts.spell, app.config['spell-dir'])
        utils.set_spell_metadata()

    elif app.endpoint_type in [EndpointType.VCS, EndpointType.HTTP]:

        utils.set_chosen_spell(spell, path.join(opts.cache_dir, spell))
        remote = get_remote_url(opts.spell)

        if remote is None:
            utils.warning("Can't guess URL matching '{}'".format(opts.spell))
            sys.exit(1)

        download(remote, app.config['spell-dir'], True)
        utils.set_spell_metadata()

    app.env = os.environ.copy()
    app.env['CONJURE_UP_CACHEDIR'] = app.argv.cache_dir
    app.env['CONJURE_UP_SPELL'] = spell_name

    if app.argv.show_env:
        if not app.argv.cloud:
            utils.error("You must specify a cloud for headless mode.")
            sys.exit(1)
        if app.endpoint_type in [None, EndpointType.LOCAL_SEARCH]:
            utils.error("Please specify a spell for headless mode.")
            sys.exit(1)

        show_env()

    if app.argv.cloud:
        if app.endpoint_type in [None, EndpointType.LOCAL_SEARCH]:
            utils.error("Please specify a spell for headless mode.")
            sys.exit(1)

        app.headless = True
        app.ui = None
        app.env['CONJURE_UP_HEADLESS'] = "1"
        _start()

    else:
        app.ui = ConjureUI()
        EventLoop.build_loop(app.ui, STYLES,
                             unhandled_input=unhandled_input)
        EventLoop.set_alarm_in(0.05, _start)
        EventLoop.run()
コード例 #11
0
 def enqueue_search(self):
     if self.search_delay_alarm:
         EventLoop.remove_alarm(self.search_delay_alarm)
     self.search_delay_alarm = EventLoop.set_alarm_in(0.5,
                                                      self.really_search)
コード例 #12
0
 def update(self, *args):
     self.update_now()
     self.alarm = EventLoop.set_alarm_in(1, self.update)
コード例 #13
0
ファイル: app.py プロジェクト: sincereuk/conjure-up
def main():
    opts = parse_options(sys.argv[1:])
    spell = os.path.basename(os.path.abspath(opts.spell))

    if not os.path.isdir(opts.cache_dir):
        os.makedirs(opts.cache_dir)

    if os.geteuid() == 0:
        utils.info("")
        utils.info("This should _not_ be run as root or with sudo.")
        utils.info("")
        sys.exit(1)

    # Application Config
    app.config = {'metadata': None}
    app.argv = opts
    app.log = setup_logging("conjure-up/{}".format(spell),
                            os.path.join(opts.cache_dir, 'conjure-up.log'),
                            opts.debug)

    # Setup proxy
    apply_proxy()

    app.session_id = os.getenv('CONJURE_TEST_SESSION_ID',
                               '{}/{}'.format(spell, str(uuid.uuid4())))

    global_config_filename = app.argv.global_config_file
    if not os.path.exists(global_config_filename):
        # fallback to source tree location
        global_config_filename = os.path.join(os.path.dirname(__file__),
                                              "../etc/conjure-up.conf")
        if not os.path.exists(global_config_filename):
            utils.error("Could not find {}.".format(global_config_filename))
            sys.exit(1)

    with open(global_config_filename) as fp:
        global_conf = yaml.safe_load(fp.read())
        app.global_config = global_conf

    spells_dir = app.argv.spells_dir
    if not os.path.exists(spells_dir):
        spells_dir = os.path.join(os.path.dirname(__file__), "../spells")

    app.config['spells-dir'] = spells_dir
    spells_index_path = os.path.join(app.config['spells-dir'],
                                     'spells-index.yaml')
    with open(spells_index_path) as fp:
        app.spells_index = yaml.safe_load(fp.read())

    spell_name = spell
    app.endpoint_type = detect_endpoint(opts.spell)

    if app.endpoint_type == EndpointType.LOCAL_SEARCH:
        spells = utils.find_spells_matching(opts.spell)

        if len(spells) == 0:
            utils.error("Can't find a spell matching '{}'".format(opts.spell))
            sys.exit(1)

        # One result means it was a direct match and we can copy it
        # now. Changing the endpoint type then stops us from showing
        # the picker UI. More than one result means we need to show
        # the picker UI and will defer the copy to
        # SpellPickerController.finish(), so nothing to do here.
        if len(spells) == 1:
            app.log.debug("found spell {}".format(spells[0]))
            spell = spells[0]
            utils.set_chosen_spell(spell_name,
                                   os.path.join(opts.cache_dir, spell['key']))
            download_local(
                os.path.join(app.config['spells-dir'], spell['key']),
                app.config['spell-dir'])
            utils.set_spell_metadata()
            app.endpoint_type = EndpointType.LOCAL_DIR

    # download spell if necessary
    elif app.endpoint_type == EndpointType.LOCAL_DIR:
        if not os.path.isdir(opts.spell):
            utils.warning("Could not find spell {}".format(opts.spell))
            sys.exit(1)

        spell_name = os.path.basename(os.path.abspath(spell))
        utils.set_chosen_spell(spell_name, path.join(opts.cache_dir,
                                                     spell_name))
        download_local(opts.spell, app.config['spell-dir'])
        utils.set_spell_metadata()

    elif app.endpoint_type in [EndpointType.VCS, EndpointType.HTTP]:

        utils.set_chosen_spell(spell, path.join(opts.cache_dir, spell))
        remote = get_remote_url(opts.spell)

        if remote is None:
            utils.warning("Can't guess URL matching '{}'".format(opts.spell))
            sys.exit(1)

        download(remote, app.config['spell-dir'], True)
        utils.set_spell_metadata()

    if app.argv.status_only:
        if not juju.model_available():
            utils.error("Attempted to access the status screen without "
                        "an available Juju model.\n"
                        "Please select a model using 'juju switch' or "
                        "create a new controller using 'juju bootstrap'.")
            sys.exit(1)

    app.env = os.environ.copy()
    app.env['CONJURE_UP_SPELL'] = spell_name

    if app.argv.cloud:
        if app.endpoint_type in [None, EndpointType.LOCAL_SEARCH]:
            utils.error("Please specify a spell for headless mode.")
            sys.exit(1)

        app.headless = True
        app.ui = None
        app.env['CONJURE_UP_HEADLESS'] = "1"
        _start()

    else:
        app.ui = ConjureUI()
        EventLoop.build_loop(app.ui, STYLES, unhandled_input=unhandled_input)
        EventLoop.set_alarm_in(0.05, _start)
        EventLoop.run()
コード例 #14
0
 def update(self, *args, **kwargs):
     self.pv.update()
     EventLoop.set_alarm_in(1, self.update)
コード例 #15
0
ファイル: app.py プロジェクト: tych0/conjure-up
def main():
    opts = parse_options(sys.argv[1:])
    spell = os.path.basename(os.path.abspath(opts.spell))

    if not os.path.isdir(opts.cache_dir):
        os.makedirs(opts.cache_dir)

    if os.geteuid() == 0:
        utils.info("")
        utils.info("This should _not_ be run as root or with sudo.")
        utils.info("")
        sys.exit(1)

    # Application Config
    app.config = {'metadata': None}
    app.argv = opts
    app.log = setup_logging("conjure-up/{}".format(spell),
                            os.path.join(opts.cache_dir, 'conjure-up.log'),
                            opts.debug)

    # Setup proxy
    apply_proxy()

    app.session_id = os.getenv('CONJURE_TEST_SESSION_ID',
                               '{}/{}'.format(
                                   spell,
                                   str(uuid.uuid4())))

    global_config_filename = app.argv.global_config_file
    if not os.path.exists(global_config_filename):
        # fallback to source tree location
        global_config_filename = os.path.join(os.path.dirname(__file__),
                                              "../etc/conjure-up.conf")
        if not os.path.exists(global_config_filename):
            utils.error("Could not find {}.".format(global_config_filename))
            sys.exit(1)

    with open(global_config_filename) as fp:
        global_conf = yaml.safe_load(fp.read())
        app.global_config = global_conf

    spells_dir = app.argv.spells_dir
    if not os.path.exists(spells_dir):
        spells_dir = os.path.join(os.path.dirname(__file__),
                                  "../spells")

    app.config['spells-dir'] = spells_dir
    spells_index_path = os.path.join(app.config['spells-dir'],
                                     'spells-index.yaml')
    with open(spells_index_path) as fp:
        app.spells_index = yaml.safe_load(fp.read())

    spell_name = spell
    app.endpoint_type = detect_endpoint(opts.spell)

    if app.endpoint_type == EndpointType.LOCAL_SEARCH:
        spells = utils.find_spells_matching(opts.spell)

        if len(spells) == 0:
            utils.error("Can't find a spell matching '{}'".format(opts.spell))
            sys.exit(1)

        # One result means it was a direct match and we can copy it
        # now. Changing the endpoint type then stops us from showing
        # the picker UI. More than one result means we need to show
        # the picker UI and will defer the copy to
        # SpellPickerController.finish(), so nothing to do here.
        if len(spells) == 1:
            print("found spell {}".format(spells[0]))
            utils.set_chosen_spell(spell_name,
                                   os.path.join(opts.cache_dir,
                                                spell_name))
            download_local(os.path.join(app.config['spells-dir'],
                                        spell_name),
                           app.config['spell-dir'])
            utils.set_spell_metadata()
            app.endpoint_type = EndpointType.LOCAL_DIR

    # download spell if necessary
    elif app.endpoint_type == EndpointType.LOCAL_DIR:
        if not os.path.isdir(opts.spell):
            utils.warning("Could not find spell {}".format(opts.spell))
            sys.exit(1)

        spell_name = os.path.basename(os.path.abspath(spell))
        utils.set_chosen_spell(spell_name,
                               path.join(opts.cache_dir, spell_name))
        download_local(opts.spell, app.config['spell-dir'])
        utils.set_spell_metadata()

    elif app.endpoint_type in [EndpointType.VCS, EndpointType.HTTP]:

        utils.set_chosen_spell(spell, path.join(opts.cache_dir, spell))
        remote = get_remote_url(opts.spell)

        if remote is None:
            utils.warning("Can't guess URL matching '{}'".format(opts.spell))
            sys.exit(1)

        download(remote, app.config['spell-dir'], True)
        utils.set_spell_metadata()

    if app.argv.status_only:
        if not juju.model_available():
            utils.error("Attempted to access the status screen without "
                        "an available Juju model.\n"
                        "Please select a model using 'juju switch' or "
                        "create a new controller using 'juju bootstrap'.")
            sys.exit(1)

    app.env = os.environ.copy()
    app.env['CONJURE_UP_SPELL'] = spell_name

    if app.argv.cloud:
        if app.endpoint_type in [None, EndpointType.LOCAL_SEARCH]:
            utils.error("Please specify a spell for headless mode.")
            sys.exit(1)

        app.headless = True
        app.ui = None
        app.env['CONJURE_UP_HEADLESS'] = "1"
        _start()

    else:
        app.ui = ConjureUI()
        EventLoop.build_loop(app.ui, STYLES,
                             unhandled_input=unhandled_input)
        EventLoop.set_alarm_in(0.05, _start)
        EventLoop.run()
コード例 #16
0
ファイル: gui.py プロジェクト: mnama/conjure-up
 def __refresh(self, *args):
     self.view.refresh_nodes()
     EventLoop.set_alarm_in(1, self.__refresh)
コード例 #17
0
 def __refresh(self, *args):
     self.view.redraw_kitt()
     self.alarm_handle = EventLoop.set_alarm_in(
         1,
         self.__refresh)
コード例 #18
0
ファイル: app.py プロジェクト: pombredanne/conjure
 def start(self):
     EventLoop.build_loop(self.common['ui'], STYLES,
                          unhandled_input=self.unhandled_input)
     EventLoop.set_alarm_in(0.05, self._start)
     EventLoop.run()
コード例 #19
0
ファイル: app.py プロジェクト: benluteijn/conjure-up
def main():
    opts = parse_options(sys.argv[1:])
    if "/" in opts.spell:
        spell = opts.spell.split("/")[-1]
    else:
        spell = opts.spell

    app.fetcher = fetcher(opts.spell)

    if os.geteuid() == 0:
        utils.info("")
        utils.info("This should _not_ be run as root or with sudo.")
        utils.info("")
        sys.exit(1)

    # Application Config
    app.argv = opts
    app.log = setup_logging("conjure-up/{}".format(spell),
                            opts.debug)

    # Setup proxy
    apply_proxy()

    app.session_id = os.getenv('CONJURE_TEST_SESSION_ID',
                               '{}/{}'.format(
                                   spell,
                                   str(uuid.uuid4())))

    has_valid_juju()

    global_conf_file = '/etc/conjure-up.conf'
    if not os.path.exists(global_conf_file):
        global_conf_file = os.path.join(
            os.path.dirname(__file__), '..', 'etc', 'conjure-up.conf')
    with open(global_conf_file) as fp:
        global_conf = yaml.safe_load(fp.read())

    # Bind UI
    app.ui = ConjureUI()

    if spell in global_conf['curated_spells']:
        install_curated_spell(spell)

    spell_dir = os.environ.get('XDG_CACHE_HOME', os.path.join(
        os.path.expanduser('~'),
        '.cache/conjure-up'))

    if app.fetcher == "charmstore-search":
        app.bundles = load_charmstore_results(spell, global_conf['blessed'])
        app.config = {'metadata': None,
                      'spell-dir': spell_dir,
                      'spell': spell}

        # Set a general description of spell
        definition = None
        if path.isfile('/usr/share/conjure-up/keyword-definitions.yaml'):
            with open('/usr/share/conjure-up/keyword-definitions.yaml') as fp:
                definitions = yaml.safe_load(fp.read())
                definition = definitions.get(spell, None)
        if definition is None:
            try:
                definition = next(
                    bundle['Meta']['bundle-metadata']['Description']
                    for bundle in app.bundles if 'Description'
                    in bundle['Meta']['bundle-metadata'])
            except StopIteration:
                app.log.error("Could not find a suitable description "
                              "for spell: {}".format(spell))

        if definition is not None:
            app.config['description'] = definition
        else:
            utils.warning(
                "Failed to find a description for spell: {}, "
                "and is a bug that should be filed.".format(spell))

    else:
        # Check cache dir for spells
        spell_dir = path.join(spell_dir, spell)

        metadata_path = path.join(spell_dir,
                                  'conjure/metadata.json')

        remote = get_remote_url(opts.spell)
        purge_top_level = True
        if remote is not None:
            if app.fetcher == "charmstore-search" or \
               app.fetcher == "charmstore-direct":
                purge_top_level = False
            download(remote, spell_dir, purge_top_level)
        else:
            utils.warning("Could not find spell: {}".format(spell))
            sys.exit(1)

        with open(metadata_path) as fp:
            metadata = json.load(fp)

        app.config = {'metadata': metadata,
                      'spell-dir': spell_dir,
                      'spell': spell}

        # Need to provide app.bundles dictionary even for single
        # spells in the GUI
        app.bundles = [
            {
                'Meta': {
                    'extra-info/conjure': metadata
                }
            }
        ]

    if hasattr(app.argv, 'cloud'):
        if app.fetcher != "charmstore-search":
            app.headless = True
            app.ui = None
        else:
            utils.error("Unable run a keyword search in headless mode, "
                        "please provide a single bundle path.")
            sys.exit(1)

    app.env = os.environ.copy()
    app.env['CONJURE_UP_SPELL'] = spell

    if app.argv.status_only:
        if not juju.available():
            utils.error("Attempted to access the status screen of "
                        "a non-bootstrapped Juju environment. "
                        "Please bootstrap an environment first.")
            sys.exit(1)

    if app.headless:
        app.env['CONJURE_UP_HEADLESS'] = "1"
        _start()
    else:
        EventLoop.build_loop(app.ui, STYLES,
                             unhandled_input=unhandled_input)
        EventLoop.set_alarm_in(0.05, _start)
        EventLoop.run()