Enable zuul unit tests for stx-gui

Enable flake8 and fix tox errors resulting from that.

Story: 2003863
Task: 27930

Change-Id: Ia331856cbd6862d3c9341435450a391a7c2a2fef
Signed-off-by: Kristine Bujold <kristine.bujold@windriver.com>
This commit is contained in:
Kristine Bujold 2018-11-14 13:50:08 -05:00
parent f1013be39f
commit 182d8ff492
69 changed files with 1491 additions and 1477 deletions

View File

@ -158,6 +158,7 @@ man_pages = [
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'stx-gui', 'stx-gui Documentation',
author, 'stx-gui', 'StarlingX Horizon plugins for new StarlingX services.',
author, 'stx-gui',
'StarlingX Horizon plugins for new StarlingX services.',
'Miscellaneous'),
]

View File

@ -1,2 +1,2 @@
SRC_DIR="starlingx-dashboard"
TIS_PATCH_VER=16
TIS_PATCH_VER=17

View File

@ -11,19 +11,19 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2017 Wind River Systems, Inc.
# Copyright (c) 2017-2018 Wind River Systems, Inc.
#
from starlingx_dashboard.api import base
from starlingx_dashboard.api import dc_manager
from starlingx_dashboard.api import fm
from starlingx_dashboard.api import neutron
from starlingx_dashboard.api import nova
from starlingx_dashboard.api import fm
from starlingx_dashboard.api import patch
from starlingx_dashboard.api import sysinv
from starlingx_dashboard.api import vim
from starlingx_dashboard.api import patch
# TODO (ediardo): cleanup the imports below
__all__ = [
"base",
"dc_manager",

View File

@ -3,9 +3,7 @@
#
# SPDX-License-Identifier: Apache-2.0
#
import six
from django.conf import settings
from horizon import exceptions
from openstack_dashboard.api import base

View File

@ -4,7 +4,13 @@
# SPDX-License-Identifier: Apache-2.0
#
from openstack_dashboard.api.neutron import *
from openstack_dashboard.api.neutron import neutronclient
from openstack_dashboard.api.neutron import PortForwardingRule
from openstack_dashboard.api.neutron import ProviderNetwork
from openstack_dashboard.api.neutron import ProviderNetworkRange
from openstack_dashboard.api.neutron import ProviderNetworkType
from openstack_dashboard.api.neutron import ProviderTenantNetwork
from openstack_dashboard.api.neutron import QoSPolicy
def provider_network_type_list(request, **params):

View File

@ -8,7 +8,8 @@ from novaclient.v2 import wrs_pci
from novaclient.v2 import wrs_providernets
from openstack_dashboard.api import base
from openstack_dashboard.api.nova import *
from openstack_dashboard.api.nova import nova_exceptions
from openstack_dashboard.api.nova import novaclient
def server_group_list(request, all_projects=False):
@ -34,8 +35,7 @@ def provider_network_get(request, providernet_id):
class DeviceUsage(base.APIResourceWrapper):
"""Wrapper for Inventory Device Usage
"""
"""Wrapper for Inventory Device Usage"""
_attrs = ['device_id', 'device_name', 'vendor_id', 'class_id',
'pci_vfs_configured', 'pci_vfs_used',
'pci_pfs_configured', 'pci_pfs_used']
@ -56,8 +56,7 @@ def get_device_usage(request, device_id):
class DetailUsage(base.APIResourceWrapper):
"""Wrapper for Inventory Device Usage
"""
"""Wrapper for Inventory Device Usage"""
_attrs = ['host',
'pci_vfs_configured', 'pci_vfs_used',
'pci_pfs_configured', 'pci_pfs_used']

View File

@ -14,10 +14,8 @@
#
import logging
try:
from urlparse import urlparse
except ModuleNotFoundError:
from urllib.parse import urlparse
from six.moves.urllib.parse import urlparse
import requests

View File

@ -26,7 +26,6 @@ from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from openstack_dashboard.api import base
from starlingx_dashboard.api import base as stx_base
import cgcs_patch.constants as patch_constants
import sysinv.common.constants as constants
@ -2005,12 +2004,14 @@ class InterfaceNetwork(base.APIResourceWrapper):
def interface_network_list_by_host(request, host_uuid):
interface_networks = cgtsclient(request).interface_network.list_by_host(host_uuid)
interface_networks = cgtsclient(request).interface_network.list_by_host(
host_uuid)
return [InterfaceNetwork(n) for n in interface_networks]
def interface_network_list_by_interface(request, interface_uuid):
interface_networks = cgtsclient(request).interface_network.list_by_interface(interface_uuid)
interface_networks = cgtsclient(request).interface_network.\
list_by_interface(interface_uuid)
return [InterfaceNetwork(n) for n in interface_networks]

View File

@ -10,14 +10,12 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2016 Wind River Systems, Inc.
# Copyright (c) 2016-2018 Wind River Systems, Inc.
#
import logging
try:
from urlparse import urlparse
except ModuleNotFoundError:
from urllib.parse import urlparse
from six.moves.urllib.parse import urlparse
from openstack_dashboard.api import base

View File

@ -16,7 +16,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
@ -30,7 +30,6 @@ from django.utils.translation import ungettext_lazy
from horizon import exceptions
from horizon import tables
from horizon.utils import filters as utils_filters
from openstack_dashboard import api
from starlingx_dashboard import api as stx_api
SUPPRESSION_STATUS_CHOICES = (

View File

@ -16,7 +16,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
@ -24,7 +24,6 @@ from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import tabs
from openstack_dashboard import api
from starlingx_dashboard import api as stx_api
from starlingx_dashboard.dashboards.admin.fault_management import tables
@ -115,9 +114,6 @@ class ActiveAlarmsTab(tabs.TableTab):
def get_alarms_data(self):
search_opts = {}
# get retrieve parameters from request/session env
marker = \
self.request.GET.get(tables.AlarmsTable._meta.pagination_param,
None)
limit = \
self.request.GET.get(tables.AlarmsTable._meta.limit_param,
None)

View File

@ -16,7 +16,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
@ -30,8 +30,8 @@ from horizon import exceptions
from horizon import tabs
from horizon import views
from openstack_dashboard.api.base import is_service_enabled
from starlingx_dashboard.api import fm
from starlingx_dashboard.api import dc_manager
from starlingx_dashboard.api import fm
from starlingx_dashboard.dashboards.admin.fault_management import \
tabs as project_tabs

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2016 Wind River Systems, Inc.
# Copyright (c) 2016-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -34,4 +34,5 @@ class HostTopology(horizon.Panel):
else:
return True
dashboard.Admin.register(HostTopology)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2016 Wind River Systems, Inc.
# Copyright (c) 2016-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -12,8 +12,8 @@ from starlingx_dashboard.dashboards.admin.fault_management import \
tables as fm_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
from starlingx_dashboard.dashboards.admin.providernets.providernets.ranges \
import tables as sr_tables
LOG = logging.getLogger(__name__)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2016 Wind River Systems, Inc.
# Copyright (c) 2016-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -159,14 +159,14 @@ class JSONView(View):
tenant_id = self.request.user.tenant_id
for resource in resources:
if (resource.get('tenant_id') and
tenant_id != resource.get('tenant_id')):
tenant_id != resource.get('tenant_id')):
continue
resource['url'] = reverse(view, None, [str(resource['id'])])
def _check_router_external_port(self, ports, router_id, network_id):
for port in ports:
if (port['network_id'] == network_id and
port['device_id'] == router_id):
port['device_id'] == router_id):
return True
return False

View File

@ -76,8 +76,8 @@ class CreateAddress(tables.LinkAction):
return False
if interface.ifclass == 'platform':
interface_networks = stx_api.sysinv.interface_network_list_by_interface(request,
interface.uuid)
interface_networks = stx_api.sysinv.\
interface_network_list_by_interface(request, interface.uuid)
for interface_network in interface_networks:
if interface_network.network_type in ALLOWED_INTERFACE_TYPES:
return True

View File

@ -390,10 +390,6 @@ class AddInterface(forms.SelfHandlingForm):
host_uuid = kwargs['initial']['ihost_uuid']
# Retrieve SDN configuration
sdn_enabled = kwargs['initial']['sdn_enabled']
sdn_l3_mode = kwargs['initial']['sdn_l3_mode_enabled']
# Populate Address Pool selections
pools = sysinv.address_pool_list(self.request)
self.fields['ipv4_pool'].choices = _get_ipv4_pool_choices(pools)
@ -640,23 +636,19 @@ class UpdateInterface(AddInterface):
ifclass_val = kwargs['initial']['ifclass']
host_uuid = kwargs['initial']['ihost_uuid']
# Get the SDN configuration
sdn_enabled = kwargs['initial']['sdn_enabled']
sdn_l3_mode = kwargs['initial']['sdn_l3_mode_enabled']
this_interface_id = kwargs['initial']['id']
iftype_val = kwargs['initial']['iftype']
interface_networks = sysinv.interface_network_list_by_interface(self.request,
this_interface_id)
interface_networks = sysinv.interface_network_list_by_interface(
self.request, this_interface_id)
if ifclass_val == 'platform':
# Load the networks associated with this interface
network_choices = self.fields['networks'].choices
network_choice_dict = dict(network_choices)
initial_networks = []
for i in interface_networks:
for uuid, name in network_choice_dict.items():
for uuid in network_choice_dict.keys():
if i.network_uuid == uuid:
initial_networks.append(uuid)
@ -750,7 +742,8 @@ class UpdateInterface(AddInterface):
ifclass = cleaned_data.get('ifclass')
interface_id = cleaned_data.get('id')
networks = cleaned_data.pop('networks', [])
interface_networks = sysinv.interface_network_list_by_interface(self.request, interface_id)
interface_networks = sysinv.interface_network_list_by_interface(
self.request, interface_id)
network_ids = []
networks_to_add = []
networks_to_remove = []
@ -773,7 +766,8 @@ class UpdateInterface(AddInterface):
interface_networks_to_remove.append(i.uuid)
cleaned_data['networks'] = network_ids
cleaned_data['networks_to_add'] = networks_to_add
cleaned_data['interface_networks_to_remove'] = interface_networks_to_remove
cleaned_data['interface_networks_to_remove'] = \
interface_networks_to_remove
return cleaned_data
def handle(self, request, data):
@ -855,7 +849,8 @@ class UpdateInterface(AddInterface):
else:
del data['networks']
if data['networks_to_add']:
data['networks_to_add'] = str(",".join(data['networks_to_add']))
data['networks_to_add'] = \
str(",".join(data['networks_to_add']))
else:
del data['networks_to_add']
if data['interface_networks_to_remove']:

View File

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 NEC Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -14,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-2018 Wind River Systems, Inc.
#

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2016 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -55,7 +55,8 @@ def get_port_data(request, host_id, interface=None):
# neighbours
neighbour_list = \
stx_api.sysinv.host_lldpneighbour_list(request, host_id)
interface_list = stx_api.sysinv.host_interface_list(request, host_id)
interface_list = stx_api.sysinv.host_interface_list(request,
host_id)
for p in port_list:
port_info = "%s (%s, %s, " % (p.get_port_display_name(),
@ -184,13 +185,14 @@ class AddInterfaceProfileView(forms.ModalFormView):
try:
host = stx_api.sysinv.host_get(self.request, host_id)
all_ports = stx_api.sysinv.host_port_list(self.request, host.uuid)
all_ports = stx_api.sysinv.host_port_list(self.request,
host.uuid)
host.ports = [p for p in all_ports if p.interface_uuid]
for p in host.ports:
p.namedisplay = p.get_port_display_name()
host.interfaces = stx_api.sysinv.host_interface_list(self.request,
host.uuid)
host.interfaces = stx_api.sysinv.host_interface_list(
self.request, host.uuid)
for i in host.interfaces:
i.ports = [p.get_port_display_name()
for p in all_ports if

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -339,7 +339,8 @@ class AddMemoryProfile(forms.SelfHandlingForm):
memoryProfileName = data['profilename']
try:
memoryProfile = stx_api.sysinv.host_memprofile_create(request, **data)
memoryProfile = stx_api.sysinv.host_memprofile_create(
request, **data)
msg = _('Memory Profile "%s" was successfully created.') % \
memoryProfileName
LOG.debug(msg)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -85,13 +85,15 @@ class AddMemoryProfileView(forms.ModalFormView):
host_id = self.kwargs['host_id']
try:
host = stx_api.sysinv.host_get(self.request, host_id)
host.nodes = stx_api.sysinv.host_node_list(self.request, host.uuid)
host.nodes = stx_api.sysinv.host_node_list(self.request,
host.uuid)
host.memory = \
stx_api.sysinv.host_memory_list(self.request, host.uuid)
numa_node_tuple_list = []
for m in host.memory:
node = stx_api.sysinv.host_node_get(self.request, m.inode_uuid)
node = stx_api.sysinv.host_node_get(self.request,
m.inode_uuid)
numa_node_tuple_list.append((node.numa_node, m))
host.numa_nodes = numa_node_tuple_list

View File

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 NEC Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -14,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-2018 Wind River Systems, Inc.
#

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -39,7 +39,8 @@ class UpdateView(forms.ModalFormView):
port_id = self.kwargs['port_id']
host_id = self.kwargs['host_id']
try:
self._object = stx_api.sysinv.host_port_get(self.request, port_id)
self._object = stx_api.sysinv.host_port_get(self.request,
port_id)
self._object.host_id = host_id
except Exception:
redirect = reverse("horizon:project:networks:detail",

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -75,7 +75,8 @@ class AddSensorGroup(forms.SelfHandlingForm):
del data['hostname']
# The REST API takes care of creating the sensorgroup and assoc
sensorgroup = stx_api.sysinv.host_sensorgroup_create(request, **data)
sensorgroup = stx_api.sysinv.host_sensorgroup_create(request,
**data)
msg = _('Sensor group was successfully created.')
LOG.debug(msg)
@ -208,9 +209,10 @@ class UpdateSensorGroup(forms.SelfHandlingForm):
mysensorgroupname = data.pop('sensorgroupname', None)
try:
sensorgroup = stx_api.sysinv.host_sensorgroup_update(request,
sensorgroup_id,
**data)
sensorgroup = \
stx_api.sysinv.host_sensorgroup_update(request,
sensorgroup_id,
**data)
msg = _('SensorGroup "%s" was '
'successfully updated.') % mysensorgroupname

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -209,7 +209,8 @@ class RelearnSensorModel(tables.Action):
def single(self, table, request, obj_ids):
LOG.debug("requesting relearn of sensor model for host "
"%s", table.kwargs['host'].uuid)
stx_api.sysinv.host_sensorgroup_relearn(request, table.kwargs['host'].uuid)
stx_api.sysinv.host_sensorgroup_relearn(request,
table.kwargs['host'].uuid)
class SensorGroupsTable(tables.DataTable):

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -74,8 +74,9 @@ class UpdateSensorGroupView(forms.ModalFormView):
LOG.debug("sensorgroup_id=%s kwargs=%s",
sensorgroup_id, self.kwargs)
try:
self._object = stx_api.sysinv.host_sensorgroup_get(self.request,
sensorgroup_id)
self._object = \
stx_api.sysinv.host_sensorgroup_get(self.request,
sensorgroup_id)
self._object.host_id = host_id
except Exception:
@ -147,7 +148,8 @@ class DetailSensorView(views.HorizonTemplateView):
if not hasattr(self, "_sensor"):
sensor_id = self.kwargs['sensor_id']
try:
sensor = stx_api.sysinv.host_sensor_get(self.request, sensor_id)
sensor = stx_api.sysinv.host_sensor_get(self.request,
sensor_id)
except Exception:
redirect = reverse('horizon:admin:inventory:index')
exceptions.handle(self.request,
@ -194,8 +196,9 @@ class DetailSensorGroupView(views.HorizonTemplateView):
if not hasattr(self, "_sensorgroup"):
sensorgroup_id = self.kwargs['sensorgroup_id']
try:
sensorgroup = stx_api.sysinv.host_sensorgroup_get(self.request,
sensorgroup_id)
sensorgroup = \
stx_api.sysinv.host_sensorgroup_get(self.request,
sensorgroup_id)
except Exception:
redirect = reverse('horizon:admin:inventory:index')
exceptions.handle(self.request,

View File

@ -40,7 +40,8 @@ class AddDiskProfile(forms.SelfHandlingForm):
def handle(self, request, data):
diskProfileName = data['profilename']
try:
diskProfile = stx_api.sysinv.host_diskprofile_create(request, **data)
diskProfile = stx_api.sysinv.host_diskprofile_create(request,
**data)
msg = _('Storage Profile "%s" was successfully created.') \
% diskProfileName
@ -72,13 +73,12 @@ class EditStorageVolume(forms.SelfHandlingForm):
help_text=_("Assign disk to journal "
"storage volume."))
journal_size_gib = forms.CharField(label=_("Journal Size GiB"),
required=False,
initial=stx_api.sysinv.JOURNAL_DEFAULT_SIZE,
widget=forms.TextInput(attrs={
'data-slug': 'journal_size_gib'}),
help_text=_("Journal's size for the "
"current OSD."))
journal_size_gib = forms.CharField(
label=_("Journal Size GiB"),
required=False,
initial=stx_api.sysinv.JOURNAL_DEFAULT_SIZE,
widget=forms.TextInput(attrs={'data-slug': 'journal_size_gib'}),
help_text=_("Journal's size for the current OSD."))
failure_url = 'horizon:admin:inventory:detail'
@ -127,7 +127,8 @@ class EditStorageVolume(forms.SelfHandlingForm):
data['journal_location'] = journal
else:
data['journal_location'] = None
data['journal_size_mib'] = stx_api.sysinv.JOURNAL_DEFAULT_SIZE * 1024
data['journal_size_mib'] = \
stx_api.sysinv.JOURNAL_DEFAULT_SIZE * 1024
del data['journal_locations']
del data['id']
@ -216,16 +217,15 @@ class AddStorageVolume(forms.SelfHandlingForm):
"journal storage "
"volume."))
journal_size_gib = forms.CharField(label=_("Journal Size GiB"),
required=False,
initial=stx_api.sysinv.JOURNAL_DEFAULT_SIZE,
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'function',
'data-function-osd':
_("Journal Size GiB")}),
help_text=_("Journal's size for the"
"current OSD."))
journal_size_gib = forms.CharField(
label=_("Journal Size GiB"),
required=False,
initial=stx_api.sysinv.JOURNAL_DEFAULT_SIZE,
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'function',
'data-function-osd': _("Journal Size GiB")}),
help_text=_("Journal's size for the current OSD."))
tiers = forms.ChoiceField(label=_("Storage Tier"),
required=False,
@ -245,7 +245,8 @@ class AddStorageVolume(forms.SelfHandlingForm):
this_stor_uuid = 0
host_uuid = kwargs['initial']['ihost_uuid']
avail_disk_list = stx_api.sysinv.host_disk_list(self.request, host_uuid)
avail_disk_list = stx_api.sysinv.host_disk_list(self.request,
host_uuid)
disk_tuple_list = []
for d in avail_disk_list:
if d.istor_uuid and d.istor_uuid != this_stor_uuid:
@ -321,7 +322,8 @@ class AddStorageVolume(forms.SelfHandlingForm):
data['journal_location'] = journal
else:
data['journal_location'] = None
data['journal_size_mib'] = stx_api.sysinv.JOURNAL_DEFAULT_SIZE * 1024
data['journal_size_mib'] = \
stx_api.sysinv.JOURNAL_DEFAULT_SIZE * 1024
try:
del data['host_id']
@ -543,7 +545,8 @@ class AddPhysicalVolume(forms.SelfHandlingForm):
if stx_api.sysinv.SUBFUNCTIONS_COMPUTE in subfunctions:
compatible_lvgs += [stx_api.sysinv.LVG_NOVA_LOCAL]
avail_disk_list = stx_api.sysinv.host_disk_list(self.request, host_uuid)
avail_disk_list = stx_api.sysinv.host_disk_list(self.request,
host_uuid)
ilvg_list = stx_api.sysinv.host_lvg_list(self.request, host_uuid)
partitions = stx_api.sysinv.host_disk_partition_list(self.request,
host_uuid)
@ -558,7 +561,8 @@ class AddPhysicalVolume(forms.SelfHandlingForm):
for lvg in ilvg_list:
if (lvg.lvm_vg_name in compatible_lvgs and
lvg.vg_state in [stx_api.sysinv.LVG_ADD, stx_api.sysinv.LVG_PROV]):
lvg.vg_state in [stx_api.sysinv.LVG_ADD,
stx_api.sysinv.LVG_PROV]):
if (lvg.lvm_vg_name == stx_api.sysinv.LVG_CINDER_VOLUMES and
pv_cinder_volumes):
continue
@ -777,7 +781,8 @@ class CreatePartition(forms.SelfHandlingForm):
# Populate disk choices.
host_uuid = kwargs['initial']['ihost_uuid']
avail_disk_list = stx_api.sysinv.host_disk_list(self.request, host_uuid)
avail_disk_list = stx_api.sysinv.host_disk_list(self.request,
host_uuid)
disk_tuple_list = []
for d in avail_disk_list:
disk_model = d.get_model_num()
@ -812,7 +817,8 @@ class CreatePartition(forms.SelfHandlingForm):
del data['size_gib']
data['type_guid'] = stx_api.sysinv.USER_PARTITION_PHYS_VOL
# The REST API takes care of creating the partition.
partition = stx_api.sysinv.host_disk_partition_create(request, **data)
partition = stx_api.sysinv.host_disk_partition_create(request,
**data)
msg = _('Partition was successfully created.')
LOG.debug(msg)

View File

@ -1,6 +1,4 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2015-2017 Wind River Systems, Inc.
# Copyright (c) 2015-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#

View File

@ -1,6 +1,4 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2015 Wind River Systems, Inc.
# Copyright (c) 2015-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#

View File

@ -1,6 +1,4 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2015 Wind River Systems, Inc.
# Copyright (c) 2015-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#

View File

@ -1,6 +1,4 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2015 Wind River Systems, Inc.
# Copyright (c) 2015-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#

View File

@ -1,6 +1,4 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2015 Wind River Systems, Inc.
# Copyright (c) 2015-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2017 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -720,13 +720,16 @@ class Hosts(tables.DataTable):
display_choices=stx_api.sysinv.Host.PERSONALITY_DISPLAY_CHOICES)
admin = tables.Column("administrative",
verbose_name=_("Admin State"),
display_choices=stx_api.sysinv.Host.ADMIN_DISPLAY_CHOICES)
display_choices=stx_api.sysinv.
Host.ADMIN_DISPLAY_CHOICES)
oper = tables.Column("operational",
verbose_name=_("Operational State"),
display_choices=stx_api.sysinv.Host.OPER_DISPLAY_CHOICES)
display_choices=stx_api.sysinv.
Host.OPER_DISPLAY_CHOICES)
avail = tables.Column("availability",
verbose_name=_("Availability State"),
display_choices=stx_api.sysinv.Host.AVAIL_DISPLAY_CHOICES)
display_choices=stx_api.sysinv.
Host.AVAIL_DISPLAY_CHOICES)
uptime = tables.Column('boottime',
verbose_name=_('Uptime'),
filters=(timesince,),

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2017 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -101,7 +101,8 @@ class HostsTab(tabs.TableTab):
return hosts
def get_hostscontroller_data(self):
controllers = self.get_hosts_data(stx_api.sysinv.PERSONALITY_CONTROLLER)
controllers = self.get_hosts_data(
stx_api.sysinv.PERSONALITY_CONTROLLER)
return controllers
@ -543,10 +544,12 @@ class InterfacesTab(tabs.TableTab):
platform_network_names = []
if i.ifclass == 'platform':
for interface_network in stx_api.sysinv.interface_network_list_by_interface(self.request,
i.uuid):
for interface_network in stx_api.sysinv.\
interface_network_list_by_interface(
self.request, i.uuid):
if str(interface_network.network_id) in i.networks:
platform_network_names.append(interface_network.network_name)
platform_network_names.append(
interface_network.network_name)
i.platform_network_names = platform_network_names
if i.iftype == 'ethernet':

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2017 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -27,6 +27,8 @@ from starlingx_dashboard.dashboards.admin.inventory.ports import \
views as port_views
from starlingx_dashboard.dashboards.admin.inventory.sensors import \
views as sensor_views
from starlingx_dashboard.dashboards.admin.inventory.storages import \
urls as storages_urls
from starlingx_dashboard.dashboards.admin.inventory.storages import \
views as storage_views
from starlingx_dashboard.dashboards.admin.inventory.views import \
@ -37,8 +39,6 @@ from starlingx_dashboard.dashboards.admin.inventory.views import \
IndexView
from starlingx_dashboard.dashboards.admin.inventory.views import \
UpdateView
from starlingx_dashboard.dashboards.admin.inventory.storages \
import urls as storages_urls
urlpatterns = [

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2017 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -64,7 +64,8 @@ class UpdateView(workflows.WorkflowView):
def get_initial(self):
try:
host = stx_api.sysinv.host_get(self.request, self.kwargs['host_id'])
host = stx_api.sysinv.host_get(self.request,
self.kwargs['host_id'])
except Exception:
exceptions.handle(self.request,
_("Unable to retrieve host data."))
@ -109,8 +110,10 @@ class DetailView(tabs.TabbedTableView):
try:
host = stx_api.sysinv.host_get(self.request, host_id)
host.nodes = stx_api.sysinv.host_node_list(self.request, host.uuid)
host.cpus = stx_api.sysinv.host_cpu_list(self.request, host.uuid)
host.nodes = stx_api.sysinv.host_node_list(self.request,
host.uuid)
host.cpus = stx_api.sysinv.host_cpu_list(self.request,
host.uuid)
icpu_utils.restructure_host_cpu_data(host)
host.memorys = stx_api.sysinv.host_memory_list(self.request,
@ -121,13 +124,16 @@ class DetailView(tabs.TabbedTableView):
m.numa_node = n.numa_node
break
host.ports = stx_api.sysinv.host_port_list(self.request, host.uuid)
host.interfaces = stx_api.sysinv.host_interface_list(self.request,
host.uuid)
host.ports = stx_api.sysinv.host_port_list(self.request,
host.uuid)
host.interfaces = stx_api.sysinv.host_interface_list(
self.request, host.uuid)
host.devices = stx_api.sysinv.host_device_list(self.request,
host.uuid)
host.disks = stx_api.sysinv.host_disk_list(self.request, host.uuid)
host.stors = stx_api.sysinv.host_stor_list(self.request, host.uuid)
host.disks = stx_api.sysinv.host_disk_list(self.request,
host.uuid)
host.stors = stx_api.sysinv.host_stor_list(self.request,
host.uuid)
host.pvs = stx_api.sysinv.host_pv_list(self.request, host.uuid)
host.partitions = stx_api.sysinv.host_disk_partition_list(
self.request, host.uuid)
@ -137,7 +143,8 @@ class DetailView(tabs.TabbedTableView):
p.status = stx_api.sysinv.PARTITION_STATUS_MSG[p.status]
host.lldpneighbours = \
stx_api.sysinv.host_lldpneighbour_list(self.request, host.uuid)
stx_api.sysinv.host_lldpneighbour_list(self.request,
host.uuid)
# Set the value for neighbours field for each port in the host.
# This will be referenced in Interfaces table
@ -151,7 +158,8 @@ class DetailView(tabs.TabbedTableView):
pv.pv_state = self._adjust_state_data(pv.pv_state,
pv.lvm_vg_name)
host.lvgs = stx_api.sysinv.host_lvg_list(self.request, host.uuid,
host.lvgs = stx_api.sysinv.host_lvg_list(self.request,
host.uuid,
get_params=True)
# Adjust lvg state to be more "user friendly"

View File

@ -56,8 +56,8 @@ BM_TYPES_CHOICES = (
def ifprofile_applicable(request, host, profile):
for interface in profile.interfaces:
interface_networks = stx_api.sysinv.interface_network_list_by_interface(request,
interface.uuid)
interface_networks = stx_api.sysinv.\
interface_network_list_by_interface(request, interface.uuid)
if (stx_api.sysinv.PERSONALITY_COMPUTE == host._personality and
any(interface_network.network_type == 'oam'
for interface_network in interface_networks)):
@ -248,8 +248,8 @@ class UpdateHostInfoAction(workflows.Action):
attrs={'class': 'switched',
'data-switch-on': 'personality',
'data-personality-' +
stx_api.sysinv.PERSONALITY_COMPUTE: _(
"Host Name")}))
stx_api.sysinv.PERSONALITY_COMPUTE:
_("Host Name")}))
location = forms.CharField(label=_("Location"),
initial='location',
@ -345,8 +345,8 @@ class UpdateHostInfoAction(workflows.Action):
if host.nodes and host.cpus and host.ports:
# Populate Available Cpu Profile Choices
try:
avail_cpu_profile_list = stx_api.sysinv.host_cpuprofile_list(
self.request)
avail_cpu_profile_list = \
stx_api.sysinv.host_cpuprofile_list(self.request)
host_profile = icpu_utils.HostCpuProfile(
host.subfunctions,
@ -393,8 +393,8 @@ class UpdateHostInfoAction(workflows.Action):
self.fields[
'interfaceProfile'].widget = forms.widgets.HiddenInput()
if ((personality == 'storage' or 'compute' in host._subfunctions) and
host.disks):
if ((personality == 'storage' or
'compute' in host._subfunctions) and host.disks):
# Populate Available Disk Profile Choices
try:
disk_profile_tuple_list = [
@ -467,10 +467,11 @@ class UpdateHostInfoAction(workflows.Action):
if cleaned_data['personality'] == stx_api.sysinv.PERSONALITY_STORAGE:
self._subfunctions = stx_api.sysinv.PERSONALITY_STORAGE
cleaned_data['subfunctions'] = self._subfunctions
elif cleaned_data['personality'] == stx_api.sysinv.PERSONALITY_CONTROLLER:
elif cleaned_data['personality'] == \
stx_api.sysinv.PERSONALITY_CONTROLLER:
if self.system_type == constants.TS_AIO:
self._subfunctions = (stx_api.sysinv.PERSONALITY_CONTROLLER + ',' +
stx_api.sysinv.PERSONALITY_COMPUTE)
self._subfunctions = (stx_api.sysinv.PERSONALITY_CONTROLLER +
',' + stx_api.sysinv.PERSONALITY_COMPUTE)
else:
self._subfunctions = stx_api.sysinv.PERSONALITY_CONTROLLER
cleaned_data['subfunctions'] = self._subfunctions
@ -629,7 +630,8 @@ class BoardManagementAction(workflows.Action):
'class': 'switched',
'data-switch-on': 'bm_type',
'data-bm_type-' +
stx_api.sysinv.BM_TYPE_GENERIC: FIELD_LABEL_BM_CONFIRM_PASSWORD}),
stx_api.sysinv.BM_TYPE_GENERIC:
FIELD_LABEL_BM_CONFIRM_PASSWORD}),
required=False)
def clean(self):
@ -639,8 +641,6 @@ class BoardManagementAction(workflows.Action):
if 'bm_ip' not in cleaned_data or not cleaned_data['bm_ip']:
raise forms.ValidationError(
_('Board management IP address is required.'))
raise forms.ValidationError(
_('Board management MAC address is required.'))
if 'bm_username' not in cleaned_data or not \
cleaned_data['bm_username']:

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-2018 Wind River Systems, Inc.
#
@ -89,7 +89,8 @@ class CreateProviderNetwork(forms.SelfHandlingForm):
'mtu': data['mtu'],
'vlan_transparent': data['vlan_transparent']}
network = stx_api.neutron.provider_network_create(request, **params)
network = stx_api.neutron.provider_network_create(request,
**params)
msg = (_('Provider network %s was successfully created.') %
data['name'])
LOG.debug(msg)
@ -97,7 +98,7 @@ class CreateProviderNetwork(forms.SelfHandlingForm):
return network
except neutron_exceptions.NeutronClientException as e:
redirect = reverse('horizon:admin:providernets:index')
exceptions.handle(request, e.message, redirect=redirect)
exceptions.handle(request, str(e), redirect=redirect)
except Exception:
redirect = reverse('horizon:admin:providernets:index')
msg = _('Failed to create provider network %s') % data['name']
@ -148,7 +149,7 @@ class UpdateProviderNetwork(forms.SelfHandlingForm):
msg = _('Failed to update provider network %s') % data['name']
LOG.info(msg)
redirect = reverse(self.failure_url)
exceptions.handle(request, e.message, redirect=redirect)
exceptions.handle(request, str(e), redirect=redirect)
except Exception:
msg = _('Failed to update provider network %s') % data['name']
LOG.info(msg)

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2015,2017 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
@ -145,11 +145,11 @@ class CreateProviderNetworkRange(forms.SelfHandlingForm):
messages.success(request, msg)
return providernet_range
except neutron_exceptions.NeutronClientException as e:
LOG.info(e.message)
LOG.info(str(e))
redirect = reverse('horizon:admin:providernets:providernets:'
'detail',
args=(data['providernet_id'],))
exceptions.handle(request, e.message, redirect=redirect)
exceptions.handle(request, str(e), redirect=redirect)
except Exception:
msg = _('Failed to create a provider'
' network range for network %s') \
@ -236,11 +236,11 @@ class UpdateProviderNetworkRange(forms.SelfHandlingForm):
messages.success(request, msg)
return providernet_range
except neutron_exceptions.NeutronClientException as e:
LOG.info(e.message)
LOG.info(str(e))
redirect = reverse('horizon:admin:providernets:providernets:'
'detail',
args=(data['providernet_id'],))
exceptions.handle(request, e.message, redirect=redirect)
exceptions.handle(request, str(e), redirect=redirect)
except Exception:
msg = (_('Failed to update provider network range %s') %
data['providernet_range_id'])

View File

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 NEC Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -14,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2014,2017 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
@ -61,8 +59,9 @@ class DeleteProviderNetworkRange(tables.DeleteAction):
try:
stx_api.neutron.provider_network_range_delete(request, obj_id)
except neutron_exceptions.NeutronClientException as e:
LOG.info(e.message)
exceptions.handle(request, e.message,
LOG.info(str(e))
exceptions.handle(request,
str(e),
redirect=self.get_redirect_url())
except Exception:
msg = _('Failed to delete provider network range %s') % obj_id

View File

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 NEC Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -14,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2016 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
from django.utils.translation import ugettext_lazy as _ # noqa

View File

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 NEC Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -14,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#

View File

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 NEC Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -14,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2017 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
@ -51,8 +49,8 @@ class CreateView(forms.ModalFormView):
if not hasattr(self, "_object"):
try:
providernet_id = self.kwargs["providernet_id"]
self._object = stx_api.neutron.provider_network_get(self.request,
providernet_id)
self._object = stx_api.neutron.provider_network_get(
self.request, providernet_id)
except Exception:
redirect = reverse(self.failure_url,
args=(self.kwargs['providernet_id'],))

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-2018 Wind River Systems, Inc.
#
@ -54,9 +54,9 @@ class DeleteProviderNetwork(tables.DeleteAction):
try:
stx_api.neutron.provider_network_delete(request, obj_id)
except neutron_exceptions.NeutronClientException as e:
LOG.info(e.message)
LOG.info(str(e))
redirect = reverse('horizon:admin:providernets:index')
exceptions.handle(request, e.message, redirect=redirect)
exceptions.handle(request, str(e), redirect=redirect)
except Exception:
msg = _('Failed to delete provider network %s') % obj_id
LOG.info(msg)

View File

@ -1,196 +1,195 @@
# 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-2017 Wind River Systems, Inc.
#
# Copyright 2012 Nebula, Inc.
# All rights reserved.
"""
Views for managing volumes.
"""
from django.conf import settings
from django.core.urlresolvers import reverse
from django.forms import ValidationError
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import forms
from horizon import messages
from openstack_dashboard import api
from openstack_dashboard.api import cinder
from openstack_dashboard.api import nova
from openstack_dashboard.dashboards.project.instances import tables
from starlingx_dashboard.api import nova as stx_nova
class CreateForm(forms.SelfHandlingForm):
tenantP = forms.ChoiceField(label=_("Project"), required=True)
name = forms.CharField(max_length="255", label=_("Server Group Name"))
policy = forms.ChoiceField(label=_("Policy"),
required=False,
widget=forms.Select(
attrs={
'class': 'switchable',
'data-slug': 'policy_ht'}))
is_best_effort = forms.BooleanField(label=_("Best Effort"), required=False)
group_size = forms.IntegerField(
min_value=1,
label=_("Max Group Size (Instances)"),
required=False,
widget=forms.TextInput(
attrs={
'class': 'switchable switched',
'data-switch-on': 'policy_ht',
'data-policy_ht-anti-affinity': 'Max Group Size (Instances)',
'data-policy_ht-affinity': 'Max Group Size (Instances)'}))
group_size_ht = forms.IntegerField(
label=_("Max Group Size (Instances)"),
required=False,
widget=forms.TextInput(
attrs={
'readonly': 'readonly',
'class': 'switchable switched',
'data-switch-on': 'policy_ht',
'data-policy_ht-affinity-hyperthread':
'Max Group Size (Instances)'}))
def __init__(self, request, *args, **kwargs):
super(CreateForm, self).__init__(request, *args, **kwargs)
self.fields['policy'].choices = [("anti-affinity", "anti-affinity"),
("affinity", "affinity")]
# Populate available project_id/name choices
all_projects = []
try:
# Get list of available projects.
all_projects, has_more = api.keystone.tenant_list(request)
projects_list = [(project.id, project.name)
for project in all_projects]
except Exception:
projects_list = []
exceptions.handle(self.request,
_('Unable to retrieve list of tenants.'))
self.fields['tenantP'].choices = projects_list
def handle(self, request, data):
try:
policy = data['policy']
policies = []
if policy:
policies.append(policy)
metadata = {}
if data['is_best_effort']:
metadata['wrs-sg:best_effort'] = "true"
group_size = data['group_size']
group_size_ht = data['group_size_ht']
if group_size:
metadata['wrs-sg:group_size'] = str(group_size)
elif group_size_ht:
metadata['wrs-sg:group_size'] = str(group_size_ht)
project_id = None
if data['tenantP']:
project_id = data['tenantP']
server_group = stx_nova.server_group_create(
request, data['name'], project_id, metadata, policies)
return server_group
except ValidationError as e:
self.api_error(e.messages[0])
return False
except Exception as e:
exceptions.handle(request, ignore=True)
self.api_error(_("Unable to create server group."))
return False
class AttachForm(forms.SelfHandlingForm):
instance = forms.ChoiceField(label=_("Attach to Server Group"),
help_text=_("Select an server group to "
"attach to."))
device = forms.CharField(label=_("Device Name"))
def __init__(self, *args, **kwargs):
super(AttachForm, self).__init__(*args, **kwargs)
# Hide the device field if the hypervisor doesn't support it.
hypervisor_features = getattr(settings,
"OPENSTACK_HYPERVISOR_FEATURES", {})
can_set_mount_point = hypervisor_features.get("can_set_mount_point",
True)
if not can_set_mount_point:
self.fields['device'].widget = forms.widgets.HiddenInput()
self.fields['device'].required = False
# populate volume_id
volume = kwargs.get('initial', {}).get("volume", None)
if volume:
volume_id = volume.id
else:
volume_id = None
self.fields['volume_id'] = forms.CharField(widget=forms.HiddenInput(),
initial=volume_id)
# Populate instance choices
instance_list = kwargs.get('initial', {}).get('instances', [])
instances = []
for instance in instance_list:
if instance.status in tables.ACTIVE_STATES and \
not any(instance.id == att["server_id"]
for att in volume.attachments):
instances.append((instance.id, '%s (%s)' % (instance.name,
instance.id)))
if instances:
instances.insert(0, ("", _("Select an instance")))
else:
instances = (("", _("No instances available")),)
self.fields['instance'].choices = instances
def handle(self, request, data):
instance_choices = dict(self.fields['instance'].choices)
instance_name = instance_choices.get(data['instance'],
_("Unknown instance (None)"))
# The name of the instance in the choices list has the ID appended to
# it, so let's slice that off...
instance_name = instance_name.rsplit(" (")[0]
try:
attach = api.nova.instance_volume_attach(request,
data['volume_id'],
data['instance'],
data.get('device', ''))
volume = cinder.volume_get(request, data['volume_id'])
if not volume.display_name:
volume_name = volume.id
else:
volume_name = volume.display_name
message = _('Attaching volume %(vol)s to instance '
'%(inst)s on %(dev)s.') % {"vol": volume_name,
"inst": instance_name,
"dev": attach.device}
messages.info(request, message)
return True
except Exception:
redirect = reverse("horizon:project:volumes:index")
exceptions.handle(request,
_('Unable to attach volume.'),
redirect=redirect)
# 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.
#
# Copyright 2012 Nebula, Inc.
# All rights reserved.
"""
Views for managing volumes.
"""
from django.conf import settings
from django.core.urlresolvers import reverse
from django.forms import ValidationError
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import forms
from horizon import messages
from openstack_dashboard import api
from openstack_dashboard.api import cinder
from openstack_dashboard.dashboards.project.instances import tables
from starlingx_dashboard.api import nova as stx_nova
class CreateForm(forms.SelfHandlingForm):
tenantP = forms.ChoiceField(label=_("Project"), required=True)
name = forms.CharField(max_length="255", label=_("Server Group Name"))
policy = forms.ChoiceField(label=_("Policy"),
required=False,
widget=forms.Select(
attrs={
'class': 'switchable',
'data-slug': 'policy_ht'}))
is_best_effort = forms.BooleanField(label=_("Best Effort"), required=False)
group_size = forms.IntegerField(
min_value=1,
label=_("Max Group Size (Instances)"),
required=False,
widget=forms.TextInput(
attrs={
'class': 'switchable switched',
'data-switch-on': 'policy_ht',
'data-policy_ht-anti-affinity': 'Max Group Size (Instances)',
'data-policy_ht-affinity': 'Max Group Size (Instances)'}))
group_size_ht = forms.IntegerField(
label=_("Max Group Size (Instances)"),
required=False,
widget=forms.TextInput(
attrs={
'readonly': 'readonly',
'class': 'switchable switched',
'data-switch-on': 'policy_ht',
'data-policy_ht-affinity-hyperthread':
'Max Group Size (Instances)'}))
def __init__(self, request, *args, **kwargs):
super(CreateForm, self).__init__(request, *args, **kwargs)
self.fields['policy'].choices = [("anti-affinity", "anti-affinity"),
("affinity", "affinity")]
# Populate available project_id/name choices
all_projects = []
try:
# Get list of available projects.
all_projects, has_more = api.keystone.tenant_list(request)
projects_list = [(project.id, project.name)
for project in all_projects]
except Exception:
projects_list = []
exceptions.handle(self.request,
_('Unable to retrieve list of tenants.'))
self.fields['tenantP'].choices = projects_list
def handle(self, request, data):
try:
policy = data['policy']
policies = []
if policy:
policies.append(policy)
metadata = {}
if data['is_best_effort']:
metadata['wrs-sg:best_effort'] = "true"
group_size = data['group_size']
group_size_ht = data['group_size_ht']
if group_size:
metadata['wrs-sg:group_size'] = str(group_size)
elif group_size_ht:
metadata['wrs-sg:group_size'] = str(group_size_ht)
project_id = None
if data['tenantP']:
project_id = data['tenantP']
server_group = stx_nova.server_group_create(
request, data['name'], project_id, metadata, policies)
return server_group
except ValidationError as e:
self.api_error(e.messages[0])
return False
except Exception as e:
exceptions.handle(request, ignore=True)
self.api_error(_("Unable to create server group."))
return False
class AttachForm(forms.SelfHandlingForm):
instance = forms.ChoiceField(label=_("Attach to Server Group"),
help_text=_("Select an server group to "
"attach to."))
device = forms.CharField(label=_("Device Name"))
def __init__(self, *args, **kwargs):
super(AttachForm, self).__init__(*args, **kwargs)
# Hide the device field if the hypervisor doesn't support it.
hypervisor_features = getattr(settings,
"OPENSTACK_HYPERVISOR_FEATURES", {})
can_set_mount_point = hypervisor_features.get("can_set_mount_point",
True)
if not can_set_mount_point:
self.fields['device'].widget = forms.widgets.HiddenInput()
self.fields['device'].required = False
# populate volume_id
volume = kwargs.get('initial', {}).get("volume", None)
if volume:
volume_id = volume.id
else:
volume_id = None
self.fields['volume_id'] = forms.CharField(widget=forms.HiddenInput(),
initial=volume_id)
# Populate instance choices
instance_list = kwargs.get('initial', {}).get('instances', [])
instances = []
for instance in instance_list:
if instance.status in tables.ACTIVE_STATES and \
not any(instance.id == att["server_id"]
for att in volume.attachments):
instances.append((instance.id, '%s (%s)' % (instance.name,
instance.id)))
if instances:
instances.insert(0, ("", _("Select an instance")))
else:
instances = (("", _("No instances available")),)
self.fields['instance'].choices = instances
def handle(self, request, data):
instance_choices = dict(self.fields['instance'].choices)
instance_name = instance_choices.get(data['instance'],
_("Unknown instance (None)"))
# The name of the instance in the choices list has the ID appended to
# it, so let's slice that off...
instance_name = instance_name.rsplit(" (")[0]
try:
attach = api.nova.instance_volume_attach(request,
data['volume_id'],
data['instance'],
data.get('device', ''))
volume = cinder.volume_get(request, data['volume_id'])
if not volume.display_name:
volume_name = volume.id
else:
volume_name = volume.display_name
message = _('Attaching volume %(vol)s to instance '
'%(inst)s on %(dev)s.') % {"vol": volume_name,
"inst": instance_name,
"dev": attach.device}
messages.info(request, message)
return True
except Exception:
redirect = reverse("horizon:project:volumes:index")
exceptions.handle(request,
_('Unable to attach volume.'),
redirect=redirect)

View File

@ -1,40 +1,40 @@
# Copyright 2012 Nebula, Inc.
#
# 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-2017 Wind River Systems, Inc.
#
from django.utils.translation import ugettext_lazy as _
import horizon
class ServerGroups(horizon.Panel):
name = _("Server Groups")
slug = 'server_groups'
# Server groups are wrs-specific
permissions = ('openstack.services.compute',)
policy_rules = (("compute", "context_is_admin"),)
def allowed(self, context):
if context['request'].user.services_region == 'SystemController':
return False
else:
return super(ServerGroups, self).allowed(context)
def nav(self, context):
if context['request'].user.services_region == 'SystemController':
return False
else:
return True
# Copyright 2012 Nebula, Inc.
#
# 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.
#
from django.utils.translation import ugettext_lazy as _
import horizon
class ServerGroups(horizon.Panel):
name = _("Server Groups")
slug = 'server_groups'
# Server groups are wrs-specific
permissions = ('openstack.services.compute',)
policy_rules = (("compute", "context_is_admin"),)
def allowed(self, context):
if context['request'].user.services_region == 'SystemController':
return False
else:
return super(ServerGroups, self).allowed(context)
def nav(self, context):
if context['request'].user.services_region == 'SystemController':
return False
else:
return True

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2017 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
from django.core.urlresolvers import NoReverseMatch
@ -28,7 +28,6 @@ from horizon import exceptions
from horizon import tables
from openstack_dashboard import api
from openstack_dashboard.api import nova
from openstack_dashboard.dashboards.project.volumes.tables \
import get_attachment_name
from openstack_dashboard.usage import quotas

View File

@ -1,53 +1,53 @@
# Copyright 2012 Nebula, Inc.
#
# 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-2017 Wind River Systems, Inc.
#
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import tabs
from openstack_dashboard.api import nova
from starlingx_dashboard.api import nova as stx_nova
class OverviewTab(tabs.Tab):
name = _("Overview")
slug = "overview"
template_name = ("admin/server_groups/"
"_detail_overview.html")
def get_context_data(self, request):
server_group_id = self.tab_group.kwargs['server_group_id']
try:
server_group = stx_nova.server_group_get(request, server_group_id)
server_group.members_display = []
for member in server_group.members:
server_group.members_display.append(
dict(id=member, instance=nova.server_get(request, member)))
except Exception:
redirect = reverse('horizon:admin:server_groups:index')
exceptions.handle(self.request,
_('Unable to retrieve server group details.'),
redirect=redirect)
return {'server_group': server_group}
class ServerGroupDetailTabs(tabs.TabGroup):
slug = "server_group_details"
tabs = (OverviewTab,)
# Copyright 2012 Nebula, Inc.
#
# 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.
#
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import tabs
from openstack_dashboard.api import nova
from starlingx_dashboard.api import nova as stx_nova
class OverviewTab(tabs.Tab):
name = _("Overview")
slug = "overview"
template_name = ("admin/server_groups/"
"_detail_overview.html")
def get_context_data(self, request):
server_group_id = self.tab_group.kwargs['server_group_id']
try:
server_group = stx_nova.server_group_get(request, server_group_id)
server_group.members_display = []
for member in server_group.members:
server_group.members_display.append(
dict(id=member, instance=nova.server_get(request, member)))
except Exception:
redirect = reverse('horizon:admin:server_groups:index')
exceptions.handle(self.request,
_('Unable to retrieve server group details.'),
redirect=redirect)
return {'server_group': server_group}
class ServerGroupDetailTabs(tabs.TabGroup):
slug = "server_group_details"
tabs = (OverviewTab,)

View File

@ -1,32 +1,32 @@
# Copyright 2012 Nebula, Inc.
#
# 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-2017 Wind River Systems, Inc.
#
from django.conf.urls import url
from starlingx_dashboard.dashboards.admin.server_groups import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^create/$', views.CreateView.as_view(), name='create'),
url(r'^(?P<server_group_id>[^/]+)/attach/$',
views.EditAttachmentsView.as_view(),
name='attach'),
url(r'^(?P<server_group_id>[^/]+)/$',
views.DetailView.as_view(),
name='detail')
]
# Copyright 2012 Nebula, Inc.
#
# 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.
#
from django.conf.urls import url
from starlingx_dashboard.dashboards.admin.server_groups import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^create/$', views.CreateView.as_view(), name='create'),
url(r'^(?P<server_group_id>[^/]+)/attach/$',
views.EditAttachmentsView.as_view(),
name='attach'),
url(r'^(?P<server_group_id>[^/]+)/$',
views.DetailView.as_view(),
name='detail')
]

View File

@ -1,148 +1,148 @@
# Copyright 2012 Nebula, Inc.
#
# 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-2017 Wind River Systems, Inc.
#
"""
Views for managing server groups.
"""
from django.core.urlresolvers import reverse_lazy # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import forms
from horizon import tables
from horizon import tabs
from openstack_dashboard import api
from openstack_dashboard.usage import quotas
from starlingx_dashboard import api as stx_api
from starlingx_dashboard.dashboards.admin.server_groups \
import forms as admin_forms
from starlingx_dashboard.dashboards.admin.server_groups \
import tables as admin_tables
from starlingx_dashboard.dashboards.admin.server_groups \
import tabs as admin_tabs
# server groups don't currently support pagination
class IndexView(tables.DataTableView):
table_class = admin_tables.ServerGroupsTable
template_name = 'admin/server_groups/index.html'
page_title = _("Server Groups")
def get_data(self):
try:
server_groups = stx_api.nova.server_group_list(
self.request, all_projects=True)
except Exception:
server_groups = []
exceptions.handle(self.request,
_('Unable to retrieve server groups.'))
return server_groups
class DetailView(tabs.TabView):
tab_group_class = admin_tabs.ServerGroupDetailTabs
template_name = 'admin/server_groups/detail.html'
page_title = 'Server Group Details'
class CreateView(forms.ModalFormView):
form_class = admin_forms.CreateForm
template_name = 'admin/server_groups/create.html'
success_url = reverse_lazy("horizon:admin:server_groups:index")
def get_context_data(self, **kwargs):
context = super(CreateView, self).get_context_data(**kwargs)
try:
context['usages'] = quotas.tenant_limit_usages(self.request)
except Exception:
exceptions.handle(self.request)
return context
class EditAttachmentsView(tables.DataTableView, forms.ModalFormView):
table_class = admin_tables.AttachmentsTable
form_class = admin_forms.AttachForm
template_name = 'admin/server_groups/attach.html'
success_url = reverse_lazy("horizon:admin:server_groups:index")
def get_object(self):
if not hasattr(self, "_object"):
volume_id = self.kwargs['volume_id']
try:
self._object = api.cinder.volume_get(self.request, volume_id)
except Exception:
self._object = None
exceptions.handle(self.request,
_('Unable to retrieve volume information.'))
return self._object
def get_data(self):
try:
volumes = self.get_object()
attachments = [att for att in volumes.attachments if att]
except Exception:
attachments = []
exceptions.handle(self.request,
_('Unable to retrieve volume information.'))
return attachments
def get_initial(self):
try:
instances, has_more = api.nova.server_list(self.request)
except Exception:
instances = []
exceptions.handle(self.request,
_("Unable to retrieve attachment information."))
return {'volume': self.get_object(),
'instances': instances}
def get_form(self):
if not hasattr(self, "_form"):
form_class = self.get_form_class()
self._form = super(EditAttachmentsView, self).get_form(form_class)
return self._form
def get_context_data(self, **kwargs):
context = super(EditAttachmentsView, self).get_context_data(**kwargs)
context['form'] = self.get_form()
volume = self.get_object()
if volume and volume.status == 'available':
context['show_attach'] = True
else:
context['show_attach'] = False
context['volume'] = volume
if self.request.is_ajax():
context['hide'] = True
return context
def get(self, request, *args, **kwargs):
# Table action handling
handled = self.construct_tables()
if handled:
return handled
return self.render_to_response(self.get_context_data(**kwargs))
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.get(request, *args, **kwargs)
# Copyright 2012 Nebula, Inc.
#
# 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.
#
"""
Views for managing server groups.
"""
from django.core.urlresolvers import reverse_lazy # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import forms
from horizon import tables
from horizon import tabs
from openstack_dashboard import api
from openstack_dashboard.usage import quotas
from starlingx_dashboard import api as stx_api
from starlingx_dashboard.dashboards.admin.server_groups \
import forms as admin_forms
from starlingx_dashboard.dashboards.admin.server_groups \
import tables as admin_tables
from starlingx_dashboard.dashboards.admin.server_groups \
import tabs as admin_tabs
# server groups don't currently support pagination
class IndexView(tables.DataTableView):
table_class = admin_tables.ServerGroupsTable
template_name = 'admin/server_groups/index.html'
page_title = _("Server Groups")
def get_data(self):
try:
server_groups = stx_api.nova.server_group_list(
self.request, all_projects=True)
except Exception:
server_groups = []
exceptions.handle(self.request,
_('Unable to retrieve server groups.'))
return server_groups
class DetailView(tabs.TabView):
tab_group_class = admin_tabs.ServerGroupDetailTabs
template_name = 'admin/server_groups/detail.html'
page_title = 'Server Group Details'
class CreateView(forms.ModalFormView):
form_class = admin_forms.CreateForm
template_name = 'admin/server_groups/create.html'
success_url = reverse_lazy("horizon:admin:server_groups:index")
def get_context_data(self, **kwargs):
context = super(CreateView, self).get_context_data(**kwargs)
try:
context['usages'] = quotas.tenant_limit_usages(self.request)
except Exception:
exceptions.handle(self.request)
return context
class EditAttachmentsView(tables.DataTableView, forms.ModalFormView):
table_class = admin_tables.AttachmentsTable
form_class = admin_forms.AttachForm
template_name = 'admin/server_groups/attach.html'
success_url = reverse_lazy("horizon:admin:server_groups:index")
def get_object(self):
if not hasattr(self, "_object"):
volume_id = self.kwargs['volume_id']
try:
self._object = api.cinder.volume_get(self.request, volume_id)
except Exception:
self._object = None
exceptions.handle(self.request,
_('Unable to retrieve volume information.'))
return self._object
def get_data(self):
try:
volumes = self.get_object()
attachments = [att for att in volumes.attachments if att]
except Exception:
attachments = []
exceptions.handle(self.request,
_('Unable to retrieve volume information.'))
return attachments
def get_initial(self):
try:
instances, has_more = api.nova.server_list(self.request)
except Exception:
instances = []
exceptions.handle(self.request,
_("Unable to retrieve attachment information."))
return {'volume': self.get_object(),
'instances': instances}
def get_form(self):
if not hasattr(self, "_form"):
form_class = self.get_form_class()
self._form = super(EditAttachmentsView, self).get_form(form_class)
return self._form
def get_context_data(self, **kwargs):
context = super(EditAttachmentsView, self).get_context_data(**kwargs)
context['form'] = self.get_form()
volume = self.get_object()
if volume and volume.status == 'available':
context['show_attach'] = True
else:
context['show_attach'] = False
context['volume'] = volume
if self.request.is_ajax():
context['hide'] = True
return context
def get(self, request, *args, **kwargs):
# Table action handling
handled = self.construct_tables()
if handled:
return handled
return self.render_to_response(self.get_context_data(**kwargs))
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.get(request, *args, **kwargs)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2016 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -57,7 +57,7 @@ class ApplyPatch(tables.BatchAction):
result = stx_api.patch.patch_apply_req(request, obj_ids)
messages.success(request, result)
except Exception as ex:
messages.error(request, ex.message)
messages.error(request, str(ex))
class RemovePatch(tables.BatchAction):
@ -97,7 +97,7 @@ class RemovePatch(tables.BatchAction):
result = stx_api.patch.patch_remove_req(request, obj_ids)
messages.success(request, result)
except Exception as ex:
messages.error(request, ex.message)
messages.error(request, str(ex))
class DeletePatch(tables.BatchAction):
@ -131,7 +131,7 @@ class DeletePatch(tables.BatchAction):
result = stx_api.patch.patch_delete_req(request, obj_ids)
messages.success(request, result)
except Exception as ex:
messages.error(request, ex.message)
messages.error(request, str(ex))
class UpdatePatchRow(tables.Row):
@ -223,7 +223,8 @@ class CreateStrategy(tables.LinkAction):
def allowed(self, request, datum):
try:
# Only a single strategy (patch or upgrade) can exist at a time.
strategy = get_cached_strategy(request, stx_api.vim.STRATEGY_SW_PATCH,
strategy = get_cached_strategy(request,
stx_api.vim.STRATEGY_SW_PATCH,
self.table)
if not strategy:
strategy = get_cached_strategy(request,
@ -290,7 +291,7 @@ class DeleteStrategy(tables.Action):
messages.error(request, "Strategy delete failed")
except Exception as ex:
LOG.exception(ex)
messages.error(request, ex.message)
messages.error(request, str(ex))
class DeletePatchStrategy(DeleteStrategy):
@ -338,7 +339,7 @@ class ApplyStrategy(tables.Action):
messages.error(request, "Strategy apply failed")
except Exception as ex:
LOG.exception(ex)
messages.error(request, ex.message)
messages.error(request, str(ex))
class ApplyPatchStrategy(ApplyStrategy):
@ -387,7 +388,7 @@ class AbortStrategy(tables.Action):
messages.error(request, "Strategy abort failed")
except Exception as ex:
LOG.exception(ex)
messages.error(request, ex.message)
messages.error(request, str(ex))
class AbortPatchStrategy(AbortStrategy):
@ -442,7 +443,8 @@ class ApplyStage(tables.BatchAction):
for obj_id in obj_ids:
try:
stage_id = obj_id.split('-', 1)[1]
result = stx_api.vim.apply_strategy(request, self.strategy_name,
result = stx_api.vim.apply_strategy(request,
self.strategy_name,
stage_id)
if result is None:
messages.error(request, "Strategy stage %s apply failed" %
@ -453,7 +455,7 @@ class ApplyStage(tables.BatchAction):
stage_id)
except Exception as ex:
LOG.exception(ex)
messages.error(request, ex.message)
messages.error(request, str(ex))
class ApplyPatchStage(ApplyStage):
@ -503,7 +505,8 @@ class AbortStage(tables.BatchAction):
for obj_id in obj_ids:
try:
stage_id = obj_id.split('-', 1)[1]
result = stx_api.vim.abort_strategy(request, self.strategy_name,
result = stx_api.vim.abort_strategy(request,
self.strategy_name,
stage_id)
if result is None:
messages.error(request,
@ -514,7 +517,7 @@ class AbortStage(tables.BatchAction):
stage_id)
except Exception as ex:
LOG.exception(ex)
messages.error(request, ex.message)
messages.error(request, str(ex))
class AbortPatchStage(AbortStage):
@ -598,7 +601,10 @@ class UpdateStageRow(tables.Row):
def get_data(self, request, row_id):
phase = row_id.split('-', 1)[0]
stage_id = row_id.split('-', 1)[1]
stage = stx_api.vim.get_stage(request, self.strategy_name, phase, stage_id)
stage = stx_api.vim.get_stage(request,
self.strategy_name,
phase,
stage_id)
return stage

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2016 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -62,7 +62,8 @@ class PatchOrchestrationTab(tabs.TableTab):
strategy = None
try:
strategy = stx_api.vim.get_strategy(request, stx_api.vim.STRATEGY_SW_PATCH)
strategy = stx_api.vim.get_strategy(request,
stx_api.vim.STRATEGY_SW_PATCH)
except Exception as ex:
LOG.exception(ex)
exceptions.handle(request,
@ -75,7 +76,8 @@ class PatchOrchestrationTab(tabs.TableTab):
request = self.request
stages = []
try:
stages = stx_api.vim.get_stages(request, stx_api.vim.STRATEGY_SW_PATCH)
stages = stx_api.vim.get_stages(request,
stx_api.vim.STRATEGY_SW_PATCH)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve stages list.'))
@ -100,8 +102,8 @@ class UpgradeOrchestrationTab(tabs.TableTab):
strategy = None
try:
strategy = stx_api.vim.get_strategy(request,
stx_api.vim.STRATEGY_SW_UPGRADE)
strategy = stx_api.vim.get_strategy(
request, stx_api.vim.STRATEGY_SW_UPGRADE)
except Exception as ex:
LOG.exception(ex)
exceptions.handle(request,
@ -114,7 +116,8 @@ class UpgradeOrchestrationTab(tabs.TableTab):
request = self.request
stages = []
try:
stages = stx_api.vim.get_stages(request, stx_api.vim.STRATEGY_SW_UPGRADE)
stages = stx_api.vim.get_stages(request,
stx_api.vim.STRATEGY_SW_UPGRADE)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve stages list.'))

View File

@ -17,8 +17,6 @@ from horizon import exceptions
from horizon import forms
from horizon import messages
from openstack_dashboard import api
from starlingx_dashboard import api as stx_api
LOG = logging.getLogger(__name__)
@ -904,9 +902,8 @@ class UpdateiStoragePools(forms.SelfHandlingForm):
LOG.debug(data)
if send_to_sysinv:
my_storage = stx_api.sysinv.storpool_update(request,
storage_config_uuid,
**data)
my_storage = stx_api.sysinv.storpool_update(
request, storage_config_uuid, **data)
if my_storage:
msg = _(

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2017 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -11,8 +11,6 @@ from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import tabs
from openstack_dashboard import api
from starlingx_dashboard import api as stx_api
from starlingx_dashboard.dashboards.admin.system_config.address_pools import \
tables as address_pool_tables

View File

@ -15,8 +15,6 @@ from horizon import forms
from horizon import tables
from horizon import tabs
from openstack_dashboard import api
from starlingx_dashboard import api as stx_api
from starlingx_dashboard.dashboards.admin.system_config.forms \
import CreateSDNController
@ -432,8 +430,8 @@ class UpdateSDNControllerView(forms.ModalFormView):
if not hasattr(self, "_object"):
controller_uuid = self.kwargs['uuid']
try:
self._object = stx_api.sysinv.sdn_controller_get(self.request,
controller_uuid)
self._object = stx_api.sysinv.sdn_controller_get(
self.request, controller_uuid)
except Exception:
redirect = self.success_url
msg = _('Unable to retrieve SDN controller details.')

View File

@ -30,4 +30,5 @@ class DCAdmin(horizon.Dashboard):
return super(DCAdmin, self).allowed(context)
horizon.register(DCAdmin)

View File

@ -115,7 +115,7 @@ class DeleteCloudPatchStrategy(tables.Action):
messages.error(request, "Strategy delete failed")
except Exception as ex:
LOG.exception(ex)
messages.error(request, ex.message)
messages.error(request, str(ex))
class ApplyCloudPatchStrategy(tables.Action):
@ -151,7 +151,7 @@ class ApplyCloudPatchStrategy(tables.Action):
messages.error(request, "Strategy apply failed")
except Exception as ex:
LOG.exception(ex)
messages.error(request, ex.message)
messages.error(request, str(ex))
class AbortCloudPatchStrategy(tables.Action):
@ -190,7 +190,7 @@ class AbortCloudPatchStrategy(tables.Action):
messages.error(request, "Strategy abort failed")
except Exception as ex:
LOG.exception(ex)
messages.error(request, ex.message)
messages.error(request, str(ex))
STEP_STATE_CHOICES = (

View File

@ -1,180 +1,180 @@
# 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-2017 Wind River Systems, Inc.
#
# Copyright 2012 Nebula, Inc.
# All rights reserved.
"""
Views for managing volumes.
"""
from django.conf import settings
from django.core.urlresolvers import reverse
from django.forms import ValidationError
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import forms
from horizon import messages
from openstack_dashboard import api
from openstack_dashboard.api import cinder
from openstack_dashboard.dashboards.project.instances import tables
from starlingx_dashboard.api import nova as stx_nova
class CreateForm(forms.SelfHandlingForm):
name = forms.CharField(max_length="255", label=_("Server Group Name"))
policy = forms.ChoiceField(label=_("Policy"),
required=False,
widget=forms.Select(
attrs={
'class': 'switchable',
'data-slug': 'policy_ht'}))
is_best_effort = forms.BooleanField(label=_("Best Effort"), required=False)
group_size = forms.IntegerField(
min_value=1,
label=_("Max Group Size (Instances)"),
required=False,
widget=forms.TextInput(
attrs={
'class': 'switchable switched',
'data-switch-on': 'policy_ht',
'data-policy_ht-anti-affinity': 'Max Group Size (Instances)',
'data-policy_ht-affinity': 'Max Group Size (Instances)'}))
group_size_ht = forms.IntegerField(
label=_("Max Group Size (Instances)"),
required=False,
widget=forms.TextInput(
attrs={
'readonly': 'readonly',
'class': 'switchable switched',
'data-switch-on': 'policy_ht',
'data-policy_ht-affinity-hyperthread':
'Max Group Size (Instances)'}))
def __init__(self, request, *args, **kwargs):
super(CreateForm, self).__init__(request, *args, **kwargs)
self.fields['policy'].choices = [("anti-affinity", "anti-affinity"),
("affinity", "affinity")]
def handle(self, request, data):
try:
project_id = self.request.user.tenant_id
policy = data['policy']
policies = []
if policy:
policies.append(policy)
metadata = {}
if data['is_best_effort']:
metadata['wrs-sg:best_effort'] = "true"
group_size = data['group_size']
group_size_ht = data['group_size_ht']
if group_size:
metadata['wrs-sg:group_size'] = str(group_size)
elif group_size_ht:
metadata['wrs-sg:group_size'] = str(group_size_ht)
kwargs = {'name': data['name'],
'policies': policies,
'metadata': metadata,
'project_id': project_id}
server_group = stx_nova.server_group_create(request, **kwargs)
return server_group
except ValidationError as e:
self.api_error(e.messages[0])
return False
except Exception:
exceptions.handle(request, ignore=True)
self.api_error(_("Unable to create server group."))
return False
class AttachForm(forms.SelfHandlingForm):
instance = forms.ChoiceField(label=_("Attach to Server Group"),
help_text=_("Select an server group to "
"attach to."))
device = forms.CharField(label=_("Device Name"))
def __init__(self, *args, **kwargs):
super(AttachForm, self).__init__(*args, **kwargs)
# Hide the device field if the hypervisor doesn't support it.
hypervisor_features = getattr(settings,
"OPENSTACK_HYPERVISOR_FEATURES",
{})
can_set_mount_point = hypervisor_features.get("can_set_mount_point",
True)
if not can_set_mount_point:
self.fields['device'].widget = forms.widgets.HiddenInput()
self.fields['device'].required = False
# populate volume_id
volume = kwargs.get('initial', {}).get("volume", None)
if volume:
volume_id = volume.id
else:
volume_id = None
self.fields['volume_id'] = forms.CharField(widget=forms.HiddenInput(),
initial=volume_id)
# Populate instance choices
instance_list = kwargs.get('initial', {}).get('instances', [])
instances = []
for instance in instance_list:
if instance.status in tables.ACTIVE_STATES and \
not any(instance.id == att["server_id"]
for att in volume.attachments):
instances.append((instance.id, '%s (%s)' % (instance.name,
instance.id)))
if instances:
instances.insert(0, ("", _("Select an instance")))
else:
instances = (("", _("No instances available")),)
self.fields['instance'].choices = instances
def handle(self, request, data):
instance_choices = dict(self.fields['instance'].choices)
instance_name = instance_choices.get(data['instance'],
_("Unknown instance (None)"))
# The name of the instance in the choices list has the ID appended to
# it, so let's slice that off...
instance_name = instance_name.rsplit(" (")[0]
try:
attach = api.nova.instance_volume_attach(request,
data['volume_id'],
data['instance'],
data.get('device', ''))
volume = cinder.volume_get(request, data['volume_id'])
if not volume.display_name:
volume_name = volume.id
else:
volume_name = volume.display_name
message = _('Attaching volume %(vol)s to instance '
'%(inst)s on %(dev)s.') % {"vol": volume_name,
"inst": instance_name,
"dev": attach.device}
messages.info(request, message)
return True
except Exception:
redirect = reverse("horizon:project:volumes:index")
exceptions.handle(request,
_('Unable to attach volume.'),
redirect=redirect)
# 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.
#
# Copyright 2012 Nebula, Inc.
# All rights reserved.
"""
Views for managing volumes.
"""
from django.conf import settings
from django.core.urlresolvers import reverse
from django.forms import ValidationError
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import forms
from horizon import messages
from openstack_dashboard import api
from openstack_dashboard.api import cinder
from openstack_dashboard.dashboards.project.instances import tables
from starlingx_dashboard.api import nova as stx_nova
class CreateForm(forms.SelfHandlingForm):
name = forms.CharField(max_length="255", label=_("Server Group Name"))
policy = forms.ChoiceField(label=_("Policy"),
required=False,
widget=forms.Select(
attrs={
'class': 'switchable',
'data-slug': 'policy_ht'}))
is_best_effort = forms.BooleanField(label=_("Best Effort"), required=False)
group_size = forms.IntegerField(
min_value=1,
label=_("Max Group Size (Instances)"),
required=False,
widget=forms.TextInput(
attrs={
'class': 'switchable switched',
'data-switch-on': 'policy_ht',
'data-policy_ht-anti-affinity': 'Max Group Size (Instances)',
'data-policy_ht-affinity': 'Max Group Size (Instances)'}))
group_size_ht = forms.IntegerField(
label=_("Max Group Size (Instances)"),
required=False,
widget=forms.TextInput(
attrs={
'readonly': 'readonly',
'class': 'switchable switched',
'data-switch-on': 'policy_ht',
'data-policy_ht-affinity-hyperthread':
'Max Group Size (Instances)'}))
def __init__(self, request, *args, **kwargs):
super(CreateForm, self).__init__(request, *args, **kwargs)
self.fields['policy'].choices = [("anti-affinity", "anti-affinity"),
("affinity", "affinity")]
def handle(self, request, data):
try:
project_id = self.request.user.tenant_id
policy = data['policy']
policies = []
if policy:
policies.append(policy)
metadata = {}
if data['is_best_effort']:
metadata['wrs-sg:best_effort'] = "true"
group_size = data['group_size']
group_size_ht = data['group_size_ht']
if group_size:
metadata['wrs-sg:group_size'] = str(group_size)
elif group_size_ht:
metadata['wrs-sg:group_size'] = str(group_size_ht)
kwargs = {'name': data['name'],
'policies': policies,
'metadata': metadata,
'project_id': project_id}
server_group = stx_nova.server_group_create(request, **kwargs)
return server_group
except ValidationError as e:
self.api_error(e.messages[0])
return False
except Exception:
exceptions.handle(request, ignore=True)
self.api_error(_("Unable to create server group."))
return False
class AttachForm(forms.SelfHandlingForm):
instance = forms.ChoiceField(label=_("Attach to Server Group"),
help_text=_("Select an server group to "
"attach to."))
device = forms.CharField(label=_("Device Name"))
def __init__(self, *args, **kwargs):
super(AttachForm, self).__init__(*args, **kwargs)
# Hide the device field if the hypervisor doesn't support it.
hypervisor_features = getattr(settings,
"OPENSTACK_HYPERVISOR_FEATURES",
{})
can_set_mount_point = hypervisor_features.get("can_set_mount_point",
True)
if not can_set_mount_point:
self.fields['device'].widget = forms.widgets.HiddenInput()
self.fields['device'].required = False
# populate volume_id
volume = kwargs.get('initial', {}).get("volume", None)
if volume:
volume_id = volume.id
else:
volume_id = None
self.fields['volume_id'] = forms.CharField(widget=forms.HiddenInput(),
initial=volume_id)
# Populate instance choices
instance_list = kwargs.get('initial', {}).get('instances', [])
instances = []
for instance in instance_list:
if instance.status in tables.ACTIVE_STATES and \
not any(instance.id == att["server_id"]
for att in volume.attachments):
instances.append((instance.id, '%s (%s)' % (instance.name,
instance.id)))
if instances:
instances.insert(0, ("", _("Select an instance")))
else:
instances = (("", _("No instances available")),)
self.fields['instance'].choices = instances
def handle(self, request, data):
instance_choices = dict(self.fields['instance'].choices)
instance_name = instance_choices.get(data['instance'],
_("Unknown instance (None)"))
# The name of the instance in the choices list has the ID appended to
# it, so let's slice that off...
instance_name = instance_name.rsplit(" (")[0]
try:
attach = api.nova.instance_volume_attach(request,
data['volume_id'],
data['instance'],
data.get('device', ''))
volume = cinder.volume_get(request, data['volume_id'])
if not volume.display_name:
volume_name = volume.id
else:
volume_name = volume.display_name
message = _('Attaching volume %(vol)s to instance '
'%(inst)s on %(dev)s.') % {"vol": volume_name,
"inst": instance_name,
"dev": attach.device}
messages.info(request, message)
return True
except Exception:
redirect = reverse("horizon:project:volumes:index")
exceptions.handle(request,
_('Unable to attach volume.'),
redirect=redirect)

View File

@ -1,45 +1,45 @@
# Copyright 2012 Nebula, Inc.
#
# 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-2017 Wind River Systems, Inc.
#
from django.utils.translation import ugettext_lazy as _ # noqa
import horizon
from openstack_dashboard.api import base
from openstack_dashboard.dashboards.project import dashboard
class ServerGroups(horizon.Panel):
name = _("Server Groups")
slug = 'server_groups'
# Server groups are wrs-specific
permissions = ('openstack.services.platform',)
def allowed(self, context):
if not base.is_service_enabled(context['request'], 'compute'):
return False
else:
return super(ServerGroups, self).allowed(context)
def nav(self, context):
if not base.is_service_enabled(context['request'], 'compute'):
return False
else:
return True
dashboard.Project.register(ServerGroups)
# Copyright 2012 Nebula, Inc.
#
# 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.
#
from django.utils.translation import ugettext_lazy as _ # noqa
import horizon
from openstack_dashboard.api import base
from openstack_dashboard.dashboards.project import dashboard
class ServerGroups(horizon.Panel):
name = _("Server Groups")
slug = 'server_groups'
# Server groups are wrs-specific
permissions = ('openstack.services.platform',)
def allowed(self, context):
if not base.is_service_enabled(context['request'], 'compute'):
return False
else:
return super(ServerGroups, self).allowed(context)
def nav(self, context):
if not base.is_service_enabled(context['request'], 'compute'):
return False
else:
return True
dashboard.Project.register(ServerGroups)

View File

@ -1,287 +1,286 @@
# Copyright 2012 Nebula, Inc.
#
# 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-2017 Wind River Systems, Inc.
#
from django.core.urlresolvers import NoReverseMatch
from django.core.urlresolvers import reverse
from django.utils import html
from django.utils import safestring
from django.utils.translation import string_concat # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
from django.utils.translation import ungettext_lazy
from horizon import exceptions
from horizon import tables
from openstack_dashboard import api
from openstack_dashboard.api import nova
from openstack_dashboard.dashboards.project.volumes.tables \
import get_attachment_name
from openstack_dashboard.usage import quotas
from starlingx_dashboard.api import nova as stx_nova
DELETABLE_STATES = ("available", "error")
class DeleteServerGroup(tables.DeleteAction):
data_type_singular = _("Server Group")
data_type_plural = _("Server Groups")
action_past = _("Scheduled deletion of")
@staticmethod
def action_present(count):
return ungettext_lazy(
"Delete Server Group",
"Delete Server Groups",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
"Deleted Server Group",
"Deleted Server Groups",
count
)
def delete(self, request, obj_id):
obj = self.table.get_object_by_id(obj_id)
name = self.table.get_object_display(obj)
try:
stx_nova.server_group_delete(request, obj_id)
except Exception:
msg = _('Unable to delete group "%s" because it is not empty. '
'Either delete the member '
'instances or remove them from the group.')
exceptions.check_message(["group", "not", "empty."], msg % name)
raise
# maybe do a precheck to see if the group is empty first?
def allowed(self, request, server_group=None):
return True
class CreateServerGroup(tables.LinkAction):
name = "create"
verbose_name = _("Create Server Group")
url = "horizon:project:server_groups:create"
classes = ("ajax-modal", "btn-create")
icon = "plus"
def allowed(self, request, volume=None):
usages = quotas.tenant_quota_usages(request)
if usages['server_groups']['available'] <= 0:
if "disabled" not in self.classes:
self.classes = [c for c in self.classes] + ['disabled']
self.verbose_name = string_concat(self.verbose_name, ' ',
_("(Quota exceeded)"))
else:
self.verbose_name = _("Create Server Group")
classes = [c for c in self.classes if c != "disabled"]
self.classes = classes
return True
class EditAttachments(tables.LinkAction):
name = "attachments"
verbose_name = _("Edit Attachments")
url = "horizon:project:server_groups:attach"
classes = ("ajax-modal", "btn-edit")
def allowed(self, request, server_group=None):
return True # volume.status in ("available", "in-use")
class CreateSnapshot(tables.LinkAction):
name = "snapshots"
verbose_name = _("Create Snapshot")
url = "horizon:project:server_groups:create_snapshot"
classes = ("ajax-modal", "btn-camera")
def allowed(self, request, server_group=None):
return True # server_group.status == "available"
class UpdateRow(tables.Row):
ajax = True
def get_data(self, request, server_group_id):
server_group = stx_nova.server_group_get(request, server_group_id)
if not server_group.name:
server_group.name = server_group_id
return server_group
def get_policies(server_group):
policies = ', '.join(server_group.policies)
return policies
def get_metadata(server_group):
metadata_items = ['{}:{}'.format(x, y) for x, y in
server_group.metadata.items()]
metadata = ', '.join(metadata_items)
return metadata
def get_member_name(request, server_id):
try:
server = api.nova.server_get(request, server_id)
name = server.name
except Exception:
name = None
exceptions.handle(request, _("Unable to retrieve "
"member information."))
# try and get a URL
try:
url = reverse("horizon:project:instances:detail", args=(server_id,))
instance = '<a href="%s">%s</a>' % (url, html.escape(name))
except NoReverseMatch:
instance = name
return instance
class MemberColumn(tables.Column):
"""Customized column class
Customized column class that does complex processing on the instances
in a server group. This was substantially copied
from the volume equivalent.
"""
def get_raw_data(self, server_group):
request = self.table.request
link = _('%(name)s (%(id)s)')
members = []
for member in server_group.members:
member_id = member
name = get_member_name(request, member)
vals = {"name": name, "id": member_id}
members.append(link % vals)
return safestring.mark_safe(", ".join(members))
def get_server_group_type(server_group):
return server_group.volume_type if server_group.volume_type != "None" \
else None
class ServerGroupsFilterAction(tables.FilterAction):
def filter(self, table, server_groups, filter_string):
"""Naive case-insensitive search."""
q = filter_string.lower()
return [group for group in server_groups
if q in group.display_name.lower()]
class ServerGroupsTable(tables.DataTable):
name = tables.Column("name",
verbose_name=_("Group Name"),
link="horizon:project:server_groups:detail")
policies = tables.Column(get_policies,
verbose_name=_("Policies"))
members = MemberColumn("members",
verbose_name=_("Members"))
metadata = tables.Column(get_metadata,
verbose_name=_("Metadata"))
class Meta(object):
name = "server_groups"
verbose_name = _("Server Groups")
row_class = UpdateRow
table_actions = (
CreateServerGroup, DeleteServerGroup, ServerGroupsFilterAction)
row_actions = (DeleteServerGroup,)
def get_object_display(self, obj):
return obj.name
class DetachServerGroup(tables.BatchAction):
name = "detach"
action_present = _("Detach")
action_past = _("Detaching") # This action is asynchronous.
data_type_singular = _("Server Group")
data_type_plural = _("Server Groups")
classes = ('btn-danger', 'btn-detach')
@staticmethod
def action_present(count):
return ungettext_lazy(
"Server Group",
"Server Groups",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
"Deleted Group",
"Deleted Groups",
count
)
def action(self, request, obj_id):
attachment = self.table.get_object_by_id(obj_id)
api.nova.instance_server_group_detach(
request,
attachment.get('server_id', None),
obj_id)
def get_success_url(self, request):
return reverse('horizon:project:server_groups:index')
class AttachedInstanceColumn(tables.Column):
"""Customized column class
Customized column class that does complex processing on the attachments
for a server group.
"""
def get_raw_data(self, attachment):
request = self.table.request
return safestring.mark_safe(get_attachment_name(request, attachment))
class AttachmentsTable(tables.DataTable):
instance = AttachedInstanceColumn(get_member_name,
verbose_name=_("Instance"))
device = tables.Column("device",
verbose_name=_("Device"))
def get_object_id(self, obj):
return obj['id']
def get_object_display(self, attachment):
instance_name = get_attachment_name(self.request, attachment)
vals = {"dev": attachment['device'],
"instance_name": html.strip_tags(instance_name)}
return _("%(dev)s on instance %(instance_name)s") % vals
def get_object_by_id(self, obj_id):
for obj in self.data:
if self.get_object_id(obj) == obj_id:
return obj
raise ValueError('No match found for the id "%s".' % obj_id)
class Meta(object):
name = "attachments"
verbose_name = _("Attachments")
table_actions = (DetachServerGroup,)
row_actions = (DetachServerGroup,)
# Copyright 2012 Nebula, Inc.
#
# 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.
#
from django.core.urlresolvers import NoReverseMatch
from django.core.urlresolvers import reverse
from django.utils import html
from django.utils import safestring
from django.utils.translation import string_concat # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
from django.utils.translation import ungettext_lazy
from horizon import exceptions
from horizon import tables
from openstack_dashboard import api
from openstack_dashboard.dashboards.project.volumes.tables \
import get_attachment_name
from openstack_dashboard.usage import quotas
from starlingx_dashboard.api import nova as stx_nova
DELETABLE_STATES = ("available", "error")
class DeleteServerGroup(tables.DeleteAction):
data_type_singular = _("Server Group")
data_type_plural = _("Server Groups")
action_past = _("Scheduled deletion of")
@staticmethod
def action_present(count):
return ungettext_lazy(
"Delete Server Group",
"Delete Server Groups",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
"Deleted Server Group",
"Deleted Server Groups",
count
)
def delete(self, request, obj_id):
obj = self.table.get_object_by_id(obj_id)
name = self.table.get_object_display(obj)
try:
stx_nova.server_group_delete(request, obj_id)
except Exception:
msg = _('Unable to delete group "%s" because it is not empty. '
'Either delete the member '
'instances or remove them from the group.')
exceptions.check_message(["group", "not", "empty."], msg % name)
raise
# maybe do a precheck to see if the group is empty first?
def allowed(self, request, server_group=None):
return True
class CreateServerGroup(tables.LinkAction):
name = "create"
verbose_name = _("Create Server Group")
url = "horizon:project:server_groups:create"
classes = ("ajax-modal", "btn-create")
icon = "plus"
def allowed(self, request, volume=None):
usages = quotas.tenant_quota_usages(request)
if usages['server_groups']['available'] <= 0:
if "disabled" not in self.classes:
self.classes = [c for c in self.classes] + ['disabled']
self.verbose_name = string_concat(self.verbose_name, ' ',
_("(Quota exceeded)"))
else:
self.verbose_name = _("Create Server Group")
classes = [c for c in self.classes if c != "disabled"]
self.classes = classes
return True
class EditAttachments(tables.LinkAction):
name = "attachments"
verbose_name = _("Edit Attachments")
url = "horizon:project:server_groups:attach"
classes = ("ajax-modal", "btn-edit")
def allowed(self, request, server_group=None):
return True # volume.status in ("available", "in-use")
class CreateSnapshot(tables.LinkAction):
name = "snapshots"
verbose_name = _("Create Snapshot")
url = "horizon:project:server_groups:create_snapshot"
classes = ("ajax-modal", "btn-camera")
def allowed(self, request, server_group=None):
return True # server_group.status == "available"
class UpdateRow(tables.Row):
ajax = True
def get_data(self, request, server_group_id):
server_group = stx_nova.server_group_get(request, server_group_id)
if not server_group.name:
server_group.name = server_group_id
return server_group
def get_policies(server_group):
policies = ', '.join(server_group.policies)
return policies
def get_metadata(server_group):
metadata_items = ['{}:{}'.format(x, y) for x, y in
server_group.metadata.items()]
metadata = ', '.join(metadata_items)
return metadata
def get_member_name(request, server_id):
try:
server = api.nova.server_get(request, server_id)
name = server.name
except Exception:
name = None
exceptions.handle(request, _("Unable to retrieve "
"member information."))
# try and get a URL
try:
url = reverse("horizon:project:instances:detail", args=(server_id,))
instance = '<a href="%s">%s</a>' % (url, html.escape(name))
except NoReverseMatch:
instance = name
return instance
class MemberColumn(tables.Column):
"""Customized column class
Customized column class that does complex processing on the instances
in a server group. This was substantially copied
from the volume equivalent.
"""
def get_raw_data(self, server_group):
request = self.table.request
link = _('%(name)s (%(id)s)')
members = []
for member in server_group.members:
member_id = member
name = get_member_name(request, member)
vals = {"name": name, "id": member_id}
members.append(link % vals)
return safestring.mark_safe(", ".join(members))
def get_server_group_type(server_group):
return server_group.volume_type if server_group.volume_type != "None" \
else None
class ServerGroupsFilterAction(tables.FilterAction):
def filter(self, table, server_groups, filter_string):
"""Naive case-insensitive search."""
q = filter_string.lower()
return [group for group in server_groups
if q in group.display_name.lower()]
class ServerGroupsTable(tables.DataTable):
name = tables.Column("name",
verbose_name=_("Group Name"),
link="horizon:project:server_groups:detail")
policies = tables.Column(get_policies,
verbose_name=_("Policies"))
members = MemberColumn("members",
verbose_name=_("Members"))
metadata = tables.Column(get_metadata,
verbose_name=_("Metadata"))
class Meta(object):
name = "server_groups"
verbose_name = _("Server Groups")
row_class = UpdateRow
table_actions = (
CreateServerGroup, DeleteServerGroup, ServerGroupsFilterAction)
row_actions = (DeleteServerGroup,)
def get_object_display(self, obj):
return obj.name
class DetachServerGroup(tables.BatchAction):
name = "detach"
action_present = _("Detach")
action_past = _("Detaching") # This action is asynchronous.
data_type_singular = _("Server Group")
data_type_plural = _("Server Groups")
classes = ('btn-danger', 'btn-detach')
@staticmethod
def action_present(count):
return ungettext_lazy(
"Server Group",
"Server Groups",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
"Deleted Group",
"Deleted Groups",
count
)
def action(self, request, obj_id):
attachment = self.table.get_object_by_id(obj_id)
api.nova.instance_server_group_detach(
request,
attachment.get('server_id', None),
obj_id)
def get_success_url(self, request):
return reverse('horizon:project:server_groups:index')
class AttachedInstanceColumn(tables.Column):
"""Customized column class
Customized column class that does complex processing on the attachments
for a server group.
"""
def get_raw_data(self, attachment):
request = self.table.request
return safestring.mark_safe(get_attachment_name(request, attachment))
class AttachmentsTable(tables.DataTable):
instance = AttachedInstanceColumn(get_member_name,
verbose_name=_("Instance"))
device = tables.Column("device",
verbose_name=_("Device"))
def get_object_id(self, obj):
return obj['id']
def get_object_display(self, attachment):
instance_name = get_attachment_name(self.request, attachment)
vals = {"dev": attachment['device'],
"instance_name": html.strip_tags(instance_name)}
return _("%(dev)s on instance %(instance_name)s") % vals
def get_object_by_id(self, obj_id):
for obj in self.data:
if self.get_object_id(obj) == obj_id:
return obj
raise ValueError('No match found for the id "%s".' % obj_id)
class Meta(object):
name = "attachments"
verbose_name = _("Attachments")
table_actions = (DetachServerGroup,)
row_actions = (DetachServerGroup,)

View File

@ -1,53 +1,53 @@
# Copyright 2012 Nebula, Inc.
#
# 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-2017 Wind River Systems, Inc.
#
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import tabs
from openstack_dashboard.api import nova
from starlingx_dashboard.api import nova as stx_nova
class OverviewTab(tabs.Tab):
name = _("Overview")
slug = "overview"
template_name = ("project/server_groups/"
"_detail_overview.html")
def get_context_data(self, request):
server_group_id = self.tab_group.kwargs['server_group_id']
try:
server_group = stx_nova.server_group_get(request, server_group_id)
server_group.members_display = []
for member in server_group.members:
server_group.members_display.append(
dict(id=member, instance=nova.server_get(request, member)))
except Exception:
redirect = reverse('horizon:project:server_groups:index')
exceptions.handle(self.request,
_('Unable to retrieve server group details.'),
redirect=redirect)
return {'server_group': server_group}
class ServerGroupDetailTabs(tabs.TabGroup):
slug = "server_group_details"
tabs = (OverviewTab,)
# Copyright 2012 Nebula, Inc.
#
# 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.
#
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import tabs
from openstack_dashboard.api import nova
from starlingx_dashboard.api import nova as stx_nova
class OverviewTab(tabs.Tab):
name = _("Overview")
slug = "overview"
template_name = ("project/server_groups/"
"_detail_overview.html")
def get_context_data(self, request):
server_group_id = self.tab_group.kwargs['server_group_id']
try:
server_group = stx_nova.server_group_get(request, server_group_id)
server_group.members_display = []
for member in server_group.members:
server_group.members_display.append(
dict(id=member, instance=nova.server_get(request, member)))
except Exception:
redirect = reverse('horizon:project:server_groups:index')
exceptions.handle(self.request,
_('Unable to retrieve server group details.'),
redirect=redirect)
return {'server_group': server_group}
class ServerGroupDetailTabs(tabs.TabGroup):
slug = "server_group_details"
tabs = (OverviewTab,)

View File

@ -1,32 +1,32 @@
# Copyright 2012 Nebula, Inc.
#
# 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-2017 Wind River Systems, Inc.
#
from django.conf.urls import url
from starlingx_dashboard.dashboards.project.server_groups import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^create/$', views.CreateView.as_view(), name='create'),
url(r'^(?P<server_group_id>[^/]+)/attach/$',
views.EditAttachmentsView.as_view(),
name='attach'),
url(r'^(?P<server_group_id>[^/]+)/$',
views.DetailView.as_view(),
name='detail'),
]
# Copyright 2012 Nebula, Inc.
#
# 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.
#
from django.conf.urls import url
from starlingx_dashboard.dashboards.project.server_groups import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^create/$', views.CreateView.as_view(), name='create'),
url(r'^(?P<server_group_id>[^/]+)/attach/$',
views.EditAttachmentsView.as_view(),
name='attach'),
url(r'^(?P<server_group_id>[^/]+)/$',
views.DetailView.as_view(),
name='detail'),
]

View File

@ -1,148 +1,148 @@
# Copyright 2012 Nebula, Inc.
#
# 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-2017 Wind River Systems, Inc.
#
"""
Views for managing server groups.
"""
from django.core.urlresolvers import reverse_lazy # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import forms
from horizon import tables
from horizon import tabs
from openstack_dashboard import api
from openstack_dashboard.usage import quotas
from starlingx_dashboard import api as stx_api
from starlingx_dashboard.dashboards.project.server_groups \
import forms as project_forms
from starlingx_dashboard.dashboards.project.server_groups \
import tables as project_tables
from starlingx_dashboard.dashboards.project.server_groups \
import tabs as project_tabs
# server groups don't currently support pagination
class IndexView(tables.DataTableView):
table_class = project_tables.ServerGroupsTable
template_name = 'project/server_groups/index.html'
page_title = _("Server Groups")
def get_data(self):
try:
server_groups = stx_api.nova.server_group_list(
self.request)
except Exception:
server_groups = []
exceptions.handle(self.request,
_('Unable to retrieve server groups.'))
return server_groups
class DetailView(tabs.TabView):
tab_group_class = project_tabs.ServerGroupDetailTabs
template_name = 'project/server_groups/detail.html'
page_title = 'Server Group Details'
class CreateView(forms.ModalFormView):
form_class = project_forms.CreateForm
template_name = 'project/server_groups/create.html'
success_url = reverse_lazy("horizon:project:server_groups:index")
def get_context_data(self, **kwargs):
context = super(CreateView, self).get_context_data(**kwargs)
try:
context['usages'] = quotas.tenant_limit_usages(self.request)
except Exception:
exceptions.handle(self.request)
return context
class EditAttachmentsView(tables.DataTableView, forms.ModalFormView):
table_class = project_tables.AttachmentsTable
form_class = project_forms.AttachForm
template_name = 'project/server_groups/attach.html'
success_url = reverse_lazy("horizon:project:server_groups:index")
def get_object(self):
if not hasattr(self, "_object"):
volume_id = self.kwargs['volume_id']
try:
self._object = api.cinder.volume_get(self.request, volume_id)
except Exception:
self._object = None
exceptions.handle(self.request,
_('Unable to retrieve volume information.'))
return self._object
def get_data(self):
try:
volumes = self.get_object()
attachments = [att for att in volumes.attachments if att]
except Exception:
attachments = []
exceptions.handle(self.request,
_('Unable to retrieve volume information.'))
return attachments
def get_initial(self):
try:
instances, has_more = api.nova.server_list(self.request)
except Exception:
instances = []
exceptions.handle(self.request,
_("Unable to retrieve attachment information."))
return {'volume': self.get_object(),
'instances': instances}
def get_form(self):
if not hasattr(self, "_form"):
form_class = self.get_form_class()
self._form = super(EditAttachmentsView, self).get_form(form_class)
return self._form
def get_context_data(self, **kwargs):
context = super(EditAttachmentsView, self).get_context_data(**kwargs)
context['form'] = self.get_form()
volume = self.get_object()
if volume and volume.status == 'available':
context['show_attach'] = True
else:
context['show_attach'] = False
context['volume'] = volume
if self.request.is_ajax():
context['hide'] = True
return context
def get(self, request, *args, **kwargs):
# Table action handling
handled = self.construct_tables()
if handled:
return handled
return self.render_to_response(self.get_context_data(**kwargs))
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.get(request, *args, **kwargs)
# Copyright 2012 Nebula, Inc.
#
# 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.
#
"""
Views for managing server groups.
"""
from django.core.urlresolvers import reverse_lazy # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import forms
from horizon import tables
from horizon import tabs
from openstack_dashboard import api
from openstack_dashboard.usage import quotas
from starlingx_dashboard import api as stx_api
from starlingx_dashboard.dashboards.project.server_groups \
import forms as project_forms
from starlingx_dashboard.dashboards.project.server_groups \
import tables as project_tables
from starlingx_dashboard.dashboards.project.server_groups \
import tabs as project_tabs
# server groups don't currently support pagination
class IndexView(tables.DataTableView):
table_class = project_tables.ServerGroupsTable
template_name = 'project/server_groups/index.html'
page_title = _("Server Groups")
def get_data(self):
try:
server_groups = stx_api.nova.server_group_list(
self.request)
except Exception:
server_groups = []
exceptions.handle(self.request,
_('Unable to retrieve server groups.'))
return server_groups
class DetailView(tabs.TabView):
tab_group_class = project_tabs.ServerGroupDetailTabs
template_name = 'project/server_groups/detail.html'
page_title = 'Server Group Details'
class CreateView(forms.ModalFormView):
form_class = project_forms.CreateForm
template_name = 'project/server_groups/create.html'
success_url = reverse_lazy("horizon:project:server_groups:index")
def get_context_data(self, **kwargs):
context = super(CreateView, self).get_context_data(**kwargs)
try:
context['usages'] = quotas.tenant_limit_usages(self.request)
except Exception:
exceptions.handle(self.request)
return context
class EditAttachmentsView(tables.DataTableView, forms.ModalFormView):
table_class = project_tables.AttachmentsTable
form_class = project_forms.AttachForm
template_name = 'project/server_groups/attach.html'
success_url = reverse_lazy("horizon:project:server_groups:index")
def get_object(self):
if not hasattr(self, "_object"):
volume_id = self.kwargs['volume_id']
try:
self._object = api.cinder.volume_get(self.request, volume_id)
except Exception:
self._object = None
exceptions.handle(self.request,
_('Unable to retrieve volume information.'))
return self._object
def get_data(self):
try:
volumes = self.get_object()
attachments = [att for att in volumes.attachments if att]
except Exception:
attachments = []
exceptions.handle(self.request,
_('Unable to retrieve volume information.'))
return attachments
def get_initial(self):
try:
instances, has_more = api.nova.server_list(self.request)
except Exception:
instances = []
exceptions.handle(self.request,
_("Unable to retrieve attachment information."))
return {'volume': self.get_object(),
'instances': instances}
def get_form(self):
if not hasattr(self, "_form"):
form_class = self.get_form_class()
self._form = super(EditAttachmentsView, self).get_form(form_class)
return self._form
def get_context_data(self, **kwargs):
context = super(EditAttachmentsView, self).get_context_data(**kwargs)
context['form'] = self.get_form()
volume = self.get_object()
if volume and volume.status == 'available':
context['show_attach'] = True
else:
context['show_attach'] = False
context['volume'] = volume
if self.request.is_ajax():
context['hide'] = True
return context
def get(self, request, *args, **kwargs):
# Table action handling
handled = self.construct_tables()
if handled:
return handled
return self.render_to_response(self.get_context_data(**kwargs))
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.get(request, *args, **kwargs)

View File

@ -1,11 +1,11 @@
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'server_groups'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'project'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'compute'
# A list of applications to be added to INSTALLED_APPS.
# Python panel class of the PANEL to be added.
ADD_PANEL = \
'starlingx_dashboard.dashboards.project.server_groups.panel.ServerGroups'
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'server_groups'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'project'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'compute'
# A list of applications to be added to INSTALLED_APPS.
# Python panel class of the PANEL to be added.
ADD_PANEL = \
'starlingx_dashboard.dashboards.project.server_groups.panel.ServerGroups'

View File

@ -1,10 +1,10 @@
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'server_groups'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'admin'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'compute'
# Python panel class of the PANEL to be added.
ADD_PANEL = \
'starlingx_dashboard.dashboards.admin.server_groups.panel.ServerGroups'
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'server_groups'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'admin'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'compute'
# Python panel class of the PANEL to be added.
ADD_PANEL = \
'starlingx_dashboard.dashboards.admin.server_groups.panel.ServerGroups'

View File

@ -1,2 +1,2 @@
from starlingx_dashboard.stx_horizon.tables.actions import FixedWithQueryFilter
from starlingx_dashboard.stx_horizon.tables.actions import LimitAction
from starlingx_dashboard.stx_horizon.tables.actions import FixedWithQueryFilter # noqa
from starlingx_dashboard.stx_horizon.tables.actions import LimitAction # noqa

View File

@ -16,8 +16,10 @@ DEFAULT_TABLE_LIMITS = [10, 20, 50, 100, 500, 1000]
class FixedWithQueryFilter(FilterAction):
"""A FilterAction that visually renders like a combination
FixedFilterAction and a FilterAction of type "query.
"""FilterAction
A FilterAction that visually renders like a combination
FixedFilterAction and a FilterAction of type query.
Before extracting data from the filter, always ensure to first call
the method updateFromRequestDataToSession(..) which will copy current
@ -38,7 +40,9 @@ class FixedWithQueryFilter(FilterAction):
self.disabled_choices = []
def _get_fieldFromGETorPOSTorSESSION(self, request, param_name):
"""Utility method for getting 'named" data (param_name) from either
"""Utility method
Utility method for getting 'named" data (param_name) from either
GET/POST or Session .
IMPORTANT NOTE: Has the side-effect of storing the data into
the session

View File

@ -1,5 +0,0 @@
#
# Copyright (c) 2018 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#

15
tox.ini
View File

@ -33,15 +33,26 @@ commands =
ignore = E501,E129
[flake8]
# H102 Apache 2.0 license header not found
# B301 Python 3 does not include `.iter*` methods on dictionaries.
# B005 Using .strip() with multi-character strings is misleading the reader.
ignore = H102, B301, B005
# H106 Dont put vim configuration in source files (off by default).
# H203 Use assertIs(Not)None to check for None (off by default).
# H904 Delay string interpolations at logging calls (off by default).
enable-extensions = H106,H203,H904
[testenv:pep8]
basepython = python3
usedevelop = False
skip_install = True
deps =
pep8
hacking
flake8-bugbear
flake8<3.6.0
commands =
pep8
flake8
[testenv:venv]
basepython = python3