Create DataNetworks modelling in System Configuration

Introduce stx-gui updates to enable DataNetwork modelling of the
physical data network in sysinv.  This is part of the Story to
"Move neutron provider network modelling to system configuration".

This is an initial update to enable Interfaces, Data Networks and
Data Network Topology panels.

Pending Stein spec support for network-segment-range-mangement,
the following GUI features are not currently supported:
    Segmentation Ranges
    Tenant Networks

The following GUI panels are updated:
    Host Inventory - Interfaces
    Data Networks (<oamip> /admin/datanets; previously /admin/providernets)
    Data Network Topology

Tests Performed:
    Data Network create, modify for network_type flat, vlan.
        vxlan excluded in this GUI commit.
    Data Network delete, modify
    Data Network Topology - basic navigation to panel
    Interface Profile create and apply
    Sanity

Story: 2004455
Task: 28325

Depends-On: https://review.openstack.org/#/c/631701/
Change-Id: I46db5b5d47a9920f21db0521a8f5fbe4213b8af3
Signed-off-by: John Kung <john.kung@windriver.com>
This commit is contained in:
John Kung 2019-01-24 09:49:31 -05:00
parent 8569c522fc
commit 2c4f8a48a4
51 changed files with 463 additions and 470 deletions

View File

@ -1,2 +1,2 @@
SRC_DIR="starlingx-dashboard"
TIS_PATCH_VER=24
TIS_PATCH_VER=25

View File

@ -1935,7 +1935,7 @@ class Interface(base.APIResourceWrapper):
_attrs = ['id', 'uuid', 'ifname', 'ifclass', 'iftype', 'imtu', 'imac',
'networktype', 'networks', 'aemode', 'txhashpolicy', 'vlan_id',
'uses', 'used_by', 'ihost_uuid', 'providernetworks',
'uses', 'used_by', 'ihost_uuid', 'datanetworks',
'ipv4_mode', 'ipv6_mode', 'ipv4_pool', 'ipv6_pool',
'sriov_numvfs']
@ -1944,6 +1944,10 @@ class Interface(base.APIResourceWrapper):
if not self.ifname:
self.ifname = '(' + str(self.uuid)[-8:] + ')'
@property
def datanetworks_csv(self):
return ",".join(self.datanetworks)
def host_interface_list(request, host_id):
interfaces = cgtsclient(request).iinterface.list(host_id)
@ -2578,3 +2582,64 @@ def is_system_k8s_aio(request):
def is_host_with_storage(request, host_id):
host = host_get(request, host_id)
return 'storage' in host.subfunctions or is_system_k8s_aio(request)
class DataNetwork(base.APIResourceWrapper):
"""..."""
_attrs = ['id', 'uuid', 'network_type', 'name', 'mtu', 'description',
'multicast_group', 'port_num', 'ttl', 'mode']
def __init__(self, apiresource):
super(DataNetwork, self).__init__(apiresource)
DATANETWORK_TYPE_FLAT = "flat"
DATANETWORK_TYPE_VLAN = "vlan"
DATANETWORK_TYPE_VXLAN = "vxlan"
data_network_type_choices_list = [
(DATANETWORK_TYPE_FLAT, DATANETWORK_TYPE_FLAT),
(DATANETWORK_TYPE_VLAN, DATANETWORK_TYPE_VLAN),
(DATANETWORK_TYPE_VXLAN, DATANETWORK_TYPE_VXLAN),
]
def data_network_type_choices():
return data_network_type_choices_list
def data_network_create(request, **kwargs):
LOG.info("data_network_create(): kwargs=%s", kwargs)
datanet = cgtsclient(request).datanetwork.create(**kwargs)
return DataNetwork(datanet)
def data_network_list(request):
datanets = cgtsclient(request).datanetwork.list()
return [DataNetwork(n) for n in datanets]
def data_network_get(request, datanet_id):
datanet = cgtsclient(request).datanetwork.get(datanet_id)
if not datanet:
raise ValueError('No match found for datanet_id "%s".' % datanet_id)
return DataNetwork(datanet)
def data_network_modify(request, datanet_id, **kwargs):
LOG.info("data_network_modify(): datanet_id,=%s, kwargs=%s",
datanet_id, kwargs)
patch = []
for key, value in kwargs.items():
patch.append(dict(path='/' + key, value=value, op='replace'))
datanet = cgtsclient(request).datanetwork.update(datanet_id, patch)
if not datanet:
raise ValueError('No match found for datanet_id "%s".' % datanet_id)
return DataNetwork(datanet)
def data_network_delete(request, datanet_id):
LOG.info("data_network_delete(): datanet_id=%s", datanet_id)
return cgtsclient(request).datanetwork.delete(datanet_id)

View File

@ -0,0 +1,147 @@
# Copyright 2012 NEC Corporation
#
# 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.
#
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
import logging
from django.core.urlresolvers import reverse # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
from cgtsclient import exc as sysinv_exceptions
from horizon import exceptions
from horizon import forms
from horizon import messages
from starlingx_dashboard import api as stx_api
LOG = logging.getLogger(__name__)
class CreateDataNetwork(forms.SelfHandlingForm):
name = forms.CharField(max_length=255,
label=_("Name"),
required=True)
description = forms.CharField(max_length=255,
label=_("Description"),
required=False)
network_type = forms.ChoiceField(label=_("Type"),
required=True)
mtu = forms.IntegerField(
label=_("MTU"),
required=True,
initial=1500,
min_value=576,
max_value=9216,
help_text=(
_("Specifies the maximum MTU value of any associated tenant "
"network. Worker node data interface MTU values must be large "
"enough to support the tenant MTU plus any additional provider "
"encapsulation headers. For example, VXLAN provider MTU of "
"1500 requires a minimum data interface MTU of 1574 bytes (1600 "
"bytes is recommended.")))
@classmethod
def _instantiate(cls, request, *args, **kwargs):
return cls(request, *args, **kwargs)
def __init__(self, request, *args, **kwargs):
super(CreateDataNetwork, self).__init__(request, *args, **kwargs)
datanet_type_choices = [('', _("Select a network type"))]
datanet_choices_list = stx_api.sysinv.data_network_type_choices()
for datanet_choices_tuple in datanet_choices_list:
datanet_type_choices.append(datanet_choices_tuple)
self.fields['network_type'].choices = datanet_type_choices
def clean(self):
cleaned_data = super(CreateDataNetwork, self).clean()
if len(cleaned_data['name'].lstrip()) == 0:
raise forms.ValidationError('invalid data network name')
return cleaned_data
def handle(self, request, data):
try:
params = {'name': data['name'],
'network_type': data['network_type'],
'description': data['description'],
'mtu': data['mtu']}
network = stx_api.sysinv.data_network_create(request,
**params)
msg = (_('Data network %s was successfully created.') %
data['name'])
LOG.info(msg)
messages.success(request, msg)
return network
except sysinv_exceptions.CgtsclientException as e:
redirect = reverse('horizon:admin:datanets:index')
exceptions.handle(request, str(e), redirect=redirect)
except Exception:
redirect = reverse('horizon:admin:datanets:index')
msg = _('Failed to create data network %s') % data['name']
exceptions.handle(request, msg, redirect=redirect)
class UpdateDataNetwork(forms.SelfHandlingForm):
name = forms.CharField(label=_("Name"), required=False,
widget=forms.TextInput(
attrs={'readonly': 'readonly'}))
network_type = forms.CharField(label=_("Type"), required=False,
widget=forms.TextInput(
attrs={'readonly': 'readonly'}))
id = forms.CharField(widget=forms.HiddenInput)
# Mutable fields
description = forms.CharField(label=_("Description"), required=False)
mtu = forms.IntegerField(label=_("MTU"),
required=True,
initial=1500,
min_value=576,
max_value=9216,
help_text=(_("Specifies the minimum interface "
"MTU required to support this "
"data network ")))
failure_url = 'horizon:admin:datanets:index'
def handle(self, request, data):
try:
if not data['description']:
data['description'] = '_'
params = {'description': data['description'],
'mtu': data['mtu']}
providernet = stx_api.sysinv.data_network_modify(
request, data['id'], **params)
msg = (_('Data network %s was successfully updated.') %
data['name'])
LOG.info(msg)
messages.success(request, msg)
return providernet
except sysinv_exceptions.CgtsclientException as e:
msg = _('Failed to update data network %s') % data['name']
LOG.info(msg)
redirect = reverse(self.failure_url)
exceptions.handle(request, str(e), redirect=redirect)
except Exception:
msg = _('Failed to update data network %s') % data['name']
LOG.info(msg)
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
@ -146,7 +146,7 @@ class CreateProviderNetworkRange(forms.SelfHandlingForm):
return providernet_range
except neutron_exceptions.NeutronClientException as e:
LOG.info(str(e))
redirect = reverse('horizon:admin:providernets:providernets:'
redirect = reverse('horizon:admin:datanets:datanets:'
'detail',
args=(data['providernet_id'],))
exceptions.handle(request, str(e), redirect=redirect)
@ -155,7 +155,7 @@ class CreateProviderNetworkRange(forms.SelfHandlingForm):
' network range for network %s') \
% data['providernet_id']
LOG.info(msg)
redirect = reverse('horizon:admin:providernets:providernets:'
redirect = reverse('horizon:admin:datanets:datanets:'
'detail',
args=(data['providernet_id'],))
exceptions.handle(request, msg, redirect=redirect)
@ -170,7 +170,7 @@ class CreateProviderNetworkRange(forms.SelfHandlingForm):
class UpdateProviderNetworkRange(forms.SelfHandlingForm):
failure_url = 'horizon:admin:providernets:providernets:detail'
failure_url = 'horizon:admin:datanets:datanets:detail'
providernet_id = forms.CharField(widget=forms.HiddenInput())
providernet_range_id = forms.CharField(widget=forms.HiddenInput())
name = forms.CharField(max_length=255,
@ -237,7 +237,7 @@ class UpdateProviderNetworkRange(forms.SelfHandlingForm):
return providernet_range
except neutron_exceptions.NeutronClientException as e:
LOG.info(str(e))
redirect = reverse('horizon:admin:providernets:providernets:'
redirect = reverse('horizon:admin:datanets:datanets:'
'detail',
args=(data['providernet_id'],))
exceptions.handle(request, str(e), redirect=redirect)

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
@ -52,7 +52,7 @@ class DeleteProviderNetworkRange(tables.DeleteAction):
def get_redirect_url(self):
providernet_id = self.table.kwargs['providernet_id']
return reverse('horizon:admin:providernets:providernets:detail',
return reverse('horizon:admin:datanets:datanets:detail',
args=(providernet_id,))
def delete(self, request, obj_id):
@ -72,7 +72,7 @@ class DeleteProviderNetworkRange(tables.DeleteAction):
class CreateProviderNetworkRange(tables.LinkAction):
name = "create"
verbose_name = _("Create Range")
url = "horizon:admin:providernets:providernets:createrange"
url = "horizon:admin:datanets:datanets:createrange"
classes = ("ajax-modal", "btn-create")
def get_link_url(self, datum=None):
@ -80,16 +80,14 @@ class CreateProviderNetworkRange(tables.LinkAction):
return reverse(self.url, args=(providernet_id,))
def allowed(self, request, datum=None):
providernet = self.table.kwargs.get('providernet')
if providernet:
return (providernet.type not in ('flat'))
return True
# TODO(datanetworks): depends on spec network-segment-range-management
return False
class EditProviderNetworkRange(tables.LinkAction):
name = "update"
verbose_name = _("Edit Range")
url = "horizon:admin:providernets:providernets:editrange"
url = "horizon:admin:datanets:datanets:editrange"
classes = ("ajax-modal", "btn-edit")
def get_link_url(self, providernet_range):
@ -113,7 +111,7 @@ class ProviderNetworkRangeTable(tables.DataTable):
tenant = tables.Column("tenant_name", verbose_name=_("Project"))
shared = tables.Column("shared", verbose_name=_("Shared"),
filters=(filters.yesno, filters.capfirst))
url = "horizon:admin:providernets:providernets:ranges:detail"
url = "horizon:admin:datanets:datanets:ranges:detail"
name = tables.Column("name", verbose_name=_("Name"), link=url)
minimum = tables.Column("minimum", verbose_name=_("Minimum"))
maximum = tables.Column("maximum", verbose_name=_("Maximum"))

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
from django.utils.translation import ugettext_lazy as _ # noqa
@ -23,7 +23,7 @@ from horizon import tabs
class OverviewTab(tabs.Tab):
name = _("Overview")
slug = "overview"
template_name = "admin/providernets/providernets/ranges/" \
template_name = "admin/datanets/datanets/ranges/" \
"_detail_overview.html"
def get_context_data(self, request):

View File

@ -12,13 +12,13 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
from django.conf.urls import url # noqa
from starlingx_dashboard.dashboards.admin.providernets.providernets.ranges \
from starlingx_dashboard.dashboards.admin.datanets.datanets.ranges \
import views
RANGES = r'^(?P<providernet_range_id>[^/]+)/%s$'

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
@ -25,17 +25,17 @@ from horizon import tabs
from horizon.utils import memoized
from starlingx_dashboard import api as stx_api
from starlingx_dashboard.dashboards.admin.providernets.providernets.ranges \
from starlingx_dashboard.dashboards.admin.datanets.datanets.ranges \
import forms as range_forms
from starlingx_dashboard.dashboards.admin.providernets.providernets.ranges \
from starlingx_dashboard.dashboards.admin.datanets.datanets.ranges \
import tabs as range_tabs
class CreateView(forms.ModalFormView):
form_class = range_forms.CreateProviderNetworkRange
template_name = 'admin/providernets/providernets/ranges/create.html'
success_url = 'horizon:admin:providernets:providernets:detail'
failure_url = 'horizon:admin:providernets:providernets:detail'
template_name = 'admin/datanets/datanets/ranges/create.html'
success_url = 'horizon:admin:datanets:datanets:detail'
failure_url = 'horizon:admin:datanets:datanets:detail'
def get_success_url(self):
return reverse(self.success_url,
@ -73,7 +73,7 @@ class CreateView(forms.ModalFormView):
class DetailView(tabs.TabView):
tab_group_class = range_tabs.ProviderNetworkRangeDetailTabs
template_name = 'admin/providernets/providernets/ranges/detail.html'
template_name = 'admin/datanets/datanets/ranges/detail.html'
page_title = '{{ providernet_range.name }}'
def _get_object(self):
@ -85,7 +85,7 @@ class DetailView(tabs.TabView):
self.request, providernet_range_id)
except Exception:
redirect = \
reverse("horizon:admin:providernets:providernets:detail",
reverse("horizon:admin:datanets:datanets:detail",
args=(
self.kwargs['providernet_id'],))
msg = _('Unable to retrieve provider network range details')
@ -99,7 +99,7 @@ class DetailView(tabs.TabView):
pnet_name = self.get_providernet_name(providernet_range.providernet_id)
breadcrumb = [
(pnet_name,
reverse('horizon:admin:providernets:providernets:detail',
reverse('horizon:admin:datanets:datanets:detail',
args=(providernet_range.providernet_id,))),
(_("Segmentation Ranges"), None)
]
@ -128,9 +128,9 @@ class DetailView(tabs.TabView):
class UpdateView(forms.ModalFormView):
form_class = range_forms.UpdateProviderNetworkRange
template_name = 'admin/providernets/providernets/ranges/update.html'
template_name = 'admin/datanets/datanets/ranges/update.html'
context_object_name = 'providernet_range'
success_url = 'horizon:admin:providernets:providernets:detail'
success_url = 'horizon:admin:datanets:datanets:detail'
def get_success_url(self):
value = reverse(self.success_url,
@ -145,7 +145,7 @@ class UpdateView(forms.ModalFormView):
self.request, providernet_range_id)
except Exception:
redirect = \
reverse("horizon:admin:providernets:providernets:detail",
reverse("horizon:admin:datanets:datanets:detail",
args=(self.kwargs['providernet_id'],))
msg = _('Unable to retrieve provider network range details')
exceptions.handle(self.request, msg, redirect=redirect)

View File

@ -12,12 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
import logging
from operator import itemgetter # noqa
from django.core.urlresolvers import reverse # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
@ -26,120 +25,103 @@ from django.utils.translation import ungettext_lazy
from horizon import exceptions
from horizon import tables
from neutronclient.common import exceptions as neutron_exceptions
from cgtsclient import exc as sysinv_exceptions
from starlingx_dashboard import api as stx_api
LOG = logging.getLogger(__name__)
class DeleteProviderNetwork(tables.DeleteAction):
class DeleteDataNetwork(tables.DeleteAction):
@staticmethod
def action_present(count):
return ungettext_lazy(
"Delete Provider Network",
"Delete Provider Networks",
"Delete Data Network",
"Delete Data Networks",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
"Deleted Provider Network",
"Deleted Provider Networks",
"Deleted Data Network",
"Deleted Data Networks",
count
)
def delete(self, request, obj_id):
try:
stx_api.neutron.provider_network_delete(request, obj_id)
except neutron_exceptions.NeutronClientException as e:
stx_api.sysinv.data_network_delete(request, obj_id)
except sysinv_exceptions.CgtsclientException as e:
LOG.info(str(e))
redirect = reverse('horizon:admin:providernets:index')
redirect = reverse('horizon:admin:datanets:index')
exceptions.handle(request, str(e), redirect=redirect)
except Exception:
msg = _('Failed to delete provider network %s') % obj_id
msg = _('Failed to delete data network %s') % obj_id
LOG.info(msg)
redirect = reverse('horizon:admin:providernets:index')
redirect = reverse('horizon:admin:datanets:index')
exceptions.handle(request, msg, redirect=redirect)
class CreateProviderNetwork(tables.LinkAction):
class CreateDataNetwork(tables.LinkAction):
name = "create"
verbose_name = _("Create Provider Network")
url = "horizon:admin:providernets:providernets:create"
verbose_name = _("Create Data Network")
url = "horizon:admin:datanets:datanets:create"
classes = ("ajax-modal", "btn-create")
class EditProviderNetwork(tables.LinkAction):
class EditDataNetwork(tables.LinkAction):
name = "update"
verbose_name = _("Edit Provider Network")
url = "horizon:admin:providernets:providernets:update"
verbose_name = _("Edit Data Network")
url = "horizon:admin:datanets:datanets:update"
classes = ("ajax-modal", "btn-edit")
class AddProviderNetworkRange(tables.LinkAction):
class AddDataNetworkRange(tables.LinkAction):
name = "addrange"
verbose_name = _("Create Segmentation Range")
url = "horizon:admin:providernets:providernets:addrange"
url = "horizon:admin:datanets:datanets:addrange"
classes = ("ajax-modal", "btn-edit")
def allowed(self, request, providernet):
if providernet:
return providernet.type not in ('flat')
return super(AddProviderNetworkRange, self).allowed(request,
providernet)
return providernet.network_type not in ('flat')
return super(AddDataNetworkRange, self).allowed(request,
providernet)
class ProviderNetworksFilterAction(tables.FilterAction):
def filter(self, table, providernets, filter_string):
class DataNetworksFilterAction(tables.FilterAction):
def filter(self, table, datanets, filter_string):
"""Naive case-insensitive search."""
q = filter_string.lower()
return [providernet for providernet in providernets
return [providernet for providernet in datanets
if q in providernet.name.lower()]
def _format_providernet_ranges(data):
ranges = data['ranges']
if not ranges:
return '-'
return ", ".join(["{}-{}".format(r['minimum'], r['maximum'])
if r['minimum'] != r['maximum']
else "{}".format(r['minimum'])
for r in sorted(ranges, key=itemgetter('minimum'))])
# TODO(datanetworks): update ranges based upon Stein spec
return '-'
PROVIDERNET_STATUS_CHOICES = (
('active', True),
('down', False),
('error', False),
('unmanaged', True)
)
class ProviderNetworksTable(tables.DataTable):
class DataNetworksTable(tables.DataTable):
name = tables.Column("name", verbose_name=_("Network Name"),
link='horizon:admin:providernets:providernets:detail')
status = tables.Column("status",
verbose_name=_("Status"),
status=True,
status_choices=PROVIDERNET_STATUS_CHOICES)
type = tables.Column("type", verbose_name=_("Type"))
link='horizon:admin:datanets:datanets:detail')
type = tables.Column("network_type", verbose_name=_("Type"))
mtu = tables.Column("mtu", verbose_name=_("MTU"))
ranges = tables.Column(transform=_format_providernet_ranges,
verbose_name=_("Segmentation Ranges"))
vlan_transparent = tables.Column("vlan_transparent",
verbose_name=_("VLAN Transparent"))
def get_object_id(self, datum):
return str(datum.uuid)
class Meta(object):
name = "provider_networks"
verbose_name = _("Provider Networks")
status_columns = ["status"]
table_actions = (CreateProviderNetwork, DeleteProviderNetwork,
ProviderNetworksFilterAction)
row_actions = (EditProviderNetwork,
DeleteProviderNetwork,
AddProviderNetworkRange)
verbose_name = _("Data Networks")
table_actions = (CreateDataNetwork, DeleteDataNetwork,
DataNetworksFilterAction)
row_actions = (EditDataNetwork,
DeleteDataNetwork,
AddDataNetworkRange)
def _get_link_url(datum):

View File

@ -12,22 +12,22 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
from django.conf.urls import include # noqa
from django.conf.urls import url # noqa
from starlingx_dashboard.dashboards.admin.providernets.providernets.ranges \
from starlingx_dashboard.dashboards.admin.datanets.datanets.ranges \
import urls as range_urls
from starlingx_dashboard.dashboards.admin.providernets.providernets.ranges \
from starlingx_dashboard.dashboards.admin.datanets.datanets.ranges \
import views as range_views
from starlingx_dashboard.dashboards.admin.providernets.providernets import \
from starlingx_dashboard.dashboards.admin.datanets.datanets import \
views
PROVIDERNETS = r'^(?P<providernet_id>[^/]+)/%s$'
VIEW_MOD = 'starlingx_dashboard.dashboards.admin.providernets.providernets.' \
VIEW_MOD = 'starlingx_dashboard.dashboards.admin.datanets.datanets.' \
'views'
urlpatterns = [

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
@ -30,30 +30,30 @@ from horizon import tables
from openstack_dashboard import api
from starlingx_dashboard import api as stx_api
from starlingx_dashboard.dashboards.admin.providernets.providernets import \
forms as providernet_forms
from starlingx_dashboard.dashboards.admin.providernets.providernets.ranges \
from starlingx_dashboard.dashboards.admin.datanets.datanets import \
forms as datanet_forms
from starlingx_dashboard.dashboards.admin.datanets.datanets.ranges \
import tables as range_tables
from starlingx_dashboard.dashboards.admin.providernets.providernets.ranges \
from starlingx_dashboard.dashboards.admin.datanets.datanets.ranges \
import views as range_views
from starlingx_dashboard.dashboards.admin.providernets.providernets import \
from starlingx_dashboard.dashboards.admin.datanets.datanets import \
tables as providernet_tables
LOG = logging.getLogger(__name__)
class CreateView(forms.ModalFormView):
form_class = providernet_forms.CreateProviderNetwork
template_name = 'admin/providernets/providernets/create.html'
success_url = reverse_lazy('horizon:admin:providernets:index')
form_class = datanet_forms.CreateDataNetwork
template_name = 'admin/datanets/datanets/create.html'
success_url = reverse_lazy('horizon:admin:datanets:index')
class DetailView(tables.MultiTableView):
table_classes = (range_tables.ProviderNetworkRangeTable,
providernet_tables.ProviderNetworkTenantNetworkTable)
template_name = 'admin/providernets/providernets/detail.html'
failure_url = reverse_lazy('horizon:admin:providernets:index')
page_title = '{{ "Provider Network Detail: "|add:providernet.name }}'
template_name = 'admin/datanets/datanets/detail.html'
failure_url = reverse_lazy('horizon:admin:datanets:index')
page_title = '{{ "Data Network Detail: "|add:providernet.name }}'
def _get_tenant_list(self):
if not hasattr(self, "_tenants"):
@ -69,10 +69,8 @@ class DetailView(tables.MultiTableView):
def get_tenant_networks_data(self):
try:
providernet_id = self.kwargs['providernet_id']
# self.table.kwargs['providernet'] = self._get_data()
networks = stx_api.neutron.provider_network_list_tenant_networks(
self.request, providernet_id=providernet_id)
# TODO(datanetworks): get tenant networks when in upstream neutron
networks = []
except Exception:
networks = []
msg = _('Tenant network list can not be retrieved.')
@ -81,10 +79,8 @@ class DetailView(tables.MultiTableView):
def get_provider_network_ranges_data(self):
try:
providernet_id = self.kwargs['providernet_id']
# self.table.kwargs['providernet'] = self._get_data()
ranges = stx_api.neutron.provider_network_range_list(
self.request, providernet_id=providernet_id)
# TODO(datanetworks) force ranges to []
ranges = []
except Exception:
ranges = []
msg = _('Segmentation id range list can not be retrieved.')
@ -101,9 +97,8 @@ class DetailView(tables.MultiTableView):
if not hasattr(self, "_providernet"):
try:
providernet_id = self.kwargs['providernet_id']
providernet = stx_api.neutron.provider_network_get(
providernet = stx_api.sysinv.data_network_get(
self.request, providernet_id)
providernet.set_id_as_name_if_empty(length=0)
except Exception:
redirect = self.failure_url
exceptions.handle(self.request,
@ -115,20 +110,8 @@ class DetailView(tables.MultiTableView):
def _get_nova_data(self):
if not hasattr(self, "_providernet_nova"):
try:
providernet_id = self.kwargs['providernet_id']
providernet_nova = stx_api.nova.provider_network_get(
self.request, providernet_id)
except Exception as ex:
# redirect = self.failure_url
# exceptions.handle(self.request,
# _('Unable to retrieve details for '
# 'provider network "%s".') % providernet_id,
# redirect=redirect)
LOG.error(ex)
providernet_nova = None
self._providernet_nova = providernet_nova
# TODO(datanetworks): depends on upstream support
self._providernet_nova = None
return self._providernet_nova
def get_context_data(self, **kwargs):
@ -139,9 +122,9 @@ class DetailView(tables.MultiTableView):
class UpdateView(forms.ModalFormView):
form_class = providernet_forms.UpdateProviderNetwork
template_name = 'admin/providernets/providernets/update.html'
success_url = reverse_lazy('horizon:admin:providernets:index')
form_class = datanet_forms.UpdateDataNetwork
template_name = 'admin/datanets/datanets/update.html'
success_url = reverse_lazy('horizon:admin:datanets:index')
def get_context_data(self, **kwargs):
context = super(UpdateView, self).get_context_data(**kwargs)
@ -152,28 +135,28 @@ class UpdateView(forms.ModalFormView):
if not hasattr(self, "_object"):
providernet_id = self.kwargs['providernet_id']
try:
self._object = stx_api.neutron.provider_network_get(
self._object = stx_api.sysinv.data_network_get(
self.request, providernet_id)
except Exception:
redirect = self.success_url
msg = _('Unable to retrieve provider network details.')
msg = _('Unable to retrieve data network details.')
exceptions.handle(self.request, msg, redirect=redirect)
return self._object
def get_initial(self):
providernet = self._get_object()
return {'id': providernet['id'],
'name': providernet['name'],
'description': providernet['description'],
'type': providernet['type'],
'mtu': providernet['mtu'],
'vlan_transparent': providernet['vlan_transparent']}
return {'id': providernet.id,
'name': providernet.name,
'network_type': providernet.network_type,
'mtu': providernet.mtu,
'description': providernet.description,
}
class CreateRangeView(range_views.CreateView):
template_name = 'admin/providernets/providernets/add_range.html'
success_url = 'horizon:admin:providernets:index'
failure_url = 'horizon:admin:providernets:index'
template_name = 'admin/datanets/datanets/add_range.html'
success_url = 'horizon:admin:datanets:index'
failure_url = 'horizon:admin:datanets:index'
def get_success_url(self):
return reverse(self.success_url)

View File

@ -11,9 +11,9 @@ from openstack_dashboard.api import base
from openstack_dashboard.dashboards.admin import dashboard
class Providernets(horizon.Panel):
name = _("Provider Networks")
slug = 'providernets'
class Datanets(horizon.Panel):
name = _("Data Networks")
slug = 'datanets'
permissions = ('openstack.services.platform', 'openstack.services.network')
def allowed(self, context):
@ -22,7 +22,7 @@ class Providernets(horizon.Panel):
if not base.is_service_enabled(context['request'], 'platform'):
return False
else:
return super(Providernets, self).allowed(context)
return super(Datanets, self).allowed(context)
def nav(self, context):
if context['request'].user.services_region == 'SystemController':
@ -33,4 +33,4 @@ class Providernets(horizon.Panel):
return True
dashboard.Admin.register(Providernets)
dashboard.Admin.register(Datanets)

View File

@ -1,47 +1,42 @@
#
# Copyright (c) 2013-2016 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import logging
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import tabs
from starlingx_dashboard.api import base as stx_base
from starlingx_dashboard.api import neutron as stx_neutron
from starlingx_dashboard.dashboards.admin.providernets.providernets import \
tables as providernets_tables
LOG = logging.getLogger(__name__)
from starlingx_dashboard.api import sysinv as stx_sysinv
from starlingx_dashboard.dashboards.admin.datanets.datanets import \
tables as datanets_tables
class ProviderNetworkTab(tabs.TableTab):
table_classes = (providernets_tables.ProviderNetworksTable,)
name = _("Provider Networks")
class DataNetworkTab(tabs.TableTab):
table_classes = (datanets_tables.DataNetworksTable,)
name = _("Data Networks")
slug = "provider_networks"
template_name = ("horizon/common/_detail_table.html")
def get_provider_networks_data(self):
try:
providernets = \
stx_neutron.provider_network_list(self.tab_group.request)
datanets = \
stx_sysinv.data_network_list(self.tab_group.request)
except Exception:
providernets = []
datanets = []
msg = _('Unable to get provider network list.')
exceptions.check_message(["Connection", "refused"], msg)
raise
return providernets
return datanets
def allowed(self, request):
return stx_base.is_stx_region(request)
class NetworkTabs(tabs.TabGroup):
slug = "providernets"
tabs = (ProviderNetworkTab,)
slug = "datanets"
tabs = (DataNetworkTab,)
sticky = True

View File

@ -2,7 +2,7 @@
{% load i18n %}
{% block form_id %}add_provider_network_range_form{% endblock %}
{% block form_action %}{% url 'horizon:admin:providernets:providernets:addrange' providernet_id %}
{% block form_action %}{% url 'horizon:admin:datanets:datanets:addrange' providernet_id %}
{% endblock %}
{% block modal-header %}{% trans "Create Segmentation Range" %}{% endblock %}

View File

@ -2,10 +2,10 @@
{% load i18n %}
{% block form_id %}create_provider_network_form{% endblock %}
{% block form_action %}{% url 'horizon:admin:providernets:providernets:create' %}
{% block form_action %}{% url 'horizon:admin:datanets:datanets:create' %}
{% endblock %}
{% block modal-header %}{% trans "Create Provider Network" %}{% endblock %}
{% block modal-header %}{% trans "Create Data Network" %}{% endblock %}
{% block modal-body %}
<div class="left">
@ -21,5 +21,5 @@
{% block modal-footer %}
<a class="btn btn-default cancel" data-dismiss="modal">{% trans "Cancel" %}</a>
<input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Provider Network" %}" />
<input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Data Network" %}" />
{% endblock %}

View File

@ -1,6 +1,6 @@
{% load i18n sizeformat %}
<h3>{% trans "Provider Network Overview" %}</h3>
<h3>{% trans "Data Network Overview" %}</h3>
<div class="info detail">
<dl class="dl-horizontal">
@ -14,8 +14,6 @@
<dd>{{ providernet.mtu|default:_("-") }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ providernet.description|default:_("None") }}</dd>
<dt>{% trans "VLAN Transparent" %}</dt>
<dd>{{ providernet.vlan_transparent|yesno|capfirst }}</dd>
{% if nova_providernet %}
<dt>{% trans "PCI PFs Configured" %}</dt>
<dd>{{ nova_providernet.pci_pfs_configured|default:_("0") }}</dd>

View File

@ -2,9 +2,9 @@
{% load i18n %}
{% block form_id %}update_provider_network_form{% endblock %}
{% block form_action %}{% url 'horizon:admin:providernets:providernets:update' providernet_id %}{% endblock %}
{% block form_action %}{% url 'horizon:admin:datanets:datanets:update' providernet_id %}{% endblock %}
{% block modal-header %}{% trans "Edit Provider Network" %}{% endblock %}
{% block modal-header %}{% trans "Edit Data Network" %}{% endblock %}
{% block modal-body %}
<div class="left">
@ -19,7 +19,7 @@
</div>
<div class="right">
<h3>{% trans "Description:" %}</h3>
<p>{% trans "You may update the editable properties of your provider network here." %}</p>
<p>{% trans "You may update the editable properties of your data network here." %}</p>
</div>
{% endblock %}

View File

@ -7,5 +7,5 @@
{% endblock page_header %}
{% block main %}
{% include "admin/providernets/providernets/_add_range.html" %}
{% include "admin/datanets/datanets/_add_range.html" %}
{% endblock %}

View File

@ -1,11 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Create Provider Network" %}{% endblock %}
{% block title %}{% trans "Create Data Network" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Create Provider Network") %}
{% include "horizon/common/_page_header.html" with title=_("Create Data Network") %}
{% endblock page_header %}
{% block main %}
{% include "admin/providernets/providernets/_create.html" %}
{% include "admin/datanets/datanets/_create.html" %}
{% endblock %}

View File

@ -1,9 +1,9 @@
{% extends 'base.html' %}
{% load i18n breadcrumb_nav %}
{% block title %}{% trans "Provider Network Detail"%}{% endblock %}
{% block title %}{% trans "Data Network Detail"%}{% endblock %}
{% block main %}
{% include "admin/providernets/providernets/_detail_overview.html" %}
{% include "admin/datanets/datanets/_detail_overview.html" %}
<hr>
<div id="ranges">
{{ provider_network_ranges_table.render }}

View File

@ -2,7 +2,7 @@
{% load i18n %}
{% block form_id %}create_provider_network_range_form{% endblock %}
{% block form_action %}{% url 'horizon:admin:providernets:providernets:createrange' providernet_id %}
{% block form_action %}{% url 'horizon:admin:datanets:datanets:createrange' providernet_id %}
{% endblock %}
{% block modal-header %}{% trans "Create Segmentation Range" %}{% endblock %}

View File

@ -18,7 +18,7 @@
<dd>{{ providernet_range.maximum|default:_("None") }}</dd>
{% if providernet_range.vxlan %}
<dt>{% trans "Provider Attributes" %}</dt>
<dd>{% include "admin/providernets/providernets/ranges/_vxlan.html" with vxlan=providernet_range.vxlan %}</dd>
<dd>{% include "admin/datanets/datanets/ranges/_vxlan.html" with vxlan=providernet_range.vxlan %}</dd>
{% endif %}
</dl>
</div>

View File

@ -2,7 +2,7 @@
{% load i18n %}
{% block form_id %}update_provider_network_range_form{% endblock %}
{% block form_action %}{% url 'horizon:admin:providernets:providernets:editrange' providernet_id providernet_range_id %}{% endblock %}
{% block form_action %}{% url 'horizon:admin:datanets:datanets:editrange' providernet_id providernet_range_id %}{% endblock %}
{% block modal-header %}{% trans "Edit Segmentation Range" %}{% endblock %}

View File

@ -7,5 +7,5 @@
{% endblock page_header %}
{% block main %}
{% include "admin/providernets/providernets/ranges/_create.html" %}
{% include "admin/datanets/datanets/ranges/_create.html" %}
{% endblock %}

View File

@ -1,11 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Update Provider Network Range" %}{% endblock %}
{% block title %}{% trans "Update Data Network Range" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Update Provider Network Range") %}
{% include "horizon/common/_page_header.html" with title=_("Update Data Network Range") %}
{% endblock page_header %}
{% block main %}
{% include 'admin/providernets/providernets/ranges/_update.html' %}
{% include 'admin/datanets/datanets/ranges/_update.html' %}
{% endblock %}

View File

@ -1,11 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Update Provider Network" %}{% endblock %}
{% block title %}{% trans "Update Data Network" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Update Provider Network") %}
{% include "horizon/common/_page_header.html" with title=_("Update Data Network") %}
{% endblock page_header %}
{% block main %}
{% include 'admin/providernets/providernets/_update.html' %}
{% include 'admin/datanets/datanets/_update.html' %}
{% endblock %}

View File

@ -1,9 +1,9 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Provider Networks" %}{% endblock %}
{% block title %}{% trans "Data Networks" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Provider Networks")%}
{% include "horizon/common/_page_header.html" with title=_("Data Networks")%}
{% endblock page_header %}
{% block main %}

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2016 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -7,15 +7,15 @@
from django.conf.urls import include
from django.conf.urls import url
from starlingx_dashboard.dashboards.admin.providernets.providernets \
from starlingx_dashboard.dashboards.admin.datanets.datanets \
import urls as providernet_urls
from starlingx_dashboard.dashboards.admin.providernets import views
from starlingx_dashboard.dashboards.admin.datanets import views
NETWORKS = r'^(?P<network_id>[^/]+)/%s$'
urlpatterns = [
url(r'^$', views.IndexViewTabbed.as_view(), name='index'),
url(r'^providernets/',
include(providernet_urls, namespace='providernets'))
url(r'^datanets/',
include(providernet_urls, namespace='datanets'))
]

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2016 Wind River Systems, Inc.
# Copyright (c) 2016-2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -8,11 +8,11 @@ from django.utils.translation import ugettext_lazy as _
from horizon import tabs
from starlingx_dashboard.dashboards.admin.providernets \
from starlingx_dashboard.dashboards.admin.datanets \
import tabs as project_tabs
class IndexViewTabbed(tabs.TabbedTableView):
tab_group_class = project_tabs.NetworkTabs
template_name = 'admin/providernets/tabs.html'
page_title = _("Provider Networks")
template_name = 'admin/datanets/tabs.html'
page_title = _("Data Networks")

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2016-2018 Wind River Systems, Inc.
# Copyright (c) 2016-2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -14,7 +14,7 @@ from openstack_dashboard.dashboards.admin import dashboard
class HostTopology(horizon.Panel):
name = _("Provider Network Topology")
name = _("Data Network Topology")
slug = 'host_topology'
permissions = ('openstack.services.platform', 'openstack.services.network')

View File

@ -11,10 +11,10 @@ import logging
from django.utils.translation import pgettext_lazy
from django.utils.translation import ugettext_lazy as _
from starlingx_dashboard.dashboards.admin.datanets.datanets.ranges \
import tables as sr_tables
from starlingx_dashboard.dashboards.admin.inventory.interfaces import \
tables as if_tables
from starlingx_dashboard.dashboards.admin.providernets.providernets.ranges \
import tables as sr_tables
LOG = logging.getLogger(__name__)

View File

@ -1,4 +1,4 @@
# Copyright (c) 2016-2018 Wind River Systems, Inc.
# Copyright (c) 2016-2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -15,12 +15,12 @@ from horizon import tabs
from openstack_dashboard import api as api
from starlingx_dashboard import api as stx_api
from starlingx_dashboard.dashboards.admin.datanets.datanets import \
tables as pn_tables
from starlingx_dashboard.dashboards.admin.host_topology import \
tables as tables
from starlingx_dashboard.dashboards.admin.inventory import \
tabs as i_tabs
from starlingx_dashboard.dashboards.admin.providernets.providernets import \
tables as pn_tables
LOG = logging.getLogger(__name__)
@ -66,7 +66,7 @@ class OverviewTab(tabs.TableTab):
table_classes = (tables.ProviderNetworkRangeTable,
pn_tables.ProviderNetworkTenantNetworkTable)
template_name = 'admin/host_topology/detail/providernet.html'
name = "Provider Network Detail"
name = "Data Network Detail"
slug = 'providernet_details_overview'
failure_url = reverse_lazy('horizon:admin:host_topology:index')
@ -83,14 +83,8 @@ class OverviewTab(tabs.TableTab):
return self._tenants
def get_tenant_networks_data(self):
try:
providernet_id = self.tab_group.kwargs['providernet_id']
networks = stx_api.neutron.provider_network_list_tenant_networks(
self.request, providernet_id=providernet_id)
except Exception:
networks = []
msg = _('Tenant network list can not be retrieved.')
exceptions.handle(self.request, msg)
# TODO(datanetworks): need to refactor for Stein
networks = []
return networks
def get_provider_network_ranges_data(self):

View File

@ -156,8 +156,8 @@ svg#topology_canvas g.loading .host .icon_bg {
<input id="host_list_search" class="form-control" type="text" placeholder="Search Worker Hosts" />
<div id="host_list" class="list-group">
</div>
<h4>Provider Networks</h4>
<input id="network_list_search" class="form-control" type="text" placeholder="Search Provider Networks" />
<h4>Data Networks</h4>
<input id="network_list_search" class="form-control" type="text" placeholder="Search Data Networks" />
<div id="network_list" class="list-group">
</div>
</div>

View File

@ -1,7 +1,7 @@
{% load i18n sizeformat %}
<div class="info row-fluid detail">
{% include "admin/providernets/providernets/_detail_overview.html" %}
{% include "admin/datanets/datanets/_detail_overview.html" %}
<hr>
<div id="ranges">
{{ provider_network_ranges_table.render }}

View File

@ -4,7 +4,7 @@
{% if host %}
<h4>Selected Entity: <a href="{% url 'horizon:admin:inventory:detail' host.id %}" >{{host.hostname}}</a></h4>
{% else %}
<h4>Selected Entity: <a href="{% url 'horizon:admin:providernets:providernets:detail' providernet.id %}" >{{providernet.name}}</a></h4>
<h4>Selected Entity: <a href="{% url 'horizon:admin:datanets:datanets:detail' providernet.id %}" >{{providernet.name}}</a></h4>
{% endif %}
{% block main %}

View File

@ -1,6 +1,6 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Provider Network Topology" %}{% endblock %}
{% block title %}{% trans "Data Network Topology" %}{% endblock %}
{% block main %}

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2016-2018 Wind River Systems, Inc.
# Copyright (c) 2016-2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -73,9 +73,8 @@ class ProvidernetDetailView(tabs.TabbedTableView):
if not hasattr(self, "_providernet"):
try:
providernet_id = self.kwargs['providernet_id']
providernet = stx_api.neutron.provider_network_get(
providernet = stx_api.sysinv.data_network_get(
self.request, providernet_id)
providernet.set_id_as_name_if_empty(length=0)
alarms = stx_api.fm.alarm_list(self.request)
# Filter out unrelated alarms
@ -98,18 +97,8 @@ class ProvidernetDetailView(tabs.TabbedTableView):
def get_nova_data(self):
if not hasattr(self, "_providernet_nova"):
try:
providernet_id = self.kwargs['providernet_id']
providernet_nova = stx_api.nova.provider_network_get(
self.request, providernet_id)
except Exception:
redirect = self.failure_url
exceptions.handle(self.request,
_('Unable to retrieve details for '
'provider network "%s".') % providernet_id,
redirect=redirect)
self._providernet_nova = providernet_nova
# TODO(datanetworks): depends on upstream support
self._providernet_nova = None
return self._providernet_nova
def get_tabs(self, request, *args, **kwargs):
@ -122,7 +111,7 @@ class ProvidernetDetailView(tabs.TabbedTableView):
class HostTopologyView(views.HorizonTemplateView):
template_name = 'admin/host_topology/index.html'
page_title = _("Provider Network Topology")
page_title = _("Data Network Topology")
def _has_permission(self, policy):
has_permission = True
@ -220,7 +209,7 @@ class JSONView(View):
def _get_pnets(self, request):
pnets = []
try:
pnets = stx_api.neutron.provider_network_list(request)
pnets = stx_api.sysinv.data_network_list(request)
except Exception as ex:
exceptions.handle(ex)
data = [p.to_dict() for p in pnets]

View File

@ -23,7 +23,6 @@ from horizon import exceptions
from horizon import forms
from horizon import messages
from starlingx_dashboard.api import neutron
from starlingx_dashboard.api import sysinv
LOG = logging.getLogger(__name__)
@ -280,37 +279,37 @@ class AddInterface(forms.SelfHandlingForm):
'data-switch-on': 'ifclass',
'data-ifclass-platform': 'Platform Network(s)'}))
providernetworks_data = MultipleChoiceField(
label=_("Provider Network(s)"),
datanetworks_data = MultipleChoiceField(
label=_("Data Network(s)"),
required=False,
widget=CheckboxSelectMultiple(
attrs={
'class': 'switched',
'data-switch-on': 'ifclass',
'data-ifclass-data': ''},
empty_value=_("No provider networks available "
empty_value=_("No data networks available "
"for this interface class.")))
providernetworks_pci = MultipleChoiceField(
label=_("Provider Network(s)"),
datanetworks_pci = MultipleChoiceField(
label=_("Data Network(s)"),
required=False,
widget=CheckboxSelectMultiple(
attrs={
'class': 'switched',
'data-switch-on': 'ifclass',
'data-ifclass-pci-passthrough': ''},
empty_value=_("No provider networks available "
empty_value=_("No data networks available "
"for this interface class.")))
providernetworks_sriov = MultipleChoiceField(
label=_("Provider Network(s)"),
datanetworks_sriov = MultipleChoiceField(
label=_("Data Network(s)"),
required=False,
widget=CheckboxSelectMultiple(
attrs={
'class': 'switched',
'data-switch-on': 'ifclass',
'data-ifclass-pci-sriov': ''},
empty_value=_("No provider networks available "
empty_value=_("No data networks available "
"for this interface class.")))
imtu = forms.IntegerField(
@ -383,9 +382,9 @@ class AddInterface(forms.SelfHandlingForm):
current_interface = sysinv.host_interface_get(
self.request, this_interface_id)
else:
self.fields['providernetworks_sriov'].widget = \
self.fields['datanetworks_sriov'].widget = \
forms.widgets.HiddenInput()
self.fields['providernetworks_pci'].widget = \
self.fields['datanetworks_pci'].widget = \
forms.widgets.HiddenInput()
host_uuid = kwargs['initial']['ihost_uuid']
@ -400,38 +399,38 @@ class AddInterface(forms.SelfHandlingForm):
network_choices = _get_network_choices(networks)
self.fields['networks'].choices = network_choices
# Populate Provider Network Choices by querying Neutron
# Populate Data Network Choices by querying SysInv
self.extras = {}
interfaces = sysinv.host_interface_list(self.request, host_uuid)
used_providernets = []
used_datanets = []
for i in interfaces:
if i.ifclass == 'data' and \
i.providernetworks and \
i.datanetworks_csv and \
i.uuid != this_interface_id:
used_providernets = used_providernets + \
i.providernetworks.split(",")
used_datanets = used_datanets + \
i.datanetworks_csv.split(",")
providernet_choices = []
providernet_filtered = []
datanet_choices = []
datanet_filtered = []
if getattr(self.request.user, 'services_region', None) == 'RegionOne' \
and getattr(settings, 'DC_MODE', False):
nt_choices = self.fields['ifclass'].choices
self.fields['ifclass'].choices = [i for i in nt_choices if
i[0] != 'data']
else:
providernets = neutron.provider_network_list(self.request)
for provider in providernets:
label = "{} (mtu={})".format(provider.name, provider.mtu)
providernet = (str(provider.name), label)
providernet_choices.append(providernet)
if provider.name not in used_providernets:
providernet_filtered.append(providernet)
datanets = sysinv.data_network_list(self.request)
for dn in datanets:
label = "{} (mtu={})".format(dn.name, dn.mtu)
datanet = (str(dn.name), label)
datanet_choices.append(datanet)
if dn.name not in used_datanets:
datanet_filtered.append(datanet)
self.fields['providernetworks_data'].choices = providernet_filtered
self.fields['datanetworks_data'].choices = datanet_filtered
if (type(self) is UpdateInterface):
self.fields['providernetworks_pci'].choices = providernet_choices
self.fields['providernetworks_sriov'].choices = providernet_choices
self.fields['datanetworks_pci'].choices = datanet_choices
self.fields['datanetworks_sriov'].choices = datanet_choices
if current_interface:
# update operation
@ -493,35 +492,35 @@ class AddInterface(forms.SelfHandlingForm):
cleaned_data.pop('ipv6_pool', None)
if ifclass == 'data':
providernetworks = [_f for _f in cleaned_data.get(
'providernetworks_data', []) if _f]
datanetworks = [_f for _f in cleaned_data.get(
'datanetworks_data', []) if _f]
elif ifclass == 'pci-passthrough':
providernetworks = [_f for _f in cleaned_data.get(
'providernetworks_pci', []) if _f]
datanetworks = [_f for _f in cleaned_data.get(
'datanetworks_pci', []) if _f]
elif ifclass == 'pci-sriov':
providernetworks = [_f for _f in cleaned_data.get(
'providernetworks_sriov', []) if _f]
datanetworks = [_f for _f in cleaned_data.get(
'datanetworks_sriov', []) if _f]
else:
providernetworks = []
datanetworks = []
# providernetwork selection is required for 'data', 'pci-passthrough'
# datanetwork selection is required for 'data', 'pci-passthrough'
# and 'pci-sriov'. It is NOT required for any other interface class
if not providernetworks:
if not datanetworks:
# Note that 1 of 3 different controls may be used to select
# provider network, make sure to set the error on the appropriate
# data network, make sure to set the error on the appropriate
# control
if ifclass in ['data', 'pci-passthrough', 'pci-sriov']:
raise forms.ValidationError(_(
"You must specify a Provider Network"))
"You must specify a Data Network"))
cleaned_data['providernetworks'] = ",".join(providernetworks)
if 'providernetworks_data' in cleaned_data:
del cleaned_data['providernetworks_data']
if 'providernetworks_pci' in cleaned_data:
del cleaned_data['providernetworks_pci']
if 'providernetworks_sriov' in cleaned_data:
del cleaned_data['providernetworks_sriov']
cleaned_data['datanetworks'] = ",".join(datanetworks)
if 'datanetworks_data' in cleaned_data:
del cleaned_data['datanetworks_data']
if 'datanetworks_pci' in cleaned_data:
del cleaned_data['datanetworks_pci']
if 'datanetworks_sriov' in cleaned_data:
del cleaned_data['datanetworks_sriov']
return cleaned_data
@ -538,8 +537,8 @@ class AddInterface(forms.SelfHandlingForm):
data['uses'] = uses
del data['ports']
if not data['providernetworks']:
del data['providernetworks']
if not data['datanetworks']:
del data['datanetworks']
if not data['vlan_id'] or data['iftype'] != 'vlan':
del data['vlan_id']
@ -813,10 +812,10 @@ class UpdateInterface(AddInterface):
break
if current_interface.ifclass == 'data':
data['providernetworks'] = 'none'
data['datanetworks'] = 'none'
if not data['providernetworks']:
del data['providernetworks']
if not data['datanetworks']:
del data['datanetworks']
if 'sriov_numvfs' in data:
data['sriov_numvfs'] = str(data['sriov_numvfs'])

View File

@ -194,8 +194,8 @@ class InterfacesTable(tables.DataTable):
platform_networks = tables.Column(get_platform_networks,
verbose_name=_('Platform Network(s)'))
providernetworks = tables.Column('providernetworks',
verbose_name=_('Provider Network(s)'))
datanetworks_csv = tables.Column('datanetworks_csv',
verbose_name=_('Data Network(s)'))
attributes = tables.Column(get_attributes,
verbose_name=_('Attributes'))

View File

@ -260,10 +260,10 @@ class UpdateView(forms.ModalFormView):
def get_initial(self):
interface = self._get_object()
providernetworks = []
if interface.providernetworks:
for pn in interface.providernetworks.split(","):
providernetworks.append(str(pn))
datanetworks_csv = []
if interface.datanetworks_csv:
for pn in interface.datanetworks_csv.split(","):
datanetworks_csv.append(str(pn))
try:
host = stx_api.sysinv.host_get(self.request, interface.host_id)
except Exception:
@ -290,10 +290,10 @@ class UpdateView(forms.ModalFormView):
# 'uses': interface.uses,
'ifclass': interface.ifclass,
'networktype': interface.networktype,
'providernetworks_data': providernetworks,
'providernetworks_data-external': providernetworks,
'providernetworks_pci': providernetworks,
'providernetworks_sriov': providernetworks,
'datanetworks_csv_data': datanetworks_csv,
'datanetworks_csv_data-external': datanetworks_csv,
'datanetworks_csv_pci': datanetworks_csv,
'datanetworks_csv_sriov': datanetworks_csv,
'sriov_numvfs': interface.sriov_numvfs,
'imtu': interface.imtu,
'ipv4_mode': getattr(interface, 'ipv4_mode', 'disabled'),

View File

@ -2,7 +2,7 @@
<li>
<strong>{{ interfaces.ifname }}</strong> {{": "}} {{ interfaces.ifclass }}
{% if interfaces.ifclass == 'data' %}
{{"("}} {{ interfaces.providernetworks }} {{")"}}
{{"("}} {{ interfaces.datanetworks_csv }} {{")"}}
{% endif %}
{{ " | " }} {{ interfaces.iftype }}
{% if interfaces.iftype != 'ae' and interfaces.iftype != 'vlan' %}

View File

@ -29,7 +29,7 @@
<li>
<strong>{{ interfaces.ifname }}</strong> {{": "}} {{ interfaces.ifclass }}
{% if interfaces.ifclass == 'data' %}
{{"("}} {{ interfaces.providernetworks }} {{")"}}
{{"("}} {{ interfaces.datanetworks_csv }} {{")"}}
{% endif %}
{{ " | " }} {{ interfaces.iftype }}
{% if interfaces.iftype != 'ae' and interfaces.iftype != 'vlan' %}

View File

@ -19,8 +19,8 @@
<dt>{% trans "Interface Class" %}</dt>
<dd>{{ interface.ifclass|default:_("None") }}</dd>
{% if interface.ifclass == "data" %}
<dt>{% trans "Provider Networks" %}</dt>
<dd>{{ interface.providernetworks|default:_("None") }}</dd>
<dt>{% trans "Data Networks" %}</dt>
<dd>{{ interface.datanetworks_csv|default:_("None") }}</dd>
<dt>{% trans "IPv4 Mode" %}</dt>
<dd>{{ interface.ipv4_mode|default:_("Disabled") }}</dd>
{% if interface.ipv4_mode == "pool" %}

View File

@ -1,157 +0,0 @@
# Copyright 2012 NEC Corporation
#
# 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.
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
import logging
from django.core.urlresolvers import reverse # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
from neutronclient.common import exceptions as neutron_exceptions
from horizon import exceptions
from horizon import forms
from horizon import messages
from starlingx_dashboard import api as stx_api
LOG = logging.getLogger(__name__)
class CreateProviderNetwork(forms.SelfHandlingForm):
name = forms.CharField(max_length=255,
label=_("Name"),
required=True)
description = forms.CharField(max_length=255,
label=_("Description"),
required=False)
type = forms.ChoiceField(label=_("Type"),
required=True)
mtu = forms.IntegerField(label=_("MTU"),
required=True,
initial=1500,
min_value=576,
max_value=9216,
help_text=(
_("Specifies the maximum MTU value of any associated tenant "
"network. Worker node data interface MTU values must be large "
"enough to support the tenant MTU plus any additional provider "
"encapsulation headers. For example, VXLAN provider MTU of "
"1500 requires a minimum data interface MTU of 1574 bytes (1600 "
"bytes is recommended.")))
vlan_transparent = forms.BooleanField(
label=_("VLAN Transparent"),
initial=False, required=False,
help_text=_("Allow tenant networks to be created that require "
"VLAN tagged packets to be transparently passed through "
"the provider network."))
@classmethod
def _instantiate(cls, request, *args, **kwargs):
return cls(request, *args, **kwargs)
def __init__(self, request, *args, **kwargs):
super(CreateProviderNetwork, self).__init__(request, *args, **kwargs)
providernet_type_choices = [('', _("Select a network type"))]
providernet_types = stx_api.neutron.provider_network_type_list(request)
for providernet_type in providernet_types:
providernet_type_choices.append((providernet_type.type,
providernet_type.type))
self.fields['type'].choices = providernet_type_choices
def clean(self):
cleaned_data = super(CreateProviderNetwork, self).clean()
if len(cleaned_data['name'].lstrip()) == 0:
raise forms.ValidationError('invalid provider name')
return cleaned_data
def handle(self, request, data):
try:
params = {'name': data['name'],
'type': data['type'],
'description': data['description'],
'mtu': data['mtu'],
'vlan_transparent': data['vlan_transparent']}
network = stx_api.neutron.provider_network_create(request,
**params)
msg = (_('Provider network %s was successfully created.') %
data['name'])
LOG.debug(msg)
messages.success(request, msg)
return network
except neutron_exceptions.NeutronClientException as e:
redirect = reverse('horizon:admin:providernets:index')
exceptions.handle(request, str(e), redirect=redirect)
except Exception:
redirect = reverse('horizon:admin:providernets:index')
msg = _('Failed to create provider network %s') % data['name']
exceptions.handle(request, msg, redirect=redirect)
class UpdateProviderNetwork(forms.SelfHandlingForm):
name = forms.CharField(label=_("Name"), required=False,
widget=forms.TextInput(
attrs={'readonly': 'readonly'}))
type = forms.CharField(label=_("Type"), required=False,
widget=forms.TextInput(
attrs={'readonly': 'readonly'}))
id = forms.CharField(widget=forms.HiddenInput)
# Mutable fields
description = forms.CharField(label=_("Description"), required=False)
mtu = forms.IntegerField(label=_("MTU"),
required=True,
initial=1500,
min_value=576,
max_value=9216,
help_text=(_("Specifies the minimum interface"
" MTU required to support this"
" provider network")))
vlan_transparent = forms.BooleanField(
label=_("VLAN Transparent"),
initial=False, required=False,
help_text=_("Allow tenant networks to be created that require "
"VLAN tagged packets to be transparently passed through "
"the provider network. "
"Changes will not impact existing networks."))
failure_url = 'horizon:admin:providernets:index'
def handle(self, request, data):
try:
params = {'description': data['description'],
'mtu': data['mtu'],
'vlan_transparent': data['vlan_transparent']}
providernet = stx_api.neutron.provider_network_modify(
request, data['id'], **params)
msg = (_('Provider network %s was successfully updated.') %
data['name'])
LOG.debug(msg)
messages.success(request, msg)
return providernet
except neutron_exceptions.NeutronClientException as e:
msg = _('Failed to update provider network %s') % data['name']
LOG.info(msg)
redirect = reverse(self.failure_url)
exceptions.handle(request, str(e), redirect=redirect)
except Exception:
msg = _('Failed to update provider network %s') % data['name']
LOG.info(msg)
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)

View File

@ -1,5 +1,5 @@
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'providernets'
PANEL = 'datanets'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'admin'
# The slug of the panel group the PANEL is associated with.
@ -7,4 +7,4 @@ PANEL_GROUP = 'platform'
# Python panel class of the PANEL to be added.
ADD_PANEL = ('starlingx_dashboard.dashboards.admin.'
'providernets.panel.Providernets')
'datanets.panel.Datanets')

View File

@ -186,8 +186,8 @@ horizon.host_topology = {
// 'expand' a single IF connected to many pnets into multiple 'connections'
$.each(host.interfaces, function(index, interface) {
var if_connections = []
if (interface.providernetworks) {
$.each(interface.providernetworks.split(','), function(index, providernet_name) {
if (interface.datanetworks_csv) {
$.each(interface.datanetworks_csv.split(','), function(index, providernet_name) {
var connection = {}
// Attach the interface to the connection
connection.interface = interface;