diff --git a/doc/source/command-objects/network-flavor-profile.rst b/doc/source/command-objects/network-flavor-profile.rst
new file mode 100644
index 0000000000..fdb95059b8
--- /dev/null
+++ b/doc/source/command-objects/network-flavor-profile.rst
@@ -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)
diff --git a/doc/source/commands.rst b/doc/source/commands.rst
index a0c67cd4c8..ccd081e8d6 100644
--- a/doc/source/commands.rst
+++ b/doc/source/commands.rst
@@ -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
diff --git a/openstackclient/network/v2/network_flavor_profile.py b/openstackclient/network/v2/network_flavor_profile.py
new file mode 100644
index 0000000000..6cf0c4124d
--- /dev/null
+++ b/openstackclient/network/v2/network_flavor_profile.py
@@ -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)
diff --git a/openstackclient/tests/functional/network/v2/test_network_flavor_profile.py b/openstackclient/tests/functional/network/v2/test_network_flavor_profile.py
new file mode 100644
index 0000000000..1a82c82b0c
--- /dev/null
+++ b/openstackclient/tests/functional/network/v2/test_network_flavor_profile.py
@@ -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)
diff --git a/openstackclient/tests/unit/network/v2/fakes.py b/openstackclient/tests/unit/network/v2/fakes.py
index 7afe332885..a2274a34e4 100644
--- a/openstackclient/tests/unit/network/v2/fakes.py
+++ b/openstackclient/tests/unit/network/v2/fakes.py
@@ -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."""
 
diff --git a/openstackclient/tests/unit/network/v2/test_network_flavor_profile.py b/openstackclient/tests/unit/network/v2/test_network_flavor_profile.py
new file mode 100644
index 0000000000..91683241c2
--- /dev/null
+++ b/openstackclient/tests/unit/network/v2/test_network_flavor_profile.py
@@ -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)
diff --git a/releasenotes/notes/add-network-flavor-profile-e7cc5b353c3ed9d9.yaml b/releasenotes/notes/add-network-flavor-profile-e7cc5b353c3ed9d9.yaml
new file mode 100644
index 0000000000..b604762dc8
--- /dev/null
+++ b/releasenotes/notes/add-network-flavor-profile-e7cc5b353c3ed9d9.yaml
@@ -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`]
+
diff --git a/setup.cfg b/setup.cfg
index e18aa5c1e7..87251a9092 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -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