Add class entity

This commit is contained in:
Ofer Ben-Yacov 2017-01-17 17:34:05 +02:00
parent 94e5d09b84
commit b71d3489c8
9 changed files with 323 additions and 42 deletions

View File

@ -35,3 +35,4 @@ neutron.db.alembic_migrations =
neutronclient.extension =
wan_qos = wan_qos.wanqos_client._wanqos
wan_tc_device = wan_qos.wanqos_client._wantcdevice
wan_tc_class = wan_qos.wanqos_client._wantcclass

View File

@ -18,4 +18,7 @@ WAN_TC = 'wan_tc'
WAN_TC_PATH = 'wan-tcs'
WAN_TC_DEVICE = 'wan_tc_device'
WAN_TC_DEVICE_PATH = 'wan-tc-devices'
WAN_TC_DEVICE_PATH = 'wan-tc-devices'
WAN_TC_CLASS = 'wan_tc_class'
WAN_TC_CLASS_PATH = 'wan-tc-classs'

View File

@ -32,30 +32,22 @@ import sqlalchemy as sa
def upgrade():
op.create_table('wan_tc_class',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('parent_class', sa.String(length=36), nullable=False),
sa.Column('device_id', sa.String(length=36),
nullable=False),
sa.Column('project_id', sa.String(length=36),
nullable=False),
sa.Column('network_id', sa.String(length=36),
sa.Column('parent', sa.String(length=36)),
sa.Column('device_id', sa.String(length=36)),
sa.Column('direction', sa.String(length=4),
nullable=False),
sa.Column('project_id', sa.String(length=36)),
sa.Column('class_ext_id', sa.Integer()),
sa.Column('min_rate',
sa.String(length=15), nullable=False),
sa.Column('max_rate', sa.String(length=15)),
sa.Column('min', sa.String(length=15)),
sa.Column('max', sa.String(length=15)),
sa.PrimaryKeyConstraint('id')
)
op.create_foreign_key(
'fk_wan_tc_class_networks',
'wan_tc_class', 'networks',
['network_id'], ['id'],
)
op.create_table('wan_tc_selector',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('class_id', sa.String(length=36),
nullable=False),
sa.Column('network_id', sa.String(length=36)),
sa.Column('protocol', sa.String(length=15)),
sa.Column('match', sa.String(length=15)),
sa.PrimaryKeyConstraint('id')
@ -67,6 +59,12 @@ def upgrade():
['class_id'], ['id'],
)
op.create_foreign_key(
'fk_wan_tc_selector_networks',
'wan_tc_selector', 'networks',
['network_id'], ['id'],
)
op.create_table(
'wan_tc_device',
sa.Column('id', sa.String(length=36), nullable=False),

View File

@ -15,7 +15,6 @@
import sqlalchemy as sa
from neutron_lib.db import model_base
@ -30,32 +29,31 @@ class WanTcDevice(model_base.BASEV2,
class WanTcClass(model_base.BASEV2,
model_base.HasId, model_base.HasProject):
model_base.HasId, model_base.HasProject):
__tablename__ = 'wan_tc_class'
device_id = sa.Column(sa.String(36),
sa.ForeignKey('wan_tc_device.id',
ondelete='CASCADE'),
nullable=False)
sa.ForeignKey('wan_tc_device.id',
ondelete='CASCADE'),
nullable=True)
direction = sa.Column(sa.String(4), nullable=False)
class_ext_id = sa.Column(sa.Integer)
parent_class = sa.Column(sa.String(36),
sa.ForeignKey('wan_tc_class.id',
ondelete='CASCADE'),
nullable=True)
network_id = sa.Column(sa.String(36),
sa.ForeignKey('networks.id',
ondelete='CASCADE'),
nullable=False)
min_rate = sa.Column(sa.String(15), nullable=False)
max_rate = sa.Column(sa.String(15))
parent = sa.Column(sa.String(36),
sa.ForeignKey('wan_tc_class.id',
ondelete='CASCADE'),
nullable=True)
min = sa.Column(sa.String(15))
max = sa.Column(sa.String(15))
class WanTcSelector(model_base.BASEV2,
model_base.HasId, model_base.HasProject):
model_base.HasId, model_base.HasProject):
__tablename__ = 'wan_tc_selector'
class_id = sa.Column(sa.String(36),
sa.ForeignKey('wan_tc_class.id',
ondelete='CASCADE'),
nullable=False)
network_id = sa.Column(sa.String(36),
sa.ForeignKey('network.id',
ondelete='CASCADE'))
protocol = sa.Column(sa.String(15))
match = sa.Column(sa.String(15))

View File

@ -17,6 +17,8 @@ from oslo_utils import uuidutils
from oslo_utils import timeutils
from oslo_log import log as logging
from neutron.db.models import segment
from wan_qos.db.models import wan_tc as models
from wan_qos.common import constants
@ -41,7 +43,7 @@ class WanTcDb(object):
uptime=now,
heartbeat_timestamp=now
)
context.session.add(wan_tc_device)
return context.session.add(wan_tc_device)
else:
LOG.debug('updating uptime for device: %s' % host_info['host'])
device.uptime = timeutils.utcnow()
@ -64,11 +66,57 @@ class WanTcDb(object):
return device_list_dict
def create_wan_tc_class(self, context, wan_qos_class):
pass
def create_wan_tc_class(self, context, wtc_class):
wtc_class_db = models.WanTcClass(
id=uuidutils.generate_uuid(),
direction=wtc_class['direction']
)
parent = wtc_class['parent']
if parent:
wtc_class_db.parent = parent
with context.session.begin(subtransactions=True):
if wtc_class['min']:
wtc_class_db.min = wtc_class['min']
if wtc_class['max']:
wtc_class_db.max = wtc_class['max']
context.session.add(wtc_class_db)
return self._class_to_dict(wtc_class_db)
def delete_wtc_class(self, context, id):
wtc_class_db = context.session.query(models.WanTcClass).filter_by(
id=id).first()
if wtc_class_db:
with context.session.begin(subtransactions=True):
context.session.delete(wtc_class_db)
def get_class_by_id(self, context, id):
wtc_class = context.session.query(models.WanTcClass).filter_by(
id=id).first()
if wtc_class:
return self._class_to_dict(wtc_class)
def get_all_classes(self, context):
return context.session.query(models.WanTcClass).all()
wtc_classes_db = context.session.query(models.WanTcClass).all()
wtc_classes = []
for wtc_class in wtc_classes_db:
wtc_classes.append(self._class_to_dict(wtc_class))
return wtc_classes
def _class_to_dict(self, wtc_class):
class_dict = {
'id': wtc_class.id,
'direction': wtc_class.direction,
'min': wtc_class.min,
'max': wtc_class.max,
'parent': wtc_class.parent
}
return class_dict
def _device_to_dict(self, device):
device_dict = {

View File

@ -0,0 +1,114 @@
# Copyright 2016 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_CLASS_PATH: {
'id': {'allow_post': False, 'allow_put': False,
'is_visible': True},
'parent': {'allow_post': True, 'allow_put': False,
'is_visible': True,
'default': ''},
'direction': {'allow_post': True, 'allow_put': False,
'validate': {'type:string': None},
'is_visible': True,
'default': ''
},
'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': '',
},
'project_id': {'allow_post': True, 'allow_put': False,
'validate': {'type:string': None},
'required_by_policy': True,
'is_visible': True}
},
}
class Wantcclass(extensions.ExtensionDescriptor):
@classmethod
def get_name(cls):
return "WAN Traffic Control class"
@classmethod
def get_alias(cls):
return "wan-tc-class"
@classmethod
def get_description(cls):
return "Class for limiting traffic on WAN links"
@classmethod
def get_updated(cls):
return "2017-01-16T00: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 WanTcClassPluginBase(object):
@abc.abstractmethod
def create_wan_tc_class(self, context, wan_tc_class):
pass
@abc.abstractmethod
def get_wan_tc_class(self, context, id, fields=None):
pass
@abc.abstractmethod
def get_wan_tc_classs(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
pass
@abc.abstractmethod
def update_wan_tc_class(self, context, id, wan_tc_class):
pass
@abc.abstractmethod
def delete_wan_tc_class(self, context, id):
pass

View File

@ -26,9 +26,10 @@ import oslo_messaging as messaging
from wan_qos.common import api
from wan_qos.common import constants
from wan_qos.common import topics
from wan_qos.db import wan_qos_db
from wan_qos.extensions import wanqos
from wan_qos.extensions import wantcdevice
from wan_qos.db import wan_qos_db
from wan_qos.extensions import wantcclass
LOG = logging.getLogger(__name__)
@ -50,8 +51,9 @@ class PluginRpcCallback(object):
class WanQosPlugin(wanqos.WanQosPluginBase,
wantcdevice.WanTcDevicePluginBase):
supported_extension_aliases = ['wan-tc', 'wan-tc-device']
wantcdevice.WanTcDevicePluginBase,
wantcclass.WanTcClassPluginBase):
supported_extension_aliases = ['wan-tc', 'wan-tc-device', 'wan-tc-class']
def __init__(self):
self.db = wan_qos_db.WanTcDb()
@ -91,7 +93,7 @@ class WanQosPlugin(wanqos.WanQosPluginBase,
def get_wan_tcs(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
return self.db.get_all_classes(context)
pass
def delete_wan_tc(self, context, id):
pass
@ -105,6 +107,24 @@ class WanQosPlugin(wanqos.WanQosPluginBase,
# tenant_id = self._get_tenant_id_for_create(context, wan_qos_class)
def get_wan_tc_class(self, context, id, fields=None):
return self.db.get_class_by_id(context, id)
def update_wan_tc_class(self, context, id, wan_tc_class):
pass
def create_wan_tc_class(self, context, wan_tc_class):
LOG.debug('got new class request: %s' % wan_tc_class)
return self.db.create_wan_tc_class(context,
wan_tc_class['wan_tc_class'])
def delete_wan_tc_class(self, context, id):
self.db.delete_wtc_class(context, id)
def get_wan_tc_classs(self, context, filters=None, fields=None, sorts=None,
limit=None, marker=None, page_reverse=False):
return self.db.get_all_classes(context)
@staticmethod
def _get_tenant_id_for_create(self, context, resource):
"""Get tenant id for creation of resources."""

View File

@ -40,7 +40,7 @@ class WanTcShow(extension.ClientExtensionShow, WanTc):
class WanTcList(extension.ClientExtensionList, WanTc):
shell_command = 'wan-tc-list'
list_columns = ['id', 'name', 'network']
list_columns = ['id', 'name', 'network', 'min-rate', 'max-rate']
pagination_support = True
sorting_support = True

View File

@ -0,0 +1,99 @@
# Copyright 2016 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 WanTcClass(extension.NeutronClientExtension):
resource = constants.WAN_TC_CLASS
resource_plural = '%ss' % constants.WAN_TC_CLASS
path = constants.WAN_TC_CLASS_PATH
object_path = '/%s' % path
resource_path = '/%s/%%s' % path
versions = ['2.0']
class WanTcShow(extension.ClientExtensionShow, WanTcClass):
shell_command = 'wan-tc-class-show'
class WanTcList(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):
shell_command = 'wan-tc-class-create'
def add_known_arguments(self, parser):
parser.add_argument(
'direction', metavar='<DIRECTION>',
choices=['both', 'in', 'out'],
help=_('The direction for the limiter. Can be both/in/out'))
parser.add_argument(
'--min',
dest='min',
help=_('Set committed rate. (mbit / kbit)'))
parser.add_argument(
'--max',
dest='max',
help=_('Set maximum rate. (mbit / kbit)'))
parser.add_argument(
'--parent',
dest='parent',
help=_('Set the parent class of this class. Omit if root.'))
def args2body(self, parsed_args):
body = {
'direction': parsed_args.direction
}
if parsed_args.min:
body['min'] = parsed_args.min
else:
if not parsed_args.max:
raise exceptions.BadRequest('Either min or max must be set')
if parsed_args.max:
body['max'] = parsed_args.max
if parsed_args.parent:
body['parent'] = parsed_args.parent
return {self.resource: body}
class WanTcDelete(extension.ClientExtensionDelete, WanTcClass):
shell_command = 'wan-tc-class-delete'
class WanTcUpdate(extension.ClientExtensionUpdate, WanTcClass):
shell_command = 'wan-tc-class-update'
def add_known_arguments(self, parser):
pass
def args2body(self, parsed_args):
body = {}
return {self.resource: body}