From c550e350c722af74787b7d1ab6fb8e0ed01a5cbe Mon Sep 17 00:00:00 2001 From: Jonathan Stout Date: Fri, 29 Jul 2022 09:52:08 -0400 Subject: [PATCH 01/52] remove auto-generation of peers on oracle endpoints fixes #1434 --- frontend/webservice/vrf.cgi | 58 -------------------- frontend/www/js_templates/modify_cloud.js | 4 +- frontend/www/js_templates/provision_cloud.js | 4 +- 3 files changed, 4 insertions(+), 62 deletions(-) diff --git a/frontend/webservice/vrf.cgi b/frontend/webservice/vrf.cgi index 37ec1ebd1..4cb4e86c8 100755 --- a/frontend/webservice/vrf.cgi +++ b/frontend/webservice/vrf.cgi @@ -601,35 +601,6 @@ sub provision_vrf{ $peerings->{"$endpoint->{node} $endpoint->{interface} $peer->{local_ip}"} = 1; next; } - if ($interface->cloud_interconnect_type eq 'oracle-fast-connect') { - my $prefix = $peering_config->prefix( - $endpoint->cloud_account_id, - $endpoint->interface_id, - $peering->{ip_version} - ); - - my $peer = new OESS::Peer( - db => $db, - model => { - peer_asn => $oracle_asn, - md5_key => '', - local_ip => $peering_config->nth_address($prefix, 1), - peer_ip => $peering_config->nth_address($prefix, 2), - ip_version => $peering->{ip_version}, - bfd => $peering->{bfd} - } - ); - my ($peer_id, $peer_err) = $peer->create(vrf_ep_id => $endpoint->vrf_endpoint_id); - if (defined $peer_err) { - $method->set_error($peer_err); - $db->rollback; - return; - } - $endpoint->add_peer($peer); - - $peerings->{"$endpoint->{node} $endpoint->{interface} $peer->{local_ip}"} = 1; - next; - } # Peerings not auto-generated for non-cloud endpoints if (defined $endpoint->{cloud_account_id} && $endpoint->{cloud_account_id} eq '') { @@ -762,35 +733,6 @@ sub provision_vrf{ $peerings->{"$endpoint->{node} $endpoint->{interface} $peering->{local_ip}"} = 1; next; } - if ($endpoint->cloud_interconnect_type eq 'oracle-fast-connect') { - my $prefix = $peering_config->prefix( - $endpoint->cloud_account_id, - $endpoint->interface_id, - $peering->{ip_version} - ); - - my $peer = new OESS::Peer( - db => $db, - model => { - peer_asn => $oracle_asn, - md5_key => '', - local_ip => $peering_config->nth_address($prefix, 1), - peer_ip => $peering_config->nth_address($prefix, 2), - ip_version => $peering->{ip_version}, - bfd => $peering->{bfd} - } - ); - my ($peer_id, $peer_err) = $peer->create(vrf_ep_id => $endpoint->vrf_endpoint_id); - if (defined $peer_err) { - $method->set_error($peer_err); - $db->rollback; - return; - } - $endpoint->add_peer($peer); - - $peerings->{"$endpoint->{node} $endpoint->{interface} $peer->{local_ip}"} = 1; - next; - } # Peerings not auto-generated for non-cloud endpoints if (defined $endpoint->{cloud_account_id} && $endpoint->{cloud_account_id} eq '') { diff --git a/frontend/www/js_templates/modify_cloud.js b/frontend/www/js_templates/modify_cloud.js index b9022a108..b3d697819 100644 --- a/frontend/www/js_templates/modify_cloud.js +++ b/frontend/www/js_templates/modify_cloud.js @@ -230,14 +230,14 @@ async function update() { e.index = i; e.peers = ('peers' in e) ? e.peers : []; e.editable = editable; - e.isPeeringAutoGenerated = (e.cloud_interconnect_type !== null && e.cloud_interconnect_type !== 'aws-hosted-connection'); + e.isPeeringAutoGenerated = (e.cloud_interconnect_type !== null && e.cloud_interconnect_type !== 'aws-hosted-connection' && e.cloud_interconnect_type !== 'oracle-fast-connect'); let endpoint = new Endpoint2('#endpoints2-list', e); e.peers.map(function(p, j) { p.index = j; p.endpointIndex = i; p.editable = editable; - p.isPeeringAutoGenerated = (e.cloud_interconnect_type !== null && e.cloud_interconnect_type !== 'aws-hosted-connection'); + p.isPeeringAutoGenerated = (e.cloud_interconnect_type !== null && e.cloud_interconnect_type !== 'aws-hosted-connection' && e.cloud_interconnect_type !== 'oracle-fast-connect'); let peeringElem = endpoint.peerings(); let peering = new Peering2(peeringElem, p); diff --git a/frontend/www/js_templates/provision_cloud.js b/frontend/www/js_templates/provision_cloud.js index a3d15cf71..64e008b4e 100644 --- a/frontend/www/js_templates/provision_cloud.js +++ b/frontend/www/js_templates/provision_cloud.js @@ -94,14 +94,14 @@ async function update(props) { e.index = i; e.peers = ('peers' in e) ? e.peers : []; e.editable = true; - e.isPeeringAutoGenerated = (e.cloud_interconnect_type !== null && e.cloud_interconnect_type !== 'aws-hosted-connection'); + e.isPeeringAutoGenerated = (e.cloud_interconnect_type !== null && e.cloud_interconnect_type !== 'aws-hosted-connection' && e.cloud_interconnect_type !== 'oracle-fast-connect'); let endpoint = new Endpoint2('#endpoints2-list', e); e.peers.map(function(p, j) { p.index = j; p.endpointIndex = i; p.editable = true; - p.isPeeringAutoGenerated = (e.cloud_interconnect_type !== null && e.cloud_interconnect_type !== 'aws-hosted-connection'); + p.isPeeringAutoGenerated = (e.cloud_interconnect_type !== null && e.cloud_interconnect_type !== 'aws-hosted-connection' && e.cloud_interconnect_type !== 'oracle-fast-connect'); let peeringElem = endpoint.peerings(); let peering = new Peering2(peeringElem, p); From a5a60db23528347e2eae1f2498f385582cd2876d Mon Sep 17 00:00:00 2001 From: Jonathan Stout Date: Fri, 29 Jul 2022 17:49:49 -0400 Subject: [PATCH 02/52] set default asn on oracle peers --- frontend/www/js_templates/l3/endpoint.js | 5 +++-- frontend/www/js_templates/l3/peering_modal.js | 20 +++++++++++++++---- frontend/www/js_templates/modify_cloud.js | 2 +- frontend/www/js_templates/provision_cloud.js | 2 +- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/frontend/www/js_templates/l3/endpoint.js b/frontend/www/js_templates/l3/endpoint.js index 02e0f0824..4916608c7 100644 --- a/frontend/www/js_templates/l3/endpoint.js +++ b/frontend/www/js_templates/l3/endpoint.js @@ -47,7 +47,7 @@ class Endpoint2 { }.bind(this)); this.element.querySelector('.add-peering-button').addEventListener('click', function(e) { - let modal = new PeeringModal('#peering-modal', endpoint); + let modal = new PeeringModal('#peering-modal', endpoint, endpoint.cloud_interconnect_type); modal.onSubmit((peering) => { if (!'peerings' in endpoint) { endpoint.peers = []; @@ -58,7 +58,8 @@ class Endpoint2 { update(); }); - modal.display(null); + modal.display(null, endpoint.cloud_interconnect_type); + }.bind(this)); diff --git a/frontend/www/js_templates/l3/peering_modal.js b/frontend/www/js_templates/l3/peering_modal.js index df21f9566..a0eaf5419 100644 --- a/frontend/www/js_templates/l3/peering_modal.js +++ b/frontend/www/js_templates/l3/peering_modal.js @@ -1,5 +1,5 @@ class PeeringModal { - constructor(query, peering) { + constructor(query, peering, cloud_interconnect_type) { let template = document.querySelector('#template-l3-peering-modal'); this.element = document.importNode(template.content, true); @@ -33,6 +33,12 @@ class PeeringModal { this.element.querySelector(`.oess-peer-ip`).setAttribute('disabled', true); } + if (cloud_interconnect_type === 'oracle-fast-connect') { + this.element.querySelector(`.bgp-asn`).value = 31898; + this.element.querySelector(`.bgp-asn`).placeholder = 31898; + this.element.querySelector('.bgp-asn').setAttribute('disabled', true); + } + this.parent = document.querySelector(query); this.parent.innerHTML = ''; this.parent.appendChild(this.element); @@ -100,13 +106,19 @@ class PeeringModal { } } - display(peering) { + display(peering, cloud_interconnect_type) { if (peering === null) { this.parent.querySelector(`.ip-version`).selectedIndex = 0; this.parent.querySelector(`.ip-version`).onchange = this.handleIpVersionChange; - this.parent.querySelector(`.bgp-asn`).value = null; - this.parent.querySelector(`.bgp-asn`).placeholder = 0; + if (cloud_interconnect_type === 'oracle-fast-connect') { + this.parent.querySelector(`.bgp-asn`).value = 31898; + this.parent.querySelector(`.bgp-asn`).placeholder = 31898; + this.parent.querySelector('.bgp-asn').setAttribute('disabled', true); + } else { + this.parent.querySelector(`.bgp-asn`).value = null; + this.parent.querySelector(`.bgp-asn`).placeholder = 0; + } this.parent.querySelector(`.bgp-key`).value = null; this.parent.querySelector(`.bgp-key`).placeholder = ''; diff --git a/frontend/www/js_templates/modify_cloud.js b/frontend/www/js_templates/modify_cloud.js index b3d697819..dfc03ddb7 100644 --- a/frontend/www/js_templates/modify_cloud.js +++ b/frontend/www/js_templates/modify_cloud.js @@ -240,7 +240,7 @@ async function update() { p.isPeeringAutoGenerated = (e.cloud_interconnect_type !== null && e.cloud_interconnect_type !== 'aws-hosted-connection' && e.cloud_interconnect_type !== 'oracle-fast-connect'); let peeringElem = endpoint.peerings(); - let peering = new Peering2(peeringElem, p); + let peering = new Peering2(peeringElem, p, e.cloud_interconnect_type); peering.onDelete(function(peering) { state.deletePeering(i, j); update(); diff --git a/frontend/www/js_templates/provision_cloud.js b/frontend/www/js_templates/provision_cloud.js index 64e008b4e..410ac039b 100644 --- a/frontend/www/js_templates/provision_cloud.js +++ b/frontend/www/js_templates/provision_cloud.js @@ -104,7 +104,7 @@ async function update(props) { p.isPeeringAutoGenerated = (e.cloud_interconnect_type !== null && e.cloud_interconnect_type !== 'aws-hosted-connection' && e.cloud_interconnect_type !== 'oracle-fast-connect'); let peeringElem = endpoint.peerings(); - let peering = new Peering2(peeringElem, p); + let peering = new Peering2(peeringElem, p, e.cloud_interconnect_type); peering.onDelete(function(peering) { state.deletePeering(i, j); update(); From a66990d293eb18d0b61dc4157c33866ed22abbca Mon Sep 17 00:00:00 2001 From: Jonathan Stout Date: Fri, 16 Sep 2022 17:06:10 -0400 Subject: [PATCH 03/52] load endpoint selection options from api --- frontend/webservice/interface.cgi | 19 +++ .../l2/endpoint_selection_modal2.html | 1 + frontend/www/js_templates/api/interfaces.js | 18 ++ .../l2/endpoint_selection_modal.js | 154 ++++++++++++------ frontend/www/js_templates/modify_l2vpn.js | 7 +- frontend/www/js_templates/provision_l2vpn.js | 7 + .../OESS/t/conf/interface-speed-config.xml | 2 +- 7 files changed, 154 insertions(+), 54 deletions(-) diff --git a/frontend/webservice/interface.cgi b/frontend/webservice/interface.cgi index 3a452d1d1..39e778a1d 100755 --- a/frontend/webservice/interface.cgi +++ b/frontend/webservice/interface.cgi @@ -4,6 +4,7 @@ use strict; use warnings; use AnyEvent; +use GRNOC::Config; use GRNOC::WebService::Method; use GRNOC::WebService::Dispatcher; @@ -20,6 +21,7 @@ use OESS::VRF; use OESS::Webservice; use OESS::Workgroup; +my $options_config_path = '/etc/oess/interface-speed-config.xml'; my $config = new OESS::Config(config_filename => '/etc/oess/database.xml'); my $db = new OESS::DB(config_obj => $config); @@ -59,6 +61,13 @@ sub register_ro_methods { $svc->register_method($method); + my $get_options = GRNOC::WebService::Method->new( + name => "get_options", + description => "get_options returns provisioning options for interfaces", + callback => sub { get_options(@_) } + ); + $svc->register_method($get_options); + my $get_interface = GRNOC::WebService::Method->new( name => "get_interface", description => "get_interface returns the requested interface", @@ -253,6 +262,16 @@ sub is_vlan_available { return {results => {allowed => $interface->vlan_valid( workgroup_id => $workgroup_id, vlan => $vlan )}}; } +sub get_options { + my $method = shift; + my $params = shift; + + my $config = new GRNOC::Config(config_file => $options_config_path, force_array => 1); + my $selectors = $config->get("/config/interface-selector"); + + return {results => $selectors}; +} + sub get_workgroup_interfaces { my $method = shift; my $params = shift; diff --git a/frontend/www/html_templates/l2/endpoint_selection_modal2.html b/frontend/www/html_templates/l2/endpoint_selection_modal2.html index 6e0aed5c3..7f6fc1438 100644 --- a/frontend/www/html_templates/l2/endpoint_selection_modal2.html +++ b/frontend/www/html_templates/l2/endpoint_selection_modal2.html @@ -71,6 +71,7 @@

Select an Endpoint

+ +   + + + ); + }; + + let columns = [ + { name: 'User', key: 'tag' }, + { name: 'Workgroup', key: 'tag' }, + { name: 'Type', key: 'cloud_interconnect_type' }, + { name: 'Entity', key: 'entity' }, + { name: 'Bandwidth (Mbps)', key: 'bandwidth' }, + { name: 'Date', key: 'tag' }, + { name: '', render: rowButtons, style: {textAlign: 'right'} } + ]; + + return ( +
+
+

Cloud

+

Provisioning Requests

+

Approve or deny cloud provisioning requests

+
+
+ + + +
+ ); + } +} +Cloud.contextType = PageContext; + +export { Cloud }; diff --git a/frontend/www/new/admin_new/src/style.css b/frontend/www/new/admin_new/src/style.css index 0186f3d39..cb3db909e 100644 --- a/frontend/www/new/admin_new/src/style.css +++ b/frontend/www/new/admin_new/src/style.css @@ -42,6 +42,10 @@ margin-bottom: 1em; margin-top: 1em; font-size: 20px; } +.title2{ + margin-top: 1em; + font-size: 16px; +} tr:hover td{ background-color:#B2D2FF !important; } diff --git a/perl-lib/OESS/lib/OESS/DB/Endpoint.pm b/perl-lib/OESS/lib/OESS/DB/Endpoint.pm index e196da48b..1041da86f 100644 --- a/perl-lib/OESS/lib/OESS/DB/Endpoint.pm +++ b/perl-lib/OESS/lib/OESS/DB/Endpoint.pm @@ -62,6 +62,7 @@ sub fetch_all { entity_id => undef, interface_id => undef, node_id => undef, + state => 'active', @_ }; @@ -110,6 +111,10 @@ sub fetch_all { push @$params, 'cloud.cloud_account_id=?'; push @$values, $args->{cloud_account_id}; } + if (defined $args->{state}) { + push @$params, 'state=?'; + push @$values, $args->{state}; + } my $where = (@$params > 0) ? 'WHERE ' . join(' AND ', @$params) : 'WHERE 1 '; @@ -154,7 +159,7 @@ sub fetch_all { JOIN node_instantiation ON node.node_id=node_instantiation.node_id and node_instantiation.end_epoch=-1 LEFT JOIN cloud_connection_vrf_ep as cloud on cloud.circuit_ep_id=circuit_ep.circuit_edge_id $where - AND circuit_ep.end_epoch = -1 AND circuit_ep.state != 'decom' + AND circuit_ep.end_epoch = -1 "; my $circuit_endpoints = $args->{db}->execute_query($q, $values); if (!defined $circuit_endpoints) { @@ -218,7 +223,6 @@ sub fetch_all { JOIN node_instantiation ON node.node_id=node_instantiation.node_id and node_instantiation.end_epoch=-1 LEFT JOIN cloud_connection_vrf_ep as cloud on cloud.vrf_ep_id=vrf_ep.vrf_ep_id $where - AND vrf_ep.state != 'decom' "; my $vrf_endpoints = $args->{db}->execute_query($q, $values); From b234b92d4d2599f98cca78cea9bb6b145cff604c Mon Sep 17 00:00:00 2001 From: Jonathan Stout Date: Fri, 30 Sep 2022 15:15:07 -0400 Subject: [PATCH 11/52] call update_cache on approve --- frontend/webservice/admin/admin.cgi | 1 + perl-lib/OESS/lib/OESS/DB/Endpoint.pm | 5 +++++ perl-lib/OESS/lib/OESS/Endpoint.pm | 6 ++++-- perl-lib/OESS/lib/OESS/L2Circuit.pm | 4 +++- perl-lib/OESS/lib/OESS/VRF.pm | 4 +++- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/frontend/webservice/admin/admin.cgi b/frontend/webservice/admin/admin.cgi index 413fb9948..196de48a7 100755 --- a/frontend/webservice/admin/admin.cgi +++ b/frontend/webservice/admin/admin.cgi @@ -1065,6 +1065,7 @@ sub review_endpoint { return; } + $conn->load_endpoints; $db2->commit; my $mq = OESS::RabbitMQ::Client->new( diff --git a/perl-lib/OESS/lib/OESS/DB/Endpoint.pm b/perl-lib/OESS/lib/OESS/DB/Endpoint.pm index 1041da86f..c7782087b 100644 --- a/perl-lib/OESS/lib/OESS/DB/Endpoint.pm +++ b/perl-lib/OESS/lib/OESS/DB/Endpoint.pm @@ -63,6 +63,7 @@ sub fetch_all { interface_id => undef, node_id => undef, state => 'active', + state_not => undef, @_ }; @@ -115,6 +116,10 @@ sub fetch_all { push @$params, 'state=?'; push @$values, $args->{state}; } + if (defined $args->{state_not}) { + push @$params, 'state!=?'; + push @$values, $args->{state_not}; + } my $where = (@$params > 0) ? 'WHERE ' . join(' AND ', @$params) : 'WHERE 1 '; diff --git a/perl-lib/OESS/lib/OESS/Endpoint.pm b/perl-lib/OESS/lib/OESS/Endpoint.pm index eb3b89e16..770c7b366 100644 --- a/perl-lib/OESS/lib/OESS/Endpoint.pm +++ b/perl-lib/OESS/lib/OESS/Endpoint.pm @@ -255,7 +255,8 @@ sub _fetch_from_db{ my ($data, $err) = OESS::DB::Endpoint::fetch_all( db => $self->{db}, circuit_id => $self->{circuit_id}, - interface_id => $self->{interface_id} + interface_id => $self->{interface_id}, + state => undef, ); if (!defined $err) { $hash = $data->[0]; @@ -263,7 +264,8 @@ sub _fetch_from_db{ } else { my ($data, $err) = OESS::DB::Endpoint::fetch_all( db => $db, - vrf_ep_id => $self->{vrf_endpoint_id} + vrf_ep_id => $self->{vrf_endpoint_id}, + state => undef, ); if (defined $err) { $self->{logger}->error($err); diff --git a/perl-lib/OESS/lib/OESS/L2Circuit.pm b/perl-lib/OESS/lib/OESS/L2Circuit.pm index 4c0b3c62d..2f20b74e4 100644 --- a/perl-lib/OESS/lib/OESS/L2Circuit.pm +++ b/perl-lib/OESS/lib/OESS/L2Circuit.pm @@ -1031,7 +1031,9 @@ sub load_endpoints { my ($ep_datas, $error) = OESS::DB::Endpoint::fetch_all( db => $self->{db}, - circuit_id => $self->{circuit_id} + circuit_id => $self->{circuit_id}, + state => undef, + state_not => 'decom' ); $self->{endpoints} = []; diff --git a/perl-lib/OESS/lib/OESS/VRF.pm b/perl-lib/OESS/lib/OESS/VRF.pm index 2e2f7300a..2eb8d5ac4 100644 --- a/perl-lib/OESS/lib/OESS/VRF.pm +++ b/perl-lib/OESS/lib/OESS/VRF.pm @@ -176,7 +176,9 @@ sub load_endpoints { my ($ep_datas, $error) = OESS::DB::Endpoint::fetch_all( db => $self->{db}, - vrf_id => $self->{vrf_id} + vrf_id => $self->{vrf_id}, + state => undef, + state_not => 'decom' ); $self->{logger}->warn($error) if defined $error; From 05fc1014c64e17f84e43bdf75e9de65d9e656e0f Mon Sep 17 00:00:00 2001 From: Jonathan Stout Date: Thu, 6 Oct 2022 16:26:23 -0400 Subject: [PATCH 12/52] add email template for connections with endpoints in-review --- Dockerfile.dev | 3 +- Makefile | 11 +- .../new/admin_new/src/pages/cloud/Cloud.jsx | 2 +- perl-lib/OESS/entrypoint.dev.sh | 4 + .../etc/notification_endpoint_review.tt.html | 401 ++++++++++++++++++ ...otification_templates_endpoint_review.tmpl | 17 + .../OESS/lib/OESS/Cloud/BandwidthValidator.pm | 21 +- perl-lib/OESS/lib/OESS/Notification.pm | 131 ++++++ 8 files changed, 571 insertions(+), 19 deletions(-) create mode 100644 perl-lib/OESS/etc/notification_endpoint_review.tt.html create mode 100644 perl-lib/OESS/etc/notification_templates_endpoint_review.tmpl diff --git a/Dockerfile.dev b/Dockerfile.dev index 66ee4ad05..b01bf3cec 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -8,7 +8,7 @@ RUN yum makecache RUN yum -y install epel-release RUN yum -y install perl httpd mariadb-server rabbitmq-server RUN yum -y install perl-Carp-Always perl-Test-Deep perl-Test-Exception perl-Test-Pod perl-Test-Pod-Coverage perl-Devel-Cover perl-Net-AMQP-RabbitMQ perl-LWP-Protocol-https perl-AnyEvent-HTTP perl-GRNOC-CLI perl-Text-CSV perl-Net-IP -RUN yum -y install perl-OESS oess-core oess-frontend yui2 +RUN yum -y install perl-OESS oess-core oess-frontend yui2 postfix COPY app/mpls/mpls_discovery.pl /usr/bin/mpls_discovery.pl COPY app/mpls/mpls_fwdctl.pl /usr/bin/mpls_fwdctl.pl @@ -24,6 +24,7 @@ COPY perl-lib/OESS/t/conf/interface-speed-config.xml /etc/oess/interface-speed-c COPY perl-lib/OESS/t/conf/logging.conf /etc/oess/logging.conf COPY perl-lib/OESS/t/conf/passwd.xml /etc/oess/.passwd.xml COPY perl-lib/OESS/t/conf/integration.sql /etc/oess/integration.sql +COPY perl-lib/OESS/etc/* /usr/share/oess-core/ COPY perl-lib/OESS/entrypoint.dev.sh /entrypoint.sh RUN chmod 777 /entrypoint.sh diff --git a/Makefile b/Makefile index eee4cb56f..01d79fea7 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -OESS_VERSION=2.0.15 +OESS_VERSION=2.0.16 OESS_NETWORK=oess TEST_FILES= @@ -21,12 +21,6 @@ test: docker run --rm -it -e OESS_TEST_FILES="$(TEST_FILES)" --volume ${PWD}/perl-lib/OESS:/perl-lib/OESS oess-test # For single container builds. Should only be used for testing. -container: - docker build -f Dockerfile.dev --tag oess:${OESS_VERSION} . - -clean-container: - docker build --no-cache -f Dockerfile.dev --tag oess:${OESS_VERSION} . - # To attach OESS to an existing docker network: # --network ${OESS_NETWORK} # @@ -38,6 +32,7 @@ clean-container: # --cap-add=NET_ADMIN # dev: + docker build --no-cache -f Dockerfile.dev --tag oess:${OESS_VERSION} . docker run -it \ --name oess-dev \ --rm \ @@ -48,8 +43,10 @@ dev: --mount type=bind,src=${PWD}/perl-lib/OESS/lib/OESS,dst=/usr/share/perl5/vendor_perl/OESS \ --mount type=bind,src=${PWD}/frontend,dst=/usr/share/oess-frontend \ --mount type=bind,src=${PWD}/perl-lib/OESS/share,dst=/usr/share/doc/perl-OESS-${OESS_VERSION}/share \ + --mount type=bind,src=${PWD}/perl-lib/OESS/t,dst=/usr/share/doc/perl-OESS-${OESS_VERSION}/t \ --mount type=bind,src=${PWD}/app,dst=/usr/bin/oess \ --mount type=bind,src=${PWD}/docs,dst=/docs \ + --mount type=bind,src=${PWD}/perl-lib/OESS/etc,dst=/usr/share/oess-core \ oess:${OESS_VERSION} /bin/bash documentation: diff --git a/frontend/www/new/admin_new/src/pages/cloud/Cloud.jsx b/frontend/www/new/admin_new/src/pages/cloud/Cloud.jsx index d4eb18182..cc08ea3d1 100644 --- a/frontend/www/new/admin_new/src/pages/cloud/Cloud.jsx +++ b/frontend/www/new/admin_new/src/pages/cloud/Cloud.jsx @@ -50,7 +50,7 @@ class Cloud extends React.Component {   diff --git a/perl-lib/OESS/entrypoint.dev.sh b/perl-lib/OESS/entrypoint.dev.sh index 190b642d4..cc3b67240 100644 --- a/perl-lib/OESS/entrypoint.dev.sh +++ b/perl-lib/OESS/entrypoint.dev.sh @@ -50,6 +50,10 @@ sed -i "s/test/$NETCONF_PASSWORD/" /etc/oess/.passwd.xml sed -i "s/900/$NETCONF_DIFF_INTERVAL/" /etc/oess/fwdctl.xml # Start OESS + +sed -i "s/inet_interfaces = localhost/inet_interfaces = 127.0.0.1/" /etc/postfix/main.cf + +/usr/sbin/postfix start & /usr/bin/oess-notify.pl & /usr/bin/mpls_discovery.pl & /usr/bin/mpls_fwdctl.pl & diff --git a/perl-lib/OESS/etc/notification_endpoint_review.tt.html b/perl-lib/OESS/etc/notification_endpoint_review.tt.html new file mode 100644 index 000000000..622e3a7d1 --- /dev/null +++ b/perl-lib/OESS/etc/notification_endpoint_review.tt.html @@ -0,0 +1,401 @@ + + + + + + + + + + + [% SUBJECT %] + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌  +
+ + + + + + + + +
+ +
+ + + + + + + + + + + +
+ +
+ + + +
+ + diff --git a/perl-lib/OESS/etc/notification_templates_endpoint_review.tmpl b/perl-lib/OESS/etc/notification_templates_endpoint_review.tmpl new file mode 100644 index 000000000..1d4f14fc7 --- /dev/null +++ b/perl-lib/OESS/etc/notification_templates_endpoint_review.tmpl @@ -0,0 +1,17 @@ +Greetings workgroup [%workgroup%], + +Connection: [% description %] +Owned by: [% workgroup %] +Last modified by: [% last_modified_by %] on [% human_time %] + +Endpoints +The following Endpoints require administrative approval: + +[% FOREACH ep IN endpoints -%] +Entity: [% ep.entity %] +Interface: [% ep.node %] - [% ep.interface %] +VLAN: [% ep.tag %] +Bandwidth: [% ep.bandwidth %] +Interconnect Type: [% ep.cloud_interconnect_type %] +State: [% ep.state %] +[% END -%] diff --git a/perl-lib/OESS/lib/OESS/Cloud/BandwidthValidator.pm b/perl-lib/OESS/lib/OESS/Cloud/BandwidthValidator.pm index 0356d2e13..be2924940 100644 --- a/perl-lib/OESS/lib/OESS/Cloud/BandwidthValidator.pm +++ b/perl-lib/OESS/lib/OESS/Cloud/BandwidthValidator.pm @@ -94,16 +94,17 @@ sub requires_approval { if (defined $check->{requires_approval} && $check->{requires_approval} eq "1") { - if (defined $check->{admin_only} && $check->{admin_only} eq "1" && $args->{is_admin} == 1) { - # Admin users will never require approval when provisioning - # endpoints. Because of this: - # - Notifications for provisioning requests will never be sent - # for admin users - # - Approval for these endpoints are auto-accepted - return 0; - } else { - return 1; - } + return 1; + # if (defined $check->{admin_only} && $check->{admin_only} eq "1" && $args->{is_admin} == 1) { + # # Admin users will never require approval when provisioning + # # endpoints. As a result, the follow hold true: + # # - Notifications for provisioning requests will never be sent + # # for admin users + # # - Approval for these endpoints are auto-accepted + # return 0; + # } else { + # return 1; + # } } } diff --git a/perl-lib/OESS/lib/OESS/Notification.pm b/perl-lib/OESS/lib/OESS/Notification.pm index 5ed39ce5b..71d1912e0 100644 --- a/perl-lib/OESS/lib/OESS/Notification.pm +++ b/perl-lib/OESS/lib/OESS/Notification.pm @@ -19,6 +19,7 @@ use GRNOC::WebService::Regex; use OESS::RabbitMQ::Client; use OESS::RabbitMQ::Dispatcher; use OESS::Circuit; +use OESS::L2Circuit; use Log::Log4perl; #new stuff @@ -142,6 +143,27 @@ sub _register_notification_events{ schema => { 'type' => 'array'}); $d->register_method($method); + $self->{'log'}->debug("Register Notification events"); + $method = GRNOC::RabbitMQ::Method->new( + name => "review_endpoint_notification", + topic => 'OF.FWDCTL.event', + callback => sub {$self->review_endpoint_notification(@_) }, + description => "Signals endpoint review required notification event" + ); + $method->add_input_parameter( + name => "connection_id", + description => "Id of related connection", + required => 1, + schema => { 'type' => 'integer'} + ); + $method->add_input_parameter( + name => "connection_type", + description => "Type of related connection", + required => 1, + pattern => $GRNOC::WebService::Regex::TEXT + ); + $d->register_method($method); + $self->{'log'}->debug("Register Notification events"); $method = GRNOC::RabbitMQ::Method->new( name => "vrf_notification", topic => 'OF.FWDCTL.event', @@ -171,6 +193,115 @@ sub _register_notification_events{ } +=head2 review_endpoint_notification + +=cut +sub review_endpoint_notification { + my $self = shift; + my $method = shift; + my $params = shift; + + my $subject = "OESS - Administrative Approval Required"; + + my $connection = undef; + my $connection_id = $params->{connection_id}{value}; + + if ($params->{connection_type}{value} eq 'circuit') { + $connection = new OESS::L2Circuit(db => $self->{db_new}, circuit_id => $connection_id); + if (!defined $connection) { + $self->{log}->error("L2 connection $connection_id could not be loaded"); + return; + } + $connection->load_endpoints; + $connection->load_users; + $connection->load_workgroup; + } else { + $connection = new OESS::VRF(db => $self->{db_new}, vrf_id => $connection_id); + if (!defined $connection) { + $self->{log}->error("L3 connection $connection_id could not be loaded"); + return; + } + $connection->load_endpoints; + $connection->load_users; + $connection->load_workgroup; + } + my $payload = $connection->to_hash; + + return $self->send_review_endpoint_notification( + subject => $subject, + connection => $payload, + ); +} + +=head2 send_review_endpoint_notification + +=cut +sub send_review_endpoint_notification { + my $self = shift; + my $args = { + subject => undef, + connection => undef, + connection_type => 'circuit', + @_ + }; + + # TODO load endpoints into $clr + my $endpoints = []; + + my $dt = DateTime->from_epoch( epoch => $args->{connection}->{last_modified} ); + my $human_time = $dt->day_name() . ", " . $dt->month_name() . " " . $dt->day() . ", " . $dt->year() . ", at " . $dt->hms() . " UTC"; + + foreach my $ep (@{$args->{connection}->{endpoints}}) { + next if ($ep->{state} ne 'in-review'); + + $ep->{cloud_interconnect_type} = (defined $ep->{cloud_interconnect_type}) ? $ep->{cloud_interconnect_type} : 'Unkown'; + $ep->{entity} = (defined $ep->{entity}) ? $ep->{entity} : 'Unkown'; + + push @$endpoints, $ep; + } + warn Dumper($args->{connection}); + + my $vars = { + SUBJECT => $args->{subject}, + base_url => $self->{base_url}, + workgroup => $args->{connection}->{workgroup}->{name}, + description => $args->{connection}->{description}, + endpoints => $endpoints, + from_signature_name => $self->{from_name}, + last_modified_by => "$args->{connection}->{last_modified_by}->{first_name} $args->{connection}->{last_modified_by}->{last_name}", + image_base_url => $self->{image_base_url}, + human_time => $human_time + }; + + my $tmpl_options = { + ABSOLUTE=>1, + RELATIVE=>0, + }; + + # TODO generate $to_string + my $to_string = 'jonstout@globalnoc.iu.edu'; + eval { + my $message = MIME::Lite::TT::HTML->new( + From => $self->{'from_address'}, + To => $to_string, + Subject => $args->{subject}, + Encoding => 'quoted-printable', + Timezone => 'UTC', + Template => { + html => "$self->{template_path}/notification_endpoint_review.tt.html", + text => "$self->{template_path}/notification_templates_endpoint_review.tmpl" + }, + TmplParams => $vars, + TmplOptions => $tmpl_options, + ); + $message->send('smtp', 'localhost'); + }; + if ($@) { + $self->{log}->error("Error sending Notification: " . $@); + } + + return 1; +} =head2 vrf_notification From 94dd076c1dbcdb40ace202232ec312259b8d5de8 Mon Sep 17 00:00:00 2001 From: Jonathan Stout Date: Fri, 7 Oct 2022 16:49:26 -0400 Subject: [PATCH 13/52] add loading indicator while approving endpoint --- frontend/webservice/vrf.cgi | 12 +++++ .../generic_components/BaseModal.jsx | 19 +++++--- .../new/admin_new/src/pages/cloud/Cloud.jsx | 44 ++++++++++++++----- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/frontend/webservice/vrf.cgi b/frontend/webservice/vrf.cgi index 9769d633c..afdc30743 100755 --- a/frontend/webservice/vrf.cgi +++ b/frontend/webservice/vrf.cgi @@ -451,6 +451,7 @@ sub provision_vrf{ $endpoints->{$ep->vrf_endpoint_id} = $ep; } + my $admin_approval_required = 0; my $add_endpoints = []; my $del_endpoints = []; @@ -556,6 +557,7 @@ sub provision_vrf{ # of these endpoints shall be avoided. push @$add_endpoints, $endpoint; } else { + $admin_approval_required = 1; warn "Endpoint will require admin approval"; } @@ -962,6 +964,16 @@ sub provision_vrf{ ); }; + if ($admin_approval_required) { + eval { + $log_client->review_endpoint_notification( + connection_id => $vrf->vrf_id, + connection_type => 'vrf', + no_reply => 1 + ); + }; + } + return { results => { success => 1, vrf_id => $vrf->vrf_id } }; } diff --git a/frontend/www/new/admin_new/src/components/generic_components/BaseModal.jsx b/frontend/www/new/admin_new/src/components/generic_components/BaseModal.jsx index faef26769..12c96c82f 100644 --- a/frontend/www/new/admin_new/src/components/generic_components/BaseModal.jsx +++ b/frontend/www/new/admin_new/src/components/generic_components/BaseModal.jsx @@ -18,6 +18,18 @@ class BaseModal extends Component { let onClose = (this.props.onClose) ? this.props.onClose : () => {}; + let header = null; + if (this.props.header !== undefined) { + header = ( +
+ +

{this.props.header}

+
+ ); + } + return (
{backdrop} @@ -25,12 +37,7 @@ class BaseModal extends Component {