Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
workloadmgr / usr / lib / python3.9 / site-packages / workloadmgr / api / v1 / migrations.py
Size: Mime:
# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright (c) 2013 TrilioData, Inc.
# All Rights Reserved.

"""The migration api."""

import os
import webob
from webob import exc
from defusedxml import minidom
import json
from jsonschema import validate

try:
    from cgi import parse_qs
except:
    from six.moves.urllib.parse import parse_qs
try:
    from cgi import escape
except:
    from html import escape

from workloadmgr.api import common
from workloadmgr.api import wsgi
from workloadmgr.api import xmlutil
from workloadmgr import exception as wlm_exceptions
from workloadmgr import flags
from workloadmgr.openstack.common import log as logging
from workloadmgr.openstack.common import strutils
from workloadmgr import utils
from workloadmgr import workloads as workloadsAPI
from workloadmgr.api.views import migrations as migration_views
from workloadmgr.api.validation_models import migration_plans as migration_plan_validator


LOG = logging.getLogger(__name__)


FLAGS = flags.FLAGS


def make_migration(elem):
    elem.set("id")
    elem.set("status")
    elem.set("created_at")
    elem.set("name")
    elem.set("description")


class MigrationTemplate(xmlutil.TemplateBuilder):
    def construct(self):
        root = xmlutil.TemplateElement("migration", selector="migration")
        make_restore(root)
        return xmlutil.MasterTemplate(root, 1)


class MigrationsTemplate(xmlutil.TemplateBuilder):
    def construct(self):
        root = xmlutil.TemplateElement("migrations")
        elem = xmlutil.SubTemplateElement(root, "migration", selector="migrations")
        make_migration(elem)
        return xmlutil.MasterTemplate(root, 1)


class MigrationDeserializer(wsgi.MetadataXMLDeserializer):
    def default(self, string):
        dom = minidom.parseString(string)
        migration = self._extract_migration(dom)
        return {"body": {"migration": migration}}

    def _extract_migration(self, node):
        migration = {}
        migration_node = self.find_first_child_named(node, "migration")
        if migration_node.getAttribute("migration_id"):
            migration["migration_id"] = migration_node.getAttribute("migration_id")
        return migration


class CreateDeserializer(wsgi.MetadataXMLDeserializer):
    def default(self, string):
        dom = minidom.parseString(string)
        migration = self._extract_migration(dom)
        return {"body": {"migration": migration}}


class MigrationsController(wsgi.Controller):
    """The migrations API controller for the OpenStack API."""

    _view_builder_class = migration_views.ViewBuilder

    def __init__(self, ext_mgr=None):
        self.migration_plan_api = workloadsAPI.API()
        self.ext_mgr = ext_mgr
        super(MigrationsController, self).__init__()

    @wsgi.response(202)
    @migration_plan_validator.validate_migration
    @wsgi.serializers(xml=MigrationTemplate)
    @wsgi.deserializers(xml=CreateDeserializer)
    def create(self, req, body):
        """Create a new migration."""
        try:
            if not self.is_valid_body(body, "migration"):
                raise exc.HTTPBadRequest()

            context = req.environ["workloadmgr.context"]

            try:
                migration = body["migration"]
            except KeyError:
                msg = _("Incorrect request body format")
                raise exc.HTTPBadRequest(explanation=msg)

            migration_plan_id = migration.get("migration_plan_id", None)
            if not migration_plan_id:
                msg = _("migration_plan_id is missing")
                raise exc.HTTPBadRequest(explanation=msg)

            options = migration.get("options", {})
            if not options:
                msg = _("Migration options is missing")
                raise exc.HTTPBadRequest(explanation=msg)

            try:
                # Validate migrations options json payload
                schema_path = os.path.join(os.path.dirname(__file__),
                                           "schemas",
                                           "migration-options.json.schema")
                with open(schema_path, "r") as f:
                    schema = json.load(f)
                validate(instance=options, schema=schema)

                new_migration_plan_dict = self.migration_plan_api.migration_plan_get(
                    context, migration_plan_id
                )
                new_migration = self.migration_plan_api.migration_create(
                    context, migration_plan_id, options
                )

                new_migration_dict = self.migration_plan_api.migration_get(
                    context, new_migration['id'])
            except Exception as error:
                raise exc.HTTPServerError(explanation=str(error))

            retval = self._view_builder.summary(req, new_migration_dict)
            return retval
        except exc.HTTPNotFound as error:
            LOG.exception(error)
            raise error
        except exc.HTTPBadRequest as error:
            LOG.exception(error)
            raise error
        except exc.HTTPServerError as error:
            LOG.exception(error)
            raise error
        except Exception as error:
            LOG.exception(error)
            raise exc.HTTPServerError(explanation=str(error))

    @wsgi.serializers(xml=MigrationTemplate)
    def show(self, req, id):
        """Return data about the given Migration."""
        try:
            context = req.environ["workloadmgr.context"]
            try:
                migration = self.migration_plan_api.migration_get(context, id)
            except wlm_exceptions.NotFound:
                raise exc.HTTPNotFound()
            return self._view_builder.detail(req, migration)
        except exc.HTTPNotFound as error:
            LOG.exception(error)
            raise error
        except exc.HTTPBadRequest as error:
            LOG.exception(error)
            raise error
        except exc.HTTPServerError as error:
            LOG.exception(error)
            raise error
        except Exception as error:
            LOG.exception(error)
            raise exc.HTTPServerError(explanation=str(error))

    def delete(self, req, id):
        """Delete a migration."""
        try:
            context = req.environ["workloadmgr.context"]
            try:
                self.migration_plan_api.migration_delete(context, id)
            except wlm_exceptions.NotFound:
                raise exc.HTTPNotFound()
            except wlm_exceptions.InvalidState as error:
                raise exc.HTTPBadRequest(explanation=str(error))
        except exc.HTTPNotFound as error:
            LOG.exception(error)
            raise error
        except exc.HTTPBadRequest as error:
            LOG.exception(error)
            raise error
        except exc.HTTPServerError as error:
            LOG.exception(error)
            raise error
        except Exception as error:
            LOG.exception(error)
            raise exc.HTTPServerError(explanation=str(error))

    def migration_cancel(self, req, id):
        """Cancel a migration."""
        try:
            context = req.environ["workloadmgr.context"]
            try:
                self.migration_plan_api.migration_cancel(context, id)
            except wlm_exceptions.NotFound:
                raise exc.HTTPNotFound()
            except wlm_exceptions.InvalidState as error:
                raise exc.HTTPBadRequest(explanation=str(error))
        except exc.HTTPNotFound as error:
            LOG.exception(error)
            raise error
        except exc.HTTPBadRequest as error:
            LOG.exception(error)
            raise error
        except exc.HTTPServerError as error:
            LOG.exception(error)
            raise error
        except Exception as error:
            LOG.exception(error)
            raise exc.HTTPServerError(explanation=str(error))

    @wsgi.serializers(xml=MigrationsTemplate)
    def index(self, req, migration_plan_id=None):
        """Returns a summary list of migrations."""
        try:
            return self._get_migrations(req, migration_plan_id=migration_plan_id, is_detail=False)
        except exc.HTTPNotFound as error:
            LOG.exception(error)
            raise error
        except exc.HTTPBadRequest as error:
            LOG.exception(error)
            raise error
        except exc.HTTPServerError as error:
            LOG.exception(error)
            raise error
        except Exception as error:
            LOG.exception(error)
            raise exc.HTTPServerError(explanation=str(error))

    @wsgi.serializers(xml=MigrationsTemplate)
    def detail(self, req, migration_plan_id=None):
        """Returns a detailed list of migrations."""
        try:
            return self._get_migrations(req, migration_plan_id=migration_plan_id, is_detail=True)
        except exc.HTTPNotFound as error:
            LOG.exception(error)
            raise error
        except exc.HTTPBadRequest as error:
            LOG.exception(error)
            raise error
        except exc.HTTPServerError as error:
            LOG.exception(error)
            raise error
        except Exception as error:
            LOG.exception(error)
            raise exc.HTTPServerError(explanation=str(error))

    def _get_migrations(self, req, migration_plan_id=None, is_detail=True):
        """Returns a list of restores, transformed through view builder."""
        context = req.environ["workloadmgr.context"]
        try:
            if not migration_plan_id:
                migration_plan_id = req.GET.get("migration_plan_id", None)
            if migration_plan_id:

                # verify migration plan exists
                self.migration_plan_api.migration_plan_get(context, migration_plan_id)

                migrations_all = self.migration_plan_api.migration_get_all(context, migration_plan_id)
            else:
                migrations_all = self.migration_plan_api.migration_get_all(context)

            limited_list = common.limited(migrations_all, req)

            # TODO(giri): implement the search_opts to specify the filters
            migrations = []
            for migration in limited_list:
                if (migration["deleted"] == False):
                    migrations.append(migration)

            if is_detail:
                migrations = self._view_builder.detail_list(req, migrations)
            else:
                migrations = self._view_builder.summary_list(req, migrations)
            return migrations
        except Exception as ex:
            LOG.exception(ex)
            raise ex


def create_resource(ext_mgr):
    return wsgi.Resource(MigrationsController(ext_mgr))