Beispiel #1
0
    def fake_get_all(context,
                     inactive=False,
                     filters=None,
                     sort_key='flavorid',
                     sort_dir='asc',
                     limit=None,
                     marker=None):
        if marker in ['99999']:
            raise exc.MarkerNotFound(marker)

        def reject_min(db_attr, filter_attr):
            return (filter_attr in filters
                    and getattr(flavor, db_attr) < int(filters[filter_attr]))

        filters = filters or {}
        res = []
        for flavor in FLAVORS.values():
            if reject_min('memory_mb', 'min_memory_mb'):
                continue
            elif reject_min('root_gb', 'min_root_gb'):
                continue

            res.append(flavor)

        res = sorted(res, key=lambda item: getattr(item, sort_key))
        output = []
        marker_found = True if marker is None else False
        for flavor in res:
            if not marker_found and marker == flavor.flavorid:
                marker_found = True
            elif marker_found:
                if limit is None or len(output) < int(limit):
                    output.append(flavor)

        return objects.FlavorList(objects=output)
Beispiel #2
0
 def test_list_flavor_detail_default_swap_value(self, mock_get):
     mock_get.return_value = objects.FlavorList(
         objects=[self.FLAVOR_WITH_NO_SWAP])
     req = self.fake_request.blank('/%s/flavors/detail?limit=1' %
                                   fakes.FAKE_PROJECT_ID,
                                   version=self.microversion)
     response = self.controller.detail(req)
     response_list = response["flavors"]
     self.assertEqual(response_list[0]['swap'], 0)
class FlavorsTestV21(test.TestCase):
    _prefix = "/v2/fake"
    Controller = flavors_v21.FlavorsController
    fake_request = fakes.HTTPRequestV21
    _rspv = "v2/fake"
    _fake = "/fake"

    def setUp(self):
        super(FlavorsTestV21, self).setUp()
        fakes.stub_out_networking(self)
        fakes.stub_out_flavor_get_all(self)
        fakes.stub_out_flavor_get_by_flavor_id(self)
        self.controller = self.Controller()

    def _set_expected_body(self, expected, flavor):
        # NOTE(oomichi): On v2.1 API, some extensions of v2.0 are merged
        # as core features and we can get the following parameters as the
        # default.
        expected['OS-FLV-EXT-DATA:ephemeral'] = flavor.ephemeral_gb
        expected['OS-FLV-DISABLED:disabled'] = flavor.disabled
        expected['swap'] = flavor.swap

    @mock.patch('nova.objects.Flavor.get_by_flavor_id',
                side_effect=return_flavor_not_found)
    def test_get_flavor_by_invalid_id(self, mock_get):
        req = self.fake_request.blank(self._prefix + '/flavors/asdf')
        self.assertRaises(webob.exc.HTTPNotFound, self.controller.show, req,
                          'asdf')

    def test_get_flavor_by_id(self):
        req = self.fake_request.blank(self._prefix + '/flavors/1')
        flavor = self.controller.show(req, '1')
        expected = {
            "flavor": {
                "id":
                fakes.FLAVORS['1'].flavorid,
                "name":
                fakes.FLAVORS['1'].name,
                "ram":
                fakes.FLAVORS['1'].memory_mb,
                "disk":
                fakes.FLAVORS['1'].root_gb,
                "vcpus":
                fakes.FLAVORS['1'].vcpus,
                "links": [
                    {
                        "rel": "self",
                        "href":
                        "http://localhost/" + self._rspv + "/flavors/1",
                    },
                    {
                        "rel": "bookmark",
                        "href": "http://localhost" + self._fake + "/flavors/1",
                    },
                ],
            },
        }
        self._set_expected_body(expected['flavor'], fakes.FLAVORS['1'])
        self.assertEqual(flavor, expected)

    def test_get_flavor_with_custom_link_prefix(self):
        self.flags(compute_link_prefix='http://zoo.com:42',
                   glance_link_prefix='http://circus.com:34',
                   group='api')
        req = self.fake_request.blank(self._prefix + '/flavors/1')
        flavor = self.controller.show(req, '1')
        expected = {
            "flavor": {
                "id":
                fakes.FLAVORS['1'].flavorid,
                "name":
                fakes.FLAVORS['1'].name,
                "ram":
                fakes.FLAVORS['1'].memory_mb,
                "disk":
                fakes.FLAVORS['1'].root_gb,
                "vcpus":
                fakes.FLAVORS['1'].vcpus,
                "links": [
                    {
                        "rel": "self",
                        "href":
                        "http://zoo.com:42/" + self._rspv + "/flavors/1",
                    },
                    {
                        "rel": "bookmark",
                        "href":
                        "http://zoo.com:42" + self._fake + "/flavors/1",
                    },
                ],
            },
        }
        self._set_expected_body(expected['flavor'], fakes.FLAVORS['1'])
        self.assertEqual(expected, flavor)

    def test_get_flavor_list(self):
        req = self.fake_request.blank(self._prefix + '/flavors')
        flavor = self.controller.index(req)
        expected = {
            "flavors": [
                {
                    "id":
                    fakes.FLAVORS['1'].flavorid,
                    "name":
                    fakes.FLAVORS['1'].name,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/1",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/1",
                        },
                    ],
                },
                {
                    "id":
                    fakes.FLAVORS['2'].flavorid,
                    "name":
                    fakes.FLAVORS['2'].name,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/2",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/2",
                        },
                    ],
                },
            ],
        }
        self.assertEqual(flavor, expected)

    def test_get_flavor_list_with_marker(self):
        self.maxDiff = None
        url = self._prefix + '/flavors?limit=1&marker=1'
        req = self.fake_request.blank(url)
        flavor = self.controller.index(req)
        expected = {
            "flavors": [
                {
                    "id":
                    fakes.FLAVORS['2'].flavorid,
                    "name":
                    fakes.FLAVORS['2'].name,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/2",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/2",
                        },
                    ],
                },
            ],
            'flavors_links': [{
                'href':
                'http://localhost/' + self._rspv + '/flavors?limit=1&marker=2',
                'rel': 'next'
            }]
        }
        self.assertThat(flavor, matchers.DictMatches(expected))

    def test_get_flavor_list_with_invalid_marker(self):
        req = self.fake_request.blank(self._prefix + '/flavors?marker=99999')
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.index, req)

    def test_get_flavor_detail_with_limit(self):
        url = self._prefix + '/flavors/detail?limit=1'
        req = self.fake_request.blank(url)
        response = self.controller.detail(req)
        response_list = response["flavors"]
        response_links = response["flavors_links"]

        expected_flavors = [
            {
                "id":
                fakes.FLAVORS['1'].flavorid,
                "name":
                fakes.FLAVORS['1'].name,
                "ram":
                fakes.FLAVORS['1'].memory_mb,
                "disk":
                fakes.FLAVORS['1'].root_gb,
                "vcpus":
                fakes.FLAVORS['1'].vcpus,
                "links": [
                    {
                        "rel": "self",
                        "href":
                        "http://localhost/" + self._rspv + "/flavors/1",
                    },
                    {
                        "rel": "bookmark",
                        "href": "http://localhost" + self._fake + "/flavors/1",
                    },
                ],
            },
        ]
        self._set_expected_body(expected_flavors[0], fakes.FLAVORS['1'])

        self.assertEqual(response_list, expected_flavors)
        self.assertEqual(response_links[0]['rel'], 'next')

        href_parts = urlparse.urlparse(response_links[0]['href'])
        self.assertEqual('/' + self._rspv + '/flavors/detail', href_parts.path)
        params = urlparse.parse_qs(href_parts.query)
        self.assertThat({
            'limit': ['1'],
            'marker': ['1']
        }, matchers.DictMatches(params))

    def test_get_flavor_with_limit(self):
        req = self.fake_request.blank(self._prefix + '/flavors?limit=2')
        response = self.controller.index(req)
        response_list = response["flavors"]
        response_links = response["flavors_links"]

        expected_flavors = [{
            "id":
            fakes.FLAVORS['1'].flavorid,
            "name":
            fakes.FLAVORS['1'].name,
            "links": [
                {
                    "rel": "self",
                    "href": "http://localhost/" + self._rspv + "/flavors/1",
                },
                {
                    "rel": "bookmark",
                    "href": "http://localhost" + self._fake + "/flavors/1",
                },
            ],
        }, {
            "id":
            fakes.FLAVORS['2'].flavorid,
            "name":
            fakes.FLAVORS['2'].name,
            "links": [
                {
                    "rel": "self",
                    "href": "http://localhost/" + self._rspv + "/flavors/2",
                },
                {
                    "rel": "bookmark",
                    "href": "http://localhost" + self._fake + "/flavors/2",
                },
            ],
        }]
        self.assertEqual(response_list, expected_flavors)
        self.assertEqual(response_links[0]['rel'], 'next')

        href_parts = urlparse.urlparse(response_links[0]['href'])
        self.assertEqual('/' + self._rspv + '/flavors', href_parts.path)
        params = urlparse.parse_qs(href_parts.query)
        self.assertThat({
            'limit': ['2'],
            'marker': ['2']
        }, matchers.DictMatches(params))

    def test_get_flavor_with_default_limit(self):
        self.stub_out('nova.api.openstack.common.get_limit_and_marker',
                      fake_get_limit_and_marker)
        self.flags(max_limit=1, group='api')
        req = fakes.HTTPRequest.blank('/v2/fake/flavors?limit=2')
        response = self.controller.index(req)
        response_list = response["flavors"]
        response_links = response["flavors_links"]

        expected_flavors = [{
            "id":
            fakes.FLAVORS['1'].flavorid,
            "name":
            fakes.FLAVORS['1'].name,
            "links": [{
                "rel": "self",
                "href": "http://localhost/v2/fake/flavors/1",
            }, {
                "rel": "bookmark",
                "href": "http://localhost/fake/flavors/1",
            }]
        }]

        self.assertEqual(response_list, expected_flavors)
        self.assertEqual(response_links[0]['rel'], 'next')
        href_parts = urlparse.urlparse(response_links[0]['href'])
        self.assertEqual('/v2/fake/flavors', href_parts.path)
        params = urlparse.parse_qs(href_parts.query)
        self.assertThat({
            'limit': ['2'],
            'marker': ['1']
        }, matchers.DictMatches(params))

    def test_get_flavor_list_detail(self):
        req = self.fake_request.blank(self._prefix + '/flavors/detail')
        flavor = self.controller.detail(req)
        expected = {
            "flavors": [
                {
                    "id":
                    fakes.FLAVORS['1'].flavorid,
                    "name":
                    fakes.FLAVORS['1'].name,
                    "ram":
                    fakes.FLAVORS['1'].memory_mb,
                    "disk":
                    fakes.FLAVORS['1'].root_gb,
                    "vcpus":
                    fakes.FLAVORS['1'].vcpus,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/1",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/1",
                        },
                    ],
                },
                {
                    "id":
                    fakes.FLAVORS['2'].flavorid,
                    "name":
                    fakes.FLAVORS['2'].name,
                    "ram":
                    fakes.FLAVORS['2'].memory_mb,
                    "disk":
                    fakes.FLAVORS['2'].root_gb,
                    "vcpus":
                    fakes.FLAVORS['2'].vcpus,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/2",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/2",
                        },
                    ],
                },
            ],
        }
        self._set_expected_body(expected['flavors'][0], fakes.FLAVORS['1'])
        self._set_expected_body(expected['flavors'][1], fakes.FLAVORS['2'])
        self.assertEqual(expected, flavor)

    @mock.patch('nova.objects.FlavorList.get_all',
                return_value=objects.FlavorList())
    def test_get_empty_flavor_list(self, mock_get):
        req = self.fake_request.blank(self._prefix + '/flavors')
        flavors = self.controller.index(req)
        expected = {'flavors': []}
        self.assertEqual(flavors, expected)

    def test_get_flavor_list_filter_min_ram(self):
        # Flavor lists may be filtered by minRam.
        req = self.fake_request.blank(self._prefix + '/flavors?minRam=512')
        flavor = self.controller.index(req)
        expected = {
            "flavors": [
                {
                    "id":
                    fakes.FLAVORS['2'].flavorid,
                    "name":
                    fakes.FLAVORS['2'].name,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/2",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/2",
                        },
                    ],
                },
            ],
        }
        self.assertEqual(flavor, expected)

    def test_get_flavor_list_filter_invalid_min_ram(self):
        # Ensure you cannot list flavors with invalid minRam param.
        req = self.fake_request.blank(self._prefix + '/flavors?minRam=NaN')
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.index, req)

    def test_get_flavor_list_filter_min_disk(self):
        # Flavor lists may be filtered by minDisk.
        req = self.fake_request.blank(self._prefix + '/flavors?minDisk=20')
        flavor = self.controller.index(req)
        expected = {
            "flavors": [
                {
                    "id":
                    fakes.FLAVORS['2'].flavorid,
                    "name":
                    fakes.FLAVORS['2'].name,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/2",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/2",
                        },
                    ],
                },
            ],
        }
        self.assertEqual(flavor, expected)

    def test_get_flavor_list_filter_invalid_min_disk(self):
        # Ensure you cannot list flavors with invalid minDisk param.
        req = self.fake_request.blank(self._prefix + '/flavors?minDisk=NaN')
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.index, req)

    def test_get_flavor_list_detail_min_ram_and_min_disk(self):
        """Tests that filtering work on flavor details and that minRam and
        minDisk filters can be combined
        """
        req = self.fake_request.blank(self._prefix + '/flavors/detail'
                                      '?minRam=256&minDisk=20')
        flavor = self.controller.detail(req)
        expected = {
            "flavors": [
                {
                    "id":
                    fakes.FLAVORS['2'].flavorid,
                    "name":
                    fakes.FLAVORS['2'].name,
                    "ram":
                    fakes.FLAVORS['2'].memory_mb,
                    "disk":
                    fakes.FLAVORS['2'].root_gb,
                    "vcpus":
                    fakes.FLAVORS['2'].vcpus,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/2",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/2",
                        },
                    ],
                },
            ],
        }
        self._set_expected_body(expected['flavors'][0], fakes.FLAVORS['2'])
        self.assertEqual(expected, flavor)
class FlavorsTestV21(test.TestCase):
    _prefix = "/v2/fake"
    Controller = flavors_v21.FlavorsController
    fake_request = fakes.HTTPRequestV21
    _rspv = "v2/fake"
    _fake = "/fake"
    microversion = '2.1'
    # Flag to tell the test if a description should be expected in a response.
    expect_description = False
    # Flag to tell the test if a extra_specs should be expected in a response.
    expect_extra_specs = False

    def setUp(self):
        super(FlavorsTestV21, self).setUp()
        fakes.stub_out_networking(self)
        fakes.stub_out_flavor_get_all(self)
        fakes.stub_out_flavor_get_by_flavor_id(self)
        self.controller = self.Controller()

    def _build_request(self, url):
        return self.fake_request.blank(self._prefix + url,
                                       version=self.microversion)

    def _set_expected_body(self, expected, flavor):
        expected['OS-FLV-EXT-DATA:ephemeral'] = flavor.ephemeral_gb
        expected['OS-FLV-DISABLED:disabled'] = flavor.disabled
        expected['swap'] = flavor.swap
        if self.expect_description:
            expected['description'] = flavor.description
        if self.expect_extra_specs:
            expected['extra_specs'] = flavor.extra_specs

    @mock.patch('nova.objects.Flavor.get_by_flavor_id',
                side_effect=return_flavor_not_found)
    def test_get_flavor_by_invalid_id(self, mock_get):
        req = self._build_request('/flavors/asdf')
        self.assertRaises(webob.exc.HTTPNotFound, self.controller.show, req,
                          'asdf')

    def test_get_flavor_by_id(self):
        req = self._build_request('/flavors/1')
        flavor = self.controller.show(req, '1')
        expected = {
            "flavor": {
                "id":
                fakes.FLAVORS['1'].flavorid,
                "name":
                fakes.FLAVORS['1'].name,
                "ram":
                fakes.FLAVORS['1'].memory_mb,
                "disk":
                fakes.FLAVORS['1'].root_gb,
                "vcpus":
                fakes.FLAVORS['1'].vcpus,
                "os-flavor-access:is_public":
                True,
                "rxtx_factor":
                1.0,
                "links": [
                    {
                        "rel": "self",
                        "href":
                        "http://localhost/" + self._rspv + "/flavors/1",
                    },
                    {
                        "rel": "bookmark",
                        "href": "http://localhost" + self._fake + "/flavors/1",
                    },
                ],
            },
        }
        self._set_expected_body(expected['flavor'], fakes.FLAVORS['1'])
        self.assertEqual(flavor, expected)

    def test_get_flavor_with_custom_link_prefix(self):
        self.flags(compute_link_prefix='http://zoo.com:42',
                   glance_link_prefix='http://circus.com:34',
                   group='api')
        req = self._build_request('/flavors/1')
        flavor = self.controller.show(req, '1')
        expected = {
            "flavor": {
                "id":
                fakes.FLAVORS['1'].flavorid,
                "name":
                fakes.FLAVORS['1'].name,
                "ram":
                fakes.FLAVORS['1'].memory_mb,
                "disk":
                fakes.FLAVORS['1'].root_gb,
                "vcpus":
                fakes.FLAVORS['1'].vcpus,
                "os-flavor-access:is_public":
                True,
                "rxtx_factor":
                1.0,
                "links": [
                    {
                        "rel": "self",
                        "href":
                        "http://zoo.com:42/" + self._rspv + "/flavors/1",
                    },
                    {
                        "rel": "bookmark",
                        "href":
                        "http://zoo.com:42" + self._fake + "/flavors/1",
                    },
                ],
            },
        }
        self._set_expected_body(expected['flavor'], fakes.FLAVORS['1'])
        self.assertEqual(expected, flavor)

    def test_get_flavor_list(self):
        req = self._build_request('/flavors')
        flavor = self.controller.index(req)
        expected = {
            "flavors": [
                {
                    "id":
                    fakes.FLAVORS['1'].flavorid,
                    "name":
                    fakes.FLAVORS['1'].name,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/1",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/1",
                        },
                    ],
                },
                {
                    "id":
                    fakes.FLAVORS['2'].flavorid,
                    "name":
                    fakes.FLAVORS['2'].name,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/2",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/2",
                        },
                    ],
                },
            ],
        }
        if self.expect_description:
            for idx, _flavor in enumerate(expected['flavors']):
                expected['flavors'][idx]['description'] = (
                    fakes.FLAVORS[_flavor['id']].description)
        self.assertEqual(flavor, expected)

    def test_get_flavor_list_with_marker(self):
        self.maxDiff = None
        url = '/flavors?limit=1&marker=1'
        req = self._build_request(url)
        flavor = self.controller.index(req)
        expected = {
            "flavors": [
                {
                    "id":
                    fakes.FLAVORS['2'].flavorid,
                    "name":
                    fakes.FLAVORS['2'].name,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/2",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/2",
                        },
                    ],
                },
            ],
            'flavors_links': [{
                'href':
                'http://localhost/' + self._rspv + '/flavors?limit=1&marker=2',
                'rel': 'next'
            }]
        }
        if self.expect_description:
            expected['flavors'][0]['description'] = (
                fakes.FLAVORS['2'].description)
        self.assertThat(flavor, matchers.DictMatches(expected))

    def test_get_flavor_list_with_invalid_marker(self):
        req = self._build_request('/flavors?marker=99999')
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.index, req)

    def test_get_flavor_detail_with_limit(self):
        url = '/flavors/detail?limit=1'
        req = self._build_request(url)
        response = self.controller.detail(req)
        response_list = response["flavors"]
        response_links = response["flavors_links"]

        expected_flavors = [
            {
                "id":
                fakes.FLAVORS['1'].flavorid,
                "name":
                fakes.FLAVORS['1'].name,
                "ram":
                fakes.FLAVORS['1'].memory_mb,
                "disk":
                fakes.FLAVORS['1'].root_gb,
                "vcpus":
                fakes.FLAVORS['1'].vcpus,
                "os-flavor-access:is_public":
                True,
                "rxtx_factor":
                1.0,
                "links": [
                    {
                        "rel": "self",
                        "href":
                        "http://localhost/" + self._rspv + "/flavors/1",
                    },
                    {
                        "rel": "bookmark",
                        "href": "http://localhost" + self._fake + "/flavors/1",
                    },
                ],
            },
        ]
        self._set_expected_body(expected_flavors[0], fakes.FLAVORS['1'])

        self.assertEqual(response_list, expected_flavors)
        self.assertEqual(response_links[0]['rel'], 'next')

        href_parts = urlparse.urlparse(response_links[0]['href'])
        self.assertEqual('/' + self._rspv + '/flavors/detail', href_parts.path)
        params = urlparse.parse_qs(href_parts.query)
        self.assertThat({
            'limit': ['1'],
            'marker': ['1']
        }, matchers.DictMatches(params))

    def test_get_flavor_with_limit(self):
        req = self._build_request('/flavors?limit=2')
        response = self.controller.index(req)
        response_list = response["flavors"]
        response_links = response["flavors_links"]

        expected_flavors = [{
            "id":
            fakes.FLAVORS['1'].flavorid,
            "name":
            fakes.FLAVORS['1'].name,
            "links": [
                {
                    "rel": "self",
                    "href": "http://localhost/" + self._rspv + "/flavors/1",
                },
                {
                    "rel": "bookmark",
                    "href": "http://localhost" + self._fake + "/flavors/1",
                },
            ],
        }, {
            "id":
            fakes.FLAVORS['2'].flavorid,
            "name":
            fakes.FLAVORS['2'].name,
            "links": [
                {
                    "rel": "self",
                    "href": "http://localhost/" + self._rspv + "/flavors/2",
                },
                {
                    "rel": "bookmark",
                    "href": "http://localhost" + self._fake + "/flavors/2",
                },
            ],
        }]
        if self.expect_description:
            for idx, _flavor in enumerate(expected_flavors):
                expected_flavors[idx]['description'] = (
                    fakes.FLAVORS[_flavor['id']].description)
        self.assertEqual(response_list, expected_flavors)
        self.assertEqual(response_links[0]['rel'], 'next')

        href_parts = urlparse.urlparse(response_links[0]['href'])
        self.assertEqual('/' + self._rspv + '/flavors', href_parts.path)
        params = urlparse.parse_qs(href_parts.query)
        self.assertThat({
            'limit': ['2'],
            'marker': ['2']
        }, matchers.DictMatches(params))

    def test_get_flavor_with_default_limit(self):
        self.stub_out('nova.api.openstack.common.get_limit_and_marker',
                      fake_get_limit_and_marker)
        self.flags(max_limit=1, group='api')
        req = self._build_request('/flavors?limit=2')
        response = self.controller.index(req)
        response_list = response["flavors"]
        response_links = response["flavors_links"]

        expected_flavors = [{
            "id":
            fakes.FLAVORS['1'].flavorid,
            "name":
            fakes.FLAVORS['1'].name,
            "links": [{
                "rel": "self",
                "href": "http://localhost/v2/fake/flavors/1",
            }, {
                "rel": "bookmark",
                "href": "http://localhost/fake/flavors/1",
            }]
        }]
        if self.expect_description:
            expected_flavors[0]['description'] = (
                fakes.FLAVORS['1'].description)

        self.assertEqual(response_list, expected_flavors)
        self.assertEqual(response_links[0]['rel'], 'next')
        href_parts = urlparse.urlparse(response_links[0]['href'])
        self.assertEqual('/v2/fake/flavors', href_parts.path)
        params = urlparse.parse_qs(href_parts.query)
        self.assertThat({
            'limit': ['2'],
            'marker': ['1']
        }, matchers.DictMatches(params))

    def test_get_flavor_list_detail(self):
        req = self._build_request('/flavors/detail')
        flavor = self.controller.detail(req)
        expected = {
            "flavors": [
                {
                    "id":
                    fakes.FLAVORS['1'].flavorid,
                    "name":
                    fakes.FLAVORS['1'].name,
                    "ram":
                    fakes.FLAVORS['1'].memory_mb,
                    "disk":
                    fakes.FLAVORS['1'].root_gb,
                    "vcpus":
                    fakes.FLAVORS['1'].vcpus,
                    "os-flavor-access:is_public":
                    True,
                    "rxtx_factor":
                    1.0,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/1",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/1",
                        },
                    ],
                },
                {
                    "id":
                    fakes.FLAVORS['2'].flavorid,
                    "name":
                    fakes.FLAVORS['2'].name,
                    "ram":
                    fakes.FLAVORS['2'].memory_mb,
                    "disk":
                    fakes.FLAVORS['2'].root_gb,
                    "vcpus":
                    fakes.FLAVORS['2'].vcpus,
                    "os-flavor-access:is_public":
                    True,
                    "rxtx_factor":
                    '',
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/2",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/2",
                        },
                    ],
                },
            ],
        }
        self._set_expected_body(expected['flavors'][0], fakes.FLAVORS['1'])
        self._set_expected_body(expected['flavors'][1], fakes.FLAVORS['2'])
        self.assertEqual(expected, flavor)

    @mock.patch('nova.objects.FlavorList.get_all',
                return_value=objects.FlavorList())
    def test_get_empty_flavor_list(self, mock_get):
        req = self._build_request('/flavors')
        flavors = self.controller.index(req)
        expected = {'flavors': []}
        self.assertEqual(flavors, expected)

    def test_get_flavor_list_filter_min_ram(self):
        # Flavor lists may be filtered by minRam.
        req = self._build_request('/flavors?minRam=512')
        flavor = self.controller.index(req)
        expected = {
            "flavors": [
                {
                    "id":
                    fakes.FLAVORS['2'].flavorid,
                    "name":
                    fakes.FLAVORS['2'].name,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/2",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/2",
                        },
                    ],
                },
            ],
        }
        if self.expect_description:
            expected['flavors'][0]['description'] = (
                fakes.FLAVORS['2'].description)
        self.assertEqual(flavor, expected)

    def test_get_flavor_list_filter_invalid_min_ram(self):
        # Ensure you cannot list flavors with invalid minRam param.
        req = self._build_request('/flavors?minRam=NaN')
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.index, req)

    def test_get_flavor_list_filter_min_disk(self):
        # Flavor lists may be filtered by minDisk.
        req = self._build_request('/flavors?minDisk=20')
        flavor = self.controller.index(req)
        expected = {
            "flavors": [
                {
                    "id":
                    fakes.FLAVORS['2'].flavorid,
                    "name":
                    fakes.FLAVORS['2'].name,
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/2",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/2",
                        },
                    ],
                },
            ],
        }
        if self.expect_description:
            expected['flavors'][0]['description'] = (
                fakes.FLAVORS['2'].description)
        self.assertEqual(flavor, expected)

    def test_get_flavor_list_filter_invalid_min_disk(self):
        # Ensure you cannot list flavors with invalid minDisk param.
        req = self._build_request('/flavors?minDisk=NaN')
        self.assertRaises(webob.exc.HTTPBadRequest, self.controller.index, req)

    def test_get_flavor_list_detail_min_ram_and_min_disk(self):
        """Tests that filtering work on flavor details and that minRam and
        minDisk filters can be combined
        """
        req = self._build_request('/flavors/detail?minRam=256&minDisk=20')
        flavor = self.controller.detail(req)
        expected = {
            "flavors": [
                {
                    "id":
                    fakes.FLAVORS['2'].flavorid,
                    "name":
                    fakes.FLAVORS['2'].name,
                    "ram":
                    fakes.FLAVORS['2'].memory_mb,
                    "disk":
                    fakes.FLAVORS['2'].root_gb,
                    "vcpus":
                    fakes.FLAVORS['2'].vcpus,
                    "os-flavor-access:is_public":
                    True,
                    "rxtx_factor":
                    '',
                    "links": [
                        {
                            "rel":
                            "self",
                            "href":
                            "http://localhost/" + self._rspv + "/flavors/2",
                        },
                        {
                            "rel": "bookmark",
                            "href":
                            "http://localhost" + self._fake + "/flavors/2",
                        },
                    ],
                },
            ],
        }
        self._set_expected_body(expected['flavors'][0], fakes.FLAVORS['2'])
        self.assertEqual(expected, flavor)

    def _test_list_flavors_with_invalid_filter(self,
                                               url,
                                               expected_exception=exception.
                                               ValidationError):
        controller_list = self.controller.index
        if 'detail' in url:
            controller_list = self.controller.detail
        req = self._build_request(url)
        self.assertRaises(expected_exception, controller_list, req)

    def test_list_flavors_with_invalid_non_int_limit(self):
        self._test_list_flavors_with_invalid_filter('/flavors?limit=-9')

    def test_list_detail_flavors_with_invalid_non_int_limit(self):
        self._test_list_flavors_with_invalid_filter('/flavors/detail?limit=-9')

    def test_list_flavors_with_invalid_string_limit(self):
        self._test_list_flavors_with_invalid_filter('/flavors?limit=abc')

    def test_list_detail_flavors_with_invalid_string_limit(self):
        self._test_list_flavors_with_invalid_filter(
            '/flavors/detail?limit=abc')

    def test_list_duplicate_query_with_invalid_string_limit(self):
        self._test_list_flavors_with_invalid_filter(
            '/flavors?limit=1&limit=abc')

    def test_list_detail_duplicate_query_with_invalid_string_limit(self):
        self._test_list_flavors_with_invalid_filter(
            '/flavors/detail?limit=1&limit=abc')

    def _test_list_flavors_duplicate_query_parameters_validation(
            self, url, expected=None):
        controller_list = self.controller.index
        if 'detail' in url:
            controller_list = self.controller.detail
        expected_resp = [{
            "id":
            fakes.FLAVORS['2'].flavorid,
            "name":
            fakes.FLAVORS['2'].name,
            "links": [
                {
                    "rel": "self",
                    "href": "http://localhost/" + self._rspv + "/flavors/2",
                },
                {
                    "rel": "bookmark",
                    "href": "http://localhost" + self._fake + "/flavors/2",
                },
            ],
        }]
        if expected:
            expected_resp[0].update(expected)
        if self.expect_description:
            expected_resp[0]['description'] = (fakes.FLAVORS['2'].description)
        if 'detail' in url and self.expect_extra_specs:
            expected_resp[0]['extra_specs'] = (fakes.FLAVORS['2'].extra_specs)
        params = {
            'limit': 1,
            'marker': 1,
            'is_public': 't',
            'minRam': 2,
            'minDisk': 2,
            'sort_key': 'id',
            'sort_dir': 'asc'
        }

        for param, value in params.items():
            req = self._build_request(url + '?marker=1&%s=%s&%s=%s' %
                                      (param, value, param, value))
            result = controller_list(req)
            self.assertEqual(expected_resp, result['flavors'])

    def test_list_duplicate_query_parameters_validation(self):
        self._test_list_flavors_duplicate_query_parameters_validation(
            '/flavors')

    def test_list_detail_duplicate_query_parameters_validation(self):
        expected = {
            "ram": fakes.FLAVORS['2'].memory_mb,
            "disk": fakes.FLAVORS['2'].root_gb,
            "vcpus": fakes.FLAVORS['2'].vcpus,
            "os-flavor-access:is_public": True,
            "rxtx_factor": '',
            "OS-FLV-EXT-DATA:ephemeral": fakes.FLAVORS['2'].ephemeral_gb,
            "OS-FLV-DISABLED:disabled": fakes.FLAVORS['2'].disabled,
            "swap": fakes.FLAVORS['2'].swap
        }
        self._test_list_flavors_duplicate_query_parameters_validation(
            '/flavors/detail', expected)

    def _test_list_flavors_with_allowed_filter(self, url, expected=None):
        controller_list = self.controller.index
        if 'detail' in url:
            controller_list = self.controller.detail
        expected_resp = [{
            "id":
            fakes.FLAVORS['2'].flavorid,
            "name":
            fakes.FLAVORS['2'].name,
            "links": [
                {
                    "rel": "self",
                    "href": "http://localhost/" + self._rspv + "/flavors/2",
                },
                {
                    "rel": "bookmark",
                    "href": "http://localhost" + self._fake + "/flavors/2",
                },
            ],
        }]
        if expected:
            expected_resp[0].update(expected)
        if self.expect_description:
            expected_resp[0]['description'] = (fakes.FLAVORS['2'].description)
        if 'detail' in url and self.expect_extra_specs:
            expected_resp[0]['extra_specs'] = (fakes.FLAVORS['2'].extra_specs)
        req = self._build_request(url + '&limit=1&marker=1')
        result = controller_list(req)
        self.assertEqual(expected_resp, result['flavors'])

    def test_list_flavors_with_additional_filter(self):
        self._test_list_flavors_with_allowed_filter(
            '/flavors?limit=1&marker=1&additional=something')

    def test_list_detail_flavors_with_additional_filter(self):
        expected = {
            "ram": fakes.FLAVORS['2'].memory_mb,
            "disk": fakes.FLAVORS['2'].root_gb,
            "vcpus": fakes.FLAVORS['2'].vcpus,
            "os-flavor-access:is_public": True,
            "rxtx_factor": '',
            "OS-FLV-EXT-DATA:ephemeral": fakes.FLAVORS['2'].ephemeral_gb,
            "OS-FLV-DISABLED:disabled": fakes.FLAVORS['2'].disabled,
            "swap": fakes.FLAVORS['2'].swap
        }
        self._test_list_flavors_with_allowed_filter(
            '/flavors/detail?limit=1&marker=1&additional=something', expected)

    def test_list_flavors_with_min_ram_filter_as_negative_int(self):
        self._test_list_flavors_with_allowed_filter('/flavors?minRam=-2')

    def test_list_detail_flavors_with_min_ram_filter_as_negative_int(self):
        expected = {
            "ram": fakes.FLAVORS['2'].memory_mb,
            "disk": fakes.FLAVORS['2'].root_gb,
            "vcpus": fakes.FLAVORS['2'].vcpus,
            "os-flavor-access:is_public": True,
            "rxtx_factor": '',
            "OS-FLV-EXT-DATA:ephemeral": fakes.FLAVORS['2'].ephemeral_gb,
            "OS-FLV-DISABLED:disabled": fakes.FLAVORS['2'].disabled,
            "swap": fakes.FLAVORS['2'].swap
        }
        self._test_list_flavors_with_allowed_filter(
            '/flavors/detail?minRam=-2', expected)

    def test_list_flavors_with_min_ram_filter_as_float(self):
        self._test_list_flavors_with_invalid_filter(
            '/flavors?minRam=1.2', expected_exception=webob.exc.HTTPBadRequest)

    def test_list_detail_flavors_with_min_ram_filter_as_float(self):
        self._test_list_flavors_with_invalid_filter(
            '/flavors/detail?minRam=1.2',
            expected_exception=webob.exc.HTTPBadRequest)

    def test_list_flavors_with_min_disk_filter_as_negative_int(self):
        self._test_list_flavors_with_allowed_filter('/flavors?minDisk=-2')

    def test_list_detail_flavors_with_min_disk_filter_as_negative_int(self):
        expected = {
            "ram": fakes.FLAVORS['2'].memory_mb,
            "disk": fakes.FLAVORS['2'].root_gb,
            "vcpus": fakes.FLAVORS['2'].vcpus,
            "os-flavor-access:is_public": True,
            "rxtx_factor": '',
            "OS-FLV-EXT-DATA:ephemeral": fakes.FLAVORS['2'].ephemeral_gb,
            "OS-FLV-DISABLED:disabled": fakes.FLAVORS['2'].disabled,
            "swap": fakes.FLAVORS['2'].swap
        }
        self._test_list_flavors_with_allowed_filter(
            '/flavors/detail?minDisk=-2', expected)

    def test_list_flavors_with_min_disk_filter_as_float(self):
        self._test_list_flavors_with_invalid_filter(
            '/flavors?minDisk=1.2',
            expected_exception=webob.exc.HTTPBadRequest)

    def test_list_detail_flavors_with_min_disk_filter_as_float(self):
        self._test_list_flavors_with_invalid_filter(
            '/flavors/detail?minDisk=1.2',
            expected_exception=webob.exc.HTTPBadRequest)

    def test_list_flavors_with_is_public_filter_as_string_none(self):
        self._test_list_flavors_with_allowed_filter('/flavors?is_public=none')

    def test_list_detail_flavors_with_is_public_filter_as_string_none(self):
        expected = {
            "ram": fakes.FLAVORS['2'].memory_mb,
            "disk": fakes.FLAVORS['2'].root_gb,
            "vcpus": fakes.FLAVORS['2'].vcpus,
            "os-flavor-access:is_public": True,
            "rxtx_factor": '',
            "OS-FLV-EXT-DATA:ephemeral": fakes.FLAVORS['2'].ephemeral_gb,
            "OS-FLV-DISABLED:disabled": fakes.FLAVORS['2'].disabled,
            "swap": fakes.FLAVORS['2'].swap
        }
        self._test_list_flavors_with_allowed_filter(
            '/flavors/detail?is_public=none', expected)

    def test_list_flavors_with_is_public_filter_as_valid_bool(self):
        self._test_list_flavors_with_allowed_filter('/flavors?is_public=false')

    def test_list_detail_flavors_with_is_public_filter_as_valid_bool(self):
        expected = {
            "ram": fakes.FLAVORS['2'].memory_mb,
            "disk": fakes.FLAVORS['2'].root_gb,
            "vcpus": fakes.FLAVORS['2'].vcpus,
            "OS-FLV-EXT-DATA:ephemeral": fakes.FLAVORS['2'].ephemeral_gb,
            "os-flavor-access:is_public": True,
            "rxtx_factor": '',
            "OS-FLV-DISABLED:disabled": fakes.FLAVORS['2'].disabled,
            "swap": fakes.FLAVORS['2'].swap
        }
        self._test_list_flavors_with_allowed_filter(
            '/flavors/detail?is_public=false', expected)

    def test_list_flavors_with_is_public_filter_as_invalid_string(self):
        self._test_list_flavors_with_allowed_filter(
            '/flavors?is_public=invalid')

    def test_list_detail_flavors_with_is_public_filter_as_invalid_string(self):
        expected = {
            "ram": fakes.FLAVORS['2'].memory_mb,
            "disk": fakes.FLAVORS['2'].root_gb,
            "vcpus": fakes.FLAVORS['2'].vcpus,
            "os-flavor-access:is_public": True,
            "rxtx_factor": '',
            "OS-FLV-EXT-DATA:ephemeral": fakes.FLAVORS['2'].ephemeral_gb,
            "OS-FLV-DISABLED:disabled": fakes.FLAVORS['2'].disabled,
            "swap": fakes.FLAVORS['2'].swap
        }
        self._test_list_flavors_with_allowed_filter(
            '/flavors/detail?is_public=invalid', expected)