¡@

Home 

OpenStack Study: test_portbindings.py

OpenStack Index

**** CubicPower OpenStack Study ****

# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2013 NEC Corporation

# All rights reserved.

#

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

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

# a copy of the License at

#

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

#

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

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

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

# License for the specific language governing permissions and limitations

# under the License.

#

# @author: Akihiro Motoki, NEC Corporation

from oslo.config import cfg

from testtools import matchers

from webob import exc

from neutron.common import exceptions as n_exc

from neutron import context

from neutron.extensions import portbindings

from neutron.tests.unit import _test_extension_portbindings as test_bindings

from neutron.tests.unit.nec import test_nec_plugin

from neutron.tests.unit import test_security_groups_rpc as test_sg_rpc

**** CubicPower OpenStack Study ****

class TestNecPortBinding(test_bindings.PortBindingsTestCase, test_nec_plugin.NecPluginV2TestCase):

VIF_TYPE = portbindings.VIF_TYPE_OVS

HAS_PORT_FILTER = True

ENABLE_SG = True

FIREWALL_DRIVER = test_sg_rpc.FIREWALL_HYBRID_DRIVER

**** CubicPower OpenStack Study ****

    def setUp(self):

        test_sg_rpc.set_firewall_driver(self.FIREWALL_DRIVER)

        cfg.CONF.set_override(

            'enable_security_group', self.ENABLE_SG,

            group='SECURITYGROUP')

        super(TestNecPortBinding, self).setUp()

**** CubicPower OpenStack Study ****

class TestNecPortBindingNoSG(TestNecPortBinding):

HAS_PORT_FILTER = False

ENABLE_SG = False

FIREWALL_DRIVER = test_sg_rpc.FIREWALL_NOOP_DRIVER

**** CubicPower OpenStack Study ****

class TestNecPortBindingHost( test_bindings.PortBindingsHostTestCaseMixin, test_nec_plugin.NecPluginV2TestCase):

pass

**** CubicPower OpenStack Study ****

class TestNecPortBindingPortInfo(test_nec_plugin.NecPluginV2TestCase):

**** CubicPower OpenStack Study ****

    def _get_portinfo(self, datapath_id=None, port_no=None):

        if datapath_id is None:

            datapath_id = '0xabc'

        if port_no is None:

            port_no = 1

        return {'datapath_id': datapath_id,

                'port_no': port_no}

**** CubicPower OpenStack Study ****

    def _check_response_portbinding_profile(self, port, datapath_id=None,

                                            port_no=None):

        expected = self._get_portinfo(datapath_id, port_no)

        profile = port[portbindings.PROFILE]

        self.assertEqual(len(profile), 2)

        self.assertEqual(profile['datapath_id'],

                         expected['datapath_id'])

        self.assertEqual(profile['port_no'],

                         expected['port_no'])

**** CubicPower OpenStack Study ****

    def _check_response_portbinding_no_profile(self, port):

        self.assertIn('status', port)

        self.assertNotIn(portbindings.PROFILE, port)

**** CubicPower OpenStack Study ****

    def _get_non_admin_context(self):

        return context.Context(user_id=None,

                               tenant_id=self._tenant_id,

                               is_admin=False,

                               read_deleted="no")

**** CubicPower OpenStack Study ****

    def test_port_create_portinfo(self):

        profile_arg = {portbindings.PROFILE: self._get_portinfo()}

        with self.port(arg_list=(portbindings.PROFILE,),

                       **profile_arg) as port:

            port_id = port['port']['id']

            # Check a response of create_port

            self._check_response_portbinding_profile(port['port'])

            self.assertEqual(self.ofc.create_ofc_port.call_count, 1)

            # Check a response of get_port

            ctx = context.get_admin_context()

            port = self._show('ports', port_id, neutron_context=ctx)['port']

            self._check_response_portbinding_profile(port)

            # By default user is admin - now test non admin user

            ctx = self._get_non_admin_context()

            non_admin_port = self._show(

                'ports', port_id, neutron_context=ctx)['port']

            self._check_response_portbinding_no_profile(non_admin_port)

            # port-update with non admin user should fail

            self._update('ports', port_id,

                         {'port': profile_arg},

                         expected_code=404,

                         neutron_context=ctx)

**** CubicPower OpenStack Study ****

    def test_port_update_portinfo(self):

        profile_arg = {portbindings.PROFILE: self._get_portinfo()}

        with self.port() as port:

            self.assertEqual(self.ofc.create_ofc_port.call_count, 0)

            port_id = port['port']['id']

            # Check a response of create_port

            self._check_response_portbinding_no_profile(port['port'])

            # Check a response of update_port

            ctx = context.get_admin_context()

            port = self._update('ports', port_id, {'port': profile_arg},

                                neutron_context=ctx)['port']

            self.assertEqual(self.ofc.create_ofc_port.call_count, 1)

            self._check_response_portbinding_profile(port)

            port = self._show('ports', port_id, neutron_context=ctx)['port']

            self._check_response_portbinding_profile(port)

**** CubicPower OpenStack Study ****

    def test_port_update_portinfo_detail(self):

        with self.port() as port:

            self.assertEqual(self.ofc.create_ofc_port.call_count, 0)

            self.assertEqual(self.ofc.delete_ofc_port.call_count, 0)

            port_id = port['port']['id']

            ctx = context.get_admin_context()

            # add portinfo

            profile_arg = {portbindings.PROFILE: self._get_portinfo()}

            port = self._update('ports', port_id, {'port': profile_arg},

                                neutron_context=ctx)['port']

            self.assertEqual(self.ofc.create_ofc_port.call_count, 1)

            self.assertEqual(self.ofc.delete_ofc_port.call_count, 0)

            # portinfo unchanged

            port = self._update('ports', port_id, {'port': profile_arg},

                                neutron_context=ctx)['port']

            self.assertEqual(self.ofc.create_ofc_port.call_count, 1)

            self.assertEqual(self.ofc.delete_ofc_port.call_count, 0)

            # modify portinfo

            profile_arg = {portbindings.PROFILE:

                           self._get_portinfo(datapath_id='0x1234567890',

                                              port_no=99)}

            port = self._update('ports', port_id, {'port': profile_arg},

                                neutron_context=ctx)['port']

            self.assertEqual(self.ofc.create_ofc_port.call_count, 2)

            self.assertEqual(self.ofc.delete_ofc_port.call_count, 1)

            # delete portinfo with an empty dict

            profile_arg = {portbindings.PROFILE: {}}

            port = self._update('ports', port_id, {'port': profile_arg},

                                neutron_context=ctx)['port']

            self.assertEqual(self.ofc.create_ofc_port.call_count, 2)

            self.assertEqual(self.ofc.delete_ofc_port.call_count, 2)

**** CubicPower OpenStack Study ****

    def test_port_update_portinfo_detail_clear_with_none(self):

        with self.port() as port:

            self.assertEqual(self.ofc.create_ofc_port.call_count, 0)

            self.assertEqual(self.ofc.delete_ofc_port.call_count, 0)

            port_id = port['port']['id']

            ctx = context.get_admin_context()

            # add portinfo

            profile_arg = {portbindings.PROFILE: self._get_portinfo()}

            port = self._update('ports', port_id, {'port': profile_arg},

                                neutron_context=ctx)['port']

            self.assertEqual(self.ofc.create_ofc_port.call_count, 1)

            self.assertEqual(self.ofc.delete_ofc_port.call_count, 0)

            # delete portinfo with None

            profile_arg = {portbindings.PROFILE: None}

            port = self._update('ports', port_id, {'port': profile_arg},

                                neutron_context=ctx)['port']

            self.assertEqual(self.ofc.create_ofc_port.call_count, 1)

            self.assertEqual(self.ofc.delete_ofc_port.call_count, 1)

**** CubicPower OpenStack Study ****

    def test_port_create_portinfo_with_empty_dict(self):

        profile_arg = {portbindings.PROFILE: {}}

        with self.port(arg_list=(portbindings.PROFILE,),

                       **profile_arg) as port:

            port_id = port['port']['id']

            # Check a response of create_port

            self._check_response_portbinding_no_profile(port['port'])

            self.assertEqual(self.ofc.create_ofc_port.call_count, 0)

            # add portinfo

            ctx = context.get_admin_context()

            profile_arg = {portbindings.PROFILE: self._get_portinfo()}

            port = self._update('ports', port_id, {'port': profile_arg},

                                neutron_context=ctx)['port']

            self._check_response_portbinding_profile(port)

            self.assertEqual(self.ofc.create_ofc_port.call_count, 1)

            self.assertEqual(self.ofc.delete_ofc_port.call_count, 0)

**** CubicPower OpenStack Study ****

    def test_port_create_portinfo_with_none(self):

        profile_arg = {portbindings.PROFILE: None}

        with self.port(arg_list=(portbindings.PROFILE,),

                       **profile_arg) as port:

            port_id = port['port']['id']

            # Check a response of create_port

            self._check_response_portbinding_no_profile(port['port'])

            self.assertEqual(self.ofc.create_ofc_port.call_count, 0)

            # add portinfo

            ctx = context.get_admin_context()

            profile_arg = {portbindings.PROFILE: self._get_portinfo()}

            port = self._update('ports', port_id, {'port': profile_arg},

                                neutron_context=ctx)['port']

            self._check_response_portbinding_profile(port)

            self.assertEqual(self.ofc.create_ofc_port.call_count, 1)

            self.assertEqual(self.ofc.delete_ofc_port.call_count, 0)

**** CubicPower OpenStack Study ****

    def test_port_update_for_existing_port_with_different_padding_dpid(self):

        ctx = context.get_admin_context()

        with self.port() as port:

            port_id = port['port']['id']

            portinfo = {'id': port_id, 'port_no': 123}

            self.rpcapi_update_ports(datapath_id='0x000000000000abcd',

                                     added=[portinfo])

            self.assertEqual(1, self.ofc.create_ofc_port.call_count)

            self.assertEqual(0, self.ofc.delete_ofc_port.call_count)

            profile_arg = {portbindings.PROFILE:

                           self._get_portinfo(datapath_id='0xabcd',

                                              port_no=123)}

            self._update('ports', port_id, {'port': profile_arg},

                         neutron_context=ctx)

            # Check create_ofc_port/delete_ofc_port are not called.

            self.assertEqual(1, self.ofc.create_ofc_port.call_count)

            self.assertEqual(0, self.ofc.delete_ofc_port.call_count)

**** CubicPower OpenStack Study ****

    def test_port_create_portinfo_non_admin(self):

        with self.network(set_context=True, tenant_id='test') as net1:

            with self.subnet(network=net1) as subnet1:

                profile_arg = {portbindings.PROFILE: self._get_portinfo()}

                try:

                    with self.port(subnet=subnet1,

                                   expected_res_status=403,

                                   arg_list=(portbindings.PROFILE,),

                                   set_context=True, tenant_id='test',

                                   **profile_arg):

                        pass

                except exc.HTTPClientError:

                    pass

                self.assertEqual(self.ofc.create_ofc_port.call_count, 0)

**** CubicPower OpenStack Study ****

    def test_port_update_portinfo_non_admin(self):

        profile_arg = {portbindings.PROFILE: self._get_portinfo()}

        with self.network() as net1:

            with self.subnet(network=net1) as subnet1:

                with self.port(subnet=subnet1) as port:

                    # By default user is admin - now test non admin user

                    # Note that 404 is returned when prohibit by policy.

                    # See comment for PolicyNotAuthorized except clause

                    # in update() in neutron.api.v2.base.Controller.

                    port_id = port['port']['id']

                    ctx = self._get_non_admin_context()

                    port = self._update('ports', port_id,

                                        {'port': profile_arg},

                                        expected_code=404,

                                        neutron_context=ctx)

                self.assertEqual(self.ofc.create_ofc_port.call_count, 0)

**** CubicPower OpenStack Study ****

    def test_port_create_portinfo_validation_called(self):

        # Check validate_portinfo is called.

        profile_arg = {portbindings.PROFILE:

                       {'datapath_id': '0xabc',

                        'port_no': 0xffff + 1}}

        try:

            with self.port(arg_list=(portbindings.PROFILE,),

                           expected_res_status=400,

                           **profile_arg):

                pass

        except exc.HTTPClientError:

            pass

**** CubicPower OpenStack Study ****

class TestNecPortBindingValidatePortInfo(test_nec_plugin.NecPluginV2TestCase):

**** CubicPower OpenStack Study ****

    def test_validate_portinfo_ok(self):

        profile = {'datapath_id': '0x1234567890abcdef',

                   'port_no': 123}

        portinfo = self.plugin._validate_portinfo(profile)

        # NOTE(mriedem): Handle long integer conversion universally.

        self.assertEqual(

            0x1234567890abcdef,

            int(portinfo['datapath_id'].replace('L', ''), 16)

        )

        self.assertEqual(portinfo['port_no'], 123)

**** CubicPower OpenStack Study ****

    def test_validate_portinfo_ok_without_0x(self):

        profile = {'datapath_id': '1234567890abcdef',

                   'port_no': 123}

        portinfo = self.plugin._validate_portinfo(profile)

        # NOTE(mriedem): Handle long integer conversion universally.

        self.assertEqual(

            0x1234567890abcdef,

            int(portinfo['datapath_id'].replace('L', ''), 16)

        )

        self.assertEqual(portinfo['port_no'], 123)

**** CubicPower OpenStack Study ****

    def _test_validate_exception(self, profile, expected_msg):

        e = self.assertRaises(n_exc.InvalidInput,

                              self.plugin._validate_portinfo, profile)

        self.assertThat(str(e), matchers.StartsWith(expected_msg))

**** CubicPower OpenStack Study ****

    def test_validate_portinfo_dict_validation(self):

        expected_msg = ("Invalid input for operation: "

                        "Validation of dictionary's keys failed.")

        profile = {'port_no': 123}

        self._test_validate_exception(profile, expected_msg)

        profile = {'datapath_id': '0xabcdef'}

        self._test_validate_exception(profile, expected_msg)

**** CubicPower OpenStack Study ****

    def test_validate_portinfo_negative_port_number(self):

        profile = {'datapath_id': '0x1234567890abcdef',

                   'port_no': -1}

        expected_msg = ("Invalid input for operation: "

                        "'-1' should be non-negative.")

        self._test_validate_exception(profile, expected_msg)

**** CubicPower OpenStack Study ****

    def test_validate_portinfo_invalid_datapath_id(self):

        expected_msg = ("Invalid input for operation: "

                        "datapath_id should be a hex string")

        # non hexidecimal datapath_id

        profile = {'datapath_id': 'INVALID',

                   'port_no': 123}

        self._test_validate_exception(profile, expected_msg)

        # Too big datapath_id

        profile = {'datapath_id': '0x10000000000000000',

                   'port_no': 123}

        self._test_validate_exception(profile, expected_msg)

**** CubicPower OpenStack Study ****

    def test_validate_portinfo_too_big_port_number(self):

        profile = {'datapath_id': '0x1234567890abcdef',

                   'port_no': 65536}

        expected_msg = ("Invalid input for operation: "

                        "port_no should be [0:65535]")

        self._test_validate_exception(profile, expected_msg)