Beispiel #1
0
async def shutdown_watcher():
    app.log.info('Watching for shutdown')
    try:
        await Shutdown.wait()
    except asyncio.CancelledError:
        pass

    app.log.info('Shutting down')
    if app.headless:
        utils.warning('Shutting down')
    else:
        app.ui.show_shutdown_message()

    try:
        if app.juju.authenticated:
            app.log.info('Disconnecting model')
            await app.juju.client.disconnect()
            app.log.info('Disconnected')

        if not app.headless:
            EventLoop.remove_alarms()

        for task in asyncio.Task.all_tasks(app.loop):
            # cancel all other tasks
            if getattr(task, '_coro', None) is not shutdown_watcher:
                task.cancel()
        app.loop.stop()
    except Exception:
        app.log.exception('Error in cleanup code')
        raise
Beispiel #2
0
def main():
    with open(maas_data) as fp:
        maas_machines = json.load(fp)
    machine_view = maas_machines
    ui = MachineUI(machine_view)
    EventLoop.build_loop(ui, STYLES, unhandled_input=unhandled_input)
    EventLoop.run()
Beispiel #3
0
def main():
    opts = parse_options(sys.argv[1:])

    config = Config('bundle-placer', opts.__dict__)
    config.save()

    setup_logger(cfg_path=config.cfg_path)
    log = logging.getLogger('bundleplacer')
    log.debug(opts.__dict__)

    log.info("Editing file: {}".format(opts.bundle_filename))

    if opts.maas_ip and opts.maas_cred:
        creds = dict(api_host=opts.maas_ip,
                     api_key=opts.maas_cred)
        maas, maas_state = connect_to_maas(creds)
    else:
        maas_state = FakeMaasState()

    placement_controller = PlacementController(config=config,
                                               maas_state=maas_state)

    mainview = PlacerView(placement_controller, config)
    ui = PlacerUI(mainview)

    def unhandled_input(key):
        if key in ['q', 'Q']:
            raise urwid.ExitMainLoop()
    EventLoop.build_loop(ui, STYLES, unhandled_input=unhandled_input)
    mainview.loop = EventLoop.loop
    mainview.update()
    EventLoop.run()
Beispiel #4
0
 def _handle_exception(self, tag, exc):
     if app.showing_error:
         return
     app.showing_error = True
     track_exception(exc.args[0])
     app.ui.show_exception_message(exc)
     EventLoop.remove_alarms()
Beispiel #5
0
    def finish(self, step_model, step_widget, done=False):
        """ handles processing step with input data

        Arguments:
        step_model: step_model returned from widget
        done: if True continues on to the summary view
        """
        if done:
            EventLoop.remove_alarms()
            return controllers.use('summary').render(self.results)

        # Set next button focus here now that the step is complete.
        self.view.steps.popleft()
        if len(self.view.steps) > 0:
            next_step = self.view.steps[0]
            next_step.generate_additional_input()
            self.view.step_pile.focus_position = self.view.step_pile.focus_position + 1  # noqa
        else:
            app.log.debug("End of step list setting the view "
                          "summary button in focus.")
            index = self.view.current_summary_button_index
            app.log.debug("Next focused button: {}".format(index))
            self.view.step_pile.focus_position = index

        future = async .submit(
            partial(common.do_step,
                    step_model,
                    step_widget,
                    app.ui.set_footer,
                    gui=True), partial(self.__handle_exception, 'E002'))
        future.add_done_callback(self.get_result)
Beispiel #6
0
    def finish(self, step_model, step_widget, done=False):
        """ handles processing step with input data

        Arguments:
        step_model: step_model returned from widget
        done: if True continues on to the summary view
        """
        if done:
            EventLoop.remove_alarms()
            return controllers.use('summary').render(self.results)

        # Set next button focus here now that the step is complete.
        self.view.steps.popleft()
        if len(self.view.steps) > 0:
            next_step = self.view.steps[0]
            next_step.generate_additional_input()
            self.view.step_pile.focus_position = self.view.step_pile.focus_position + 1  # noqa
        else:
            app.log.debug(
                "End of step list setting the view "
                "summary button in focus.")
            index = self.view.current_summary_button_index
            app.log.debug("Next focused button: {}".format(index))
            self.view.step_pile.focus_position = index

        future = async.submit(partial(common.do_step,
                                      step_model,
                                      step_widget,
                                      app.ui.set_footer,
                                      gui=True),
                              partial(self.__handle_exception, 'E002'))
        future.add_done_callback(self.get_result)
Beispiel #7
0
async def shutdown_watcher():
    app.log.info('Watching for shutdown')
    try:
        try:
            await Shutdown.wait()
        except asyncio.CancelledError:
            pass

        app.log.info('Shutting down')
        if app.headless:
            utils.warning('Shutting down')

        # Store application configuration state
        await app.save()

        if app.juju.authenticated:
            app.log.info('Disconnecting model')
            await app.juju.client.disconnect()
            app.log.info('Disconnected')

        if not app.headless:
            EventLoop.remove_alarms()

        for task in asyncio.Task.all_tasks(app.loop):
            # cancel all other tasks
            coro = getattr(task, '_coro', None)
            cr_code = getattr(coro, 'cr_code', None)
            if cr_code is not shutdown_watcher.__code__:
                app.log.debug('Cancelling pending task: {}'.format(task))
                task.cancel()
        await asyncio.sleep(0.1)  # give tasks a chance to see the cancel
    except Exception as e:
        app.log.exception('Error in cleanup code: {}'.format(e))
    app.loop.stop()
Beispiel #8
0
    def show_exception_message(self, ex):
        errmsg = str(ex)
        errmsg += ("\n\n"
                   "Review log messages at ~/.cache/conjure-up/conjure-up.log "
                   "If appropriate, please submit a bug here: "
                   "https://github.com/conjure-up/conjure-up/issues/new")

        async .shutdown()
        EventLoop.remove_alarms()
        self.frame.body = ErrorView(errmsg)
        app.log.debug("Showing dialog for exception: {}".format(ex))
Beispiel #9
0
    def show(self):
        def _stop(key):
            if key in ['q', 'Q']:
                raise ExitMainLoop()

        app.notrack = True
        app.noreport = True
        app.ui = ConjureUI()
        EventLoop.build_loop(app.ui, STYLES, unhandled_input=_stop)
        super().show()
        EventLoop.run()
 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)
Beispiel #11
0
    def show_exception_message(self, ex):
        _cache_dir = Path(app.argv.cache_dir) / 'conjure-up.log'
        errmsg = str(ex)
        errmsg += ("\n\n Review log messages at {} "
                   "If appropriate, please submit a bug here: "
                   "https://github.com/conjure-up/conjure-up/issues/new".
                   format(_cache_dir))

        async .shutdown()
        EventLoop.remove_alarms()
        self.frame.body = ErrorView(errmsg)
        # ensure error is shown, even if exception was inside urwid
        EventLoop.redraw_screen()
        app.log.debug("Showing dialog for exception: {}".format(ex))
Beispiel #12
0
    def __handle_bootstrap_done(self, future):
        app.log.debug("handle bootstrap")
        result = future.result()
        if result.returncode < 0:
            # bootstrap killed via user signal, we're quitting
            return
        if result.returncode > 0:
            err = result.stderr.read().decode()
            app.log.error(err)
            return self.__handle_exception(Exception("error "))

        utils.pollinate(app.session_id, 'J004')
        EventLoop.remove_alarms()
        app.ui.set_footer('Bootstrap complete...')
        self.__post_bootstrap_exec()
Beispiel #13
0
    def __handle_bootstrap_done(self, future):
        app.log.debug("handle bootstrap")
        result = future.result()
        if result.returncode < 0:
            # bootstrap killed via user signal, we're quitting
            return
        if result.returncode > 0:
            err = result.stderr.read().decode()
            app.log.error(err)
            return self.__handle_exception(Exception("error "))

        utils.pollinate(app.session_id, 'J004')
        EventLoop.remove_alarms()
        app.ui.set_footer('Bootstrap complete...')
        juju.switch_controller(app.current_controller)
        self.__post_bootstrap_exec()
Beispiel #14
0
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(app,
                            os.path.join(opts.cache_dir, 'conjure-down.log'),
                            opts.debug)

    # Make sure juju paths are setup
    juju.set_bin_path()

    app.env = os.environ.copy()
    app.loop = asyncio.get_event_loop()
    app.loop.add_signal_handler(signal.SIGINT, events.Shutdown.set)
    app.loop.create_task(events.shutdown_watcher())
    app.loop.create_task(_start())

    try:
        if app.argv.controller and app.argv.model:
            app.headless = True
            app.ui = None
            app.env['CONJURE_UP_HEADLESS'] = "1"
            app.loop.run_forever()
        else:
            app.ui = ConjureUI()
            EventLoop.build_loop(app.ui,
                                 STYLES,
                                 unhandled_input=events.unhandled_input)
            EventLoop.run()
    finally:
        # explicitly close aysncio event loop to avoid hitting the
        # following issue due to signal handlers added by
        # asyncio.create_subprocess_exec being cleaned up during final
        # garbage collection: https://github.com/python/asyncio/issues/396
        app.loop.close()
    def do_commit(self, sender):
        """Commit changes to shadow assignments, constraints, and pins"""
        app.metadata_controller.bundle.machines = self._machines

        self.controller.clear_assignments(self.application)
        for juju_machine_id, al in self.shadow_assignments.items():
            for application, atype in al:
                assert application == self.application
                self.controller.add_assignment(self.application,
                                               juju_machine_id, atype)

        for j_m_id, m in self.shadow_pins.items():
            self.controller.set_machine_pin(j_m_id, m)

        self.controller.handle_sub_view_done()
        if self.alarm:
            EventLoop.remove_alarm(self.alarm)
Beispiel #16
0
 def show_readme(self):
     _, rows = EventLoop.screen_size()
     cur_spell = self.selected_spell
     spellname = cur_spell['name']
     spelldir = cur_spell['spell-dir']
     brmv = BundleReadmeView(self.app.metadata_controller, spellname,
                             spelldir, self.hide_readme, int(rows * .75))
     self.app.ui.set_header("Spell Readme")
     self.app.ui.set_body(brmv)
    def do_commit(self, sender):
        """Commit changes to shadow assignments, constraints, and pins"""
        app.metadata_controller.bundle.machines = self._machines

        self.controller.clear_assignments(self.application)
        for juju_machine_id, al in self.shadow_assignments.items():
            for application, atype in al:
                assert application == self.application
                self.controller.add_assignment(self.application,
                                               juju_machine_id, atype)

        self.controller.clear_machine_pins()
        for j_m_id, m in self.shadow_pins.items():
            self.controller.set_machine_pin(j_m_id, m)

        self.controller.handle_sub_view_done()
        if self.alarm:
            EventLoop.remove_alarm(self.alarm)
Beispiel #18
0
    def finish(self, needs_lxd_setup=False, lxdnetwork=None, back=False):
        """ Processes the new LXD setup and loads the controller to
        finish bootstrapping the model.

        Arguments:
        back: if true loads previous controller
        needs_lxd_setup: if true prompt user to run lxd init
        """
        if back:
            return controllers.use('clouds').render()

        if needs_lxd_setup:
            EventLoop.remove_alarms()
            EventLoop.exit(1)

        if lxdnetwork is None:
            return app.ui.show_exception_message(
                Exception("Unable to configure LXD network bridge."))

        formatted_network = self.__format_input(lxdnetwork)
        app.log.debug("LXD Config {}".format(formatted_network))

        out = self.__format_conf(formatted_network)

        with NamedTemporaryFile(mode="w", encoding="utf-8",
                                delete=False) as tempf:
            app.log.debug("Saving LXD config to {}".format(tempf.name))
            utils.spew(tempf.name, out)
            sh = utils.run('sudo mv {} /etc/default/lxd-bridge'.format(
                tempf.name), shell=True)
            if sh.returncode > 0:
                return app.ui.show_exception_message(
                    Exception("Problem saving config: {}".format(
                        sh.stderr.decode('utf8'))))

        app.log.debug("Restarting lxd-bridge")
        utils.run("sudo systemctl restart lxd-bridge.service", shell=True)

        utils.pollinate(app.session_id, 'L002')
        controllers.use('newcloud').render(
            cloud='localhost', bootstrap=True)
Beispiel #19
0
    def finish(self, needs_lxd_setup=False, lxdnetwork=None, back=False):
        """ Processes the new LXD setup and loads the controller to
        finish bootstrapping the model.

        Arguments:
        back: if true loads previous controller
        needs_lxd_setup: if true prompt user to run lxd init
        """
        if back:
            return controllers.use('clouds').render()

        if needs_lxd_setup:
            EventLoop.remove_alarms()
            EventLoop.exit(1)

        if lxdnetwork is None:
            return app.ui.show_exception_message(
                Exception("Unable to configure LXD network bridge."))

        formatted_network = self.__format_input(lxdnetwork)
        app.log.debug("LXD Config {}".format(formatted_network))

        out = self.__format_conf(formatted_network)

        with NamedTemporaryFile(mode="w", encoding="utf-8",
                                delete=False) as tempf:
            app.log.debug("Saving LXD config to {}".format(tempf.name))
            utils.spew(tempf.name, out)
            sh = run('sudo mv {} /etc/default/lxd-bridge'.format(
                tempf.name), shell=True)
            if sh.returncode > 0:
                return app.ui.show_exception_message(
                    Exception("Problem saving config: {}".format(
                        sh.stderr.decode('utf8'))))

        app.log.debug("Restarting lxd-bridge")
        run("sudo systemctl restart lxd-bridge.service", shell=True)

        utils.pollinate(app.session_id, 'L002')
        controllers.use('newcloud').render(
            cloud='localhost', bootstrap=True)
Beispiel #20
0
    def __handle_bootstrap_done(self, future):
        app.log.debug("handle bootstrap")
        result = future.result()
        if result.returncode < 0:
            # bootstrap killed via user signal, we're quitting
            return
        if result.returncode > 0:
            pathbase = os.path.join(app.config['spell-dir'],
                                    '{}-bootstrap').format(
                                        app.current_controller)

            with open(pathbase + ".err") as errf:
                err = "\n".join(errf.readlines())
                app.log.error(err)
            e = Exception("Bootstrap error: {}".format(err))
            return self.__handle_exception(e)

        track_event("Juju Bootstrap", "Done", "")
        EventLoop.remove_alarms()
        app.ui.set_footer('Bootstrap complete...')
        self.__post_bootstrap_exec()
Beispiel #21
0
    def finish(self, step_model, step_widget, done=False):
        """ handles processing step with input data

        Arguments:
        step_model: step_model returned from widget
        done: if True continues on to the summary view
        """
        if done:
            EventLoop.remove_alarms()
            return controllers.use('summary').render(self.results)

        if utils.is_linux() and step_model.needs_sudo:
            password = None
            if step_widget.sudo_input:
                password = step_widget.sudo_input.value
            if not step_model.can_sudo(password):
                step_widget.set_error(
                    'Sudo failed.  Please check your password and ensure that '
                    'your sudo timeout is not set to zero.')
                step_widget.show_button()
                return

        step_widget.clear_error()

        # Set next button focus here now that the step is complete.
        self.view.steps.popleft()

        if len(self.view.steps) > 0:
            next_step = self.view.steps[0]
            next_step.generate_additional_input()
            self.view.step_pile.focus_position = self.view.step_pile.focus_position + 1  # noqa

        future = async.submit(partial(common.do_step,
                                      step_model,
                                      step_widget,
                                      app.ui.set_footer,
                                      gui=True),
                              partial(self.__handle_exception, 'E002'))
        if future:
            future.add_done_callback(self.get_result)
Beispiel #22
0
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()
Beispiel #23
0
 def keypress(self, size, key):
     rv = super().keypress(size, key)
     if key in ['tab', 'shift tab']:
         self._swap_focus()
     self.handle_focus_changed()
     if key in ['r'] and self.selected_spell_w is not None:
         _, rows = EventLoop.screen_size()
         cur_spell = self.selected_spell_w.spell
         spellname = cur_spell['name']
         spelldir = cur_spell['spell-dir']
         brmv = BundleReadmeView(self.app.metadata_controller, spellname,
                                 spelldir, self.handle_readme_done,
                                 int(rows * .75))
         self.app.ui.set_header("Spell Readme")
         self.app.ui.set_body(brmv)
     return rv
Beispiel #24
0
 def keypress(self, size, key):
     rv = super().keypress(size, key)
     if key in ["tab", "shift tab"]:
         self._swap_focus()
     self.handle_focus_changed()
     if key in ["r"] and self.selected_spell_w is not None:
         _, rows = EventLoop.screen_size()
         cur_spell = self.selected_spell_w.spell
         spellname = cur_spell["name"]
         spelldir = cur_spell["spell-dir"]
         brmv = BundleReadmeView(
             self.app.metadata_controller, spellname, spelldir, self.handle_readme_done, int(rows * 0.75)
         )
         self.app.ui.set_header("Spell Readme")
         self.app.ui.set_body(brmv)
     return rv
Beispiel #25
0
 def finish(self):
     EventLoop.remove_alarms()
     EventLoop.exit(0)
Beispiel #26
0
 def cancel(self, btn):
     EventLoop.exit(0)
 def do_cancel(self, sender):
     self.controller.handle_sub_view_done()
     if self.alarm:
         EventLoop.remove_alarm(self.alarm)
Beispiel #28
0
 def __refresh(self, *args):
     self.view.refresh_nodes()
     EventLoop.set_alarm_in(1, self.__refresh)
Beispiel #29
0
 def __handle_destroy_done(self, future):
     if not future.exception():
         app.ui.set_footer("")
         return controllers.use('destroy').render()
     EventLoop.remove_alarms()
def main():
    with open(juju_data) as fp:
        juju_state = json.load(fp)
    ui = ServiceUI(juju_state)
    EventLoop.build_loop(ui, STYLES, unhandled_input=unhandled_input)
    EventLoop.run()
Beispiel #31
0
def finish():
    EventLoop.remove_alarms()
Beispiel #32
0
 def cancel(self, button):
     EventLoop.exit(0)
Beispiel #33
0
 def __refresh(self, *args):
     self.view.redraw_kitt()
     self.alarm_handle = EventLoop.set_alarm_in(
         1,
         self.__refresh)
def main():
    if os.getenv("BUNDLE_EDITOR_TESTING"):
        test_args = True
    else:
        test_args = False

    opts = parse_options(sys.argv[1:], test_args)

    config = Config('bundle-placer', opts.__dict__)
    config.save()

    setup_logger(cfg_path=config.cfg_path)
    log = logging.getLogger('bundleplacer')
    log.debug(opts.__dict__)

    log.info("Editing file: {}".format(opts.bundle_filename))

    if opts.maas_ip and opts.maas_cred:
        creds = dict(api_host=opts.maas_ip,
                     api_key=opts.maas_cred)
        maas, maas_state = connect_to_maas(creds)
    elif 'fake_maas' in opts and opts.fake_maas:
        maas = None
        maas_state = FakeMaasState()
    else:
        maas = None
        maas_state = None

    try:
        placement_controller = PlacementController(config=config,
                                                   maas_state=maas_state)
    except Exception as e:
        print("Error: " + e.args[0])
        return

    def cb():
        if maas:
            maas.tag_name(maas.nodes)

        bw = BundleWriter(placement_controller)
        if opts.out_filename:
            outfn = opts.out_filename
        else:
            outfn = opts.bundle_filename
            if os.path.exists(outfn):
                shutil.copy2(outfn, outfn + '~')
        bw.write_bundle(outfn)
        async.shutdown()
        raise urwid.ExitMainLoop()

    has_maas = (maas_state is not None)
    mainview = PlacerView(placement_controller, config, cb, has_maas=has_maas)
    ui = PlacerUI(mainview)

    def unhandled_input(key):
        if key in ['q', 'Q']:
            async.shutdown()
            raise urwid.ExitMainLoop()
    EventLoop.build_loop(ui, STYLES, unhandled_input=unhandled_input)
    mainview.loop = EventLoop.loop
    mainview.update()
    EventLoop.run()
Beispiel #35
0
 def unhandled_input(self, key):
     if key in ['q', 'Q']:
         EventLoop.exit(0)
Beispiel #36
0
def main():
    opts = parse_options(sys.argv[1:])
    opt_defaults = parse_options([])

    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}

    # Load conjurefile, merge any overridding options from argv
    if not opts.conf_file:
        opts.conf_file = []
    if pathlib.Path('~/.config/conjure-up.conf').expanduser().exists():
        opts.conf_file.insert(
            0,
            pathlib.Path('~/.config/conjure-up.conf').expanduser())
    if (pathlib.Path('.') / 'Conjurefile').exists():
        opts.conf_file.insert(0, pathlib.Path('.') / 'Conjurefile')
    for conf in opts.conf_file:
        if not conf.exists():
            print("Unable to locate config {} for processing.".format(
                str(conf)))
            sys.exit(1)

    app.conjurefile = Conjurefile.load(opts.conf_file)
    app.conjurefile.merge_argv(opts, opt_defaults)

    app.log = setup_logging(app,
                            os.path.join(opts.cache_dir, 'conjure-down.log'),
                            opts.debug)

    app.no_track = app.conjurefile['no-track']
    app.no_report = app.conjurefile['no-report']
    app.env = os.environ.copy()

    # Make sure juju paths are setup
    juju.set_bin_path()

    app.loop = asyncio.get_event_loop()
    app.loop.add_signal_handler(signal.SIGINT, events.Shutdown.set)
    app.loop.create_task(events.shutdown_watcher())
    app.loop.create_task(_start())

    try:
        if app.conjurefile['controller'] and app.conjurefile['model']:
            app.headless = True
            app.ui = None
            app.env['CONJURE_UP_HEADLESS'] = "1"
            app.loop.run_forever()
        else:
            app.ui = ConjureUI()
            EventLoop.build_loop(app.ui,
                                 STYLES,
                                 unhandled_input=events.unhandled_input)
            EventLoop.run()
    finally:
        # explicitly close aysncio event loop to avoid hitting the
        # following issue due to signal handlers added by
        # asyncio.create_subprocess_exec being cleaned up during final
        # garbage collection: https://github.com/python/asyncio/issues/396
        app.loop.close()
Beispiel #37
0
 def finish(self, *args):
     if self.alarm_handle:
         EventLoop.remove_alarm(self.alarm_handle)
     return controllers.use('deploystatus').render()
Beispiel #38
0
def main():
    if os.geteuid() == 0:
        print("")
        print("  !! This should _not_ be run as root or with sudo. !!")
        print("")
        sys.exit(1)

    # Verify we can access ~/.local/share/juju if it exists
    juju_dir = pathlib.Path('~/.local/share/juju').expanduser()
    if juju_dir.exists():
        try:
            for f in juju_dir.iterdir():
                if f.is_file():
                    f.read_text()
        except PermissionError:
            print("")
            print("  !! Unable to read from ~/.local/share/juju, please "
                  "double check your permissions on that directory "
                  "and its files. !!")
            print("")
            sys.exit(1)

    utils.set_terminal_title("conjure-up")
    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
    os.environ['UNIT_STATE_DB'] = os.path.join(opts.cache_dir, '.state.db')
    app.state = unitdata.kv()

    app.env = os.environ.copy()
    app.config = {'metadata': None}
    app.argv = opts
    app.log = setup_logging(app, os.path.join(opts.cache_dir,
                                              'conjure-up.log'), opts.debug)

    if app.argv.conf_file.expanduser().exists():
        conf = configparser.ConfigParser()
        conf.read_string(app.argv.conf_file.expanduser().read_text())
        app.notrack = conf.getboolean('REPORTING', 'notrack', fallback=False)
        app.noreport = conf.getboolean('REPORTING', 'noreport', fallback=False)
    if app.argv.notrack:
        app.notrack = True
    if app.argv.noreport:
        app.noreport = True

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

    # Setup proxy
    apply_proxy()

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

    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.argv.registry,
                                      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()
            StepModel.load_spell_steps()
            AddonModel.load_spell_addons()
            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()
        StepModel.load_spell_steps()
        AddonModel.load_spell_addons()

    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()
        StepModel.load_spell_steps()
        AddonModel.load_spell_addons()

    app.env['CONJURE_UP_CACHEDIR'] = app.argv.cache_dir

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

        show_env()

    app.sentry = raven.Client(
        dsn=SENTRY_DSN,
        release=VERSION,
        transport=RequestsHTTPTransport,
        processors=('conjureup.utils.SanitizeDataProcessor', ))

    track_screen("Application Start")
    track_event("OS", platform.platform(), "")

    app.loop = asyncio.get_event_loop()
    app.loop.add_signal_handler(signal.SIGINT, events.Shutdown.set)
    try:
        if app.argv.cloud:
            cloud = None
            region = None
            if '/' in app.argv.cloud:
                parse_cli_cloud = app.argv.cloud.split('/')
                cloud, region = parse_cli_cloud
                app.log.debug("Region found {} for cloud {}".format(
                    cloud, region))
            else:
                cloud = app.argv.cloud

            cloud_types = juju.get_cloud_types_by_name()
            if cloud not in cloud_types:
                utils.error('Unknown cloud: {}'.format(cloud))
                sys.exit(1)

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

            app.provider = load_schema(cloud_types[cloud])

            try:
                app.provider.load(cloud)
            except SchemaErrorUnknownCloud as e:
                utils.error(e)
                sys.exit(1)

            if region:
                app.provider.region = region

            app.headless = True
            app.ui = None
            app.env['CONJURE_UP_HEADLESS'] = "1"
            app.loop.create_task(events.shutdown_watcher())
            app.loop.create_task(_start())
            app.loop.run_forever()

        else:
            app.ui = ConjureUI()

            EventLoop.build_loop(app.ui,
                                 STYLES,
                                 unhandled_input=events.unhandled_input)
            app.loop.create_task(events.shutdown_watcher())
            app.loop.create_task(_start())
            EventLoop.run()
    finally:
        # explicitly close asyncio event loop to avoid hitting the
        # following issue due to signal handlers added by
        # asyncio.create_subprocess_exec being cleaned up during final
        # garbage collection: https://github.com/python/asyncio/issues/396
        app.loop.close()
    sys.exit(app.exit_code)
Beispiel #39
0
 def __handle_exception(self, tag, exc):
     utils.pollinate(app.session_id, tag)
     EventLoop.remove_alarms()
     app.ui.show_exception_message(exc)
 def update(self, *args, **kwargs):
     self.pv.update()
     EventLoop.set_alarm_in(1, self.update)
Beispiel #41
0
def unhandled_input(key):
    if key in ['q', 'Q']:
        async.shutdown()
        EventLoop.exit(0)
Beispiel #42
0
 def finish(self, future):
     if not future.exception():
         return controllers.use('steps').render()
     EventLoop.remove_alarms()
Beispiel #43
0
 def update(self, *args):
     for w in self.all_step_widgets:
         w.update()
     EventLoop.set_alarm_in(1, self.update)
 def update(self, *args):
     self.update_now()
     self.alarm = EventLoop.set_alarm_in(1, self.update)
Beispiel #45
0
 def cancel(self, button):
     pollinate(app.session_id, 'UC')
     EventLoop.exit(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)
Beispiel #47
0
from conjureup import async
from conjureup.app_config import app
from ubuntui.ev import EventLoop
import macumba
import errno


class ConjureUI(Frame):
    def show_exception_message(self, ex):

        if isinstance(ex, async.ThreadCancelledException):
            pass
        elif isinstance(ex, macumba.errors.ServerError):
            errmsg = ex.args[1]
        elif hasattr(ex, 'errno') and ex.errno == errno.ENOENT:
            # handle oserror
            errmsg = ex.args[1]
        else:
            errmsg = ex.args[0]
        errmsg += ("\n\n"
                   "Review log messages at /var/log/conjure-up/combined.log "
                   "If appropriate, please submit a bug here: "
                   "https://bugs.launchpad.net/conjure-up/+filebug")

        self.frame.body = ErrorView(errmsg)
        app.log.exception("Showing dialog for exception:")
        EventLoop.remove_alarms()

    def show_error_message(self, msg):
        self.frame.body = ErrorView(msg)
Beispiel #48
0
def unhandled_input(key):
    if key in ['q', 'Q']:
        Shutdown.set()
    if key in ['R']:
        EventLoop.redraw_screen()
Beispiel #49
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',
                               '{}/{}'.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()
Beispiel #50
0
 def cancel(self, btn):
     EventLoop.exit(0)
Beispiel #51
0
 def __handle_exception(self, tag, exc):
     utils.pollinate(app.session_id, tag)
     EventLoop.remove_alarms()
     app.ui.show_exception_message(exc)
Beispiel #52
0
 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()
Beispiel #53
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()
Beispiel #54
0
 def update(self, *args):
     for w in self.all_step_widgets:
         w.update()
     EventLoop.set_alarm_in(1, self.update)
Beispiel #55
0
 def _handle_exception(self, tag, exc):
     track_exception(exc.args[0])
     app.ui.show_exception_message(exc)
     self.showing_error = True
     EventLoop.remove_alarms()