def _detach(cfg: config.UAConfig, assume_yes: bool) -> int:
    """Detach the machine from the active Ubuntu Advantage subscription,

    :param cfg: a ``config.UAConfig`` instance
    :param assume_yes: Assume a yes answer to any prompts requested.
         In this case, it means automatically disable any service during
         detach.

    @return: 0 on success, 1 otherwise
    """
    to_disable = []
    for ent_cls in entitlements.ENTITLEMENT_CLASSES:
        ent = ent_cls(cfg)
        if ent.can_disable(silent=True):
            to_disable.append(ent)
    if to_disable:
        suffix = "s" if len(to_disable) > 1 else ""
        print("Detach will disable the following service{}:".format(suffix))
        for ent in to_disable:
            print("    {}".format(ent.name))
    if not util.prompt_for_confirmation(assume_yes=assume_yes):
        return 1
    for ent in to_disable:
        ent.disable(silent=True)
    contract_client = contract.UAContractClient(cfg)
    machine_token = cfg.machine_token["machineToken"]
    contract_id = cfg.machine_token["machineTokenInfo"]["contractInfo"]["id"]
    contract_client.detach_machine_from_contract(machine_token, contract_id)
    cfg.delete_cache()
    print(ua_status.MESSAGE_DETACH_SUCCESS)
    return 0
示例#2
0
def action_detach(args, cfg):
    """Perform the detach action for this machine.

    @return: 0 on success, 1 otherwise
    """
    to_disable = []
    for ent_cls in entitlements.ENTITLEMENT_CLASSES:
        ent = ent_cls(cfg)
        if ent.can_disable(silent=True):
            to_disable.append(ent)
    if to_disable:
        suffix = "s" if len(to_disable) > 1 else ""
        print("Detach will disable the following service{}:".format(suffix))
        for ent in to_disable:
            print("    {}".format(ent.name))
    if not args.assume_yes and not util.prompt_for_confirmation():
        return 1
    for ent in to_disable:
        ent.disable(silent=True)
    contract_client = contract.UAContractClient(cfg)
    machine_token = cfg.machine_token["machineToken"]
    contract_id = cfg.machine_token["machineTokenInfo"]["contractInfo"]["id"]
    contract_client.detach_machine_from_contract(machine_token, contract_id)
    cfg.delete_cache()
    print(ua_status.MESSAGE_DETACH_SUCCESS)
    return 0
示例#3
0
    def _enable_required_services(
        self,
    ) -> Tuple[bool, Optional[messages.NamedMessage]]:
        """
        Prompt user when required services are found during enable.

        When enabling a service, we may find that there are required services
        that must be enabled first. In that situation, we can ask the user
        if the required service should be enabled before proceeding.
        """
        from uaclient.entitlements import entitlement_factory

        for required_service in self.required_services:
            try:
                ent_cls = entitlement_factory(
                    cfg=self.cfg, name=required_service
                )
            except exceptions.EntitlementNotFoundError:
                msg = messages.REQUIRED_SERVICE_NOT_FOUND.format(
                    service=required_service
                )
                return False, msg

            ent = ent_cls(self.cfg, allow_beta=True)

            is_service_disabled = (
                ent.application_status()[0] == ApplicationStatus.DISABLED
            )

            if is_service_disabled:
                user_msg = messages.REQUIRED_SERVICE.format(
                    service_being_enabled=self.title,
                    required_service=ent.title,
                )

                e_msg = messages.REQUIRED_SERVICE_STOPS_ENABLE.format(
                    service_being_enabled=self.title,
                    required_service=ent.title,
                )

                if not util.prompt_for_confirmation(
                    msg=user_msg, assume_yes=self.assume_yes
                ):
                    return False, e_msg

                event.info("Enabling required service: {}".format(ent.title))
                ret, fail = ent.enable(silent=True)
                if not ret:
                    error_msg = ""
                    if fail.message and fail.message.msg:
                        error_msg = "\n" + fail.message.msg

                    msg = messages.ERROR_ENABLING_REQUIRED_SERVICE.format(
                        error=error_msg, service=ent.title
                    )
                    return ret, msg

        return True, None
示例#4
0
    def handle_incompatible_services(
        self,
    ) -> Tuple[bool, Optional[messages.NamedMessage]]:
        """
        Prompt user when incompatible services are found during enable.

        When enabling a service, we may find that there is an incompatible
        service already enable. In that situation, we can ask the user
        if the incompatible service should be disabled before proceeding.
        There are also different ways to configure that behavior:

        We can disable removing incompatible service during enable by
        adding the following lines into uaclient.conf:

        features:
          block_disable_on_enable: true
        """
        cfg_block_disable_on_enable = util.is_config_value_true(
            config=self.cfg.cfg,
            path_to_value="features.block_disable_on_enable",
        )
        for service in self.blocking_incompatible_services():
            ent = service.entitlement(self.cfg, assume_yes=True)

            user_msg = messages.INCOMPATIBLE_SERVICE.format(
                service_being_enabled=self.title,
                incompatible_service=ent.title,
            )

            e_msg = messages.INCOMPATIBLE_SERVICE_STOPS_ENABLE.format(
                service_being_enabled=self.title,
                incompatible_service=ent.title,
            )

            if cfg_block_disable_on_enable:
                return False, e_msg

            if not util.prompt_for_confirmation(
                msg=user_msg, assume_yes=self.assume_yes
            ):
                return False, e_msg

            disable_msg = "Disabling incompatible service: {}".format(
                ent.title
            )
            event.info(disable_msg)

            ret = ent.disable(silent=True)
            if not ret:
                return ret, None

        return True, None
示例#5
0
def action_detach(args, cfg):
    """Perform the detach action for this machine.

    @return: 0 on success, 1 otherwise
    """
    to_disable = []
    for ent_cls in entitlements.ENTITLEMENT_CLASSES:
        ent = ent_cls(cfg)
        if ent.can_disable(silent=True):
            to_disable.append(ent)
    if to_disable:
        suffix = "s" if len(to_disable) > 1 else ""
        print("Detach will disable the following service{}:".format(suffix))
        for ent in to_disable:
            print("    {}".format(ent.name))
    if not util.prompt_for_confirmation():
        return 1
    for ent in to_disable:
        ent.disable(silent=True)
    cfg.delete_cache()
    print(ua_status.MESSAGE_DETACH_SUCCESS)
    return 0
示例#6
0
    def _disable_dependent_services(
        self, silent: bool
    ) -> Tuple[bool, Optional[messages.NamedMessage]]:
        """
        Disable dependent services

        When performing a disable operation, we might have
        other services that depend on the original services.
        If that is true, we will alert the user about this
        and prompt for confirmation to disable these services
        as well.

        @param silent: Boolean set True to silence print/log of messages
        """
        from uaclient.entitlements import entitlement_factory

        for dependent_service in self.dependent_services:
            try:
                ent_cls = entitlement_factory(
                    cfg=self.cfg, name=dependent_service
                )
            except exceptions.EntitlementNotFoundError:
                msg = messages.DEPENDENT_SERVICE_NOT_FOUND.format(
                    service=dependent_service
                )
                event.info(info_msg=msg.msg, file_type=sys.stderr)
                return False, msg

            ent = ent_cls(cfg=self.cfg, assume_yes=True)

            is_service_enabled = (
                ent.application_status()[0] == ApplicationStatus.ENABLED
            )

            if is_service_enabled:
                user_msg = messages.DEPENDENT_SERVICE.format(
                    dependent_service=ent.title,
                    service_being_disabled=self.title,
                )

                e_msg = messages.DEPENDENT_SERVICE_STOPS_DISABLE.format(
                    service_being_disabled=self.title,
                    dependent_service=ent.title,
                )

                if not util.prompt_for_confirmation(
                    msg=user_msg, assume_yes=self.assume_yes
                ):
                    return False, e_msg

                if not silent:
                    event.info(
                        messages.DISABLING_DEPENDENT_SERVICE.format(
                            required_service=ent.title
                        )
                    )

                ret, fail = ent.disable(silent=True)
                if not ret:
                    error_msg = ""
                    if fail.message and fail.message.msg:
                        error_msg = "\n" + fail.message.msg

                    msg = messages.FAILED_DISABLING_DEPENDENT_SERVICE.format(
                        error=error_msg, required_service=ent.title
                    )
                    return False, msg

        return True, None
示例#7
0
    def test_prompt_text(self, m_input, assume_yes, message, input_calls):
        util.prompt_for_confirmation(msg=message, assume_yes=assume_yes)

        assert input_calls == m_input.call_args_list
示例#8
0
 def test_input_conversion(self, m_input, return_value, user_input):
     m_input.return_value = user_input
     assert return_value == util.prompt_for_confirmation()
    def test_prompt_text(self, m_input):
        util.prompt_for_confirmation()

        assert [mock.call("Are you sure? (y/N) ")] == m_input.call_args_list