Esempio n. 1
0
    def delete(self, _id):
        context = t_context.extract_context_from_environ()

        # TODO(joehuang): get the release of top and bottom
        t_release = cons.R_MITAKA
        b_release = cons.R_MITAKA

        s_ctx = hclient.get_res_routing_ref(context, _id, request.url,
                                            cons.ST_CINDER)
        if not s_ctx:
            return utils.format_cinder_error(
                404,
                _('Volume %s could not be found.') % _id)

        if s_ctx['b_url'] == '':
            return utils.format_cinder_error(
                404, _('Bottom Pod endpoint incorrect'))

        b_headers = hclient.convert_header(t_release, b_release,
                                           request.headers)

        resp = hclient.forward_req(context, 'DELETE', b_headers,
                                   s_ctx['b_url'], request.body)

        response.status = resp.status_code

        # don't remove the resource routing for delete is async. operation
        # remove the routing when query is executed but not find
        # No content in the resp actually
        return response
Esempio n. 2
0
    def get_one(self, _id):
        context = t_context.extract_context_from_environ()

        if _id == 'detail':
            return {'volumes': self._get_all(context)}

        # TODO(joehuang): get the release of top and bottom
        t_release = cons.R_MITAKA
        b_release = cons.R_MITAKA

        b_headers = hclient.convert_header(t_release, b_release,
                                           request.headers)

        s_ctx = hclient.get_res_routing_ref(context, _id, request.url,
                                            cons.ST_CINDER)
        if not s_ctx:
            return utils.format_cinder_error(
                404,
                _('Volume %s could not be found.') % _id)

        if s_ctx['b_url'] == '':
            return utils.format_cinder_error(
                404, _('Bottom Pod endpoint incorrect'))

        resp = hclient.forward_req(context, 'GET', b_headers, s_ctx['b_url'],
                                   request.body)

        b_ret_body = jsonutils.loads(resp.content)

        b_status = resp.status_code
        response.status = b_status
        if b_status == 200:
            if b_ret_body.get('volume') is not None:
                b_vol_ret = b_ret_body['volume']
                ret_vol = hclient.convert_object(b_release,
                                                 t_release,
                                                 b_vol_ret,
                                                 res_type=cons.RT_VOLUME)

                pod = utils.get_pod_by_top_id(context, _id)
                if pod:
                    ret_vol['availability_zone'] = pod['az_name']

                return {'volume': ret_vol}

        # resource not find but routing exist, remove the routing
        if b_status == 404:
            filters = [{
                'key': 'top_id',
                'comparator': 'eq',
                'value': _id
            }, {
                'key': 'resource_type',
                'comparator': 'eq',
                'value': cons.RT_VOLUME
            }]
            with context.session.begin():
                core.delete_resources(context, models.ResourceRouting, filters)
        return b_ret_body
Esempio n. 3
0
    def _get_all(self, context):

        # TODO(joehuang): query optimization for pagination, sort, etc
        ret = {}
        ret['volumes'] = []

        pods = az_ag.list_pods_by_tenant(context, self.tenant_id)
        for pod in pods:
            if pod['pod_name'] == '':
                continue

            query = urlparse.urlsplit(request.url).query
            query_filters = urlparse.parse_qsl(query)
            skip_pod = False
            for k, v in query_filters:
                if k == 'availability_zone' and v != pod['az_name']:
                    skip_pod = True
                    break
            if skip_pod:
                continue

            s_ctx = hclient.get_pod_service_ctx(context,
                                                request.url,
                                                pod['pod_name'],
                                                s_type=cons.ST_CINDER)
            if s_ctx['b_url'] == '':
                LOG.error(
                    _LE("bottom pod endpoint incorrect %s") % pod['pod_name'])
                continue

            # TODO(joehuang): get the release of top and bottom
            t_release = cons.R_MITAKA
            b_release = cons.R_MITAKA
            b_headers = hclient.convert_header(t_release, b_release,
                                               request.headers)

            resp = hclient.forward_req(context, 'GET', b_headers,
                                       s_ctx['b_url'], request.body)

            if resp.status_code == 200:

                routings = db_api.get_bottom_mappings_by_tenant_pod(
                    context, self.tenant_id, pod['pod_id'], cons.RT_VOLUME)

                b_ret_body = jsonutils.loads(resp.content)
                if b_ret_body.get('volumes'):
                    for vol in b_ret_body['volumes']:

                        if not routings.get(vol['id']):
                            b_ret_body['volumes'].remove(vol)
                            continue

                        vol['availability_zone'] = pod['az_name']

                    ret['volumes'].extend(b_ret_body['volumes'])

                if b_ret_body.get('volumes_links'):
                    ret['volumes_links'] = b_ret_body['volumes_links']
        return ret
Esempio n. 4
0
    def get_one(self):
        """Get all metadata associated with a volume."""
        context = t_context.extract_context_from_environ()

        t_release = cons.R_MITAKA
        b_release = cons.R_MITAKA

        b_headers = hclient.convert_header(t_release,
                                           b_release,
                                           request.headers)

        try:
            s_ctx = hclient.get_res_routing_ref(context, self.volume_id,
                                                request.url, cons.ST_CINDER)
            if not s_ctx:
                return utils.format_cinder_error(
                    500, _('Fail to find resource'))
        except Exception as e:
            LOG.exception(_LE('Fail to get metadata for a volume:'
                              '%(volume_id)s'
                              '%(exception)s'),
                          {'volume_id': self.volume_id,
                           'exception': e})
            return utils.format_cinder_error(500, _('Fail to get metadata'))

        if s_ctx['b_url'] == '':
            return utils.format_cinder_error(
                500, _('Bottom pod endpoint incorrect'))

        resp = hclient.forward_req(context, 'GET',
                                   b_headers,
                                   s_ctx['b_url'],
                                   request.body)

        b_body_ret = jsonutils.loads(resp.content)

        b_status = resp.status_code
        response.status = b_status
        if b_status == 200:
            if b_body_ret.get('metadata') is not None:
                b_metadata_ret = b_body_ret['metadata']
                vol_ret = hclient.convert_object(b_release, t_release,
                                                 b_metadata_ret,
                                                 res_type=cons.
                                                 RT_VOl_METADATA)
                return {'metadata': vol_ret}

        return b_body_ret
Esempio n. 5
0
    def delete(self, key):
        """Delete the given metadata item from a volume."""
        context = t_context.extract_context_from_environ()

        t_release = cons.R_MITAKA
        b_release = cons.R_MITAKA

        try:
            s_ctx = hclient.get_res_routing_ref(context, self.volume_id,
                                                request.url, cons.ST_CINDER)
            if not s_ctx:
                return utils.format_cinder_error(
                    404, _('Fail to find resource'))
        except Exception as e:
            LOG.exception(_LE('Fail to delete metadata from a volume: '
                              '%(volume_id)s'
                              '%(exception)s'),
                          {'volume_id': self.volume_id,
                           'exception': e})
            return utils.format_cinder_error(
                500, _('Fail to delete metadata'))

        if s_ctx['b_url'] == '':
            return utils.format_cinder_error(
                500, _('Bottom pod endpoint incorrect'))

        b_headers = hclient.convert_header(t_release,
                                           b_release,
                                           request.headers)

        resp = hclient.forward_req(context, 'DELETE',
                                   b_headers,
                                   s_ctx['b_url'],
                                   request.body)

        response.status = resp.status_code

        # don't remove the resource routing for delete is async. operation
        # remove the routing when query is executed but not found
        # No content in the resp actually
        return response
Esempio n. 6
0
    def post(self, **kw):
        context = t_context.extract_context_from_environ()

        if 'volume' not in kw:
            return utils.format_cinder_error(
                400, _("Missing required element 'volume' in request body."))

        az = kw['volume'].get('availability_zone', '')
        pod, pod_az = az_ag.get_pod_by_az_tenant(context,
                                                 az_name=az,
                                                 tenant_id=self.tenant_id)
        if not pod:
            LOG.error(_LE("Pod not configured or scheduling failure"))
            return utils.format_cinder_error(
                500, _('Pod not configured or scheduling failure'))

        t_pod = db_api.get_top_pod(context)
        if not t_pod:
            LOG.error(_LE("Top Pod not configured"))
            return utils.format_cinder_error(500, _('Top Pod not configured'))

        # TODO(joehuang): get release from pod configuration,
        # to convert the content
        # b_release = pod['release']
        # t_release = t_pod['release']
        t_release = cons.R_MITAKA
        b_release = cons.R_MITAKA

        s_ctx = hclient.get_pod_service_ctx(context,
                                            request.url,
                                            pod['pod_name'],
                                            s_type=cons.ST_CINDER)

        if s_ctx['b_url'] == '':
            LOG.error(
                _LE("Bottom Pod endpoint incorrect %s") % pod['pod_name'])
            return utils.format_cinder_error(
                500, _('Bottom Pod endpoint incorrect'))

        b_headers = hclient.convert_header(t_release, b_release,
                                           request.headers)

        t_vol = kw['volume']

        # add or remove key-value in the request for diff. version
        b_vol_req = hclient.convert_object(t_release,
                                           b_release,
                                           t_vol,
                                           res_type=cons.RT_VOLUME)

        # convert az to the configured one
        # remove the AZ parameter to bottom request for default one
        b_vol_req['availability_zone'] = pod['pod_az_name']
        if b_vol_req['availability_zone'] == '':
            b_vol_req.pop("availability_zone", None)

        b_body = jsonutils.dumps({'volume': b_vol_req})

        resp = hclient.forward_req(context, 'POST', b_headers, s_ctx['b_url'],
                                   b_body)
        b_status = resp.status_code
        b_ret_body = jsonutils.loads(resp.content)

        # build routing and convert response from the bottom pod
        # for different version.
        response.status = b_status
        if b_status == 202:
            if b_ret_body.get('volume') is not None:
                b_vol_ret = b_ret_body['volume']

                try:
                    with context.session.begin():
                        core.create_resource(
                            context, models.ResourceRouting, {
                                'top_id': b_vol_ret['id'],
                                'bottom_id': b_vol_ret['id'],
                                'pod_id': pod['pod_id'],
                                'project_id': self.tenant_id,
                                'resource_type': cons.RT_VOLUME
                            })
                except Exception as e:
                    LOG.exception(
                        _LE('Failed to create volume '
                            'resource routing'
                            'top_id: %(top_id)s ,'
                            'bottom_id: %(bottom_id)s ,'
                            'pod_id: %(pod_id)s ,'
                            '%(exception)s '), {
                                'top_id': b_vol_ret['id'],
                                'bottom_id': b_vol_ret['id'],
                                'pod_id': pod['pod_id'],
                                'exception': e
                            })
                    return utils.format_cinder_error(
                        500, _('Failed to create volume resource routing'))

                ret_vol = hclient.convert_object(b_release,
                                                 t_release,
                                                 b_vol_ret,
                                                 res_type=cons.RT_VOLUME)

                ret_vol['availability_zone'] = pod['az_name']

                return {'volume': ret_vol}

        return b_ret_body
Esempio n. 7
0
    def put(self, _id, **kw):
        context = t_context.extract_context_from_environ()

        # TODO(joehuang): Implement API multi-version compatibility
        # currently _convert_header and _convert_object are both dummy
        # functions and API versions are hard coded. After multi-version
        # compatibility is implemented, API versions will be retrieved from
        # top and bottom API server, also, _convert_header and _convert_object
        # will do the real job to convert the request header and body
        # according to the API versions.
        t_release = cons.R_MITAKA
        b_release = cons.R_MITAKA

        s_ctx = hclient.get_res_routing_ref(context, _id, request.url,
                                            cons.ST_CINDER)
        if not s_ctx:
            return utils.format_cinder_error(
                404,
                _('Volume %s could not be found.') % _id)

        if s_ctx['b_url'] == '':
            return utils.format_cinder_error(
                404, _('Bottom Pod endpoint incorrect'))

        b_headers = hclient.convert_header(t_release, b_release,
                                           request.headers)

        t_vol = kw['volume']

        # add or remove key-value in the request for diff. version
        b_vol_req = hclient.convert_object(t_release,
                                           b_release,
                                           t_vol,
                                           res_type=cons.RT_VOLUME)

        b_body = jsonutils.dumps({'volume': b_vol_req})

        resp = hclient.forward_req(context, 'PUT', b_headers, s_ctx['b_url'],
                                   b_body)

        b_status = resp.status_code
        b_ret_body = jsonutils.loads(resp.content)
        response.status = b_status

        if b_status == 200:
            if b_ret_body.get('volume') is not None:
                b_vol_ret = b_ret_body['volume']
                ret_vol = hclient.convert_object(b_release,
                                                 t_release,
                                                 b_vol_ret,
                                                 res_type=cons.RT_VOLUME)

                pod = utils.get_pod_by_top_id(context, _id)
                if pod:
                    ret_vol['availability_zone'] = pod['az_name']

                return {'volume': ret_vol}

        # resource not found but routing exist, remove the routing
        if b_status == 404:
            filters = [{
                'key': 'top_id',
                'comparator': 'eq',
                'value': _id
            }, {
                'key': 'resource_type',
                'comparator': 'eq',
                'value': cons.RT_VOLUME
            }]
            with context.session.begin():
                core.delete_resources(context, models.ResourceRouting, filters)
        return b_ret_body
Esempio n. 8
0
    def post(self, **kw):
        """Create volume metadata associated with a volume.

        :param kw: dictionary of values to be created
        :returns: created volume metadata
        """
        context = t_context.extract_context_from_environ()

        if 'metadata' not in kw:
            return utils.format_cinder_error(
                400, _("Missing required element 'metadata' in "
                       "request body."))

        try:
            pod = utils.get_pod_by_top_id(context, self.volume_id)
            if pod is None:
                return utils.format_cinder_error(
                    404, _('Volume %(volume_id)s could not be found.') % {
                        'volume_id': self.volume_id
                    })

            t_pod = db_api.get_top_pod(context)
            if not t_pod:
                LOG.error(_LE("Top Pod not configured"))
                return utils.format_cinder_error(
                    500, _('Top Pod not configured'))
        except Exception as e:
            LOG.exception(_LE('Fail to create metadata for a volume:'
                              '%(volume_id)s'
                              '%(exception)s'),
                          {'volume_id': self.volume_id,
                           'exception': e})
            return utils.format_cinder_error(500, _('Fail to create metadata'))

        t_release = cons.R_MITAKA
        b_release = cons.R_MITAKA

        s_ctx = hclient.get_pod_service_ctx(
            context,
            request.url,
            pod['pod_name'],
            s_type=cons.ST_CINDER)

        if s_ctx['b_url'] == '':
            LOG.error(_LE("Bottom pod endpoint incorrect %s") %
                      pod['pod_name'])
            return utils.format_cinder_error(
                500, _('Bottom pod endpoint incorrect'))

        b_headers = hclient.convert_header(t_release, b_release,
                                           request.headers)

        t_metadata = kw['metadata']

        # add or remove key-value in the request for diff. version
        b_vol_req = hclient.convert_object(t_release, b_release, t_metadata,
                                           res_type=cons.RT_VOl_METADATA)

        b_body = jsonutils.dumps({'metadata': b_vol_req})

        resp = hclient.forward_req(
            context,
            'POST',
            b_headers,
            s_ctx['b_url'],
            b_body)
        b_status = resp.status_code
        b_body_ret = jsonutils.loads(resp.content)

        # convert response from the bottom pod
        # for different version.
        response.status = b_status
        if b_status == 200:
            if b_body_ret.get('metadata') is not None:
                b_metadata_ret = b_body_ret['metadata']

                vol_ret = hclient.convert_object(b_release, t_release,
                                                 b_metadata_ret,
                                                 res_type=cons.
                                                 RT_VOl_METADATA)

                return {'metadata': vol_ret}

        return b_body_ret
Esempio n. 9
0
    def put(self, **kw):
        """Update volume metadata.

        :param kw: dictionary of values to be updated
        :returns: updated volume type
        """
        context = t_context.extract_context_from_environ()

        if 'metadata' not in kw:
            return utils.format_cinder_error(
                400, _("Missing required element 'metadata' in "
                       "request body."))

        t_release = cons.R_MITAKA
        b_release = cons.R_MITAKA

        try:
            s_ctx = hclient.get_res_routing_ref(context, self.volume_id,
                                                request.url, cons.ST_CINDER)
            if not s_ctx:
                return utils.format_cinder_error(
                    404, _('Resource not found'))
        except Exception as e:
            LOG.exception(_LE('Fail to update metadata for a volume: '
                              '%(volume_id)s'
                              '%(exception)s'),
                          {'volume_id': self.volume_id,
                           'exception': e})
            return utils.format_cinder_error(
                500, _('Fail to update metadata'))

        if s_ctx['b_url'] == '':
            return utils.format_cinder_error(
                500, _('Bottom pod endpoint incorrect'))

        b_headers = hclient.convert_header(t_release,
                                           b_release,
                                           request.headers)

        t_metadata = kw['metadata']

        # add or remove key/value in the request for diff. version
        b_vol_req = hclient.convert_object(t_release, b_release, t_metadata,
                                           res_type=cons.RT_VOl_METADATA)

        b_body = jsonutils.dumps({'metadata': b_vol_req})

        resp = hclient.forward_req(context, 'PUT',
                                   b_headers,
                                   s_ctx['b_url'],
                                   b_body)

        b_status = resp.status_code
        b_body_ret = jsonutils.loads(resp.content)
        response.status = b_status

        if b_status == 200:
            if b_body_ret.get('metadata') is not None:
                b_metadata_ret = b_body_ret['metadata']
                vol_ret = hclient.convert_object(b_release, t_release,
                                                 b_metadata_ret,
                                                 res_type=cons.
                                                 RT_VOl_METADATA)
                return {'metadata': vol_ret}

        return b_body_ret