Example #1
0
def start(ctx, services, all, wait_time, no_vm, no_zt_dep, publishing_ip, assume_yes):
    """
Start selling a containerized service.

\b
Start selling a single service.
$ 21 sell start <service_name>

\b
Start selling all available services.
$ 21 sell start --all
"""
    # display help command if no service is selected
    if len(services) == 0 and all is False:
        raise click.UsageError('No service selected.', ctx=ctx)

    # no-vm version coming soon
    if no_vm:
        raise click.UsageError('This mode is not yet supported.', ctx=ctx)

    # assign manager and installer from context
    manager = ctx.obj['manager']
    installer = ctx.obj['installer']

    if no_zt_dep:
        if publishing_ip is None:
            logger.info(click.style("--no-zt-dep must be used in "
                                    "conjunction with --publishing-ip <IP_TO_PUBLISH>.",
                                    fg=cli_helpers.PROMPT_COLOR))
            sys.exit()

    if cli_helpers.running_old_sell(manager, installer):
        if click.confirm(click.style("It appears that you are running an old version of 21 sell.\n"
                                     "In order to continue using 21 sell, you must update the 21 "
                                     "VM.\nWould you like to delete the existing VM and create a "
                                     "new one?",
                                     fg=cli_helpers.WARNING_COLOR)):
            upgrade_21_sell(ctx, services, all, wait_time, no_vm)
            sys.exit()
        else:
            logger.info(click.style("Please note that your services may be unreachable "
                                    "without this update.",
                                    fg=cli_helpers.WARNING_COLOR))
            sys.exit()

    logger.info(click.style("Checking dependencies.", fg=cli_helpers.TITLE_COLOR))
    deps_list = installer.check_dependencies()
    if no_zt_dep:
        deps_list = [(name, installed) for name, installed in deps_list if name != 'Docker']
    all_deps_installed = cli_helpers.package_check(deps_list, True)

    # install virtualbox, docker, and zerotier deps
    if not all_deps_installed:
        if assume_yes or click.confirm(click.style("Would you like to install the missing "
                                                   "packages?",
                                                   fg=cli_helpers.PROMPT_COLOR)):
            logger.info(click.style("Installing missing dependencies.", fg=cli_helpers.TITLE_COLOR))
            all_installed = cli_helpers.install_missing_dependencies(deps_list,
                                                                     installer)
            if not all_installed:
                sys.exit()
        else:
            sys.exit()

    # pick up docker group permissions by forced logout
    if cli_helpers.check_needs_logout(installer):
        sys.exit()

    if isinstance(manager.machine, Two1MachineVirtual):
        logger.info(click.style("Checking virtual machine status.", fg=cli_helpers.TITLE_COLOR))
        just_started = False
        vm_status = manager.status_machine()
        if vm_status == VmState.NOEXIST:
            if assume_yes or click.confirm(click.style("  21 virtual machine does not exist. "
                                                       "Would you like to create it?",
                                                       fg=cli_helpers.PROMPT_COLOR)):
                vm_config = cli_helpers.get_vm_options()
                try:
                    cli_helpers.start_long_running("Creating machine (this may take a few minutes)",
                                                   manager.create_machine,
                                                   "21",
                                                   vm_config.disk_size,
                                                   vm_config.vm_memory,
                                                   vm_config.server_port)
                    manager.write_machine_config(vm_config._asdict())
                    cli_helpers.print_str("21 virtual machine", ["Created"], "TRUE", True)

                except Two1MachineCreateException:
                    cli_helpers.print_str("21 virtual machine", ["Not created"], "FALSE", False)
                vm_status = manager.status_machine()
            else:
                sys.exit()

        if vm_status != VmState.RUNNING:
            try:
                cli_helpers.start_long_running("Starting machine (this may take a few minutes)",
                                               manager.start_machine)
                just_started = True
            except Two1MachineStartException:
                cli_helpers.print_str("21 virtual machine", ["Not started"], "FALSE", False)
                sys.exit()
            vm_status = manager.status_machine()

        # check if machine running
        if vm_status == VmState.RUNNING:
            if just_started:
                cli_helpers.print_str("21 virtual machine", ["Started"], "TRUE", True)
            else:
                cli_helpers.print_str("21 virtual machine", ["Running"], "TRUE", True)
        else:
            sys.exit()
    else:
        server_port = cli_helpers.get_server_port()
        manager.write_machine_config({"server_port": server_port})

    # connect to zerotier virtual network
    if not manager.status_networking():
        if no_zt_dep:
            pass
        else:
            try:
                if not isinstance(manager.machine, Two1MachineVirtual):
                    if assume_yes or click.confirm(click.style(
                            "ZeroTier One virtual network service is not running. Would you like "
                            "to start the service?", fg=cli_helpers.PROMPT_COLOR)):
                        manager.start_networking()
                    else:
                        sys.exit()
                else:
                    cli_helpers.start_long_running("Starting ZeroTier One",
                                                   manager.start_networking)

                cli_helpers.print_str("ZeroTier One", ["Started"], "TRUE", True)
            except Two1MachineNetworkStartException:
                cli_helpers.print_str("ZeroTier One", ["Not started"], "FALSE", False)
                sys.exit()

    # join the 21mkt network
    if manager.get_market_address() == "":
        if no_zt_dep:
            pass
        else:
            if not isinstance(manager.machine, Two1MachineVirtual):
                if assume_yes or click.confirm(click.style(
                        "21mkt network not connected. Would you like to join 21mkt?",
                        fg=cli_helpers.PROMPT_COLOR)):
                    logger.info("You might need to enter your superuser password.")
                    manager.connect_market(ctx.obj["client"])
                else:
                    sys.exit()
            else:
                cli_helpers.start_long_running("Connecting to 21mkt",
                                               manager.connect_market,
                                               ctx.obj["client"])

            if manager.get_market_address() != "":
                cli_helpers.print_str("21mkt", ["Joined"], "TRUE", True)
            else:
                cli_helpers.print_str("21mkt", ["Unable to join"], "FALSE", False)
                sys.exit()
    else:
        cli_helpers.print_str("21mkt", ["Joined"], "TRUE", True)

    # ensure docker service is running
    if manager.status_docker() is False:
        if assume_yes or click.confirm(click.style(
                "Docker service is not running. Would you like to start "
                "the service?", fg=cli_helpers.PROMPT_COLOR)):
            try:
                manager.start_docker()
                cli_helpers.print_str("Docker", ["Started"], "TRUE", True)
            except Two1MachineNetworkStartException:
                cli_helpers.print_str("Docker", ["Not started"], "FALSE", False)
        else:
            sys.exit()

    # generate machine wallet & initialize micropayments server
    logger.info(click.style("Initializing micropayments server.", fg=cli_helpers.TITLE_COLOR))
    username, password = cli_helpers.get_user_credentials()  # get user creds
    try:
        server_port = manager.get_server_port()
    except Exception:
        logger.info(click.style("Error: cannot read server port from file.  Please try again or contact "
                                "[email protected].", fg="magenta"))
    status_init, new_wallet_mnemonic = manager.initialize_server(username, password, server_port)
    if status_init == 0:
        # if new mnemonic has been generated
        if new_wallet_mnemonic is not None:
            logger.info(click.style("\nA unique machine wallet has been generated for your micropayments "
                                    "server.\nPlease write down the following mnemonic and store it in "
                                    "a safe place:\n", fg=cli_helpers.PROMPT_COLOR))
            logger.info(click.style("    {}\n".format(new_wallet_mnemonic), fg="magenta"))
            click.pause()
    else:
        logger.info(click.style("Error initializing micropayments server. Please try again or "
                                "contact [email protected].", fg="magenta"))
        sys.exit()

    # check that services to start are available
    available_services = manager.get_available_services()

    if len(available_services) == 0:
        raise click.ClickException(click.style("Unable to fetch available services. Please try again or contact"
                                               " [email protected].", fg="magenta"))

    if not all:
        logger.info(click.style("Checking availability of selected services.", fg=cli_helpers.TITLE_COLOR))

        available_selected_services = set(services) & available_services
        unavailable_selected_services = set(services) - available_services

        for available_selected_service in available_selected_services:
            cli_helpers.print_str(available_selected_service, ["Available"], "TRUE", True)

        for unavailable_selected_service in unavailable_selected_services:
            cli_helpers.print_str(unavailable_selected_service, ["Unavailable"], "False", False)

        if available_selected_services == set(services):
            service_to_pull = set(services)
        elif len(available_selected_services) > 0:
            if click.confirm(click.style("Not all selected services are available, would you like to start the"
                                         " available services anyways?", fg=cli_helpers.PROMPT_COLOR)):
                service_to_pull = available_selected_services
            else:
                raise click.Abort()
        else:
            raise click.ClickException(click.style("None of the services you've selected is available.", fg="magenta") +
                                       click.style(" Run", fg="magenta") +
                                       click.style(" `21 sell list`", bold=True, fg=cli_helpers.PROMPT_COLOR) +
                                       click.style(" to see available microservices.", fg="magenta"))
    else:
        service_to_pull = available_services

    # Pulling images for services in `service_to_pull`
    logger.info(click.style("Pulling images for selected services.", fg=cli_helpers.TITLE_COLOR))

    service_to_start = set()
    for service_name in service_to_pull:

        image_for_service = manager.get_image(service_name)

        def image_sucessfully_pulled_hook(image):
            service_to_start.add(service_name)
            cli_helpers.print_str('%s -> %s' % (service_name, image), ["Pulled"], "TRUE", True)

        def image_failed_to_pull_hook(image):
            cli_helpers.print_str('%s -> %s' % (service_name, image), ["Failed to pull"], "False", False)

        def image_is_local_hook(image):
            service_to_start.add(service_name)
            cli_helpers.print_str('%s -> %s' % (service_name, image), ["Exists locally"], "TRUE", True)

        def image_is_malformed_hook(image):
            cli_helpers.print_str('%s -> %s' % (service_name, image), ["Malformed image name"], "False", False)

        manager.pull_image(image_for_service,
                           image_sucessfully_pulled_hook, image_failed_to_pull_hook, image_is_local_hook,
                           image_is_malformed_hook)

    if service_to_pull > service_to_start:
        if len(service_to_start) > 0:
            if not click.confirm(click.style("Not all Docker Hub images were successfully pulled for the services"
                                             " you've selected, would you like to start the services that had their"
                                             " images successfully pulled anyways?", fg=cli_helpers.PROMPT_COLOR)):
                raise click.Abort()
        else:
            raise click.ClickException(click.style("None of the Docker Hub images were successfully pulled for the"
                                                   " services you've selected.", fg="magenta"))

    # Start services for services in `service_to_start`
    logger.info(click.style("Starting services.", fg=cli_helpers.TITLE_COLOR))
    try:
        manager.start_services(service_to_start,
                               cli_helpers.failed_to_start_hook,
                               cli_helpers.started_hook,
                               cli_helpers.failed_to_restart_hook,
                               cli_helpers.restarted_hook,
                               cli_helpers.failed_to_up_hook,
                               cli_helpers.up_hook)
    except:
        raise click.ClickException(click.style("Unable to start services.", fg="magenta"))

    try:
        started_services = manager.get_running_services()
    except:
        raise click.ClickException(click.style("Unable to fetch running services.", fg="magenta"))

    # prompt to publish services
    published_stats = cli_helpers.prompt_to_publish(started_services, manager, publishing_ip, assume_yes=assume_yes)
    for stat in published_stats:
        cli_helpers.print_str(stat[0],
                              stat[2],
                              "TRUE" if stat[1] else "FALSE",
                              stat[1])

    # help tip message
    logger.info(click.style("\nTip: (1) run ", fg=cli_helpers.PROMPT_COLOR) +
                click.style("`21 publish list`", bold=True, fg=cli_helpers.PROMPT_COLOR) +
                click.style(" to see your published services.\n", fg=cli_helpers.PROMPT_COLOR) +
                click.style("     (2) run ", fg=cli_helpers.PROMPT_COLOR) +
                click.style("`21 sell status --detail`", bold=True, fg=cli_helpers.PROMPT_COLOR) +
                click.style(" to see your microservice balances.", fg=cli_helpers.PROMPT_COLOR))
Example #2
0
def start(ctx, services, all, wait_time, no_vm, assume_yes):
    """
Start selling a containerized service.

\b
Start selling a single service.
$ 21 sell start <service_name>

\b
Start selling all available services.
$ 21 sell start --all
"""
    # display help command if no args
    if len(services) == 0 and all is False:
        logger.info(ctx.command.get_help(ctx))
        sys.exit()

    # no-vm version coming soon
    if no_vm:
        logger.info(
            click.style("This mode is not yet supported.", fg="magenta"))
        sys.exit()

    # assign manager and installer from context
    manager = ctx.obj['manager']
    installer = ctx.obj['installer']

    if cli_helpers.running_old_sell(manager, installer):
        if click.confirm(
                click.style(
                    "It appears that you are running an old version of 21 sell.\n"
                    "In order to continue using 21 sell, you must update the 21 VM.\n"
                    "Would you like to delete the existing VM and create a new one?",
                    fg=cli_helpers.WARNING_COLOR)):
            upgrade_21_sell(ctx, services, all, wait_time, no_vm)
            sys.exit()
        else:
            logger.info(
                click.style(
                    "Please note that your services may be unreachable without this update.",
                    fg=cli_helpers.WARNING_COLOR))
            sys.exit()

    logger.info(
        click.style("Checking dependencies.", fg=cli_helpers.TITLE_COLOR))
    deps_list = installer.check_dependencies()
    all_deps_installed = cli_helpers.package_check(deps_list, True)

    # install virtualbox, docker, and zerotier deps
    if not all_deps_installed:
        if assume_yes or click.confirm(
                click.style("Would you like to install the missing packages?",
                            fg=cli_helpers.PROMPT_COLOR)):
            logger.info(
                click.style("Installing missing dependencies.",
                            fg=cli_helpers.TITLE_COLOR))
            all_installed = cli_helpers.install_missing_dependencies(
                deps_list, installer)
            if not all_installed:
                sys.exit()
        else:
            sys.exit()

    # pick up docker group permissions by forced logout
    if cli_helpers.check_needs_logout(installer):
        sys.exit()

    if isinstance(manager.machine, Two1MachineVirtual):
        logger.info(
            click.style("Checking virtual machine status.",
                        fg=cli_helpers.TITLE_COLOR))
        just_started = False
        vm_status = manager.status_machine()
        if vm_status == VmState.NOEXIST:
            if assume_yes or click.confirm(
                    click.style(
                        "  21 virtual machine does not exist. "
                        "Would you like to create it?",
                        fg=cli_helpers.PROMPT_COLOR)):
                vm_config = cli_helpers.get_vm_options()
                try:
                    cli_helpers.start_long_running(
                        "Creating machine (this may take a few minutes)",
                        manager.create_machine, "21", vm_config.disk_size,
                        vm_config.vm_memory, vm_config.server_port)
                    manager.write_machine_config(vm_config._asdict())
                    cli_helpers.print_str("21 virtual machine", ["Created"],
                                          "TRUE", True)

                except Two1MachineCreateException:
                    cli_helpers.print_str("21 virtual machine",
                                          ["Not created"], "FALSE", False)
                vm_status = manager.status_machine()
            else:
                sys.exit()

        if vm_status != VmState.RUNNING:
            try:
                cli_helpers.start_long_running(
                    "Starting machine (this may take a few minutes)",
                    manager.start_machine)
                just_started = True
            except Two1MachineStartException:
                cli_helpers.print_str("21 virtual machine", ["Not started"],
                                      "FALSE", False)
                sys.exit()
            vm_status = manager.status_machine()

        # check if machine running
        if vm_status == VmState.RUNNING:
            if just_started:
                cli_helpers.print_str("21 virtual machine", ["Started"],
                                      "TRUE", True)
            else:
                cli_helpers.print_str("21 virtual machine", ["Running"],
                                      "TRUE", True)
        else:
            sys.exit()
    else:
        server_port = cli_helpers.get_server_port()
        manager.write_machine_config({"server_port": server_port})

    # connect to zerotier virtual network
    if not manager.status_networking():
        try:
            if not isinstance(manager.machine, Two1MachineVirtual):
                if assume_yes or click.confirm(
                        click.style(
                            "ZeroTier One virtual network service is not running. Would you like to start "
                            "the service?",
                            fg=cli_helpers.PROMPT_COLOR)):
                    manager.start_networking()
                else:
                    sys.exit()
            else:
                cli_helpers.start_long_running("Starting ZeroTier One",
                                               manager.start_networking)

            cli_helpers.print_str("ZeroTier One", ["Started"], "TRUE", True)
        except Two1MachineNetworkStartException:
            cli_helpers.print_str("ZeroTier One", ["Not started"], "FALSE",
                                  False)
            sys.exit()

    # join the 21mkt network
    if manager.get_market_address() == "":
        if not isinstance(manager.machine, Two1MachineVirtual):
            if assume_yes or click.confirm(
                    click.style(
                        "21mkt network not connected. Would you like to join 21mkt?",
                        fg=cli_helpers.PROMPT_COLOR)):
                logger.info("You might need to enter your superuser password.")
                manager.connect_market(ctx.obj["client"])
            else:
                sys.exit()
        else:
            cli_helpers.start_long_running("Connecting to 21mkt",
                                           manager.connect_market,
                                           ctx.obj["client"])

        if manager.get_market_address() != "":
            cli_helpers.print_str("21mkt", ["Joined"], "TRUE", True)
        else:
            cli_helpers.print_str("21mkt", ["Unable to join"], "FALSE", False)
            sys.exit()
    else:
        cli_helpers.print_str("21mkt", ["Joined"], "TRUE", True)

    # ensure docker service is running
    if manager.status_docker() is False:
        if assume_yes or click.confirm(
                click.style(
                    "Docker service is not running. Would you like to start "
                    "the service?",
                    fg=cli_helpers.PROMPT_COLOR)):
            try:
                manager.start_docker()
                cli_helpers.print_str("Docker", ["Started"], "TRUE", True)
            except Two1MachineNetworkStartException:
                cli_helpers.print_str("Docker", ["Not started"], "FALSE",
                                      False)
        else:
            sys.exit()

    # generate machine wallet & initialize micropayments server
    logger.info(
        click.style("Initializing micropayments server.",
                    fg=cli_helpers.TITLE_COLOR))
    username, password = cli_helpers.get_user_credentials()  # get user creds
    try:
        server_port = manager.get_server_port()
    except Exception:
        logger.info(
            click.style(
                "Error: cannot read server port from file.  Please try again or contact "
                "[email protected].",
                fg="magenta"))
    status_init, new_wallet_mnemonic = manager.initialize_server(
        username, password, server_port)
    if status_init == 0:
        # if new mnemonic has been generated
        if new_wallet_mnemonic is not None:
            logger.info(
                click.style(
                    "\nA unique machine wallet has been generated for your micropayments "
                    "server.\nPlease write down the following mnemonic and store it in "
                    "a safe place:\n",
                    fg=cli_helpers.PROMPT_COLOR))
            logger.info(
                click.style("    {}\n".format(new_wallet_mnemonic),
                            fg="magenta"))
            click.pause()
    else:
        logger.info(
            click.style(
                "Error initializing micropayments server. Please try again or "
                "contact [email protected].",
                fg="magenta"))
        sys.exit()

    # start microservices
    two1_services = manager.list_available_services()
    if all:
        try:
            valid_services = two1_services
        except Exception:
            logger.info(
                click.style(
                    "Error: unable to fetch machine images. Please try again or "
                    "contact [email protected].",
                    fg="magenta"))
            sys.exit()
    else:
        valid_services = []
        for serv in services:
            if serv in two1_services:
                valid_services.append(serv)

    if len(valid_services) <= 0:
        logger.info(
            click.style(
                "No service available to sell. Please try again or "
                "contact [email protected].",
                fg="magenta"))
        sys.exit()

    logger.info(
        click.style("Pulling latest images.", fg=cli_helpers.TITLE_COLOR))
    selected_services = list(
        set(['service-' + name for name in valid_services
             ]).union(set(Two1Composer.BASE_SERVICES)))
    try:
        manager.pull_latest_images(selected_services)
    except Exception:
        logger.info("Unable to pull latest images.", fg="magenta")
        sys.exit()

    logger.info(click.style("Starting services.", fg=cli_helpers.TITLE_COLOR))
    try:
        manager.start_services(
            valid_services, cli_helpers.failed_to_start_hook,
            cli_helpers.started_hook, cli_helpers.failed_to_restart_hook,
            cli_helpers.restarted_hook, cli_helpers.failed_to_up_hook,
            cli_helpers.up_hook)
    except Exception:
        logger.info("Unable to start services.", fg="magenta")
        sys.exit()

    try:
        started_services = manager.get_running_services()
    except Exception:
        logger.info("Unable to fetch running services.", fg="magenta")
        sys.exit()

    published_stats = cli_helpers.prompt_to_publish(started_services, manager,
                                                    assume_yes)
    for stat in published_stats:
        cli_helpers.print_str(stat[0], stat[2], "TRUE" if stat[1] else "FALSE",
                              stat[1])

    # help tip message
    logger.info(
        click.style("\nTip: (1) run ", fg=cli_helpers.PROMPT_COLOR) +
        click.style(
            "`21 publish list`", bold=True, fg=cli_helpers.PROMPT_COLOR) +
        click.style(" to see your published services.\n",
                    fg=cli_helpers.PROMPT_COLOR) +
        click.style("     (2) run ", fg=cli_helpers.PROMPT_COLOR) +
        click.style("`21 sell status --detail`",
                    bold=True,
                    fg=cli_helpers.PROMPT_COLOR) +
        click.style(" to see your microservice balances.",
                    fg=cli_helpers.PROMPT_COLOR))
Example #3
0
File: sell.py Project: shayanb/two1
def start(ctx, services, all, wait_time, no_vm):
    """
Start selling a containerized service.

\b
Start selling a single service.
$ 21 sell start <service_name>

\b
Start selling all available services.
$ 21 sell start --all
"""

    # display help command if no args
    if len(services) == 0 and all is False:
        logger.info(ctx.command.get_help(ctx))
        sys.exit()

    # no-vm version coming soon
    if no_vm:
        logger.info(click.style("This mode is not yet supported.", fg="magenta"))
        sys.exit()

    # assign manager and installer from context
    manager = ctx.obj['manager']
    installer = ctx.obj['installer']

    logger.info(click.style("Checking dependencies...", fg=cli_helpers.TITLE_COLOR))
    deps_list = installer.check_dependencies()
    all_deps_installed = cli_helpers.package_check(deps_list, True)

    # install virtualbox, docker, and zerotier deps
    if not all_deps_installed:
        if click.confirm(click.style("Would you like to install the missing packages?",
                                     fg=cli_helpers.PROMPT_COLOR)):
            logger.info(click.style("Installing missing dependencies...", fg=cli_helpers.TITLE_COLOR))
            all_installed = cli_helpers.install_missing_dependencies(deps_list,
                                                                     installer)
            if not all_installed:
                sys.exit()
        else:
            sys.exit()

    # pick up docker group permissions by force logout (via user prompt)
    if cli_helpers.check_needs_logout(installer):
        sys.exit()

    # connect to zerotier virtual network
    if not manager.status_networking():
        if click.confirm(click.style(
                "ZeroTier One virtual network service is not running. Would you like to start "
                "the service?", fg=cli_helpers.PROMPT_COLOR)):
            try:
                manager.start_networking()
                cli_helpers.print_str("ZeroTier One", ["Started"], "TRUE", True)
            except Two1MachineNetworkStartException:
                cli_helpers.print_str("ZeroTier One", ["Not started"], "FALSE", False)
        else:
            sys.exit()

    # join the 21market network
    if manager.get_market_address() == "":
        if click.confirm(click.style(
                "21market network not connected. Would you like to join 21market?", fg=cli_helpers.PROMPT_COLOR)):
            logger.info("You might need to enter your superuser password.")
            manager.connect_market(ctx.obj['client'])
            if manager.get_market_address() == "":
                cli_helpers.print_str("21market", ["Joined"], "TRUE", True)
            else:
                cli_helpers.print_str("21market", ["Unable to join"], "FALSE", False)
        else:
            sys.exit()
    else:
        cli_helpers.print_str("21market", ["Joined"], "TRUE", True)

    if isinstance(manager.machine, Two1MachineVirtual):
        logger.info(click.style("Checking virtual machine status...", fg=cli_helpers.TITLE_COLOR))
        just_started = False
        vm_status = manager.status_machine()
        if vm_status == VmState.NOEXIST:
            if click.confirm(click.style("  21 virtual machine does not exist. "
                                         "Would you like to create it?",
                                         fg=cli_helpers.PROMPT_COLOR)):
                vm_config = cli_helpers.get_vm_options()
                try:
                    cli_helpers.start_long_running("Creating machine (this may take a few minutes)",
                                                   manager.create_machine,
                                                   "21",
                                                   vm_config.disk_size,
                                                   vm_config.vm_memory,
                                                   vm_config.server_port,
                                                   vm_config.network_interface)
                    cli_helpers.write_machine_config(vm_config._asdict())
                    cli_helpers.print_str("21 virtual machine", ["Created"], "TRUE", True)

                except Two1MachineCreateException:
                    cli_helpers.print_str("21 virtual machine", ["Not created"], "FALSE", False)

                vm_status = manager.status_machine()
            else:
                sys.exit()

        if vm_status != VmState.RUNNING:
            if not manager.status_networking():
                if click.confirm(click.style(
                        "ZeroTier One virtual network service is not running. "
                        "Would you like to start the service?", fg=cli_helpers.PROMPT_COLOR)):
                    try:
                        manager.start_networking()
                        cli_helpers.print_str("ZeroTier One", ["Started"], "TRUE", True)
                    except Two1MachineNetworkStartException:
                        cli_helpers.print_str("ZeroTier One", ["Not started"], "FALSE", False)
                else:
                    sys.exit()
            try:
                cli_helpers.start_long_running("Starting machine (this may take a few minutes)",
                                               manager.start_machine)
                just_started = True
            except Two1MachineStartException:
                cli_helpers.print_str("21 virtual machine", ["Not started"], "FALSE", False)
                sys.exit()
            vm_status = manager.status_machine()

        # check if machine running
        if vm_status == VmState.RUNNING:
            if just_started:
                cli_helpers.print_str("21 virtual machine", ["Started"], "TRUE", True)
            else:
                cli_helpers.print_str("21 virtual machine", ["Running"], "TRUE", True)
        else:
            sys.exit()
    else:
        server_port = cli_helpers.get_server_port()
        cli_helpers.write_machine_config({"server_port": server_port})

    # write user credentials info to environment file
    username, pw = cli_helpers.get_user_credentials()
    status_env = manager.write_global_services_env(username, pw)

    # build service images
    try:
        payment_wallet = cli_helpers.start_long_running("Building base services (this may take a few minutes)",
                                                        manager.build_base_services)
    except:
        cli_helpers.print_str("Services", ["Not built"], "FALSE", False)
        sys.exit()
    else:
        cli_helpers.print_str("Services", ["Built"], "TRUE", True)

    if payment_wallet["created"]:
        logger.info(click.style("A wallet has been generated for the payment container,\nplease write down its wallet mnemonic and store it in a safe place:\n"
                                "    {}".format(payment_wallet['mnemonic']), fg="magenta"))
        click.pause()

    if all:
        valid_services = manager.get_all_services_list()
    else:
        valid_services = services

    # build service images
    try:
        wallets_dict = cli_helpers.start_long_running("Building market services (this may take a few minutes)",
                                                      manager.build_market_services,
                                                      valid_services)
    except:
        cli_helpers.print_str("Services", ["Not built"], "FALSE", False)
        sys.exit()
    else:
        cli_helpers.print_str("Services", ["Built"], "TRUE", True)

    for service, wallet_template in wallets_dict.items():
        if wallet_template["created"]:
            logger.info(click.style("A wallet has been generated for the service \"{}\",\nplease write down its wallet mnemonic and store it in a safe place:\n"
                                    "    {}".format(service, wallet_template['mnemonic']), fg="magenta"))
            click.pause()

    # start container services
    start_stats = cli_helpers.start_long_running("Starting services (this may take a few minutes)",
                                                 manager.start_services,
                                                 valid_services)
    formatted_stats = cli_helpers.start_dict_to_list(start_stats)
    cli_helpers.service_status_check(formatted_stats, False)
    published_stats = cli_helpers.prompt_to_publish(formatted_stats, manager)
    for stat in published_stats:
        cli_helpers.print_str(stat[0],
                              stat[2],
                              "TRUE" if stat[1] else "FALSE",
                              stat[1])
    # help tip message
    logger.info(click.style("\nTip: run ", fg=cli_helpers.PROMPT_COLOR) +
                click.style("`21 sell status --detail`", bold=True, fg=cli_helpers.PROMPT_COLOR) +
                click.style(" to see your microservice balances.", fg=cli_helpers.PROMPT_COLOR))
Example #4
0
def start(ctx, services, all, wait_time, no_vm, no_zt_dep, publishing_ip,
          assume_yes):
    """
Start selling a containerized service.

\b
Start selling a single service.
$ 21 sell start <service_name>

\b
Start selling all available services.
$ 21 sell start --all
"""
    # display help command if no service is selected
    if len(services) == 0 and all is False:
        raise click.UsageError('No service selected.', ctx=ctx)

    # no-vm version coming soon
    if no_vm:
        raise click.UsageError('This mode is not yet supported.', ctx=ctx)

    # assign manager and installer from context
    manager = ctx.obj['manager']
    installer = ctx.obj['installer']

    if no_zt_dep:
        if publishing_ip is None:
            logger.info(
                click.style(
                    "--no-zt-dep must be used in "
                    "conjunction with --publishing-ip <IP_TO_PUBLISH>.",
                    fg=cli_helpers.PROMPT_COLOR))
            sys.exit()

    if cli_helpers.running_old_sell(manager, installer):
        if click.confirm(
                click.style(
                    "It appears that you are running an old version of 21 sell.\n"
                    "In order to continue using 21 sell, you must update the 21 "
                    "VM.\nWould you like to delete the existing VM and create a "
                    "new one?",
                    fg=cli_helpers.WARNING_COLOR)):
            upgrade_21_sell(ctx, services, all, wait_time, no_vm)
            sys.exit()
        else:
            logger.info(
                click.style(
                    "Please note that your services may be unreachable "
                    "without this update.",
                    fg=cli_helpers.WARNING_COLOR))
            sys.exit()

    logger.info(
        click.style("Checking dependencies.", fg=cli_helpers.TITLE_COLOR))
    deps_list = installer.check_dependencies()
    if no_zt_dep:
        deps_list = [(name, installed) for name, installed in deps_list
                     if name != 'Docker']
    all_deps_installed = cli_helpers.package_check(deps_list, True)

    # install virtualbox, docker, and zerotier deps
    if not all_deps_installed:
        if assume_yes or click.confirm(
                click.style(
                    "Would you like to install the missing "
                    "packages?",
                    fg=cli_helpers.PROMPT_COLOR)):
            logger.info(
                click.style("Installing missing dependencies.",
                            fg=cli_helpers.TITLE_COLOR))
            all_installed = cli_helpers.install_missing_dependencies(
                deps_list, installer)
            if not all_installed:
                sys.exit()
        else:
            sys.exit()

    # pick up docker group permissions by forced logout
    if cli_helpers.check_needs_logout(installer):
        sys.exit()

    if isinstance(manager.machine, Two1MachineVirtual):
        logger.info(
            click.style("Checking virtual machine status.",
                        fg=cli_helpers.TITLE_COLOR))
        just_started = False
        vm_status = manager.status_machine()
        if vm_status == VmState.NOEXIST:
            if assume_yes or click.confirm(
                    click.style(
                        "  21 virtual machine does not exist. "
                        "Would you like to create it?",
                        fg=cli_helpers.PROMPT_COLOR)):
                vm_config = cli_helpers.get_vm_options()
                try:
                    cli_helpers.start_long_running(
                        "Creating machine (this may take a few minutes)",
                        manager.create_machine, "21", vm_config.disk_size,
                        vm_config.vm_memory, vm_config.server_port)
                    manager.write_machine_config(vm_config._asdict())
                    cli_helpers.print_str("21 virtual machine", ["Created"],
                                          "TRUE", True)

                except Two1MachineCreateException:
                    cli_helpers.print_str("21 virtual machine",
                                          ["Not created"], "FALSE", False)
                vm_status = manager.status_machine()
            else:
                sys.exit()

        if vm_status != VmState.RUNNING:
            try:
                cli_helpers.start_long_running(
                    "Starting machine (this may take a few minutes)",
                    manager.start_machine)
                just_started = True
            except Two1MachineStartException:
                cli_helpers.print_str("21 virtual machine", ["Not started"],
                                      "FALSE", False)
                sys.exit()
            vm_status = manager.status_machine()

        # check if machine running
        if vm_status == VmState.RUNNING:
            if just_started:
                cli_helpers.print_str("21 virtual machine", ["Started"],
                                      "TRUE", True)
            else:
                cli_helpers.print_str("21 virtual machine", ["Running"],
                                      "TRUE", True)
        else:
            sys.exit()
    else:
        server_port = cli_helpers.get_server_port()
        manager.write_machine_config({"server_port": server_port})

    # connect to zerotier virtual network
    if not manager.status_networking():
        if no_zt_dep:
            pass
        else:
            try:
                if not isinstance(manager.machine, Two1MachineVirtual):
                    if assume_yes or click.confirm(
                            click.style(
                                "ZeroTier One virtual network service is not running. Would you like "
                                "to start the service?",
                                fg=cli_helpers.PROMPT_COLOR)):
                        manager.start_networking()
                    else:
                        sys.exit()
                else:
                    cli_helpers.start_long_running("Starting ZeroTier One",
                                                   manager.start_networking)

                cli_helpers.print_str("ZeroTier One", ["Started"], "TRUE",
                                      True)
            except Two1MachineNetworkStartException:
                cli_helpers.print_str("ZeroTier One", ["Not started"], "FALSE",
                                      False)
                sys.exit()

    # join the 21mkt network
    if manager.get_market_address() == "":
        if no_zt_dep:
            pass
        else:
            if not isinstance(manager.machine, Two1MachineVirtual):
                if assume_yes or click.confirm(
                        click.style(
                            "21mkt network not connected. Would you like to join 21mkt?",
                            fg=cli_helpers.PROMPT_COLOR)):
                    logger.info(
                        "You might need to enter your superuser password.")
                    manager.connect_market(ctx.obj["client"])
                else:
                    sys.exit()
            else:
                cli_helpers.start_long_running("Connecting to 21mkt",
                                               manager.connect_market,
                                               ctx.obj["client"])

            if manager.get_market_address() != "":
                cli_helpers.print_str("21mkt", ["Joined"], "TRUE", True)
            else:
                cli_helpers.print_str("21mkt", ["Unable to join"], "FALSE",
                                      False)
                sys.exit()
    else:
        cli_helpers.print_str("21mkt", ["Joined"], "TRUE", True)

    # ensure docker service is running
    if manager.status_docker() is False:
        if assume_yes or click.confirm(
                click.style(
                    "Docker service is not running. Would you like to start "
                    "the service?",
                    fg=cli_helpers.PROMPT_COLOR)):
            try:
                manager.start_docker()
                cli_helpers.print_str("Docker", ["Started"], "TRUE", True)
            except Two1MachineNetworkStartException:
                cli_helpers.print_str("Docker", ["Not started"], "FALSE",
                                      False)
        else:
            sys.exit()

    # generate machine wallet & initialize micropayments server
    logger.info(
        click.style("Initializing micropayments server.",
                    fg=cli_helpers.TITLE_COLOR))
    username, password = cli_helpers.get_user_credentials()  # get user creds
    try:
        server_port = manager.get_server_port()
    except Exception:
        logger.info(
            click.style(
                "Error: cannot read server port from file.  Please try again or contact "
                "[email protected].",
                fg="magenta"))
    status_init, new_wallet_mnemonic = manager.initialize_server(
        username, password, server_port)
    if status_init == 0:
        # if new mnemonic has been generated
        if new_wallet_mnemonic is not None:
            logger.info(
                click.style(
                    "\nA unique machine wallet has been generated for your micropayments "
                    "server.\nPlease write down the following mnemonic and store it in "
                    "a safe place:\n",
                    fg=cli_helpers.PROMPT_COLOR))
            logger.info(
                click.style("    {}\n".format(new_wallet_mnemonic),
                            fg="magenta"))
            click.pause()
    else:
        logger.info(
            click.style(
                "Error initializing micropayments server. Please try again or "
                "contact [email protected].",
                fg="magenta"))
        sys.exit()

    # check that services to start are available
    available_services = manager.get_available_services()

    if len(available_services) == 0:
        raise click.ClickException(
            click.style(
                "Unable to fetch available services. Please try again or contact"
                " [email protected].",
                fg="magenta"))

    if not all:
        logger.info(
            click.style("Checking availability of selected services.",
                        fg=cli_helpers.TITLE_COLOR))

        available_selected_services = set(services) & available_services
        unavailable_selected_services = set(services) - available_services

        for available_selected_service in available_selected_services:
            cli_helpers.print_str(available_selected_service, ["Available"],
                                  "TRUE", True)

        for unavailable_selected_service in unavailable_selected_services:
            cli_helpers.print_str(unavailable_selected_service,
                                  ["Unavailable"], "False", False)

        if available_selected_services == set(services):
            service_to_pull = set(services)
        elif len(available_selected_services) > 0:
            if click.confirm(
                    click.style(
                        "Not all selected services are available, would you like to start the"
                        " available services anyways?",
                        fg=cli_helpers.PROMPT_COLOR)):
                service_to_pull = available_selected_services
            else:
                raise click.Abort()
        else:
            raise click.ClickException(
                click.style(
                    "None of the services you've selected is available.",
                    fg="magenta") + click.style(" Run", fg="magenta") +
                click.style(" `21 sell list`",
                            bold=True,
                            fg=cli_helpers.PROMPT_COLOR) +
                click.style(" to see available microservices.", fg="magenta"))
    else:
        service_to_pull = available_services

    # Pulling images for services in `service_to_pull`
    logger.info(
        click.style("Pulling images for selected services.",
                    fg=cli_helpers.TITLE_COLOR))

    service_to_start = set()
    for service_name in service_to_pull:

        image_for_service = manager.get_image(service_name)

        def image_sucessfully_pulled_hook(image):
            service_to_start.add(service_name)
            cli_helpers.print_str('%s -> %s' % (service_name, image),
                                  ["Pulled"], "TRUE", True)

        def image_failed_to_pull_hook(image):
            cli_helpers.print_str('%s -> %s' % (service_name, image),
                                  ["Failed to pull"], "False", False)

        def image_is_local_hook(image):
            service_to_start.add(service_name)
            cli_helpers.print_str('%s -> %s' % (service_name, image),
                                  ["Exists locally"], "TRUE", True)

        def image_is_malformed_hook(image):
            cli_helpers.print_str('%s -> %s' % (service_name, image),
                                  ["Malformed image name"], "False", False)

        manager.pull_image(image_for_service, image_sucessfully_pulled_hook,
                           image_failed_to_pull_hook, image_is_local_hook,
                           image_is_malformed_hook)

    if service_to_pull > service_to_start:
        if len(service_to_start) > 0:
            if not click.confirm(
                    click.style(
                        "Not all Docker Hub images were successfully pulled for the services"
                        " you've selected, would you like to start the services that had their"
                        " images successfully pulled anyways?",
                        fg=cli_helpers.PROMPT_COLOR)):
                raise click.Abort()
        else:
            raise click.ClickException(
                click.style(
                    "None of the Docker Hub images were successfully pulled for the"
                    " services you've selected.",
                    fg="magenta"))

    # Start services for services in `service_to_start`
    logger.info(click.style("Starting services.", fg=cli_helpers.TITLE_COLOR))
    try:
        manager.start_services(
            service_to_start, cli_helpers.failed_to_start_hook,
            cli_helpers.started_hook, cli_helpers.failed_to_restart_hook,
            cli_helpers.restarted_hook, cli_helpers.failed_to_up_hook,
            cli_helpers.up_hook)
    except:
        raise click.ClickException(
            click.style("Unable to start services.", fg="magenta"))

    try:
        started_services = manager.get_running_services()
    except:
        raise click.ClickException(
            click.style("Unable to fetch running services.", fg="magenta"))

    # prompt to publish services
    published_stats = cli_helpers.prompt_to_publish(started_services,
                                                    manager,
                                                    publishing_ip,
                                                    assume_yes=assume_yes)
    for stat in published_stats:
        cli_helpers.print_str(stat[0], stat[2], "TRUE" if stat[1] else "FALSE",
                              stat[1])

    # help tip message
    logger.info(
        click.style("\nTip: (1) run ", fg=cli_helpers.PROMPT_COLOR) +
        click.style(
            "`21 publish list`", bold=True, fg=cli_helpers.PROMPT_COLOR) +
        click.style(" to see your published services.\n",
                    fg=cli_helpers.PROMPT_COLOR) +
        click.style("     (2) run ", fg=cli_helpers.PROMPT_COLOR) +
        click.style("`21 sell status --detail`",
                    bold=True,
                    fg=cli_helpers.PROMPT_COLOR) +
        click.style(" to see your microservice balances.",
                    fg=cli_helpers.PROMPT_COLOR))
Example #5
0
def start(ctx, services, all, wait_time, no_vm):
    """
Start selling a containerized service.

\b
Start selling a single service.
$ 21 sell start <service_name>

\b
Start selling all available services.
$ 21 sell start --all
"""

    # display help command if no args
    if len(services) == 0 and all is False:
        logger.info(ctx.command.get_help(ctx))
        sys.exit()

    # no-vm version coming soon
    if no_vm:
        logger.info(click.style("This mode is not yet supported.", fg="magenta"))
        sys.exit()

    # assign manager and installer from context
    manager = ctx.obj['manager']
    installer = ctx.obj['installer']

    logger.info(click.style("Checking dependencies.", fg=cli_helpers.TITLE_COLOR))
    deps_list = installer.check_dependencies()
    all_deps_installed = cli_helpers.package_check(deps_list, True)

    # install virtualbox, docker, and zerotier deps
    if not all_deps_installed:
        if click.confirm(click.style("Would you like to install the missing packages?",
                                     fg=cli_helpers.PROMPT_COLOR)):
            logger.info(click.style("Installing missing dependencies.", fg=cli_helpers.TITLE_COLOR))
            all_installed = cli_helpers.install_missing_dependencies(deps_list,
                                                                     installer)
            if not all_installed:
                sys.exit()
        else:
            sys.exit()

    # pick up docker group permissions by force logout (via user prompt)
    if cli_helpers.check_needs_logout(installer):
        sys.exit()

    # connect to zerotier virtual network
    if not manager.status_networking():
        if click.confirm(click.style(
                "ZeroTier One virtual network service is not running. Would you like to start "
                "the service?", fg=cli_helpers.PROMPT_COLOR)):
            try:
                manager.start_networking()
                cli_helpers.print_str("ZeroTier One", ["Started"], "TRUE", True)
            except Two1MachineNetworkStartException:
                cli_helpers.print_str("ZeroTier One", ["Not started"], "FALSE", False)
        else:
            sys.exit()
    # ensure docker service is running
    if manager.status_docker() is False:
        if click.confirm(click.style(
                "Docker service is not running. Would you like to start "
                "the service?", fg=cli_helpers.PROMPT_COLOR)):
            try:
                manager.start_docker()
                cli_helpers.print_str("Docker", ["Started"], "TRUE", True)
            except Two1MachineNetworkStartException:
                cli_helpers.print_str("Docker", ["Not started"], "FALSE", False)
        else:
            sys.exit()

    # join the 21market network
    if manager.get_market_address() == "":
        if click.confirm(click.style(
                "21market network not connected. Would you like to join 21market?", fg=cli_helpers.PROMPT_COLOR)):
            logger.info("You might need to enter your superuser password.")
            manager.connect_market(ctx.obj['client'])
            if manager.get_market_address() == "":
                cli_helpers.print_str("21market", ["Joined"], "TRUE", True)
            else:
                cli_helpers.print_str("21market", ["Unable to join"], "FALSE", False)
        else:
            sys.exit()
    else:
        cli_helpers.print_str("21market", ["Joined"], "TRUE", True)

    if isinstance(manager.machine, Two1MachineVirtual):
        logger.info(click.style("Checking virtual machine status.", fg=cli_helpers.TITLE_COLOR))
        just_started = False
        vm_status = manager.status_machine()
        if vm_status == VmState.NOEXIST:
            if click.confirm(click.style("  21 virtual machine does not exist. "
                                         "Would you like to create it?",
                                         fg=cli_helpers.PROMPT_COLOR)):
                vm_config = cli_helpers.get_vm_options()
                try:
                    cli_helpers.start_long_running("Creating machine (this may take a few minutes)",
                                                   manager.create_machine,
                                                   "21",
                                                   vm_config.disk_size,
                                                   vm_config.vm_memory,
                                                   vm_config.server_port,
                                                   vm_config.network_interface)
                    manager.write_machine_config(vm_config._asdict())
                    cli_helpers.print_str("21 virtual machine", ["Created"], "TRUE", True)

                except Two1MachineCreateException:
                    cli_helpers.print_str("21 virtual machine", ["Not created"], "FALSE", False)
                vm_status = manager.status_machine()
            else:
                sys.exit()

        if vm_status != VmState.RUNNING:
            if not manager.status_networking():
                if click.confirm(click.style(
                        "ZeroTier One virtual network service is not running. "
                        "Would you like to start the service?", fg=cli_helpers.PROMPT_COLOR)):
                    try:
                        manager.start_networking()
                        cli_helpers.print_str("ZeroTier One", ["Started"], "TRUE", True)
                    except Two1MachineNetworkStartException:
                        cli_helpers.print_str("ZeroTier One", ["Not started"], "FALSE", False)
                else:
                    sys.exit()
            try:
                cli_helpers.start_long_running("Starting machine (this may take a few minutes)",
                                               manager.start_machine)
                just_started = True
            except Two1MachineStartException:
                cli_helpers.print_str("21 virtual machine", ["Not started"], "FALSE", False)
                sys.exit()
            vm_status = manager.status_machine()

        # check if machine running
        if vm_status == VmState.RUNNING:
            if just_started:
                cli_helpers.print_str("21 virtual machine", ["Started"], "TRUE", True)
            else:
                cli_helpers.print_str("21 virtual machine", ["Running"], "TRUE", True)
        else:
            sys.exit()
    else:
        server_port = cli_helpers.get_server_port()
        manager.write_machine_config({"server_port": server_port})

    # generate machine wallet & initialize micropayments server
    logger.info(click.style("Initializing micropayments server.", fg=cli_helpers.TITLE_COLOR))
    username, password = cli_helpers.get_user_credentials()  # get user creds
    try:
        server_port = manager.get_server_port()
    except Exception:
        logger.info(click.style("Error: cannot read server port from file.  Please try again or contact "
                                "[email protected].", fg="magenta"))
    status_init, new_wallet_mnemonic = manager.initialize_server(username, password, server_port)
    if status_init == 0:
        # if new mnemonic has been generated
        if new_wallet_mnemonic is not None:
            logger.info(click.style("\nA unique machine wallet has been generated for your micropayments "
                                    "server.\nPlease write down the following mnemonic and store it in "
                                    "a safe place:\n", fg=cli_helpers.PROMPT_COLOR))
            logger.info(click.style("    {}\n".format(new_wallet_mnemonic), fg="magenta"))
            click.pause()
    else:
        logger.info(click.style("Error initializing micropayments server. Please try again or "
                                "contact [email protected].", fg="magenta"))
        sys.exit()

    # start microservices
    two1_services = manager.list_available_services()
    if all:
        try:
            valid_services = two1_services
        except Exception:
            logger.info(click.style("Error: unable to fetch machine images. Please try again or "
                                    "contact [email protected].", fg="magenta"))
            sys.exit()
    else:
        valid_services = []
        for serv in services:
            if serv in two1_services:
                valid_services.append(serv)

    if len(valid_services) <= 0:
        logger.info(click.style("No service available to sell. Please try again or "
                                "contact [email protected].", fg="magenta"))
        sys.exit()

    def failed_to_build_hook(service_name):
        cli_helpers.print_str(service_name, ["Failed to build"], "FALSE", False)

    def built_hook(service_name):
        cli_helpers.print_str(service_name, ["Built"], "TRUE", True)

    def failed_to_start_hook(service_name):
        cli_helpers.print_str(service_name, ["Failed to start"], "FALSE", False)

    def started_hook(service_name):
        cli_helpers.print_str(service_name, ["Started"], "TRUE", True)

    def failed_to_restart_hook(service_name):
        cli_helpers.print_str(service_name, ["Failed to restart"], "FALSE", False)

    def restarted_hook(service_name):
        cli_helpers.print_str(service_name, ["Restarted"], "TRUE", True)

    def failed_to_up_hook(service_name):
        cli_helpers.print_str(service_name, ["Failed to up"], "FALSE", False)

    def up_hook(service_name):
        cli_helpers.print_str(service_name, ["Up"], "TRUE", True)

    logger.info(click.style("Pulling latest images.", fg=cli_helpers.TITLE_COLOR))
    selected_services = list(set(['service-' + name for name in valid_services]).union(
            set(Two1Composer.BASE_SERVICES)))
    try:
        manager.pull_latest_images(selected_services)
    except Exception:
        logger.info("Unable to pull latest images.", fg="magenta")
        sys.exit()

    logger.info(click.style("Starting services.", fg=cli_helpers.TITLE_COLOR))
    try:
        manager.start_services(valid_services, failed_to_start_hook, started_hook,
                               failed_to_restart_hook, restarted_hook, failed_to_up_hook, up_hook)
    except Exception:
        logger.info("Unable to start services.", fg="magenta")
        sys.exit()

    try:
        started_services = manager.get_running_services()
    except Exception:
        logger.info("Unable to fetch running services.", fg="magenta")
        sys.exit()

    published_stats = cli_helpers.prompt_to_publish(started_services, manager)
    for stat in published_stats:
        cli_helpers.print_str(stat[0],
                              stat[2],
                              "TRUE" if stat[1] else "FALSE",
                              stat[1])

    # help tip message
    logger.info(click.style("\nTip: (1) run ", fg=cli_helpers.PROMPT_COLOR) +
                click.style("`21 publish list`", bold=True, fg=cli_helpers.PROMPT_COLOR) +
                click.style(" to see your published services.\n", fg=cli_helpers.PROMPT_COLOR) +
                click.style("     (2) run ", fg=cli_helpers.PROMPT_COLOR) +
                click.style("`21 sell status --detail`", bold=True, fg=cli_helpers.PROMPT_COLOR) +
                click.style(" to see your microservice balances.", fg=cli_helpers.PROMPT_COLOR))