Browse Source

Code cleaned after Vancouver Demo

Change-Id: I9746ec6bec06f8edf2e1b01a320ca3bfab780980
changes/78/570578/1
Carmelo Romeo 4 years ago
parent
commit
d8547deb54
  1. 8
      .gitignore
  2. 85
      iotronic_ui.egg-info/PKG-INFO
  3. 88
      iotronic_ui.egg-info/SOURCES.txt
  4. 1
      iotronic_ui.egg-info/dependency_links.txt
  5. 1
      iotronic_ui.egg-info/not-zip-safe
  6. 1
      iotronic_ui.egg-info/pbr.json
  7. 6
      iotronic_ui.egg-info/requires.txt
  8. 1
      iotronic_ui.egg-info/top_level.txt
  9. 111
      iotronic_ui/api/iotronic.py
  10. 282
      iotronic_ui/iot/boards/forms.py
  11. 4
      iotronic_ui/iot/boards/panel.py
  12. 56
      iotronic_ui/iot/boards/tables.py
  13. 4
      iotronic_ui/iot/boards/tabs.py
  14. 8
      iotronic_ui/iot/boards/templates/boards/_attachport.html
  15. 8
      iotronic_ui/iot/boards/templates/boards/_detachport.html
  16. 52
      iotronic_ui/iot/boards/templates/boards/_detail_overview.html
  17. 8
      iotronic_ui/iot/boards/templates/boards/_disableservice.html
  18. 8
      iotronic_ui/iot/boards/templates/boards/_enableservice.html
  19. 0
      iotronic_ui/iot/boards/templates/boards/_removeservices.html
  20. 7
      iotronic_ui/iot/boards/templates/boards/attachport.html
  21. 7
      iotronic_ui/iot/boards/templates/boards/detachport.html
  22. 7
      iotronic_ui/iot/boards/templates/boards/disableservice.html
  23. 7
      iotronic_ui/iot/boards/templates/boards/enableservice.html
  24. 2
      iotronic_ui/iot/boards/templates/boards/removeservices.html
  25. 10
      iotronic_ui/iot/boards/urls.py
  26. 429
      iotronic_ui/iot/boards/views.py
  27. 1
      iotronic_ui/iot/dashboard.py
  28. 113
      iotronic_ui/iot/plugins/forms.py
  29. 5
      iotronic_ui/iot/plugins/panel.py
  30. 24
      iotronic_ui/iot/plugins/tables.py
  31. 4
      iotronic_ui/iot/plugins/urls.py
  32. 7
      iotronic_ui/iot/plugins/views.py
  33. 85
      iotronic_ui/iot/services/forms.py
  34. 3
      iotronic_ui/iot/services/panel.py
  35. 22
      iotronic_ui/iot/services/tables.py
  36. 2
      iotronic_ui/iot/services/urls.py
  37. 56
      iotronic_ui/iot/services/views.py
  38. BIN
      iotronic_ui/iot/static/iot/images/blue-circle.png
  39. BIN
      iotronic_ui/iot/static/iot/images/green-circle.png
  40. BIN
      iotronic_ui/iot/static/iot/images/marker-icon-green.png
  41. BIN
      iotronic_ui/iot/static/iot/images/marker-icon-red.png
  42. BIN
      iotronic_ui/iot/static/iot/images/marker-icon.png
  43. BIN
      iotronic_ui/iot/static/iot/images/marker-shadow.png
  44. BIN
      iotronic_ui/iot/static/iot/images/red-circle.png
  45. 122
      iotronic_ui/iot/static/iot/js/iot.js
  46. 7
      iotronic_ui/iot/static/iot/scss/iot.scss

8
.gitignore vendored

@ -0,0 +1,8 @@
.tox
.idea
iotronic_ui.egg-info
build
*.pyc
AUTHORS
Authors
ChangeLog

85
iotronic_ui.egg-info/PKG-INFO

@ -1,85 +0,0 @@
Metadata-Version: 1.1
Name: iotronic-ui
Version: 0.0.0
Summary: Iotronic plugin for the OpenStack Dashboard
Home-page: http://www.openstack.org/
Author: OpenStack
Author-email: openstack-dev@lists.openstack.org
License: UNKNOWN
Description: ===============================
IoTronic Panels
===============================
Iotronic plugin for the OpenStack Dashboard
* Free software: Apache license
* Source: http://git.openstack.org/cgit/openstack/iotronic_ui
* Bugs: http://bugs.launchpad.net/None
Features
--------
* TODO
Enabling in DevStack
--------------------
Add this repo as an external repository into your ``local.conf`` file::
[[local|localrc]]
enable_plugin iotronic_ui https://github.com/openstack/iotronic_ui
Manual Installation
-------------------
Begin by cloning the Horizon and IoTronic Panels repositories::
git clone https://github.com/openstack/horizon
git clone https://github.com/openstack/iotronic_ui
Create a virtual environment and install Horizon dependencies::
cd horizon
python tools/install_venv.py
Set up your ``local_settings.py`` file::
cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py
Open up the copied ``local_settings.py`` file in your preferred text
editor. You will want to customize several settings:
- ``OPENSTACK_HOST`` should be configured with the hostname of your
OpenStack server. Verify that the ``OPENSTACK_KEYSTONE_URL`` and
``OPENSTACK_KEYSTONE_DEFAULT_ROLE`` settings are correct for your
environment. (They should be correct unless you modified your
OpenStack server to change them.)
Install IoTronic Panels with all dependencies in your virtual environment::
tools/with_venv.sh pip install -e ../iotronic_ui/
And enable it in Horizon::
ln -s ../iotronic_ui/iotronic_ui/enabled/_90_project_iot_panelgroup.py openstack_dashboard/local/enabled
ln -s ../iotronic_ui/iotronic_ui/enabled/_91_project_iot_boardss_panel.py openstack_dashboard/local/enabled
To run horizon with the newly enabled IoTronic Panels plugin run::
./run_tests.sh --runserver 0.0.0.0:8080
to have the application start on port 8080 and the horizon dashboard will be
available in your browser at http://localhost:8080/
Platform: UNKNOWN
Classifier: Environment :: OpenStack
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.5

88
iotronic_ui.egg-info/SOURCES.txt

@ -1,88 +0,0 @@
CONTRIBUTING.rst
HACKING.rst
LICENSE
MANIFEST.in
README.rst
babel-django.cfg
babel-djangojs.cfg
manage.py
package.json
requirements.txt
setup.cfg
setup.py
test-requirements.txt
test-shim.js
tox.ini
doc/Makefile
doc/source/conf.py
doc/source/index.rst
doc/source/configuration/index.rst
doc/source/contributor/api.rst
doc/source/contributor/index.rst
doc/source/install/index.rst
iotronic_ui/__init__.py
iotronic_ui.egg-info/PKG-INFO
iotronic_ui.egg-info/SOURCES.txt
iotronic_ui.egg-info/dependency_links.txt
iotronic_ui.egg-info/not-zip-safe
iotronic_ui.egg-info/pbr.json
iotronic_ui.egg-info/requires.txt
iotronic_ui.egg-info/top_level.txt
iotronic_ui/api/iotronic.py
iotronic_ui/enabled/_6000_iot.py
iotronic_ui/enabled/_6010_iot_boards_panel.py
iotronic_ui/enabled/_6020_iot_plugins_panel.py
iotronic_ui/iot/__init__.py
iotronic_ui/iot/dashboard.py
iotronic_ui/iot/boards/__init__.py
iotronic_ui/iot/boards/forms.py
iotronic_ui/iot/boards/panel.py
iotronic_ui/iot/boards/tables.py
iotronic_ui/iot/boards/tabs.py
iotronic_ui/iot/boards/tests.py
iotronic_ui/iot/boards/urls.py
iotronic_ui/iot/boards/views.py
iotronic_ui/iot/boards/templates/boards/_create.html
iotronic_ui/iot/boards/templates/boards/_detail_overview.html
iotronic_ui/iot/boards/templates/boards/_removeplugins.html
iotronic_ui/iot/boards/templates/boards/_update.html
iotronic_ui/iot/boards/templates/boards/create.html
iotronic_ui/iot/boards/templates/boards/index.html
iotronic_ui/iot/boards/templates/boards/removeplugins.html
iotronic_ui/iot/boards/templates/boards/update.html
iotronic_ui/iot/plugins/__init__.py
iotronic_ui/iot/plugins/forms.py
iotronic_ui/iot/plugins/panel.py
iotronic_ui/iot/plugins/tables.py
iotronic_ui/iot/plugins/tabs.py
iotronic_ui/iot/plugins/tests.py
iotronic_ui/iot/plugins/urls.py
iotronic_ui/iot/plugins/views.py
iotronic_ui/iot/plugins/templates/plugins/_call.html
iotronic_ui/iot/plugins/templates/plugins/_create.html
iotronic_ui/iot/plugins/templates/plugins/_detail_overview.html
iotronic_ui/iot/plugins/templates/plugins/_inject.html
iotronic_ui/iot/plugins/templates/plugins/_remove.html
iotronic_ui/iot/plugins/templates/plugins/_start.html
iotronic_ui/iot/plugins/templates/plugins/_stop.html
iotronic_ui/iot/plugins/templates/plugins/_update.html
iotronic_ui/iot/plugins/templates/plugins/call.html
iotronic_ui/iot/plugins/templates/plugins/create.html
iotronic_ui/iot/plugins/templates/plugins/index.html
iotronic_ui/iot/plugins/templates/plugins/inject.html
iotronic_ui/iot/plugins/templates/plugins/remove.html
iotronic_ui/iot/plugins/templates/plugins/start.html
iotronic_ui/iot/plugins/templates/plugins/stop.html
iotronic_ui/iot/plugins/templates/plugins/update.html
iotronic_ui/iot/static/iot/images/blue-circle.png
iotronic_ui/iot/static/iot/images/green-circle.png
iotronic_ui/iot/static/iot/images/marker-icon-green.png
iotronic_ui/iot/static/iot/images/marker-icon-red.png
iotronic_ui/iot/static/iot/images/marker-icon.png
iotronic_ui/iot/static/iot/images/marker-shadow.png
iotronic_ui/iot/static/iot/images/red-circle.png
iotronic_ui/iot/static/iot/js/iot.js
iotronic_ui/iot/static/iot/scss/iot.scss
iotronic_ui/iot/templates/iot/base.html
tools/tox_install.sh
tools/tox_install.sh_ORIG

1
iotronic_ui.egg-info/dependency_links.txt

@ -1 +0,0 @@

1
iotronic_ui.egg-info/not-zip-safe

@ -1 +0,0 @@

1
iotronic_ui.egg-info/pbr.json

@ -1 +0,0 @@
{"git_version": "4902c1d", "is_release": false}

6
iotronic_ui.egg-info/requires.txt

@ -1,6 +0,0 @@
pbr!=2.1.0,>=2.0.0
Babel!=2.4.0,>=2.3.4
Django<2.0,>=1.8
django-babel>=0.5.1
django-compressor>=2.0
django-pyscss>=2.0.2

1
iotronic_ui.egg-info/top_level.txt

@ -1 +0,0 @@
iotronic_ui

111
iotronic_ui/api/iotronic.py

@ -43,14 +43,12 @@ def iotronicclient(request):
# BOARD MANAGEMENT
def board_list(request, status=None, detail=None, project=None):
"""List boards."""
boards = iotronicclient(request).board.list(status, detail, project)
return boards
return iotronicclient(request).board.list(status, detail, project)
def board_get(request, board_id, fields):
"""Get board info."""
board = iotronicclient(request).board.get(board_id, fields)
return board
return iotronicclient(request).board.get(board_id, fields)
def board_create(request, code, mobile, location, type, name):
@ -60,30 +58,26 @@ def board_create(request, code, mobile, location, type, name):
"location": location,
"type": type,
"name": name}
board = iotronicclient(request).board.create(**params)
return board
iotronicclient(request).board.create(**params)
def board_update(request, board_id, patch):
"""Update board."""
board = iotronicclient(request).board.update(board_id, patch)
return board
iotronicclient(request).board.update(board_id, patch)
def board_delete(request, board_id):
"""Delete board."""
board = iotronicclient(request).board.delete(board_id)
return board
iotronicclient(request).board.delete(board_id)
# PLUGIN MANAGEMENT (Cloud Side)
def plugin_list(request, detail=None, project=None, with_public=False,
all_plugins=False):
"""List plugins."""
plugins = iotronicclient(request).plugin.list(detail, project, \
with_public=with_public, \
all_plugins=all_plugins)
return plugins
return iotronicclient(request).plugin.list(detail, project,
with_public=with_public,
all_plugins=all_plugins)
def plugin_get(request, plugin_id, fields):
@ -99,53 +93,43 @@ def plugin_create(request, name, public, callable, code, parameters):
"callable": callable,
"code": code,
"parameters": parameters}
plugin = iotronicclient(request).plugin.create(**params)
return plugin
iotronicclient(request).plugin.create(**params)
def plugin_update(request, plugin_id, patch):
"""Update plugin."""
plugin = iotronicclient(request).plugin.update(plugin_id, patch)
return plugin
iotronicclient(request).plugin.update(plugin_id, patch)
def plugin_delete(request, plugin_id):
"""Delete plugin."""
plugin = iotronicclient(request).plugin.delete(plugin_id)
return plugin
return iotronicclient(request).plugin.delete(plugin_id)
# PLUGIN MANAGEMENT (Board Side)
def plugin_inject(request, board_id, plugin_id, onboot):
"""Inject plugin on board(s)."""
plugin = iotronicclient(request).plugin_injection. \
plugin_inject(board_id, \
plugin_id, \
onboot)
return plugin
return iotronicclient(request).plugin_injection.plugin_inject(board_id,
plugin_id,
onboot)
def plugin_action(request, board_id, plugin_id, action, params={}):
"""Start/Stop/Call actions on board(s)."""
plugin = iotronicclient(request).plugin_injection. \
plugin_action(board_id,
plugin_id,
action,
params)
return plugin
return iotronicclient(request).plugin_injection.plugin_action(
board_id, plugin_id, action, params)
def plugin_remove(request, board_id, plugin_id):
"""Inject plugin on board(s)."""
plugin = iotronicclient(request).plugin_injection. \
plugin_remove(board_id, plugin_id)
return plugin
"""Remove plugin from board."""
iotronicclient(request).plugin_injection.plugin_remove(board_id,
plugin_id)
def plugins_on_board(request, board_id):
"""Plugins on board."""
plugins = iotronicclient(request).plugin_injection. \
plugins_on_board(board_id)
plugins = iotronicclient(request).plugin_injection.plugins_on_board(
board_id)
detailed_plugins = []
# fields = {"name", "public", "callable"}
@ -161,14 +145,12 @@ def plugins_on_board(request, board_id):
# SERVICE MANAGEMENT
def service_list(request, detail=None):
"""List services."""
services = iotronicclient(request).service.list(detail)
return services
return iotronicclient(request).service.list(detail)
def service_get(request, service_id, fields):
"""Get service info."""
service = iotronicclient(request).service.get(service_id, fields)
return service
return iotronicclient(request).service.get(service_id, fields)
def service_create(request, name, port, protocol):
@ -176,36 +158,34 @@ def service_create(request, name, port, protocol):
params = {"name": name,
"port": port,
"protocol": protocol}
service = iotronicclient(request).service.create(**params)
return service
iotronicclient(request).service.create(**params)
def service_update(request, service_id, patch):
"""Update service."""
service = iotronicclient(request).service.update(service_id, patch)
return service
iotronicclient(request).service.update(service_id, patch)
def service_delete(request, service_id):
"""Delete service."""
service = iotronicclient(request).service.delete(service_id)
return service
iotronicclient(request).service.delete(service_id)
def services_on_board(request, board_id, detail=False):
"""List services on board."""
services = iotronicclient(request).exposed_service \
.services_on_board(board_id)
services = iotronicclient(request).exposed_service.services_on_board(
board_id)
if detail:
detailed_services = []
fields = {"name", "port", "protocol"}
for service in services:
details = iotronicclient(request). \
service.get(service._info["service"], fields)
details = iotronicclient(request).service.get(
service._info["service"], fields)
detailed_services.append({"name": details._info["name"],
detailed_services.append({"uuid": service._info["service"],
"name": details._info["name"],
"public_port":
service._info["public_port"],
"port": details._info["port"],
@ -219,14 +199,29 @@ def services_on_board(request, board_id, detail=False):
def service_action(request, board_id, service_id, action):
"""Action on service."""
service_action = iotronicclient(request).exposed_service. \
service_action(board_id, service_id, action)
return service_action
return iotronicclient(request).exposed_service.service_action(board_id,
service_id,
action)
def restore_services(request, board_id):
"""Restore services."""
service_restore = iotronicclient(request).exposed_service. \
restore_services(board_id)
return service_restore
return iotronicclient(request).exposed_service.restore_services(board_id)
# PORTS MANAGEMENT
def port_list(request, board_id):
"""Get ports attached to a board."""
return iotronicclient(request).port.list()
def attach_port(request, board_id, network_id, subnet_id):
"""Attach port to a subnet for a board."""
return iotronicclient(request).portonboard.attach_port(board_id,
network_id,
subnet_id)
def detach_port(request, board_id, port_id):
"""Detach port from the board."""
iotronicclient(request).portonboard.detach_port(board_id, port_id)

282
iotronic_ui/iot/boards/forms.py

@ -67,12 +67,13 @@ class CreateBoardForm(forms.SelfHandlingForm):
"longitude": str(data["longitude"]),
"altitude": str(data["altitude"])}]
board = iotronic.board_create(request, data["code"],
data["mobile"], data["location"],
data["type"], data["name"])
iotronic.board_create(request, data["code"],
data["mobile"], data["location"],
data["type"], data["name"])
messages.success(request, _("Board created successfully."))
return True
return board
except Exception:
exceptions.handle(request, _('Unable to create board.'))
@ -82,49 +83,54 @@ class UpdateBoardForm(forms.SelfHandlingForm):
name = forms.CharField(label=_("Board Name"))
mobile = forms.BooleanField(label=_("Mobile"), required=False)
"""
latitude = forms.FloatField(label=_("Latitude"))
longitude = forms.FloatField(label=_("Longitude"))
altitude = forms.FloatField(label=_("Altitude"))
"""
def __init__(self, *args, **kwargs):
super(UpdateBoardForm, self).__init__(*args, **kwargs)
# LOG.debug("MELO INITIAL: %s", kwargs["initial"])
# LOG.debug("INITIAL: %s", kwargs["initial"])
LOG.debug("MELO Manager: %s", policy.check((("iot", "iot_manager"),),
self.request))
LOG.debug("MELO Admin: %s", policy.check((("iot", "iot_admin"),),
self.request))
# LOG.debug("Manager: %s", policy.check((("iot", "iot_manager"),),
# self.request))
# LOG.debug("Admin: %s", policy.check((("iot", "iot_admin"),),
# self.request))
# Admin
if policy.check((("iot", "iot:update_boards"),), self.request):
# LOG.debug("MELO ADMIN")
# LOG.debug("ADMIN")
pass
# Manager or Admin of the iot project
elif (policy.check((("iot", "iot_manager"),), self.request) or
policy.check((("iot", "iot_admin"),), self.request)):
# LOG.debug("MELO NO-edit IOT ADMIN")
# LOG.debug("NO-edit IOT ADMIN")
pass
# Other users
else:
if self.request.user.id != kwargs["initial"]["owner"]:
# LOG.debug("MELO IMMUTABLE FIELDS")
# LOG.debug("IMMUTABLE FIELDS")
self.fields["name"].widget.attrs = {'readonly': 'readonly'}
self.fields["mobile"].widget.attrs = {'disabled': 'disabled'}
"""
self.fields["latitude"].widget.attrs = {'readonly':
'readonly'}
self.fields["longitude"].widget.attrs = {'readonly':
'readonly'}
self.fields["altitude"].widget.attrs = {'readonly':
'readonly'}
"""
def handle(self, request, data):
try:
"""
data["location"] = [{"latitude": str(data["latitude"]),
"longitude": str(data["longitude"]),
"altitude": str(data["altitude"])}]
@ -132,13 +138,196 @@ class UpdateBoardForm(forms.SelfHandlingForm):
{"name": data["name"],
"mobile": data["mobile"],
"location": data["location"]})
"""
iotronic.board_update(request, data["uuid"],
{"name": data["name"],
"mobile": data["mobile"]})
messages.success(request, _("Board updated successfully."))
return True
except Exception:
exceptions.handle(request, _('Unable to update board.'))
class EnableServiceForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Plugin ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Board Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
service_list = forms.MultipleChoiceField(
label=_("Services List"),
widget=forms.SelectMultiple(
attrs={'class': 'switchable',
'data-slug': 'slug-select-services'}),
help_text=_("Add available services from this pool")
)
def __init__(self, *args, **kwargs):
super(EnableServiceForm, self).__init__(*args, **kwargs)
self.fields["service_list"].choices = kwargs["initial"]["service_list"]
def handle(self, request, data):
counter = 0
for service in data["service_list"]:
try:
action = iotronic.service_action(request, data["uuid"],
service, "ServiceEnable")
# message_text = "Service(s) enabled successfully."
message_text = action
messages.success(request, _(message_text))
if counter != len(data["service_list"]) - 1:
counter += 1
else:
return True
except Exception:
message_text = "Unable to enable service."
exceptions.handle(request, _(message_text))
class DisableServiceForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Plugin ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Board Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
service_list = forms.MultipleChoiceField(
label=_("Services List"),
widget=forms.SelectMultiple(
attrs={'class': 'switchable',
'data-slug': 'slug-select-services'}),
help_text=_("Select services to disable from this pool")
)
def __init__(self, *args, **kwargs):
super(DisableServiceForm, self).__init__(*args, **kwargs)
self.fields["service_list"].choices = kwargs["initial"]["service_list"]
def handle(self, request, data):
counter = 0
for service in data["service_list"]:
try:
action = iotronic.service_action(request, data["uuid"],
service, "ServiceDisable")
# message_text = "Service(s) disabled successfully."
message_text = action
messages.success(request, _(message_text))
if counter != len(data["service_list"]) - 1:
counter += 1
else:
return True
except Exception:
message_text = "Unable to disable service."
exceptions.handle(request, _(message_text))
class AttachPortForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Board ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Board Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
networks_list = forms.ChoiceField(
label=_("Networks List"),
help_text=_("Select network:subnet from the list")
)
def __init__(self, *args, **kwargs):
super(AttachPortForm, self).__init__(*args, **kwargs)
net_choices = kwargs["initial"]["networks_list"]
self.fields["networks_list"].choices = net_choices
def handle(self, request, data):
array = data["networks_list"].split(':')
LOG.debug(array)
network_id = array[0]
subnet_id = array[1]
try:
attach = iotronic.attach_port(request, data["uuid"],
network_id, subnet_id)
# LOG.debug("ATTACH: %s", attach)
ip = attach._info["ip"]
message_text = "Attached port to ip " + str(ip) + \
" on board " + str(data["name"]) + \
" completed successfully"
messages.success(request, _(message_text))
return True
except Exception:
message_text = "Unable to attach port on board " + \
str(data["name"])
exceptions.handle(request, _(message_text))
class DetachPortForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Board ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Board Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
port_list = forms.MultipleChoiceField(
label=_("Ports List"),
widget=forms.SelectMultiple(
attrs={'class': 'switchable', 'data-slug': 'slug-detacj-ports'}),
help_text=_("Select one or more of the following attached ports")
)
def __init__(self, *args, **kwargs):
super(DetachPortForm, self).__init__(*args, **kwargs)
self.fields["port_list"].choices = kwargs["initial"]["ports"]
def handle(self, request, data):
# LOG.debug("DATA: %s %s", data, len(data["port_list"]))
counter = 0
for port in data["port_list"]:
try:
iotronic.detach_port(request, data["uuid"], port)
message_text = "Detach port " + str(port) + " from board " + \
str(data["name"]) + " completed successfully"
messages.success(request, _(message_text))
if counter != len(data["port_list"]) - 1:
counter += 1
else:
return True
except Exception:
message_text = "Unable to detach port " + str(port) + \
" from board " + str(data["name"])
exceptions.handle(request, _(message_text))
class RemovePluginsForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Board ID"), widget=forms.HiddenInput)
@ -159,11 +348,7 @@ class RemovePluginsForm(forms.SelfHandlingForm):
super(RemovePluginsForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
boardslist_length = len(kwargs["initial"]["board_list"])
self.fields["plugin_list"].choices = kwargs["initial"]["plugin_list"]
self.fields["plugin_list"].max_length = boardslist_length
def handle(self, request, data):
@ -174,13 +359,8 @@ class RemovePluginsForm(forms.SelfHandlingForm):
if key == plugin:
try:
board = None
iotronic.plugin_remove(request, data["uuid"], key)
# LOG.debug('INJECT: %s %s', plugin, value)
# board = iotronic.plugin_create(request, data["name"],
# data["public"],
# data["callable"],
# data["code"])
message_text = "Plugin " + str(value) + \
" removed successfully."
messages.success(request, _(message_text))
@ -188,10 +368,64 @@ class RemovePluginsForm(forms.SelfHandlingForm):
if counter != len(data["plugin_list"]) - 1:
counter += 1
else:
return board
return True
except Exception:
message_text = "Unable to remove plugin " \
+ str(value) + "."
exceptions.handle(request, _(message_text))
break
class RemoveServicesForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Board ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Board Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
service_list = forms.MultipleChoiceField(
label=_("Services List"),
widget=forms.SelectMultiple(
attrs={'class': 'switchable',
'data-slug': 'slug-remove-services'}),
help_text=_("Select services in this pool")
)
def __init__(self, *args, **kwargs):
super(RemoveServicesForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
self.fields["service_list"].choices = kwargs["initial"]["service_list"]
def handle(self, request, data):
counter = 0
for service in data["service_list"]:
for key, value in self.fields["service_list"].choices:
if key == service:
try:
disable = iotronic.service_action(request,
data["uuid"],
key,
"ServiceDisable")
message_text = disable
messages.success(request, _(message_text))
if counter != len(data["service_list"]) - 1:
counter += 1
else:
return True
except Exception:
message_text = "Unable to disable service " \
+ str(value) + "."
exceptions.handle(request, _(message_text))
break

4
iotronic_ui/iot/boards/panel.py

@ -15,6 +15,7 @@ from django.utils.translation import ugettext_lazy as _
import horizon
# from openstack_dashboard.api import keystone
from iotronic_ui.iot import dashboard
class Boards(horizon.Panel):
@ -31,3 +32,6 @@ class Boards(horizon.Panel):
return False
return super(Roles, self).can_access(context)
"""
dashboard.Iot.register(Boards)

56
iotronic_ui/iot/boards/tables.py

@ -64,13 +64,56 @@ class RestoreServices(tables.BatchAction):
api.iotronic.restore_services(request, board_id)
class EnableServiceLink(tables.LinkAction):
name = "enableservice"
verbose_name = _("Enable Service(s)")
url = "horizon:iot:boards:enableservice"
classes = ("ajax-modal",)
# icon = "plus"
# policy_rules = (("iot", "iot:service_action"),)
class DisableServiceLink(tables.LinkAction):
name = "disableservice"
verbose_name = _("Disable Service(s)")
url = "horizon:iot:boards:disableservice"
classes = ("ajax-modal",)
# icon = "plus"
# policy_rules = (("iot", "iot:service_action"),)
class RemovePluginsLink(tables.LinkAction):
name = "removeplugins"
verbose_name = _("Remove Plugin(s)")
url = "horizon:iot:boards:removeplugins"
classes = ("ajax-modal",)
icon = "plus"
# policy_rules = (("iot", "iot:create_board"),)
# policy_rules = (("iot", "iot:remove_plugins"),)
class RemoveServicesLink(tables.LinkAction):
name = "removeservices"
verbose_name = _("Remove Service(s)")
url = "horizon:iot:boards:removeservices"
classes = ("ajax-modal",)
icon = "plus"
# policy_rules = (("iot", "iot:remove_services"),)
class AttachPortLink(tables.LinkAction):
name = "attachport"
verbose_name = _("Attach Port")
url = "horizon:iot:boards:attachport"
classes = ("ajax-modal",)
icon = "plus"
class DetachPortLink(tables.LinkAction):
name = "detachport"
verbose_name = _("Detach Port")
url = "horizon:iot:boards:detachport"
classes = ("ajax-modal",)
icon = "plus"
class DeleteBoardsAction(tables.DeleteAction):
@ -117,6 +160,7 @@ class BoardFilterAction(tables.FilterAction):
return [board for board in boards
if q in board.name.lower()]
def show_services(board_info):
template_name = 'iot/boards/_cell_services.html'
context = board_info._info
@ -145,7 +189,9 @@ class BoardsTable(tables.DataTable):
class Meta(object):
name = "boards"
verbose_name = _("boards")
row_actions = (EditBoardLink, RestoreServices,
RemovePluginsLink, DeleteBoardsAction)
table_actions = (BoardFilterAction, CreateBoardLink,
RestoreServices, DeleteBoardsAction)
row_actions = (EditBoardLink, EnableServiceLink, DisableServiceLink,
RestoreServices, AttachPortLink, DetachPortLink,
RemovePluginsLink, RemoveServicesLink,
DeleteBoardsAction)
table_actions = (BoardFilterAction, CreateBoardLink,
DeleteBoardsAction)

4
iotronic_ui/iot/boards/tabs.py

@ -21,7 +21,7 @@ LOG = logging.getLogger(__name__)
"""
import inspect
LOG.debug('MELO CLASSES: %s',
LOG.debug('CLASSES: %s',
inspect.getmembers(tabs, predicate=inspect.isclass))
"""
@ -34,12 +34,14 @@ class OverviewTab(tabs.Tab):
def get_context_data(self, request):
coordinates = self.tab_group.kwargs['board'].__dict__['location'][0]
ports = self.tab_group.kwargs['board']._info['ports']
services = self.tab_group.kwargs['board']._info['services']
plugins = self.tab_group.kwargs['board']._info['plugins']
return {"board": self.tab_group.kwargs['board'],
"coordinates": coordinates,
"services": services,
"ports": ports,
"plugins": plugins,
"is_superuser": request.user.is_superuser}

8
iotronic_ui/iot/boards/templates/boards/_attachport.html

@ -0,0 +1,8 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Attach port to the selected board." %}</p>
{% endblock %}

8
iotronic_ui/iot/boards/templates/boards/_detachport.html

@ -0,0 +1,8 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Detach one or more attached ports from the board." %}</p>
{% endblock %}

52
iotronic_ui/iot/boards/templates/boards/_detail_overview.html

@ -22,26 +22,50 @@
<dd>{{ board.mobile }}</dd>
<dt>{% trans "Extra" %}</dt>
<dd>{{ board.extra }}</dd>
<dt>{% trans "Services" %}</dt>
{% if services %}
</dl>
<h4>{% trans "Ports" %}</h4>
<hr class="header_rule">
<dl class="dl-horizontal">
{% if ports %}
{% for port in ports %}
<dt>{{ port.VIF_name }}</dt>
<dd>{{ port.ip }}</dd>
{% endfor %}
{% else %}
<dd>--</dd>
{% endif %}
</dl>
<h4>{% trans "Services" %}</h4>
<hr class="header_rule">
<dl class="dl-horizontal">
{% if services %}
{% for service in services %}
<dd>{{ service.name }} [{{ service.protocol }}] {{ service.port }} --> {{ service.public_port }}</dd>
<dt>{{ service.name }} [{{ service.protocol }}] {{ service.port }}</dt>
<dd>{{ service.public_port }}</dd>
{% endfor %}
{% else %}
{% else %}
<dd>--</dd>
{% endif %}
<dt>{% trans "Plugins" %}</dt>
{% if plugins %}
{% for plugin in plugins %}
<dd>{{ plugin.name }}</dd>
{% endfor %}
{% else %}
<dd>--</dd>
{% endif %}
{% endif %}
</dl>
<h4>{% trans "Plugins" %}</h4>
<hr class="header_rule">
<dl class="dl-horizontal">
{% if plugins %}
{% for plugin in plugins %}
<dt>{{ plugin.name }}</dt>
<dd>{{ plugin.id }}</dd>
{% endfor %}
{% else %}
<dd>--</dd>
{% endif %}
</dl>
</div>
<!--<div id="mapdiv" style="min-height:300px; margin-bottom: 10px;" data-coordinates='[{"latitude": "{{ coordinates.latitude }}", "longitude": "{{ coordinates.longitude }}", "altitude": "{{ coordinates.altitude }}"}]'>-->
<!--
<div id="mapdiv" style="min-height:300px; margin-bottom: 10px;">
<script>
$(document).ready(function(){
@ -64,4 +88,4 @@
});
</script>
</div>
-->

8
iotronic_ui/iot/boards/templates/boards/_disableservice.html

@ -0,0 +1,8 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Disable service(s) on the selected board." %}</p>
{% endblock %}

8
iotronic_ui/iot/boards/templates/boards/_enableservice.html

@ -0,0 +1,8 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Enable service(s) on the selected board." %}</p>
{% endblock %}

0
iotronic_ui/iot/services/templates/services/_remove.html → iotronic_ui/iot/boards/templates/boards/_removeservices.html

7
iotronic_ui/iot/boards/templates/boards/attachport.html

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Attach" %}{% endblock %}
{% block main %}
{% include 'iot/boards/_attachport.html' %}
{% endblock %}

7
iotronic_ui/iot/boards/templates/boards/detachport.html

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Detach" %}{% endblock %}
{% block main %}
{% include 'iot/boards/_detachport.html' %}
{% endblock %}

7
iotronic_ui/iot/boards/templates/boards/disableservice.html

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Disable" %}{% endblock %}
{% block main %}
{% include 'iot/boards/_disableservice.html' %}
{% endblock %}

7
iotronic_ui/iot/boards/templates/boards/enableservice.html

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Enable" %}{% endblock %}
{% block main %}
{% include 'iot/boards/_enableservice.html' %}
{% endblock %}

2
iotronic_ui/iot/services/templates/services/remove.html → iotronic_ui/iot/boards/templates/boards/removeservices.html

@ -3,5 +3,5 @@
{% block title %}{% trans "Remove service(s)." %}{% endblock %}
{% block main %}
{% include 'iot/services/_remove.html' %}
{% include 'iot/boards/_removeservices.html' %}
{% endblock %}

10
iotronic_ui/iot/boards/urls.py

@ -22,6 +22,16 @@ urlpatterns = [
name='update'),
url(r'^(?P<board_id>[^/]+)/removeplugins/$',
views.RemovePluginsView.as_view(), name='removeplugins'),
url(r'^(?P<board_id>[^/]+)/removeservices/$',
views.RemoveServicesView.as_view(), name='removeservices'),
url(r'^(?P<board_id>[^/]+)/enableservice/$',
views.EnableServiceView.as_view(), name='enableservice'),
url(r'^(?P<board_id>[^/]+)/disableservice/$',
views.DisableServiceView.as_view(), name='disableservice'),
url(r'^(?P<board_id>[^/]+)/attachport/$',
views.AttachPortView.as_view(), name='attachport'),
url(r'^(?P<board_id>[^/]+)/detachport/$',
views.DetachPortView.as_view(), name='detachport'),
url(r'^(?P<board_id>[^/]+)/detail/$', views.BoardDetailView.as_view(),
name='detail'),
]

429
iotronic_ui/iot/boards/views.py

@ -23,7 +23,8 @@ from horizon import tables
from horizon import tabs
from horizon.utils import memoized
from openstack_dashboard.api import iotronic
# from openstack_dashboard.api import iotronic
from openstack_dashboard import api
from openstack_dashboard import policy
from iotronic_ui.iot.boards import forms as project_forms
@ -42,25 +43,10 @@ class IndexView(tables.DataTableView):
def get_data(self):
boards = []
# FROM
"""
if policy.check((("identity", "identity:list_roles"),), self.request):
try:
boards = iotronic.board_list(self.request, None, None)
# LOG.debug('IOT BOARDS: %s', boards)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve boards list.'))
else:
msg = _("Insufficient privilege level to view boards information.")
messages.info(self.request, msg)
"""
# TO
# Admin
if policy.check((("iot", "iot:list_all_boards"),), self.request):
try:
boards = iotronic.board_list(self.request, None, None)
boards = api.iotronic.board_list(self.request, None, None)
except Exception:
exceptions.handle(self.request,
@ -69,7 +55,7 @@ class IndexView(tables.DataTableView):
# Admin_iot_project
elif policy.check((("iot", "iot:list_project_boards"),), self.request):
try:
boards = iotronic.board_list(self.request, None, None)
boards = api.iotronic.board_list(self.request, None, None)
except Exception:
exceptions.handle(self.request,
@ -78,14 +64,16 @@ class IndexView(tables.DataTableView):
# Other users
else:
try:
boards = iotronic.board_list(self.request, None, None)
boards = api.iotronic.board_list(self.request, None, None)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve user boards list.'))
for board in boards:
board_services = iotronic.services_on_board(self.request, board.uuid, True)
board_services = api.iotronic.services_on_board(self.request,
board.uuid,
True)
# board.__dict__.update(dict(services=board_services))
board._info.update(dict(services=board_services))
@ -116,8 +104,9 @@ class UpdateView(forms.ModalFormView):
@memoized.memoized_method
def get_object(self):
try:
return iotronic.board_get(self.request, self.kwargs['board_id'],
None)
return api.iotronic.board_get(self.request,
self.kwargs['board_id'],
None)
except Exception:
redirect = reverse("horizon:iot:boards:index")
exceptions.handle(self.request,
@ -143,12 +132,226 @@ class UpdateView(forms.ModalFormView):
'altitude': location["altitude"]}
class EnableServiceView(forms.ModalFormView):
template_name = 'iot/boards/enableservice.html'
modal_header = _("Enable Service(s)")
form_id = "service_enable_form"
form_class = project_forms.EnableServiceForm
submit_label = _("Enable")
# submit_url = reverse_lazy("horizon:iot:boards:enableservice")
submit_url = "horizon:iot:boards:enableservice"
success_url = reverse_lazy('horizon:iot:boards:index')
page_title = _("Action")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.board_get(self.request,
self.kwargs['board_id'],
None)
except Exception:
redirect = reverse("horizon:iot:boards:index")
exceptions.handle(self.request,
_('Unable to get board information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(EnableServiceView, self).get_context_data(**kwargs)
args = (self.get_object().uuid,)
context['submit_url'] = reverse(self.submit_url, args=args)
return context
def get_initial(self):
board = self.get_object()
# Populate available services
cloud_services = api.iotronic.service_list(self.request, None)
board_services = api.iotronic.services_on_board(self.request,
board.uuid,
True)
service_list = []
for cloud_service in cloud_services:
if len(board_services) == 0:
service_list.append((cloud_service._info["uuid"],
_(cloud_service._info["name"])))
else:
counter = 0
for board_service in board_services:
if board_service["uuid"] == cloud_service._info["uuid"]:
break
elif counter != len(board_services) - 1:
counter += 1
else:
service_list.append((cloud_service._info["uuid"],
_(cloud_service._info["name"])))
return {'uuid': board.uuid,
'name': board.name,
'service_list': service_list}
class DisableServiceView(forms.ModalFormView):
template_name = 'iot/boards/disableservice.html'
modal_header = _("Disable Service(s)")
form_id = "service_disable_form"
form_class = project_forms.DisableServiceForm
submit_label = _("Disable")
# submit_url = reverse_lazy("horizon:iot:boards:disableservice")
submit_url = "horizon:iot:boards:disableservice"
success_url = reverse_lazy('horizon:iot:boards:index')
page_title = _("Action")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.board_get(self.request,
self.kwargs['board_id'],
None)
except Exception:
redirect = reverse("horizon:iot:boards:index")
exceptions.handle(self.request,
_('Unable to get board information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(DisableServiceView, self).get_context_data(**kwargs)
args = (self.get_object().uuid,)
context['submit_url'] = reverse(self.submit_url, args=args)
return context
def get_initial(self):
board = self.get_object()
# Populate available services
cloud_services = api.iotronic.service_list(self.request, None)
board_services = api.iotronic.services_on_board(self.request,
board.uuid,
True)
service_list = []
for cloud_service in cloud_services:
for board_service in board_services:
if board_service["uuid"] == cloud_service._info["uuid"]:
service_list.append((cloud_service._info["uuid"],
_(cloud_service._info["name"])))
return {'uuid': board.uuid,
'name': board.name,
'service_list': service_list}
class AttachPortView(forms.ModalFormView):
template_name = 'iot/boards/attachport.html'
modal_header = _("Attach")
form_id = "attach_boardport_form"
form_class = project_forms.AttachPortForm
submit_label = _("Attach")
# submit_url = reverse_lazy("horizon:iot:boards:attachport")
submit_url = "horizon:iot:boards:attachport"
success_url = reverse_lazy('horizon:iot:boards:index')
page_title = _("Attach port")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.board_get(self.request,
self.kwargs['board_id'],
None)
except Exception:
redirect = reverse("horizon:iot:boards:index")
exceptions.handle(self.request,
_('Unable to get board information.'),
redirect=</