Merge "Enable zuul unit tests for stx-gui"
This commit is contained in:
commit
4f0afaf708
@ -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'),
|
||||
]
|
||||
|
@ -1,2 +1,2 @@
|
||||
SRC_DIR="starlingx-dashboard"
|
||||
TIS_PATCH_VER=16
|
||||
TIS_PATCH_VER=17
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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']
|
||||
|
@ -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
|
||||
|
||||
|
@ -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]
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 = (
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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__)
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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']:
|
||||
|
@ -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.
|
||||
#
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
#
|
||||
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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,),
|
||||
|
@ -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':
|
||||
|
@ -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 = [
|
||||
|
@ -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"
|
||||
|
@ -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']:
|
||||
|
@ -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)
|
||||
|
@ -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'])
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
#
|
||||
|
||||
|
||||
|
@ -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'],))
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,)
|
||||
|
@ -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')
|
||||
]
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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.'))
|
||||
|
@ -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 = _(
|
||||
|
@ -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
|
||||
|
@ -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.')
|
||||
|
@ -30,4 +30,5 @@ class DCAdmin(horizon.Dashboard):
|
||||
|
||||
return super(DCAdmin, self).allowed(context)
|
||||
|
||||
|
||||
horizon.register(DCAdmin)
|
||||
|
@ -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 = (
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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,)
|
||||
|
@ -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,)
|
||||
|
@ -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'),
|
||||
]
|
||||
|
@ -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)
|
||||
|
@ -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'
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,5 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
15
tox.ini
15
tox.ini
@ -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 Don’t 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user