Add class entity
This commit is contained in:
parent
94e5d09b84
commit
b71d3489c8
|
@ -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
|
||||
|
|
|
@ -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'
|
|
@ -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),
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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
|
|
@ -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."""
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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}
|
Loading…
Reference in New Issue