OSC Network Flavor Profile

Implement Neutron feature of Network Flavor Profile
into OpenstackClient
This patch implements the following commands:
network flavor profile create
network flavor profile delete
network flavor profile list
network flavor profile show
network flavor profile set

SDK Version needed: 0.9.9

Change-Id: Ie6fe5e53122cfb2eda8d326851d54562739a8386
Partially-Implements: blueprint neutron-client-flavors
This commit is contained in:
Nakul Dahiwade 2016-11-11 21:42:24 +00:00
parent 69b7b9b059
commit 7ef1e9ea96
8 changed files with 1057 additions and 0 deletions

View File

@ -0,0 +1,145 @@
======================
network flavor profile
======================
A **network flavor profile** allows administrators to create, delete, list,
show and update network service profile, which details a framework to enable
operators to configure and users to select from different abstract
representations of a service implementation in the Networking service.
It decouples the logical configuration from its instantiation enabling
operators to create user options according to deployment needs.
Network v2
network flavor profile create
-----------------------------
Create a new network flavor profile
.. program:: network flavor profile create
.. code:: bash
openstack network flavor profile create
[--project <project> [--project-domain <project-domain>]]
[--description <description>]
[--enable | --disable]
(--driver <driver> | --metainfo <metainfo> | --driver <driver> --metainfo <metainfo>)
.. option:: --project <project>
Owner's project (name or ID)
*Network version 2 only*
.. option:: --project-domain <project-domain>
Domain the project belongs to (name or ID). This can
be used in case collisions between project names
exist
.. option:: --description <description>
Description for the flavor profile
*Network version 2 only*
.. option:: --enable
Enable the flavor profile (default)
.. option:: --disable
Disable the flavor profile
.. option:: --driver <driver>
Python module path to driver
*Network version 2 only*
.. option:: --metainfo <metainfo>
Metainfo for the flavor profile
*Network version 2 only*
network flavor profile delete
-----------------------------
Delete network flavor profile
.. program:: network flavor profile delete
.. code:: bash
openstack network flavor profile delete
<flavor-profile-id> [<flavor-profile-id> ...]
.. describe:: <flavor-profile-id>
Flavor profile(s) to delete (ID only)
network flavor profile list
---------------------------
List network flavor profiles
.. program:: network flavor profile list
.. code:: bash
openstack network flavor profile list
network flavor profile set
--------------------------
Set network flavor profile properties
.. program:: network flavor profile set
.. code:: bash
openstack network flavor profile set
[--description <description>]
[--driver <driver>]
[--enable | --disable]
[--metainfo <metainfo>]
<flavor-profile-id>
.. option:: --description <description>
Description of the flavor profile
.. option:: --driver <driver>
Python module path to driver
.. option:: --enable (Default)
Enable the flavor profile
.. option:: --disable
Disable the flavor profile
.. option:: --metainfo <metainfo>
Metainfo for the flavor profile
.. describe:: <flavor-profile-id>
Flavor profile to update (ID only)
network flavor profile show
---------------------------
Show network flavor profile
.. program:: network flavor profile show
.. code:: bash
openstack network flavor profile show
<flavor-profile-id>
.. describe:: <flavor-profile-id>
Flavor profile to display (ID only)

View File

@ -113,6 +113,7 @@ referring to both Compute and Volume quotas.
* ``network agent``: (**Network**) - A network agent is an agent that handles various tasks used to implement virtual networks
* ``network auto allocated topology``: (**Network**) - an auto-allocated topology for a project
* ``network flavor``: (**Network**) - allows the user to choose the type of service by a set of advertised service capabilities (e.g., LOADBALANCER, FWAAS, L3, VPN, etc) rather than by a provider type or named vendor
* ``network flavor profile``: (**Network**) - predefined neutron service configurations: driver
* ``network meter``: (**Network**) - allow traffic metering in a network
* ``network meter rule``: (**Network**) - rules for network traffic metering
* ``network rbac``: (**Network**) - an RBAC policy for network resources

View File

@ -0,0 +1,250 @@
# 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.
#
import logging
from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import sdk_utils
LOG = logging.getLogger(__name__)
def _get_columns(item):
column_map = {
'is_enabled': 'enabled',
'tenant_id': 'project_id',
}
return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
def _get_attrs(client_manager, parsed_args):
attrs = {}
if parsed_args.description is not None:
attrs['description'] = parsed_args.description
if parsed_args.driver is not None:
attrs['driver'] = parsed_args.driver
if parsed_args.metainfo is not None:
attrs['metainfo'] = parsed_args.metainfo
if parsed_args.enable:
attrs['enabled'] = True
if parsed_args.disable:
attrs['enabled'] = False
if 'project' in parsed_args and parsed_args.project is not None:
identity_client = client_manager.identity
project_id = identity_common.find_project(
identity_client,
parsed_args.project,
parsed_args.project_domain,
).id
attrs['tenant_id'] = project_id
return attrs
# TODO(ndahiwade): Use the SDK resource mapped attribute names once the
# OSC minimum requirements include SDK 1.0.
class CreateNetworkFlavorProfile(command.ShowOne):
_description = _("Create new network flavor profile")
def get_parser(self, prog_name):
parser = super(CreateNetworkFlavorProfile, self).get_parser(prog_name)
parser.add_argument(
'--project',
metavar="<project>",
help=_("Owner's project (name or ID)")
)
identity_common.add_project_domain_option_to_parser(parser)
parser.add_argument(
'--description',
metavar="<description>",
help=_("Description for the flavor profile")
)
enable_group = parser.add_mutually_exclusive_group()
enable_group.add_argument(
'--enable',
action='store_true',
help=_("Enable the flavor profile")
)
enable_group.add_argument(
'--disable',
action='store_true',
help=_("Disable the flavor profile")
)
parser.add_argument(
'--driver',
help=_("Python module path to driver. This becomes "
"required if --metainfo is missing and vice versa")
)
parser.add_argument(
'--metainfo',
help=_("Metainfo for the flavor profile. This becomes "
"required if --driver is missing and vice versa")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.network
attrs = _get_attrs(self.app.client_manager, parsed_args)
if parsed_args.driver is None and parsed_args.metainfo is None:
msg = _("Either --driver or --metainfo or both are required")
raise exceptions.CommandError(msg)
obj = client.create_service_profile(**attrs)
display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters={})
return (display_columns, data)
class DeleteNetworkFlavorProfile(command.Command):
_description = _("Delete network flavor profile")
def get_parser(self, prog_name):
parser = super(DeleteNetworkFlavorProfile, self).get_parser(prog_name)
parser.add_argument(
'flavor_profile',
metavar='<flavor-profile>',
nargs='+',
help=_("Flavor profile(s) to delete (ID only)")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.network
result = 0
for flavor_profile in parsed_args.flavor_profile:
try:
obj = client.find_service_profile(flavor_profile,
ignore_missing=False)
client.delete_service_profile(obj)
except Exception as e:
result += 1
LOG.error(_("Failed to delete flavor profile with "
"ID '%(flavor_profile)s': %(e)s"),
{"flavor_profile": flavor_profile, "e": e})
if result > 0:
total = len(parsed_args.flavor_profile)
msg = (_("%(result)s of %(total)s flavor_profiles failed "
"to delete.") % {"result": result, "total": total})
raise exceptions.CommandError(msg)
class ListNetworkFlavorProfile(command.Lister):
_description = _("List network flavor profile(s)")
def take_action(self, parsed_args):
client = self.app.client_manager.network
columns = (
'id',
'driver',
'is_enabled',
'metainfo',
'description',
)
column_headers = (
'ID',
'Driver',
'Enabled',
'Metainfo',
'Description',
)
data = client.service_profiles()
return (column_headers,
(utils.get_item_properties(
s, columns,
) for s in data))
# TODO(ndahiwade): Use the SDK resource mapped attribute names once the
# OSC minimum requirements include SDK 1.0.
class SetNetworkFlavorProfile(command.Command):
_description = _("Set network flavor profile properties")
def get_parser(self, prog_name):
parser = super(SetNetworkFlavorProfile, self).get_parser(prog_name)
parser.add_argument(
'flavor_profile',
metavar="<flavor-profile>",
help=_("Flavor profile to update (ID only)")
)
identity_common.add_project_domain_option_to_parser(parser)
parser.add_argument(
'--description',
metavar="<description>",
help=_("Description for the flavor profile")
)
enable_group = parser.add_mutually_exclusive_group()
enable_group.add_argument(
'--enable',
action='store_true',
help=_("Enable the flavor profile")
)
enable_group.add_argument(
'--disable',
action='store_true',
help=_("Disable the flavor profile")
)
parser.add_argument(
'--driver',
help=_("Python module path to driver. This becomes "
"required if --metainfo is missing and vice versa")
)
parser.add_argument(
'--metainfo',
help=_("Metainfo for the flavor profile. This becomes "
"required if --driver is missing and vice versa")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.network
obj = client.find_service_profile(parsed_args.flavor_profile,
ignore_missing=False)
attrs = _get_attrs(self.app.client_manager, parsed_args)
client.update_service_profile(obj, **attrs)
class ShowNetworkFlavorProfile(command.ShowOne):
_description = _("Display network flavor profile details")
def get_parser(self, prog_name):
parser = super(ShowNetworkFlavorProfile, self).get_parser(prog_name)
parser.add_argument(
'flavor_profile',
metavar='<flavor-profile>',
help=_("Flavor profile to display (ID only)")
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.network
obj = client.find_service_profile(parsed_args.flavor_profile,
ignore_missing=False)
display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns)
return (display_columns, data)

View File

@ -0,0 +1,151 @@
# 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.
import json
from openstackclient.tests.functional import base
class NetworkFlavorProfileTests(base.TestCase):
"""Functional tests for network flavor-profile."""
DESCRIPTION = 'fakedescription'
METAINFO = 'Extrainfo'
def test_network_flavor_profile_create(self):
json_output = json.loads(self.openstack(
' network flavor profile create -f json --description '
+ self.DESCRIPTION + ' --enable --metainfo ' + self.METAINFO))
ID = json_output.get('id')
self.assertIsNotNone(ID)
self.assertEqual(
True,
json_output.get('enabled'))
self.assertEqual(
'fakedescription',
json_output.get('description'))
self.assertEqual(
'Extrainfo',
json_output.get('meta_info')
)
# Clean up
raw_output = self.openstack('network flavor profile delete ' + ID)
self.assertOutput('', raw_output)
def test_network_flavor_profile_list(self):
json_output = json.loads(self.openstack(
' network flavor profile create -f json --description '
+ self.DESCRIPTION + ' --enable --metainfo ' + self.METAINFO))
ID1 = json_output.get('id')
self.assertIsNotNone(ID1)
self.assertEqual(
True,
json_output.get('enabled'))
self.assertEqual(
'fakedescription',
json_output.get('description'))
self.assertEqual(
'Extrainfo',
json_output.get('meta_info')
)
json_output = json.loads(self.openstack(
' network flavor profile create -f json --description '
+ self.DESCRIPTION + ' --disable --metainfo ' + self.METAINFO))
ID2 = json_output.get('id')
self.assertIsNotNone(ID2)
self.assertEqual(
False,
json_output.get('enabled'))
self.assertEqual(
'fakedescription',
json_output.get('description'))
self.assertEqual(
'Extrainfo',
json_output.get('meta_info')
)
# Test list
json_output = json.loads(self.openstack(
'network flavor profile list -f json'))
self.assertIsNotNone(json_output)
id_list = [item.get('ID') for item in json_output]
self.assertIn(ID1, id_list)
self.assertIn(ID2, id_list)
# Clean up
raw_output = self.openstack(
'network flavor profile delete ' + ID1 + " " + ID2)
self.assertOutput('', raw_output)
def test_network_flavor_profile_set(self):
json_output_1 = json.loads(self.openstack(
' network flavor profile create -f json --description '
+ self.DESCRIPTION + ' --enable --metainfo ' + self.METAINFO))
ID = json_output_1.get('id')
self.assertIsNotNone(ID)
self.assertEqual(
True,
json_output_1.get('enabled'))
self.assertEqual(
'fakedescription',
json_output_1.get('description'))
self.assertEqual(
'Extrainfo',
json_output_1.get('meta_info')
)
self.openstack('network flavor profile set --disable ' + ID)
json_output = json.loads(self.openstack('network flavor profile show '
'-f json ' + ID))
self.assertEqual(
False,
json_output.get('enabled'))
self.assertEqual(
'fakedescription',
json_output.get('description'))
self.assertEqual(
'Extrainfo',
json_output.get('meta_info')
)
# Clean up
raw_output = self.openstack('network flavor profile delete ' + ID)
self.assertOutput('', raw_output)
def test_network_flavor_profile_show(self):
json_output_1 = json.loads(self.openstack(
' network flavor profile create -f json --description '
+ self.DESCRIPTION + ' --enable --metainfo ' + self.METAINFO))
ID = json_output_1.get('id')
self.assertIsNotNone(ID)
json_output = json.loads(self.openstack('network flavor profile show '
'-f json ' + ID))
self.assertEqual(
ID,
json_output["id"])
self.assertEqual(
True,
json_output["enabled"])
self.assertEqual(
'fakedescription',
json_output["description"])
self.assertEqual(
'Extrainfo',
json_output["meta_info"])
# Clean up
raw_output = self.openstack('network flavor profile delete ' + ID)
self.assertOutput('', raw_output)

View File

@ -769,6 +769,53 @@ class FakeNetworkRBAC(object):
return mock.Mock(side_effect=rbac_policies)
class FakeNetworkFlavorProfile(object):
"""Fake network flavor profile."""
@staticmethod
def create_one_service_profile(attrs=None):
"""Create flavor profile."""
attrs = attrs or {}
flavor_profile_attrs = {
'id': 'flavor-profile-id' + uuid.uuid4().hex,
'description': 'flavor-profile-description-' + uuid.uuid4().hex,
'tenant_id': 'project-id-' + uuid.uuid4().hex,
'driver': 'driver-' + uuid.uuid4().hex,
'metainfo': 'metainfo-' + uuid.uuid4().hex,
'enabled': True
}
flavor_profile_attrs.update(attrs)
flavor_profile = fakes.FakeResource(
info=copy.deepcopy(flavor_profile_attrs),
loaded=True)
flavor_profile.project_id = flavor_profile_attrs['tenant_id']
flavor_profile.is_enabled = flavor_profile_attrs['enabled']
return flavor_profile
@staticmethod
def create_service_profile(attrs=None, count=2):
"""Create multiple flavor profiles."""
flavor_profiles = []
for i in range(0, count):
flavor_profiles.append(FakeNetworkFlavorProfile.
create_one_service_profile(attrs))
return flavor_profiles
@staticmethod
def get_service_profile(flavor_profile=None, count=2):
"""Get a list of flavor profiles."""
if flavor_profile is None:
flavor_profile = (FakeNetworkFlavorProfile.
create_service_profile(count))
return mock.Mock(side_effect=flavor_profile)
class FakeNetworkQosPolicy(object):
"""Fake one or more QoS policies."""

View File

@ -0,0 +1,448 @@
# 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.
import mock
from osc_lib import exceptions
from openstackclient.network.v2 import network_flavor_profile
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes_v3
from openstackclient.tests.unit.network.v2 import fakes as network_fakes
class TestFlavorProfile(network_fakes.TestNetworkV2):
def setUp(self):
super(TestFlavorProfile, self).setUp()
# Get the network client
self.network = self.app.client_manager.network
# Get the ProjectManager Mock
self.projects_mock = self.app.client_manager.identity.projects
# Get the DomainManager Mock
self.domains_mock = self.app.client_manager.identity.domains
class TestCreateFlavorProfile(TestFlavorProfile):
project = identity_fakes_v3.FakeProject.create_one_project()
domain = identity_fakes_v3.FakeDomain.create_one_domain()
new_flavor_profile = (
network_fakes.FakeNetworkFlavorProfile.
create_one_service_profile()
)
columns = (
'description',
'driver',
'enabled',
'id',
'metainfo',
'project_id',
)
data = (
new_flavor_profile.description,
new_flavor_profile.driver,
new_flavor_profile.enabled,
new_flavor_profile.id,
new_flavor_profile.metainfo,
new_flavor_profile.project_id,
)
def setUp(self):
super(TestCreateFlavorProfile, self).setUp()
self.network.create_service_profile = mock.Mock(
return_value=self.new_flavor_profile)
self.projects_mock.get.return_value = self.project
# Get the command object to test
self.cmd = (network_flavor_profile.CreateNetworkFlavorProfile(
self.app, self.namespace))
def test_create_all_options(self):
arglist = [
"--description", self.new_flavor_profile.description,
"--project", self.new_flavor_profile.project_id,
'--project-domain', self.domain.name,
"--enable",
"--driver", self.new_flavor_profile.driver,
"--metainfo", self.new_flavor_profile.metainfo,
]
verifylist = [
('description', self.new_flavor_profile.description),
('project', self.new_flavor_profile.project_id),
('project_domain', self.domain.name),
('enable', True),
('driver', self.new_flavor_profile.driver),
('metainfo', self.new_flavor_profile.metainfo)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = (self.cmd.take_action(parsed_args))
self.network.create_service_profile.assert_called_once_with(
**{'description': self.new_flavor_profile.description,
'tenant_id': self.project.id,
'enabled': self.new_flavor_profile.enabled,
'driver': self.new_flavor_profile.driver,
'metainfo': self.new_flavor_profile.metainfo}
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, data)
def test_create_with_metainfo(self):
arglist = [
"--description", self.new_flavor_profile.description,
"--project", self.new_flavor_profile.project_id,
'--project-domain', self.domain.name,
"--enable",
"--metainfo", self.new_flavor_profile.metainfo,
]
verifylist = [
('description', self.new_flavor_profile.description),
('project', self.new_flavor_profile.project_id),
('project_domain', self.domain.name),
('enable', True),
('metainfo', self.new_flavor_profile.metainfo)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = (self.cmd.take_action(parsed_args))
self.network.create_service_profile.assert_called_once_with(
**{'description': self.new_flavor_profile.description,
'tenant_id': self.project.id,
'enabled': self.new_flavor_profile.enabled,
'metainfo': self.new_flavor_profile.metainfo}
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, data)
def test_create_with_driver(self):
arglist = [
"--description", self.new_flavor_profile.description,
"--project", self.new_flavor_profile.project_id,
'--project-domain', self.domain.name,
"--enable",
"--driver", self.new_flavor_profile.driver,
]
verifylist = [
('description', self.new_flavor_profile.description),
('project', self.new_flavor_profile.project_id),
('project_domain', self.domain.name),
('enable', True),
('driver', self.new_flavor_profile.driver),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = (self.cmd.take_action(parsed_args))
self.network.create_service_profile.assert_called_once_with(
**{'description': self.new_flavor_profile.description,
'tenant_id': self.project.id,
'enabled': self.new_flavor_profile.enabled,
'driver': self.new_flavor_profile.driver,
}
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, data)
def test_create_without_driver_and_metainfo(self):
arglist = [
"--description", self.new_flavor_profile.description,
"--project", self.new_flavor_profile.project_id,
'--project-domain', self.domain.name,
"--enable",
]
verifylist = [
('description', self.new_flavor_profile.description),
('project', self.new_flavor_profile.project_id),
('project_domain', self.domain.name),
('enable', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(
exceptions.CommandError,
self.cmd.take_action,
parsed_args,
)
def test_create_disable(self):
arglist = [
'--disable',
'--driver', self.new_flavor_profile.driver,
]
verifylist = [
('disable', True),
('driver', self.new_flavor_profile.driver)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.network.create_service_profile.assert_called_once_with(**{
'enabled': False,
'driver': self.new_flavor_profile.driver,
})
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, data)
class TestDeleteFlavorProfile(TestFlavorProfile):
# The network flavor_profiles to delete.
_network_flavor_profiles = (
network_fakes.FakeNetworkFlavorProfile.create_service_profile(count=2))
def setUp(self):
super(TestDeleteFlavorProfile, self).setUp()
self.network.delete_service_profile = mock.Mock(return_value=None)
self.network.find_service_profile = (
network_fakes.FakeNetworkFlavorProfile.get_service_profile(
flavor_profile=self._network_flavor_profiles)
)
# Get the command object to test
self.cmd = network_flavor_profile.DeleteNetworkFlavorProfile(
self.app, self.namespace)
def test_network_flavor_profile_delete(self):
arglist = [
self._network_flavor_profiles[0].id,
]
verifylist = [
('flavor_profile', [self._network_flavor_profiles[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.network.find_service_profile.assert_called_once_with(
self._network_flavor_profiles[0].id, ignore_missing=False)
self.network.delete_service_profile.assert_called_once_with(
self._network_flavor_profiles[0])
self.assertIsNone(result)
def test_multi_network_flavor_profiles_delete(self):
arglist = []
for a in self._network_flavor_profiles:
arglist.append(a.id)
verifylist = [
('flavor_profile', arglist),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
calls = []
for a in self._network_flavor_profiles:
calls.append(mock.call(a))
self.network.delete_service_profile.assert_has_calls(calls)
self.assertIsNone(result)
def test_multi_network_flavor_profiles_delete_with_exception(self):
arglist = [
self._network_flavor_profiles[0].id,
'unexist_network_flavor_profile',
]
verifylist = [
('flavor_profile',
[self._network_flavor_profiles[0].id,
'unexist_network_flavor_profile']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
find_mock_result = [self._network_flavor_profiles[0],
exceptions.CommandError]
self.network.find_service_profile = (
mock.Mock(side_effect=find_mock_result)
)
try:
self.cmd.take_action(parsed_args)
self.fail('CommandError should be raised.')
except exceptions.CommandError as e:
self.assertEqual('1 of 2 flavor_profiles failed to delete.',
str(e))
self.network.find_service_profile.assert_any_call(
self._network_flavor_profiles[0].id, ignore_missing=False)
self.network.find_service_profile.assert_any_call(
'unexist_network_flavor_profile', ignore_missing=False)
self.network.delete_service_profile.assert_called_once_with(
self._network_flavor_profiles[0]
)
class TestListFlavorProfile(TestFlavorProfile):
# The network flavor profiles list
_network_flavor_profiles = (
network_fakes.FakeNetworkFlavorProfile.create_service_profile(count=2))
columns = (
'ID',
'Driver',
'Enabled',
'Metainfo',
'Description',
)
data = []
for flavor_profile in _network_flavor_profiles:
data.append((
flavor_profile.id,
flavor_profile.driver,
flavor_profile.enabled,
flavor_profile.metainfo,
flavor_profile.description,
))
def setUp(self):
super(TestListFlavorProfile, self).setUp()
self.network.service_profiles = mock.Mock(
return_value=self._network_flavor_profiles)
# Get the command object to test
self.cmd = network_flavor_profile.ListNetworkFlavorProfile(
self.app, self.namespace)
def test_network_flavor_profile_list(self):
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.network.service_profiles.assert_called_once_with(**{})
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
class TestShowFlavorProfile(TestFlavorProfile):
# The network flavor profile to show.
network_flavor_profile = (
network_fakes.FakeNetworkFlavorProfile.create_one_service_profile())
columns = (
'description',
'driver',
'enabled',
'id',
'metainfo',
'project_id',
)
data = (
network_flavor_profile.description,
network_flavor_profile.driver,
network_flavor_profile.enabled,
network_flavor_profile.id,
network_flavor_profile.metainfo,
network_flavor_profile.project_id,
)
def setUp(self):
super(TestShowFlavorProfile, self).setUp()
self.network.find_service_profile = mock.Mock(
return_value=self.network_flavor_profile)
# Get the command object to test
self.cmd = network_flavor_profile.ShowNetworkFlavorProfile(
self.app, self.namespace)
def test_show_all_options(self):
arglist = [
self.network_flavor_profile.id,
]
verifylist = [
('flavor_profile', self.network_flavor_profile.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.network.find_service_profile.assert_called_once_with(
self.network_flavor_profile.id, ignore_missing=False)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, data)
class TestSetFlavorProfile(TestFlavorProfile):
# The network flavor profile to set.
network_flavor_profile = (
network_fakes.FakeNetworkFlavorProfile.create_one_service_profile())
def setUp(self):
super(TestSetFlavorProfile, self).setUp()
self.network.update_service_profile = mock.Mock(return_value=None)
self.network.find_service_profile = mock.Mock(
return_value=self.network_flavor_profile)
# Get the command object to test
self.cmd = network_flavor_profile.SetNetworkFlavorProfile(
self.app, self.namespace)
def test_set_nothing(self):
arglist = [self.network_flavor_profile.id]
verifylist = [
('flavor_profile', self.network_flavor_profile.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
attrs = {}
self.network.update_service_profile.assert_called_with(
self.network_flavor_profile, **attrs)
self.assertIsNone(result)
def test_set_enable(self):
arglist = [
'--enable',
self.network_flavor_profile.id,
]
verifylist = [
('enable', True),
('flavor_profile', self.network_flavor_profile.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
attrs = {
'enabled': True,
}
self.network.update_service_profile.assert_called_with(
self.network_flavor_profile, **attrs)
self.assertIsNone(result)
def test_set_disable(self):
arglist = [
'--disable',
self.network_flavor_profile.id,
]
verifylist = [
('disable', True),
('flavor_profile', self.network_flavor_profile.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
attrs = {
'enabled': False,
}
self.network.update_service_profile.assert_called_with(
self.network_flavor_profile, **attrs)
self.assertIsNone(result)

View File

@ -0,0 +1,9 @@
---
features:
- |
Add support for Network Flavor Profile commands:
``network flavor profile create``, ``network flavor profile delete``,
``network flavor profile list``, ``network flavor profile show`` and
``network flavor profile set``
[Blueprint :oscbp:`neutron-client-flavors`]

View File

@ -369,6 +369,12 @@ openstack.network.v2 =
network_flavor_set = openstackclient.network.v2.network_flavor:SetNetworkFlavor
network_flavor_show = openstackclient.network.v2.network_flavor:ShowNetworkFlavor
network_flavor_profile_create = openstackclient.network.v2.network_flavor_profile:CreateNetworkFlavorProfile
network_flavor_profile_delete = openstackclient.network.v2.network_flavor_profile:DeleteNetworkFlavorProfile
network_flavor_profile_list = openstackclient.network.v2.network_flavor_profile:ListNetworkFlavorProfile
network_flavor_profile_set = openstackclient.network.v2.network_flavor_profile:SetNetworkFlavorProfile
network_flavor_profile_show = openstackclient.network.v2.network_flavor_profile:ShowNetworkFlavorProfile
network_create = openstackclient.network.v2.network:CreateNetwork
network_delete = openstackclient.network.v2.network:DeleteNetwork
network_list = openstackclient.network.v2.network:ListNetwork