diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1539061
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+.tox
+.idea
+iotronic_ui.egg-info
+build
+*.pyc
+AUTHORS
+Authors
+ChangeLog
diff --git a/iotronic_ui.egg-info/PKG-INFO b/iotronic_ui.egg-info/PKG-INFO
deleted file mode 100644
index df40467..0000000
--- a/iotronic_ui.egg-info/PKG-INFO
+++ /dev/null
@@ -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
diff --git a/iotronic_ui.egg-info/SOURCES.txt b/iotronic_ui.egg-info/SOURCES.txt
deleted file mode 100644
index 1e94740..0000000
--- a/iotronic_ui.egg-info/SOURCES.txt
+++ /dev/null
@@ -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
\ No newline at end of file
diff --git a/iotronic_ui.egg-info/dependency_links.txt b/iotronic_ui.egg-info/dependency_links.txt
deleted file mode 100644
index 8b13789..0000000
--- a/iotronic_ui.egg-info/dependency_links.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/iotronic_ui.egg-info/not-zip-safe b/iotronic_ui.egg-info/not-zip-safe
deleted file mode 100644
index 8b13789..0000000
--- a/iotronic_ui.egg-info/not-zip-safe
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/iotronic_ui.egg-info/pbr.json b/iotronic_ui.egg-info/pbr.json
deleted file mode 100644
index 34d2e6e..0000000
--- a/iotronic_ui.egg-info/pbr.json
+++ /dev/null
@@ -1 +0,0 @@
-{"git_version": "4902c1d", "is_release": false}
\ No newline at end of file
diff --git a/iotronic_ui.egg-info/requires.txt b/iotronic_ui.egg-info/requires.txt
deleted file mode 100644
index 1725ef9..0000000
--- a/iotronic_ui.egg-info/requires.txt
+++ /dev/null
@@ -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
diff --git a/iotronic_ui.egg-info/top_level.txt b/iotronic_ui.egg-info/top_level.txt
deleted file mode 100644
index 7d4fe56..0000000
--- a/iotronic_ui.egg-info/top_level.txt
+++ /dev/null
@@ -1 +0,0 @@
-iotronic_ui
diff --git a/iotronic_ui/api/iotronic.py b/iotronic_ui/api/iotronic.py
index cf2c825..8957f5f 100644
--- a/iotronic_ui/api/iotronic.py
+++ b/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)
diff --git a/iotronic_ui/iot/boards/forms.py b/iotronic_ui/iot/boards/forms.py
index 8e4ba45..e128360 100644
--- a/iotronic_ui/iot/boards/forms.py
+++ b/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"])
- messages.success(request, _("Board created successfully."))
+ 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
diff --git a/iotronic_ui/iot/boards/panel.py b/iotronic_ui/iot/boards/panel.py
index beb3ef9..fd23096 100644
--- a/iotronic_ui/iot/boards/panel.py
+++ b/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)
diff --git a/iotronic_ui/iot/boards/tables.py b/iotronic_ui/iot/boards/tables.py
index c944caf..afee155 100644
--- a/iotronic_ui/iot/boards/tables.py
+++ b/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)
diff --git a/iotronic_ui/iot/boards/tabs.py b/iotronic_ui/iot/boards/tabs.py
index 07a5528..4bdef2b 100644
--- a/iotronic_ui/iot/boards/tabs.py
+++ b/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}
diff --git a/iotronic_ui/iot/boards/templates/boards/_attachport.html b/iotronic_ui/iot/boards/templates/boards/_attachport.html
new file mode 100644
index 0000000..0fc9d03
--- /dev/null
+++ b/iotronic_ui/iot/boards/templates/boards/_attachport.html
@@ -0,0 +1,8 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block modal-body-right %}
+
{% trans "Description:" %}
+ {% trans "Attach port to the selected board." %}
+{% endblock %}
+
diff --git a/iotronic_ui/iot/boards/templates/boards/_detachport.html b/iotronic_ui/iot/boards/templates/boards/_detachport.html
new file mode 100644
index 0000000..fe52c60
--- /dev/null
+++ b/iotronic_ui/iot/boards/templates/boards/_detachport.html
@@ -0,0 +1,8 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block modal-body-right %}
+ {% trans "Description:" %}
+ {% trans "Detach one or more attached ports from the board." %}
+{% endblock %}
+
diff --git a/iotronic_ui/iot/boards/templates/boards/_detail_overview.html b/iotronic_ui/iot/boards/templates/boards/_detail_overview.html
index 60afed2..f7e8e27 100644
--- a/iotronic_ui/iot/boards/templates/boards/_detail_overview.html
+++ b/iotronic_ui/iot/boards/templates/boards/_detail_overview.html
@@ -22,26 +22,50 @@
{{ board.mobile }}
{% trans "Extra" %}
{{ board.extra }}
- {% trans "Services" %}
- {% if services %}
+
+
+ {% trans "Ports" %}
+
+
+ {% if ports %}
+ {% for port in ports %}
+ - {{ port.VIF_name }}
+ - {{ port.ip }}
+ {% endfor %}
+ {% else %}
+ - --
+ {% endif %}
+
+
+ {% trans "Services" %}
+
+
+ {% if services %}
{% for service in services %}
- - {{ service.name }} [{{ service.protocol }}] {{ service.port }} --> {{ service.public_port }}
+ - {{ service.name }} [{{ service.protocol }}] {{ service.port }}
+ - {{ service.public_port }}
{% endfor %}
- {% else %}
+ {% else %}
- --
- {% endif %}
- - {% trans "Plugins" %}
- {% if plugins %}
- {% for plugin in plugins %}
- - {{ plugin.name }}
- {% endfor %}
- {% else %}
- - --
- {% endif %}
+ {% endif %}
+
+
+ {% trans "Plugins" %}
+
+
+ {% if plugins %}
+ {% for plugin in plugins %}
+ - {{ plugin.name }}
+ - {{ plugin.id }}
+ {% endfor %}
+ {% else %}
+ - --
+ {% endif %}
+
diff --git a/iotronic_ui/iot/boards/templates/boards/_disableservice.html b/iotronic_ui/iot/boards/templates/boards/_disableservice.html
new file mode 100644
index 0000000..21138ce
--- /dev/null
+++ b/iotronic_ui/iot/boards/templates/boards/_disableservice.html
@@ -0,0 +1,8 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block modal-body-right %}
+ {% trans "Description:" %}
+ {% trans "Disable service(s) on the selected board." %}
+{% endblock %}
+
diff --git a/iotronic_ui/iot/boards/templates/boards/_enableservice.html b/iotronic_ui/iot/boards/templates/boards/_enableservice.html
new file mode 100644
index 0000000..ec9e3be
--- /dev/null
+++ b/iotronic_ui/iot/boards/templates/boards/_enableservice.html
@@ -0,0 +1,8 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block modal-body-right %}
+ {% trans "Description:" %}
+ {% trans "Enable service(s) on the selected board." %}
+{% endblock %}
+
diff --git a/iotronic_ui/iot/services/templates/services/_remove.html b/iotronic_ui/iot/boards/templates/boards/_removeservices.html
similarity index 100%
rename from iotronic_ui/iot/services/templates/services/_remove.html
rename to iotronic_ui/iot/boards/templates/boards/_removeservices.html
diff --git a/iotronic_ui/iot/boards/templates/boards/attachport.html b/iotronic_ui/iot/boards/templates/boards/attachport.html
new file mode 100644
index 0000000..72b3c94
--- /dev/null
+++ b/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 %}
diff --git a/iotronic_ui/iot/boards/templates/boards/detachport.html b/iotronic_ui/iot/boards/templates/boards/detachport.html
new file mode 100644
index 0000000..aa2e4a1
--- /dev/null
+++ b/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 %}
diff --git a/iotronic_ui/iot/boards/templates/boards/disableservice.html b/iotronic_ui/iot/boards/templates/boards/disableservice.html
new file mode 100644
index 0000000..4280e56
--- /dev/null
+++ b/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 %}
diff --git a/iotronic_ui/iot/boards/templates/boards/enableservice.html b/iotronic_ui/iot/boards/templates/boards/enableservice.html
new file mode 100644
index 0000000..968caf4
--- /dev/null
+++ b/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 %}
diff --git a/iotronic_ui/iot/services/templates/services/remove.html b/iotronic_ui/iot/boards/templates/boards/removeservices.html
similarity index 72%
rename from iotronic_ui/iot/services/templates/services/remove.html
rename to iotronic_ui/iot/boards/templates/boards/removeservices.html
index d1addca..0c2f1a1 100644
--- a/iotronic_ui/iot/services/templates/services/remove.html
+++ b/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 %}
diff --git a/iotronic_ui/iot/boards/urls.py b/iotronic_ui/iot/boards/urls.py
index 7349a04..0348d95 100644
--- a/iotronic_ui/iot/boards/urls.py
+++ b/iotronic_ui/iot/boards/urls.py
@@ -22,6 +22,16 @@ urlpatterns = [
name='update'),
url(r'^(?P[^/]+)/removeplugins/$',
views.RemovePluginsView.as_view(), name='removeplugins'),
+ url(r'^(?P[^/]+)/removeservices/$',
+ views.RemoveServicesView.as_view(), name='removeservices'),
+ url(r'^(?P[^/]+)/enableservice/$',
+ views.EnableServiceView.as_view(), name='enableservice'),
+ url(r'^(?P[^/]+)/disableservice/$',
+ views.DisableServiceView.as_view(), name='disableservice'),
+ url(r'^(?P[^/]+)/attachport/$',
+ views.AttachPortView.as_view(), name='attachport'),
+ url(r'^(?P[^/]+)/detachport/$',
+ views.DetachPortView.as_view(), name='detachport'),
url(r'^(?P[^/]+)/detail/$', views.BoardDetailView.as_view(),
name='detail'),
]
diff --git a/iotronic_ui/iot/boards/views.py b/iotronic_ui/iot/boards/views.py
index df8e3af..de6a6bf 100644
--- a/iotronic_ui/iot/boards/views.py
+++ b/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=redirect)
+
+ def get_context_data(self, **kwargs):
+ context = super(AttachPortView, 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 networks
+ networks = api.neutron.network_list(self.request)
+ net_choices = []
+
+ for net in networks:
+ for subnet in net["subnets"]:
+ net_choices.append((net["id"] + ':' + subnet["id"],
+ _(net["name"] + ':' + subnet["name"])))
+
+ return {'uuid': board.uuid,
+ 'name': board.name,
+ 'networks_list': net_choices}
+
+
+class DetachPortView(forms.ModalFormView):
+ template_name = 'iot/boards/detachport.html'
+ modal_header = _("Detach")
+ form_id = "detach_boardport_form"
+ form_class = project_forms.DetachPortForm
+ submit_label = _("Detach")
+ # submit_url = reverse_lazy("horizon:iot:boards:detachport")
+ submit_url = "horizon:iot:boards:detachport"
+ success_url = reverse_lazy('horizon:iot:boards:index')
+ page_title = _("Detach 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=redirect)
+
+ def get_context_data(self, **kwargs):
+ context = super(DetachPortView, 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()
+
+ ports = api.iotronic.port_list(self.request, board.uuid)
+
+ # TO BE REMOVED (change it once the port_list per board is
+ # completed and tested !
+ # ################################################################
+ # LOG.debug("PORTS: %s", ports)
+
+ filtered_ports = []
+ for port in ports:
+ if port._info["board_uuid"] == board.uuid:
+ filtered_ports.append((port._info["uuid"],
+ _(port._info["ip"])))
+
+ ports = filtered_ports
+ # ################################################################
+
+ # Populate board ports
+ return {'uuid': board.uuid,
+ 'name': board.name,
+ 'ports': ports}
+
+
class RemovePluginsView(forms.ModalFormView):
template_name = 'iot/boards/removeplugins.html'
modal_header = _("Remove Plugins from board")
form_id = "remove_boardplugins_form"
form_class = project_forms.RemovePluginsForm
- submit_label = _("Remove Plugins from board")
+ submit_label = _("Remove")
# submit_url = reverse_lazy("horizon:iot:boards:removeplugins")
submit_url = "horizon:iot:boards:removeplugins"
success_url = reverse_lazy('horizon:iot:boards:index')
@@ -157,8 +360,9 @@ class RemovePluginsView(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,
@@ -176,49 +380,74 @@ class RemovePluginsView(forms.ModalFormView):
# Populate plugins
# TO BE DONE.....filter by available on this board!!!
- # plugins = iotronic.plugin_list(self.request, None, None)
- plugins = iotronic.plugins_on_board(self.request, board.uuid)
+ # plugins = api.iotronic.plugin_list(self.request, None, None)
+ plugins = api.iotronic.plugins_on_board(self.request, board.uuid)
- plugins.sort(key=lambda b: b.name)
+ plugins.sort(key=lambda b: b["name"])
plugin_list = []
for plugin in plugins:
- plugin_list.append((plugin.uuid, _(plugin.name)))
+ plugin_list.append((plugin["id"], _(plugin["name"])))
return {'uuid': board.uuid,
'name': board.name,
'plugin_list': plugin_list}
+class RemoveServicesView(forms.ModalFormView):
+ template_name = 'iot/boards/removeservices.html'
+ modal_header = _("Remove Services from board")
+ form_id = "remove_boardservices_form"
+ form_class = project_forms.RemoveServicesForm
+ submit_label = _("Remove")
+ # submit_url = reverse_lazy("horizon:iot:boards:removeservices")
+ submit_url = "horizon:iot:boards:removeservices"
+ success_url = reverse_lazy('horizon:iot:boards:index')
+ page_title = _("Remove Services from board")
+
+ @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(RemoveServicesView, 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 services
+ services = api.iotronic.services_on_board(self.request,
+ board.uuid,
+ True)
+ services.sort(key=lambda b: b["name"])
+
+ service_list = []
+ for service in services:
+ service_list.append((service["uuid"], _(service["name"])))
+
+ return {'uuid': board.uuid,
+ 'name': board.name,
+ 'service_list': service_list}
+
+
class DetailView(tabs.TabView):
- # FROM
- """
- tab_group_class = project_tabs.InstanceDetailTabs
- template_name = 'horizon/common/_detail.html'
- redirect_url = 'horizon:project:instances:index'
- page_title = "{{ instance.name|default:instance.id }}"
- image_url = 'horizon:project:images:images:detail'
- volume_url = 'horizon:project:volumes:volumes:detail'
- """
- # TO
tab_group_class = project_tabs.BoardDetailTabs
template_name = 'horizon/common/_detail.html'
page_title = "{{ board.name|default:board.uuid }}"
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
- # FROM
- """
- instance = self.get_data()
- if instance.image:
- instance.image_url = reverse(self.image_url,
- args=[instance.image['id']])
- instance.volume_url = self.volume_url
- context["instance"] = instance
- context["url"] = reverse(self.redirect_url)
- context["actions"] = self._get_actions(instance)
- """
- # TO
board = self.get_data()
context["board"] = board
context["url"] = reverse(self.redirect_url)
@@ -226,94 +455,38 @@ class DetailView(tabs.TabView):
return context
- # FROM
- """
- def _get_actions(self, instance):
- table = project_tables.InstancesTable(self.request)
- return table.render_row_actions(instance)
- """
- # TO
def _get_actions(self, board):
table = project_tables.BoardsTable(self.request)
return table.render_row_actions(board)
- # FROM
- """
- @memoized.memoized_method
- def get_data(self):
- instance_id = self.kwargs['instance_id']
-
- try:
- instance = api.nova.server_get(self.request, instance_id)
- except Exception:
- redirect = reverse(self.redirect_url)
- exceptions.handle(self.request,
- _('Unable to retrieve details for '
- 'instance "%s".') % instance_id,
- redirect=redirect)
- # Not all exception types handled above will result in a redirect.
- # Need to raise here just in case.
- raise exceptions.Http302(redirect)
-
- choices = project_tables.STATUS_DISPLAY_CHOICES
- instance.status_label = (
- filters.get_display_label(choices, instance.status))
-
- try:
- instance.volumes = api.nova.instance_volumes_list(self.request,
- instance_id)
- # Sort by device name
- instance.volumes.sort(key=lambda vol: vol.device)
- except Exception:
- msg = _('Unable to retrieve volume list for instance '
- '"%(name)s" (%(id)s).') % {'name': instance.name,
- 'id': instance_id}
- exceptions.handle(self.request, msg, ignore=True)
-
- try:
- instance.full_flavor = api.nova.flavor_get(
- self.request, instance.flavor["id"])
- except Exception:
- msg = _('Unable to retrieve flavor information for instance '
- '"%(name)s" (%(id)s).') % {'name': instance.name,
- 'id': instance_id}
- exceptions.handle(self.request, msg, ignore=True)
-
- try:
- instance.security_groups = api.network.server_security_groups(
- self.request, instance_id)
- except Exception:
- msg = _('Unable to retrieve security groups for instance '
- '"%(name)s" (%(id)s).') % {'name': instance.name,
- 'id': instance_id}
- exceptions.handle(self.request, msg, ignore=True)
-
- try:
- api.network.servers_update_addresses(self.request, [instance])
- except Exception:
- msg = _('Unable to retrieve IP addresses from Neutron for '
- 'instance "%(name)s" (%(id)s).') % {'name': instance.name,
- 'id': instance_id}
- exceptions.handle(self.request, msg, ignore=True)
-
- return instance
- """
-
- # TO
@memoized.memoized_method
def get_data(self):
board_id = self.kwargs['board_id']
try:
- board_services = []
- board_plugins = []
+ board_ports = []
- board = iotronic.board_get(self.request, board_id, None)
- board_services = iotronic.services_on_board(self.request, board_id, True)
+ board = api.iotronic.board_get(self.request, board_id, None)
+
+ # FIX this problem with the new APIs
+ # (remove the "if" clause with a better approach)
+ # #################################################################
+ ports = api.iotronic.port_list(self.request, board_id)
+
+ for port in ports:
+ if port._info["board_uuid"] == board_id:
+ board_ports.append(port._info)
+ board._info.update(dict(ports=board_ports))
+ # #################################################################
+
+ board_services = api.iotronic.services_on_board(self.request,
+ board_id, True)
board._info.update(dict(services=board_services))
- board_plugins = iotronic.plugins_on_board(self.request, board_id)
+ board_plugins = api.iotronic.plugins_on_board(self.request,
+ board_id)
board._info.update(dict(plugins=board_plugins))
+
# LOG.debug("BOARD: %s\n\n%s", board, board._info)
except Exception:
@@ -322,14 +495,6 @@ class DetailView(tabs.TabView):
exceptions.handle(self.request, msg, ignore=True)
return board
- # FROM
- """
- def get_tabs(self, request, *args, **kwargs):
- instance = self.get_data()
- return self.tab_group_class(request, instance=instance, **kwargs)
- """
-
- # TO
def get_tabs(self, request, *args, **kwargs):
board = self.get_data()
return self.tab_group_class(request, board=board, **kwargs)
diff --git a/iotronic_ui/iot/dashboard.py b/iotronic_ui/iot/dashboard.py
index 3660d9b..ed7ab1d 100644
--- a/iotronic_ui/iot/dashboard.py
+++ b/iotronic_ui/iot/dashboard.py
@@ -23,4 +23,5 @@ class Iot(horizon.Dashboard):
# Specify the slug of the dashboard's default panel.
default_panel = 'boards'
+
horizon.register(Iot)
diff --git a/iotronic_ui/iot/plugins/forms.py b/iotronic_ui/iot/plugins/forms.py
index 8ef14ba..5e9f3dd 100644
--- a/iotronic_ui/iot/plugins/forms.py
+++ b/iotronic_ui/iot/plugins/forms.py
@@ -68,18 +68,17 @@ class CreatePluginForm(forms.SelfHandlingForm):
data["parameters"] = json.loads(data["parameters"])
try:
- plugin = iotronic.plugin_create(request, data["name"],
- data["public"], data["callable"],
- data["code"], data["parameters"])
- LOG.debug("MELO API REQ: %s", request)
+ iotronic.plugin_create(request, data["name"],
+ data["public"], data["callable"],
+ data["code"], data["parameters"])
messages.success(request, _("Plugin created successfully."))
- return plugin
+ return True
# except iot_exceptions.ClientException:
except Exception:
- # LOG.debug("MELO API REQ EXC: %s", request)
- # LOG.debug("MELO API REQ (DICT): %s", exceptions.__dict__)
+ # LOG.debug("API REQ EXC: %s", request)
+ # LOG.debug("API REQ (DICT): %s", exceptions.__dict__)
exceptions.handle(request, _('Unable to create plugin.'))
@@ -97,7 +96,7 @@ class InjectPluginForm(forms.SelfHandlingForm):
board_list = forms.MultipleChoiceField(
label=_("Boards List"),
widget=forms.SelectMultiple(
- attrs={'class': 'switchable', 'data-slug': 'slug-inject-boards'}),
+ attrs={'class': 'switchable', 'data-slug': 'slug-inject-plugin'}),
help_text=_("Select boards in this pool ")
)
@@ -120,19 +119,18 @@ class InjectPluginForm(forms.SelfHandlingForm):
if key == board:
try:
- plugin = None
- plugin = iotronic.plugin_inject(request, key,
+ inject = iotronic.plugin_inject(request, key,
data["uuid"],
data["onboot"])
- # LOG.debug("MELO API: %s %s", plugin, request)
- message_text = "Plugin injected successfully on " \
- "board " + str(value) + "."
+ # LOG.debug("API: %s %s", plugin, request)
+ message_text = inject
messages.success(request, _(message_text))
if counter != len(data["board_list"]) - 1:
counter += 1
else:
- return plugin
+ return True
+
except Exception:
message_text = "Unable to inject plugin on board " \
+ str(value) + "."
@@ -191,20 +189,19 @@ class StartPluginForm(forms.SelfHandlingForm):
if key == board:
try:
- plugin = None
- plugin = iotronic.plugin_action(request, key,
+ action = iotronic.plugin_action(request, key,
data["uuid"],
"PluginStart",
data["parameters"])
- # LOG.debug("MELO API: %s %s", plugin, request)
- message_text = "Plugin started successfully on board "\
- + str(value) + "."
+ # LOG.debug("API: %s %s", plugin, request)
+ message_text = action
messages.success(request, _(message_text))
if counter != len(data["board_list"]) - 1:
counter += 1
else:
- return plugin
+ return True
+
except Exception:
message_text = "Unable to start plugin on board " \
+ str(value) + "."
@@ -259,20 +256,19 @@ class StopPluginForm(forms.SelfHandlingForm):
if key == board:
try:
- plugin = None
- plugin = iotronic.plugin_action(request, key,
+ action = iotronic.plugin_action(request, key,
data["uuid"],
"PluginStop",
data["delay"])
- # LOG.debug("MELO API: %s %s", plugin, request)
- message_text = "Plugin stopped successfully on board "\
- + str(value) + "."
+ # LOG.debug("API: %s %s", plugin, request)
+ message_text = action
messages.success(request, _(message_text))
if counter != len(data["board_list"]) - 1:
counter += 1
else:
- return plugin
+ return True
+
except Exception:
message_text = "Unable to stop plugin on board " \
+ str(value) + "."
@@ -330,20 +326,19 @@ class CallPluginForm(forms.SelfHandlingForm):
if key == board:
try:
- plugin = None
- plugin = iotronic.plugin_action(request, key,
+ action = iotronic.plugin_action(request, key,
data["uuid"],
"PluginCall",
data["parameters"])
- # LOG.debug("MELO API: %s %s", plugin, request)
- message_text = "Plugin called successfully on board " \
- + str(value) + "."
+
+ message_text = action
messages.success(request, _(message_text))
if counter != len(data["board_list"]) - 1:
- counter += 2
+ counter += 1
else:
- return plugin
+ return True
+
except Exception:
message_text = "Unable to call plugin on board " \
+ str(value) + "."
@@ -387,10 +382,10 @@ class RemovePluginForm(forms.SelfHandlingForm):
if key == board:
try:
- plugin = None
- plugin = iotronic.plugin_remove(request, key,
- data["uuid"])
- # LOG.debug("MELO API: %s %s", plugin, request)
+ iotronic.plugin_remove(request,
+ key,
+ data["uuid"])
+ # LOG.debug("API: %s %s", plugin, request)
message_text = "Plugin removed successfully from" \
+ " board " + str(value) + "."
messages.success(request, _(message_text))
@@ -398,7 +393,8 @@ class RemovePluginForm(forms.SelfHandlingForm):
if counter != len(data["board_list"]) - 1:
counter += 1
else:
- return plugin
+ return True
+
except Exception:
message_text = "Unable to remove plugin from board " \
+ str(value) + "."
@@ -411,34 +407,7 @@ class UpdatePluginForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Plugin ID"), widget=forms.HiddenInput)
owner = forms.CharField(label=_("Owner"), widget=forms.HiddenInput)
-
- """
name = forms.CharField(label=_("Plugin Name"))
- public = forms.ChoiceField(label=_("Public"))
- callable = forms.ChoiceField(label=_("Callable"))
- code = forms.CharField(label=_("Code"))
- """
-
- name = forms.CharField(label=_("Plugin Name"))
-
- """
- public = forms.ChoiceField(
- label=_("Public"),
- choices =[('false', _('False')), ('true', _('True'))],
- widget=forms.Select(
- attrs={'class': 'switchable', 'data-slug': 'slug-public'},
- )
- )
-
-
- callable = forms.ChoiceField(
- label=_("Callable"),
- choices =[('false', _('False')), ('true', _('True'))],
- widget=forms.Select(
- attrs={'class': 'switchable', 'data-slug': 'slug-callable'},
- )
- )
- """
public = forms.BooleanField(label=_("Public"), required=False)
callable = forms.BooleanField(label=_("Callable"), required=False)
@@ -454,16 +423,16 @@ class UpdatePluginForm(forms.SelfHandlingForm):
# Admin
if policy.check((("iot", "iot:update_plugins"),), self.request):
- # LOG.debug("MELO ADMIN")
+ # LOG.debug("ADMIN")
pass
# Admin_iot_project
elif policy.check((("iot", "iot:update_project_plugins"),),
self.request):
- # LOG.debug("MELO IOT ADMIN")
+ # LOG.debug("IOT ADMIN")
if self.request.user.id != kwargs["initial"]["owner"]:
- # LOG.debug("MELO NO-edit IOT ADMIN")
+ # LOG.debug("NO-edit IOT ADMIN")
self.fields["name"].widget.attrs = {'readonly': 'readonly'}
self.fields["public"].widget.attrs = {'disabled': 'disabled'}
self.fields["callable"].widget.attrs = {'disabled': 'disabled'}
@@ -472,7 +441,7 @@ class UpdatePluginForm(forms.SelfHandlingForm):
# 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["public"].widget.attrs = {'disabled': 'disabled'}
self.fields["callable"].widget.attrs = {'disabled': 'disabled'}
@@ -481,7 +450,6 @@ class UpdatePluginForm(forms.SelfHandlingForm):
def handle(self, request, data):
try:
- # LOG.debug("MELO DATA: %s", data)
data["code"] = cPickle.dumps(str(data["code"]))
iotronic.plugin_update(request, data["uuid"],
@@ -489,7 +457,10 @@ class UpdatePluginForm(forms.SelfHandlingForm):
"public": data["public"],
"callable": data["callable"],
"code": data["code"]})
- messages.success(request, _("Plugin updated successfully."))
+
+ messages.success(request, _("Plugin " + str(data["name"]) +
+ " updated successfully."))
return True
+
except Exception:
exceptions.handle(request, _('Unable to update plugin.'))
diff --git a/iotronic_ui/iot/plugins/panel.py b/iotronic_ui/iot/plugins/panel.py
index a099a3d..2625c5d 100644
--- a/iotronic_ui/iot/plugins/panel.py
+++ b/iotronic_ui/iot/plugins/panel.py
@@ -14,9 +14,14 @@ from django.utils.translation import ugettext_lazy as _
import horizon
+from iotronic_ui.iot import dashboard
+
class Plugins(horizon.Panel):
name = _("Plugins")
slug = "plugins"
# policy_rules = (("iot", "iot:list_all_plugins"),
# ("iot", "iot:list_project_plugins"))
+
+
+dashboard.Iot.register(Plugins)
diff --git a/iotronic_ui/iot/plugins/tables.py b/iotronic_ui/iot/plugins/tables.py
index 464ec46..362d7d6 100644
--- a/iotronic_ui/iot/plugins/tables.py
+++ b/iotronic_ui/iot/plugins/tables.py
@@ -28,7 +28,7 @@ class CreatePluginLink(tables.LinkAction):
url = "horizon:iot:plugins:create"
classes = ("ajax-modal",)
icon = "plus"
- # policy_rules = (("iot", "iot:create_board"),)
+ # policy_rules = (("iot", "iot:create_plugin"),)
class EditPluginLink(tables.LinkAction):
@@ -37,12 +37,12 @@ class EditPluginLink(tables.LinkAction):
url = "horizon:iot:plugins:update"
classes = ("ajax-modal",)
icon = "pencil"
- # policy_rules = (("iot", "iot:update_board"),)
+ # policy_rules = (("iot", "iot:update_plugin"),)
"""
def allowed(self, request, plugin):
- # LOG.debug("MELO ALLOWED: %s %s %s", self, request, plugin)
- # LOG.debug("MELO user: %s", request.user.id)
+ # LOG.debug("ALLOWED: %s %s %s", self, request, plugin)
+ # LOG.debug("user: %s", request.user.id)
return True
"""
@@ -54,7 +54,7 @@ class InjectPluginLink(tables.LinkAction):
url = "horizon:iot:plugins:inject"
classes = ("ajax-modal",)
icon = "plus"
- # policy_rules = (("iot", "iot:create_board"),)
+ # policy_rules = (("iot", "iot:inject_plugin"),)
class StartPluginLink(tables.LinkAction):
@@ -63,7 +63,7 @@ class StartPluginLink(tables.LinkAction):
url = "horizon:iot:plugins:start"
classes = ("ajax-modal",)
icon = "plus"
- # policy_rules = (("iot", "iot:create_board"),)
+ # policy_rules = (("iot", "iot:start_plugin"),)
class StopPluginLink(tables.LinkAction):
@@ -72,7 +72,7 @@ class StopPluginLink(tables.LinkAction):
url = "horizon:iot:plugins:stop"
classes = ("ajax-modal",)
icon = "plus"
- # policy_rules = (("iot", "iot:create_board"),)
+ # policy_rules = (("iot", "iot:stop_plugin"),)
class CallPluginLink(tables.LinkAction):
@@ -81,7 +81,7 @@ class CallPluginLink(tables.LinkAction):
url = "horizon:iot:plugins:call"
classes = ("ajax-modal",)
icon = "plus"
- # policy_rules = (("iot", "iot:create_board"),)
+ # policy_rules = (("iot", "iot:call_plugin"),)
class RemovePluginLink(tables.LinkAction):
@@ -90,7 +90,7 @@ class RemovePluginLink(tables.LinkAction):
url = "horizon:iot:plugins:remove"
classes = ("ajax-modal",)
icon = "plus"
- # policy_rules = (("iot", "iot:create_board"),)
+ # policy_rules = (("iot", "iot:remove_plugin"),)
class DeletePluginsAction(tables.DeleteAction):
@@ -109,7 +109,7 @@ class DeletePluginsAction(tables.DeleteAction):
u"Deleted Plugins",
count
)
- # policy_rules = (("iot", "iot:delete_board"),)
+ # policy_rules = (("iot", "iot:delete_plugin"),)
"""
def allowed(self, request, role):
@@ -140,14 +140,14 @@ class PluginsTable(tables.DataTable):
# Overriding get_object_id method because in IoT service the "id" is
# identified by the field UUID
def get_object_id(self, datum):
- # LOG.debug("MELO datum %s", datum)
+ # LOG.debug("datum %s", datum)
return datum.uuid
# Overriding get_row_actions method because we need to discriminate
# between Sync and Async plugins
def get_row_actions(self, datum):
actions = super(PluginsTable, self).get_row_actions(datum)
- # LOG.debug("MELO ACTIONS: %s %s", actions[0].name, datum.name)
+ # LOG.debug("ACTIONS: %s %s", actions[0].name, datum.name)
selected_row_actions = []
diff --git a/iotronic_ui/iot/plugins/urls.py b/iotronic_ui/iot/plugins/urls.py
index 1894504..90a3d03 100644
--- a/iotronic_ui/iot/plugins/urls.py
+++ b/iotronic_ui/iot/plugins/urls.py
@@ -18,6 +18,8 @@ from iotronic_ui.iot.plugins import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^create/$', views.CreateView.as_view(), name='create'),
+ url(r'^(?P[^/]+)/update/$', views.UpdateView.as_view(),
+ name='update'),
url(r'^(?P[^/]+)/inject/$', views.InjectView.as_view(),
name='inject'),
url(r'^(?P[^/]+)/start/$', views.StartView.as_view(),
@@ -28,8 +30,6 @@ urlpatterns = [
name='call'),
url(r'^(?P[^/]+)/remove/$', views.RemoveView.as_view(),
name='remove'),
- url(r'^(?P[^/]+)/update/$', views.UpdateView.as_view(),
- name='update'),
url(r'^(?P[^/]+)/detail/$', views.PluginDetailView.as_view(),
name='detail'),
]
diff --git a/iotronic_ui/iot/plugins/views.py b/iotronic_ui/iot/plugins/views.py
index 1cb3f13..093acb8 100644
--- a/iotronic_ui/iot/plugins/views.py
+++ b/iotronic_ui/iot/plugins/views.py
@@ -67,13 +67,6 @@ class IndexView(tables.DataTableView):
# Other users
else:
- # FROM
- """
- msg = _("Insufficient privilege level to view
- plugins information.")
- messages.info(self.request, msg)
- """
- # TO
try:
plugins = iotronic.plugin_list(self.request, None, None,
with_public=True)
diff --git a/iotronic_ui/iot/services/forms.py b/iotronic_ui/iot/services/forms.py
index c8297c3..f3fa65f 100644
--- a/iotronic_ui/iot/services/forms.py
+++ b/iotronic_ui/iot/services/forms.py
@@ -41,17 +41,18 @@ class CreateServiceForm(forms.SelfHandlingForm):
def handle(self, request, data):
try:
- # LOG.error("DATA: %s", data)
- service = iotronic.service_create(request, data["name"],
- data["port"], data["protocol"])
- messages.success(request, _("Service created successfully."))
+ iotronic.service_create(request, data["name"],
+ data["port"], data["protocol"])
+
+ messages.success(request, _("Service " + str(data["name"]) +
+ " created successfully."))
+ return True
- return service
except Exception:
exceptions.handle(request, _('Unable to create service.'))
-class UpdateBoardForm(forms.SelfHandlingForm):
+class UpdateServiceForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Service ID"), widget=forms.HiddenInput)
name = forms.CharField(label=_("Service Name"))
port = forms.IntegerField(label=_("Port"))
@@ -65,23 +66,23 @@ class UpdateBoardForm(forms.SelfHandlingForm):
def __init__(self, *args, **kwargs):
- super(UpdateBoardForm, self).__init__(*args, **kwargs)
+ super(UpdateServiceForm, self).__init__(*args, **kwargs)
# Admin
if policy.check((("iot", "iot:update_services"),), 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["port"].widget.attrs = {'readonly': 'readonly'}
self.fields["protocol"].widget.attrs = {'readonly': 'readonly'}
@@ -89,12 +90,13 @@ class UpdateBoardForm(forms.SelfHandlingForm):
def handle(self, request, data):
try:
iotronic.service_update(request, data["uuid"],
- {"name": data["name"],
- "port": data["port"],
- "protocol": data["protocol"]})
+ {"name": data["name"],
+ "port": data["port"],
+ "protocol": data["protocol"]})
messages.success(request, _("Service updated successfully."))
return True
+
except Exception:
exceptions.handle(request, _('Unable to update service.'))
@@ -117,7 +119,9 @@ class ServiceActionForm(forms.SelfHandlingForm):
action = forms.ChoiceField(
label=_("Action"),
- choices=[('ServiceEnable', _('Enable')), ('ServiceDisable', _('Disable')), ('ServiceRestore', _('Restore'))],
+ choices=[('ServiceEnable', _('Enable')),
+ ('ServiceDisable', _('Disable')),
+ ('ServiceRestore', _('Restore'))],
widget=forms.Select(
attrs={'class': 'switchable', 'data-slug': 'slug-action'},
)
@@ -128,10 +132,7 @@ class ServiceActionForm(forms.SelfHandlingForm):
super(ServiceActionForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
- boardslist_length = len(kwargs["initial"]["board_list"])
-
self.fields["board_list"].choices = kwargs["initial"]["board_list"]
- # self.fields["board_list"].max_length = boardslist_length
def handle(self, request, data):
@@ -142,60 +143,20 @@ class ServiceActionForm(forms.SelfHandlingForm):
if key == board:
try:
- action = None
action = iotronic.service_action(request, key,
- data["uuid"],
- data["action"])
-
- message_text = "Action executed successfully on " \
- "board " + str(value) + "."
+ data["uuid"],
+ data["action"])
+ message_text = action
messages.success(request, _(message_text))
if counter != len(data["board_list"]) - 1:
counter += 1
else:
- return action
+ return True
+
except Exception:
message_text = "Unable to execute action on board " \
+ str(value) + "."
exceptions.handle(request, _(message_text))
break
-
-
-class RemoveServicesForm(forms.SelfHandlingForm):
-
- uuid = forms.CharField(label=_("Service ID"), widget=forms.HiddenInput)
-
- name = forms.CharField(
- label=_('Service Name'),
- widget=forms.TextInput(attrs={'readonly': 'readonly'})
- )
- port = forms.IntegerField(
- label=_("Port"),
- widget=forms.TextInput(attrs={'readonly': 'readonly'})
- )
-
- protocol = forms.ChoiceField(
- label=_("Protocol"),
- choices=[('TCP', _('TCP')), ('UDP', _('UDP'))],
- widget=forms.TextInput(attrs={'readonly': 'readonly'})
- )
-
- def __init__(self, *args, **kwargs):
-
- super(RemoveServicesForm, self).__init__(*args, **kwargs)
- # input=kwargs.get('initial',{})
-
-
- def handle(self, request, data):
-
- try:
- message_text = "Service "+str(data["name"])+" deleted successfully."
-
- iotronic.service_delete(request, data["uuid"])
- messages.success(request, _(message_text))
- return True
- except Exception:
- message_text = "Unable to delete service "+str(data["name"])+"."
- exceptions.handle(request, _(message_text))
diff --git a/iotronic_ui/iot/services/panel.py b/iotronic_ui/iot/services/panel.py
index aa531a0..9f52117 100644
--- a/iotronic_ui/iot/services/panel.py
+++ b/iotronic_ui/iot/services/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 Services(horizon.Panel):
@@ -23,3 +24,5 @@ class Services(horizon.Panel):
permissions = ('openstack.services.iot', )
# policy_rules = (("iot", "iot:list_all_services"),)
+
+dashboard.Iot.register(Services)
diff --git a/iotronic_ui/iot/services/tables.py b/iotronic_ui/iot/services/tables.py
index d4efc26..abe7cd9 100644
--- a/iotronic_ui/iot/services/tables.py
+++ b/iotronic_ui/iot/services/tables.py
@@ -22,7 +22,6 @@ from openstack_dashboard import api
LOG = logging.getLogger(__name__)
-
class CreateServiceLink(tables.LinkAction):
name = "create"
verbose_name = _("Create Service")
@@ -32,7 +31,7 @@ class CreateServiceLink(tables.LinkAction):
# policy_rules = (("iot", "iot:create_service"),)
-class EditBoardLink(tables.LinkAction):
+class EditServiceLink(tables.LinkAction):
name = "edit"
verbose_name = _("Edit")
url = "horizon:iot:services:update"
@@ -41,17 +40,6 @@ class EditBoardLink(tables.LinkAction):
# policy_rules = (("iot", "iot:update_service"),)
-"""
-class RemoveServicesLink(tables.LinkAction):
- name = "remove"
- verbose_name = _("Remove Service(s)")
- url = "horizon:iot:services:remove"
- classes = ("ajax-modal",)
- icon = "plus"
- # policy_rules = (("iot", "iot:delete_service"),)
-"""
-
-
class ActionServiceLink(tables.LinkAction):
name = "action"
verbose_name = _("Service Action")
@@ -106,11 +94,7 @@ class ServicesTable(tables.DataTable):
class Meta(object):
name = "services"
verbose_name = _("services")
- row_actions = (EditBoardLink, ActionServiceLink,
+ row_actions = (EditServiceLink, ActionServiceLink,
DeleteServicesAction)
table_actions = (ServiceFilterAction, CreateServiceLink,
- DeleteServicesAction)
-
- # row_actions = (EditBoardLink, RemovePluginsLink, DeleteBoardsAction)
- # table_actions = (BoardFilterAction, CreateBoardLink,
- # DeleteBoardsAction)
+ DeleteServicesAction)
diff --git a/iotronic_ui/iot/services/urls.py b/iotronic_ui/iot/services/urls.py
index b748942..fd61ed0 100644
--- a/iotronic_ui/iot/services/urls.py
+++ b/iotronic_ui/iot/services/urls.py
@@ -22,8 +22,6 @@ urlpatterns = [
name='update'),
url(r'^(?P[^/]+)/action/$', views.ActionView.as_view(),
name='action'),
- url(r'^(?P[^/]+)/remove/$',
- views.RemoveServicesView.as_view(), name='remove'),
url(r'^(?P[^/]+)/detail/$', views.ServiceDetailView.as_view(),
name='detail'),
]
diff --git a/iotronic_ui/iot/services/views.py b/iotronic_ui/iot/services/views.py
index b17a0f3..afc31cf 100644
--- a/iotronic_ui/iot/services/views.py
+++ b/iotronic_ui/iot/services/views.py
@@ -52,7 +52,8 @@ class IndexView(tables.DataTableView):
_('Unable to retrieve services list.'))
# Admin_iot_project
- elif policy.check((("iot", "iot:list_project_services"),), self.request):
+ elif policy.check((("iot", "iot:list_project_services"),),
+ self.request):
try:
services = iotronic.service_list(self.request, None)
@@ -87,7 +88,7 @@ class UpdateView(forms.ModalFormView):
template_name = 'iot/services/update.html'
modal_header = _("Update Service")
form_id = "update_service_form"
- form_class = project_forms.UpdateBoardForm
+ form_class = project_forms.UpdateServiceForm
submit_label = _("Update Service")
submit_url = "horizon:iot:services:update"
success_url = reverse_lazy('horizon:iot:services:index')
@@ -96,8 +97,9 @@ class UpdateView(forms.ModalFormView):
@memoized.memoized_method
def get_object(self):
try:
- return iotronic.service_get(self.request, self.kwargs['service_id'],
- None)
+ return iotronic.service_get(self.request,
+ self.kwargs['service_id'],
+ None)
except Exception:
redirect = reverse("horizon:iot:services:index")
exceptions.handle(self.request,
@@ -133,8 +135,9 @@ class ActionView(forms.ModalFormView):
@memoized.memoized_method
def get_object(self):
try:
- return iotronic.service_get(self.request, self.kwargs['service_id'],
- None)
+ return iotronic.service_get(self.request,
+ self.kwargs['service_id'],
+ None)
except Exception:
redirect = reverse("horizon:iot:services:index")
exceptions.handle(self.request,
@@ -163,43 +166,6 @@ class ActionView(forms.ModalFormView):
'board_list': board_list}
-class RemoveServicesView(forms.ModalFormView):
- template_name = 'iot/services/remove.html'
- modal_header = _("Remove Service")
- form_id = "remove_service_form"
- form_class = project_forms.RemoveServicesForm
- submit_label = _("Remove Service")
- # submit_url = reverse_lazy("horizon:iot:boards:removeplugins")
- submit_url = "horizon:iot:services:remove"
- success_url = reverse_lazy('horizon:iot:services:index')
- page_title = _("Remove Service")
-
- @memoized.memoized_method
- def get_object(self):
- try:
- return iotronic.service_get(self.request, self.kwargs['service_id'],
- None)
- except Exception:
- redirect = reverse("horizon:iot:services:index")
- exceptions.handle(self.request,
- _('Unable to get service information.'),
- redirect=redirect)
-
- def get_context_data(self, **kwargs):
- context = super(RemoveServicesView, 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):
- service = self.get_object()
-
- return {'uuid': service.uuid,
- 'name': service.name,
- 'port': service.port,
- 'protocol': service.protocol}
-
-
class DetailView(tabs.TabView):
tab_group_class = project_tabs.ServiceDetailTabs
template_name = 'horizon/common/_detail.html'
@@ -224,8 +190,8 @@ class DetailView(tabs.TabView):
try:
service = iotronic.service_get(self.request, service_id, None)
except Exception:
- msg = ('Unable to retrieve service %s information') % {'name':
- service.name}
+ s = service.name
+ msg = ('Unable to retrieve service %s information') % {'name': s}
exceptions.handle(self.request, msg, ignore=True)
return service
diff --git a/iotronic_ui/iot/static/iot/images/blue-circle.png b/iotronic_ui/iot/static/iot/images/blue-circle.png
deleted file mode 100644
index 3e1f389..0000000
Binary files a/iotronic_ui/iot/static/iot/images/blue-circle.png and /dev/null differ
diff --git a/iotronic_ui/iot/static/iot/images/green-circle.png b/iotronic_ui/iot/static/iot/images/green-circle.png
deleted file mode 100644
index f639e78..0000000
Binary files a/iotronic_ui/iot/static/iot/images/green-circle.png and /dev/null differ
diff --git a/iotronic_ui/iot/static/iot/images/marker-icon-green.png b/iotronic_ui/iot/static/iot/images/marker-icon-green.png
deleted file mode 100644
index 56db5ea..0000000
Binary files a/iotronic_ui/iot/static/iot/images/marker-icon-green.png and /dev/null differ
diff --git a/iotronic_ui/iot/static/iot/images/marker-icon-red.png b/iotronic_ui/iot/static/iot/images/marker-icon-red.png
deleted file mode 100644
index 3165a31..0000000
Binary files a/iotronic_ui/iot/static/iot/images/marker-icon-red.png and /dev/null differ
diff --git a/iotronic_ui/iot/static/iot/images/marker-icon.png b/iotronic_ui/iot/static/iot/images/marker-icon.png
deleted file mode 100644
index e2e9f75..0000000
Binary files a/iotronic_ui/iot/static/iot/images/marker-icon.png and /dev/null differ
diff --git a/iotronic_ui/iot/static/iot/images/marker-shadow.png b/iotronic_ui/iot/static/iot/images/marker-shadow.png
deleted file mode 100644
index d1e773c..0000000
Binary files a/iotronic_ui/iot/static/iot/images/marker-shadow.png and /dev/null differ
diff --git a/iotronic_ui/iot/static/iot/images/red-circle.png b/iotronic_ui/iot/static/iot/images/red-circle.png
deleted file mode 100644
index bb3bbdf..0000000
Binary files a/iotronic_ui/iot/static/iot/images/red-circle.png and /dev/null differ
diff --git a/iotronic_ui/iot/static/iot/js/iot.js b/iotronic_ui/iot/static/iot/js/iot.js
deleted file mode 100644
index 97e3b8d..0000000
--- a/iotronic_ui/iot/static/iot/js/iot.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/* Additional JavaScript for iot. */
-
-//alert('MELO');
-
-//var image_url = 'https://ing-res-17.me.trigrid.it/iotronic/';
-var images_url = 'http://'+location.host+'/dashboard/static/iot/images/';
-
-var markers = [];
-markers = L.markerClusterGroup({
- spiderfyOnMaxZoom: false,
- disableClusteringAtZoom: 17
-});
-
-
-var marker_red = L.icon({
- iconUrl: images_url+'marker-icon-red.png',
- iconAnchor:[12.5, 41],
- shadowUrl: images_url+'marker-shadow.png'
-});
-
-
-var marker_green = L.icon({
- iconUrl: images_url+'marker-icon-green.png',
- iconAnchor:[12.5, 41],
- shadowUrl: images_url+'marker-shadow.png'
-});
-
-
-var marker_blue = L.icon({
- iconUrl: images_url+'marker-icon.png',
- iconAnchor:[12.5, 41],
- shadowUrl: images_url+'marker-shadow.png'
-});
-
-
-var labels = [];
-var latitude = [];
-var longitude = [];
-var altitude = [];
-var statuses = [];
-var last_update = [];
-
-
-function render_map(map_id, coordinates){
- var osmUrl='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
- var osm = new L.TileLayer(osmUrl, {});
-
- var lat = 38.20523;
- var lon = 15.55972;
- if(coordinates["coordinates"].length ==1){
- lat = coordinates["coordinates"][0].lat;
- lon = coordinates["coordinates"][0].lon;
- }
- var map = L.map(map_id, {scrollWheelZoom:false, worldCopyJump: true}).setView([lat, lon], 12);
- map.addLayer(osm);
-
- //Copyright
- L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
- attribution: '© OpenStreetMap - by MDSLab'
- }).addTo(map);
-
- //var marker = L.marker([lat, lon]);
- //marker.setIcon(marker_red);
- coord = coordinates["coordinates"];
- for(var i=0;i';
- if(statuses[sel] == "online")
- img = '
';
- if(statuses[sel] == "offline")
- img = '
';
-
- var open_popup = '';
-
- var default_popup = '
'+img +' '+labels[sel]+'
' +
- ''+last_update[sel]+'
'+
- 'Latitude: '+latitude[sel]+ '
' +
- 'Longitude: '+longitude[sel]+'
' +
- 'Altitude: '+altitude[sel]+'
';
-
- global_popup = open_popup + default_popup +"";
- var popup = L.popup().setLatLng(e.latlng).setContent(global_popup).openOn(map);
- });
- markers.addLayer(marker);
- }
- map.addLayer(markers);
- //return map;
-}
-
-
-
-function choose_marker(status){
- if(status=="online") return marker_green;
- else if(status =="offline") return marker_red;
- else return marker_blue;
-}
diff --git a/iotronic_ui/iot/static/iot/scss/iot.scss b/iotronic_ui/iot/static/iot/scss/iot.scss
deleted file mode 100644
index e1bd25d..0000000
--- a/iotronic_ui/iot/static/iot/scss/iot.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-/* Additional SCSS for {{ dash_name }}. */
-
-/*
-#mapdiv {
- min-height: 300px;
-}
-*/