¡@

Home 

OpenStack Study: services.py

OpenStack Index

**** CubicPower OpenStack Study ****

# Copyright 2012 IBM Corp.

#

# Licensed under the Apache License, Version 2.0 (the "License"); you may

# not use this file except in compliance with the License. You may obtain

# a copy of the License at

#

# http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

# License for the specific language governing permissions and limitations

# under the License.

from oslo.config import cfg

import webob.exc

from nova.api.openstack import extensions

from nova.api.openstack import wsgi

from nova.api.openstack import xmlutil

from nova import compute

from nova import exception

from nova.openstack.common.gettextutils import _

from nova import servicegroup

from nova import utils

authorize = extensions.extension_authorizer('compute', 'services')

CONF = cfg.CONF

CONF.import_opt('service_down_time', 'nova.service')

**** CubicPower OpenStack Study ****

class ServicesIndexTemplate(xmlutil.TemplateBuilder):

**** CubicPower OpenStack Study ****

    def construct(self):

        root = xmlutil.TemplateElement('services')

        elem = xmlutil.SubTemplateElement(root, 'service', selector='services')

        elem.set('id')

        elem.set('binary')

        elem.set('host')

        elem.set('zone')

        elem.set('status')

        elem.set('state')

        elem.set('updated_at')

        elem.set('disabled_reason')

        return xmlutil.MasterTemplate(root, 1)

**** CubicPower OpenStack Study ****

class ServiceUpdateTemplate(xmlutil.TemplateBuilder):

**** CubicPower OpenStack Study ****

    def construct(self):

        root = xmlutil.TemplateElement('service', selector='service')

        root.set('host')

        root.set('binary')

        root.set('status')

        root.set('disabled_reason')

        return xmlutil.MasterTemplate(root, 1)

**** CubicPower OpenStack Study ****

class ServiceUpdateDeserializer(wsgi.XMLDeserializer):

**** CubicPower OpenStack Study ****

    def default(self, string):

        node = xmlutil.safe_minidom_parse_string(string)

        service = {}

        service_node = self.find_first_child_named(node, 'service')

        if service_node is None:

            return service

        service['host'] = service_node.getAttribute('host')

        service['binary'] = service_node.getAttribute('binary')

        service['disabled_reason'] = service_node.getAttribute(

                                                    'disabled_reason')

        return dict(body=service)

**** CubicPower OpenStack Study ****

class ServiceController(object):

**** CubicPower OpenStack Study ****

    def __init__(self, ext_mgr=None, *args, **kwargs):

        self.host_api = compute.HostAPI()

        self.servicegroup_api = servicegroup.API()

        self.ext_mgr = ext_mgr

**** CubicPower OpenStack Study ****

    def _get_services(self, req):

        context = req.environ['nova.context']

        authorize(context)

        services = self.host_api.service_get_all(

            context, set_zones=True)

        host = ''

        if 'host' in req.GET:

            host = req.GET['host']

        binary = ''

        if 'binary' in req.GET:

            binary = req.GET['binary']

        if host:

            services = [s for s in services if s['host'] == host]

        if binary:

            services = [s for s in services if s['binary'] == binary]

        return services

**** CubicPower OpenStack Study ****

    def _get_service_detail(self, svc, detailed):

        alive = self.servicegroup_api.service_is_up(svc)

        state = (alive and "up") or "down"

        active = 'enabled'

        if svc['disabled']:

            active = 'disabled'

        service_detail = {'binary': svc['binary'], 'host': svc['host'],

                     'zone': svc['availability_zone'],

                     'status': active, 'state': state,

                     'updated_at': svc['updated_at']}

        if self.ext_mgr.is_loaded('os-extended-services-delete'):

            service_detail['id'] = svc['id']

        if detailed:

            service_detail['disabled_reason'] = svc['disabled_reason']

        return service_detail

**** CubicPower OpenStack Study ****

    def _get_services_list(self, req, detailed):

        services = self._get_services(req)

        svcs = []

        for svc in services:

            svcs.append(self._get_service_detail(svc, detailed))

        return svcs

**** CubicPower OpenStack Study ****

    def _is_valid_as_reason(self, reason):

        try:

            utils.check_string_length(reason.strip(), 'Disabled reason',

                                      min_length=1, max_length=255)

        except exception.InvalidInput:

            return False

        return True

    @wsgi.response(204)

**** CubicPower OpenStack Study ****

    def delete(self, req, id):

        """Deletes the specified service."""

        if not self.ext_mgr.is_loaded('os-extended-services-delete'):

            raise webob.exc.HTTPMethodNotAllowed()

        context = req.environ['nova.context']

        authorize(context)

        try:

            self.host_api.service_delete(context, id)

        except exception.ServiceNotFound:

            explanation = _("Service %s not found.") % id

            raise webob.exc.HTTPNotFound(explanation=explanation)

    @wsgi.serializers(xml=ServicesIndexTemplate)

**** CubicPower OpenStack Study ****

    def index(self, req):

        """Return a list of all running services."""

        detailed = self.ext_mgr.is_loaded('os-extended-services')

        services = self._get_services_list(req, detailed)

        return {'services': services}

    @wsgi.deserializers(xml=ServiceUpdateDeserializer)

    @wsgi.serializers(xml=ServiceUpdateTemplate)

**** CubicPower OpenStack Study ****

    def update(self, req, id, body):

        """Enable/Disable scheduling for a service."""

        context = req.environ['nova.context']

        authorize(context)

        ext_loaded = self.ext_mgr.is_loaded('os-extended-services')

        if id == "enable":

            disabled = False

            status = "enabled"

        elif (id == "disable" or

                (id == "disable-log-reason" and ext_loaded)):

            disabled = True

            status = "disabled"

        else:

            msg = _("Unknown action")

            raise webob.exc.HTTPNotFound(explanation=msg)

        try:

            host = body['host']

            binary = body['binary']

            ret_value = {

                'service': {

                    'host': host,

                    'binary': binary,

                    'status': status,

                },

            }

            status_detail = {

                'disabled': disabled,

                'disabled_reason': None,

            }

            if id == "disable-log-reason":

                reason = body['disabled_reason']

                if not self._is_valid_as_reason(reason):

                    msg = _('The string containing the reason for disabling '

                            'the service contains invalid characters or is '

                            'too long.')

                    raise webob.exc.HTTPUnprocessableEntity(detail=msg)

                status_detail['disabled_reason'] = reason

                ret_value['service']['disabled_reason'] = reason

        except (TypeError, KeyError):

            msg = _('Invalid attribute in the request')

            if 'host' in body and 'binary' in body:

                msg = _('Missing disabled reason field')

            raise webob.exc.HTTPUnprocessableEntity(detail=msg)

        try:

            self.host_api.service_update(context, host, binary, status_detail)

        except exception.HostBinaryNotFound as e:

            raise webob.exc.HTTPNotFound(explanation=e.format_message())

        return ret_value

**** CubicPower OpenStack Study ****

class Services(extensions.ExtensionDescriptor):

"""Services support."""

name = "Services"

alias = "os-services"

namespace = "http://docs.openstack.org/compute/ext/services/api/v2"

updated = "2012-10-28T00:00:00-00:00"

**** CubicPower OpenStack Study ****

    def get_resources(self):

        resources = []

        resource = extensions.ResourceExtension('os-services',

                                               ServiceController(self.ext_mgr))

        resources.append(resource)

        return resources