Add single command TC

This commit is contained in:
Ofer Ben-Yacov 2017-02-28 16:41:15 +02:00
parent 9c7a31f780
commit 97e1392d90
7 changed files with 288 additions and 8 deletions

View File

@ -36,3 +36,4 @@ neutronclient.extension =
wan_tc_filter = wan_qos.wanqos_client._wantcfilter
wan_tc_device = wan_qos.wanqos_client._wantcdevice
wan_tc_class = wan_qos.wanqos_client._wantcclass
wan_tc = wan_qos.wanqos_client._wantc

View File

@ -23,3 +23,6 @@ WAN_TC_CLASS_PATH = 'wan-tc-classs'
WAN_TC_FILTER = 'wan_tc_filter'
WAN_TC_FILTER_PATH = 'wan-tc-filters'
WAN_TC = 'wan_tc'
WAN_TC_PATH = 'wan-tcs'

View File

@ -244,6 +244,9 @@ class WanTcDb(object):
class_id=wan_tc_filter['class_id']
)
if 'network' in wan_tc_filter:
wtc_filter_db.network = wan_tc_filter['network']
with context.session.begin(subtransactions=True):
context.session.add(wtc_filter_db)
@ -254,7 +257,8 @@ class WanTcDb(object):
'id': wtc_filter_db.id,
'protocol': wtc_filter_db.protocol,
'match': wtc_filter_db.match,
'class_id': wtc_filter_db.class_id
'class_id': wtc_filter_db.class_id,
'network': wtc_filter_db.network
}
return wtc_filter

111
wan_qos/extensions/wantc.py Normal file
View File

@ -0,0 +1,111 @@
# Copyright 2017 Huawei corp.
# 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.
import abc
from neutron_lib.api import extensions
from neutron.api.v2 import resource_helper
from wan_qos.common import constants
RESOURCE_ATTRIBUTE_MAP = {
constants.WAN_TC_PATH: {
'id': {'allow_post': False, 'allow_put': False,
'is_visible': True},
'min': {'allow_post': True, 'allow_put': False,
'validate': {'type:string': None},
'is_visible': True,
'default': '',
},
'max': {'allow_post': True, 'allow_put': False,
'validate': {'type:string': None},
'is_visible': True,
'default': '',
},
'network': {'allow_post': True, 'allow_put': False,
'validate': {'type:string': None},
'is_visible': True,
'default': '',
},
'project_id': {'allow_post': True, 'allow_put': False,
'validate': {'type:string': None},
'required_by_policy': True,
'is_visible': True}
},
}
class Wantc(extensions.ExtensionDescriptor):
@classmethod
def get_name(cls):
return "WAN Traffic Control single command"
@classmethod
def get_alias(cls):
return "wan-tc"
@classmethod
def get_description(cls):
return "Class for limiting traffic on WAN links using single command"
@classmethod
def get_updated(cls):
return "2017-02-28T00:00:00-00:00"
@classmethod
def get_resources(cls):
"""Returns Ext Resources."""
mem_actions = {}
plural_mappings = resource_helper.build_plural_mappings(
{}, RESOURCE_ATTRIBUTE_MAP)
resources = resource_helper.build_resource_info(plural_mappings,
RESOURCE_ATTRIBUTE_MAP,
constants.WANTC,
action_map=mem_actions,
register_quota=True,
translate_name=True)
return resources
def get_extended_resources(self, version):
if version == "2.0":
return RESOURCE_ATTRIBUTE_MAP
else:
return {}
class WanTcPluginBase(object):
@abc.abstractmethod
def create_wan_tc(self, context, wan_tc):
pass
@abc.abstractmethod
def get_wan_tc(self, context, id, fields=None):
pass
@abc.abstractmethod
def get_wan_tcs(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
pass
@abc.abstractmethod
def update_wan_tc(self, context, id, wan_tc):
pass
@abc.abstractmethod
def delete_wan_tc(self, context, id):
pass

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from neutron_lib.plugins import directory
from neutron.common import rpc as n_rpc
from neutron.db import agents_db
from neutron_lib import exceptions
@ -30,6 +31,7 @@ from wan_qos.db import wan_qos_db
from wan_qos.extensions import wantcfilter
from wan_qos.extensions import wantcdevice
from wan_qos.extensions import wantcclass
from wan_qos.extensions import wantc
LOG = logging.getLogger(__name__)
@ -63,9 +65,10 @@ class PluginRpcCallback(object):
class WanQosPlugin(wantcfilter.WanTcFilterPluginBase,
wantcdevice.WanTcDevicePluginBase,
wantcclass.WanTcClassPluginBase):
wantcclass.WanTcClassPluginBase,
wantc.WanTcPluginBase):
supported_extension_aliases = ['wan-tc-filter', 'wan-tc-device',
'wan-tc-class']
'wan-tc-class', 'wan-tc']
def __init__(self):
self.db = wan_qos_db.WanTcDb()
@ -88,6 +91,10 @@ class WanQosPlugin(wantcfilter.WanTcFilterPluginBase,
"""Get description of the plugin."""
return 'Plugin for rate limiting on WAN links.'
@property
def _core_plugin(self):
return directory.get_plugin()
def delete_wan_tc_device(self, context, id):
self.db.delete_wan_tc_device(context, id)
@ -167,3 +174,67 @@ class WanQosPlugin(wantcfilter.WanTcFilterPluginBase,
else:
tenant_id = context.tenant_id
return tenant_id
def get_wan_tc(self, context, id, fields=None):
filter_db = self.get_wan_tc_filter(context, id, fields)
class_db = self.get_wan_tc_class(context, filter_db['class_id'])
filter_db['min'] = class_db['min']
filter_db['max'] = class_db['max']
return filter_db
def get_wan_tcs(self, context, filters=None, fields=None, sorts=None,
limit=None, marker=None, page_reverse=False):
filters = self.get_wan_tc_filters(context, filters, fields, sorts,
limit, marker, page_reverse)
for filter_db in filters:
class_db = self.get_wan_tc_class(context, filter_db['class_id'])
filter_db['min'] = class_db['min']
filter_db['max'] = class_db['max']
return filters
def create_wan_tc(self, context, wan_tc):
LOG.debug('got WAN_TC: %s' % wan_tc)
wan_tc_req = wan_tc['wan_tc']
filter_db = self.get_wan_tc_filters(context, filters={
'network': [wan_tc_req['network']]})
if filter_db:
raise exceptions.InvalidInput(
error_message='Network already has limiter')
network = self._core_plugin.get_network(context, wan_tc_req['network'])
if network['provider:network_type'] != 'vxlan':
raise exceptions.InvalidInput()
vni = network['provider:segmentation_id']
tc_class = {'wan_tc_class': {
'direction': 'both',
'min': wan_tc_req['min']
}
}
if 'max' in wan_tc_req:
tc_class['wan_tc_class']['max'] = wan_tc_req['max']
tc_class_db = self.create_wan_tc_class(context, tc_class)
tc_filter_req = {'wan_tc_filter': {
'protocol': 'vxlan',
'match': 'vni=%s' % vni,
'class_id': tc_class_db['id'],
'network': network['id']
}
}
tc_filter_db = self.create_wan_tc_filter(context, tc_filter_req)
tc_filter_db['min'] = tc_class_db['min']
tc_filter_db['max'] = tc_class_db['max']
return tc_filter_db
def update_wan_tc(self, context, id, wan_tc):
raise exceptions.BadRequest(msg='Not implemented yet!')
def delete_wan_tc(self, context, id):
LOG.debug('Deleting TC: %s' % id)
tc_filter = self.get_wan_tc_filter(context, id)
class_id = tc_filter['class_id']
self.delete_wan_tc_filter(context, id)
self.delete_wan_tc_class(context, class_id)

View File

@ -0,0 +1,90 @@
# Copyright 2017 Huawei corp.
# 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.
from neutronclient._i18n import _
from neutronclient.common import extension
from neutronclient.common import exceptions
from wan_qos.common import constants
class WanTc(extension.NeutronClientExtension):
resource = constants.WAN_TC
resource_plural = '%ss' % constants.WAN_TC
path = constants.WAN_TC_PATH
object_path = '/%s' % path
resource_path = '/%s/%%s' % path
versions = ['2.0']
class WanTcShow(extension.ClientExtensionShow, WanTc):
shell_command = 'wan-tc-show'
class WanTcList(extension.ClientExtensionList, WanTc):
shell_command = 'wan-tc-list'
list_columns = ['id', 'network', 'min', 'max']
pagination_support = True
sorting_support = True
class WanTcCreate(extension.ClientExtensionCreate, WanTc):
shell_command = 'wan-tc-create'
def add_known_arguments(self, parser):
parser.add_argument(
'network', metavar='<network>',
help=_('Network ID'))
parser.add_argument(
'--min',
dest='min',
help=_('Set committed rate. (mbit / kbit)'))
parser.add_argument(
'--max',
dest='max',
help=_('Set maximum rate. (mbit / kbit)'))
def args2body(self, parsed_args):
body = {
'network': parsed_args.network
}
if parsed_args.min:
body['min'] = parsed_args.min
else:
raise exceptions.BadRequest('min must be set')
if parsed_args.max:
body['max'] = parsed_args.max
return {self.resource: body}
class WanTcDelete(extension.ClientExtensionDelete, WanTc):
shell_command = 'wan-tc-delete'
class WanTcUpdate(extension.ClientExtensionUpdate, WanTc):
shell_command = 'wan-tc-update'
def add_known_arguments(self, parser):
pass
def args2body(self, parsed_args):
body = {}
return {self.resource: body}

View File

@ -31,18 +31,18 @@ class WanTcClass(extension.NeutronClientExtension):
versions = ['2.0']
class WanTcShow(extension.ClientExtensionShow, WanTcClass):
class WanTcClassShow(extension.ClientExtensionShow, WanTcClass):
shell_command = 'wan-tc-class-show'
class WanTcList(extension.ClientExtensionList, WanTcClass):
class WanTcClassList(extension.ClientExtensionList, WanTcClass):
shell_command = 'wan-tc-class-list'
list_columns = ['id', 'parent', 'direction', 'min', 'max']
pagination_support = True
sorting_support = True
class WanTcCreate(extension.ClientExtensionCreate, WanTcClass):
class WanTcClassCreate(extension.ClientExtensionCreate, WanTcClass):
shell_command = 'wan-tc-class-create'
def add_known_arguments(self, parser):
@ -84,11 +84,11 @@ class WanTcCreate(extension.ClientExtensionCreate, WanTcClass):
return {self.resource: body}
class WanTcDelete(extension.ClientExtensionDelete, WanTcClass):
class WanTcClassDelete(extension.ClientExtensionDelete, WanTcClass):
shell_command = 'wan-tc-class-delete'
class WanTcUpdate(extension.ClientExtensionUpdate, WanTcClass):
class WanTcClassUpdate(extension.ClientExtensionUpdate, WanTcClass):
shell_command = 'wan-tc-class-update'
def add_known_arguments(self, parser):