Beispiel #1
0
    def delete(self, name, force=None):
        """Delete the application with the given name

        :param name: application name
        """
        try:
            db_app = objects.kube_app.get_by_name(pecan.request.context, name)
        except exception.KubeAppNotFound:
            LOG.error("Received a request to delete app %s which does not "
                      "exist." % name)
            raise wsme.exc.ClientSideError(
                _("Application-delete rejected: application not found."))

        if db_app.status not in [
                constants.APP_UPLOAD_SUCCESS, constants.APP_UPLOAD_FAILURE
        ]:
            raise wsme.exc.ClientSideError(
                _("Application-delete rejected: operation is not allowed "
                  "while the current status is {}.".format(db_app.status)))

        try:
            lifecycle_hook_info = LifecycleHookInfo()
            lifecycle_hook_info.init(
                constants.APP_LIFECYCLE_MODE_MANUAL,
                constants.APP_LIFECYCLE_TYPE_SEMANTIC_CHECK,
                constants.APP_LIFECYCLE_TIMING_PRE, constants.APP_DELETE_OP)
            # Converting string to boolean
            if force == 'True':
                force = True
            else:
                force = False

            lifecycle_hook_info.extra = {
                constants.APP_LIFECYCLE_FORCE_OPERATION: force
            }
            self._app_lifecycle_actions(db_app, lifecycle_hook_info)
        except rpc_common.RemoteError as e:
            raise wsme.exc.ClientSideError(
                _("Application-delete rejected: " + str(e.value)))
        except Exception as e:
            raise wsme.exc.ClientSideError(
                _("Application-delete rejected: " + six.text_type(e)))

        lifecycle_hook_info = LifecycleHookInfo()
        lifecycle_hook_info.mode = constants.APP_LIFECYCLE_MODE_MANUAL

        response = pecan.request.rpcapi.perform_app_delete(
            pecan.request.context,
            db_app,
            lifecycle_hook_info=lifecycle_hook_info)
        if response:
            raise wsme.exc.ClientSideError(_("%s." % response))
Beispiel #2
0
    def update(self, body):
        """Update the applied application to a different version"""
        tarfile = body.get('tarfile')
        name = body.get('name', '')
        version = body.get('app_version', '')
        name, version, mname, mfile = self._check_tarfile(
            tarfile, name, version, constants.APP_UPDATE_OP)

        reuse_overrides_flag = body.get('reuse_user_overrides', None)
        if reuse_overrides_flag is None:
            # None means let the application decide
            reuse_overrides = None
        elif reuse_overrides_flag in ['true', 'True']:
            reuse_overrides = True
        elif reuse_overrides_flag in ['false', 'False']:
            reuse_overrides = False
        else:
            raise wsme.exc.ClientSideError(
                _("Application-update rejected: "
                  "invalid reuse_user_overrides setting."))

        try:
            applied_app = objects.kube_app.get_by_name(pecan.request.context,
                                                       name)
        except exception.KubeAppNotFound:
            LOG.error(
                "Received a request to update app %s which does not exist." %
                name)
            raise wsme.exc.ClientSideError(
                _("Application-update rejected: application not found."))

        try:
            lifecycle_hook_info = LifecycleHookInfo()
            lifecycle_hook_info.init(
                constants.APP_LIFECYCLE_MODE_MANUAL,
                constants.APP_LIFECYCLE_TYPE_SEMANTIC_CHECK,
                constants.APP_LIFECYCLE_TIMING_PRE, constants.APP_UPDATE_OP)
            self._app_lifecycle_actions(applied_app, lifecycle_hook_info)
        except Exception as e:
            raise wsme.exc.ClientSideError(
                _("Application-update rejected: " + str(e.message)))

        if applied_app.status == constants.APP_UPDATE_IN_PROGRESS:
            raise wsme.exc.ClientSideError(
                _("Application-update rejected: update is already "
                  "in progress."))
        elif applied_app.status != constants.APP_APPLY_SUCCESS:
            raise wsme.exc.ClientSideError(
                _("Application-update rejected: operation is not allowed "
                  "while the current status is {}.".format(
                      applied_app.status)))

        if applied_app.app_version == version:
            raise wsme.exc.ClientSideError(
                _("Application-update rejected: the version %s is already "
                  "applied." % version))
        # Set the status for the current applied app to inactive
        applied_app.status = constants.APP_INACTIVE_STATE
        applied_app.progress = None
        applied_app.save()

        # If the version has ever applied before(inactive app found),
        # use armada rollback to apply application later, otherwise,
        # use armada apply.
        # On the AIO-SX, always use armada apply even it was applied
        # before, issue on AIO-SX(replicas is 1) to leverage rollback,
        # armada/helm rollback --wait does not wait for pods to be
        # ready before it returns.
        # related to helm issue,
        # https://github.com/helm/helm/issues/4210
        # https://github.com/helm/helm/issues/2006
        try:
            target_app = objects.kube_app.get_inactive_app_by_name_version(
                pecan.request.context, name, version)
            target_app.status = constants.APP_UPDATE_IN_PROGRESS
            target_app.save()
            if cutils.is_aio_simplex_system(pecan.request.dbapi):
                operation = constants.APP_APPLY_OP
            else:
                operation = constants.APP_ROLLBACK_OP
        except exception.KubeAppInactiveNotFound:
            target_app_data = {
                'name': name,
                'app_version': version,
                'manifest_name': mname,
                'manifest_file': os.path.basename(mfile),
                'status': constants.APP_UPDATE_IN_PROGRESS,
                'active': True
            }
            operation = constants.APP_APPLY_OP

            try:
                target_app = pecan.request.dbapi.kube_app_create(
                    target_app_data)
            except exception.KubeAppAlreadyExists as e:
                applied_app.status = constants.APP_APPLY_SUCCESS
                applied_app.progress = constants.APP_PROGRESS_COMPLETED
                applied_app.save()
                LOG.exception(e)
                raise wsme.exc.ClientSideError(
                    _("Application-update failed: Unable to start application update, "
                      "application info update failed."))

        lifecycle_hook_info = LifecycleHookInfo()
        lifecycle_hook_info.mode = constants.APP_LIFECYCLE_MODE_MANUAL

        pecan.request.rpcapi.perform_app_update(pecan.request.context,
                                                applied_app, target_app,
                                                tarfile, operation,
                                                lifecycle_hook_info,
                                                reuse_overrides)

        return KubeApp.convert_with_links(target_app)
Beispiel #3
0
    def patch(self, name, directive, values):
        """Install/update the specified application

        :param name: application name
        :param directive: either 'apply' (fresh install/update), 'remove' or 'abort'
        """
        if directive not in ['apply', 'remove', 'abort']:
            raise exception.OperationNotPermitted

        try:
            db_app = objects.kube_app.get_by_name(pecan.request.context, name)
        except exception.KubeAppNotFound:
            LOG.error("Received a request to %s app %s which does not exist." %
                      (directive, name))
            raise wsme.exc.ClientSideError(
                _("Application-{} rejected: application not found.".format(
                    directive)))

        if directive == 'apply':
            if not values:
                mode = None
            elif name not in constants.HELM_APP_APPLY_MODES.keys():
                raise wsme.exc.ClientSideError(
                    _("Application-apply rejected: Mode is not supported "
                      "for app {}.".format(name)))
            elif (values['mode'] and values['mode']
                  not in constants.HELM_APP_APPLY_MODES[name]):
                raise wsme.exc.ClientSideError(
                    _("Application-apply rejected: Mode {} for app {} is not "
                      "valid. Valid modes are {}.".format(
                          values['mode'], name,
                          constants.HELM_APP_APPLY_MODES[name])))
            else:
                mode = values['mode']

            try:
                app_helper = KubeAppHelper(pecan.request.dbapi)
                app_helper._check_app_compatibility(db_app.name,
                                                    db_app.app_version)
            except exception.IncompatibleKubeVersion as e:
                raise wsme.exc.ClientSideError(
                    _("Application-apply rejected: " + str(e)))

            if db_app.status == constants.APP_APPLY_IN_PROGRESS:
                raise wsme.exc.ClientSideError(
                    _("Application-apply rejected: install/update is already "
                      "in progress."))
            elif db_app.status not in [
                    constants.APP_UPLOAD_SUCCESS, constants.APP_APPLY_FAILURE,
                    constants.APP_APPLY_SUCCESS
            ]:
                raise wsme.exc.ClientSideError(
                    _("Application-apply rejected: operation is not allowed "
                      "while the current status is {}.".format(db_app.status)))

            try:
                lifecycle_hook_info = LifecycleHookInfo()
                lifecycle_hook_info.init(
                    constants.APP_LIFECYCLE_MODE_MANUAL,
                    constants.APP_LIFECYCLE_TYPE_SEMANTIC_CHECK,
                    constants.APP_LIFECYCLE_TIMING_PRE, constants.APP_APPLY_OP)
                self._app_lifecycle_actions(db_app, lifecycle_hook_info)
            except Exception as e:
                raise wsme.exc.ClientSideError(
                    _("Application-apply rejected: " + str(e.message)))

            db_app.status = constants.APP_APPLY_IN_PROGRESS
            db_app.progress = None
            db_app.recovery_attempts = 0
            db_app.mode = mode
            db_app.save()

            lifecycle_hook_info = LifecycleHookInfo()
            lifecycle_hook_info.mode = constants.APP_LIFECYCLE_MODE_MANUAL

            pecan.request.rpcapi.perform_app_apply(
                pecan.request.context,
                db_app,
                mode=mode,
                lifecycle_hook_info=lifecycle_hook_info)
        elif directive == 'remove':
            if db_app.status not in [
                    constants.APP_APPLY_SUCCESS, constants.APP_APPLY_FAILURE,
                    constants.APP_REMOVE_FAILURE
            ]:
                raise wsme.exc.ClientSideError(
                    _("Application-remove rejected: operation is not allowed while "
                      "the current status is {}.".format(db_app.status)))

            try:
                lifecycle_hook_info = LifecycleHookInfo()
                lifecycle_hook_info.init(
                    constants.APP_LIFECYCLE_MODE_MANUAL,
                    constants.APP_LIFECYCLE_TYPE_SEMANTIC_CHECK,
                    constants.APP_LIFECYCLE_TIMING_PRE,
                    constants.APP_REMOVE_OP)
                self._app_lifecycle_actions(db_app, lifecycle_hook_info)
            except Exception as e:
                raise wsme.exc.ClientSideError(
                    _("Application-remove rejected: " + str(e.message)))

            db_app.status = constants.APP_REMOVE_IN_PROGRESS
            db_app.progress = None
            db_app.save()

            lifecycle_hook_info = LifecycleHookInfo()
            lifecycle_hook_info.mode = constants.APP_LIFECYCLE_MODE_MANUAL

            pecan.request.rpcapi.perform_app_remove(
                pecan.request.context,
                db_app,
                lifecycle_hook_info=lifecycle_hook_info)
        else:
            if db_app.status not in [
                    constants.APP_APPLY_IN_PROGRESS,
                    constants.APP_UPDATE_IN_PROGRESS,
                    constants.APP_REMOVE_IN_PROGRESS
            ]:
                raise wsme.exc.ClientSideError(
                    _("Application-abort rejected: operation is not allowed while "
                      "the current status is {}.".format(db_app.status)))

            try:
                lifecycle_hook_info = LifecycleHookInfo()
                lifecycle_hook_info.init(
                    constants.APP_LIFECYCLE_MODE_MANUAL,
                    constants.APP_LIFECYCLE_TYPE_SEMANTIC_CHECK,
                    constants.APP_LIFECYCLE_TIMING_PRE, constants.APP_ABORT_OP)
                self._app_lifecycle_actions(db_app, lifecycle_hook_info)
            except Exception as e:
                raise wsme.exc.ClientSideError(
                    _("Application-abort rejected: " + str(e.message)))

            lifecycle_hook_info = LifecycleHookInfo()
            lifecycle_hook_info.mode = constants.APP_LIFECYCLE_MODE_MANUAL

            pecan.request.rpcapi.perform_app_abort(
                pecan.request.context,
                db_app,
                lifecycle_hook_info=lifecycle_hook_info)
        return KubeApp.convert_with_links(db_app)