Beispiel #1
0
    def post(self, **kw):
        context = t_context.extract_context_from_environ()

        if 'volumeAttachment' not in kw:
            return utils.format_nova_error(400,
                                           _('volumeAttachment is not set'))
        body = kw['volumeAttachment']
        if 'volumeId' not in body:
            return utils.format_nova_error(
                400, _('Invalid input for field/attribute volumeAttachment'))

        server_mappings = db_api.get_bottom_mappings_by_top_id(
            context, self.server_id, constants.RT_SERVER)
        if not server_mappings:
            return utils.format_nova_error(
                404,
                _('Instance %s could not be '
                  'found.') % self.server_id)
        volume_mappings = db_api.get_bottom_mappings_by_top_id(
            context, body['volumeId'], constants.RT_VOLUME)
        if not volume_mappings:
            return utils.format_nova_error(
                404,
                _('Volume %s could not be found') % body['volumeId'])

        server_pod_name = server_mappings[0][0]['pod_name']
        volume_pod_name = volume_mappings[0][0]['pod_name']
        if server_pod_name != volume_pod_name:
            LOG.error(
                _LE('Server %(server)s is in pod %(server_pod)s and '
                    'volume %(volume)s is in pod %(volume_pod)s, which '
                    'are not the same.'), {
                        'server': self.server_id,
                        'server_pod': server_pod_name,
                        'volume': body['volumeId'],
                        'volume_pod': volume_pod_name
                    })
            return utils.format_nova_error(
                400, _('Server and volume not in the same pod'))

        device = None
        if 'device' in body:
            device = body['device']
            # this regular expression is copied from nova/block_device.py
            match = re.match('(^/dev/x{0,1}[a-z]{0,1}d{0,1})([a-z]+)[0-9]*$',
                             device)
            if not match:
                return utils.format_nova_error(
                    400,
                    _('The supplied device path (%s) is '
                      'invalid.') % device)

        client = self._get_client(server_pod_name)
        volume = client.action_server_volumes(context, 'create_server_volume',
                                              server_mappings[0][1],
                                              volume_mappings[0][1], device)
        return {'volumeAttachment': volume.to_dict()}
Beispiel #2
0
 def test_get_bottom_mappings_by_top_id(self):
     for i in xrange(3):
         pod = {
             'pod_id': 'test_pod_uuid_%d' % i,
             'pod_name': 'test_pod_%d' % i,
             'az_name': 'test_az_uuid_%d' % i
         }
         api.create_pod(self.context, pod)
     route1 = {
         'top_id': 'top_uuid',
         'pod_id': 'test_pod_uuid_0',
         'resource_type': 'port'
     }
     route2 = {
         'top_id': 'top_uuid',
         'pod_id': 'test_pod_uuid_1',
         'bottom_id': 'bottom_uuid_1',
         'resource_type': 'port'
     }
     route3 = {
         'top_id': 'top_uuid',
         'pod_id': 'test_pod_uuid_2',
         'bottom_id': 'bottom_uuid_2',
         'resource_type': 'neutron'
     }
     routes = [route1, route2, route3]
     with self.context.session.begin():
         for route in routes:
             core.create_resource(self.context, models.ResourceRouting,
                                  route)
     mappings = api.get_bottom_mappings_by_top_id(self.context, 'top_uuid',
                                                  'port')
     self.assertEqual('test_pod_uuid_1', mappings[0][0]['pod_id'])
     self.assertEqual('bottom_uuid_1', mappings[0][1])
Beispiel #3
0
def get_pod_by_top_id(context, _id):
    """Get pod resource from pod table .

    :param _id: the top id of resource
    :returns: pod resource
    """
    mappings = db_api.get_bottom_mappings_by_top_id(
        context, _id,
        cons.RT_VOLUME)

    if not mappings or len(mappings) != 1:
        return None

    return mappings[0][0]
Beispiel #4
0
    def post(self, **kw):
        context = t_context.extract_context_from_environ()

        action_handle = None
        action_type = None
        for _type in self.handle_map:
            if _type in kw:
                action_handle = self.handle_map[_type]
                action_type = _type
        if not action_handle:
            return utils.format_nova_error(400,
                                           _('Server action not supported'))

        server_mappings = db_api.get_bottom_mappings_by_top_id(
            context, self.server_id, constants.RT_SERVER)
        if not server_mappings:
            return utils.format_nova_error(
                404,
                _('Server %s could not be found') % self.server_id)

        pod_name = server_mappings[0][0]['pod_name']
        try:
            resp, body = action_handle(context, pod_name, kw)
            pecan.response.status = resp.status_code
            if not body:
                return pecan.response
            else:
                return body
        except Exception as e:
            code = 500
            message = _('Action %(action)s on server %(server_id)s fails') % {
                'action': action_type,
                'server_id': self.server_id
            }
            if hasattr(e, 'code'):
                code = e.code
            ex_message = str(e)
            if ex_message:
                message = ex_message
            LOG.error(message)
            return utils.format_nova_error(code, message)
Beispiel #5
0
    def delete(self, _id):
        context = t_context.extract_context_from_environ()

        mappings = db_api.get_bottom_mappings_by_top_id(
            context, _id, constants.RT_SERVER)
        if not mappings:
            pecan.response.status = 404
            return {'Error': {'message': _('Server not found'), 'code': 404}}

        pod, bottom_id = mappings[0]
        client = self._get_client(pod['pod_name'])
        try:
            ret = client.delete_servers(context, bottom_id)
            # none return value indicates server not found
            if ret is None:
                self._remove_stale_mapping(context, _id)
                pecan.response.status = 404
                return {
                    'Error': {
                        'message': _('Server not found'),
                        'code': 404
                    }
                }
        except Exception as e:
            code = 500
            message = _('Delete server %(server_id)s fails') % {
                'server_id': _id
            }
            if hasattr(e, 'code'):
                code = e.code
            ex_message = str(e)
            if ex_message:
                message = ex_message
            LOG.error(message)

            pecan.response.status = code
            return {'Error': {'message': message, 'code': code}}

        pecan.response.status = 204
        return pecan.response
Beispiel #6
0
    def get_one(self, _id, **kwargs):
        context = t_context.extract_context_from_environ()

        if _id == 'detail':
            # return {'servers': [self._construct_brief_server_entry(
            #     server) for server in self._get_all(context, kwargs)]}
            return {'servers': self._get_all(context, kwargs)}

        mappings = db_api.get_bottom_mappings_by_top_id(
            context, _id, constants.RT_SERVER)
        if not mappings:
            return utils.format_nova_error(
                404,
                _('Instance %s could not be found.') % _id)
        pod, bottom_id = mappings[0]
        client = self._get_client(pod['pod_name'])
        server = client.get_servers(context, bottom_id)
        if not server:
            return utils.format_nova_error(
                404,
                _('Instance %s could not be found.') % _id)
        else:
            return {'server': server}
Beispiel #7
0
    def post(self, **kw):
        context = t_context.extract_context_from_environ()

        action_handle = None
        action_type = None
        for _type in self.handle_map:
            if _type in kw:
                action_handle = self.handle_map[_type]
                action_type = _type
        if not action_handle:
            return utils.format_cinder_error(400,
                                             _('Volume action not supported'))

        volume_mappings = db_api.get_bottom_mappings_by_top_id(
            context, self.volume_id, constants.RT_VOLUME)
        if not volume_mappings:
            return utils.format_cinder_error(
                404,
                _('Volume %(volume_id)s could not be found.') %
                {'volume_id': self.volume_id})

        pod_name = volume_mappings[0][0]['pod_name']

        if action_type == 'os-attach':
            instance_uuid = kw['os-attach'].get('instance_uuid')
            if instance_uuid is not None:
                server_mappings = db_api.get_bottom_mappings_by_top_id(
                    context, instance_uuid, constants.RT_SERVER)
                if not server_mappings:
                    return utils.format_cinder_error(404,
                                                     _('Server not found'))
                server_pod_name = server_mappings[0][0]['pod_name']
                if server_pod_name != pod_name:
                    LOG.error(
                        _LE('Server %(server)s is in pod %(server_pod)s'
                            'and volume %(volume)s is in pod'
                            '%(volume_pod)s, which '
                            'are not the same.'), {
                                'server': instance_uuid,
                                'server_pod': server_pod_name,
                                'volume': self.volume_id,
                                'volume_pod': pod_name
                            })
                    return utils.format_cinder_error(
                        400, _('Server and volume not in the same pod'))

        try:
            resp, body = action_handle(context, pod_name, kw)
            pecan.response.status = resp.status_code
            if not body:
                return pecan.response
            else:
                return body
        except Exception as e:
            code = 500
            message = _('Action %(action)s on volume %(volume_id)s fails') % {
                'action': action_type,
                'volume_id': self.volume_id
            }
            if hasattr(e, 'code'):
                code = e.code
            ex_message = str(e)
            if ex_message:
                message = ex_message
            LOG.error(message)
            return utils.format_cinder_error(code, message)