def is_lxd_ready(): """ routine for making sure lxd is configured for localhost deployments """ if utils.lxd_version() < parse_version('2.9'): return { "ready": False, "msg": "The current version of LXD found on this system is " "not compatible. Please run the following to get the latest " "supported LXD:\n\n" " sudo apt-add-repository ppa:ubuntu-lxc/lxd-stable\n" " sudo apt-get update\n" " sudo apt-get install lxd lxd-client\n\n" "Or if you're using the snap version:\n\n" " sudo snap refresh lxd\n\n" "Once complete please re-run conjure-up." } if not utils.check_user_in_group('lxd'): return { "ready": False, "msg": "User {} is not part of the LXD group. You will need " "to exit conjure-up and do one of the following:\n\n" " 1: Run `newgrp lxd` and re-launch conjure-up\n\n" " Or\n\n" " 2: Log out completely, Log in and " "re-launch conjure-up".format(os.environ['USER']) } try: setup_lxdbr0_network() setup_conjureup0_network() except Exception as e: return { "ready": False, "msg": "Unable to determine an existing LXD network bridge, " "please make sure you've run `sudo lxd init` to configure " "LXD.\n\n{}".format(e) } if utils.lxd_has_ipv6(): return { "ready": False, "msg": "The LXD bridge has IPv6 enabled. Currently this is " "unsupported by conjure-up. Please disable IPv6 and " "re-launch conjure-up\n\n" "Visit https://docs.ubuntu.com/conjure-up/en/troubleshoot#lxd " "for information on how to disable IPv6." } app.log.debug("Found an IPv4 address, " "assuming LXD is configured.") return {"ready": True, "msg": ""}
def handle_exception(loop, context): if 'exception' not in context: return # not an error, cleanup message if isinstance(context['exception'], ExitMainLoop): Shutdown.set() # use previously stored exit code return if Error.is_set(): return # already reporting an error Error.set() exc = context['exception'] if not (app.noreport or any(pred(exc) for pred in NOTRACK_EXCEPTIONS)): track_exception(str(exc)) try: exc_info = (type(exc), exc, exc.__traceback__) app.sentry.captureException(exc_info, tags={ 'spell': app.config.get('spell'), 'cloud_type': app.current_cloud_type, 'region': app.current_region, 'jaas': app.is_jaas, 'headless': app.headless, 'juju_version': utils.juju_version(), 'lxd_version': utils.lxd_version(), }) except Exception: app.log.exception('Error reporting error') app.log.exception('Unhandled exception', exc_info=exc) if app.headless: msg = str(exc) utils.error(msg) Shutdown.set(1) else: app.exit_code = 1 # store exit code for later app.ui.show_exception_message(exc) # eventually raises ExitMainLoop
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 app.state = redis.StrictRedis(host='localhost', port=opts.redis_port, db=0) 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("LXD version: {}, " "Juju version: {}, " "conjure-up version: {}".format(utils.lxd_version(), 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() 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['CONJURE_UP_CACHEDIR'] = app.argv.cache_dir 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() app.sentry = raven.Client( dsn=SENTRY_DSN, release=VERSION, 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: if '/' in app.argv.cloud: parse_cli_cloud = app.argv.cloud.split('/') app.current_cloud, app.current_region = parse_cli_cloud app.log.debug("Region found {} for cloud {}".format( app.current_cloud, app.current_region)) else: app.current_cloud = app.argv.cloud if app.endpoint_type in [None, EndpointType.LOCAL_SEARCH]: utils.error("Please specify a spell for headless mode.") sys.exit(1) cloud_types = juju.get_cloud_types_by_name() if app.current_cloud not in cloud_types: utils.error('Unknown cloud: {}'.format(app.current_cloud)) sys.exit(1) app.current_cloud_type = cloud_types[app.current_cloud] 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)