Support NFV Orchestration API v2.0
Support the latest NFV Orchestration API v2.0 listed below. * VNF LCM v2 * VNF FM v1 * VNF PM v2 In addition, to manage VNF packages for testing purposes, also support Orchestration API v1.0 listed below. * VNF packages Implements: blueprint v2-api-horizon Change-Id: I0284cba30154cf4cc5d496be157288e2c2614ccf
This commit is contained in:
parent
4709605bd5
commit
a1840d24ba
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Support the latest NFV Orchestration API v2.0 listed below.
|
||||
|
||||
* Virtualized Network Function Lifecycle Management Interface (VNF LCM) v2
|
||||
* Virtualized Network Function Fault Management Interface (VNF FM) v1
|
||||
* Virtualized Network Function Performance Management Interface (VNF PM) v2
|
||||
|
||||
In addition, to manage VNF packages for testing purposes, also support
|
||||
Orchestration API v1.0 listed below.
|
||||
|
||||
* Virtualized Network Function Packages (VNF packages)
|
|
@ -44,10 +44,11 @@ CERT_VERIFY_TYPES = (
|
|||
|
||||
|
||||
@memoized
|
||||
def tackerclient(request):
|
||||
def tackerclient(request, api_version="1"):
|
||||
insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
|
||||
cacert = getattr(settings, 'OPENSTACK_SSL_CACERT', None)
|
||||
c = tacker_client.Client(
|
||||
api_version=api_version,
|
||||
token=request.user.token.id,
|
||||
auth_url=base.url_for(request, 'identity'),
|
||||
endpoint_url=base.url_for(request, 'nfv-orchestration'),
|
||||
|
@ -251,3 +252,370 @@ def create_ns(request, ns_arg, **params):
|
|||
LOG.debug("create_ns(): ns_arg=%s", str(ns_arg))
|
||||
ns_instance = tackerclient(request).create_ns(body=ns_arg)
|
||||
return ns_instance
|
||||
|
||||
|
||||
# VNF Packages v1
|
||||
@profiler.trace
|
||||
def create_vnf_package(request, body):
|
||||
LOG.debug("create_vnf_package(): body=%s", body)
|
||||
vnf_package = tackerclient(request).create_vnf_package(body=body)
|
||||
return vnf_package
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def list_vnf_packages(request, **params):
|
||||
LOG.debug("list_vnf_packages(): params=%s", params)
|
||||
vnf_packages = tackerclient(request).list_vnf_packages(**params).get(
|
||||
'vnf_packages')
|
||||
return vnf_packages
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def get_vnf_package(request, vnf_pkg_id):
|
||||
LOG.debug("get_vnf_package(): vnf_pkg_id=%s", vnf_pkg_id)
|
||||
vnf_package = tackerclient(request).show_vnf_package(vnf_pkg_id)
|
||||
return vnf_package
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def delete_vnf_package(request, vnf_pkg_id):
|
||||
LOG.debug("delete_vnf_package(): vnf_pkg_id=%s", vnf_pkg_id)
|
||||
result = tackerclient(request).delete_vnf_package(vnf_pkg_id)
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def upload_vnf_package(request, vnf_pkg_id, file_data=None, **params):
|
||||
LOG.debug("upload_vnf_package(): vnf_pkg_id=%s, params=%s",
|
||||
vnf_pkg_id, params)
|
||||
vnf_package = tackerclient(request).upload_vnf_package(
|
||||
vnf_pkg_id, file_data=file_data, **params)
|
||||
return vnf_package
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def update_vnf_package(request, vnf_pkg_id, body):
|
||||
LOG.debug("update_vnf_package(): vnf_pkg_id=%s, body=%s",
|
||||
vnf_pkg_id, body)
|
||||
updated_values = tackerclient(request).update_vnf_package(
|
||||
vnf_pkg_id, body=body)
|
||||
return updated_values
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def fetch_vnf_package(request, vnf_pkg_id):
|
||||
LOG.debug("fetch_vnf_package(): vnf_pkg_id=%s", vnf_pkg_id)
|
||||
vnf_package_file = tackerclient(request).download_vnf_package(vnf_pkg_id)
|
||||
return vnf_package_file
|
||||
|
||||
|
||||
# VNF LCM v2
|
||||
@profiler.trace
|
||||
def create_vnf_instance(request, body):
|
||||
LOG.debug("create_vnf_instance(): body=%s", body)
|
||||
vnf_instance = (tackerclient(request, api_version="2")
|
||||
.create_vnf_instance(body=body))
|
||||
return vnf_instance
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def get_vnf_instance(request, vnf_instance_id):
|
||||
LOG.debug("get_vnf_instance(): vnf_instance_id=%s", vnf_instance_id)
|
||||
vnf_instance = (tackerclient(request, api_version="2")
|
||||
.show_vnf_instance(vnf_instance_id))
|
||||
return vnf_instance
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def list_vnf_instances(request, **params):
|
||||
LOG.debug("list_vnf_instances(): params=%s", params)
|
||||
vnf_instances = (tackerclient(request, api_version="2")
|
||||
.list_vnf_instances(**params))
|
||||
return vnf_instances
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def delete_vnf_instance(request, vnf_instance_id):
|
||||
LOG.debug("delete_vnf_instance(): vnf_instance_id=%s", vnf_instance_id)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.delete_vnf_instance(vnf_instance_id))
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def instantiate_vnf_instance(request, vnf_instance_id, body):
|
||||
LOG.debug("instantiate_vnf_instance(): vnf_instance_id=%s, body=%s",
|
||||
vnf_instance_id, body)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.instantiate_vnf_instance(vnf_instance_id, body=body))
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def terminate_vnf_instance(request, vnf_instance_id, body):
|
||||
LOG.debug("terminate_vnf_instance(): vnf_instance_id=%s, body=%s",
|
||||
vnf_instance_id, body)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.terminate_vnf_instance(vnf_instance_id, body=body))
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def heal_vnf_instance(request, vnf_instance_id, body):
|
||||
LOG.debug("heal_vnf_instance(): vnf_instance_id=%s, body=%s",
|
||||
vnf_instance_id, body)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.heal_vnf_instance(vnf_instance_id, body=body))
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def update_vnf_instance(request, vnf_instance_id, body):
|
||||
LOG.debug("update_vnf_instance(): vnf_instance_id=%s, body=%s",
|
||||
vnf_instance_id, body)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.update_vnf_instance(vnf_instance_id, body=body))
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def scale_vnf_instance(request, vnf_instance_id, body):
|
||||
LOG.debug("scale_vnf_instance(): vnf_instance_id=%s, body=%s",
|
||||
vnf_instance_id, body)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.scale_vnf_instance(vnf_instance_id, body=body))
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def change_ext_conn_vnf_instance(request, vnf_instance_id, body):
|
||||
LOG.debug("change_ext_conn_vnf_instance(): vnf_instance_id=%s, body=%s",
|
||||
vnf_instance_id, body)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.change_ext_conn_vnf_instance(vnf_instance_id, body=body))
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def change_vnfpkg_vnf_instance(request, vnf_instance_id, body):
|
||||
LOG.debug("change_vnfpkg_vnf_instance(): vnf_instance_id=%s, body=%s",
|
||||
vnf_instance_id, body)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.change_vnfpkg_vnf_instance(vnf_instance_id, body=body))
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def list_vnf_lcm_op_occs(request, **params):
|
||||
LOG.debug("list_vnf_lcm_op_occs(): params=%s", params)
|
||||
op_occs = (tackerclient(request, api_version="2")
|
||||
.list_vnf_lcm_op_occs(**params))
|
||||
return op_occs
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def get_vnf_lcm_op_occ(request, op_occ_id):
|
||||
LOG.debug("get_vnf_lcm_op_occ(): op_occ_id=%s", op_occ_id)
|
||||
op_occ = (tackerclient(request, api_version="2")
|
||||
.show_vnf_lcm_op_occs(op_occ_id))
|
||||
return op_occ
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def rollback_vnf_lcm_op_occ(request, op_occ_id):
|
||||
LOG.debug("rollback_vnf_lcm_op_occ(): op_occ_id=%s", op_occ_id)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.rollback_vnf_instance(op_occ_id))
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def retry_vnf_lcm_op_occ(request, op_occ_id):
|
||||
LOG.debug("retry_vnf_lcm_op_occ(): op_occ_id=%s", op_occ_id)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.retry_vnf_instance(op_occ_id))
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def fail_vnf_lcm_op_occ(request, op_occ_id):
|
||||
LOG.debug("fail_vnf_lcm_op_occs(): op_occ_id=%s", op_occ_id)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.fail_vnf_instance(op_occ_id))
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def list_vnf_lcm_subscriptions(request, **params):
|
||||
LOG.debug("list_vnf_lcm_subscriptions(): params=%s", params)
|
||||
subscriptions = (tackerclient(request, api_version="2")
|
||||
.list_lccn_subscriptions(**params))
|
||||
return subscriptions
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def get_vnf_lcm_subscription(request, subsc_id):
|
||||
LOG.debug("get_vnf_lcm_subscription(): subsc_id=%s", subsc_id)
|
||||
subscription = (tackerclient(request, api_version="2")
|
||||
.show_lccn_subscription(subsc_id))
|
||||
return subscription
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def delete_vnf_lcm_subscription(request, subsc_id):
|
||||
LOG.debug("delete_vnf_lcm_subscription(): subsc_id=%s", subsc_id)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.delete_lccn_subscription(subsc_id))
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def create_vnf_lcm_subscription(request, param):
|
||||
LOG.debug("create_vnf_lcm_subscription(): param=%s", param)
|
||||
subscription = (tackerclient(request, api_version="2")
|
||||
.create_lccn_subscription(body=param))
|
||||
return subscription
|
||||
|
||||
|
||||
# VNF FM v1
|
||||
@profiler.trace
|
||||
def list_fm_alarms(request, **params):
|
||||
LOG.debug("list_fm_alarms(): params=%s", params)
|
||||
fm_alarms = tackerclient(request).list_vnf_fm_alarms(**params).get(
|
||||
'vnf_fm_alarms')
|
||||
return fm_alarms
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def get_fm_alarm(request, alarm_id):
|
||||
LOG.debug("get_fm_alarm(): alarm_id=%s", alarm_id)
|
||||
fm_alarm = tackerclient(request).show_vnf_fm_alarm(alarm_id)
|
||||
return fm_alarm
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def update_fm_alarm(request, alarm_id, body):
|
||||
LOG.debug("update_fm_alarm(): alarm_id=%s, body=%s", alarm_id, body)
|
||||
updated_values = tackerclient(request).update_vnf_fm_alarm(
|
||||
alarm_id, body=body)
|
||||
return updated_values
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def create_fm_subscription(request, body):
|
||||
LOG.debug("create_fm_subscription(): body=%s", body)
|
||||
fm_subscription = tackerclient(request).create_vnf_fm_sub(body=body)
|
||||
return fm_subscription
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def list_fm_subscriptions(request, **params):
|
||||
LOG.debug("list_fm_subscriptions(): params=%s", params)
|
||||
fm_subscriptions = tackerclient(request).list_vnf_fm_subs(**params).get(
|
||||
'vnf_fm_subs')
|
||||
return fm_subscriptions
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def get_fm_subscription(request, subsc_id):
|
||||
LOG.debug("get_fm_subscription(): subsc_id=%s", subsc_id)
|
||||
fm_subscription = tackerclient(request).show_vnf_fm_sub(subsc_id)
|
||||
return fm_subscription
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def delete_fm_subscription(request, subsc_id):
|
||||
LOG.debug("delete_fm_subscription(): subsc_id=%s", subsc_id)
|
||||
result = tackerclient(request).delete_vnf_fm_sub(subsc_id)
|
||||
return result
|
||||
|
||||
|
||||
# VNF PM v2
|
||||
@profiler.trace
|
||||
def create_pm_job(request, body):
|
||||
LOG.debug("create_pm_job(): body=%s", body)
|
||||
pm_job = (tackerclient(request, api_version="2")
|
||||
.create_vnf_pm_job(body=body))
|
||||
return pm_job
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def list_pm_jobs(request, **params):
|
||||
LOG.debug("list_pm_jobs(): params=%s", params)
|
||||
pm_jobs = (tackerclient(request, api_version="2")
|
||||
.list_vnf_pm_jobs(**params).get('vnf_pm_jobs'))
|
||||
return pm_jobs
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def get_pm_job(request, pm_job_id):
|
||||
LOG.debug("get_pm_job(): pm_job_id=%s", pm_job_id)
|
||||
pm_job = tackerclient(request, api_version="2").show_vnf_pm_job(pm_job_id)
|
||||
return pm_job
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def update_pm_job(request, pm_job_id, body):
|
||||
LOG.debug("update_pm_job(): pm_job_id=%s, body=%s", pm_job_id, body)
|
||||
updated_values = (tackerclient(request, api_version="2")
|
||||
.update_vnf_pm_job(pm_job_id, body=body))
|
||||
return updated_values
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def delete_pm_job(request, pm_job_id):
|
||||
LOG.debug("delete_pm_job(): pm_job_id=%s", pm_job_id)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.delete_vnf_pm_job(pm_job_id))
|
||||
return result
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def get_pm_report(request, pm_job_id, pm_report_id):
|
||||
LOG.debug("get_pm_report(): pm_job_id=%s, pm_report_id=%s",
|
||||
pm_job_id, pm_report_id)
|
||||
pm_report = (tackerclient(request, api_version="2")
|
||||
.show_vnf_pm_report(pm_job_id, pm_report_id))
|
||||
return pm_report
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def create_pm_threshold(request, body):
|
||||
LOG.debug("create_pm_threshold(): body=%s", body)
|
||||
pm_threshold = (tackerclient(request, api_version="2")
|
||||
.create_vnf_pm_threshold(body=body))
|
||||
return pm_threshold
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def list_pm_thresholds(request, **params):
|
||||
LOG.debug("list_pm_thresholds(): params=%s", params)
|
||||
pm_thresholds = (tackerclient(request, api_version="2")
|
||||
.list_vnf_pm_thresholds(**params)
|
||||
.get('vnf_pm_thresholds'))
|
||||
return pm_thresholds
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def get_pm_threshold(request, pm_threshold_id):
|
||||
LOG.debug("get_pm_threshold(): pm_threshold_id=%s", pm_threshold_id)
|
||||
pm_threshold = (tackerclient(request, api_version="2")
|
||||
.show_vnf_pm_threshold(pm_threshold_id))
|
||||
return pm_threshold
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def update_pm_threshold(request, pm_threshold_id, body):
|
||||
LOG.debug("update_pm_threshold(): pm_threshold_id=%s, body=%s",
|
||||
pm_threshold_id, body)
|
||||
updated_values = (tackerclient(request, api_version="2")
|
||||
.update_vnf_pm_threshold(pm_threshold_id, body=body))
|
||||
return updated_values
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def delete_pm_threshold(request, pm_threshold_id):
|
||||
LOG.debug("delete_pm_threshold(): pm_threshold_id=%s", pm_threshold_id)
|
||||
result = (tackerclient(request, api_version="2")
|
||||
.delete_vnf_pm_threshold(pm_threshold_id))
|
||||
return result
|
||||
|
|
|
@ -20,21 +20,46 @@ import horizon
|
|||
|
||||
class Vnfmgroup(horizon.PanelGroup):
|
||||
slug = "nfvgroup"
|
||||
name = _("VNF Management")
|
||||
name = _("(Legacy)VNF Management")
|
||||
panels = ('vnfcatalog', 'vnfmanager',)
|
||||
|
||||
|
||||
class Nfvogroup(horizon.PanelGroup):
|
||||
slug = "nfvogroup"
|
||||
name = _("NFV Orchestration")
|
||||
name = _("(Legacy)NFV Orchestration")
|
||||
panels = ('vim', 'vnffgcatalog', 'vnffgmanager',
|
||||
'nscatalog', 'nsmanager')
|
||||
|
||||
|
||||
class Vnfpkggroup(horizon.PanelGroup):
|
||||
slug = "vnfpkggroup"
|
||||
name = _("VNF Packages v1")
|
||||
panels = ('vnfpackages',)
|
||||
|
||||
|
||||
class Vnflcmgroup(horizon.PanelGroup):
|
||||
slug = "vnflcmgroup"
|
||||
name = _("VNF LCM v2")
|
||||
panels = ('vnflcm', 'vnflcmopocc', 'lccnsubscription',)
|
||||
|
||||
|
||||
class Vnffmgroup(horizon.PanelGroup):
|
||||
slug = "vnffmgroup"
|
||||
name = _("VNF FM v1")
|
||||
panels = ('vnffmalarm', 'vnffmsubscription',)
|
||||
|
||||
|
||||
class Vnfpmgroup(horizon.PanelGroup):
|
||||
slug = "vnfpmgroup"
|
||||
name = _("VNF PM v2")
|
||||
panels = ('vnfpmjob', 'vnfpmthreshold',)
|
||||
|
||||
|
||||
class Nfv(horizon.Dashboard):
|
||||
name = _("NFV")
|
||||
slug = "nfv"
|
||||
panels = (Vnfmgroup, Nfvogroup,) # Add your panels here.
|
||||
panels = (Vnfmgroup, Nfvogroup, Vnfpkggroup, Vnflcmgroup, Vnffmgroup,
|
||||
Vnfpmgroup,) # Add your panels here.
|
||||
default_panel = 'vnfcatalog' # Specify the slug of the dashboard's
|
||||
# default panel.
|
||||
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
import json
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import messages
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
|
||||
|
||||
class CreateLccnSubscription(forms.SelfHandlingForm):
|
||||
param_file = forms.FileField(
|
||||
label=_("Param File"),
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-upload': _('Param File')}))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(CreateLccnSubscription, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(CreateLccnSubscription, self).clean()
|
||||
|
||||
try:
|
||||
param_str = self.files['param_file'].read()
|
||||
param = json.loads(param_str)
|
||||
data['param_data'] = param
|
||||
except Exception as e:
|
||||
msg = _('Failed to read file: %s.') % e
|
||||
raise forms.ValidationError(msg)
|
||||
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
param = data['param_data']
|
||||
subsc = api.tacker.create_vnf_lcm_subscription(request, param)
|
||||
messages.success(
|
||||
request,
|
||||
_('Create LCCN Subscription. (id: %s)') % subsc['id'])
|
||||
|
||||
except Exception:
|
||||
exceptions.handle(
|
||||
request,
|
||||
_('Failed to create LCCN Subscription.'))
|
||||
return False
|
||||
|
||||
return True
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
import horizon
|
||||
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv import dashboard
|
||||
|
||||
|
||||
class LccnSubscription(horizon.Panel):
|
||||
name = _("LCCN Subscription")
|
||||
slug = "lccnsubscription"
|
||||
|
||||
|
||||
dashboard.Nfv.register(LccnSubscription)
|
|
@ -0,0 +1,69 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext_lazy
|
||||
|
||||
from horizon import tables
|
||||
from openstack_dashboard import policy
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
|
||||
|
||||
class DeleteLccnSubscription(policy.PolicyTargetMixin, tables.DeleteAction):
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
return ngettext_lazy(
|
||||
"Delete Lccn Subscription",
|
||||
"Delete Lccn Subscriptions",
|
||||
count
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def action_past(count):
|
||||
return ngettext_lazy(
|
||||
"Delete Lccn Subscription",
|
||||
"Delete Lccn Subscriptions",
|
||||
count
|
||||
)
|
||||
|
||||
def action(self, request, obj_id):
|
||||
api.tacker.delete_vnf_lcm_subscription(request, obj_id)
|
||||
|
||||
|
||||
class CreateLccnSubscription(tables.LinkAction):
|
||||
name = "create_lccnsubsc"
|
||||
verbose_name = _("Create Lccn Subscription")
|
||||
classes = ("ajax-modal",)
|
||||
icon = "plus"
|
||||
url = "horizon:nfv:lccnsubscription:createlccnsubscription"
|
||||
|
||||
|
||||
class LccnSubscriptionTable(tables.DataTable):
|
||||
id = tables.Column('id', verbose_name=_("ID"),
|
||||
link="horizon:nfv:lccnsubscription:detail",)
|
||||
callback_uri = tables.Column('callback_uri',
|
||||
verbose_name=_("Callback URI"))
|
||||
|
||||
class Meta(object):
|
||||
name = "lccnsubsc"
|
||||
verbose_name = _("LCCN Subscription")
|
||||
pagination_param = 'subsc_marker'
|
||||
prev_pagination_param = 'prev_subsc_marker'
|
||||
table_actions = (CreateLccnSubscription, DeleteLccnSubscription,
|
||||
tables.FilterAction)
|
||||
row_actions = (DeleteLccnSubscription,)
|
||||
multi_select = True
|
|
@ -0,0 +1,109 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs
|
||||
from horizon import utils as horizon_utils
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.lccnsubscription \
|
||||
import tables
|
||||
|
||||
|
||||
class LccnSubscItem(object):
|
||||
def __init__(self, subsc_id, callback_uri):
|
||||
self.id = subsc_id
|
||||
self.name = subsc_id
|
||||
self.callback_uri = callback_uri
|
||||
|
||||
|
||||
class LccnSubscriptionTab(tabs.TableTab):
|
||||
name = _("LCCN Subscription tab")
|
||||
slug = "lccnsubsc_tab"
|
||||
table_classes = (tables.LccnSubscriptionTable,)
|
||||
template_name = ("horizon/common/_detail_table.html")
|
||||
preload = False
|
||||
|
||||
def has_prev_data(self, table):
|
||||
return self._has_prev
|
||||
|
||||
def has_more_data(self, table):
|
||||
return self._has_more
|
||||
|
||||
def get_lccnsubsc_data(self):
|
||||
try:
|
||||
self._has_prev = False
|
||||
page_size = horizon_utils.functions.get_page_size(self.request)
|
||||
marker = self.request.GET.get(
|
||||
"subsc_marker", None)
|
||||
prev_marker = self.request.GET.get(
|
||||
"prev_subsc_marker", None)
|
||||
subscs = api.tacker.list_vnf_lcm_subscriptions(
|
||||
self.request)
|
||||
if marker is not None or prev_marker is not None:
|
||||
for i, subsc in enumerate(subscs):
|
||||
if subsc["id"] == marker and i < len(subscs) - 1:
|
||||
subscs = subscs[i + 1:]
|
||||
self._has_prev = True
|
||||
break
|
||||
if subsc["id"] == prev_marker and i > page_size:
|
||||
subscs = subscs[i - page_size:]
|
||||
self._has_prev = True
|
||||
break
|
||||
|
||||
if len(subscs) > page_size:
|
||||
self._has_more = True
|
||||
else:
|
||||
self._has_more = False
|
||||
|
||||
rows = []
|
||||
for i, subsc in enumerate(subscs):
|
||||
if i >= page_size:
|
||||
break
|
||||
item = LccnSubscItem(
|
||||
subsc_id=subsc.get('id', ''),
|
||||
callback_uri=subsc.get('callbackUri', ''))
|
||||
rows.append(item)
|
||||
return rows
|
||||
except Exception:
|
||||
self._has_more = False
|
||||
error_message = _('Failed to get LCCN Subscriptions.')
|
||||
exceptions.handle(self.request, error_message)
|
||||
|
||||
return []
|
||||
|
||||
|
||||
class LccnSubscriptionTabs(tabs.TabGroup):
|
||||
slug = "lccnsubsc_tabs"
|
||||
tabs = (LccnSubscriptionTab,)
|
||||
sticky = True
|
||||
|
||||
|
||||
class LccnSubscDetailTab(tabs.Tab):
|
||||
name = _("LCCN Subscription Detail Tab")
|
||||
slug = "lccnsubsc_detail_tab"
|
||||
template_name = "nfv/lccnsubscription/lccnsubsc_detail.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
return {'lccnsubscription': self.tab_group.kwargs['lccnsubscription']}
|
||||
|
||||
|
||||
class LccnSubscDetailTabs(tabs.TabGroup):
|
||||
slug = "lccnsubsc_detail_tabs"
|
||||
tabs = (LccnSubscDetailTab,)
|
||||
sticky = True
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Create a Lccn Subscription." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "create_lccn_subscription" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("create_lccn_subscription") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/lccnsubscription/_create_lccn_subscription.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Lccn Subscription Detail" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=page_title %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "LCCN Subscription" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("LCCN Subscription") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,14 @@
|
|||
{% load i18n %}
|
||||
|
||||
<div class="detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Callback URI" %}</dt>
|
||||
<dd>{{ lccnsubscription.callbackUri }}</dd>
|
||||
<dt>{% trans "Filter" %}</dt>
|
||||
<dd>{{ lccnsubscription.filter }}</dd>
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ lccnsubscription.id }}</dd>
|
||||
<dt>{% trans "Links" %}</dt>
|
||||
<dd>{{ lccnsubscription.links }}</dd>
|
||||
</dl>
|
||||
</div>
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.urls import re_path
|
||||
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.lccnsubscription \
|
||||
import views
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^$', views.IndexView.as_view(), name='index'),
|
||||
re_path(r'^(?P<id>[^/]+)/$', views.DetailView.as_view(),
|
||||
name='detail'),
|
||||
re_path(r'^createlccnsubscription$',
|
||||
views.CreateLccnSubscriptionView.as_view(),
|
||||
name='createlccnsubscription'),
|
||||
]
|
|
@ -0,0 +1,88 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.urls import reverse
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import tabs
|
||||
from horizon.utils import memoized
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api as tacker_api
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.lccnsubscription \
|
||||
import forms as project_forms
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.lccnsubscription \
|
||||
import tabs as lccnsubsctabs
|
||||
|
||||
|
||||
class IndexView(tabs.TabbedTableView):
|
||||
tab_group_class = lccnsubsctabs.LccnSubscriptionTabs
|
||||
template_name = 'nfv/lccnsubscription/index.html'
|
||||
|
||||
|
||||
class CreateLccnSubscriptionView(forms.ModalFormView):
|
||||
form_class = project_forms.CreateLccnSubscription
|
||||
template_name = 'nfv/lccnsubscription/create_lccn_subscription.html'
|
||||
success_url = reverse_lazy("horizon:nfv:lccnsubscription:index")
|
||||
modal_id = "add_service_modal"
|
||||
modal_header = _("Create Lccn Subscription")
|
||||
submit_label = _("Create Lccn Subscription")
|
||||
submit_url = "horizon:nfv:lccnsubscription:createlccnsubscription"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(
|
||||
CreateLccnSubscriptionView, self).get_context_data(**kwargs)
|
||||
context['submit_url'] = reverse(self.submit_url)
|
||||
return context
|
||||
|
||||
|
||||
class DetailView(tabs.TabView):
|
||||
tab_group_class = lccnsubsctabs.LccnSubscDetailTabs
|
||||
template_name = 'nfv/lccnsubscription/detail.html'
|
||||
redirect_url = 'horizon:nfv:lccnsubscription:index'
|
||||
page_title = _("LCCN Subscription Detail")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
lccnsubscription = self.get_data()
|
||||
context['lccnsubscription'] = lccnsubscription
|
||||
context['id'] = kwargs['id']
|
||||
context['url'] = reverse(self.redirect_url)
|
||||
return context
|
||||
|
||||
@memoized.memoized_method
|
||||
def get_data(self):
|
||||
subsc_id = self.kwargs.get('id', None)
|
||||
|
||||
try:
|
||||
lccnsubscription = tacker_api.tacker.get_vnf_lcm_subscription(
|
||||
self.request, subsc_id)
|
||||
lccnsubscription['links'] = lccnsubscription.get('_links', '')
|
||||
return lccnsubscription
|
||||
except Exception as e:
|
||||
redirect = reverse(self.redirect_url)
|
||||
exceptions.handle(
|
||||
self.request,
|
||||
_('Failed to get LCCN Subscription. (id: %s)') % subsc_id,
|
||||
redirect=redirect)
|
||||
raise exceptions.Http302(redirect) from e
|
||||
|
||||
def get_tabs(self, request, *args, **kwargs):
|
||||
lccnsubscription = self.get_data()
|
||||
return self.tab_group_class(
|
||||
request, lccnsubscription=lccnsubscription, **kwargs)
|
|
@ -0,0 +1,52 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import messages
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
|
||||
|
||||
class UpdateVnfFmAlarm(forms.SelfHandlingForm):
|
||||
ack_state = forms.ChoiceField(
|
||||
label=_('ACK State'),
|
||||
choices=[('ACKNOWLEDGED', _('ACKNOWLEDGED')),
|
||||
('UNACKNOWLEDGED', _('UNACKNOWLEDGED'))])
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(UpdateVnfFmAlarm, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(UpdateVnfFmAlarm, self).clean()
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
ack_state = data.get('ack_state', None)
|
||||
|
||||
body = {}
|
||||
body['ackState'] = ack_state
|
||||
alarm_id = request.resolver_match.kwargs['id']
|
||||
api.tacker.update_fm_alarm(request, alarm_id, body)
|
||||
messages.success(request,
|
||||
_('Update FM Alarm. (id: %s)') % alarm_id)
|
||||
return True
|
||||
except Exception:
|
||||
msg = _('Failed to update FM Alarm. (id: %s)') % alarm_id
|
||||
exceptions.handle(request, msg)
|
||||
return False
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
import horizon
|
||||
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv import dashboard
|
||||
|
||||
|
||||
class VnfFmAlarm(horizon.Panel):
|
||||
name = _("Alarm")
|
||||
slug = "vnffmalarm"
|
||||
|
||||
|
||||
dashboard.Nfv.register(VnfFmAlarm)
|
|
@ -0,0 +1,48 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import tables
|
||||
|
||||
|
||||
class UpdateVnfFmAlarm(tables.LinkAction):
|
||||
name = "updatealarm"
|
||||
verbose_name = _("Update Alarm")
|
||||
url = "horizon:nfv:vnffmalarm:updatealarm"
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
|
||||
class VnfFmAlarmTable(tables.DataTable):
|
||||
id = tables.Column('id', link="horizon:nfv:vnffmalarm:detail",
|
||||
verbose_name=_("ID"))
|
||||
|
||||
managed_object_id = tables.Column('managed_object_id',
|
||||
verbose_name=_("Managed Object ID"))
|
||||
ack_state = tables.Column('ack_state', verbose_name=_("Ack State"))
|
||||
event_type = tables.Column('event_type', verbose_name=_("Event Type"))
|
||||
perceived_severity = tables.Column('perceived_severity',
|
||||
verbose_name=_("Perceived Severity"))
|
||||
probable_cause = tables.Column('probable_cause',
|
||||
verbose_name=_("Probable Cause"))
|
||||
|
||||
class Meta(object):
|
||||
name = "alarm"
|
||||
verbose_name = _("Alarm")
|
||||
pagination_param = 'vnffmalarm_marker'
|
||||
prev_pagination_param = 'prev_vnffmalarm_marker'
|
||||
table_actions = (tables.FilterAction,)
|
||||
row_actions = (UpdateVnfFmAlarm,)
|
|
@ -0,0 +1,114 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs
|
||||
from horizon import utils as horizon_utils
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnffmalarm \
|
||||
import tables
|
||||
|
||||
|
||||
class VnfFmAlarmItem(object):
|
||||
def __init__(self, alarm_id, managed_object_id, ack_state, event_type,
|
||||
perceived_severity, probable_cause):
|
||||
self.id = alarm_id
|
||||
self.name = alarm_id
|
||||
self.managed_object_id = managed_object_id
|
||||
self.ack_state = ack_state
|
||||
self.event_type = event_type
|
||||
self.perceived_severity = perceived_severity
|
||||
self.probable_cause = probable_cause
|
||||
|
||||
|
||||
class VnfFmAlarmTab(tabs.TableTab):
|
||||
name = _("VNFFMAlarm Tab")
|
||||
slug = "vnffmalarm_tab"
|
||||
table_classes = (tables.VnfFmAlarmTable,)
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
preload = False
|
||||
|
||||
def has_prev_data(self, table):
|
||||
return self._has_prev
|
||||
|
||||
def has_more_data(self, table):
|
||||
return self._has_more
|
||||
|
||||
def get_alarm_data(self):
|
||||
try:
|
||||
self._has_prev = False
|
||||
page_size = horizon_utils.functions.get_page_size(self.request)
|
||||
marker = self.request.GET.get("vnffmalarm_marker", None)
|
||||
prev_marker = self.request.GET.get("prev_vnffmalarm_marker", None)
|
||||
alarms = api.tacker.list_fm_alarms(self.request)
|
||||
|
||||
if marker is not None or prev_marker is not None:
|
||||
for i, alarm in enumerate(alarms):
|
||||
if alarm["id"] == marker and i < len(alarms) - 1:
|
||||
alarms = alarms[i + 1:]
|
||||
self._has_prev = True
|
||||
break
|
||||
if alarm["id"] == prev_marker and i > page_size:
|
||||
alarms = alarms[i - page_size:]
|
||||
self._has_prev = True
|
||||
break
|
||||
|
||||
if len(alarms) > page_size:
|
||||
self._has_more = True
|
||||
else:
|
||||
self._has_more = False
|
||||
|
||||
rows = []
|
||||
for i, alarm in enumerate(alarms):
|
||||
if i >= page_size:
|
||||
break
|
||||
item = VnfFmAlarmItem(alarm['id'],
|
||||
alarm['managedObjectId'],
|
||||
alarm['ackState'],
|
||||
alarm['eventType'],
|
||||
alarm['perceivedSeverity'],
|
||||
alarm['probableCause'])
|
||||
rows.append(item)
|
||||
return rows
|
||||
except Exception:
|
||||
self._has_more = False
|
||||
error_message = _('Failed to get FM Alarms.')
|
||||
exceptions.handle(self.request, error_message)
|
||||
return []
|
||||
|
||||
|
||||
class VnfFmAlarmTabs(tabs.TabGroup):
|
||||
slug = "vnffmalarm_tabs"
|
||||
tabs = (VnfFmAlarmTab,)
|
||||
sticky = True
|
||||
|
||||
|
||||
class VnfFmAlarmDetailTab(tabs.Tab):
|
||||
name = _("VNF FM Alarm")
|
||||
slug = "vnffmalarm_detail_tab"
|
||||
template_name = "nfv/vnffmalarm/alarm_detail.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
return {'alarm': self.tab_group.kwargs['alarm']}
|
||||
|
||||
|
||||
class VnfFmAlarmDetailTabs(tabs.TabGroup):
|
||||
slug = "vnffmalarm_detail_tabs"
|
||||
tabs = (VnfFmAlarmDetailTab,)
|
||||
sticky = True
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Update a Alarm." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,42 @@
|
|||
{% load i18n %}
|
||||
|
||||
<div class="detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Ack State" %}</dt>
|
||||
<dd>{{ alarm.ackState }}</dd>
|
||||
<dt title="Alarm Acknowledged Time">{% trans "Alarm Acknowledged Time" %}</dt>
|
||||
<dd>{{ alarm.alarmAcknowledgedTime }}</dd>
|
||||
<dt>{% trans "Alarm Changed Time" %}</dt>
|
||||
<dd>{{ alarm.alarmChangedTime }}</dd>
|
||||
<dt>{% trans "Alarm Cleared Time" %}</dt>
|
||||
<dd>{{ alarm.alarmClearedTime }}</dd>
|
||||
<dt>{% trans "Alarm Raised Time" %}</dt>
|
||||
<dd>{{ alarm.alarmRaisedTime }}</dd>
|
||||
<dt>{% trans "Correlated Alarm IDs" %}</dt>
|
||||
<dd>{{ alarm.correlatedAlarmIds }}</dd>
|
||||
<dt>{% trans "Event Time" %}</dt>
|
||||
<dd>{{ alarm.eventTime }}</dd>
|
||||
<dt>{% trans "Event Type" %}</dt>
|
||||
<dd>{{ alarm.eventType }}</dd>
|
||||
<dt>{% trans "Fault Details" %}</dt>
|
||||
<dd>{{ alarm.faultDetails }}</dd>
|
||||
<dt>{% trans "Fault Type" %}</dt>
|
||||
<dd>{{ alarm.faultType }}</dd>
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ alarm.id }}</dd>
|
||||
<dt>{% trans "Is Root Cause" %}</dt>
|
||||
<dd>{{ alarm.isRootCause }}</dd>
|
||||
<dt>{% trans "Links" %}</dt>
|
||||
<dd>{{ alarm.links }}</dd>
|
||||
<dt>{% trans "Managed Object ID" %}</dt>
|
||||
<dd>{{ alarm.managedObjectId }}</dd>
|
||||
<dt>{% trans "Perceived Severity" %}</dt>
|
||||
<dd>{{ alarm.perceivedSeverity }}</dd>
|
||||
<dt>{% trans "Probable Cause" %}</dt>
|
||||
<dd>{{ alarm.probableCause }}</dd>
|
||||
<dt title="Root Cause Faulty Resource">{% trans "Root Cause Faulty Resource" %}</dt>
|
||||
<dd>{{ alarm.rootCauseFaultyResource }}</dd>
|
||||
<dt>{% trans "VNFC Instance IDs" %}</dt>
|
||||
<dd>{{ alarm.vnfcInstanceIds }}</dd>
|
||||
</dl>
|
||||
</div>
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Alarm Detail" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=page_title %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Alarm" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Alarm") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Update Alarm" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Update Alarm") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/vnffmalarm/_update_alarm.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.urls import re_path
|
||||
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnffmalarm \
|
||||
import views
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^$', views.IndexView.as_view(), name='index'),
|
||||
re_path(r'^(?P<id>[^/]+)/updatealarm$',
|
||||
views.UpdateVnfFmAlarmView.as_view(),
|
||||
name='updatealarm'),
|
||||
re_path(r'^(?P<id>[^/]+)/$', views.DetailView.as_view(),
|
||||
name='detail'),
|
||||
]
|
|
@ -0,0 +1,90 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.urls import reverse
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import tabs
|
||||
from horizon.utils import memoized
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api as tacker_api
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnffmalarm \
|
||||
import forms as project_forms
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnffmalarm \
|
||||
import tabs as alarm_tabs
|
||||
|
||||
|
||||
class IndexView(tabs.TabbedTableView):
|
||||
# A very simple class-based view...
|
||||
tab_group_class = alarm_tabs.VnfFmAlarmTabs
|
||||
template_name = 'nfv/vnffmalarm/index.html'
|
||||
|
||||
def get_data(self, request, context, *args, **kwargs):
|
||||
# Add data to the context here...
|
||||
return context
|
||||
|
||||
|
||||
class UpdateVnfFmAlarmView(forms.ModalFormView):
|
||||
form_class = project_forms.UpdateVnfFmAlarm
|
||||
template_name = 'nfv/vnffmalarm/update_alarm.html'
|
||||
success_url = reverse_lazy("horizon:nfv:vnffmalarm:index")
|
||||
modal_id = "update_alarm_modal"
|
||||
modal_header = _("Update Alarm")
|
||||
submit_label = _("Update Alarm")
|
||||
submit_url = "horizon:nfv:vnffmalarm:updatealarm"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(UpdateVnfFmAlarmView, self).get_context_data(**kwargs)
|
||||
context['submit_url'] = reverse(self.submit_url,
|
||||
kwargs={'id': self.kwargs['id']})
|
||||
return context
|
||||
|
||||
|
||||
class DetailView(tabs.TabView):
|
||||
tab_group_class = alarm_tabs.VnfFmAlarmDetailTabs
|
||||
template_name = 'nfv/vnffmalarm/detail.html'
|
||||
redirect_url = 'horizon:nfv:vnffmalarm:index'
|
||||
page_title = _("Alarm Detail: {{ id }}")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
alarm = self.get_data()
|
||||
context['alarm'] = alarm
|
||||
context['id'] = kwargs['id']
|
||||
context['url'] = reverse(self.redirect_url)
|
||||
return context
|
||||
|
||||
@memoized.memoized_method
|
||||
def get_data(self):
|
||||
alarm_id = self.kwargs['id']
|
||||
|
||||
try:
|
||||
alarm = tacker_api.tacker.get_fm_alarm(self.request, alarm_id)
|
||||
alarm['links'] = alarm.get('_links', '')
|
||||
return alarm
|
||||
except Exception:
|
||||
redirect = reverse(self.redirect_url)
|
||||
exceptions.handle(self.request,
|
||||
_('Failed to get FM Alarm. (id: %s)') % alarm_id,
|
||||
redirect=redirect)
|
||||
raise exceptions.Http302(redirect)
|
||||
|
||||
def get_tabs(self, request, *args, **kwargs):
|
||||
alarm = self.get_data()
|
||||
return self.tab_group_class(request, alarm=alarm, **kwargs)
|
|
@ -0,0 +1,64 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
import json
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import messages
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
|
||||
|
||||
class CreateVnfFmSubscription(forms.SelfHandlingForm):
|
||||
param_file = forms.FileField(
|
||||
label=_("Param File"),
|
||||
help_text=_("parameter file to upload."),
|
||||
widget=forms.FileInput(
|
||||
attrs={'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-file': _('Param File')}))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(CreateVnfFmSubscription, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(CreateVnfFmSubscription, self).clean()
|
||||
|
||||
try:
|
||||
param_str = self.files['param_file'].read()
|
||||
param = json.loads(param_str)
|
||||
data['param'] = param
|
||||
except Exception as e:
|
||||
msg = _('Failed to read file: %s.') % e
|
||||
raise forms.ValidationError(msg)
|
||||
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
param = data['param']
|
||||
subscription_instance = api.tacker.create_fm_subscription(
|
||||
request, param)
|
||||
messages.success(request,
|
||||
_('Create FM Subscription. (id: %s)') %
|
||||
subscription_instance['id'])
|
||||
return True
|
||||
except Exception:
|
||||
msg = _('Failed to create FM Subscription.')
|
||||
exceptions.handle(request, msg)
|
||||
return False
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
import horizon
|
||||
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv import dashboard
|
||||
|
||||
|
||||
class VnfFmSubscription(horizon.Panel):
|
||||
name = _("Subscription")
|
||||
slug = "vnffmsubscription"
|
||||
|
||||
|
||||
dashboard.Nfv.register(VnfFmSubscription)
|
|
@ -0,0 +1,68 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext_lazy
|
||||
|
||||
from horizon import tables
|
||||
from openstack_dashboard import policy
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
|
||||
|
||||
class DeleteVnfFmSubscription(policy.PolicyTargetMixin, tables.DeleteAction):
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
return ngettext_lazy(
|
||||
"Delete Subscription",
|
||||
"Delete Subscriptions",
|
||||
count
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def action_past(count):
|
||||
return ngettext_lazy(
|
||||
"Delete Subscription",
|
||||
"Delete Subscriptions",
|
||||
count
|
||||
)
|
||||
|
||||
def action(self, request, obj_id):
|
||||
api.tacker.delete_fm_subscription(request, obj_id)
|
||||
|
||||
|
||||
class CreateVnfFmSubscription(tables.LinkAction):
|
||||
name = "createsubscription"
|
||||
verbose_name = _("Create Subscription")
|
||||
classes = ("ajax-modal",)
|
||||
icon = "plus"
|
||||
url = "horizon:nfv:vnffmsubscription:createsubscription"
|
||||
|
||||
|
||||
class VnfFmSubscriptionTable(tables.DataTable):
|
||||
id = tables.Column('id', link="horizon:nfv:vnffmsubscription:detail",
|
||||
verbose_name=_("ID"))
|
||||
callback_uri = tables.Column('callback_uri',
|
||||
verbose_name=_("Callback Uri"))
|
||||
|
||||
class Meta(object):
|
||||
name = "subscription"
|
||||
verbose_name = _("Subscription")
|
||||
pagination_param = 'vnffmsubscription_marker'
|
||||
prev_pagination_param = 'prev_vnffmsubscription_marker'
|
||||
table_actions = (CreateVnfFmSubscription, DeleteVnfFmSubscription,
|
||||
tables.FilterAction,)
|
||||
row_actions = (DeleteVnfFmSubscription,)
|
|
@ -0,0 +1,106 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs
|
||||
from horizon import utils as horizon_utils
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnffmsubscription \
|
||||
import tables
|
||||
|
||||
|
||||
class VnfFmSubscriptionItem(object):
|
||||
def __init__(self, subscription_id, callback_uri):
|
||||
self.id = subscription_id
|
||||
self.name = subscription_id
|
||||
self.callback_uri = callback_uri
|
||||
|
||||
|
||||
class VnfFmSubscriptionTab(tabs.TableTab):
|
||||
name = _("VNFFMSubscription Tab")
|
||||
slug = "vnffmsubscription_tab"
|
||||
table_classes = (tables.VnfFmSubscriptionTable,)
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
preload = False
|
||||
|
||||
def has_prev_data(self, table):
|
||||
return self._has_prev
|
||||
|
||||
def has_more_data(self, table):
|
||||
return self._has_more
|
||||
|
||||
def get_subscription_data(self):
|
||||
try:
|
||||
self._has_prev = False
|
||||
page_size = horizon_utils.functions.get_page_size(self.request)
|
||||
marker = self.request.GET.get("vnffmsubscription_marker", None)
|
||||
prev_marker = self.request.GET.get(
|
||||
"prev_vnffmsubscription_marker", None)
|
||||
subscriptions = api.tacker.list_fm_subscriptions(self.request)
|
||||
|
||||
if marker is not None or prev_marker is not None:
|
||||
for i, subsc in enumerate(subscriptions):
|
||||
if subsc["id"] == marker and i < len(subscriptions) - 1:
|
||||
subscriptions = subscriptions[i + 1:]
|
||||
self._has_prev = True
|
||||
break
|
||||
if subsc["id"] == prev_marker and i > page_size:
|
||||
subscriptions = subscriptions[i - page_size:]
|
||||
self._has_prev = True
|
||||
break
|
||||
|
||||
if len(subscriptions) > page_size:
|
||||
self._has_more = True
|
||||
else:
|
||||
self._has_more = False
|
||||
|
||||
rows = []
|
||||
for i, subsc in enumerate(subscriptions):
|
||||
if i >= page_size:
|
||||
break
|
||||
item = VnfFmSubscriptionItem(subsc['id'],
|
||||
subsc['callbackUri'])
|
||||
rows.append(item)
|
||||
return rows
|
||||
except Exception:
|
||||
self._has_more = False
|
||||
error_message = _('Failed to get FM Subscriptions.')
|
||||
exceptions.handle(self.request, error_message)
|
||||
return []
|
||||
|
||||
|
||||
class VnfFmSubscriptionTabs(tabs.TabGroup):
|
||||
slug = "vnffmsubscription_tabs"
|
||||
tabs = (VnfFmSubscriptionTab,)
|
||||
sticky = True
|
||||
|
||||
|
||||
class VnfFmSubscriptionDetailTab(tabs.Tab):
|
||||
name = _("VNF FM Subscription")
|
||||
slug = "vnffmsubscription_detail_tab"
|
||||
template_name = "nfv/vnffmsubscription/subscription_detail.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
return {'subscription': self.tab_group.kwargs['subscription']}
|
||||
|
||||
|
||||
class VnfFmSubscriptionDetailTabs(tabs.TabGroup):
|
||||
slug = "vnffmsubscription_detail_tabs"
|
||||
tabs = (VnfFmSubscriptionDetailTab,)
|
||||
sticky = True
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Create a Subscription." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Create Subscription" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Create Subscription") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/vnffmsubscription/_create_subscription.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Subscription Detail" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=page_title %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Subscription" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Subscription") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,14 @@
|
|||
{% load i18n %}
|
||||
|
||||
<div class="detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ subscription.id }}</dd>
|
||||
<dt>{% trans "Links" %}</dt>
|
||||
<dd>{{ subscription.links }}</dd>
|
||||
<dt>{% trans "Callback Uri" %}</dt>
|
||||
<dd>{{ subscription.callback_uri }}</dd>
|
||||
<dt>{% trans "Filter" %}</dt>
|
||||
<dd>{{ subscription.filter }}</dd>
|
||||
</dl>
|
||||
</div>
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.urls import re_path
|
||||
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnffmsubscription \
|
||||
import views
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^$', views.IndexView.as_view(), name='index'),
|
||||
re_path(r'^createsubscription',
|
||||
views.CreateVnfFmSubscriptionView.as_view(),
|
||||
name='createsubscription'),
|
||||
re_path(r'^(?P<id>[^/]+)/$', views.DetailView.as_view(),
|
||||
name='detail'),
|
||||
]
|
|
@ -0,0 +1,94 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.urls import reverse
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import tabs
|
||||
from horizon.utils import memoized
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api as tacker_api
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnffmsubscription \
|
||||
import forms as project_forms
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnffmsubscription \
|
||||
import tabs as subscription_tabs
|
||||
|
||||
|
||||
class IndexView(tabs.TabbedTableView):
|
||||
# A very simple class-based view...
|
||||
tab_group_class = subscription_tabs.VnfFmSubscriptionTabs
|
||||
template_name = 'nfv/vnffmsubscription/index.html'
|
||||
|
||||
def get_data(self, request, context, *args, **kwargs):
|
||||
# Add data to the context here...
|
||||
return context
|
||||
|
||||
|
||||
class CreateVnfFmSubscriptionView(forms.ModalFormView):
|
||||
form_class = project_forms.CreateVnfFmSubscription
|
||||
template_name = 'nfv/vnffmsubscription/create_subscription.html'
|
||||
success_url = reverse_lazy("horizon:nfv:vnffmsubscription:index")
|
||||
modal_id = "create_subscription_modal"
|
||||
modal_header = _("Create Subscription")
|
||||
submit_label = _("Create Subscription")
|
||||
submit_url = "horizon:nfv:vnffmsubscription:createsubscription"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(CreateVnfFmSubscriptionView,
|
||||
self).get_context_data(**kwargs)
|
||||
context['submit_url'] = reverse(self.submit_url)
|
||||
return context
|
||||
|
||||
|
||||
class DetailView(tabs.TabView):
|
||||
tab_group_class = subscription_tabs.VnfFmSubscriptionDetailTabs
|
||||
template_name = 'nfv/vnffmsubscription/detail.html'
|
||||
redirect_url = 'horizon:nfv:vnffmsubscription:index'
|
||||
page_title = _("Subscription Detail: {{ id }}")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
subscription = self.get_data()
|
||||
context['subscription'] = subscription
|
||||
context['id'] = kwargs['id']
|
||||
context['url'] = reverse(self.redirect_url)
|
||||
return context
|
||||
|
||||
@memoized.memoized_method
|
||||
def get_data(self):
|
||||
subscription_id = self.kwargs['id']
|
||||
|
||||
try:
|
||||
subscription = tacker_api.tacker.get_fm_subscription(
|
||||
self.request, subscription_id)
|
||||
subscription['links'] = subscription.get('_links', '')
|
||||
subscription['callback_uri'] = subscription.get('callbackUri', '')
|
||||
subscription['filter'] = subscription.get('filter', '')
|
||||
return subscription
|
||||
except Exception:
|
||||
redirect = reverse(self.redirect_url)
|
||||
exceptions.handle(self.request,
|
||||
_('Failed to get FM Subscription. (id: %s)') %
|
||||
subscription_id, redirect=redirect)
|
||||
raise exceptions.Http302(redirect)
|
||||
|
||||
def get_tabs(self, request, *args, **kwargs):
|
||||
subscription = self.get_data()
|
||||
return self.tab_group_class(request,
|
||||
subscription=subscription, **kwargs)
|
|
@ -0,0 +1,425 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
import json
|
||||
import time
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import messages
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
|
||||
|
||||
class CreateVnfIdentifier(forms.SelfHandlingForm):
|
||||
vnfd_id = forms.CharField(label=_("VNFD ID"))
|
||||
param_file = forms.FileField(
|
||||
label=_("Param File"),
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-upload': _('Param File')}),
|
||||
required=False)
|
||||
name = forms.CharField(label=_("Name"), required=False)
|
||||
description = forms.CharField(label=_("Description"), required=False)
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(CreateVnfIdentifier, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(CreateVnfIdentifier, self).clean()
|
||||
|
||||
param_file = data.get('param_file', None)
|
||||
|
||||
try:
|
||||
if param_file:
|
||||
metadata = self.files['param_file'].read()
|
||||
data['metadata'] = json.loads(metadata)
|
||||
except Exception as e:
|
||||
msg = _('Failed to read file: %s.') % e
|
||||
raise forms.ValidationError(msg)
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
vnfd_id = data.get('vnfd_id', None)
|
||||
metadata = data.get('metadata', None)
|
||||
name = data.get('name', None)
|
||||
description = data.get('description', None)
|
||||
|
||||
body = {}
|
||||
body['vnfdId'] = vnfd_id
|
||||
if metadata:
|
||||
body['metadata'] = metadata
|
||||
if name:
|
||||
body['vnfInstanceName'] = name
|
||||
if description:
|
||||
body['vnfInstanceDescription'] = description
|
||||
|
||||
response = api.tacker.create_vnf_instance(request, body)
|
||||
messages.success(request,
|
||||
_('Create VNF Identifier. (id: %s)') %
|
||||
response['id'])
|
||||
|
||||
except Exception:
|
||||
exceptions.handle(request, _('Failed to create VNF Identifier.'))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class InstantiateVnf(forms.SelfHandlingForm):
|
||||
param_file = forms.FileField(
|
||||
label=_("Param File"),
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-upload': _('Param File')}))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(InstantiateVnf, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(InstantiateVnf, self).clean()
|
||||
|
||||
try:
|
||||
param_str = self.files['param_file'].read()
|
||||
param = json.loads(param_str)
|
||||
data['param_data'] = param
|
||||
except Exception as e:
|
||||
msg = _('Failed to read file: %s.') % e
|
||||
raise forms.ValidationError(msg)
|
||||
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
vnf_id = request.resolver_match.kwargs.get('id', None)
|
||||
param = data['param_data']
|
||||
api.tacker.instantiate_vnf_instance(request, vnf_id, param)
|
||||
messages.success(request,
|
||||
_('Accepted to instantiate VNF Instance. '
|
||||
'(id: %s)') % vnf_id)
|
||||
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Failed to instantiate VNF Instance. '
|
||||
'(id: %s)') % vnf_id)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class TerminateVnf(forms.SelfHandlingForm):
|
||||
termination_type = forms.ChoiceField(
|
||||
label=_('Termination Type'),
|
||||
required=True,
|
||||
choices=[('GRACEFUL', _('GRACEFUL')),
|
||||
('FORCEFUL', _('FORCEFUL'))],
|
||||
widget=forms.Select(
|
||||
attrs={'class': 'switchable', 'data-slug': 'source'}))
|
||||
termination_timeout = forms.IntegerField(
|
||||
min_value=0,
|
||||
required=False,
|
||||
label=_('Graceful Termination Timeout'))
|
||||
is_delete = forms.BooleanField(
|
||||
label=_('Delete VNF Instance'),
|
||||
required=False)
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(TerminateVnf, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(TerminateVnf, self).clean()
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
is_delete = data.get('is_delete', False)
|
||||
vnf_id = request.resolver_match.kwargs.get('id', None)
|
||||
body = {}
|
||||
termination_type = data.get('termination_type', None)
|
||||
body['terminationType'] = termination_type
|
||||
termination_timeout = data.get('terminationTimeout', None)
|
||||
if termination_timeout:
|
||||
body['gracefulTerminationTimeout'] = termination_timeout
|
||||
api.tacker.terminate_vnf_instance(request, vnf_id, body)
|
||||
if not is_delete:
|
||||
messages.success(request,
|
||||
_('Accepted to terminate VNF Instance. '
|
||||
'(id: %s)') % vnf_id)
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Failed to terminate VNF Instance. '
|
||||
'(id: %s)') % vnf_id)
|
||||
return False
|
||||
|
||||
if is_delete:
|
||||
retry = 0
|
||||
retry_limit = 12
|
||||
while True:
|
||||
try:
|
||||
time.sleep(10)
|
||||
api.tacker.delete_vnf_instance(request, vnf_id)
|
||||
messages.success(request,
|
||||
_('Delete VNF Identifier. (id: %s)') %
|
||||
vnf_id)
|
||||
break
|
||||
except Exception as exc:
|
||||
if 'is in progress' in str(exc):
|
||||
# Conflict error occurs even if delete
|
||||
# is executed immediately after terminate
|
||||
retry = retry + 1
|
||||
if retry >= retry_limit:
|
||||
exceptions.handle(
|
||||
request,
|
||||
_('Delete VNF Identifier retry out. (id: %s)')
|
||||
% vnf_id)
|
||||
break
|
||||
continue
|
||||
else:
|
||||
exceptions.handle(
|
||||
request,
|
||||
_('Failed to delete VNF Identifer. (id: %s)') %
|
||||
vnf_id)
|
||||
break
|
||||
return True
|
||||
|
||||
|
||||
class HealVnf(forms.SelfHandlingForm):
|
||||
cause = forms.CharField(label=_("Cause"),
|
||||
required=False)
|
||||
vnfc_instances = forms.CharField(
|
||||
label=_('VNFC Instance'), required=False, widget=forms.Textarea,
|
||||
help_text=_('Enter VNFC instance IDs in comma-separated list format.'))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(HealVnf, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(HealVnf, self).clean()
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
vnf_id = request.resolver_match.kwargs.get('id', None)
|
||||
body = {}
|
||||
cause = data.get('cause', None)
|
||||
if cause:
|
||||
body['cause'] = cause
|
||||
array_str = data.get('vnfc_instances', None)
|
||||
if array_str:
|
||||
array_str.replace('\n', '')
|
||||
vnfc_instance_ids = [s.strip() for s in array_str.split(',')]
|
||||
body['vnfcInstanceId'] = vnfc_instance_ids
|
||||
api.tacker.heal_vnf_instance(request, vnf_id, body)
|
||||
messages.success(request,
|
||||
_('Accepted to heal VNF Instance. (id: %s)') %
|
||||
vnf_id)
|
||||
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Failed to heal VNF Instance. (id: %s)') %
|
||||
vnf_id)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class UpdateVnf(forms.SelfHandlingForm):
|
||||
param_file = forms.FileField(
|
||||
label=_("Param File"),
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-upload': _('Param File')}))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(UpdateVnf, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(UpdateVnf, self).clean()
|
||||
try:
|
||||
param_str = self.files['param_file'].read()
|
||||
param = json.loads(param_str)
|
||||
data['param_data'] = param
|
||||
except Exception as e:
|
||||
msg = _('Failed to read file: %s.') % e
|
||||
raise forms.ValidationError(msg)
|
||||
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
vnf_id = request.resolver_match.kwargs.get('id', None)
|
||||
param = data['param_data']
|
||||
api.tacker.update_vnf_instance(request, vnf_id, param)
|
||||
messages.success(request,
|
||||
_('Accepted to update VNF Instance. '
|
||||
'(id: %s)') % vnf_id)
|
||||
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Failed to update VNF Instance. '
|
||||
'(id: %s)') % vnf_id)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class ScaleVnf(forms.SelfHandlingForm):
|
||||
scale_type = forms.ChoiceField(
|
||||
label=_('Type'),
|
||||
choices=[('SCALE_IN', _('SCALE_IN')),
|
||||
('SCALE_OUT', _('SCALE_OUT'))])
|
||||
aspect_id = forms.CharField(label=_("Aspect ID"))
|
||||
num_of_steps = forms.IntegerField(
|
||||
label=_("Number of Steps"), min_value=1, required=False)
|
||||
param_file = forms.FileField(
|
||||
label=_("Param File"),
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-upload': _('Param File')}),
|
||||
required=False)
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(ScaleVnf, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(ScaleVnf, self).clean()
|
||||
|
||||
param_file = data.get('param_file', None)
|
||||
|
||||
try:
|
||||
if param_file:
|
||||
additional_params = self.files['param_file'].read()
|
||||
data['additional_params'] = json.loads(additional_params)
|
||||
except Exception as e:
|
||||
msg = _('Failed to read file: %s.') % e
|
||||
raise forms.ValidationError(msg)
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
vnf_id = request.resolver_match.kwargs.get('id', None)
|
||||
scale_type = data.get('scale_type', None)
|
||||
aspect_id = data.get('aspect_id', None)
|
||||
num_of_steps = data.get('num_of_steps', None)
|
||||
additional_params = data.get('additional_params', None)
|
||||
|
||||
body = {}
|
||||
body['type'] = scale_type
|
||||
body['aspectId'] = aspect_id
|
||||
if num_of_steps:
|
||||
body['numberOfSteps'] = num_of_steps
|
||||
if additional_params:
|
||||
body['additionalParams'] = additional_params
|
||||
|
||||
api.tacker.scale_vnf_instance(request, vnf_id, body)
|
||||
messages.success(request,
|
||||
_('Accepted to scale VNF Instance. '
|
||||
'(id: %s)') % vnf_id)
|
||||
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Failed to scale VNF Instance. '
|
||||
'(id: %s)') % vnf_id)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class ChangeExternalVnfConnectivity(forms.SelfHandlingForm):
|
||||
param_file = forms.FileField(
|
||||
label=_("Param File"),
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-upload': _('Param File')}))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(ChangeExternalVnfConnectivity,
|
||||
self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(ChangeExternalVnfConnectivity, self).clean()
|
||||
try:
|
||||
param_str = self.files['param_file'].read()
|
||||
param = json.loads(param_str)
|
||||
data['param_data'] = param
|
||||
except Exception as e:
|
||||
msg = _('Failed to read file: %s.') % e
|
||||
raise forms.ValidationError(msg)
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
vnf_id = request.resolver_match.kwargs.get('id', None)
|
||||
param = data['param_data']
|
||||
api.tacker.change_ext_conn_vnf_instance(request, vnf_id, param)
|
||||
messages.success(request,
|
||||
_('Accepted to change External VNF Connectivity. '
|
||||
'(id: %s)') % vnf_id)
|
||||
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Failed to change External VNF Connectivity. '
|
||||
'(id: %s)') % vnf_id)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class ChangeCurrentVnfPackage(forms.SelfHandlingForm):
|
||||
param_file = forms.FileField(
|
||||
label=_("Param File"),
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-upload': _('Param File')}))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(ChangeCurrentVnfPackage, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(ChangeCurrentVnfPackage, self).clean()
|
||||
try:
|
||||
param_str = self.files['param_file'].read()
|
||||
param = json.loads(param_str)
|
||||
data['param_data'] = param
|
||||
except Exception as e:
|
||||
msg = _('Failed to read file: %s.') % e
|
||||
raise forms.ValidationError(msg)
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
vnf_id = request.resolver_match.kwargs.get('id', None)
|
||||
param = data['param_data']
|
||||
api.tacker.change_vnfpkg_vnf_instance(request, vnf_id, param)
|
||||
messages.success(request,
|
||||
_('Accepted to change Current VNF Package. '
|
||||
'(id: %s)') % vnf_id)
|
||||
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Failed to change Current VNF Package. '
|
||||
'(id: %s)') % vnf_id)
|
||||
return False
|
||||
|
||||
return True
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
import horizon
|
||||
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv import dashboard
|
||||
|
||||
|
||||
class VnfLcm(horizon.Panel):
|
||||
name = _("VNF LCM")
|
||||
slug = "vnflcm"
|
||||
|
||||
|
||||
dashboard.Nfv.register(VnfLcm)
|
|
@ -0,0 +1,129 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext_lazy
|
||||
|
||||
from horizon import tables
|
||||
from openstack_dashboard import policy
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
|
||||
|
||||
class DeleteVnfIdentifier(policy.PolicyTargetMixin, tables.DeleteAction):
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
return ngettext_lazy(
|
||||
"Delete VNF Identifier",
|
||||
"Delete VNF Identifiers",
|
||||
count
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def action_past(count):
|
||||
return ngettext_lazy(
|
||||
"Delete VNF Identifier",
|
||||
"Delete VNF Identifiers",
|
||||
count
|
||||
)
|
||||
|
||||
def action(self, request, obj_id):
|
||||
api.tacker.delete_vnf_instance(request, obj_id)
|
||||
|
||||
|
||||
class CreateVnfIdentifier(tables.LinkAction):
|
||||
name = "createvnfid"
|
||||
verbose_name = _("Create VNF Identifier")
|
||||
url = "horizon:nfv:vnflcm:createvnfidentifier"
|
||||
classes = ("ajax-modal",)
|
||||
icon = "plus"
|
||||
|
||||
|
||||
class InstantiateVnf(tables.LinkAction):
|
||||
name = "instantiatevnf"
|
||||
verbose_name = _("Instantiate VNF")
|
||||
url = "horizon:nfv:vnflcm:instantiatevnf"
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
|
||||
class TerminateVnf(tables.LinkAction):
|
||||
name = "terminate_vnf"
|
||||
verbose_name = _("Terminate VNF")
|
||||
url = "horizon:nfv:vnflcm:terminatevnf"
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
|
||||
class HealVnf(tables.LinkAction):
|
||||
name = "heal_vnf"
|
||||
verbose_name = _("Heal VNF")
|
||||
url = "horizon:nfv:vnflcm:healvnf"
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
|
||||
class UpdateVnf(tables.LinkAction):
|
||||
name = "update_Vnf"
|
||||
verbose_name = _("Update VNF")
|
||||
url = "horizon:nfv:vnflcm:updatevnf"
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
|
||||
class ScaleVnf(tables.LinkAction):
|
||||
name = "scale_vnf"
|
||||
verbose_name = _("Scale VNF")
|
||||
url = "horizon:nfv:vnflcm:scalevnf"
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
|
||||
class ChangeExternalVnfConnectivity(tables.LinkAction):
|
||||
name = "change_external_vnf_connectivity"
|
||||
verbose_name = _("Change External VNF Connectivity")
|
||||
url = "horizon:nfv:vnflcm:changeconnectivity"
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
|
||||
class ChangeCurrentVnfPackage(tables.LinkAction):
|
||||
name = "change_current_vnf_package"
|
||||
verbose_name = _("Change Current VNF Package")
|
||||
url = "horizon:nfv:vnflcm:changevnfpkg"
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
|
||||
class VnfLcmTable(tables.DataTable):
|
||||
id = tables.Column('id', verbose_name=_("ID"),
|
||||
link="horizon:nfv:vnflcm:detail",)
|
||||
vnf_instance_name = tables.Column('vnf_instance_name',
|
||||
verbose_name=_("VNF Instance Name"))
|
||||
instantiation_state = tables.Column('instantiation_state',
|
||||
verbose_name=_("Instantiation State"))
|
||||
vnf_provider = tables.Column('vnf_provider',
|
||||
verbose_name=_("VNF Provider"))
|
||||
vnf_software_version = tables.Column(
|
||||
'vnf_software_version',
|
||||
verbose_name=_("VNF Software Version"))
|
||||
vnf_product_name = tables.Column('vnf_product_name',
|
||||
verbose_name=_("VNF Product Name"))
|
||||
vnfd_id = tables.Column('vnfd_id', verbose_name=_("VNFD ID"))
|
||||
|
||||
class Meta(object):
|
||||
name = "vnflcm"
|
||||
verbose_name = _("VNF LCM")
|
||||
pagination_param = 'vnflcm_marker'
|
||||
prev_pagination_param = 'prev_vnflcm_marker'
|
||||
table_actions = (CreateVnfIdentifier, DeleteVnfIdentifier,
|
||||
tables.FilterAction,)
|
||||
row_actions = (InstantiateVnf, TerminateVnf, DeleteVnfIdentifier,
|
||||
HealVnf, UpdateVnf, ScaleVnf,
|
||||
ChangeExternalVnfConnectivity, ChangeCurrentVnfPackage,)
|
|
@ -0,0 +1,131 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs
|
||||
from horizon import utils as horizon_utils
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnflcm import tables
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnflcmopocc \
|
||||
import tabs as opocc_tab
|
||||
|
||||
|
||||
class VnfLcmItem(object):
|
||||
def __init__(self, vnf_id, vnf_instance_name, instantiation_state,
|
||||
vnf_provider, vnf_software_version, vnf_product_name,
|
||||
vnfd_id):
|
||||
self.id = vnf_id
|
||||
self.name = vnf_id
|
||||
self.vnf_instance_name = vnf_instance_name
|
||||
self.instantiation_state = instantiation_state
|
||||
self.vnf_provider = vnf_provider
|
||||
self.vnf_software_version = vnf_software_version
|
||||
self.vnf_product_name = vnf_product_name
|
||||
self.vnfd_id = vnfd_id
|
||||
|
||||
|
||||
class VnfLcmTab(tabs.TableTab):
|
||||
name = _("VNFLCM tab")
|
||||
slug = "vnflcm_tab"
|
||||
table_classes = (tables.VnfLcmTable,)
|
||||
template_name = ("horizon/common/_detail_table.html")
|
||||
preload = False
|
||||
|
||||
def has_prev_data(self, table):
|
||||
return self._has_prev
|
||||
|
||||
def has_more_data(self, table):
|
||||
return self._has_more
|
||||
|
||||
def get_vnflcm_data(self):
|
||||
try:
|
||||
self._has_prev = False
|
||||
page_size = horizon_utils.functions.get_page_size(self.request)
|
||||
marker = self.request.GET.get(
|
||||
"vnflcm_marker", None)
|
||||
prev_marker = self.request.GET.get(
|
||||
"prev_vnflcm_marker", None)
|
||||
vnf_instances = api.tacker.list_vnf_instances(self.request)
|
||||
if marker is not None or prev_marker is not None:
|
||||
for i, instance in enumerate(vnf_instances):
|
||||
if instance["id"] == marker and i < len(vnf_instances) - 1:
|
||||
vnf_instances = vnf_instances[i + 1:]
|
||||
self._has_prev = True
|
||||
break
|
||||
if instance["id"] == prev_marker and i > page_size:
|
||||
vnf_instances = vnf_instances[i - page_size:]
|
||||
self._has_prev = True
|
||||
break
|
||||
|
||||
if len(vnf_instances) > page_size:
|
||||
self._has_more = True
|
||||
else:
|
||||
self._has_more = False
|
||||
|
||||
rows = []
|
||||
for i, instance in enumerate(vnf_instances):
|
||||
if i >= page_size:
|
||||
break
|
||||
item = VnfLcmItem(
|
||||
vnf_id=instance.get('id', ''),
|
||||
vnf_instance_name=instance.get('vnfInstanceName', ''),
|
||||
instantiation_state=instance.get(
|
||||
'instantiationState', ''),
|
||||
vnf_provider=instance.get('vnfProvider', ''),
|
||||
vnf_software_version=instance.get(
|
||||
'vnfSoftwareVersion', ''),
|
||||
vnf_product_name=instance.get('vnfProductName', ''),
|
||||
vnfd_id=instance.get('vnfdId', ''))
|
||||
rows.append(item)
|
||||
return rows
|
||||
except Exception:
|
||||
self._has_more = False
|
||||
error_message = _('Failed to get VNF Instances.')
|
||||
exceptions.handle(self.request, error_message)
|
||||
|
||||
return []
|
||||
|
||||
|
||||
class VnfLcmTabs(tabs.TabGroup):
|
||||
slug = "vnflcm_tabs"
|
||||
tabs = (VnfLcmTab,)
|
||||
sticky = True
|
||||
|
||||
|
||||
class VnfLcmOpOccItem(object):
|
||||
def __init__(self, id, operation_state, vnf_instance_id, operation):
|
||||
self.id = id
|
||||
self.operation_state = operation_state
|
||||
self.vnf_instance_id = vnf_instance_id
|
||||
self.operation = operation
|
||||
|
||||
|
||||
class VnfLcmDetailTab(tabs.Tab):
|
||||
name = _("VNF Instance Detail Tab")
|
||||
slug = "vnflcm_detail_tab"
|
||||
template_name = "nfv/vnflcm/vnflcm_detail.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
return {'vnflcm': self.tab_group.kwargs['vnflcm']}
|
||||
|
||||
|
||||
class VnfLcmDetailTabs(tabs.TabGroup):
|
||||
slug = "vnflcm_detail_tabs"
|
||||
tabs = (VnfLcmDetailTab, opocc_tab.VnfLcmOpOccTab,)
|
||||
sticky = True
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Change a External VNF Connectivity." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Change a Current VNF Package." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Create a VNF Identifier." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Heal a VNF instance." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Instantiate a VNF instance." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Scale a VNF instance." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Terminate a VNF instance." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Update a VNF instance." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Change External VNF Connectivity" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Change External VNF Connectivity") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/vnflcm/_change_connectivity.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Change Current VNF Package" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Change Current VNF Package") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/vnflcm/_change_vnfpkg.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "create_vnf_id" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Create VNF Identifier") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/vnflcm/_create_vnf_identifier.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "VNF LCM Detail" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=page_title %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Heal VNF" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Heal VNF") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/vnflcm/_heal_vnf.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "VNF LCM" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("VNF LCM") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Instantiate VNF" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Instantiate VNF") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/vnflcm/_instantiate_vnf.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Scale VNF" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Scale VNF") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/vnflcm/_scale_vnf.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Terminate VNF" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Terminate VNF") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/vnflcm/_terminate_vnf.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Update VNF" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Update VNF") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/vnflcm/_update_vnf.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,30 @@
|
|||
{% load i18n %}
|
||||
|
||||
<div class="detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ vnflcm.id }}</dd>
|
||||
<dt>{% trans "Instantiated Vnf Info" %}</dt>
|
||||
<dd>{{ vnflcm.instantiatedVnfInfo }}</dd>
|
||||
<dt>{% trans "Instantiation State" %}</dt>
|
||||
<dd>{{ vnflcm.instantiationState }}</dd>
|
||||
<dt>{% trans "Links" %}</dt>
|
||||
<dd>{{ vnflcm.links }}</dd>
|
||||
<dt>{% trans "VIM Connection Info" %}</dt>
|
||||
<dd>{{ vnflcm.vimConnectionInfo }}</dd>
|
||||
<dt>{% trans "VNF Instance Description" %}</dt>
|
||||
<dd>{{ vnflcm.vnfInstanceDescription }}</dd>
|
||||
<dt>{% trans "VNF Instance Name" %}</dt>
|
||||
<dd>{{ vnflcm.vnfInstanceName }}</dd>
|
||||
<dt>{% trans "VNF Product Name" %}</dt>
|
||||
<dd>{{ vnflcm.vnfProductName }}</dd>
|
||||
<dt>{% trans "VNF Provider" %}</dt>
|
||||
<dd>{{ vnflcm.vnfProvider }}</dd>
|
||||
<dt>{% trans "VNF Software Version" %}</dt>
|
||||
<dd>{{ vnflcm.vnfSoftwareVersion }}</dd>
|
||||
<dt>{% trans "VNFD ID" %}</dt>
|
||||
<dd>{{ vnflcm.vnfdId }}</dd>
|
||||
<dt>{% trans "VNFD Version" %}</dt>
|
||||
<dd>{{ vnflcm.vnfdVersion }}</dd>
|
||||
</dl>
|
||||
</div>
|
|
@ -0,0 +1,44 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.urls import re_path
|
||||
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnflcm \
|
||||
import views
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^$', views.IndexView.as_view(), name='index'),
|
||||
re_path(r'^(?P<id>[^/]+)/$', views.DetailView.as_view(), name='detail'),
|
||||
re_path(r'^createvnfidentifier$', views.CreateVnfIdentifierView.as_view(),
|
||||
name='createvnfidentifier'),
|
||||
re_path(r'^(?P<id>[^/]+)/instantiatevnf/$',
|
||||
views.InstantiateVnfView.as_view(),
|
||||
name='instantiatevnf'),
|
||||
re_path(r'^(?P<id>[^/]+)/terminatevnf/$', views.TerminateVnfView.as_view(),
|
||||
name='terminatevnf'),
|
||||
re_path(r'^(?P<id>[^/]+)/healvnf/$', views.HealVnfView.as_view(),
|
||||
name='healvnf'),
|
||||
re_path(r'^(?P<id>[^/]+)/updatevnf/$', views.UpdateVnfView.as_view(),
|
||||
name='updatevnf'),
|
||||
re_path(r'^(?P<id>[^/]+)/scalevnf/$', views.ScaleVnfView.as_view(),
|
||||
name='scalevnf'),
|
||||
re_path(r'^(?P<id>[^/]+)/changeconnectivity/$',
|
||||
views.ChangeExternalVnfConnectivityView.as_view(),
|
||||
name='changeconnectivity'),
|
||||
re_path(r'^(?P<id>[^/]+)/changevnfpkg/$',
|
||||
views.ChangeCurrentVnfPackageView.as_view(),
|
||||
name='changevnfpkg'),
|
||||
]
|
|
@ -0,0 +1,200 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.urls import reverse
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import tabs
|
||||
from horizon.utils import memoized
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api as tacker_api
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnflcm \
|
||||
import forms as project_forms
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnflcm \
|
||||
import tabs as vnflcm_tabs
|
||||
|
||||
|
||||
class IndexView(tabs.TabbedTableView):
|
||||
tab_group_class = vnflcm_tabs.VnfLcmTabs
|
||||
template_name = 'nfv/vnflcm/index.html'
|
||||
|
||||
|
||||
class CreateVnfIdentifierView(forms.ModalFormView):
|
||||
form_class = project_forms.CreateVnfIdentifier
|
||||
template_name = 'nfv/vnflcm/create_vnf_identifier.html'
|
||||
success_url = reverse_lazy("horizon:nfv:vnflcm:index")
|
||||
modal_id = "add_service_modal"
|
||||
modal_header = _("Create VNF Identifier")
|
||||
submit_label = _("Create VNF Identifier")
|
||||
submit_url = "horizon:nfv:vnflcm:createvnfidentifier"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(
|
||||
CreateVnfIdentifierView, self).get_context_data(**kwargs)
|
||||
context['submit_url'] = reverse(self.submit_url)
|
||||
return context
|
||||
|
||||
|
||||
class InstantiateVnfView(forms.ModalFormView):
|
||||
form_class = project_forms.InstantiateVnf
|
||||
template_name = 'nfv/vnflcm/instantiate_vnf.html'
|
||||
success_url = reverse_lazy("horizon:nfv:vnflcm:index")
|
||||
modal_id = "add_service_modal"
|
||||
modal_header = _("Instantiate VNF")
|
||||
submit_label = _("Instantiate VNF")
|
||||
submit_url = "horizon:nfv:vnflcm:instantiatevnf"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(InstantiateVnfView, self).get_context_data(**kwargs)
|
||||
context['submit_url'] = reverse(self.submit_url,
|
||||
kwargs={'id': self.kwargs['id']})
|
||||
return context
|
||||
|
||||
|
||||
class TerminateVnfView(forms.ModalFormView):
|
||||
form_class = project_forms.TerminateVnf
|
||||
template_name = 'nfv/vnflcm/terminate_vnf.html'
|
||||
success_url = reverse_lazy("horizon:nfv:vnflcm:index")
|
||||
modal_id = "add_service_modal"
|
||||
modal_header = _("Terminate VNF")
|
||||
submit_label = _("Terminate VNF")
|
||||
submit_url = "horizon:nfv:vnflcm:terminatevnf"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(TerminateVnfView, self).get_context_data(**kwargs)
|
||||
context['submit_url'] = reverse(self.submit_url,
|
||||
kwargs={'id': self.kwargs['id']})
|
||||
return context
|
||||
|
||||
|
||||
class HealVnfView(forms.ModalFormView):
|
||||
form_class = project_forms.HealVnf
|
||||
template_name = 'nfv/vnflcm/heal_vnf.html'
|
||||
success_url = reverse_lazy("horizon:nfv:vnflcm:index")
|
||||
modal_id = "add_service_modal"
|
||||
modal_header = _("Heal VNF")
|
||||
submit_label = _("Heal VNF")
|
||||
submit_url = "horizon:nfv:vnflcm:healvnf"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(HealVnfView, self).get_context_data(**kwargs)
|
||||
context['submit_url'] = reverse(self.submit_url,
|
||||
kwargs={'id': self.kwargs['id']})
|
||||
return context
|
||||
|
||||
|
||||
class UpdateVnfView(forms.ModalFormView):
|
||||
form_class = project_forms.UpdateVnf
|
||||
template_name = 'nfv/vnflcm/update_vnf.html'
|
||||
success_url = reverse_lazy("horizon:nfv:vnflcm:index")
|
||||
modal_id = "add_service_modal"
|
||||
modal_header = _("Update VNF")
|
||||
submit_label = _("Update VNF")
|
||||
submit_url = "horizon:nfv:vnflcm:updatevnf"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(UpdateVnfView, self).get_context_data(**kwargs)
|
||||
context['submit_url'] = reverse(self.submit_url,
|
||||
kwargs={'id': self.kwargs['id']})
|
||||
return context
|
||||
|
||||
|
||||
class ScaleVnfView(forms.ModalFormView):
|
||||
form_class = project_forms.ScaleVnf
|
||||
template_name = 'nfv/vnflcm/scale_vnf.html'
|
||||
success_url = reverse_lazy("horizon:nfv:vnflcm:index")
|
||||
modal_id = "add_service_modal"
|
||||
modal_header = _("Scale VNF")
|
||||
submit_label = _("Scale VNF")
|
||||
submit_url = "horizon:nfv:vnflcm:scalevnf"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ScaleVnfView, self).get_context_data(**kwargs)
|
||||
context['submit_url'] = reverse(self.submit_url,
|
||||
kwargs={'id': self.kwargs['id']})
|
||||
return context
|
||||
|
||||
|
||||
class ChangeExternalVnfConnectivityView(forms.ModalFormView):
|
||||
form_class = project_forms.ChangeExternalVnfConnectivity
|
||||
template_name = 'nfv/vnflcm/change_connectivity.html'
|
||||
success_url = reverse_lazy("horizon:nfv:vnflcm:index")
|
||||
modal_id = "add_service_modal"
|
||||
modal_header = _("Change External VNF Connectivity")
|
||||
submit_label = _("Change External VNF Connectivity")
|
||||
submit_url = "horizon:nfv:vnflcm:changeconnectivity"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(
|
||||
ChangeExternalVnfConnectivityView, self).get_context_data(**kwargs)
|
||||
context['submit_url'] = reverse(self.submit_url,
|
||||
kwargs={'id': self.kwargs['id']})
|
||||
return context
|
||||
|
||||
|
||||
class ChangeCurrentVnfPackageView(forms.ModalFormView):
|
||||
form_class = project_forms.ChangeCurrentVnfPackage
|
||||
template_name = 'nfv/vnflcm/change_vnfpkg.html'
|
||||
success_url = reverse_lazy("horizon:nfv:vnflcm:index")
|
||||
modal_id = "add_service_modal"
|
||||
modal_header = _("Change Current VNF Package")
|
||||
submit_label = _("Change Current VNF Package")
|
||||
submit_url = "horizon:nfv:vnflcm:changevnfpkg"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(
|
||||
ChangeCurrentVnfPackageView, self).get_context_data(**kwargs)
|
||||
context['submit_url'] = reverse(self.submit_url,
|
||||
kwargs={'id': self.kwargs['id']})
|
||||
return context
|
||||
|
||||
|
||||
class DetailView(tabs.TabbedTableView):
|
||||
tab_group_class = vnflcm_tabs.VnfLcmDetailTabs
|
||||
template_name = 'nfv/vnflcm/detail.html'
|
||||
redirect_url = 'horizon:nfv:vnflcm:index'
|
||||
page_title = _("VNF Instance Detail: {{ id }}")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
vnflcm = self.get_data()
|
||||
context['vnflcm'] = vnflcm
|
||||
context['id'] = kwargs['id']
|
||||
context['url'] = reverse(self.redirect_url)
|
||||
return context
|
||||
|
||||
@memoized.memoized_method
|
||||
def get_data(self):
|
||||
vnf_id = self.kwargs['id']
|
||||
|
||||
try:
|
||||
vnflcm = tacker_api.tacker.get_vnf_instance(self.request, vnf_id)
|
||||
vnflcm['links'] = vnflcm.get('_links', '')
|
||||
return vnflcm
|
||||
except Exception:
|
||||
redirect = reverse(self.redirect_url)
|
||||
exceptions.handle(
|
||||
self.request,
|
||||
_('Failed to get VNF instance. (id: %s)') % vnf_id,
|
||||
redirect=redirect)
|
||||
raise exceptions.Http302(redirect)
|
||||
|
||||
def get_tabs(self, request, *args, **kwargs):
|
||||
vnflcm = self.get_data()
|
||||
return self.tab_group_class(request, vnflcm=vnflcm, **kwargs)
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
import horizon
|
||||
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv import dashboard
|
||||
|
||||
|
||||
class VnfOpOcc(horizon.Panel):
|
||||
name = _("VNF OP OCC")
|
||||
slug = "vnflcmopocc"
|
||||
|
||||
|
||||
dashboard.Nfv.register(VnfOpOcc)
|
|
@ -0,0 +1,114 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext_lazy
|
||||
|
||||
from horizon import tables
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
|
||||
|
||||
class VnfLcmRollback(tables.BatchAction):
|
||||
name = "vnflcmrollback"
|
||||
verbose_name = _("Rollback VNF Lifecycle Management Operation")
|
||||
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
return ngettext_lazy(
|
||||
"Rollback VNF Lifecycle Management Operation",
|
||||
"Rollback VNF Lifecycle Management Operation",
|
||||
count
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def action_past(count):
|
||||
return ngettext_lazy(
|
||||
"Rollback VNF Lifecycle Management Operation",
|
||||
"Rollback VNF Lifecycle Management Operation",
|
||||
count
|
||||
)
|
||||
|
||||
def action(self, request, obj_id):
|
||||
api.tacker.rollback_vnf_lcm_op_occ(request, obj_id)
|
||||
|
||||
|
||||
class VnfLcmRetry(tables.BatchAction):
|
||||
name = "vnflcmretry"
|
||||
verbose_name = _("Retry")
|
||||
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
return ngettext_lazy(
|
||||
"Retry",
|
||||
"Retry",
|
||||
count
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def action_past(count):
|
||||
return ngettext_lazy(
|
||||
"Retry",
|
||||
"Retry",
|
||||
count
|
||||
)
|
||||
|
||||
def action(self, request, obj_id):
|
||||
api.tacker.retry_vnf_lcm_op_occ(request, obj_id)
|
||||
|
||||
|
||||
class VnfLcmFail(tables.BatchAction):
|
||||
name = "vnflcmfail"
|
||||
verbose_name = _("Fail")
|
||||
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
return ngettext_lazy(
|
||||
"Fail",
|
||||
"Fail",
|
||||
count
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def action_past(count):
|
||||
return ngettext_lazy(
|
||||
"Fail",
|
||||
"Fail",
|
||||
count
|
||||
)
|
||||
|
||||
def action(self, request, obj_id):
|
||||
api.tacker.fail_vnf_lcm_op_occ(request, obj_id)
|
||||
|
||||
|
||||
class VnfLcmOpOccTable(tables.DataTable):
|
||||
id = tables.Column('id', verbose_name=_("ID"),
|
||||
link="horizon:nfv:vnflcmopocc:detail",)
|
||||
operation_state = tables.Column('operation_state',
|
||||
verbose_name=_("OperationState"))
|
||||
vnf_instance_id = tables.Column('vnf_instance_id',
|
||||
verbose_name=_("VNFInstanceID"))
|
||||
operation = tables.Column('operation', verbose_name=_("Operation"))
|
||||
|
||||
class Meta(object):
|
||||
name = "vnflcmopocc"
|
||||
verbose_name = _("VNF LCM OP OCC")
|
||||
pagination_param = 'opocc_marker'
|
||||
prev_pagination_param = 'prev_opocc_marker'
|
||||
table_actions = (VnfLcmRollback, VnfLcmRetry, VnfLcmFail,
|
||||
tables.FilterAction,)
|
||||
row_actions = (VnfLcmRollback, VnfLcmRetry, VnfLcmFail,)
|
||||
multi_select = True
|
|
@ -0,0 +1,118 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs
|
||||
from horizon import utils as horizon_utils
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnflcmopocc \
|
||||
import tables
|
||||
|
||||
|
||||
class VnfLcmOpOccItem(object):
|
||||
def __init__(self, opocc_id, operation_state, vnf_instance_id,
|
||||
operation):
|
||||
self.id = opocc_id
|
||||
self.name = opocc_id
|
||||
self.operation_state = operation_state
|
||||
self.vnf_instance_id = vnf_instance_id
|
||||
self.operation = operation
|
||||
|
||||
|
||||
class VnfLcmOpOccTab(tabs.TableTab):
|
||||
name = _("List LCM Operation Occurrences")
|
||||
slug = "vnflcmopocc_tab"
|
||||
table_classes = (tables.VnfLcmOpOccTable,)
|
||||
template_name = ("horizon/common/_detail_table.html")
|
||||
preload = False
|
||||
|
||||
def has_prev_data(self, table):
|
||||
return self._has_prev
|
||||
|
||||
def has_more_data(self, table):
|
||||
return self._has_more
|
||||
|
||||
def get_vnflcmopocc_data(self):
|
||||
try:
|
||||
opoccs = []
|
||||
self._has_prev = False
|
||||
page_size = horizon_utils.functions.get_page_size(self.request)
|
||||
marker = self.request.GET.get(
|
||||
"opocc_marker", None)
|
||||
prev_marker = self.request.GET.get(
|
||||
"prev_opocc_marker", None)
|
||||
params = {}
|
||||
opocc_id = self.request.resolver_match.kwargs.get("id", None)
|
||||
if opocc_id:
|
||||
params["filter"] = "(eq,vnfInstanceId,{0})".format(opocc_id)
|
||||
opoccs = api.tacker.list_vnf_lcm_op_occs(self.request, **params)
|
||||
if marker is not None or prev_marker is not None:
|
||||
for i, opocc in enumerate(opoccs):
|
||||
if opocc["id"] == marker and i < len(opoccs) - 1:
|
||||
opoccs = opoccs[i + 1:]
|
||||
self._has_prev = True
|
||||
break
|
||||
if opocc["id"] == prev_marker and i > page_size:
|
||||
opoccs = opoccs[i - page_size:]
|
||||
self._has_prev = True
|
||||
break
|
||||
|
||||
if len(opoccs) > page_size:
|
||||
self._has_more = True
|
||||
else:
|
||||
self._has_more = False
|
||||
|
||||
rows = []
|
||||
for i, opocc in enumerate(opoccs):
|
||||
if i >= page_size:
|
||||
break
|
||||
item = VnfLcmOpOccItem(
|
||||
opocc_id=opocc.get('id', ''),
|
||||
operation_state=opocc.get('operationState', ''),
|
||||
vnf_instance_id=opocc.get('vnfInstanceId', ''),
|
||||
operation=opocc.get('operation', ''))
|
||||
rows.append(item)
|
||||
return rows
|
||||
except Exception:
|
||||
self._has_more = False
|
||||
error_message = _('Failed to get VNF LCM operation occurrences.')
|
||||
exceptions.handle(self.request, error_message)
|
||||
|
||||
return []
|
||||
|
||||
|
||||
class VnfLcmOpOccTabs(tabs.TabGroup):
|
||||
slug = "vnflcmopocc_tabs"
|
||||
tabs = (VnfLcmOpOccTab,)
|
||||
sticky = True
|
||||
|
||||
|
||||
class VnfOpOccDetailTab(tabs.Tab):
|
||||
name = _("LCM OP OCC Detail")
|
||||
slug = "vnflcmopocc_detail_tab"
|
||||
template_name = "nfv/vnflcmopocc/vnflcmopocc_detail.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
return {'vnflcmopocc': self.tab_group.kwargs['vnflcmopocc']}
|
||||
|
||||
|
||||
class VnfOpOccDetailTabs(tabs.TabGroup):
|
||||
slug = "vnflcmopocc_detail_tabs"
|
||||
tabs = (VnfOpOccDetailTab,)
|
||||
sticky = True
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "VNF LCM OP OCC" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=page_title %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "VNF LCM OP OCC" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("VNF LCM OP OCC") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,38 @@
|
|||
{% load i18n %}
|
||||
|
||||
<div class="detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "CancelMode" %}</dt>
|
||||
<dd>{{ vnflcmopocc.cancelMode }}</dd>
|
||||
<dt>{% trans "ChangedExtConnectivity" %}</dt>
|
||||
<dd>{{ vnflcmopocc.changedExtConnectivity }}</dd>
|
||||
<dt>{% trans "ChangedInfo" %}</dt>
|
||||
<dd>{{ vnflcmopocc.changedInfo }}</dd>
|
||||
<dt>{% trans "Error" %}</dt>
|
||||
<dd>{{ vnflcmopocc.error }}</dd>
|
||||
<dt>{% trans "GrantID" %}</dt>
|
||||
<dd>{{ vnflcmopocc.grantId }}</dd>
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ vnflcmopocc.id }}</dd>
|
||||
<dt>{% trans "IsAutomaticInvocation" %}</dt>
|
||||
<dd>{{ vnflcmopocc.isAutomaticInvocation }}</dd>
|
||||
<dt>{% trans "IsCancelPending" %}</dt>
|
||||
<dd>{{ vnflcmopocc.isCancelPending }}</dd>
|
||||
<dt>{% trans "Links" %}</dt>
|
||||
<dd>{{ vnflcmopocc.links }}</dd>
|
||||
<dt>{% trans "Operation" %}</dt>
|
||||
<dd>{{ vnflcmopocc.operation }}</dd>
|
||||
<dt>{% trans "OperationParams" %}</dt>
|
||||
<dd>{{ vnflcmopocc.operationParams }}</dd>
|
||||
<dt>{% trans "OperationState" %}</dt>
|
||||
<dd>{{ vnflcmopocc.operationState }}</dd>
|
||||
<dt>{% trans "ResourceChanges" %}</dt>
|
||||
<dd>{{ vnflcmopocc.resourceChanges }}</dd>
|
||||
<dt>{% trans "StartTime" %}</dt>
|
||||
<dd>{{ vnflcmopocc.startTime }}</dd>
|
||||
<dt>{% trans "StateEnteredTime" %}</dt>
|
||||
<dd>{{ vnflcmopocc.stateEnteredTime }}</dd>
|
||||
<dt>{% trans "VnfInstanceID" %}</dt>
|
||||
<dd>{{ vnflcmopocc.vnfInstanceId }}</dd>
|
||||
</dl>
|
||||
</div>
|
|
@ -0,0 +1,25 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.urls import re_path
|
||||
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnflcmopocc \
|
||||
import views
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^$', views.IndexView.as_view(), name='index'),
|
||||
re_path(r'^(?P<id>[^/]+)/$', views.DetailView.as_view(), name='detail'),
|
||||
]
|
|
@ -0,0 +1,73 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs
|
||||
from horizon.utils import memoized
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api as tacker_api
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnflcmopocc \
|
||||
import tabs as vnflcmopocc_tabs
|
||||
|
||||
|
||||
class IndexView(tabs.TabbedTableView):
|
||||
# A very simple class-based view...
|
||||
tab_group_class = vnflcmopocc_tabs.VnfLcmOpOccTabs
|
||||
template_name = 'nfv/vnflcmopocc/index.html'
|
||||
|
||||
def get_data(self, request, context, *args, **kwargs):
|
||||
# Add data to the context here...
|
||||
return context
|
||||
|
||||
|
||||
class DetailView(tabs.TabView):
|
||||
tab_group_class = vnflcmopocc_tabs.VnfOpOccDetailTabs
|
||||
template_name = 'nfv/vnflcmopocc/detail.html'
|
||||
redirect_url = 'horizon:nfv:vnflcmopocc:index'
|
||||
page_title = _("LCM OP OCC Details: {{ id }}")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
vnflcmopocc = self.get_data()
|
||||
context['vnflcmopocc'] = vnflcmopocc
|
||||
context['id'] = kwargs['id']
|
||||
context['url'] = reverse(self.redirect_url)
|
||||
return context
|
||||
|
||||
@memoized.memoized_method
|
||||
def get_data(self):
|
||||
opocc_id = self.kwargs['id']
|
||||
|
||||
try:
|
||||
vnflcmopocc = tacker_api.tacker.get_vnf_lcm_op_occ(self.request,
|
||||
opocc_id)
|
||||
vnflcmopocc['links'] = vnflcmopocc.get('_links', '')
|
||||
return vnflcmopocc
|
||||
except Exception:
|
||||
redirect = reverse(self.redirect_url)
|
||||
exceptions.handle(
|
||||
self.request,
|
||||
_('Failed to get VNF LCM operation occurrence. (id: %s)') %
|
||||
opocc_id,
|
||||
redirect=redirect)
|
||||
raise exceptions.Http302(redirect)
|
||||
|
||||
def get_tabs(self, request, *args, **kwargs):
|
||||
vnflcmopocc = self.get_data()
|
||||
return self.tab_group_class(request, vnflcmopocc=vnflcmopocc, **kwargs)
|
|
@ -0,0 +1,189 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
import os
|
||||
|
||||
from django.core.files.uploadedfile import InMemoryUploadedFile
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.core.files.uploadedfile import TemporaryUploadedFile
|
||||
from django.forms import ValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import messages
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UploadVnfPackage(forms.SelfHandlingForm):
|
||||
user_data = forms.JSONField(
|
||||
label=_("User Data"), required=False)
|
||||
source_type = forms.ChoiceField(
|
||||
label=_('VNF Package Source'),
|
||||
choices=[('url', _('URL')), ('file', _('File'))],
|
||||
widget=forms.Select(
|
||||
attrs={'class': 'switchable', 'data-slug': 'source'}))
|
||||
url = forms.URLField(
|
||||
widget=forms.TextInput(attrs={
|
||||
'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-url': _('URL')}),
|
||||
required=False)
|
||||
user_name = forms.CharField(
|
||||
widget=forms.TextInput(attrs={
|
||||
'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-url': _('User Name')}),
|
||||
required=False)
|
||||
password = forms.CharField(
|
||||
widget=forms.PasswordInput(attrs={
|
||||
'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-url': _('Password')}),
|
||||
required=False)
|
||||
vnf_package = forms.FileField(
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-file': _('VNF Package')}),
|
||||
required=False)
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(UploadVnfPackage, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(UploadVnfPackage, self).clean()
|
||||
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
body = {}
|
||||
user_data = data.get('user_data', None)
|
||||
if user_data:
|
||||
body['userDefinedData'] = user_data
|
||||
response = api.tacker.create_vnf_package(request, body)
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Failed to create VNF Package.'))
|
||||
return False
|
||||
|
||||
try:
|
||||
params = {}
|
||||
source_type = data.get('source_type', None)
|
||||
if source_type == 'url':
|
||||
params['url'] = data.get('url', None)
|
||||
user_name = data.get('user_name', None)
|
||||
password = data.get('password', None)
|
||||
if user_name:
|
||||
params['userName'] = user_name
|
||||
params['password'] = password
|
||||
api.tacker.upload_vnf_package(
|
||||
request, response['id'], **params)
|
||||
messages.success(
|
||||
request,
|
||||
_('Accepted to upload VNF Package. '
|
||||
'(id: %s)') % response['id'])
|
||||
else:
|
||||
file = request.FILES['vnf_package']
|
||||
if isinstance(file, TemporaryUploadedFile):
|
||||
# Hack to fool Django, so we can keep file open.
|
||||
file.file._closer.close_called = True
|
||||
elif isinstance(file, InMemoryUploadedFile):
|
||||
# Clone a new file for InMemoryUploadedFile.
|
||||
# Because the old one will be closed by Django.
|
||||
file = SimpleUploadedFile(
|
||||
file.name, file.read(), file.content_type)
|
||||
try:
|
||||
api.tacker.upload_vnf_package(
|
||||
request, response['id'], file, **params)
|
||||
messages.success(
|
||||
request,
|
||||
_('Accepted to upload VNF Package. '
|
||||
'(id: %s)') % response['id'])
|
||||
finally:
|
||||
try:
|
||||
filename = str(file.file.name)
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
os.remove(filename)
|
||||
except OSError as e:
|
||||
LOG.warning(
|
||||
'Failed to remove temporary file '
|
||||
'%(file)s (%(e)s)',
|
||||
{'file': filename, 'e': e})
|
||||
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Failed to upload VNF Package. (id: %s)') %
|
||||
response['id'])
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class UpdateVnfPackage(forms.SelfHandlingForm):
|
||||
operationalState = forms.ChoiceField(
|
||||
label=_('Operational State'),
|
||||
required=False,
|
||||
choices=[(None, _(' ')),
|
||||
('ENABLED', _('ENABLED')),
|
||||
('DISABLED', _('DISABLED'))],
|
||||
widget=forms.Select(
|
||||
attrs={'class': 'switchable', 'data-slug': 'source'}))
|
||||
userData = forms.JSONField(label=_('User Data'),
|
||||
required=False)
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(UpdateVnfPackage, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(UpdateVnfPackage, self).clean()
|
||||
operationalState = data.get('operationalState', None)
|
||||
userData = data.get('userData', None)
|
||||
if operationalState is None and userData is None:
|
||||
raise ValidationError(
|
||||
_("At least one of the \"operationalState\" or \
|
||||
\"userDefinedData\" parameters shall be present."))
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
vnfpkg_id = request.resolver_match.kwargs.get('id', None)
|
||||
body = {}
|
||||
operationalState = data.get('operationalState', None)
|
||||
if operationalState:
|
||||
body['operationalState'] = operationalState
|
||||
|
||||
userDefinedData = data.get('userData', None)
|
||||
if userDefinedData:
|
||||
body['userDefinedData'] = userDefinedData
|
||||
api.tacker.update_vnf_package(request, vnfpkg_id, body)
|
||||
messages.success(request,
|
||||
_('Update VNF Package. (id: %s)') % vnfpkg_id)
|
||||
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Failed to update VNF Package. (id: %s)') %
|
||||
vnfpkg_id)
|
||||
return False
|
||||
|
||||
return True
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
import horizon
|
||||
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv import dashboard
|
||||
|
||||
|
||||
class VnfPackages(horizon.Panel):
|
||||
name = _("VNF Packages")
|
||||
slug = "vnfpackages"
|
||||
|
||||
|
||||
dashboard.Nfv.register(VnfPackages)
|
|
@ -0,0 +1,116 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext_lazy
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import messages
|
||||
from horizon import tables
|
||||
from openstack_dashboard import policy
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
|
||||
|
||||
class DeleteVnfPackage(policy.PolicyTargetMixin, tables.DeleteAction):
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
return ngettext_lazy(
|
||||
"Delete VNF Package",
|
||||
"Delete VNF Packages",
|
||||
count
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def action_past(count):
|
||||
return ngettext_lazy(
|
||||
"Delete VNF Package",
|
||||
"Delete VNF Packages",
|
||||
count
|
||||
)
|
||||
|
||||
def action(self, request, obj_id):
|
||||
api.tacker.delete_vnf_package(request, obj_id)
|
||||
|
||||
|
||||
class UploadVnfPackage(tables.LinkAction):
|
||||
name = "uploadvnfpkg"
|
||||
verbose_name = _("Upload VNF Package")
|
||||
classes = ("ajax-modal",)
|
||||
icon = "plus"
|
||||
url = "horizon:nfv:vnfpackages:uploadvnfpkg"
|
||||
|
||||
|
||||
class FetchVnfPackage(tables.LinkAction):
|
||||
name = "fetchvnfpkg"
|
||||
verbose_name = _("Fetch VNF Package")
|
||||
verbose_name_plural = _("Fetch VNF Package")
|
||||
icon = "download"
|
||||
url = "horizon:nfv:vnfpackages:fetch"
|
||||
|
||||
def allowed(self, request, datum=None):
|
||||
return True
|
||||
|
||||
|
||||
class UpdateVnfPackageInfo(tables.LinkAction):
|
||||
name = "updatevnfpkginfo"
|
||||
verbose_name = _("Update VNF Package Info")
|
||||
url = "horizon:nfv:vnfpackages:updatevnfpkg"
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
|
||||
class CreateVnfIdentifier(tables.Action):
|
||||
name = "createvnfid"
|
||||
verbose_name = _("Create VNF Identifier")
|
||||
|
||||
def single(self, table, request, obj_id): # pylint: disable=E0202
|
||||
try:
|
||||
vnf_pkg = api.tacker.get_vnf_package(request, obj_id)
|
||||
vnfd_id = vnf_pkg.get('vnfdId', None)
|
||||
if not vnfd_id:
|
||||
msg = _('Failed to get VNFD ID')
|
||||
raise Exception(msg)
|
||||
req_body = {}
|
||||
req_body['vnfdId'] = vnfd_id
|
||||
response = api.tacker.create_vnf_instance(request, req_body)
|
||||
messages.success(request,
|
||||
_('Create VNF Identifier. (id: %s)') %
|
||||
response['id'])
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Failed to create VNF Identifier.'))
|
||||
|
||||
|
||||
class VnfPackageTable(tables.DataTable):
|
||||
id = tables.Column('id', verbose_name=_("ID"),
|
||||
link="horizon:nfv:vnfpackages:detail",)
|
||||
name = tables.Column('vnf_product_name',
|
||||
verbose_name=_("VNF Product Name"))
|
||||
onboarding_state = tables.Column('onboarding_state',
|
||||
verbose_name=_("Onboarding State"))
|
||||
usage_state = tables.Column('usage_state', verbose_name=_("Usage State"))
|
||||
operational_state = tables.Column('operational_state',
|
||||
verbose_name=_("Operational State"))
|
||||
|
||||
class Meta(object):
|
||||
name = "vnfpackage"
|
||||
verbose_name = _("VNF Package")
|
||||
pagination_param = 'package_marker'
|
||||
prev_pagination_param = 'prev_package_marker'
|
||||
table_actions = (UploadVnfPackage, DeleteVnfPackage,
|
||||
tables.FilterAction,)
|
||||
row_actions = (FetchVnfPackage, UpdateVnfPackageInfo, DeleteVnfPackage,
|
||||
CreateVnfIdentifier,)
|
|
@ -0,0 +1,118 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs
|
||||
from horizon import utils as horizon_utils
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv import utils # noqa
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnfpackages \
|
||||
import tables
|
||||
|
||||
|
||||
class VnfPackageItem(object):
|
||||
def __init__(self, vnfpkg_id, vnf_product_name, onboarding_state,
|
||||
usage_state, operational_state, vnfd_id,):
|
||||
self.id = vnfpkg_id
|
||||
self.name = vnfpkg_id
|
||||
self.vnf_product_name = vnf_product_name
|
||||
self.onboarding_state = onboarding_state
|
||||
self.usage_state = usage_state
|
||||
self.operational_state = operational_state
|
||||
self.vnfd_id = vnfd_id
|
||||
|
||||
|
||||
class VnfPackageTab(tabs.TableTab):
|
||||
name = _("VNFP tab")
|
||||
slug = "vnfpkg_tab"
|
||||
table_classes = (tables.VnfPackageTable,)
|
||||
template_name = ("horizon/common/_detail_table.html")
|
||||
preload = False
|
||||
|
||||
def has_prev_data(self, table):
|
||||
return self._has_prev
|
||||
|
||||
def has_more_data(self, table):
|
||||
return self._has_more
|
||||
|
||||
def get_vnfpackage_data(self):
|
||||
try:
|
||||
self._has_prev = False
|
||||
page_size = horizon_utils.functions.get_page_size(self.request)
|
||||
marker = self.request.GET.get(
|
||||
"package_marker", None)
|
||||
prev_marker = self.request.GET.get(
|
||||
"prev_package_marker", None)
|
||||
packages = api.tacker.list_vnf_packages(self.request)
|
||||
if marker is not None or prev_marker is not None:
|
||||
for i, package in enumerate(packages):
|
||||
if package["id"] == marker and i < len(packages) - 1:
|
||||
packages = packages[i + 1:]
|
||||
self._has_prev = True
|
||||
break
|
||||
if package["id"] == prev_marker and i > page_size:
|
||||
packages = packages[i - page_size:]
|
||||
self._has_prev = True
|
||||
break
|
||||
|
||||
if len(packages) > page_size:
|
||||
self._has_more = True
|
||||
else:
|
||||
self._has_more = False
|
||||
|
||||
rows = []
|
||||
for i, package in enumerate(packages):
|
||||
if i >= page_size:
|
||||
break
|
||||
item = VnfPackageItem(
|
||||
vnfpkg_id=package.get('id', ''),
|
||||
vnf_product_name=package.get('vnfProductName', ''),
|
||||
onboarding_state=package.get('onboardingState', ''),
|
||||
usage_state=package.get('usageState', ''),
|
||||
operational_state=package.get('operationalState', ''),
|
||||
vnfd_id=package.get('vnfdId', ''),)
|
||||
rows.append(item)
|
||||
return rows
|
||||
except Exception:
|
||||
self._has_more = False
|
||||
error_message = _('Failed to get VNF Packages.')
|
||||
exceptions.handle(self.request, error_message)
|
||||
|
||||
return []
|
||||
|
||||
|
||||
class VnfPackageTabs(tabs.TabGroup):
|
||||
slug = "vnfpkg_tabs"
|
||||
tabs = (VnfPackageTab,)
|
||||
sticky = True
|
||||
|
||||
|
||||
class VnfPackageDetailTab(tabs.Tab):
|
||||
name = _("VNFPkg Detail")
|
||||
slug = "vnfpkg_detail_tab"
|
||||
template_name = "nfv/vnfpackages/vnfpkg_detail.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
return {'vnfpkg': self.tab_group.kwargs['vnfpkg']}
|
||||
|
||||
|
||||
class VnfPackageDetailTabs(tabs.TabGroup):
|
||||
slug = "vnfpkg_detail_tabs"
|
||||
tabs = (VnfPackageDetailTab,)
|
||||
sticky = True
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Update a VNF Package information." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Upload a VNF Package." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "VNF Package Details" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=page_title %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "VNF Packages" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("VNF Packages") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Update VNF Package" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Update VNF Package") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/vnfpackages/_update_vnfpkg.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Upload VNF Package" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Upload VNF Package") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/vnfpackages/_upload_vnfpkg.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,34 @@
|
|||
{% load i18n %}
|
||||
|
||||
<div class="detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Additional Artifacts" %}</dt>
|
||||
<dd>{{ vnfpkg.additionalArtifacts }}</dd>
|
||||
<dt>{% trans "Checksum" %}</dt>
|
||||
<dd>{{ vnfpkg.checksum }}</dd>
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ vnfpkg.id }}</dd>
|
||||
<dt>{% trans "Links" %}</dt>
|
||||
<dd>{{ vnfpkg.links }}</dd>
|
||||
<dt>{% trans "Onboarding State" %}</dt>
|
||||
<dd>{{ vnfpkg.onboardingState }}</dd>
|
||||
<dt>{% trans "Operational State" %}</dt>
|
||||
<dd>{{ vnfpkg.operationalState }}</dd>
|
||||
<dt>{% trans "Software Images" %}</dt>
|
||||
<dd>{{ vnfpkg.softwareImages }}</dd>
|
||||
<dt>{% trans "Usage State" %}</dt>
|
||||
<dd>{{ vnfpkg.usageState }}</dd>
|
||||
<dt>{% trans "User Defined Data" %}</dt>
|
||||
<dd>{{ vnfpkg.userDefinedData }}</dd>
|
||||
<dt>{% trans "VNF Product Name" %}</dt>
|
||||
<dd>{{ vnfpkg.vnfProductName }}</dd>
|
||||
<dt>{% trans "VNF Provider" %}</dt>
|
||||
<dd>{{ vnfpkg.vnfProvider }}</dd>
|
||||
<dt>{% trans "VNF Software Version" %}</dt>
|
||||
<dd>{{ vnfpkg.vnfSoftwareVersion }}</dd>
|
||||
<dt>{% trans "VNFD ID" %}</dt>
|
||||
<dd>{{ vnfpkg.vnfdId }}</dd>
|
||||
<dt>{% trans "VNFD Version" %}</dt>
|
||||
<dd>{{ vnfpkg.vnfdVersion }}</dd>
|
||||
</dl>
|
||||
</div>
|
|
@ -0,0 +1,31 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.urls import re_path
|
||||
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnfpackages \
|
||||
import views
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^$', views.IndexView.as_view(), name='index'),
|
||||
re_path(r'^(?P<id>[^/]+)/fetch/$', views.fetch_vnf_package,
|
||||
name='fetch'),
|
||||
re_path(r'^uploadvnfpkg$', views.UploadVnfPackageView.as_view(),
|
||||
name='uploadvnfpkg'),
|
||||
re_path(r'^(?P<id>[^/]+)/$', views.DetailView.as_view(), name='detail'),
|
||||
re_path(r'^(?P<id>[^/]+)/updatevnfpkg/$',
|
||||
views.UpdateVnfPackageView.as_view(), name='updatevnfpkg'),
|
||||
]
|
|
@ -0,0 +1,121 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django import http
|
||||
from django.urls import reverse
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import tabs
|
||||
from horizon.utils import memoized
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api as tacker_api
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnfpackages \
|
||||
import forms as project_forms
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnfpackages \
|
||||
import tabs as vnfpkg_tabs
|
||||
|
||||
|
||||
def fetch_vnf_package(request, id):
|
||||
try:
|
||||
file = tacker_api.tacker.fetch_vnf_package(request, id)
|
||||
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_('Failed to fetch VNF Package. (id: %s)') % id,
|
||||
redirect="horizon:nfv:vnfpackages:index")
|
||||
response = http.HttpResponse(content_type='application/zip')
|
||||
response.write(file)
|
||||
response['Content-Disposition'] = (
|
||||
'attachment; filename="package-%s.zip"' % id)
|
||||
response['Content-Length'] = len(file)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
class IndexView(tabs.TabbedTableView):
|
||||
tab_group_class = vnfpkg_tabs.VnfPackageTabs
|
||||
template_name = 'nfv/vnfpackages/index.html'
|
||||
|
||||
|
||||
class UploadVnfPackageView(forms.ModalFormView):
|
||||
form_class = project_forms.UploadVnfPackage
|
||||
template_name = 'nfv/vnfpackages/upload_vnfpkg.html'
|
||||
success_url = reverse_lazy("horizon:nfv:vnfpackages:index")
|
||||
modal_id = "add_service_modal"
|
||||
modal_header = _("Upload VNF Package")
|
||||
submit_label = _("Upload VNF Package")
|
||||
submit_url = "horizon:nfv:vnfpackages:uploadvnfpkg"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(UploadVnfPackageView, self).get_context_data(**kwargs)
|
||||
context['submit_url'] = reverse(self.submit_url)
|
||||
return context
|
||||
|
||||
|
||||
class UpdateVnfPackageView(forms.ModalFormView):
|
||||
form_class = project_forms.UpdateVnfPackage
|
||||
template_name = 'nfv/vnfpackages/update_vnfpkg.html'
|
||||
success_url = reverse_lazy("horizon:nfv:vnfpackages:index")
|
||||
modal_id = "add_service_modal"
|
||||
modal_header = _("Update VNF Package Info")
|
||||
submit_label = _("Update VNF Package Info")
|
||||
submit_url = "horizon:nfv:vnfpackages:updatevnfpkg"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(UpdateVnfPackageView, self).get_context_data(**kwargs)
|
||||
context['id'] = self.kwargs['id']
|
||||
context['submit_url'] = reverse(self.submit_url,
|
||||
kwargs={'id': self.kwargs['id']})
|
||||
return context
|
||||
|
||||
|
||||
class DetailView(tabs.TabView):
|
||||
tab_group_class = vnfpkg_tabs.VnfPackageDetailTabs
|
||||
template_name = 'nfv/vnfpackages/detail.html'
|
||||
redirect_url = 'horizon:nfv:vnfpackages:index'
|
||||
page_title = _("VNF Package Details: {{ id }}")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
vnfpkg = self.get_data()
|
||||
context['vnfpkg'] = vnfpkg
|
||||
context['id'] = kwargs['id']
|
||||
context['url'] = reverse(self.redirect_url)
|
||||
|
||||
return context
|
||||
|
||||
@memoized.memoized_method
|
||||
def get_data(self):
|
||||
vnfpkg_id = self.kwargs.get('id', None)
|
||||
|
||||
try:
|
||||
vnfpkg = tacker_api.tacker.get_vnf_package(self.request, vnfpkg_id)
|
||||
vnfpkg['links'] = vnfpkg.get('_links', '')
|
||||
return vnfpkg
|
||||
except Exception:
|
||||
redirect = reverse(self.redirect_url)
|
||||
exceptions.handle(
|
||||
self.request,
|
||||
_('Failed to get VNF Package. (id: %s)') % vnfpkg_id,
|
||||
redirect=redirect)
|
||||
raise exceptions.Http302(redirect)
|
||||
|
||||
def get_tabs(self, request, *args, **kwargs):
|
||||
vnfpkg = self.get_data()
|
||||
return self.tab_group_class(request, vnfpkg=vnfpkg, **kwargs)
|
|
@ -0,0 +1,102 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
import json
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import messages
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
|
||||
|
||||
class CreatePmJob(forms.SelfHandlingForm):
|
||||
param_file = forms.FileField(
|
||||
label=_("Param File"),
|
||||
help_text=_("parameter file to upload."),
|
||||
widget=forms.FileInput(
|
||||
attrs={'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-file': _('Param File')}))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(CreatePmJob, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(CreatePmJob, self).clean()
|
||||
|
||||
try:
|
||||
param_str = self.files['param_file'].read()
|
||||
param = json.loads(param_str)
|
||||
data['param'] = param
|
||||
except Exception as e:
|
||||
msg = _('Failed to read file: %s.') % e
|
||||
raise forms.ValidationError(msg)
|
||||
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
param = data['param']
|
||||
pmjob = api.tacker.create_pm_job(request, param)
|
||||
messages.success(request,
|
||||
_('Create PM Job. (id: %s)') %
|
||||
pmjob['id'])
|
||||
return True
|
||||
except Exception:
|
||||
msg = _('Failed to create PM Job.')
|
||||
exceptions.handle(request, msg)
|
||||
return False
|
||||
|
||||
|
||||
class UpdatePmJob(forms.SelfHandlingForm):
|
||||
param_file = forms.FileField(
|
||||
label=_("Param File"),
|
||||
help_text=_("parameter file to upload."),
|
||||
widget=forms.FileInput(
|
||||
attrs={'class': 'switched',
|
||||
'data-switch-on': 'source',
|
||||
'data-source-file': _('Param File')}))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(UpdatePmJob, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
data = super(UpdatePmJob, self).clean()
|
||||
|
||||
try:
|
||||
param_str = self.files['param_file'].read()
|
||||
param = json.loads(param_str)
|
||||
data['param'] = param
|
||||
except Exception as e:
|
||||
msg = _('Failed to read file: %s.') % e
|
||||
raise forms.ValidationError(msg)
|
||||
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
param = data['param']
|
||||
job_id = request.resolver_match.kwargs['id']
|
||||
api.tacker.update_pm_job(request, job_id, param)
|
||||
messages.success(request,
|
||||
_('Update PM Job. (id: %s)') % job_id)
|
||||
return True
|
||||
except Exception:
|
||||
msg = _('Failed to update PM Job. (id: %s)') % job_id
|
||||
exceptions.handle(request, msg)
|
||||
return False
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
import horizon
|
||||
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv import dashboard
|
||||
|
||||
|
||||
class VnfPmJob(horizon.Panel):
|
||||
name = _("PM Job")
|
||||
slug = "vnfpmjob"
|
||||
|
||||
|
||||
dashboard.Nfv.register(VnfPmJob)
|
|
@ -0,0 +1,74 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext_lazy
|
||||
|
||||
from horizon import tables
|
||||
from openstack_dashboard import policy
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
|
||||
|
||||
class DeletePmJob(policy.PolicyTargetMixin, tables.DeleteAction):
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
return ngettext_lazy(
|
||||
"Delete PM Job",
|
||||
"Delete PM Jobs",
|
||||
count
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def action_past(count):
|
||||
return ngettext_lazy(
|
||||
"Delete PM Job",
|
||||
"Delete PM Jobs",
|
||||
count
|
||||
)
|
||||
|
||||
def action(self, request, obj_id):
|
||||
api.tacker.delete_pm_job(request, obj_id)
|
||||
|
||||
|
||||
class CreatePmJob(tables.LinkAction):
|
||||
name = "createpmjob"
|
||||
verbose_name = _("Create PM Job")
|
||||
classes = ("ajax-modal",)
|
||||
icon = "plus"
|
||||
url = "horizon:nfv:vnfpmjob:createpmjob"
|
||||
|
||||
|
||||
class UpdatePmJob(tables.LinkAction):
|
||||
name = "updatepmjob"
|
||||
verbose_name = _("Update PM Job")
|
||||
url = "horizon:nfv:vnfpmjob:updatepmjob"
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
|
||||
class VnfPmJobTable(tables.DataTable):
|
||||
id = tables.Column('id', link="horizon:nfv:vnfpmjob:detail",
|
||||
verbose_name=_("ID"))
|
||||
object_type = tables.Column('object_type', verbose_name=_("Object Type"))
|
||||
links = tables.Column('links', verbose_name=_("Links"))
|
||||
|
||||
class Meta(object):
|
||||
name = "pmjob"
|
||||
verbose_name = _("PM Job")
|
||||
pagination_param = 'vnfpmjob_marker'
|
||||
prev_pagination_param = 'prev_vnfpmjob_marker'
|
||||
table_actions = (CreatePmJob, DeletePmJob, tables.FilterAction,)
|
||||
row_actions = (UpdatePmJob, DeletePmJob,)
|
|
@ -0,0 +1,122 @@
|
|||
# Copyright (C) 2024 Fujitsu
|
||||
# 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.
|
||||
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs
|
||||
from horizon import utils as horizon_utils
|
||||
|
||||
from tacker_horizon.openstack_dashboard import api
|
||||
from tacker_horizon.openstack_dashboard.dashboards.nfv.vnfpmjob \
|
||||
import tables
|
||||
|
||||
|
||||
class VnfPmJobItem(object):
|
||||
def __init__(self, job_id, links, object_type):
|
||||
self.id = job_id
|
||||
self.name = job_id
|
||||
self.links = links
|
||||
self.object_type = object_type
|
||||
|
||||
|
||||
class VnfPmJobTab(tabs.TableTab):
|
||||
name = _("VNFPMJob Tab")
|
||||
slug = "vnfpmjob_tab"
|
||||
table_classes = (tables.VnfPmJobTable,)
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
preload = False
|
||||
|
||||
def has_prev_data(self, table):
|
||||
return self._has_prev
|
||||
|
||||
def has_more_data(self, table):
|
||||
return self._has_more
|
||||
|
||||
def get_pmjob_data(self):
|
||||
try:
|
||||
self._has_prev = False
|
||||
page_size = horizon_utils.functions.get_page_size(self.request)
|
||||
marker = self.request.GET.get("vnfpmjob_marker", None)
|
||||
prev_marker = self.request.GET.get("prev_vnfpmjob_marker", None)
|
||||
pmjobs = api.tacker.list_pm_jobs(self.request)
|
||||
|
||||
if marker is not None or prev_marker is not None:
|
||||
for i, pmjob in enumerate(pmjobs):
|
||||
if pmjob["id"] == marker and i < len(pmjobs) - 1:
|
||||
pmjobs = pmjobs[i + 1:]
|
||||
self._has_prev = True
|
||||
break
|
||||
if pmjob["id"] == prev_marker and i > page_size:
|
||||
pmjobs = pmjobs[i - page_size:]
|
||||
self._has_prev = True
|
||||
break
|
||||
|
||||
if len(pmjobs) > page_size:
|
||||
self._has_more = True
|
||||
else:
|
||||
self._has_more = False
|
||||
|
||||
rows = []
|
||||
for i, pmjob in enumerate(pmjobs):
|
||||
if i >= page_size:
|
||||
break
|
||||
item = VnfPmJobItem(pmjob['id'],
|
||||
pmjob['_links'],
|
||||
pmjob['objectType'])
|
||||
rows.append(item)
|
||||
return rows
|
||||
except Exception:
|
||||
self._has_more = False
|
||||
error_message = _('Failed to get PM Jobs.')
|
||||
exceptions.handle(self.request, error_message)
|
||||
return []
|
||||
|
||||
|
||||
class VnfPmJobTabs(tabs.TabGroup):
|
||||
slug = "vnfpmjob_tabs"
|
||||
tabs = (VnfPmJobTab,)
|
||||
sticky = True
|
||||
|
||||
|
||||
class VnfPmJobDetailTab(tabs.Tab):
|
||||
name = _("VNF PM Job")
|
||||
slug = "vnfpmjob_detail_tab"
|
||||
template_name = "nfv/vnfpmjob/pmjob_detail.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
return {'pmjob': self.tab_group.kwargs['pmjob']}
|
||||
|
||||
|
||||
class VnfPmJobDetailTabs(tabs.TabGroup):
|
||||
slug = "vnfpmjob_detail_tabs"
|
||||
tabs = (VnfPmJobDetailTab,)
|
||||
sticky = True
|
||||
|
||||
|
||||
class VnfPmJobReportDetailTab(tabs.Tab):
|
||||
name = _("PM Job Reports")
|
||||
slug = "vnfpmjob_report_detail_tab"
|
||||
template_name = "nfv/vnfpmjob/report_detail.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
return {'report': self.tab_group.kwargs['report']}
|
||||
|
||||
|
||||
class VnfPmJobReportDetailTabs(tabs.TabGroup):
|
||||
slug = "vnfpmjob_report_detail_tabs"
|
||||
tabs = (VnfPmJobReportDetailTab,)
|
||||
sticky = True
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Create a PM Job." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Update a PM Job." %}</p>
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Create PM Job" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Create PM Job") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nfv/vnfpmjob/_create_pmjob.html' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "PM Job Detail" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=page_title %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "PM Job" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("PM Job") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,57 @@
|
|||
{% load i18n %}
|
||||
|
||||
<style>
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
th, td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ pmjob.id }}</dd>
|
||||
<dt>{% trans "Links" %}</dt>
|
||||
<dd>{{ pmjob.links }}</dd>
|
||||
<dt>{% trans "Callback Uri" %}</dt>
|
||||
<dd>{{ pmjob.callback_uri }}</dd>
|
||||
<dt>{% trans "Criteria" %}</dt>
|
||||
<dd>{{ pmjob.criteria }}</dd>
|
||||
<dt>{% trans "Object Instance IDs" %}</dt>
|
||||
<dd>{{ pmjob.object_instance_ids }}</dd>
|
||||
<dt>{% trans "Object Type" %}</dt>
|
||||
<dd>{{ pmjob.object_type }}</dd>
|
||||
<dt>{% trans "Sub Object Instance IDs" %}</dt>
|
||||
<dd>{{ pmjob.sub_object_instance_ids }}</dd>
|
||||
<dt>{% trans "Reports" %}</dt>
|
||||
<dd>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<th><b>{% trans "readyTime" %}<br/></b></th>
|
||||
<th><b>{% trans "href" %}<br/></b></th>
|
||||
</tr>
|
||||
{% for report in pmjob.reports %}
|
||||
<tr>
|
||||
<td>{{ report.readyTime }}</td>
|
||||
<td>
|
||||
{% if report.href %}
|
||||
{% if report.id and report.reportId %}
|
||||
<a href="{% url 'horizon:nfv:vnfpmjob:reportdetail' report.id report.reportId %}">{{ report.href }}</a>
|
||||
{% else %}
|
||||
{% trans report.href %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% trans "-" %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
|
@ -0,0 +1,39 @@
|
|||
{% load i18n %}
|
||||
|
||||
<style>
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
th, td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Entries" %}</dt>
|
||||
<dd>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<th><b>{% trans "objectType" %}<br/></b></th>
|
||||
<th><b>{% trans "objectInstanceId" %}<br/></b></th>
|
||||
<th><b>{% trans "subObjectInstanceId" %}<br/></b></th>
|
||||
<th><b>{% trans "performanceMetric" %}<br/></b></th>
|
||||
<th><b>{% trans "performanceValues" %}<br/></b></th>
|
||||
</tr>
|
||||
{% for entrie in report.entries %}
|
||||
<tr>
|
||||
<td>{{ entrie.objectType }}</td>
|
||||
<td>{{ entrie.objectInstanceId }}</td>
|
||||
<td>{{ entrie.subObjectInstanceId }}</td>
|
||||
<td>{{ entrie.performanceMetric }}</td>
|
||||
<td>{{ entrie.performanceValues }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue