Upgraded to Iotronic 0.5.0 functions.

Change-Id: Iabd1863e3d0c541f33644c808cf57a631d24ae27
This commit is contained in:
Nicola Peditto 2021-11-24 16:52:30 +01:00
parent 60acb5cfbb
commit e8db63a870
117 changed files with 5658 additions and 199 deletions

View File

@ -1,17 +1,18 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# http://www.apache.org/licenses/LICENSE-2.0
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# from collections import OrderedDict
# import threading
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
from iotronicclient import client as iotronic_client
# from django.conf import settings
@ -71,6 +72,44 @@ def board_delete(request, board_id):
iotronicclient(request).board.delete(board_id)
# DEVICE MANAGEMENT
def device_list(request, status=None, detail=None, project=None):
"""List devices."""
return iotronicclient(request).board.list(status, detail, project)
def device_get(request, device_id, fields):
"""Get device info."""
return iotronicclient(request).board.get(device_id, fields)
def device_create(request, code, mobile, location, type, name):
"""Create device."""
params = {"code": code,
"mobile": mobile,
"location": location,
"type": type,
"name": name}
iotronicclient(request).board.create(**params)
def device_update(request, device_id, patch):
"""Update device."""
iotronicclient(request).board.update(device_id, patch)
def device_delete(request, device_id):
"""Delete device."""
iotronicclient(request).board.delete(device_id)
def device_action(request, device_id, action, parameters):
"""Action on device."""
return iotronicclient(request).board.board_action(device_id,
action,
parameters)
# PLUGIN MANAGEMENT (Cloud Side)
def plugin_list(request, detail=None, project=None, with_public=False,
all_plugins=False):
@ -107,22 +146,22 @@ def plugin_delete(request, plugin_id):
# PLUGIN MANAGEMENT (Board Side)
def plugin_inject(request, board_id, plugin_id, onboot):
"""Inject plugin on board(s)."""
return iotronicclient(request).plugin_injection.plugin_inject(board_id,
def plugin_inject(request, device_id, plugin_id, onboot):
"""Inject plugin on device."""
return iotronicclient(request).plugin_injection.plugin_inject(device_id,
plugin_id,
onboot)
def plugin_action(request, board_id, plugin_id, action, params={}):
"""Start/Stop/Call actions on board(s)."""
def plugin_action(request, device_id, plugin_id, action, params={}):
"""Start/Stop/Call actions on device."""
return iotronicclient(request).plugin_injection.plugin_action(
board_id, plugin_id, action, params)
device_id, plugin_id, action, params)
def plugin_remove(request, board_id, plugin_id):
"""Remove plugin from board."""
iotronicclient(request).plugin_injection.plugin_remove(board_id,
def plugin_remove(request, device_id, plugin_id):
"""Remove plugin from device."""
iotronicclient(request).plugin_injection.plugin_remove(device_id,
plugin_id)
@ -142,6 +181,27 @@ def plugins_on_board(request, board_id):
return detailed_plugins
def plugins_on_device(request, device_id):
"""Plugins on device."""
plugins = iotronicclient(request).plugin_injection.plugins_on_board(
device_id)
detailed_plugins = []
fields = {"name", "public", "callable"}
# fields = {"name"}
for plugin in plugins:
details = iotronicclient(request).plugin.get(plugin.plugin, fields)
details._info[u"uuid"] = plugin.plugin
"""
detailed_plugins.append({"name": details._info["name"],
"public": details._info["public"],
"callable": details._info["callable"],
"uuid": plugin.plugin})
"""
detailed_plugins.append(details)
return detailed_plugins
# SERVICE MANAGEMENT
def service_list(request, detail=None):
"""List services."""
@ -197,34 +257,60 @@ def services_on_board(request, board_id, detail=False):
return services
def service_action(request, board_id, service_id, action):
def services_on_device(request, device_id, detail=False):
"""List services on device."""
services = iotronicclient(request).exposed_service.services_on_board(
device_id)
if detail:
detailed_services = []
fields = {"name", "port", "protocol"}
for service in services:
details = iotronicclient(request).service.get(
service._info["service"], fields)
detailed_services.append({"uuid": service._info["service"],
"name": details._info["name"],
"public_port":
service._info["public_port"],
"port": details._info["port"],
"protocol": details._info["protocol"]})
return detailed_services
else:
return services
def service_action(request, device_id, service_id, action):
"""Action on service."""
return iotronicclient(request).exposed_service.service_action(board_id,
return iotronicclient(request).exposed_service.service_action(device_id,
service_id,
action)
def restore_services(request, board_id):
def restore_services(request, device_id):
"""Restore services."""
return iotronicclient(request).exposed_service.restore_services(board_id)
return iotronicclient(request).exposed_service.restore_services(device_id)
# PORTS MANAGEMENT
def port_list(request, board_id):
"""Get ports attached to a board."""
def port_list(request, device_id):
"""Get ports attached to a device."""
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,
def attach_port(request, device_id, network_id, subnet_id):
"""Attach port to a subnet for a device."""
return iotronicclient(request).portonboard.attach_port(device_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)
def detach_port(request, device_id, port_id):
"""Detach port from the device."""
iotronicclient(request).portonboard.detach_port(device_id, port_id)
# FLEETS MANAGEMENT
@ -256,8 +342,8 @@ def fleet_update(request, fleet_id, patch):
iotronicclient(request).fleet.update(fleet_id, patch)
def fleet_get_boards(request, fleet_id):
"""Get fleet boards."""
def fleet_get_devices(request, fleet_id):
"""Get fleet devices."""
return iotronicclient(request).fleet.boards_in_fleet(fleet=fleet_id)
@ -272,14 +358,14 @@ def webservice_enabled_list(request):
return iotronicclient(request).enabledwebservice.list()
def webservice_get_enabled_info(request, board_id, detail=None):
def webservice_get_enabled_info(request, device_id, detail=None):
"""Get the information of the enabled webservices."""
ws_info = []
ws_enabled = iotronicclient(request).enabledwebservice.list()
for ws in ws_enabled:
if ws.board_uuid == board_id:
if ws.board_uuid == device_id:
ws_info = ws
break
@ -302,35 +388,51 @@ def webservices_on_board(request, board_id, fields=None):
return detailed_webservices
def webservices_on_device(request, device_id, fields=None):
"""Get web services on device list."""
webservices = iotronicclient(request).webserviceonboard.list(device_id,
fields)
detailed_webservices = []
# fields = {"name", "port", "uuid"}
for ws in webservices:
detailed_webservices.append({"name": ws._info["name"],
"port": ws._info["port"],
"uuid": ws._info["uuid"]})
return detailed_webservices
def webservice_get(request, webservice_id, fields):
"""Get web service info."""
return iotronicclient(request).webservice.get(webservice_id, fields)
def webservice_expose(request, board_id, name, port, secure):
def webservice_expose(request, device, name, port, secure):
"""Expose a web service."""
return iotronicclient(request).webserviceonboard.expose(board_id,
return iotronicclient(request).webserviceonboard.expose(device,
name,
port,
secure)
def webservice_unexpose(request, webservice_id):
"""Unexpose a web service from a board."""
"""Unexpose a web service from a device."""
return iotronicclient(request).webservice.delete(webservice_id)
def webservice_enable(request, board, dns, zone, email):
def webservice_enable(request, dev, dns, zone, email):
"""Enable web service."""
return iotronicclient(request).webserviceonboard.enable_webservice(board,
return iotronicclient(request).webserviceonboard.enable_webservice(dev,
dns,
zone,
email)
def webservice_disable(request, board):
def webservice_disable(request, dev):
"""Disable web service."""
return iotronicclient(request).webserviceonboard.disable_webservice(board)
return iotronicclient(request).webserviceonboard.disable_webservice(dev)
def boards_no_webservice(request):
@ -347,8 +449,9 @@ def boards_no_webservice(request):
for i in range(len(board_ws_list)):
if board.uuid == board_ws_list[i].board_uuid:
break
elif ((board.uuid != board_ws_list[i].board_uuid) and
(i==len(board_ws_list)-1)):
elif (
(board.uuid != board_ws_list[i].board_uuid) and (i == len(board_ws_list)-1)
):
boards_no_ws_enabled.append((board.uuid, _(board.name)))
# LOG.debug('COMPLEMENTARY %s', boards_no_ws_enabled)

View File

@ -1,16 +1,18 @@
# Copyright 2015, Rackspace, US, Inc.
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
# The slug of the dashboard to be added to HORIZON['dashboards']. Required.
DASHBOARD = 'iot'

View File

@ -0,0 +1,24 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
from django.utils.translation import ugettext_lazy as _
# The slug of the panel group to be added to HORIZON_CONFIG. Required.
PANEL_GROUP = 'iot_devices'
# The display name of the PANEL_GROUP. Required.
PANEL_GROUP_NAME = _('Devices')
# The slug of the dashboard the PANEL_GROUP associated with. Required.
PANEL_GROUP_DASHBOARD = 'iot'

View File

@ -0,0 +1,28 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'devices'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'iot'
# The slug of the panel group the PANEL is associated with.
# PANEL_GROUP = 'iot'
PANEL_GROUP = 'iot_devices'
# If set, it will update the default panel of the PANEL_DASHBOARD.
DEFAULT_PANEL = ''
# Python panel class of the PANEL to be added.
ADD_PANEL = 'iotronic_ui.iot.devices.panel.Devices'

View File

@ -0,0 +1,23 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'fleets'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'iot'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'iot_devices'
# If set, it will update the default panel of the PANEL_DASHBOARD.
DEFAULT_PANEL = ''
# Python panel class of the PANEL to be added.
ADD_PANEL = 'iotronic_ui.iot.fleets.panel.Fleets'

View File

@ -0,0 +1,24 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
from django.utils.translation import ugettext_lazy as _
# The slug of the panel group to be added to HORIZON_CONFIG. Required.
PANEL_GROUP = 'iot_plugins'
# The display name of the PANEL_GROUP. Required.
PANEL_GROUP_NAME = _('Plugins')
# The slug of the dashboard the PANEL_GROUP associated with. Required.
PANEL_GROUP_DASHBOARD = 'iot'

View File

@ -0,0 +1,23 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'plugins_devices'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'iot'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'iot_plugins'
# If set, it will update the default panel of the PANEL_DASHBOARD.
DEFAULT_PANEL = ''
# Python panel class of the PANEL to be added.
ADD_PANEL = 'iotronic_ui.iot.plugins_devices.panel.PluginsDevices'

View File

@ -0,0 +1,23 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'plugins'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'iot'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'iot_plugins'
# If set, it will update the default panel of the PANEL_DASHBOARD.
DEFAULT_PANEL = ''
# Python panel class of the PANEL to be added.
ADD_PANEL = 'iotronic_ui.iot.plugins.panel.Plugins'

View File

@ -0,0 +1,24 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
from django.utils.translation import ugettext_lazy as _
# The slug of the panel group to be added to HORIZON_CONFIG. Required.
PANEL_GROUP = 'iot_services'
# The display name of the PANEL_GROUP. Required.
PANEL_GROUP_NAME = _('Services')
# The slug of the dashboard the PANEL_GROUP associated with. Required.
PANEL_GROUP_DASHBOARD = 'iot'

View File

@ -0,0 +1,23 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'services_devices'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'iot'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'iot_services'
# If set, it will update the default panel of the PANEL_DASHBOARD.
DEFAULT_PANEL = ''
# Python panel class of the PANEL to be added.
ADD_PANEL = 'iotronic_ui.iot.services_devices.panel.ServicesDevices'

View File

@ -0,0 +1,23 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'services'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'iot'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'iot_services'
# If set, it will update the default panel of the PANEL_DASHBOARD.
DEFAULT_PANEL = ''
# Python panel class of the PANEL to be added.
ADD_PANEL = 'iotronic_ui.iot.services.panel.Services'

View File

@ -0,0 +1,24 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
from django.utils.translation import ugettext_lazy as _
# The slug of the panel group to be added to HORIZON_CONFIG. Required.
PANEL_GROUP = 'iot_webservices'
# The display name of the PANEL_GROUP. Required.
PANEL_GROUP_NAME = _('Web Services')
# The slug of the dashboard the PANEL_GROUP associated with. Required.
PANEL_GROUP_DASHBOARD = 'iot'

View File

@ -0,0 +1,23 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'webservices_devices'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'iot'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'iot_webservices'
# If set, it will update the default panel of the PANEL_DASHBOARD.
DEFAULT_PANEL = ''
# Python panel class of the PANEL to be added.
ADD_PANEL = 'iotronic_ui.iot.webservices_devices.panel.WebServicesDevices'

View File

@ -0,0 +1,23 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'webservices'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'iot'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'iot_webservices'
# If set, it will update the default panel of the PANEL_DASHBOARD.
DEFAULT_PANEL = ''
# Python panel class of the PANEL to be added.
ADD_PANEL = 'iotronic_ui.iot.webservices.panel.Webservices'

View File

@ -82,7 +82,6 @@ class CreateBoardForm(forms.SelfHandlingForm):
class UpdateBoardForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Board ID"), widget=forms.HiddenInput)
name = forms.CharField(label=_("Board Name"))
fleet_list = forms.ChoiceField(
label=_("Fleets List"),
widget=forms.Select(

View File

@ -80,7 +80,7 @@ class IndexView(tables.DataTableView):
# ------------------------------------------------------------
filter_ws = []
for service in board_services:
if ((service["name"] != "webservice") and
if ((service["name"] != "webservice") and
(service["name"] != "webservice_ssl")):
filter_ws.append(service)
@ -90,7 +90,7 @@ class IndexView(tables.DataTableView):
# board.__dict__.update(dict(services=board_services))
board._info.update(dict(services=board_services))
if board.fleet != None:
if board.fleet != None:
fleet_info = api.iotronic.fleet_get(self.request,
board.fleet,
None)
@ -295,7 +295,7 @@ class DisableServiceView(forms.ModalFormView):
for board_service in board_services:
if ((board_service["uuid"] == cloud_service._info["uuid"]) and
((board_service["name"] != "webservice") and
(board_service["name"] != "webservice_ssl"))):
(board_service["name"] != "webservice_ssl"))):
service_list.append((cloud_service._info["uuid"],
_(cloud_service._info["name"])))
# ------------------------------------------------------------

View File

@ -18,11 +18,13 @@ import horizon
class Iot(horizon.Dashboard):
name = _("IoT")
slug = "iot"
panels = ('boards', 'plugins', 'services',
'webservices', 'fleets') # Add your panels here.
# Commented because with group definition this will break the
# configuration
# panels = ('boards', 'plugins', 'services',
# 'webservices', 'fleets', 'devices') # Add your panels here.
# Specify the slug of the dashboard's default panel.
default_panel = 'boards'
default_panel = 'devices'
horizon.register(Iot)

View File

View File

@ -0,0 +1,654 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import json
import logging
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon import messages
from openstack_dashboard.api import iotronic
# from iotronic_ui.api import iotronic
from openstack_dashboard import policy
LOG = logging.getLogger(__name__)
class CreateDeviceForm(forms.SelfHandlingForm):
name = forms.CharField(label=_("Device Name"))
code = forms.CharField(
label=_("Registration Code"),
help_text=_("Registration code")
)
# MODIFY ---> options: yun, server
type = forms.ChoiceField(
label=_("Type"),
# choices=[('gateway', _('Gateway')), ('server', _('Server'))],
choices=[
('raspberry', _('Arancino')),
('yun', _('Arduino YUN')),
('generic', _('Generic')),
('raspberry', _('Raspberry')),
('server', _('Server'))
],
widget=forms.Select(
attrs={'class': 'switchable', 'data-slug': 'slug-type'},
)
)
mobile = forms.BooleanField(label=_("Mobile"), required=False)
latitude = forms.FloatField(label=_("Latitude"))
longitude = forms.FloatField(label=_("Longitude"))
altitude = forms.FloatField(label=_("Altitude"))
def handle(self, request, data):
try:
# Float
# data["location"] = [{"latitude": data["latitude"],
# "longitude": data["longitude"],
# "altitude": data["altitude"]}]
# String
data["location"] = [{"latitude": str(data["latitude"]),
"longitude": str(data["longitude"]),
"altitude": str(data["altitude"])}]
# LOG.debug('DATA: %s', data)
iotronic.device_create(request, data["code"],
data["mobile"], data["location"],
data["type"], data["name"])
messages.success(request, _("Device created successfully."))
return True
except Exception:
exceptions.handle(request, _('Unable to create device.'))
class UpdateDeviceForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(label=_("Device Name"))
fleet_list = forms.ChoiceField(
label=_("Fleets List"),
widget=forms.Select(
attrs={'class': 'switchable', 'data-slug': 'slug-fleet'}),
help_text=_("Select fleet in this pool "),
required=False
)
mobile = forms.BooleanField(label=_("Mobile"), required=False)
def __init__(self, *args, **kwargs):
super(UpdateDeviceForm, self).__init__(*args, **kwargs)
# Populate fleets
fleets = iotronic.fleet_list(self.request, None)
fleets.sort(key=lambda b: b.name)
fleet_list = []
fleet_list.append((None, _("-")))
for fleet in fleets:
fleet_list.append((fleet.uuid, _(fleet.name)))
# LOG.debug("FLEETS: %s", fleet_list)
self.fields["fleet_list"].choices = fleet_list
self.fields["fleet_list"].initial = kwargs["initial"]["fleet_id"]
# Admin
if policy.check((("iot", "iot:update_boards"),), self.request):
# 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("NO-edit IOT ADMIN")
pass
# Other users
else:
if self.request.user.id != kwargs["initial"]["owner"]:
# LOG.debug("IMMUTABLE FIELDS")
self.fields["name"].widget.attrs = {'readonly': 'readonly'}
self.fields["mobile"].widget.attrs = {'disabled': 'disabled'}
self.fields["fleet_list"].widget.attrs = {'disabled':
'disabled'}
def handle(self, request, data):
try:
if data["fleet_list"] == '':
data["fleet_list"] = None
iotronic.device_update(request, data["uuid"],
{"name": data["name"],
"fleet": data["fleet_list"],
"mobile": data["mobile"]})
messages.success(request, _("Device updated successfully."))
return True
except Exception:
exceptions.handle(request, _('Unable to update device.'))
class AttachPortForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device 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 device " + str(data["name"]) + \
" completed successfully"
messages.success(request, _(message_text))
return True
except Exception:
message_text = "Unable to attach port on device " + \
str(data["name"])
exceptions.handle(request, _(message_text))
class DetachPortForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device 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 device " + 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 device " + str(data["name"])
exceptions.handle(request, _(message_text))
class ActionDeviceForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
# action_list = forms.MultipleChoiceField(
action_list = forms.ChoiceField(
label=_("Actions List"),
# widget=forms.SelectMultiple(
widget=forms.Select(
attrs={'class': 'switchable', 'data-slug': 'slug-action-device'}),
help_text=_("Select action in this pool ")
)
parameters = forms.CharField(
label=_("Parameters"),
required=False,
widget=forms.Textarea(
attrs={'class': 'switchable',
'data-slug': 'slug-actiondevice-json'}),
help_text=_("Action parameters")
)
def __init__(self, *args, **kwargs):
super(ActionDeviceForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
self.fields["action_list"].choices = kwargs["initial"]["action_list"]
def handle(self, request, data):
# counter = 0
if not data["parameters"]:
data["parameters"] = {}
else:
data["parameters"] = json.loads(data["parameters"])
try:
action = iotronic.device_action(request,
data["uuid"],
data["action_list"],
data["parameters"])
message_text = action
messages.success(request, _(message_text))
return True
except Exception:
message_text = "Unable to call action " \
+ str(data["action_list"]) + " on device " \
+ str(data["name"]) + "."
exceptions.handle(request, _(message_text))
class PackageActionDeviceForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
manager_list = forms.ChoiceField(
label=_("Manager"),
widget=forms.Select(
attrs={'class': 'switchable',
'data-slug': 'slug-packageaction-manager'}),
help_text=_("Select a manager in this pool ")
)
command_list = forms.ChoiceField(
label=_("Command"),
widget=forms.Select(
attrs={'class': 'switchable',
'data-slug': 'slug-packageaction-command'}),
help_text=_("Select a command in this pool ")
)
packages = forms.CharField(
label=_("Package"),
# required=False,
widget=forms.Textarea(
attrs={
'class': 'switchable',
'rows': 2,
'data-slug': 'slug-package'
}
),
help_text=_("Package name")
)
options = forms.CharField(
label=_("Options"),
required=False,
widget=forms.Textarea(
attrs={
'class': 'switchable',
'rows': 2,
'data-slug': 'slug-options-json'
}
),
help_text=_("Package options")
)
version = forms.CharField(
label=_("Version"),
required=False,
widget=forms.Textarea(
attrs={
'class': 'switchable',
'rows': 1,
'data-slug': 'slug-version-json'
}
),
help_text=_("Package version")
)
def __init__(self, *args, **kwargs):
super(PackageActionDeviceForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
self.fields["manager_list"].choices = kwargs["initial"]["manager_list"]
self.fields["command_list"].choices = kwargs["initial"]["command_list"]
def handle(self, request, data):
# counter = 0
if not data["options"]:
data["options"] = ""
if not data["version"]:
data["version"] = ""
data["parameters"] = {"manager": data["manager_list"],
"command": data["command_list"],
"package": data["packages"],
"options": data["options"],
"version": data["version"]}
try:
action = iotronic.device_action(request,
data["uuid"],
"DevicePkgOperation",
data["parameters"])
message_text = action
messages.success(request, _(message_text))
return True
except Exception:
message_text = "Unable to call package action " \
+ "DevicePkgOperation on device " \
+ str(data["name"]) + "."
exceptions.handle(request, _(message_text))
class MountActionDeviceForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
# mount_action_list = forms.MultipleChoiceField(
mount_action_list = forms.ChoiceField(
label=_("Mount actions List"),
# widget=forms.SelectMultiple(
widget=forms.Select(
attrs={'class': 'switchable',
'data-slug': 'slug-mountaction-device'}),
help_text=_("Select action in this pool ")
)
def __init__(self, *args, **kwargs):
super(MountActionDeviceForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
mount_actions = kwargs["initial"]["mount_action_list"]
self.fields["mount_action_list"].choices = mount_actions
def handle(self, request, data):
# counter = 0
data["parameters"] = {"mnt_cmd": data["mount_action_list"]}
try:
action = iotronic.device_action(request,
data["uuid"],
"DeviceMountFs",
data["parameters"])
message_text = action
messages.success(request, _(message_text))
return True
except Exception:
message_text = "Unable to call action " \
+ str(data["mount_action_list"]) + " on device " \
+ str(data["name"]) + "."
exceptions.handle(request, _(message_text))
class UpgradeLRForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
delay = forms.IntegerField(
label=_("Delay"),
required=False,
help_text=_("Delay in seconds")
)
version = forms.CharField(
label=_("Version"),
required=False,
widget=forms.Textarea(
attrs={
'class': 'switchable',
'rows': 1,
'data-slug': 'slug-version-json'
}
),
help_text=_("Package version")
)
update_conf = forms.BooleanField(
label=_("Update Configuration"),
required=False
)
def handle(self, request, data):
# counter = 0
if not data["delay"]:
data["delay"] = 3
if not data["version"]:
data["version"] = ""
data["parameters"] = {"delay": data["delay"],
"version": data["version"],
"update_conf": data["update_conf"]}
try:
action = iotronic.device_action(request,
data["uuid"],
"DeviceUpgradeLR",
data["parameters"])
message_text = action
messages.success(request, _(message_text))
return True
except Exception:
message_text = "Unable to call DeviceUpgradeLR on device " \
+ str(data["name"]) + "."
exceptions.handle(request, _(message_text))
class RestartLRForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
delay = forms.IntegerField(
label=_("Delay"),
required=False,
help_text=_("Delay in seconds")
)
def handle(self, request, data):
# counter = 0
if not data["delay"]:
data["delay"] = 3
data["parameters"] = {"delay": data["delay"]}
try:
action = iotronic.device_action(request,
data["uuid"],
"DeviceRestartLR",
data["parameters"])
message_text = action
messages.success(request, _(message_text))
return True
except Exception:
message_text = "Unable to call DeviceRestartLR on device " \
+ str(data["name"]) + "."
exceptions.handle(request, _(message_text))
class RebootForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
delay = forms.IntegerField(
label=_("Delay"),
required=False,
help_text=_("Delay in seconds")
)
def handle(self, request, data):
# counter = 0
if not data["delay"]:
data["delay"] = 3
data["parameters"] = {"delay": data["delay"]}
try:
action = iotronic.device_action(request,
data["uuid"],
"DeviceReboot",
data["parameters"])
message_text = action
messages.success(request, _(message_text))
return True
except Exception:
message_text = "Unable to call DeviceReboot on device " \
+ str(data["name"]) + "."
exceptions.handle(request, _(message_text))
class NetConfForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
def handle(self, request, data):
# counter = 0
data["parameters"] = {}
try:
action = iotronic.device_action(request,
data["uuid"],
"DeviceNetConfig",
data["parameters"])
message_text = action
messages.success(request, _(message_text))
return True
except Exception:
message_text = "Unable to call DeviceNetConfig on device " \
+ str(data["name"]) + "."
exceptions.handle(request, _(message_text))
class PingForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
def handle(self, request, data):
# counter = 0
data["parameters"] = {}
try:
action = iotronic.device_action(request,
data["uuid"],
"DevicePing",
data["parameters"])
message_text = action
messages.success(request, _(message_text))
return True
except Exception:
message_text = "Unable to call DevicePing on device " \
+ str(data["name"]) + "."
exceptions.handle(request, _(message_text))

View File

@ -0,0 +1,27 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
from django.utils.translation import ugettext_lazy as _
import horizon
from iotronic_ui.iot import dashboard
class Devices(horizon.Panel):
name = _("Manager")
slug = "devices"
dashboard.Iot.register(Devices)

View File

@ -0,0 +1,220 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import logging
from django import template
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy
from horizon import tables
from openstack_dashboard import api
# from iotronic_ui import api
LOG = logging.getLogger(__name__)
class CreateDeviceLink(tables.LinkAction):
name = "create"
verbose_name = _("Create Device")
url = "horizon:iot:devices:create"
classes = ("ajax-modal",)
icon = "plus"
# policy_rules = (("iot", "iot:create_device"),)
class EditDeviceLink(tables.LinkAction):
name = "edit"
verbose_name = _("Edit")
url = "horizon:iot:devices:update"
classes = ("ajax-modal",)
icon = "pencil"
# policy_rules = (("iot", "iot:update_device"),)
class AttachPortLink(tables.LinkAction):
name = "attachport"
verbose_name = _("Attach Port")
url = "horizon:iot:devices:attachport"
classes = ("ajax-modal",)
icon = "plus"
class DetachPortLink(tables.LinkAction):
name = "detachport"
verbose_name = _("Detach Port")
url = "horizon:iot:devices:detachport"
classes = ("ajax-modal",)
icon = "plus"
class ActionLink(tables.LinkAction):
name = "action"
verbose_name = _("Action")
url = "horizon:iot:devices:action"
classes = ("ajax-modal",)
icon = "plus"
class PackageActionLink(tables.LinkAction):
name = "packageaction"
verbose_name = _("Package Action")
url = "horizon:iot:devices:packageaction"
classes = ("ajax-modal",)
icon = "plus"
class UpgradeLRLink(tables.LinkAction):
name = "upgradelr"
verbose_name = _("Upgrade LR")
url = "horizon:iot:devices:upgradelr"
classes = ("ajax-modal",)
icon = "plus"
class RestartLRLink(tables.LinkAction):
name = "restartlr"
verbose_name = _("Restart LR")
url = "horizon:iot:devices:restartlr"
classes = ("ajax-modal",)
icon = "plus"
class RebootLink(tables.LinkAction):
name = "reboot"
verbose_name = _("Reboot")
url = "horizon:iot:devices:reboot"
classes = ("ajax-modal",)
icon = "plus"
class NetConfLink(tables.LinkAction):
name = "netconf"
verbose_name = _("Connections")
url = "horizon:iot:devices:netconf"
classes = ("ajax-modal",)
icon = "plus"
class PingLink(tables.LinkAction):
name = "ping"
verbose_name = _("Ping")
url = "horizon:iot:devices:ping"
classes = ("ajax-modal",)
icon = "plus"
class RestoreServices(tables.BatchAction):
name = "restoreservices"
@staticmethod
def action_present(count):
return u"Restore ALL Services"
@staticmethod
def action_past(count):
return u"Restored ALL Services"
def allowed(self, request, device=None):
return True
def action(self, request, device_id):
api.iotronic.restore_services(request, device_id)
class DeleteDevicesAction(tables.DeleteAction):
@staticmethod
def action_present(count):
return ungettext_lazy(
u"Delete Device",
u"Delete Devices",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
u"Deleted Device",
u"Deleted Devices",
count
)
# policy_rules = (("iot", "iot:delete_device"),)
"""
def allowed(self, request, role):
return api.keystone.keystone_can_edit_role()
"""
def delete(self, request, device_id):
api.iotronic.board_delete(request, device_id)
class DeviceFilterAction(tables.FilterAction):
# If uncommented it will appear the select menu list of fields
# and filter button
"""
filter_type = "server"
filter_choices = (("name", _("Device Name ="), True),
("type", _("Type ="), True),
("status", _("Status ="), True))
"""
def filter(self, table, devices, filter_string):
"""Naive case-insensitive search."""
q = filter_string.lower()
return [device for device in devices
if q in device.name.lower()]
def show_services(device_info):
template_name = 'iot/devices/_cell_services.html'
context = device_info._info
# LOG.debug("CONTEXT: %s", context)
return template.loader.render_to_string(template_name,
context)
class DevicesTable(tables.DataTable):
name = tables.WrappingColumn('name', link="horizon:iot:devices:detail",
verbose_name=_('Device Name'))
type = tables.Column('type', verbose_name=_('Type'))
# mobile = tables.Column('mobile', verbose_name=_('Mobile'))
lr_version = tables.Column('lr_version', verbose_name=_('LR version'))
# fleet = tables.Column('fleet', verbose_name=_('Fleet ID'))
fleet_name = tables.Column('fleet_name', verbose_name=_('Fleet Name'))
# code = tables.Column('code', verbose_name=_('Code'))
status = tables.Column('status', verbose_name=_('Status'))
uuid = tables.Column('uuid', verbose_name=_('Device ID'))
# location = tables.Column('location', verbose_name=_('Geo'))
services = tables.Column(show_services, verbose_name=_('SSH Access'))
# extra = tables.Column('extra', verbose_name=_('Extra'))
# Overriding get_object_id method because in IoT service the "id" is
# identified by the field UUID
def get_object_id(self, datum):
return datum.uuid
class Meta(object):
name = "devices"
verbose_name = _("devices")
row_actions = (EditDeviceLink, AttachPortLink, DetachPortLink,
PackageActionLink, UpgradeLRLink, RestartLRLink,
RebootLink, NetConfLink, PingLink,
ActionLink, RestoreServices, DeleteDevicesAction)
table_actions = (DeviceFilterAction, CreateDeviceLink,
DeleteDevicesAction)

View File

@ -0,0 +1,53 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import logging
# from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from horizon import tabs
LOG = logging.getLogger(__name__)
class OverviewTab(tabs.Tab):
name = _("Overview")
slug = "overview"
template_name = ("iot/devices/_detail_overview.html")
def get_context_data(self, request):
coordinates = self.tab_group.kwargs['device'].__dict__['location'][0]
ports = self.tab_group.kwargs['device']._info['ports']
services = self.tab_group.kwargs['device']._info['services']
webservices = self.tab_group.kwargs['device']._info['webservices']
plugins = self.tab_group.kwargs['device']._info['plugins']
return {"device": self.tab_group.kwargs['device'],
"coordinates": coordinates,
"services": services,
"webservices": webservices,
"ports": ports,
"plugins": plugins,
"is_superuser": request.user.is_superuser}
class DeviceDetailTabs(tabs.TabGroup):
slug = "device_details"
# tabs = (OverviewTab, LogTab, ConsoleTab, AuditTab)
tabs = (OverviewTab,)
sticky = True

View File

@ -0,0 +1,8 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Call action on device." %}</p>
{% endblock %}

View File

@ -0,0 +1,16 @@
{% load i18n %}
{% if services %}
{% for service in services %}
{% if service.name == "ssh" %}
<dd>ssh -p {{ service.public_port}} root@{{ service.wstun_ip }}</dd>
{% elif service.name == "nodered" %}
<dd>https://nodered.bla.bla.eu</dd>
{% elif service.name == "http" %}
<dd>https://{{ service.wstun_ip }}:{{ service.public_port }}</dd>
{% else %}
<dd>{{ service.name }} [{{ service.protocol }}] {{ service.port }} --> {{ service.public_port }}</dd>
{% endif %}
{% endfor %}
{% else %}
<dd>--</dd>
{% endif %}

View File

@ -0,0 +1,8 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Add a new device." %}</p>
{% endblock %}

View File

@ -0,0 +1,137 @@
{% load i18n sizeformat %}
<div class="detail">
<h4>{% trans "Info" %}</h4>
<hr class="header_rule">
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ device.name }}</dd>
<dt>{% trans "Status" %}</dt>
<dd>{{ device.status }}</dd>
<dt>{% trans "Type" %}</dt>
<dd>{{ device.type }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ device.uuid }}</dd>
<dt>{% trans "LR version" %}</dt>
<dd>{{ device.lr_version }}</dd>
<dt>{% trans "WAMP Agent" %}</dt>
<dd>{{ device.agent }}</dd>
<dt>{% trans "Code" %}</dt>
<dd>{{ device.code }}</dd>
<dt>{% trans "Creation data" %}</dt>
<dd>{{ device.created_at }}</dd>
<dt>{% trans "Location" %}</dt>
<dd>Latitude: {{ coordinates.latitude }}</dd>
<dd>Longitude: {{ coordinates.longitude }}</dd>
<dd>Altitude: {{ coordinates.altitude }}</dd>
<dt>{% trans "Connectivity" %}</dt>
{% if device.connectivity.mac %}
<dd>MAC: {{ device.connectivity.mac }}</dd>
<dd>Interface: {{ device.connectivity.iface }}</dd>
<dd>Local IP: {{ device.connectivity.local_ip }}</dd>
{% else %}
<dd>--</dd>
{% endif %}
<dt>{% trans "Mobile" %}</dt>
<dd>{{ device.mobile }}</dd>
<dt>{% trans "Extra" %}</dt>
<dd>{{ device.extra }}</dd>
<dt>{% trans "Fleet Name" %}</dt>
<dd>{{ device.fleet_name }}</dd>
<dt>{% trans "Fleet ID" %}</dt>
<dd>{{ device.fleet }}</dd>
</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 %}
<!--
<dt>{{ service.name }} [{{ service.protocol }}] {{ service.port }}</dt>
<dd>{{ service.public_port }}</dd>
-->
<!--
<dt>{{ service.name }}</dt>
<dd>[{{ service.protocol }}] L: {{ service.port }}; P: {{ service.public_port }}</dd>
-->
<dt>{{ service.name }}</dt>
{% if service.name == "ssh" %}
<dd>ssh -p {{ service.public_port}} root@{{ service.wstun_ip }}</dd>
{% elif service.name == "nodered" %}
<dd><a href="http://{{ service.wstun_ip }}:{{ service.public_port }}" target="_blank">http://{{ service.wstun_ip }}:{{ service.public_port }}</a></dd>
{% else %}
<dd>{{ service.name }} [{{ service.protocol }}] {{ service.port }} --> {{ service.public_port }}</dd>
{% endif %}
{% endfor %}
{% else %}
<dd>--</dd>
{% endif %}
</dl>
<h4>{% trans "Web Services" %}</h4>
<hr class="header_rule">
<dl class="dl-horizontal">
{% if webservices %}
{% for ws in webservices %}
<dt>{{ ws.name }} [{{ ws.port }}]</dt>
<dd>{{ ws.uuid }}</dd>
{% endfor %}
{% else %}
<dd>--</dd>
{% 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(){
/*
coordinates = JSON.parse(document.getElementById("mapdiv").getAttribute("data-coordinates"));
lat = coordinates[0]["latitude"];
lon = coordinates[0]["longitude"];
alt = coordinates[0]["altitude"];
*/
var lat = "{{ coordinates.latitude }}";
var lon = "{{ coordinates.longitude }}";
var alt = "{{ coordinates.altitude }}";
var label = "{{ board.name }}";
var status = "{{ board.status }}";
var updated = "{{ board.updated_at }}";
var array_coord = {"coordinates" : [{"lat": lat, "lon": lon, "alt": alt, "updated": updated, "label": label, "status": status}]}
render_map("mapdiv", array_coord);
});
</script>
</div>
-->

View File

@ -0,0 +1,8 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Show device connections." %}</p>
{% endblock %}

View File

@ -0,0 +1,8 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Call package action on device." %}</p>
{% endblock %}

View File

@ -0,0 +1,8 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Send ping command." %}</p>
{% endblock %}

View File

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

View File

@ -0,0 +1,8 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Restart LR on device." %}</p>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Edit the device's details." %}</p>
{% endblock %}

View File

@ -0,0 +1,8 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Upgrade LR on device." %}</p>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Action on Device" %}{% endblock %}
{% block main %}
{% include 'iot/devices/_action.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Insert Device" %}{% endblock %}
{% block main %}
{% include 'iot/devices/_create.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Devices" %}{% endblock %}
{% block main %}
{{ table.render }}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Show connections" %}{% endblock %}
{% block main %}
{% include 'iot/devices/_netconf.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Package action on Device" %}{% endblock %}
{% block main %}
{% include 'iot/devices/_packageaction.html' %}
{% endblock %}

View File

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

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Reboot the device" %}{% endblock %}
{% block main %}
{% include 'iot/devices/_reboot.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Restart LR" %}{% endblock %}
{% block main %}
{% include 'iot/devices/_restartlr.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Update Device" %}{% endblock %}
{% block main %}
{% include 'iot/devices/_update.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Upgrade LR" %}{% endblock %}
{% block main %}
{% include 'iot/devices/_upgradelr.html' %}
{% endblock %}

View File

@ -0,0 +1,19 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from horizon.test import helpers as test
class DevicesTests(test.TestCase):
# Unit tests for devices.
def test_me(self):
self.assertTrue(1 + 1 == 2)

View File

@ -0,0 +1,47 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
from django.conf.urls import url
from iotronic_ui.iot.devices import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^create/$', views.CreateView.as_view(), name='create'),
url(r'^(?P<device_id>[^/]+)/update/$', views.UpdateView.as_view(),
name='update'),
url(r'^(?P<device_id>[^/]+)/detail/$', views.DeviceDetailView.as_view(),
name='detail'),
url(r'^(?P<device_id>[^/]+)/attachport/$',
views.AttachPortView.as_view(), name='attachport'),
url(r'^(?P<device_id>[^/]+)/detachport/$',
views.DetachPortView.as_view(), name='detachport'),
url(r'^(?P<device_id>[^/]+)/netconf/$',
views.NetConfView.as_view(), name='netconf'),
url(r'^(?P<device_id>[^/]+)/ping/$',
views.PingView.as_view(), name='ping'),
url(r'^(?P<device_id>[^/]+)/action/$',
views.ActionView.as_view(), name='action'),
url(r'^(?P<device_id>[^/]+)/packageaction/$',
views.PackageActionView.as_view(), name='packageaction'),
url(r'^(?P<device_id>[^/]+)/upgradelr/$',
views.UpgradeLRView.as_view(), name='upgradelr'),
url(r'^(?P<device_id>[^/]+)/restartlr/$',
views.RestartLRView.as_view(), name='restartlr'),
url(r'^(?P<device_id>[^/]+)/reboot/$',
views.RebootView.as_view(), name='reboot'),
]

View File

@ -0,0 +1,647 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import logging
from django.conf import settings
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
# from horizon import messages
from horizon import tables
from horizon import tabs
from horizon.utils import memoized
from openstack_dashboard import api
# from iotronic_ui.api import iotronic
from openstack_dashboard import policy
from iotronic_ui.iot.devices import forms as project_forms
from iotronic_ui.iot.devices import tables as project_tables
from iotronic_ui.iot.devices import tabs as project_tabs
LOG = logging.getLogger(__name__)
class IndexView(tables.DataTableView):
table_class = project_tables.DevicesTable
template_name = 'iot/devices/index.html'
page_title = _("Devices")
def get_data(self):
devices = []
# Admin
if policy.check((("iot", "iot:list_all_boards"),), self.request):
try:
devices = api.iotronic.device_list(self.request, None, None)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve devices list.'))
# Admin_iot_project
elif policy.check((("iot", "iot:list_project_boards"),), self.request):
try:
devices = api.iotronic.device_list(self.request, None, None)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve user devices list.'))
# Other users
else:
try:
devices = api.iotronic.device_list(self.request, None, None)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve user devices list.'))
for device in devices:
device_services = api.iotronic.services_on_device(self.request,
device.uuid,
True)
# x = api.iotronic.device_get(self.request, device.uuid, None)
# LOG.debug('DEVICE: %s', x)
# TO BE REMOVED
# ------------------------------------------------------------
filter_ws = []
for service in device_services:
# We are filtering the services that starts with "webservice"
"""
if ((service["name"] != "webservice") and
(service["name"] != "webservice_ssl")):
filter_ws.append(service)
"""
# We want to show only the "ssh" service
if (service["name"] == "ssh"):
service["wstun_ip"] = device.wstun_ip
filter_ws.append(service)
device_services = filter_ws
# ------------------------------------------------------------
# device.__dict__.update(dict(services=device_services))
device._info.update(dict(services=device_services))
if device.fleet != None:
fleet_info = api.iotronic.fleet_get(self.request,
device.fleet,
None)
device.fleet_name = fleet_info.name
else:
device.fleet_name = None
devices.sort(key=lambda b: b.name)
# LOG.debug('DEVICES: %s', devices)
return devices
class CreateView(forms.ModalFormView):
template_name = 'iot/devices/create.html'
modal_header = _("Create Device")
form_id = "create_device_form"
form_class = project_forms.CreateDeviceForm
submit_label = _("Create Device")
submit_url = reverse_lazy("horizon:iot:devices:create")
success_url = reverse_lazy('horizon:iot:devices:index')
page_title = _("Create Device")
class UpdateView(forms.ModalFormView):
template_name = 'iot/devices/update.html'
modal_header = _("Update Device")
form_id = "update_device_form"
form_class = project_forms.UpdateDeviceForm
submit_label = _("Update Device")
submit_url = "horizon:iot:devices:update"
success_url = reverse_lazy('horizon:iot:devices:index')
page_title = _("Update Device")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:devices:index")
exceptions.handle(self.request,
_('Unable to get device information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(UpdateView, 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):
device = self.get_object()
location = device.location[0]
return {'uuid': device.uuid,
'name': device.name,
'mobile': device.mobile,
'owner': device.owner,
'fleet_id': device.fleet,
'latitude': location["latitude"],
'longitude': location["longitude"],
'altitude': location["altitude"]}
class AttachPortView(forms.ModalFormView):
template_name = 'iot/devices/attachport.html'
modal_header = _("Attach")
form_id = "attach_deviceport_form"
form_class = project_forms.AttachPortForm
submit_label = _("Attach")
# submit_url = reverse_lazy("horizon:iot:devices:attachport")
submit_url = "horizon:iot:devices:attachport"
success_url = reverse_lazy('horizon:iot:devices:index')
page_title = _("Attach port")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:devices:index")
exceptions.handle(self.request,
_('Unable to get device 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):
device = self.get_object()
# Populate networks
networks = api.neutron.network_list(self.request)
net_choices = []
networks.sort(key=lambda b: b.name)
for net in networks:
for subnet in net["subnets"]:
net_choices.append((net["id"] + ':' + subnet["id"],
_(net["name"] + ':' + subnet["name"])))
return {'uuid': device.uuid,
'name': device.name,
'networks_list': net_choices}
class DetachPortView(forms.ModalFormView):
template_name = 'iot/devices/detachport.html'
modal_header = _("Detach")
form_id = "detach_deviceport_form"
form_class = project_forms.DetachPortForm
submit_label = _("Detach")
# submit_url = reverse_lazy("horizon:iot:devices:detachport")
submit_url = "horizon:iot:devices:detachport"
success_url = reverse_lazy('horizon:iot:devices:index')
page_title = _("Detach port")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:devices:index")
exceptions.handle(self.request,
_('Unable to get device 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):
device = self.get_object()
ports = api.iotronic.port_list(self.request, device.uuid)
# TO BE REMOVED (change it once the port_list per device is
# completed and tested !
# ################################################################
# LOG.debug("PORTS: %s", ports)
ports.sort(key=lambda b: b.name)
filtered_ports = []
for port in ports:
if port._info["board_uuid"] == device.uuid:
filtered_ports.append((port._info["uuid"],
_(port._info["ip"])))
ports = filtered_ports
# ################################################################
# Populate device ports
return {'uuid': device.uuid,
'name': device.name,
'ports': ports}
class ActionView(forms.ModalFormView):
template_name = 'iot/devices/action.html'
modal_header = _("Action on Device")
form_id = "action_device_form"
form_class = project_forms.ActionDeviceForm
submit_label = _("Action")
# submit_url = reverse_lazy("horizon:iot:devices:action")
submit_url = "horizon:iot:devices:action"
success_url = reverse_lazy('horizon:iot:devices:index')
page_title = _("Action on Device")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:devices:index")
exceptions.handle(self.request,
_('Unable to get device information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(ActionView, 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):
device = self.get_object()
# Populate actions (TO BE REPLACED with an action list api)
actions = ["DeviceNetConfig", "DevicePing", "DeviceEcho",
"DeviceUpgradeLR", "DevicePkgOperation",
"DeviceRestartLR", "DeviceReboot"]
actions.sort()
action_list = []
for action in actions:
name = action.replace("Device", "")
action_list.append((action, _(name)))
return {'uuid': device.uuid,
'name': device.name,
'action_list': action_list}
class PackageActionView(forms.ModalFormView):
template_name = 'iot/devices/packageaction.html'
modal_header = _("Action on packages on Device")
form_id = "package_action_device_form"
form_class = project_forms.PackageActionDeviceForm
submit_label = _("Package Action")
# submit_url = reverse_lazy("horizon:iot:devices:packageaction")
submit_url = "horizon:iot:devices:packageaction"
success_url = reverse_lazy('horizon:iot:devices:index')
page_title = _("Action on packages on Device")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:devices:index")
exceptions.handle(self.request,
_('Unable to get device information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(PackageActionView, 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):
device = self.get_object()
managers = ["apt", "npm", "pip", "pip3"]
commands = ["install", "remove", "uninstall"]
managers.sort()
commands.sort()
manager_list = []
command_list = []
for manager in managers:
manager_list.append((manager, _(manager)))
for command in commands:
command_list.append((command, _(command)))
return {'uuid': device.uuid,
'name': device.name,
'manager_list': manager_list,
'command_list': command_list}
class UpgradeLRView(forms.ModalFormView):
template_name = 'iot/devices/upgradelr.html'
modal_header = _("Upgrade LR on Device")
form_id = "upgrade_lr_form"
form_class = project_forms.UpgradeLRForm
submit_label = _("Upgrade")
# submit_url = reverse_lazy("horizon:iot:devices:upgradelr")
submit_url = "horizon:iot:devices:upgradelr"
success_url = reverse_lazy('horizon:iot:devices:index')
page_title = _("Upgrade LR")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:devices:index")
exceptions.handle(self.request,
_('Unable to get device information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(UpgradeLRView, 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):
device = self.get_object()
return {'uuid': device.uuid,
'name': device.name}
class RestartLRView(forms.ModalFormView):
template_name = 'iot/devices/restartlr.html'
modal_header = _("Restart LR on Device")
form_id = "restart_lr_form"
form_class = project_forms.RestartLRForm
submit_label = _("Restart")
# submit_url = reverse_lazy("horizon:iot:devices:restartlr")
submit_url = "horizon:iot:devices:restartlr"
success_url = reverse_lazy('horizon:iot:devices:index')
page_title = _("Restart LR")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:devices:index")
exceptions.handle(self.request,
_('Unable to get device information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(RestartLRView, 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):
device = self.get_object()
return {'uuid': device.uuid,
'name': device.name}
class RebootView(forms.ModalFormView):
template_name = 'iot/devices/reboot.html'
modal_header = _("Reboot the Device")
form_id = "reboot_form"
form_class = project_forms.RebootForm
submit_label = _("Reboot")
# submit_url = reverse_lazy("horizon:iot:devices:reboot")
submit_url = "horizon:iot:devices:reboot"
success_url = reverse_lazy('horizon:iot:devices:index')
page_title = _("Reboot Device")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:devices:index")
exceptions.handle(self.request,
_('Unable to get device information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(RebootView, 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):
device = self.get_object()
return {'uuid': device.uuid,
'name': device.name}
class NetConfView(forms.ModalFormView):
template_name = 'iot/devices/netconf.html'
modal_header = _("Device connections")
form_id = "netconf_form"
form_class = project_forms.NetConfForm
submit_label = _("Show")
# submit_url = reverse_lazy("horizon:iot:devices:netconf")
submit_url = "horizon:iot:devices:netconf"
success_url = reverse_lazy('horizon:iot:devices:index')
page_title = _("Device connections")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:devices:index")
exceptions.handle(self.request,
_('Unable to get device information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(NetConfView, 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):
device = self.get_object()
return {'uuid': device.uuid,
'name': device.name}
class PingView(forms.ModalFormView):
template_name = 'iot/devices/ping.html'
modal_header = _("Ping")
form_id = "ping_form"
form_class = project_forms.PingForm
submit_label = _("Submit")
# submit_url = reverse_lazy("horizon:iot:devices:ping")
submit_url = "horizon:iot:devices:ping"
success_url = reverse_lazy('horizon:iot:devices:index')
page_title = _("Ping")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:devices:index")
exceptions.handle(self.request,
_('Unable to get device information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(PingView, 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):
device = self.get_object()
return {'uuid': device.uuid,
'name': device.name}
class DetailView(tabs.TabView):
tab_group_class = project_tabs.DeviceDetailTabs
template_name = 'horizon/common/_detail.html'
page_title = "{{ device.name|default:device.uuid }}"
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
device = self.get_data()
context["device"] = device
context["url"] = reverse(self.redirect_url)
context["actions"] = self._get_actions(device)
return context
def _get_actions(self, device):
table = project_tables.BoardsTable(self.request)
return table.render_row_actions(device)
@memoized.memoized_method
def get_data(self):
device = []
device_id = self.kwargs['device_id']
try:
device_ports = []
device = api.iotronic.device_get(self.request, device_id, None)
# FIX this problem with the new APIs
# (remove the "if" clause with a better approach)
# #################################################################
ports = api.iotronic.port_list(self.request, device_id)
for port in ports:
if port._info["board_uuid"] == device_id:
device_ports.append(port._info)
device._info.update(dict(ports=device_ports))
# #################################################################
device_services = api.iotronic.services_on_device(self.request,
device_id, True)
# We have to add the wstun_ip to the service
for service in device_services:
service["wstun_ip"] = device.wstun_ip
device._info.update(dict(services=device_services))
device_plugins = api.iotronic.plugins_on_device(self.request,
device_id)
device._info.update(dict(plugins=device_plugins))
device_webservices = api.iotronic.webservices_on_device(self.request,
device_id)
# LOG.debug('DEVICE %s, WEB SERVICES: %s', device_id, device_webservices)
device._info.update(dict(webservices=device_webservices))
# Adding fleet name
if device.fleet != None:
fleet_info = api.iotronic.fleet_get(self.request,
device.fleet,
None)
device.fleet_name = fleet_info.name
else:
device.fleet_name = None
# Adding LR web service description
lr_ws = api.iotronic.webservice_get_enabled_info(self.request,
device_id)
device._info.update(dict(lr_webservice=lr_ws))
# LOG.debug("DEVICE: %s\n\n%s", device, device._info)
except Exception:
msg = ('Unable to retrieve device %s information') % {'name':
device.name}
exceptions.handle(self.request, msg, ignore=True)
return device
def get_tabs(self, request, *args, **kwargs):
device = self.get_data()
return self.tab_group_class(request, device=device, **kwargs)
class DeviceDetailView(DetailView):
redirect_url = 'horizon:iot:devices:index'
def _get_actions(self, device):
table = project_tables.DevicesTable(self.request)
return table.render_row_actions(device)

View File

@ -35,8 +35,10 @@ class CreateFleetForm(forms.SelfHandlingForm):
def handle(self, request, data):
try:
iotronic.fleet_create(request, data["name"],
data["description"])
iotronic.fleet_create(
request, data["name"],
data["description"]
)
messages.success(request, _("Fleet " + str(data["name"]) +
" created successfully."))
@ -79,9 +81,13 @@ class UpdateFleetForm(forms.SelfHandlingForm):
def handle(self, request, data):
try:
iotronic.fleet_update(request, data["uuid"],
{"name": data["name"],
"description": data["description"]})
iotronic.fleet_update(
request, data["uuid"],
{
"name": data["name"],
"description": data["description"]
}
)
messages.success(request, _("Fleet updated successfully."))
return True

View File

@ -97,9 +97,7 @@ class UpdateView(forms.ModalFormView):
@memoized.memoized_method
def get_object(self):
try:
return iotronic.fleet_get(self.request,
self.kwargs['fleet_id'],
None)
return iotronic.fleet_get(self.request, self.kwargs['fleet_id'], None)
except Exception:
redirect = reverse("horizon:iot:fleets:index")
exceptions.handle(self.request,
@ -146,7 +144,7 @@ class DetailView(tabs.TabView):
fleet_id = self.kwargs['fleet_id']
try:
fleet = iotronic.fleet_get(self.request, fleet_id, None)
boards = iotronic.fleet_get_boards(self.request, fleet_id)
boards = iotronic.fleet_get_devices(self.request, fleet_id)
# LOG.debug('Boards: %s', boards)

View File

@ -93,11 +93,11 @@ class InjectPluginForm(forms.SelfHandlingForm):
onboot = forms.BooleanField(label=_("On Boot"), required=False)
board_list = forms.MultipleChoiceField(
label=_("Boards List"),
device_list = forms.MultipleChoiceField(
label=_("Devices List"),
widget=forms.SelectMultiple(
attrs={'class': 'switchable', 'data-slug': 'slug-inject-plugin'}),
help_text=_("Select boards in this pool ")
help_text=_("Select devices in this pool ")
)
def __init__(self, *args, **kwargs):
@ -105,18 +105,18 @@ class InjectPluginForm(forms.SelfHandlingForm):
super(InjectPluginForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
boardslist_length = len(kwargs["initial"]["board_list"])
deviceslist_length = len(kwargs["initial"]["device_list"])
self.fields["board_list"].choices = kwargs["initial"]["board_list"]
self.fields["board_list"].max_length = boardslist_length
self.fields["device_list"].choices = kwargs["initial"]["device_list"]
self.fields["device_list"].max_length = deviceslist_length
def handle(self, request, data):
counter = 0
for board in data["board_list"]:
for key, value in self.fields["board_list"].choices:
if key == board:
for device in data["device_list"]:
for key, value in self.fields["device_list"].choices:
if key == device:
try:
inject = iotronic.plugin_inject(request, key,
@ -126,13 +126,13 @@ class InjectPluginForm(forms.SelfHandlingForm):
message_text = inject
messages.success(request, _(message_text))
if counter != len(data["board_list"]) - 1:
if counter != len(data["device_list"]) - 1:
counter += 1
else:
return True
except Exception:
message_text = "Unable to inject plugin on board " \
message_text = "Unable to inject plugin on device " \
+ str(value) + "."
exceptions.handle(request, _(message_text))
@ -148,12 +148,12 @@ class StartPluginForm(forms.SelfHandlingForm):
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
board_list = forms.MultipleChoiceField(
label=_("Boards List"),
device_list = forms.MultipleChoiceField(
label=_("Devices List"),
widget=forms.SelectMultiple(
attrs={'class': 'switchable',
'data-slug': 'slug-start-boards'}),
help_text=_("Select boards in this pool ")
'data-slug': 'slug-start-devices'}),
help_text=_("Select devices in this pool ")
)
parameters = forms.CharField(
@ -170,10 +170,10 @@ class StartPluginForm(forms.SelfHandlingForm):
super(StartPluginForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
boardslist_length = len(kwargs["initial"]["board_list"])
deviceslist_length = len(kwargs["initial"]["device_list"])
self.fields["board_list"].choices = kwargs["initial"]["board_list"]
self.fields["board_list"].max_length = boardslist_length
self.fields["device_list"].choices = kwargs["initial"]["device_list"]
self.fields["device_list"].max_length = deviceslist_length
def handle(self, request, data):
@ -184,9 +184,9 @@ class StartPluginForm(forms.SelfHandlingForm):
else:
data["parameters"] = json.loads(data["parameters"])
for board in data["board_list"]:
for key, value in self.fields["board_list"].choices:
if key == board:
for device in data["device_list"]:
for key, value in self.fields["device_list"].choices:
if key == device:
try:
action = iotronic.plugin_action(request, key,
@ -197,13 +197,13 @@ class StartPluginForm(forms.SelfHandlingForm):
message_text = action
messages.success(request, _(message_text))
if counter != len(data["board_list"]) - 1:
if counter != len(data["device_list"]) - 1:
counter += 1
else:
return True
except Exception:
message_text = "Unable to start plugin on board " \
message_text = "Unable to start plugin on device " \
+ str(value) + "."
exceptions.handle(request, _(message_text))
@ -225,11 +225,11 @@ class StopPluginForm(forms.SelfHandlingForm):
help_text=_("OPTIONAL: seconds to wait before stopping the plugin")
)
board_list = forms.MultipleChoiceField(
label=_("Boards List"),
device_list = forms.MultipleChoiceField(
label=_("Devices List"),
widget=forms.SelectMultiple(
attrs={'class': 'switchable', 'data-slug': 'slug-stop-boards'}),
help_text=_("Select boards in this pool ")
attrs={'class': 'switchable', 'data-slug': 'slug-stop-devices'}),
help_text=_("Select devices in this pool ")
)
def __init__(self, *args, **kwargs):
@ -237,10 +237,10 @@ class StopPluginForm(forms.SelfHandlingForm):
super(StopPluginForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
boardslist_length = len(kwargs["initial"]["board_list"])
deviceslist_length = len(kwargs["initial"]["device_list"])
self.fields["board_list"].choices = kwargs["initial"]["board_list"]
self.fields["board_list"].max_length = boardslist_length
self.fields["device_list"].choices = kwargs["initial"]["device_list"]
self.fields["device_list"].max_length = deviceslist_length
def handle(self, request, data):
@ -251,9 +251,9 @@ class StopPluginForm(forms.SelfHandlingForm):
else:
data["delay"] = {"delay": data["delay"]}
for board in data["board_list"]:
for key, value in self.fields["board_list"].choices:
if key == board:
for device in data["device_list"]:
for key, value in self.fields["device_list"].choices:
if key == device:
try:
action = iotronic.plugin_action(request, key,
@ -264,13 +264,13 @@ class StopPluginForm(forms.SelfHandlingForm):
message_text = action
messages.success(request, _(message_text))
if counter != len(data["board_list"]) - 1:
if counter != len(data["device_list"]) - 1:
counter += 1
else:
return True
except Exception:
message_text = "Unable to stop plugin on board " \
message_text = "Unable to stop plugin on device " \
+ str(value) + "."
exceptions.handle(request, _(message_text))
@ -286,11 +286,11 @@ class CallPluginForm(forms.SelfHandlingForm):
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
board_list = forms.MultipleChoiceField(
label=_("Boards List"),
device_list = forms.MultipleChoiceField(
label=_("Devices List"),
widget=forms.SelectMultiple(
attrs={'class': 'switchable', 'data-slug': 'slug-call-boards'}),
help_text=_("Select boards in this pool ")
attrs={'class': 'switchable', 'data-slug': 'slug-call-devices'}),
help_text=_("Select devices in this pool ")
)
parameters = forms.CharField(
@ -307,10 +307,10 @@ class CallPluginForm(forms.SelfHandlingForm):
super(CallPluginForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
boardslist_length = len(kwargs["initial"]["board_list"])
deviceslist_length = len(kwargs["initial"]["device_list"])
self.fields["board_list"].choices = kwargs["initial"]["board_list"]
self.fields["board_list"].max_length = boardslist_length
self.fields["device_list"].choices = kwargs["initial"]["device_list"]
self.fields["device_list"].max_length = deviceslist_length
def handle(self, request, data):
@ -321,9 +321,9 @@ class CallPluginForm(forms.SelfHandlingForm):
else:
data["parameters"] = json.loads(data["parameters"])
for board in data["board_list"]:
for key, value in self.fields["board_list"].choices:
if key == board:
for device in data["device_list"]:
for key, value in self.fields["device_list"].choices:
if key == device:
try:
action = iotronic.plugin_action(request, key,
@ -334,13 +334,13 @@ class CallPluginForm(forms.SelfHandlingForm):
message_text = action
messages.success(request, _(message_text))
if counter != len(data["board_list"]) - 1:
if counter != len(data["device_list"]) - 1:
counter += 1
else:
return True
except Exception:
message_text = "Unable to call plugin on board " \
message_text = "Unable to call plugin on device " \
+ str(value) + "."
exceptions.handle(request, _(message_text))
@ -356,11 +356,11 @@ class RemovePluginForm(forms.SelfHandlingForm):
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
board_list = forms.MultipleChoiceField(
label=_("Boards List"),
device_list = forms.MultipleChoiceField(
label=_("Devices List"),
widget=forms.SelectMultiple(
attrs={'class': 'switchable', 'data-slug': 'slug-remove-boards'}),
help_text=_("Select boards in this pool ")
attrs={'class': 'switchable', 'data-slug': 'slug-remove-devices'}),
help_text=_("Select devices in this pool ")
)
def __init__(self, *args, **kwargs):
@ -368,18 +368,18 @@ class RemovePluginForm(forms.SelfHandlingForm):
super(RemovePluginForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
boardslist_length = len(kwargs["initial"]["board_list"])
deviceslist_length = len(kwargs["initial"]["device_list"])
self.fields["board_list"].choices = kwargs["initial"]["board_list"]
self.fields["board_list"].max_length = boardslist_length
self.fields["device_list"].choices = kwargs["initial"]["device_list"]
self.fields["device_list"].max_length = deviceslist_length
def handle(self, request, data):
counter = 0
for board in data["board_list"]:
for key, value in self.fields["board_list"].choices:
if key == board:
for device in data["device_list"]:
for key, value in self.fields["device_list"].choices:
if key == device:
try:
iotronic.plugin_remove(request,
@ -387,16 +387,16 @@ class RemovePluginForm(forms.SelfHandlingForm):
data["uuid"])
# LOG.debug("API: %s %s", plugin, request)
message_text = "Plugin removed successfully from" \
+ " board " + str(value) + "."
+ " device " + str(value) + "."
messages.success(request, _(message_text))
if counter != len(data["board_list"]) - 1:
if counter != len(data["device_list"]) - 1:
counter += 1
else:
return True
except Exception:
message_text = "Unable to remove plugin from board " \
message_text = "Unable to remove plugin from device " \
+ str(value) + "."
exceptions.handle(request, _(message_text))
@ -458,8 +458,7 @@ class UpdatePluginForm(forms.SelfHandlingForm):
"callable": data["callable"],
"code": data["code"]})
messages.success(request, _("Plugin " + str(data["name"]) +
" updated successfully."))
messages.success(request, _("Plugin " + str(data["name"]) + " updated successfully."))
return True
except Exception:

View File

@ -86,7 +86,7 @@ class CallPluginLink(tables.LinkAction):
class RemovePluginLink(tables.LinkAction):
name = "remove"
verbose_name = _("Remove Plugin from board(s)")
verbose_name = _("Remove Plugin from device(s)")
url = "horizon:iot:plugins:remove"
classes = ("ajax-modal",)
icon = "plus"

View File

@ -3,5 +3,5 @@
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Call a plugin on board(s)." %}</p>
<p>{% trans "Call a plugin on device(s)." %}</p>
{% endblock %}

View File

@ -3,5 +3,5 @@
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Inject a plugin into board(s)." %}</p>
<p>{% trans "Inject a plugin into device(s)." %}</p>
{% endblock %}

View File

@ -3,5 +3,5 @@
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Remove a plugin from board(s)." %}</p>
<p>{% trans "Remove a plugin from device(s)." %}</p>
{% endblock %}

View File

@ -3,5 +3,5 @@
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Start a plugin on board(s)." %}</p>
<p>{% trans "Start a plugin on device(s)." %}</p>
{% endblock %}

View File

@ -3,5 +3,5 @@
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Stop a plugin on board(s)." %}</p>
<p>{% trans "Stop a plugin on device(s)." %}</p>
{% endblock %}

View File

@ -42,7 +42,7 @@ class IndexView(tables.DataTableView):
def get_data(self):
plugins = []
users = []
LOG.debug("REQUEST: %s", self.request)
# Admin
if policy.check((("iot", "iot:list_all_plugins"),), self.request):
try:
@ -128,17 +128,17 @@ class InjectView(forms.ModalFormView):
def get_initial(self):
plugin = self.get_object()
# Populate boards
boards = iotronic.board_list(self.request, "online", None, None)
boards.sort(key=lambda b: b.name)
# Populate devices
devices = iotronic.device_list(self.request, "online", None, None)
devices.sort(key=lambda b: b.name)
board_list = []
for board in boards:
board_list.append((board.uuid, _(board.name)))
device_list = []
for device in devices:
device_list.append((device.uuid, _(device.name)))
return {'uuid': plugin.uuid,
'name': plugin.name,
'board_list': board_list}
'device_list': device_list}
class StartView(forms.ModalFormView):
@ -172,17 +172,17 @@ class StartView(forms.ModalFormView):
def get_initial(self):
plugin = self.get_object()
# Populate boards
boards = iotronic.board_list(self.request, "online", None, None)
boards.sort(key=lambda b: b.name)
# Populate devices
devices = iotronic.device_list(self.request, "online", None, None)
devices.sort(key=lambda b: b.name)
board_list = []
for board in boards:
board_list.append((board.uuid, _(board.name)))
device_list = []
for device in devices:
device_list.append((device.uuid, _(device.name)))
return {'uuid': plugin.uuid,
'name': plugin.name,
'board_list': board_list}
'device_list': device_list}
class StopView(forms.ModalFormView):
@ -216,17 +216,17 @@ class StopView(forms.ModalFormView):
def get_initial(self):
plugin = self.get_object()
# Populate boards
boards = iotronic.board_list(self.request, "online", None, None)
boards.sort(key=lambda b: b.name)
# Populate devices
devices = iotronic.device_list(self.request, "online", None, None)
devices.sort(key=lambda b: b.name)
board_list = []
for board in boards:
board_list.append((board.uuid, _(board.name)))
device_list = []
for device in devices:
device_list.append((device.uuid, _(device.name)))
return {'uuid': plugin.uuid,
'name': plugin.name,
'board_list': board_list}
'device_list': device_list}
class CallView(forms.ModalFormView):
@ -260,17 +260,17 @@ class CallView(forms.ModalFormView):
def get_initial(self):
plugin = self.get_object()
# Populate boards
boards = iotronic.board_list(self.request, "online", None, None)
boards.sort(key=lambda b: b.name)
# Populate devices
devices = iotronic.device_list(self.request, "online", None, None)
devices.sort(key=lambda b: b.name)
board_list = []
for board in boards:
board_list.append((board.uuid, _(board.name)))
device_list = []
for device in devices:
device_list.append((device.uuid, _(device.name)))
return {'uuid': plugin.uuid,
'name': plugin.name,
'board_list': board_list}
'device_list': device_list}
class RemoveView(forms.ModalFormView):
@ -304,17 +304,17 @@ class RemoveView(forms.ModalFormView):
def get_initial(self):
plugin = self.get_object()
# Populate boards
boards = iotronic.board_list(self.request, "online", None, None)
boards.sort(key=lambda b: b.name)
# Populate devices
devices = iotronic.device_list(self.request, "online", None, None)
devices.sort(key=lambda b: b.name)
board_list = []
for board in boards:
board_list.append((board.uuid, _(board.name)))
device_list = []
for device in devices:
device_list.append((device.uuid, _(device.name)))
return {'uuid': plugin.uuid,
'name': plugin.name,
'board_list': board_list}
'device_list': device_list}
class UpdateView(forms.ModalFormView):

View File

@ -0,0 +1,316 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import cPickle
import json
import logging
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon import messages
from openstack_dashboard.api import iotronic
# from iotronic_ui.api import iotronic
from openstack_dashboard import policy
LOG = logging.getLogger(__name__)
class InjectPluginForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
onboot = forms.BooleanField(label=_("On Boot"), required=False)
plugin_list = forms.MultipleChoiceField(
label=_("Plugins List"),
widget=forms.SelectMultiple(
attrs={'class': 'switchable', 'data-slug': 'slug-inject-plugin'}),
help_text=_("Select plugin in this pool ")
)
def __init__(self, *args, **kwargs):
super(InjectPluginForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
pluginslist_length = len(kwargs["initial"]["plugin_list"])
self.fields["plugin_list"].choices = kwargs["initial"]["plugin_list"]
self.fields["plugin_list"].max_length = pluginslist_length
def handle(self, request, data):
counter = 0
for plugin in data["plugin_list"]:
for key, value in self.fields["plugin_list"].choices:
if key == plugin:
try:
inject = iotronic.plugin_inject(request,
data["uuid"],
key,
data["onboot"])
# LOG.debug("API: %s %s", plugin, request)
message_text = inject
messages.success(request, _(message_text))
if counter != len(data["plugin_list"]) - 1:
counter += 1
else:
return True
except Exception:
message_text = "Unable to inject plugin on device " \
+ str(data["name"]) + "."
exceptions.handle(request, _(message_text))
break
class CallPluginForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
# plugin_list = forms.MultipleChoiceField(
plugin_list = forms.ChoiceField(
label=_("Plugins List"),
# widget=forms.SelectMultiple(
widget=forms.Select(
attrs={'class': 'switchable', 'data-slug': 'slug-call-plugin'}),
help_text=_("Select plugins in this pool ")
)
parameters = forms.CharField(
label=_("Parameters"),
required=False,
widget=forms.Textarea(
attrs={'class': 'switchable',
'data-slug': 'slug-callplugin-json'}),
help_text=_("Plugin parameters")
)
def __init__(self, *args, **kwargs):
super(CallPluginForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
# pluginslist_length = len(kwargs["initial"]["plugin_list"])
self.fields["plugin_list"].choices = kwargs["initial"]["plugin_list"]
# self.fields["plugin_list"].max_length = pluginslist_length
def handle(self, request, data):
# counter = 0
if not data["parameters"]:
data["parameters"] = {}
else:
data["parameters"] = json.loads(data["parameters"])
try:
action = iotronic.plugin_action(request,
data["uuid"],
data["plugin_list"],
"PluginCall",
data["parameters"])
message_text = action
messages.success(request, _(message_text))
return True
except Exception:
message_text = "Unable to call plugin on device " \
+ str(data["name"]) + "."
exceptions.handle(request, _(message_text))
class StartPluginForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
# plugin_list = forms.MultipleChoiceField(
plugin_list = forms.ChoiceField(
label=_("Plugins List"),
# widget=forms.SelectMultiple(
widget=forms.Select(
attrs={'class': 'switchable', 'data-slug': 'slug-start-plugin'}),
help_text=_("Select plugins in this pool ")
)
parameters = forms.CharField(
label=_("Parameters"),
required=False,
widget=forms.Textarea(
attrs={'class': 'switchable',
'data-slug': 'slug-startplugin-json'}),
help_text=_("Plugin parameters")
)
def __init__(self, *args, **kwargs):
super(StartPluginForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
self.fields["plugin_list"].choices = kwargs["initial"]["plugin_list"]
def handle(self, request, data):
# counter = 0
if not data["parameters"]:
data["parameters"] = {}
else:
data["parameters"] = json.loads(data["parameters"])
try:
action = iotronic.plugin_action(request,
data["uuid"],
data["plugin_list"],
"PluginStart",
data["parameters"])
message_text = action
messages.success(request, _(message_text))
return True
except Exception:
message_text = "Unable to start plugin on device " \
+ str(data["name"]) + "."
exceptions.handle(request, _(message_text))
class StopPluginForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
delay = forms.IntegerField(
label=_("Delay in secs"),
required=False,
help_text=_("OPTIONAL: seconds to wait before stopping the plugin")
)
# plugin_list = forms.MultipleChoiceField(
plugin_list = forms.ChoiceField(
label=_("Plugins List"),
# widget=forms.SelectMultiple(
widget=forms.Select(
attrs={'class': 'switchable', 'data-slug': 'slug-stop-plugin'}),
help_text=_("Select plugins in this pool ")
)
def __init__(self, *args, **kwargs):
super(StopPluginForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
self.fields["plugin_list"].choices = kwargs["initial"]["plugin_list"]
def handle(self, request, data):
# counter = 0
if not data["delay"]:
data["delay"] = {}
else:
data["delay"] = {"delay": data["delay"]}
try:
action = iotronic.plugin_action(request,
data["uuid"],
data["plugin_list"],
"PluginStop",
data["delay"])
message_text = action
messages.success(request, _(message_text))
return True
except Exception:
message_text = "Unable to stop plugin on device " \
+ str(data["name"]) + "."
exceptions.handle(request, _(message_text))
class RemovePluginsForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
plugin_list = forms.MultipleChoiceField(
label=_("Plugins List"),
widget=forms.SelectMultiple(
attrs={'class': 'switchable', 'data-slug': 'slug-remove-plugins'}),
help_text=_("Select plugins in this pool ")
)
def __init__(self, *args, **kwargs):
super(RemovePluginsForm, self).__init__(*args, **kwargs)
# input=kwargs.get('initial',{})
self.fields["plugin_list"].choices = kwargs["initial"]["plugin_list"]
def handle(self, request, data):
counter = 0
for plugin in data["plugin_list"]:
for key, value in self.fields["plugin_list"].choices:
if key == plugin:
try:
iotronic.plugin_remove(request, data["uuid"], key)
message_text = "Plugin " + str(value) + \
" removed successfully."
messages.success(request, _(message_text))
if counter != len(data["plugin_list"]) - 1:
counter += 1
else:
return True
except Exception:
message_text = "Unable to remove plugin " \
+ str(value) + "."
exceptions.handle(request, _(message_text))
break

View File

@ -0,0 +1,27 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
from django.utils.translation import ugettext_lazy as _
import horizon
from iotronic_ui.iot import dashboard
class PluginsDevices(horizon.Panel):
name = _("Devices")
slug = "plugins_devices"
dashboard.Iot.register(PluginsDevices)

View File

@ -0,0 +1,128 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import logging
from django import template
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy
from horizon import tables
from openstack_dashboard import api
# from iotronic_ui import api
LOG = logging.getLogger(__name__)
class DeviceFilterAction(tables.FilterAction):
# If uncommented it will appear the select menu list of fields
# and filter button
"""
filter_type = "server"
filter_choices = (("name", _("Device Name ="), True),
("type", _("Type ="), True),
("status", _("Status ="), True))
"""
def filter(self, table, devices, filter_string):
"""Naive case-insensitive search."""
q = filter_string.lower()
return [device for device in devices
if q in device.name.lower()]
def show_services(device_info):
template_name = 'iot/plugins_devices/_cell_services.html'
context = device_info._info
# LOG.debug("CONTEXT: %s", context)
return template.loader.render_to_string(template_name,
context)
class InjectPluginLink(tables.LinkAction):
name = "inject"
verbose_name = _("Inject Plugin")
url = "horizon:iot:plugins_devices:inject"
classes = ("ajax-modal",)
icon = "plus"
# policy_rules = (("iot", "iot:inject_plugin"),)
class CallPluginLink(tables.LinkAction):
name = "call"
verbose_name = _("Call Plugin")
url = "horizon:iot:plugins_devices:call"
classes = ("ajax-modal",)
icon = "plus"
# policy_rules = (("iot", "iot:call_plugin"),)
class StartPluginLink(tables.LinkAction):
name = "start"
verbose_name = _("Start Plugin")
url = "horizon:iot:plugins_devices:start"
classes = ("ajax-modal",)
icon = "plus"
# policy_rules = (("iot", "iot:start_plugin"),)
class StopPluginLink(tables.LinkAction):
name = "stop"
verbose_name = _("Stop Plugin")
url = "horizon:iot:plugins_devices:stop"
classes = ("ajax-modal",)
icon = "plus"
# policy_rules = (("iot", "iot:stop_plugin"),)
class RemovePluginsLink(tables.LinkAction):
name = "removeplugins"
verbose_name = _("Remove Plugin(s)")
url = "horizon:iot:plugins_devices:removeplugins"
classes = ("ajax-modal",)
icon = "plus"
# policy_rules = (("iot", "iot:remove_plugins"),)
class DevicesTable(tables.DataTable):
name = tables.WrappingColumn('name',
link="horizon:iot:plugins_devices:detail",
verbose_name=_('Device Name'))
type = tables.Column('type', verbose_name=_('Type'))
# mobile = tables.Column('mobile', verbose_name=_('Mobile'))
lr_version = tables.Column('lr_version', verbose_name=_('LR version'))
# fleet = tables.Column('fleet', verbose_name=_('Fleet ID'))
fleet_name = tables.Column('fleet_name', verbose_name=_('Fleet Name'))
# code = tables.Column('code', verbose_name=_('Code'))
status = tables.Column('status', verbose_name=_('Status'))
uuid = tables.Column('uuid', verbose_name=_('Device ID'))
# location = tables.Column('location', verbose_name=_('Geo'))
services = tables.Column(show_services, verbose_name=_('SSH Access'))
# extra = tables.Column('extra', verbose_name=_('Extra'))
# Overriding get_object_id method because in IoT service the "id" is
# identified by the field UUID
def get_object_id(self, datum):
return datum.uuid
class Meta(object):
name = "devices"
verbose_name = _("devices")
row_actions = (InjectPluginLink, CallPluginLink, StartPluginLink,
StopPluginLink, RemovePluginsLink,)
table_actions = (DeviceFilterAction,)

View File

@ -0,0 +1,53 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import logging
# from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from horizon import tabs
LOG = logging.getLogger(__name__)
class OverviewTab(tabs.Tab):
name = _("Overview")
slug = "overview"
template_name = ("iot/plugins_devices/_detail_overview.html")
def get_context_data(self, request):
coordinates = self.tab_group.kwargs['device'].__dict__['location'][0]
ports = self.tab_group.kwargs['device']._info['ports']
services = self.tab_group.kwargs['device']._info['services']
webservices = self.tab_group.kwargs['device']._info['webservices']
plugins = self.tab_group.kwargs['device']._info['plugins']
return {"device": self.tab_group.kwargs['device'],
"coordinates": coordinates,
"services": services,
"webservices": webservices,
"ports": ports,
"plugins": plugins,
"is_superuser": request.user.is_superuser}
class DeviceDetailTabs(tabs.TabGroup):
slug = "device_details"
# tabs = (OverviewTab, LogTab, ConsoleTab, AuditTab)
tabs = (OverviewTab,)
sticky = True

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Call a plugin on device." %}</p>
{% endblock %}

View File

@ -0,0 +1,16 @@
{% load i18n %}
{% if services %}
{% for service in services %}
{% if service.name == "ssh" %}
<dd>ssh -p {{ service.public_port}} root@{{ service.wstun_ip }}</dd>
{% elif service.name == "nodered" %}
<dd>https://nodered.bla.bla.eu</dd>
{% elif service.name == "http" %}
<dd>https://{{ service.wstun_ip }}:{{ service.public_port }}</dd>
{% else %}
<dd>{{ service.name }} [{{ service.protocol }}] {{ service.port }} --> {{ service.public_port }}</dd>
{% endif %}
{% endfor %}
{% else %}
<dd>--</dd>
{% endif %}

View File

@ -0,0 +1,137 @@
{% load i18n sizeformat %}
<div class="detail">
<h4>{% trans "Info" %}</h4>
<hr class="header_rule">
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ device.name }}</dd>
<dt>{% trans "Status" %}</dt>
<dd>{{ device.status }}</dd>
<dt>{% trans "Type" %}</dt>
<dd>{{ device.type }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ device.uuid }}</dd>
<dt>{% trans "LR version" %}</dt>
<dd>{{ device.lr_version }}</dd>
<dt>{% trans "WAMP Agent" %}</dt>
<dd>{{ device.agent }}</dd>
<dt>{% trans "Code" %}</dt>
<dd>{{ device.code }}</dd>
<dt>{% trans "Creation data" %}</dt>
<dd>{{ device.created_at }}</dd>
<dt>{% trans "Location" %}</dt>
<dd>Latitude: {{ coordinates.latitude }}</dd>
<dd>Longitude: {{ coordinates.longitude }}</dd>
<dd>Altitude: {{ coordinates.altitude }}</dd>
<dt>{% trans "Connectivity" %}</dt>
{% if device.connectivity.mac %}
<dd>MAC: {{ device.connectivity.mac }}</dd>
<dd>Interface: {{ device.connectivity.iface }}</dd>
<dd>Local IP: {{ device.connectivity.local_ip }}</dd>
{% else %}
<dd>--</dd>
{% endif %}
<dt>{% trans "Mobile" %}</dt>
<dd>{{ device.mobile }}</dd>
<dt>{% trans "Extra" %}</dt>
<dd>{{ device.extra }}</dd>
<dt>{% trans "Fleet Name" %}</dt>
<dd>{{ device.fleet_name }}</dd>
<dt>{% trans "Fleet ID" %}</dt>
<dd>{{ device.fleet }}</dd>
</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 %}
<!--
<dt>{{ service.name }} [{{ service.protocol }}] {{ service.port }}</dt>
<dd>{{ service.public_port }}</dd>
-->
<!--
<dt>{{ service.name }}</dt>
<dd>[{{ service.protocol }}] L: {{ service.port }}; P: {{ service.public_port }}</dd>
-->
<dt>{{ service.name }}</dt>
{% if service.name == "ssh" %}
<dd>ssh -p {{ service.public_port}} root@{{ service.wstun_ip }}</dd>
{% elif service.name == "nodered" %}
<dd><a href="http://{{ service.wstun_ip }}:{{ service.public_port }}" target="_blank">http://{{ service.wstun_ip }}:{{ service.public_port }}</a></dd>
{% else %}
<dd>{{ service.name }} [{{ service.protocol }}] {{ service.port }} --> {{ service.public_port }}</dd>
{% endif %}
{% endfor %}
{% else %}
<dd>--</dd>
{% endif %}
</dl>
<h4>{% trans "Web Services" %}</h4>
<hr class="header_rule">
<dl class="dl-horizontal">
{% if webservices %}
{% for ws in webservices %}
<dt>{{ ws.name }} [{{ ws.port }}]</dt>
<dd>{{ ws.uuid }}</dd>
{% endfor %}
{% else %}
<dd>--</dd>
{% 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.uuid }}</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(){
/*
coordinates = JSON.parse(document.getElementById("mapdiv").getAttribute("data-coordinates"));
lat = coordinates[0]["latitude"];
lon = coordinates[0]["longitude"];
alt = coordinates[0]["altitude"];
*/
var lat = "{{ coordinates.latitude }}";
var lon = "{{ coordinates.longitude }}";
var alt = "{{ coordinates.altitude }}";
var label = "{{ board.name }}";
var status = "{{ board.status }}";
var updated = "{{ board.updated_at }}";
var array_coord = {"coordinates" : [{"lat": lat, "lon": lon, "alt": alt, "updated": updated, "label": label, "status": status}]}
render_map("mapdiv", array_coord);
});
</script>
</div>
-->

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Inject a plugin into the device." %}</p>
{% endblock %}

View File

@ -0,0 +1,8 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Remove plugin(s) from this device." %}</p>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Start a plugin on device(s)." %}</p>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Stop a plugin on device(s)." %}</p>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Call Plugin" %}{% endblock %}
{% block main %}
{% include 'iot/plugins_devices/_call.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Devices" %}{% endblock %}
{% block main %}
{{ table.render }}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Inject Plugin" %}{% endblock %}
{% block main %}
{% include 'iot/plugins_devices/_inject.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Remove plugin(s) from this device." %}{% endblock %}
{% block main %}
{% include 'iot/plugins_devices/_removeplugins.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Start Plugin" %}{% endblock %}
{% block main %}
{% include 'iot/plugins_devices/_start.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Stop Plugin" %}{% endblock %}
{% block main %}
{% include 'iot/plugins_devices/_stop.html' %}
{% endblock %}

View File

@ -0,0 +1,19 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from horizon.test import helpers as test
class DevicesTests(test.TestCase):
# Unit tests for devices.
def test_me(self):
self.assertTrue(1 + 1 == 2)

View File

@ -0,0 +1,36 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
from django.conf.urls import url
from iotronic_ui.iot.plugins_devices import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<device_id>[^/]+)/detail/$', views.DeviceDetailView.as_view(),
name='detail'),
url(r'^(?P<device_id>[^/]+)/inject/$', views.InjectView.as_view(),
name='inject'),
url(r'^(?P<device_id>[^/]+)/call/$', views.CallView.as_view(),
name='call'),
url(r'^(?P<device_id>[^/]+)/start/$', views.StartView.as_view(),
name='start'),
url(r'^(?P<device_id>[^/]+)/stop/$', views.StopView.as_view(),
name='stop'),
url(r'^(?P<device_id>[^/]+)/removeplugins/$',
views.RemovePluginsView.as_view(), name='removeplugins'),
]

View File

@ -0,0 +1,468 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import logging
from django.conf import settings
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
# from horizon import messages
from horizon import tables
from horizon import tabs
from horizon.utils import memoized
from openstack_dashboard import api
# from iotronic_ui.api import iotronic
from openstack_dashboard import policy
from iotronic_ui.iot.plugins_devices import forms as project_forms
from iotronic_ui.iot.plugins_devices import tables as project_tables
from iotronic_ui.iot.plugins_devices import tabs as project_tabs
LOG = logging.getLogger(__name__)
class IndexView(tables.DataTableView):
table_class = project_tables.DevicesTable
template_name = 'iot/plugins_devices/index.html'
page_title = _("Devices")
def get_data(self):
devices = []
# Admin
if policy.check((("iot", "iot:list_all_boards"),), self.request):
try:
devices = api.iotronic.device_list(self.request, None, None)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve devices list.'))
# Admin_iot_project
elif policy.check((("iot", "iot:list_project_boards"),), self.request):
try:
devices = api.iotronic.device_list(self.request, None, None)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve user devices list.'))
# Other users
else:
try:
devices = api.iotronic.device_list(self.request, None, None)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve user devices list.'))
for device in devices:
device_services = api.iotronic.services_on_device(self.request,
device.uuid,
True)
# x = api.iotronic.device_get(self.request, device.uuid, None)
# LOG.debug('DEVICE: %s', x)
# TO BE REMOVED
# ------------------------------------------------------------
filter_ws = []
for service in device_services:
# We are filtering the services that starts with "webservice"
"""
if ((service["name"] != "webservice") and
(service["name"] != "webservice_ssl")):
filter_ws.append(service)
"""
# We want to show only the "ssh" service
if (service["name"] == "ssh"):
service["wstun_ip"] = device.wstun_ip
filter_ws.append(service)
device_services = filter_ws
# ------------------------------------------------------------
# device.__dict__.update(dict(services=device_services))
device._info.update(dict(services=device_services))
if device.fleet != None:
fleet_info = api.iotronic.fleet_get(self.request,
device.fleet,
None)
device.fleet_name = fleet_info.name
else:
device.fleet_name = None
devices.sort(key=lambda b: b.name)
return devices
class DetailView(tabs.TabView):
tab_group_class = project_tabs.DeviceDetailTabs
template_name = 'horizon/common/_detail.html'
page_title = "{{ device.name|default:device.uuid }}"
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
device = self.get_data()
context["device"] = device
context["url"] = reverse(self.redirect_url)
context["actions"] = self._get_actions(device)
return context
def _get_actions(self, device):
table = project_tables.DevicesTable(self.request)
return table.render_row_actions(device)
@memoized.memoized_method
def get_data(self):
device = []
device_id = self.kwargs['device_id']
try:
device_ports = []
device = api.iotronic.device_get(self.request, device_id, None)
# FIX this problem with the new APIs
# (remove the "if" clause with a better approach)
# #################################################################
ports = api.iotronic.port_list(self.request, device_id)
for port in ports:
if port._info["board_uuid"] == device_id:
device_ports.append(port._info)
device._info.update(dict(ports=device_ports))
# #################################################################
device_services = api.iotronic.services_on_device(self.request,
device_id, True)
# We have to add the wstun_ip to the service
for service in device_services:
service["wstun_ip"] = device.wstun_ip
device._info.update(dict(services=device_services))
device_plugins = api.iotronic.plugins_on_device(self.request,
device_id)
# Create a list with name and uuid
p_list = []
for p in device_plugins:
p_list.append({"uuid": p._info["uuid"], "name": p.name})
device_plugins = p_list
device._info.update(dict(plugins=device_plugins))
device_webservices = api.iotronic.webservices_on_device(self.request,
device_id)
device._info.update(dict(webservices=device_webservices))
# Adding fleet name
if device.fleet != None:
fleet_info = api.iotronic.fleet_get(self.request,
device.fleet,
None)
device.fleet_name = fleet_info.name
else:
device.fleet_name = None
# Adding LR web service description
lr_ws = api.iotronic.webservice_get_enabled_info(self.request,
device_id)
device._info.update(dict(lr_webservice=lr_ws))
except Exception:
msg = ('Unable to retrieve device %s information') % {'name':
device.name}
exceptions.handle(self.request, msg, ignore=True)
return device
def get_tabs(self, request, *args, **kwargs):
device = self.get_data()
return self.tab_group_class(request, device=device, **kwargs)
class DeviceDetailView(DetailView):
redirect_url = 'horizon:iot:plugins_devices:index'
def _get_actions(self, device):
table = project_tables.DevicesTable(self.request)
return table.render_row_actions(device)
class InjectView(forms.ModalFormView):
template_name = 'iot/plugins_devices/inject.html'
modal_header = _("Inject Plugin")
form_id = "inject_plugin_form"
form_class = project_forms.InjectPluginForm
submit_label = _("Inject Plugin")
# submit_url = reverse_lazy("horizon:iot:plugins_devices:inject")
submit_url = "horizon:iot:plugins_devices:inject"
success_url = reverse_lazy('horizon:iot:plugins_devices:index')
page_title = _("Inject Plugin")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:plugins_devices:index")
exceptions.handle(self.request,
_('Unable to get device information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(InjectView, 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):
device = self.get_object()
# Populate plugins (not yet injected)
plugins = api.iotronic.plugin_list(self.request, None, None,
all_plugins=True)
plg_ondevice = api.iotronic.plugins_on_device(self.request,
device.uuid)
diff = []
if len(plg_ondevice) != 0:
for p in plugins:
count = 0
for d in plg_ondevice:
if d._info["uuid"] == p.uuid:
break
elif d._info["uuid"] != p.uuid and count == len(plg_ondevice) - 1:
diff.append(p)
else:
count += 1
plugins = diff
plugins.sort(key=lambda b: b.name)
plugin_list = []
for plugin in plugins:
plugin_list.append((plugin.uuid, _(plugin.name)))
return {'uuid': device.uuid,
'name': device.name,
'plugin_list': plugin_list}
class CallView(forms.ModalFormView):
template_name = 'iot/plugins_devices/call.html'
modal_header = _("Call Plugin")
form_id = "call_plugin_form"
form_class = project_forms.CallPluginForm
submit_label = _("Call Plugin")
# submit_url = reverse_lazy("horizon:iot:plugins_devices:call")
submit_url = "horizon:iot:plugins_devices:call"
success_url = reverse_lazy('horizon:iot:plugins_devices:index')
page_title = _("Call Plugin")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:plugins_devices:index")
exceptions.handle(self.request,
_('Unable to get device information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(CallView, 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):
device = self.get_object()
# Populate plugins
plugins = api.iotronic.plugin_list(self.request, None, None,
all_plugins=True)
plugins.sort(key=lambda b: b.name)
plugin_list = []
for plugin in plugins:
if plugin.callable == True:
plugin_list.append((plugin.uuid, _(plugin.name)))
return {'uuid': device.uuid,
'name': device.name,
'plugin_list': plugin_list}
class StartView(forms.ModalFormView):
template_name = 'iot/plugins_devices/start.html'
modal_header = _("Start Plugin")
form_id = "call_plugin_form"
form_class = project_forms.StartPluginForm
submit_label = _("Start Plugin")
# submit_url = reverse_lazy("horizon:iot:plugins_devices:start")
submit_url = "horizon:iot:plugins_devices:start"
success_url = reverse_lazy('horizon:iot:plugins_devices:index')
page_title = _("Start Plugin")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:plugins_devices:index")
exceptions.handle(self.request,
_('Unable to get device information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(StartView, 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):
device = self.get_object()
# Populate plugins
# plugins = api.iotronic.plugin_list(self.request, None, None,
# all_plugins=True)
plugins = api.iotronic.plugins_on_device(self.request, device.uuid)
plugins.sort(key=lambda b: b.name)
plugin_list = []
for plugin in plugins:
if plugin.callable == False:
plugin_list.append((plugin._info["uuid"], _(plugin.name)))
return {'uuid': device.uuid,
'name': device.name,
'plugin_list': plugin_list}
class StopView(forms.ModalFormView):
template_name = 'iot/plugins_devices/stop.html'
modal_header = _("Stop Plugin")
form_id = "call_plugin_form"
form_class = project_forms.StopPluginForm
submit_label = _("Stop Plugin")
# submit_url = reverse_lazy("horizon:iot:plugins_devices:stop")
submit_url = "horizon:iot:plugins_devices:stop"
success_url = reverse_lazy('horizon:iot:plugins_devices:index')
page_title = _("Stop Plugin")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:plugins_devices:index")
exceptions.handle(self.request,
_('Unable to get device information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(StopView, 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):
device = self.get_object()
# Populate plugins
plugins = api.iotronic.plugin_list(self.request, None, None,
all_plugins=True)
plugins.sort(key=lambda b: b.name)
plugin_list = []
for plugin in plugins:
if plugin.callable == False:
plugin_list.append((plugin.uuid, _(plugin.name)))
return {'uuid': device.uuid,
'name': device.name,
'plugin_list': plugin_list}
class RemovePluginsView(forms.ModalFormView):
template_name = 'iot/plugins_devices/removeplugins.html'
modal_header = _("Remove Plugins from device")
form_id = "remove_deviceplugins_form"
form_class = project_forms.RemovePluginsForm
submit_label = _("Remove")
# submit_url = reverse_lazy("horizon:iot:plugins_devices:removeplugins")
submit_url = "horizon:iot:plugins_devices:removeplugins"
success_url = reverse_lazy('horizon:iot:plugins_devices:index')
page_title = _("Remove Plugins from device")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:plugins_devices:index")
exceptions.handle(self.request,
_('Unable to get device information.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(RemovePluginsView, 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):
device = self.get_object()
# Populate plugins
# TO BE DONE.....filter by available on this device!!!
# plugins = api.iotronic.plugin_list(self.request, None, None)
plugins = api.iotronic.plugins_on_device(self.request, device.uuid)
plugins.sort(key=lambda b: b.name)
plugin_list = []
for plugin in plugins:
plugin_list.append((plugin._info["uuid"], _(plugin.name)))
return {'uuid': device.uuid,
'name': device.name,
'plugin_list': plugin_list}

View File

@ -0,0 +1,115 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import logging
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon import messages
from openstack_dashboard.api import iotronic
# from iotronic_ui.api import iotronic
# from openstack_dashboard import policy
LOG = logging.getLogger(__name__)
class EnableServiceForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device 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=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device 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))

View File

@ -0,0 +1,27 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
from django.utils.translation import ugettext_lazy as _
import horizon
from iotronic_ui.iot import dashboard
class ServicesDevices(horizon.Panel):
name = _("Devices")
slug = "services_devices"
dashboard.Iot.register(ServicesDevices)

View File

@ -0,0 +1,119 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import logging
from django import template
from django.utils.translation import ugettext_lazy as _
# from django.utils.translation import ungettext_lazy
from horizon import tables
from openstack_dashboard import api
# from iotronic_ui import api
LOG = logging.getLogger(__name__)
class DeviceFilterAction(tables.FilterAction):
# If uncommented it will appear the select menu list of fields
# and filter button
"""
filter_type = "server"
filter_choices = (("name", _("Device Name ="), True),
("type", _("Type ="), True),
("status", _("Status ="), True))
"""
def filter(self, table, devices, filter_string):
"""Naive case-insensitive search."""
q = filter_string.lower()
return [device for device in devices
if q in device.name.lower()]
def show_services(device_info):
template_name = 'iot/services_devices/_cell_services.html'
context = device_info._info
# LOG.debug("CONTEXT: %s", context)
return template.loader.render_to_string(template_name,
context)
class EnableServiceLink(tables.LinkAction):
name = "enableservice"
verbose_name = _("Enable Service(s)")
url = "horizon:iot:services_devices: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:services_devices:disableservice"
classes = ("ajax-modal",)
# icon = "plus"
# policy_rules = (("iot", "iot:service_action"),)
class RestoreServices(tables.BatchAction):
name = "restoreservices"
@staticmethod
def action_present(count):
return u"Restore ALL Services"
@staticmethod
def action_past(count):
return u"Restored ALL Services"
def allowed(self, request, device=None):
return True
def action(self, request, device_id):
api.iotronic.restore_services(request, device_id)
class DevicesTable(tables.DataTable):
name = tables.WrappingColumn('name',
link="horizon:iot:services_devices:detail",
verbose_name=_('Device Name'))
type = tables.Column('type', verbose_name=_('Type'))
# mobile = tables.Column('mobile', verbose_name=_('Mobile'))
lr_version = tables.Column('lr_version', verbose_name=_('LR version'))
# fleet = tables.Column('fleet', verbose_name=_('Fleet ID'))
fleet_name = tables.Column('fleet_name', verbose_name=_('Fleet Name'))
# code = tables.Column('code', verbose_name=_('Code'))
status = tables.Column('status', verbose_name=_('Status'))
uuid = tables.Column('uuid', verbose_name=_('Device ID'))
# location = tables.Column('location', verbose_name=_('Geo'))
services = tables.Column(show_services, verbose_name=_('SSH Access'))
# extra = tables.Column('extra', verbose_name=_('Extra'))
# Overriding get_object_id method because in IoT service the "id" is
# identified by the field UUID
def get_object_id(self, datum):
return datum.uuid
class Meta(object):
name = "devices"
verbose_name = _("devices")
row_actions = (EnableServiceLink, DisableServiceLink,
RestoreServices,)
table_actions = (DeviceFilterAction,)

View File

@ -0,0 +1,53 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import logging
# from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from horizon import tabs
LOG = logging.getLogger(__name__)
class OverviewTab(tabs.Tab):
name = _("Overview")
slug = "overview"
template_name = ("iot/services_devices/_detail_overview.html")
def get_context_data(self, request):
coordinates = self.tab_group.kwargs['device'].__dict__['location'][0]
ports = self.tab_group.kwargs['device']._info['ports']
services = self.tab_group.kwargs['device']._info['services']
webservices = self.tab_group.kwargs['device']._info['webservices']
plugins = self.tab_group.kwargs['device']._info['plugins']
return {"device": self.tab_group.kwargs['device'],
"coordinates": coordinates,
"services": services,
"webservices": webservices,
"ports": ports,
"plugins": plugins,
"is_superuser": request.user.is_superuser}
class DeviceDetailTabs(tabs.TabGroup):
slug = "device_details"
# tabs = (OverviewTab, LogTab, ConsoleTab, AuditTab)
tabs = (OverviewTab,)
sticky = True

View File

@ -0,0 +1,16 @@
{% load i18n %}
{% if services %}
{% for service in services %}
{% if service.name == "ssh" %}
<dd>ssh -p {{ service.public_port}} root@{{ service.wstun_ip }}</dd>
{% elif service.name == "nodered" %}
<dd>https://nodered.bla.bla.eu</dd>
{% elif service.name == "http" %}
<dd>https://{{ service.wstun_ip }}:{{ service.public_port }}</dd>
{% else %}
<dd>{{ service.name }} [{{ service.protocol }}] {{ service.port }} --> {{ service.public_port }}</dd>
{% endif %}
{% endfor %}
{% else %}
<dd>--</dd>
{% endif %}

View File

@ -0,0 +1,137 @@
{% load i18n sizeformat %}
<div class="detail">
<h4>{% trans "Info" %}</h4>
<hr class="header_rule">
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ device.name }}</dd>
<dt>{% trans "Status" %}</dt>
<dd>{{ device.status }}</dd>
<dt>{% trans "Type" %}</dt>
<dd>{{ device.type }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ device.uuid }}</dd>
<dt>{% trans "LR version" %}</dt>
<dd>{{ device.lr_version }}</dd>
<dt>{% trans "WAMP Agent" %}</dt>
<dd>{{ device.agent }}</dd>
<dt>{% trans "Code" %}</dt>
<dd>{{ device.code }}</dd>
<dt>{% trans "Creation data" %}</dt>
<dd>{{ device.created_at }}</dd>
<dt>{% trans "Location" %}</dt>
<dd>Latitude: {{ coordinates.latitude }}</dd>
<dd>Longitude: {{ coordinates.longitude }}</dd>
<dd>Altitude: {{ coordinates.altitude }}</dd>
<dt>{% trans "Connectivity" %}</dt>
{% if device.connectivity.mac %}
<dd>MAC: {{ device.connectivity.mac }}</dd>
<dd>Interface: {{ device.connectivity.iface }}</dd>
<dd>Local IP: {{ device.connectivity.local_ip }}</dd>
{% else %}
<dd>--</dd>
{% endif %}
<dt>{% trans "Mobile" %}</dt>
<dd>{{ device.mobile }}</dd>
<dt>{% trans "Extra" %}</dt>
<dd>{{ device.extra }}</dd>
<dt>{% trans "Fleet Name" %}</dt>
<dd>{{ device.fleet_name }}</dd>
<dt>{% trans "Fleet ID" %}</dt>
<dd>{{ device.fleet }}</dd>
</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 %}
<!--
<dt>{{ service.name }} [{{ service.protocol }}] {{ service.port }}</dt>
<dd>{{ service.public_port }}</dd>
-->
<!--
<dt>{{ service.name }}</dt>
<dd>[{{ service.protocol }}] L: {{ service.port }}; P: {{ service.public_port }}</dd>
-->
<dt>{{ service.name }}</dt>
{% if service.name == "ssh" %}
<dd>ssh -p {{ service.public_port}} root@{{ service.wstun_ip }}</dd>
{% elif service.name == "nodered" %}
<dd><a href="http://{{ service.wstun_ip }}:{{ service.public_port }}" target="_blank">http://{{ service.wstun_ip }}:{{ service.public_port }}</a></dd>
{% else %}
<dd>{{ service.name }} [{{ service.protocol }}] {{ service.port }} --> {{ service.public_port }}</dd>
{% endif %}
{% endfor %}
{% else %}
<dd>--</dd>
{% endif %}
</dl>
<h4>{% trans "Web Services" %}</h4>
<hr class="header_rule">
<dl class="dl-horizontal">
{% if webservices %}
{% for ws in webservices %}
<dt>{{ ws.name }} [{{ ws.port }}]</dt>
<dd>{{ ws.uuid }}</dd>
{% endfor %}
{% else %}
<dd>--</dd>
{% 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(){
/*
coordinates = JSON.parse(document.getElementById("mapdiv").getAttribute("data-coordinates"));
lat = coordinates[0]["latitude"];
lon = coordinates[0]["longitude"];
alt = coordinates[0]["altitude"];
*/
var lat = "{{ coordinates.latitude }}";
var lon = "{{ coordinates.longitude }}";
var alt = "{{ coordinates.altitude }}";
var label = "{{ board.name }}";
var status = "{{ board.status }}";
var updated = "{{ board.updated_at }}";
var array_coord = {"coordinates" : [{"lat": lat, "lon": lon, "alt": alt, "updated": updated, "label": label, "status": status}]}
render_map("mapdiv", array_coord);
});
</script>
</div>
-->

View File

@ -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 device." %}</p>
{% endblock %}

View File

@ -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 device." %}</p>
{% endblock %}

View File

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

View File

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

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Devices" %}{% endblock %}
{% block main %}
{{ table.render }}
{% endblock %}

View File

@ -0,0 +1,19 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from horizon.test import helpers as test
class DevicesTests(test.TestCase):
# Unit tests for devices.
def test_me(self):
self.assertTrue(1 + 1 == 2)

View File

@ -0,0 +1,30 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
from django.conf.urls import url
from iotronic_ui.iot.services_devices import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<device_id>[^/]+)/detail/$', views.DeviceDetailView.as_view(),
name='detail'),
url(r'^(?P<device_id>[^/]+)/enableservice/$',
views.EnableServiceView.as_view(), name='enableservice'),
url(r'^(?P<device_id>[^/]+)/disableservice/$',
views.DisableServiceView.as_view(), name='disableservice'),
]

View File

@ -0,0 +1,358 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import logging
# from django.conf import settings
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
# from horizon import messages
from horizon import tables
from horizon import tabs
from horizon.utils import memoized
from openstack_dashboard import api
# from iotronic_ui.api import iotronic
from openstack_dashboard import policy
from iotronic_ui.iot.services_devices import forms as project_forms
from iotronic_ui.iot.services_devices import tables as project_tables
from iotronic_ui.iot.services_devices import tabs as project_tabs
LOG = logging.getLogger(__name__)
class IndexView(tables.DataTableView):
table_class = project_tables.DevicesTable
template_name = 'iot/services_devices/index.html'
page_title = _("Devices")
def get_data(self):
devices = []
# Admin
if policy.check((("iot", "iot:list_all_boards"),), self.request):
try:
devices = api.iotronic.device_list(self.request, None, None)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve devices list.'))
# Admin_iot_project
elif policy.check((("iot", "iot:list_project_boards"),), self.request):
try:
devices = api.iotronic.device_list(self.request, None, None)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve user devices list.'))
# Other users
else:
try:
devices = api.iotronic.device_list(self.request, None, None)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve user devices list.'))
for device in devices:
device_services = api.iotronic.services_on_device(self.request,
device.uuid,
True)
# x = api.iotronic.device_get(self.request, device.uuid, None)
# LOG.debug('DEVICE: %s', x)
# TO BE REMOVED
# ------------------------------------------------------------
filter_ws = []
for service in device_services:
# We are filtering the services that starts with "webservice"
"""
if ((service["name"] != "webservice") and
(service["name"] != "webservice_ssl")):
filter_ws.append(service)
"""
# We want to show only the "ssh" service
if (service["name"] == "ssh"):
service["wstun_ip"] = device.wstun_ip
filter_ws.append(service)
device_services = filter_ws
# ------------------------------------------------------------
# device.__dict__.update(dict(services=device_services))
device._info.update(dict(services=device_services))
if device.fleet != None:
fleet_info = api.iotronic.fleet_get(self.request,
device.fleet,
None)
device.fleet_name = fleet_info.name
else:
device.fleet_name = None
devices.sort(key=lambda b: b.name)
# LOG.debug('DEVICES: %s', devices)
return devices
class DetailView(tabs.TabView):
tab_group_class = project_tabs.DeviceDetailTabs
template_name = 'horizon/common/_detail.html'
page_title = "{{ device.name|default:device.uuid }}"
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
device = self.get_data()
context["device"] = device
context["url"] = reverse(self.redirect_url)
context["actions"] = self._get_actions(device)
return context
def _get_actions(self, device):
table = project_tables.DevicesTable(self.request)
return table.render_row_actions(device)
@memoized.memoized_method
def get_data(self):
device = []
device_id = self.kwargs['device_id']
try:
device_ports = []
device = api.iotronic.device_get(self.request, device_id, None)
# FIX this problem with the new APIs
# (remove the "if" clause with a better approach)
# #################################################################
ports = api.iotronic.port_list(self.request, device_id)
for port in ports:
if port._info["board_uuid"] == device_id:
device_ports.append(port._info)
device._info.update(dict(ports=device_ports))
# #################################################################
device_services = api.iotronic.services_on_device(self.request,
device_id, True)
# We have to add the wstun_ip to the service
for service in device_services:
service["wstun_ip"] = device.wstun_ip
device._info.update(dict(services=device_services))
device_plugins = api.iotronic.plugins_on_device(self.request,
device_id)
device._info.update(dict(plugins=device_plugins))
device_webservices = api.iotronic.webservices_on_device(self.request,
device_id)
# LOG.debug('DEVICE %s, WEB SERVICES: %s', device_id, device_webservices)
device._info.update(dict(webservices=device_webservices))
# Adding fleet name
if device.fleet != None:
fleet_info = api.iotronic.fleet_get(self.request,
device.fleet,
None)
device.fleet_name = fleet_info.name
else:
device.fleet_name = None
# Adding LR web service description
lr_ws = api.iotronic.webservice_get_enabled_info(self.request,
device_id)
device._info.update(dict(lr_webservice=lr_ws))
# LOG.debug("DEVICE: %s\n\n%s", device, device._info)
except Exception:
msg = ('Unable to retrieve device %s information') % {'name':
device.name}
exceptions.handle(self.request, msg, ignore=True)
return device
def get_tabs(self, request, *args, **kwargs):
device = self.get_data()
return self.tab_group_class(request, device=device, **kwargs)
class EnableServiceView(forms.ModalFormView):
template_name = 'iot/services_devices/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:services_devices:enableservice")
submit_url = "horizon:iot:services_devices:enableservice"
success_url = reverse_lazy('horizon:iot:services_devices:index')
page_title = _("Action")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:services_devices:index")
exceptions.handle(self.request,
_('Unable to get device 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):
device = self.get_object()
# Populate available services
cloud_services = api.iotronic.service_list(self.request, None)
device_services = api.iotronic.services_on_device(self.request,
device.uuid,
True)
cloud_services.sort(key=lambda b: b.name)
service_list = []
# LOG.debug('CLOUD SERVICES: %s', cloud_services)
for cloud_service in cloud_services:
uuid = cloud_service._info["uuid"]
name = cloud_service._info["name"]
if len(device_services) == 0:
# BEFORE filtering necessity
# service_list.append((cloud_service._info["uuid"],
# _(cloud_service._info["name"])))
# AFTER filtering necessity
# We are filtering the services that starts with "webservice"
if ((name != "webservice") and (name != "webservice_ssl")):
service_list.append((uuid, _(name)))
else:
counter = 0
for device_service in device_services:
if device_service["uuid"] == cloud_service._info["uuid"]:
break
elif counter != len(device_services) - 1:
counter += 1
else:
# BEFORE filtering necessity
# service_list.append((uuid, _(name)))
# AFTER filtering necessity
# We are filtering the services that starts
# with "webservice"
if ((name != "webservice") and ("name" != "webservice_ssl")):
service_list.append((uuid, _(name)))
# LOG.debug('SERVICES: %s', service_list)
return {'uuid': device.uuid,
'name': device.name,
'service_list': service_list}
class DisableServiceView(forms.ModalFormView):
template_name = 'iot/services_devices/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:services_devices:disableservice")
submit_url = "horizon:iot:services_devices:disableservice"
success_url = reverse_lazy('horizon:iot:services_devices:index')
page_title = _("Action")
@memoized.memoized_method
def get_object(self):
try:
return api.iotronic.device_get(self.request,
self.kwargs['device_id'],
None)
except Exception:
redirect = reverse("horizon:iot:services_devices:index")
exceptions.handle(self.request,
_('Unable to get device 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):
device = self.get_object()
# Populate available services
cloud_services = api.iotronic.service_list(self.request, None)
device_services = api.iotronic.services_on_device(self.request,
device.uuid,
True)
cloud_services.sort(key=lambda b: b.name)
service_list = []
# BEFORE filtering necessity
"""
for cloud_service in cloud_services:
for device_service in device_services:
if device_service["uuid"] == cloud_service._info["uuid"]:
service_list.append((cloud_service._info["uuid"],
_(cloud_service._info["name"])))
"""
# AFTER filtering necessity
# We are filtering the services that starts with "webservice"
# ------------------------------------------------------------
for cloud_service in cloud_services:
for device_service in device_services:
if ((device_service["uuid"] == cloud_service._info["uuid"]) and ((device_service["name"] != "webservice") and (device_service["name"] != "webservice_ssl"))):
service_list.append((cloud_service._info["uuid"], _(cloud_service._info["name"])))
# ------------------------------------------------------------
return {'uuid': device.uuid,
'name': device.name,
'service_list': service_list}
class DeviceDetailView(DetailView):
redirect_url = 'horizon:iot:services_devices:index'
def _get_actions(self, device):
table = project_tables.DevicesTable(self.request)
return table.render_row_actions(device)

View File

@ -82,6 +82,24 @@ def show_webservices(board_info):
context)
class RestoreServices(tables.BatchAction):
name = "restoreservices"
@staticmethod
def action_present(count):
return u"Restore ALL Services"
@staticmethod
def action_past(count):
return u"Restored ALL Services"
def allowed(self, request, device=None):
return True
def action(self, request, device_id):
api.iotronic.restore_services(request, device_id)
class WebservicesTable(tables.DataTable):
"""
@ -90,11 +108,14 @@ class WebservicesTable(tables.DataTable):
verbose_name=_('UUID'))
"""
board = tables.Column('name', verbose_name=_('Board Name'))
status = tables.Column('status', verbose_name=_('Status'))
board_uuid = tables.Column('board_uuid',
board_uuid = tables.Column('board_uuid',
verbose_name=_('Board UUID'),
hidden=True)
# ssh = tables.Column('ssh', verbose_name=_('SSH Access'))
webservices = tables.Column(show_webservices,
verbose_name=_('Web Services'))
@ -116,6 +137,6 @@ class WebservicesTable(tables.DataTable):
DisableWebservicesAction)
table_actions = (WebserviceFilterAction, DisableWebservicesAction)
"""
row_actions = (ExposeWebserviceLink,
UnexposeWebserviceLink)
row_actions = (ExposeWebserviceLink, UnexposeWebserviceLink,
RestoreServices,)
table_actions = (WebserviceFilterAction,)

View File

@ -15,7 +15,7 @@ import logging
# from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from horizon import tabs
# from horizon import tabs
LOG = logging.getLogger(__name__)

View File

@ -20,7 +20,7 @@ from horizon import exceptions
from horizon import forms
# from horizon import messages
from horizon import tables
from horizon import tabs
# from horizon import tabs
from horizon.utils import memoized
from openstack_dashboard.api import iotronic
@ -28,7 +28,7 @@ from openstack_dashboard import policy
from iotronic_ui.iot.webservices import forms as project_forms
from iotronic_ui.iot.webservices import tables as project_tables
from iotronic_ui.iot.webservices import tabs as project_tabs
# from iotronic_ui.iot.webservices import tabs as project_tabs
LOG = logging.getLogger(__name__)
@ -80,8 +80,22 @@ class IndexView(tables.DataTableView):
# Append some information to the webservice
# LOG.debug('WSS: %s', webservices)
for ws_en in en_webservices:
board = iotronic.board_get(self.request, ws_en.board_uuid, None)
"""
services = iotronic.services_on_board(self.request,
ws_en.board_uuid,
True)
LOG.debug('SERVICES: %s', services)
ssh_access = "--"
for service in services:
if (service["name"] == "ssh"):
ssh_access = "ssh -p " + str(service["public_port"]) +\
" root@x.x.x.x"
break
"""
ws_list = []
ws_list.append({"local_port": "LR",
"service_url": "https://" + ws_en.dns + "." + ws_en.zone})
for ws in webservices:
if ws_en.board_uuid == ws.board_uuid:
@ -93,8 +107,10 @@ class IndexView(tables.DataTableView):
ws_en.uuid = ws.uuid
board = iotronic.board_get(self.request, ws_en.board_uuid, None)
# board = iotronic.board_get(self.request, ws_en.board_uuid, None)
ws_en.name = board.name
ws_en.status = board.status
# ws_en.ssh = ssh_access
ws_en._info.update(dict(webservices=ws_list))
return en_webservices

View File

@ -0,0 +1,94 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import logging
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon import messages
from openstack_dashboard.api import iotronic
# from iotronic_ui.api import iotronic
# from openstack_dashboard import policy
LOG = logging.getLogger(__name__)
class EnableWebServiceForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
dns = forms.CharField(label=_("Domain Name Server"))
# zone = forms.CharField(label=_("Zone"))
zones_list = forms.ChoiceField(
label=_("Zones List"),
help_text=_("Select a zone from the list")
)
email = forms.CharField(label=_("Email"))
def __init__(self, *args, **kwargs):
super(EnableWebServiceForm, self).__init__(*args, **kwargs)
zone_choices = kwargs["initial"]["zones_list"]
self.fields["zones_list"].choices = zone_choices
def handle(self, request, data):
try:
iotronic.webservice_enable(request, data["uuid"],
data["dns"], data["zones_list"],
data["email"])
messages.success(request, _("Web Service enabled on device " + str(data["name"]) + "."))
return True
except Exception:
message_text = "Unable to enable web service."
exceptions.handle(request, _(message_text))
class DisableWebServiceForm(forms.SelfHandlingForm):
uuid = forms.CharField(label=_("Device ID"), widget=forms.HiddenInput)
name = forms.CharField(
label=_('Device Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'})
)
def __init__(self, *args, **kwargs):
super(DisableWebServiceForm, self).__init__(*args, **kwargs)
def handle(self, request, data):
try:
iotronic.webservice_disable(request, data["uuid"])
messages.success(request, _("Web Service disabled on device " + str(data["name"]) + "."))
return True
except Exception:
message_text = "Unable to disable web service."
exceptions.handle(request, _(message_text))

View File

@ -0,0 +1,27 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
from django.utils.translation import ugettext_lazy as _
import horizon
from iotronic_ui.iot import dashboard
class WebServicesDevices(horizon.Panel):
name = _("Devices")
slug = "webservices_devices"
dashboard.Iot.register(WebServicesDevices)

View File

@ -0,0 +1,117 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import logging
from django import template
from django.utils.translation import ugettext_lazy as _
# from django.utils.translation import ungettext_lazy
from horizon import tables
from openstack_dashboard import api
# from iotronic_ui import api
LOG = logging.getLogger(__name__)
class DeviceFilterAction(tables.FilterAction):
# If uncommented it will appear the select menu list of fields
# and filter button
"""
filter_type = "server"
filter_choices = (("name", _("Device Name ="), True),
("type", _("Type ="), True),
("status", _("Status ="), True))
"""
def filter(self, table, devices, filter_string):
"""Naive case-insensitive search."""
q = filter_string.lower()
return [device for device in devices
if q in device.name.lower()]
def show_services(device_info):
template_name = 'iot/webservices_devices/_cell_services.html'
context = device_info._info
# LOG.debug("CONTEXT: %s", context)
return template.loader.render_to_string(template_name,
context)
class EnableWebServiceLink(tables.LinkAction):
name = "enablewebservice"
verbose_name = _("Enable Web Services Manager")
url = "horizon:iot:webservices_devices:enablewebservice"
classes = ("ajax-modal",)
icon = "plus"
class DisableWebServiceLink(tables.LinkAction):
name = "disablewebservice"
verbose_name = _("Disable Web Services Manager")
url = "horizon:iot:webservices_devices:disablewebservice"
classes = ("ajax-modal",)
icon = "plus"
class RestoreServices(tables.BatchAction):
name = "restoreservices"
@staticmethod
def action_present(count):
return u"Restore ALL Services"
@staticmethod
def action_past(count):
return u"Restored ALL Services"
def allowed(self, request, device=None):
return True
def action(self, request, device_id):
api.iotronic.restore_services(request, device_id)
class DevicesTable(tables.DataTable):
name = tables.WrappingColumn('name',
link="horizon:iot:webservices_devices:detail",
verbose_name=_('Device Name'))
type = tables.Column('type', verbose_name=_('Type'))
# mobile = tables.Column('mobile', verbose_name=_('Mobile'))
lr_version = tables.Column('lr_version', verbose_name=_('LR version'))
# fleet = tables.Column('fleet', verbose_name=_('Fleet ID'))
fleet_name = tables.Column('fleet_name', verbose_name=_('Fleet Name'))
# code = tables.Column('code', verbose_name=_('Code'))
status = tables.Column('status', verbose_name=_('Status'))
uuid = tables.Column('uuid', verbose_name=_('Device ID'))
# location = tables.Column('location', verbose_name=_('Geo'))
services = tables.Column(show_services, verbose_name=_('SSH Access'))
# extra = tables.Column('extra', verbose_name=_('Extra'))
# Overriding get_object_id method because in IoT service the "id" is
# identified by the field UUID
def get_object_id(self, datum):
return datum.uuid
class Meta(object):
name = "devices"
verbose_name = _("devices")
row_actions = (RestoreServices, EnableWebServiceLink,
DisableWebServiceLink)
table_actions = (DeviceFilterAction,)

View File

@ -0,0 +1,53 @@
# Copyright 2017-2019 MDSLAB - University of Messina All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
author = "Carmelo Romeo <carmelo.romeo85@gmail.com>"
import logging
# from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from horizon import tabs
LOG = logging.getLogger(__name__)
class OverviewTab(tabs.Tab):
name = _("Overview")
slug = "overview"
template_name = ("iot/webservices_devices/_detail_overview.html")
def get_context_data(self, request):
coordinates = self.tab_group.kwargs['device'].__dict__['location'][0]
ports = self.tab_group.kwargs['device']._info['ports']
services = self.tab_group.kwargs['device']._info['services']
webservices = self.tab_group.kwargs['device']._info['webservices']
plugins = self.tab_group.kwargs['device']._info['plugins']
return {"device": self.tab_group.kwargs['device'],
"coordinates": coordinates,
"services": services,
"webservices": webservices,
"ports": ports,
"plugins": plugins,
"is_superuser": request.user.is_superuser}
class DeviceDetailTabs(tabs.TabGroup):
slug = "device_details"
# tabs = (OverviewTab, LogTab, ConsoleTab, AuditTab)
tabs = (OverviewTab,)
sticky = True

Some files were not shown because too many files have changed in this diff Show More