Beispiel #1
0
class ExecutionStepsView(generic.CRUDView):

    NAME = "execution_step"
    MODEL_NAME = "execution_step"

    decorators = [
        auth.require_authorization("api", "view_execution"),
        auth.require_authorization("api", "view_execution_steps"),
        auth.require_authentication
    ]

    @classmethod
    def register_to(cls, application):
        main_endpoint = generic.make_endpoint(
            ExecutionView.ENDPOINT,
            "<{0}:item_id>".format(ExecutionView.PARAMETER_TYPE),
            "steps"
        )

        application.add_url_rule(
            main_endpoint,
            view_func=cls.as_view(cls.NAME), methods=["GET"]
        )

    @validators.with_model(execution.ExecutionModel)
    def get(self, item_id, item):
        return execution_step.ExecutionStep.list_models(
            str(item_id), self.pagination
        )
Beispiel #2
0
class ExecutionStepsLog(generic.View):

    NAME = "execution_step_log"

    decorators = [
        auth.require_authorization("api", "view_execution"),
        auth.require_authorization("api", "view_execution_steps"),
        auth.require_authentication
    ]

    @classmethod
    def register_to(cls, application):
        main_endpoint = generic.make_endpoint(
            ExecutionView.ENDPOINT,
            "<{0}:item_id>".format(ExecutionView.PARAMETER_TYPE),
            "log"
        )

        application.add_url_rule(
            main_endpoint,
            view_func=cls.as_view(cls.NAME), methods=["GET"]
        )

    @validators.with_model(execution.ExecutionModel)
    def get(self, item_id, item):
        logfile = item.logfile
        if not logfile:
            raise http_exceptions.NotFound()

        download = self.request_query.get("download", "no")
        try:
            download = distutils.util.strtobool(download)
        except Exception:
            download = False

        request_json = False
        for header in "Accept", "Content-Type":
            header = self.request_headers.get(header) or ""
            if header == "application/json":
                request_json = True
                break

        if not download and request_json:
            def generator():
                fileobj = codecs.getreader("utf-8")(logfile, errors="ignore")
                result = fileobj.read(1024)
                while result:
                    yield result
                    result = fileobj.read(1024)

            return {"data": "".join(generator())}

        response = generic.fs_response(logfile, download,
                                       cache_for=LOG_CACHE_TIMEOUT)
        response = response.make_conditional(flask.request.environ)

        return response
Beispiel #3
0
def require_create_server_authorization(func):
    """Special authorization decorator for server create."""

    normal_decorated_func = auth.require_authorization("api", "create_server")
    normal_decorated_func = normal_decorated_func(func)
    normal_decorated_func = auth.require_authentication(normal_decorated_func)

    @functools.wraps(func)
    def decorator(*args, **kwargs):
        token_id = flask.request.headers.get("Authorization")
        if token_id == CONF["api"]["server_discovery_token"]:
            return func(*args, **kwargs)
        return normal_decorated_func(*args, **kwargs)

    return decorator
Beispiel #4
0
class PermissionView(generic.ModelView):

    decorators = [
        auth.require_authorization("api", "view_role"),
        auth.require_authentication
    ]

    NAME = "permission"
    ENDPOINT = "/permission/"

    def get(self):
        known_permissions = [{
            "name": key,
            "permissions": sorted(value)
        } for key, value in role.PermissionSet.KNOWN_PERMISSIONS.items()]

        return {"items": known_permissions}
Beispiel #5
0
class PlaybookConfigurationView(generic.VersionedCRUDView):
    """Implementation of view for /v1/playbook_configuration API."""

    decorators = [
        auth.require_authorization("api", "view_playbook_configuration"),
        auth.require_authentication
    ]

    NAME = "playbook_configuration"
    MODEL_NAME = "playbook_configuration"
    ENDPOINT = "/playbook_configuration/"
    PARAMETER_TYPE = "uuid"

    def get_all(self):
        return playbook_configuration.PlaybookConfigurationModel.list_models(
            self.pagination
        )

    @validators.with_model(playbook_configuration.PlaybookConfigurationModel)
    def get_item(self, item_id, item, *args):
        return item

    @auth.require_authorization("api", "view_playbook_configuration_version")
    def get_versions(self, item_id):
        return playbook_configuration.PlaybookConfigurationModel.list_versions(
            str(item_id), self.pagination
        )

    @auth.require_authorization("api", "view_playbook_configuration_version")
    def get_version(self, item_id, version):
        model = playbook_configuration.PlaybookConfigurationModel.find_version(
            str(item_id), int(version)
        )

        if not model:
            LOG.info("Cannot find model with ID %s", item_id)
            raise http_exceptions.NotFound

        return model

    @auth.require_authorization("api", "edit_playbook_configuration")
    @validators.with_model(playbook_configuration.PlaybookConfigurationModel)
    @validators.require_schema(MODEL_SCHEMA)
    @validators.no_updates_on_default_fields
    def put(self, item_id, item):
        for fieldname in "configuration", "name":
            if fieldname in self.request_json["data"]:
                setattr(item, fieldname, self.request_json["data"][fieldname])

        item.initiator_id = self.initiator_id

        try:
            item.save()
        except base_exceptions.CannotUpdateDeletedModel as exc:
            LOG.warning(
                "Cannot update playbook configuration %s (deleted at %s, "
                "version %s)",
                item_id, item.time_deleted, item.version
            )
            raise http_exceptions.CannotUpdateDeletedModel() from exc
        except base_exceptions.UniqueConstraintViolationError as exc:
            LOG.warning("Cannot update playbook configuration %s "
                        "(unique constraint violation)",
                        self.request_json["data"]["name"])
            raise http_exceptions.CannotUpdateModelWithSuchParameters() \
                from exc

        LOG.info("Playbook configuration %s was updated by %s",
                 item_id, self.initiator_id)

        return item

    @auth.require_authorization("api", "create_playbook_configuration")
    @validators.require_schema(POST_SCHEMA)
    def post(self):
        cluster_model = self.get_cluster_model(self.request_json["cluster_id"])
        servers_for_playbook = self.get_servers_for_playbook(
            self.request_json["playbook_id"],
            self.request_json["server_ids"],
            cluster_model
        )

        try:
            pcmodel = playbook_configuration.PlaybookConfigurationModel.create(
                name=self.request_json["name"],
                playbook_id=self.request_json["playbook_id"],
                cluster=cluster_model,
                servers=servers_for_playbook,
                initiator_id=self.initiator_id
            )
        except base_exceptions.UniqueConstraintViolationError as exc:
            LOG.warning(
                "Cannot create cluster %s (unique constraint "
                "violation)",
                self.request_json["name"]
            )
            raise http_exceptions.ImpossibleToCreateSuchModel() from exc

        LOG.info("Playbook configuration %s (%s) created by %s",
                 self.request_json["name"], pcmodel.model_id,
                 self.initiator_id)

        return pcmodel

    @auth.require_authorization("api", "delete_playbook_confuiguration")
    @validators.with_model(playbook_configuration.PlaybookConfigurationModel)
    def delete(self, item_id, item):
        try:
            item.delete()
        except base_exceptions.CannotUpdateDeletedModel as exc:
            LOG.warning("Cannot delete deleted role %s", item_id)
            raise http_exceptions.CannotUpdateDeletedModel() from exc

        LOG.info("Playbook configuration %s was deleted by %s",
                 item_id, self.initiator_id)

        return item

    def get_servers_for_playbook(self, playbook_id, suggested_servers,
                                 cluster_model):
        plugs = plugins.get_public_playbook_plugins()
        if playbook_id not in plugs:
            raise http_exceptions.UnknownPlaybookError(playbook_id)

        plug = plugs[playbook_id]()
        if plug.REQUIRED_SERVER_LIST:
            if not suggested_servers:
                raise http_exceptions.ServerListIsRequiredForPlaybookError(
                    playbook_id
                )

            servers = server.ServerModel.find_by_model_id(*suggested_servers)
            if not isinstance(servers, list):
                servers = [servers]
            if len(servers) != len(set(suggested_servers)):
                raise ValueError(
                    "All suggested servers were not found. "
                    "Suggested servers were {0}".format(suggested_servers))

            deleted_servers = [srv for srv in servers if srv.time_deleted]
            if deleted_servers:
                raise ValueError(
                    "Some servers were deleted: {0}".format(
                        ", ".join(srv.model_id for srv in deleted_servers)))
            return servers

        return cluster_model.server_list

    def get_cluster_model(self, cluster_id):
        cluster_model = cluster.ClusterModel.find_by_model_id(cluster_id)

        if not (cluster_model and not cluster_model.time_deleted):
            raise http_exceptions.UnknownClusterError(cluster_id)

        return cluster_model
Beispiel #6
0
class ExecutionView(generic.VersionedCRUDView):
    """Implementation of view for /v1/execution API."""

    decorators = [
        auth.require_authorization("api", "view_execution"),
        auth.require_authentication
    ]

    NAME = "execution"
    MODEL_NAME = "execution"
    ENDPOINT = "/execution/"
    PARAMETER_TYPE = "uuid"

    def get_all(self):
        return execution.ExecutionModel.list_models(self.pagination)

    @validators.with_model(execution.ExecutionModel)
    def get_item(self, item_id, item, *args):
        return item

    @auth.require_authorization("api", "view_execution_version")
    def get_versions(self, item_id):
        return execution.ExecutionModel.list_versions(
            str(item_id), self.pagination
        )

    def get_version(self, item_id, version):
        model = execution.ExecutionModel.find_version(
            str(item_id), int(version)
        )

        if not model:
            LOG.info("Cannot find model with ID %s", item_id)
            raise http_exceptions.NotFound

        return model

    @auth.require_authorization("api", "create_execution")
    @validators.require_schema(POST_SCHEMA)
    def post(self):
        pc_id = self.request_json["playbook_configuration"]["id"]
        pc_version = self.request_json["playbook_configuration"]["version"]

        config = playbook_configuration.PlaybookConfigurationModel
        config = config.find_version(pc_id, pc_version)
        if not config:
            LOG.warning(
                "Cannot find playbook configuration %s of version %s",
                pc_id, pc_version
            )
            raise http_exceptions.UnknownPlaybookConfiguration(
                pc_id, pc_version
            )

        auth.check_auth_permission(flask.g.token.user,
                                   "playbook", config.playbook_id)

        model = execution.ExecutionModel.create(config, self.initiator_id)
        LOG.info(
            "Created execution %s for playbook configuration %s of "
            "version %s",
            model.model_id, config.model_id, config.version
        )

        try:
            tsk = task.PlaybookPluginTask(
                config.playbook_id, config._id, model.model_id
            )
            tsk.create()
        except Exception as exc:
            LOG.error("Cannot create task for execution %s: %s",
                      model.model_id, exc)
            model.state = execution.ExecutionState.failed
            model.save()
            raise
        else:
            LOG.info("Created task for execution %s: %s",
                     model.model_id, tsk._id)

        return model

    @auth.require_authorization("api", "delete_execution")
    @validators.with_model(execution.ExecutionModel)
    def delete(self, item_id, item):
        if item.state == execution.ExecutionState.created:
            try:
                return self.cancel_created_execution(item)
            except base_exceptions.UniqueConstraintViolationError:
                LOG.debug("Execution %s already changed it's state")
                item = execution.ExecutionModel.find_by_model_id(item_id)

        if item.state == execution.ExecutionState.started:
            item = self.cancel_started_execution(item)

        return item

    def cancel_created_execution(self, item):
        item.initiator_id = self.initiator_id
        item.state = execution.ExecutionState.canceled
        item.save()

        LOG.info("Not started execution %s was canceled", item.model_id)

        return item

    def cancel_started_execution(self, item):
        item.initiator_id = self.initiator_id
        item.state = execution.ExecutionState.canceling
        item.save()

        LOG.info("Execution %s is cancelling now", item.model_id)

        tsk = task.CancelPlaybookPluginTask(item.model_id)
        tsk.create()

        LOG.info("Task for cancelling execution %s is %s",
                 item.model_id, tsk._id)

        return item
Beispiel #7
0
class RoleView(generic.VersionedCRUDView):
    """Implementation of view for /v1/role API."""

    decorators = [
        auth.require_authorization("api", "view_role"),
        auth.require_authentication
    ]

    NAME = "role"
    MODEL_NAME = "role"
    ENDPOINT = "/role/"
    PARAMETER_TYPE = "uuid"

    def get_all(self):
        return role.RoleModel.list_models(self.pagination)

    @validators.with_model(role.RoleModel)
    def get_item(self, item_id, item, *args):
        return item

    @auth.require_authorization("api", "view_role_versions")
    def get_versions(self, item_id):
        return role.RoleModel.list_versions(str(item_id), self.pagination)

    @auth.require_authorization("api", "view_role_versions")
    def get_version(self, item_id, version):
        model = role.RoleModel.find_version(str(item_id), int(version))

        if not model:
            LOG.info("Cannot find model with ID %s", item_id)
            raise http_exceptions.NotFound

        return model

    @auth.require_authorization("api", "edit_role")
    @validators.with_model(role.RoleModel)
    @validators.require_schema(MODEL_SCHEMA)
    @validators.no_updates_on_default_fields
    def put(self, item_id, item):
        try:
            for key, value in self.request_json["data"].items():
                setattr(item, key, value)
            item.initiator_id = self.initiator_id
            item.save()
        except base_exceptions.CannotUpdateDeletedModel as exc:
            LOG.warning(
                "Cannot update deleted role %s (deleted at %s, "
                "version %s)",
                item_id, item.time_deleted, item.version
            )
            raise http_exceptions.CannotUpdateDeletedModel() from exc
        except base_exceptions.UniqueConstraintViolationError as exc:
            LOG.warning("Cannot update role %s (unique constraint "
                        "violation)", self.request_json["data"]["name"])
            raise http_exceptions.CannotUpdateModelWithSuchParameters() \
                from exc
        except ValueError as exc:
            LOG.warning("Incorrect permissions for role %s: %s",
                        item_id, exc)
            raise http_exceptions.BadRequest from exc

        LOG.info("Role %s was updated by %s", item_id, self.initiator_id)

        return item

    @auth.require_authorization("api", "create_role")
    @validators.require_schema(POST_SCHEMA)
    def post(self):
        try:
            role_model = role.RoleModel.make_role(
                self.request_json["name"],
                self.request_json["permissions"],
                initiator_id=self.initiator_id
            )
        except base_exceptions.UniqueConstraintViolationError as exc:
            LOG.warning("Cannot create role %s (unique constraint violation)",
                        self.request_json["name"])
            raise http_exceptions.ImpossibleToCreateSuchModel() from exc
        except base_exceptions.UniqueConstraintViolationError as exc:
            raise http_exceptions.UniqueConstraintViolationError() from exc
        except ValueError as exc:
            LOG.warning("Incorrect permissions for role %s: %s",
                        self.request_json["name"], exc)
            raise http_exceptions.BadRequest from exc

        LOG.info("Role %s (%s) created by %s",
                 self.request_json["name"], role_model.model_id,
                 self.initiator_id)

        return role_model

    @auth.require_authorization("api", "delete_role")
    @validators.with_model(role.RoleModel)
    def delete(self, item_id, item):
        try:
            item.delete()
        except base_exceptions.CannotUpdateDeletedModel as exc:
            LOG.warning("Cannot delete deleted role %s", item_id)
            raise http_exceptions.CannotUpdateDeletedModel() from exc
        except base_exceptions.CannotDeleteRoleWithActiveUsers as exc:
            LOG.warning("Cannot delete role %s with active users", item_id)
            raise http_exceptions.CannotDeleteRoleWithActiveUsers() from exc

        LOG.info("Role %s was deleted by %s", item_id, self.initiator_id)

        return item
Beispiel #8
0
class UserView(generic.VersionedCRUDView):
    """Implementation of view for /v1/user/."""

    decorators = [
        auth.require_authorization("api", "view_user"),
        auth.require_authentication
    ]

    NAME = "user"
    MODEL_NAME = "user"
    ENDPOINT = "/user/"
    PARAMETER_TYPE = "uuid"

    def get_all(self):
        return user.UserModel.list_models(self.pagination)

    @validators.with_model(user.UserModel)
    def get_item(self, item_id, item, *args):
        return item

    @auth.require_authorization("api", "view_user_versions")
    def get_versions(self, item_id):
        return user.UserModel.list_versions(str(item_id), self.pagination)

    @auth.require_authorization("api", "view_user_versions")
    def get_version(self, item_id, version):
        model = user.UserModel.find_version(str(item_id), int(version))

        if not model:
            LOG.warning("Cannot find version %s of user model %s", version,
                        item_id)
            raise http_exceptions.NotFound

        return model

    @auth.require_authorization("api", "edit_user")
    @validators.with_model(user.UserModel)
    @validators.require_schema(MODEL_SCHEMA)
    @validators.no_updates_on_default_fields
    def put(self, item_id, item):
        for key, value in self.request_json["data"].items():
            setattr(item, key, value)
        item.initiator_id = self.initiator_id

        try:
            item.save()
        except base_exceptions.CannotUpdateDeletedModel as exc:
            LOG.warning(
                "Cannot update deleted model %s (deleted at %s, "
                "version %s)", item.model_id, item.time_deleted, item.version)
            raise http_exceptions.CannotUpdateDeletedModel() from exc
        except base_exceptions.UniqueConstraintViolationError as exc:
            LOG.warning(
                "Cannot update user %s (unique constraint "
                "violation)", self.request_json["data"]["login"])
            raise http_exceptions.CannotUpdateModelWithSuchParameters() \
                from exc

        LOG.info("User model %s was updated to version %s by %s",
                 item.model_id, item.version, self.initiator_id)

        return item

    @auth.require_authorization("api", "create_user")
    @validators.require_schema(POST_SCHEMA)
    def post(self):
        new_password = passwords.generate_password()

        try:
            user_model = user.UserModel.make_user(
                self.request_json["login"],
                new_password,
                self.request_json["email"],
                self.request_json["full_name"],
                self.request_json["role_id"],
                initiator_id=self.initiator_id)
        except base_exceptions.UniqueConstraintViolationError as exc:
            LOG.warning(
                "Cannot create new user %s: violation of unique constraint",
                self.request_json["login"])
            raise http_exceptions.ImpossibleToCreateSuchModel() from exc

        LOG.info("User %s was created by %s", user_model.model_id,
                 self.initiator_id)

        notify_about_new_password(user_model, new_password)

        return user_model

    @auth.require_authorization("api", "delete_user")
    @validators.with_model(user.UserModel)
    def delete(self, item_id, item):
        try:
            item.delete()
        except base_exceptions.CannotUpdateDeletedModel as exc:
            LOG.warning("Cannot delete deleted user %s", item_id)
            raise http_exceptions.CannotUpdateDeletedModel() from exc

        LOG.info("User %s was deleted by %s", item_id, self.initiator_id)

        return item
Beispiel #9
0
class ClusterView(generic.VersionedCRUDView):
    """Implementation of view for /v1/cluster API."""

    decorators = [
        auth.require_authorization("api", "view_cluster"),
        auth.require_authentication
    ]

    NAME = "cluster"
    MODEL_NAME = "cluster"
    ENDPOINT = "/cluster/"
    PARAMETER_TYPE = "uuid"

    def get_all(self):
        return cluster.ClusterModel.list_models(self.pagination)

    @validators.with_model(cluster.ClusterModel)
    def get_item(self, item_id, item, *args):
        return item

    @auth.require_authorization("api", "view_cluster_versions")
    def get_versions(self, item_id):
        return cluster.ClusterModel.list_versions(str(item_id),
                                                  self.pagination)

    @auth.require_authorization("api", "view_cluster_versions")
    def get_version(self, item_id, version):
        model = cluster.ClusterModel.find_version(str(item_id), int(version))

        if not model:
            LOG.info("Cannot find model with ID %s", item_id)
            raise http_exceptions.NotFound

        return model

    @auth.require_authorization("api", "edit_cluster")
    @validators.with_model(cluster.ClusterModel)
    @validators.require_schema(MODEL_SCHEMA)
    @validators.no_updates_on_default_fields
    def put(self, item_id, item):
        if "name" in self.request_json["data"]:
            item.name = self.request_json["data"]["name"]

        item.initiator_id = self.initiator_id

        try:
            item.save()
        except base_exceptions.CannotUpdateDeletedModel as exc:
            LOG.warning(
                "Cannot update cluster %s (deleted at %s, "
                "version %s)", item_id, item.time_deleted, item.version)
            raise http_exceptions.CannotUpdateDeletedModel() from exc
        except base_exceptions.UniqueConstraintViolationError as exc:
            LOG.warning(
                "Cannot update cluster %s (unique constraint "
                "violation)", self.request_json["data"]["name"])
            raise http_exceptions.CannotUpdateModelWithSuchParameters() \
                from exc

        LOG.info("Cluster %s was updated by %s", item_id, self.initiator_id)

        return item

    @auth.require_authorization("api", "create_cluster")
    @validators.require_schema(POST_SCHEMA)
    def post(self):
        try:
            cluster_model = cluster.ClusterModel.create(
                self.request_json["name"], initiator_id=self.initiator_id)
        except base_exceptions.UniqueConstraintViolationError as exc:
            LOG.warning(
                "Cannot create cluster %s (unique constraint "
                "violation)", self.request_json["name"])
            raise http_exceptions.ImpossibleToCreateSuchModel() from exc

        LOG.info("Cluster %s (%s) created by %s", self.request_json["name"],
                 cluster_model.model_id, self.initiator_id)

        return cluster_model

    @auth.require_authorization("api", "delete_cluster")
    @validators.with_model(cluster.ClusterModel)
    def delete(self, item_id, item):
        try:
            item.delete()
        except base_exceptions.CannotUpdateDeletedModel as exc:
            LOG.warning("Cannot delete deleted role %s", item_id)
            raise http_exceptions.CannotUpdateDeletedModel() from exc
        except base_exceptions.CannotDeleteClusterWithServers as exc:
            raise http_exceptions.CannotDeleteClusterWithServers from exc

        LOG.info("Cluster %s was deleted by %s", item_id, self.initiator_id)

        return item