Example #1
0
def get_metadata_item(context, path_tokens, os_instance_id, remote_ip):
    version = path_tokens[0]
    if version == "latest":
        version = VERSIONS[-1]
    elif version not in VERSIONS:
        raise exception.EC2MetadataNotFound()

    ec2_instance, ec2_reservation = (_get_ec2_instance_and_reservation(
        context, os_instance_id))
    # NOTE(ft): check for case of Neutron metadata proxy.
    # It sends project_id as X-Tenant-ID HTTP header. We make sure it's correct
    if context.project_id != ec2_reservation['ownerId']:
        LOG.warning(
            _('Tenant_id %(tenant_id)s does not match tenant_id '
              'of instance %(instance_id)s.'), {
                  'tenant_id': context.project_id,
                  'instance_id': os_instance_id
              })
        raise exception.EC2MetadataNotFound()

    metadata = _build_metadata(context, ec2_instance, ec2_reservation,
                               os_instance_id, remote_ip)
    # TODO(ft): cache built metadata
    metadata = _cut_down_to_version(metadata, version)
    metadata_item = _find_path_in_tree(metadata, path_tokens[1:])
    return _format_metadata_item(metadata_item)
Example #2
0
def _find_path_in_tree(data, path_tokens):
    # given a dict/list tree, and a path in that tree, return data found there.
    for i in range(0, len(path_tokens)):
        if isinstance(data, dict) or isinstance(data, list):
            if path_tokens[i] in data:
                data = data[path_tokens[i]]
            else:
                raise exception.EC2MetadataNotFound()
        else:
            if i != len(path_tokens) - 1:
                raise exception.EC2MetadataNotFound()
            data = data[path_tokens[i]]
    return data
Example #3
0
    def test_build_proxy_request_headers(self, get_remote_ip, get_context,
                                         sign_instance_id):
        req = mock.Mock(headers={})

        req.headers = {'X-Instance-ID': 'fake_instance_id',
                       'fake_key': 'fake_value'}

        self.assertThat(self.handler._build_proxy_request_headers(req),
                        matchers.DictMatches(req.headers))

        req.headers = {'fake_key': 'fake_value'}
        get_remote_ip.return_value = 'fake_instance_ip'
        get_context.return_value = 'fake_context'
        sign_instance_id.return_value = 'signed'

        with mock.patch('ec2api.metadata.api.'
                        'get_os_instance_and_project_id') as get_ids:

            get_ids.return_value = ('fake_instance_id', 'fake_project_id')
            self.assertThat(self.handler._build_proxy_request_headers(req),
                            matchers.DictMatches(
                                {'X-Forwarded-For': 'fake_instance_ip',
                                 'X-Instance-ID': 'fake_instance_id',
                                 'X-Tenant-ID': 'fake_project_id',
                                 'X-Instance-ID-Signature': 'signed'}))
            get_remote_ip.assert_called_with(req)
            get_context.assert_called_with()
            sign_instance_id.assert_called_with('fake_instance_id')
            get_ids.assert_called_with('fake_context', 'fake_instance_ip')

            get_ids.side_effect = exception.EC2MetadataNotFound()
            self.assertRaises(exception.EC2MetadataNotFound,
                              self.handler._build_proxy_request_headers, req)
Example #4
0
 def test_proxy_call_no_instance(self, proxy):
     req = mock.Mock(path_info='/openstack')
     proxy.side_effect = exception.EC2MetadataNotFound()
     with mock.patch.object(metadata.MetadataRequestHandler,
                            '_get_requester'):
         retval = self.handler(req)
     self.assertIsInstance(retval, webob.exc.HTTPNotFound)
Example #5
0
def get_metadata_item(context, path_tokens, os_instance_id, remote_ip,
                      cache_region):
    version = path_tokens[0]
    if version == "latest":
        version = VERSIONS[-1]
    elif version not in VERSIONS:
        raise exception.EC2MetadataNotFound()

    cache_key = 'ec2api-metadata-%s' % os_instance_id
    cache = cache_region.get(cache_key,
                             expiration_time=CONF.metadata.cache_expiration)
    if cache and cache != cache_core.NO_VALUE:
        _check_instance_owner(context, os_instance_id, cache['owner_id'])
        LOG.debug("Using cached metadata for instance %s", os_instance_id)
    else:
        ec2_instance, ec2_reservation = (_get_ec2_instance_and_reservation(
            context, os_instance_id))

        _check_instance_owner(context, os_instance_id,
                              ec2_reservation['ownerId'])

        metadata = _build_metadata(context, ec2_instance, ec2_reservation,
                                   os_instance_id, remote_ip)
        cache = {'metadata': metadata, 'owner_id': ec2_reservation['ownerId']}

        cache_region.set(cache_key, cache)

    metadata = cache['metadata']
    metadata = _cut_down_to_version(metadata, version)
    metadata_item = _find_path_in_tree(metadata, path_tokens[1:])
    return _format_metadata_item(metadata_item)
Example #6
0
def get_os_instance_and_project_id_by_provider_id(context, provider_id,
                                                  fixed_ip):
    neutron = clients.neutron(context)
    os_subnets = neutron.list_subnets(advanced_service_providers=[provider_id],
                                      fields=['network_id'])
    if not os_subnets:
        raise exception.EC2MetadataNotFound()
    os_networks = [subnet['network_id'] for subnet in os_subnets['subnets']]
    try:
        os_port = neutron.list_ports(fixed_ips='ip_address=' + fixed_ip,
                                     network_id=os_networks,
                                     fields=['device_id',
                                             'tenant_id'])['ports'][0]
    except IndexError:
        raise exception.EC2MetadataNotFound()
    os_instance_id = os_port['device_id']
    project_id = os_port['tenant_id']
    return os_instance_id, project_id
Example #7
0
def _check_instance_owner(context, os_instance_id, owner_id):
    # NOTE(ft): check for case of Neutron metadata proxy.
    # It sends project_id as X-Tenant-ID HTTP header.
    # We make sure it's correct
    if context.project_id != owner_id:
        LOG.warning(
            'Tenant_id %(tenant_id)s does not match tenant_id '
            'of instance %(instance_id)s.', {
                'tenant_id': context.project_id,
                'instance_id': os_instance_id
            })
        raise exception.EC2MetadataNotFound()
Example #8
0
def get_os_instance_and_project_id(context, fixed_ip):
    try:
        nova = clients.nova(context)
        os_address = nova.fixed_ips.get(fixed_ip)
        os_instances = nova.servers.list(
                search_opts={'hostname': os_address.hostname,
                             'all_tenants': True})
        return next((os_instance.id, os_instance.tenant_id)
                    for os_instance in os_instances
                    if any((addr['addr'] == fixed_ip and
                            addr['OS-EXT-IPS:type'] == 'fixed')
                           for addr in itertools.chain(
                                *os_instance.addresses.itervalues())))
    except (nova_exception.NotFound, StopIteration):
        raise exception.EC2MetadataNotFound()
Example #9
0
def _get_ec2_instance_and_reservation(context, os_instance_id):
    instance_id = ec2utils.os_id_to_ec2_id(context, 'i', os_instance_id)
    try:
        ec2_reservations = instance_api.describe_instances(
                context, [instance_id])
    except exception.InvalidInstanceIDNotFound:
        ec2_reservations = instance_api.describe_instances(
                context, filter=[{'name': 'instance-id',
                                  'value': [instance_id]}])
    if (len(ec2_reservations['reservationSet']) != 1 or
            len(ec2_reservations['reservationSet'][0]['instancesSet']) != 1):
        LOG.error(_('Failed to get metadata for instance id: %s'),
                  os_instance_id)
        raise exception.EC2MetadataNotFound()

    ec2_reservation = ec2_reservations['reservationSet'][0]
    ec2_instance = ec2_reservation['instancesSet'][0]

    return ec2_instance, ec2_reservation
Example #10
0
    def test_version_root(self, get_metadata):
        get_metadata.return_value = 'fake'
        request = webob.Request.blank('/latest')
        response = request.get_response(self.handler)
        self.assertEqual('fake', response.body)
        response_ctype = response.headers['Content-Type']
        self.assertTrue(response_ctype.startswith("text/plain"))
        get_metadata.assert_called_with(mock.ANY, ['latest'])

        get_metadata.side_effect = exception.EC2MetadataNotFound()
        request = webob.Request.blank('/latest')
        response = request.get_response(self.handler)
        self.assertEqual(404, response.status_int)

        with mock.patch.object(metadata, 'LOG') as log:
            get_metadata.side_effect = Exception()
            request = webob.Request.blank('/latest')
            response = request.get_response(self.handler)
            self.assertEqual(500, response.status_int)
            self.assertEqual(len(log.mock_calls), 2)
Example #11
0
 def test_proxy_call_no_instance(self, proxy):
     req = mock.Mock(path_info='/openstack')
     proxy.side_effect = exception.EC2MetadataNotFound()
     retval = self.handler(req)
     self.assertIsInstance(retval, webob.exc.HTTPNotFound)