cisco_node_utils 1.5.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/README.md +2 -1
- data/docs/cisco_node_utils.yaml.example +6 -0
- data/lib/cisco_node_utils/cisco_cmn_utils.rb +6 -15
- data/lib/cisco_node_utils/client/nxapi/client.rb +19 -1
- data/lib/cisco_node_utils/client/utils.rb +1 -1
- data/lib/cisco_node_utils/cmd_ref/README_YAML.md +1 -1
- data/lib/cisco_node_utils/cmd_ref/interface.yaml +25 -0
- data/lib/cisco_node_utils/cmd_ref/radius_global.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/radius_server.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/route_map.yaml +592 -0
- data/lib/cisco_node_utils/cmd_ref/snmp_community.yaml +40 -12
- data/lib/cisco_node_utils/cmd_ref/tacacs_global.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/tacacs_server.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/tacacs_server_host.yaml +1 -1
- data/lib/cisco_node_utils/cmd_ref/upgrade.yaml +38 -0
- data/lib/cisco_node_utils/dhcp_relay_global.rb +6 -2
- data/lib/cisco_node_utils/dns_domain.rb +2 -2
- data/lib/cisco_node_utils/environment.rb +1 -0
- data/lib/cisco_node_utils/interface.rb +58 -0
- data/lib/cisco_node_utils/itd_service.rb +5 -2
- data/lib/cisco_node_utils/node.rb +26 -13
- data/lib/cisco_node_utils/radius_global.rb +6 -1
- data/lib/cisco_node_utils/radius_server.rb +7 -1
- data/lib/cisco_node_utils/route_map.rb +2558 -0
- data/lib/cisco_node_utils/tacacs_global.rb +5 -2
- data/lib/cisco_node_utils/tacacs_server.rb +5 -2
- data/lib/cisco_node_utils/tacacs_server_host.rb +10 -4
- data/lib/cisco_node_utils/upgrade.rb +118 -0
- data/lib/cisco_node_utils/version.rb +1 -1
- data/spec/environment_spec.rb +16 -2
- data/tests/test_bgp_af.rb +8 -1
- data/tests/test_dhcp_relay_global.rb +3 -2
- data/tests/test_evpn_vni.rb +2 -2
- data/tests/test_feature.rb +4 -1
- data/tests/test_interface.rb +93 -0
- data/tests/test_interface_svi.rb +1 -0
- data/tests/test_itd_service.rb +4 -0
- data/tests/test_radius_global.rb +2 -2
- data/tests/test_radius_server.rb +6 -6
- data/tests/test_route_map.rb +1489 -0
- data/tests/test_router_bgp.rb +2 -0
- data/tests/test_snmpcommunity.rb +12 -0
- data/tests/test_snmpserver.rb +1 -1
- data/tests/test_snmpuser.rb +6 -9
- data/tests/test_tacacs_server.rb +2 -2
- data/tests/test_tacacs_server_host.rb +2 -2
- data/tests/test_upgrade.rb +106 -0
- data/tests/test_vlan.rb +2 -4
- data/tests/upgrade_info.yaml.example +3 -0
- data/tests/yum_package.yaml +13 -3
- metadata +9 -2
data/tests/test_router_bgp.rb
CHANGED
@@ -1315,6 +1315,8 @@ class TestRouterBgp < CiscoTestCase
|
|
1315
1315
|
end
|
1316
1316
|
|
1317
1317
|
def test_suppress_fib_pending
|
1318
|
+
skip_legacy_defect?('7.0.3.I4.5',
|
1319
|
+
'CSCvd41536: Unable to remove suppress-fib-pending')
|
1318
1320
|
bgp = setup_default
|
1319
1321
|
if validate_property_excluded?('bgp', 'suppress_fib_pending')
|
1320
1322
|
assert_raises(Cisco::UnsupportedError) do
|
data/tests/test_snmpcommunity.rb
CHANGED
@@ -191,6 +191,18 @@ class TestSnmpCommunity < CiscoTestCase
|
|
191
191
|
cleanup_snmpcommunity(snmpcommunity)
|
192
192
|
end
|
193
193
|
|
194
|
+
def test_get_group_complex_name
|
195
|
+
skip("Test not supported on #{product_tag} due to CSCva63814") if product_tag[/n5|6|7k/]
|
196
|
+
names = ['C0mplex()Community!', 'C#', 'C$', 'C%', 'C^', 'C&', 'C*',
|
197
|
+
'C-', 'C=', 'C<', 'C,', 'C.', 'C/', 'C|', 'C{}[]']
|
198
|
+
group = 'network-admin'
|
199
|
+
names.each do |name|
|
200
|
+
sc = SnmpCommunity.new(name, group)
|
201
|
+
assert_equal(group, sc.group)
|
202
|
+
cleanup_snmpcommunity(sc)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
194
206
|
def test_group_set_zero_length
|
195
207
|
name = 'ciscogroupsetcom'
|
196
208
|
group = 'network-operator'
|
data/tests/test_snmpserver.rb
CHANGED
@@ -155,7 +155,7 @@ class TestSnmpServer < CiscoTestCase
|
|
155
155
|
end
|
156
156
|
|
157
157
|
def test_packet_size
|
158
|
-
skip_legacy_defect?('7.0.3.I2.2e|7.0.3.I3.1',
|
158
|
+
skip_legacy_defect?('7.0.3.I2.2e|7.0.3.I2.5|7.0.3.I3.1',
|
159
159
|
'CSCuz14217: CLI shows default snmp packet-size incorrectly as 0')
|
160
160
|
|
161
161
|
if validate_property_excluded?('snmp_server', 'packet_size')
|
data/tests/test_snmpuser.rb
CHANGED
@@ -564,16 +564,15 @@ class TestSnmpUser < CiscoTestCase
|
|
564
564
|
end
|
565
565
|
|
566
566
|
def test_privpassword
|
567
|
-
name = 'test_privpassword'
|
568
567
|
priv_password = '0x123456'
|
569
|
-
snmpuser = SnmpUser.new(
|
568
|
+
snmpuser = SnmpUser.new('test_pp1', [''], :md5, priv_password,
|
570
569
|
:des, priv_password, true, '')
|
571
570
|
|
572
571
|
pw = snmpuser.priv_password
|
573
572
|
assert_equal(priv_password, pw)
|
574
573
|
snmpuser.destroy
|
575
574
|
|
576
|
-
snmpuser = SnmpUser.new(
|
575
|
+
snmpuser = SnmpUser.new('test_pp2', [''], :md5, priv_password,
|
577
576
|
:aes128, priv_password, true, '')
|
578
577
|
pw = snmpuser.priv_password
|
579
578
|
assert_equal(priv_password, pw)
|
@@ -581,16 +580,15 @@ class TestSnmpUser < CiscoTestCase
|
|
581
580
|
end
|
582
581
|
|
583
582
|
def test_privpassword_with_engineid
|
584
|
-
name = 'test_privpassword2'
|
585
583
|
priv_password = '0x123456'
|
586
584
|
engine_id = '128:12:12:12:12'
|
587
|
-
snmpuser = SnmpUser.new(
|
585
|
+
snmpuser = SnmpUser.new('test_pp3', [''], :md5, priv_password,
|
588
586
|
:des, priv_password, true, engine_id)
|
589
587
|
pw = snmpuser.priv_password
|
590
588
|
assert_equal(priv_password, pw)
|
591
589
|
snmpuser.destroy
|
592
590
|
|
593
|
-
snmpuser = SnmpUser.new(
|
591
|
+
snmpuser = SnmpUser.new('test_pp4', [''], :md5, priv_password,
|
594
592
|
:aes128, priv_password, true, '')
|
595
593
|
pw = snmpuser.priv_password
|
596
594
|
assert_equal(priv_password, pw)
|
@@ -612,17 +610,16 @@ class TestSnmpUser < CiscoTestCase
|
|
612
610
|
end
|
613
611
|
|
614
612
|
def test_priv_password_equal_with_engineid
|
615
|
-
name = 'test_privpass_equal'
|
616
613
|
priv_pass = 'XXWWPass0wrf'
|
617
614
|
engine_id = '128:12:12:12:12'
|
618
615
|
|
619
|
-
snmpuser = SnmpUser.new(
|
616
|
+
snmpuser = SnmpUser.new('test_pp5', [''], :md5, priv_pass, :des, priv_pass, false,
|
620
617
|
engine_id)
|
621
618
|
assert(snmpuser.priv_password_equal?(priv_pass, false))
|
622
619
|
refute(snmpuser.priv_password_equal?('tWWXXpass0wrf', false))
|
623
620
|
snmpuser.destroy
|
624
621
|
|
625
|
-
snmpuser = SnmpUser.new(
|
622
|
+
snmpuser = SnmpUser.new('test_pp6', [''], :md5, priv_pass,
|
626
623
|
:aes128, priv_pass, false, engine_id)
|
627
624
|
assert(snmpuser.priv_password_equal?(priv_pass, false))
|
628
625
|
refute(snmpuser.priv_password_equal?('tWWXXpass0wrf', false))
|
data/tests/test_tacacs_server.rb
CHANGED
@@ -140,7 +140,7 @@ class TestTacacsServer < CiscoTestCase
|
|
140
140
|
tacacs = TacacsServer.new
|
141
141
|
|
142
142
|
if platform == :nexus
|
143
|
-
|
143
|
+
assert_match(/#{sh_run_encryption_password}/,
|
144
144
|
tacacs.encryption_password,
|
145
145
|
'Error: Tacacs Server, encryption password incorrect')
|
146
146
|
elsif platform == :ios_xr
|
@@ -186,7 +186,7 @@ class TestTacacsServer < CiscoTestCase
|
|
186
186
|
encrypted_type = md.to_s.split(' ').last.to_i
|
187
187
|
assert_equal(encrypted_type, tacacs.encryption_type,
|
188
188
|
'Error: Tacacs Server, encryption type incorrect')
|
189
|
-
|
189
|
+
assert_match(/#{encrypted_password}/, tacacs.encryption_password,
|
190
190
|
'Error: Tacacs Server, encryption password incorrect')
|
191
191
|
tacacs.destroy
|
192
192
|
end
|
@@ -299,7 +299,7 @@ class TestTacacsSvrHost < CiscoTestCase
|
|
299
299
|
host.encryption_key_set(0, pass)
|
300
300
|
|
301
301
|
if platform != :ios_xr
|
302
|
-
|
302
|
+
assert_match(/#{sh_run_pass}/, host.encryption_password,
|
303
303
|
'Error: Tacacs Host encryption password incorrect')
|
304
304
|
else
|
305
305
|
# Only do not-nil checking for IOS XR
|
@@ -339,7 +339,7 @@ class TestTacacsSvrHost < CiscoTestCase
|
|
339
339
|
pass_no_quotes = md.captures[1].gsub(/(?:^\")|(?:\"$)/, '')
|
340
340
|
assert_equal(sh_run_pass, pass_no_quotes,
|
341
341
|
'Error: Tacacs Host encryption password mismatch')
|
342
|
-
|
342
|
+
assert_match(/#{sh_run_pass}/, host.encryption_password,
|
343
343
|
'Error: Tacacs Host encryption password incorrect')
|
344
344
|
else
|
345
345
|
# Only do not-nil checking for IOS XR
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# Copyright (c) 2016-2017 Cisco and/or its affiliates.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require_relative 'ciscotest'
|
16
|
+
require_relative '../lib/cisco_node_utils/upgrade'
|
17
|
+
|
18
|
+
include Cisco
|
19
|
+
|
20
|
+
# TestUpgrade - Minitest for router Upgrade node Utility class
|
21
|
+
class TestUpgrade < CiscoTestCase
|
22
|
+
@skip_unless_supported = 'upgrade'
|
23
|
+
|
24
|
+
def preconfig_upgrade_info
|
25
|
+
path = File.expand_path('../upgrade_info.yaml', __FILE__)
|
26
|
+
skip('Cannot find tests/upgrade_info.yaml') unless File.file?(path)
|
27
|
+
info = YAML.load(File.read(path))
|
28
|
+
valid_info?(info)
|
29
|
+
info
|
30
|
+
end
|
31
|
+
|
32
|
+
def valid_info?(info)
|
33
|
+
skip('tests/upgrade_info.yaml file is empty') unless info
|
34
|
+
msg = 'Missing key in tests/upgrade_info.yaml'
|
35
|
+
%w(install_image install_uri).each do |key|
|
36
|
+
skip("#{msg}: #{key}") if info[key].nil?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
###################
|
41
|
+
# Upgrade tests #
|
42
|
+
###################
|
43
|
+
|
44
|
+
def test_clear_status
|
45
|
+
Upgrade.clear_status
|
46
|
+
refute(Upgrade.upgraded?)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_delete
|
50
|
+
config('show version > bootflash:foobar')
|
51
|
+
Upgrade.delete('foobar')
|
52
|
+
assert_raises(CliError) do
|
53
|
+
Upgrade.delete('foobar')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_delete_negative
|
58
|
+
assert_raises(CliError) do
|
59
|
+
# Delete a file that doesn't exist
|
60
|
+
Upgrade.delete('foobar')
|
61
|
+
end
|
62
|
+
assert_raises(CliError) do
|
63
|
+
# Delete a file that doesn't exist
|
64
|
+
Upgrade.delete('foobar', 'logflash:')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# def test_delete_boot
|
69
|
+
# Upgrade.delete_boot
|
70
|
+
# end
|
71
|
+
|
72
|
+
def test_image_version
|
73
|
+
version = Upgrade.image_version
|
74
|
+
assert_match(/^\d.\d\(\d\)\S+\(\S+\)$/, version)
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_box_online
|
78
|
+
assert(Upgrade.box_online?)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_upgrade
|
82
|
+
image_info = preconfig_upgrade_info
|
83
|
+
version = Upgrade.image_version(image_info['install_image'], image_info['install_uri'])
|
84
|
+
Upgrade.upgrade(version, image_info['install_image'], image_info['install_uri'])
|
85
|
+
# Wait 15 seconds for device to start rebooting
|
86
|
+
# TODO : Consider getting the sleep value dynamically
|
87
|
+
sleep 15
|
88
|
+
begin
|
89
|
+
assert(Upgrade.upgraded?)
|
90
|
+
rescue
|
91
|
+
tries ||= 1
|
92
|
+
retry unless (tries += 1) > 5
|
93
|
+
raise
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_upgrade_boot_image
|
98
|
+
preconfig_upgrade_info
|
99
|
+
image_uri = node.config_get('show_version', 'system_image')
|
100
|
+
image = image_uri.split('/')[-1]
|
101
|
+
uri = image_uri.split('/')[0]
|
102
|
+
skip('Boot image not on bootflash:') unless uri == 'bootflash:'
|
103
|
+
Upgrade.upgrade(Upgrade.image_version, image, uri)
|
104
|
+
assert(Upgrade.upgraded?)
|
105
|
+
end
|
106
|
+
end
|
data/tests/test_vlan.rb
CHANGED
@@ -127,6 +127,8 @@ class TestVlan < CiscoTestCase
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def test_name_zero_length
|
130
|
+
skip_legacy_defect?('7.0.3.I5.2',
|
131
|
+
'CSCvd09257: Configuration of vlan name via nxapi should be noop')
|
130
132
|
v = Vlan.new(1000)
|
131
133
|
v.vlan_name = ''
|
132
134
|
assert('', v.vlan_name)
|
@@ -155,10 +157,6 @@ class TestVlan < CiscoTestCase
|
|
155
157
|
name = 'LONG_NAME' + ('E' * 119)
|
156
158
|
v.vlan_name = name
|
157
159
|
assert_equal(name, v.vlan_name)
|
158
|
-
name = 'LONG_NAME' + ('E' * 120)
|
159
|
-
assert_raises(Cisco::CliError) do
|
160
|
-
v.vlan_name = name
|
161
|
-
end
|
162
160
|
v.destroy
|
163
161
|
config 'no system vlan long-name'
|
164
162
|
end
|
data/tests/yum_package.yaml
CHANGED
@@ -13,10 +13,10 @@
|
|
13
13
|
name: 'nxos.sample-n9k_EOR'
|
14
14
|
version: '1.0.0-7.0.3.I2.2e'
|
15
15
|
|
16
|
-
|
17
|
-
filename: 'nxos.sample-n9k_EOR-1.0.0-7.0.3.
|
16
|
+
7_0_3_I2_5_:
|
17
|
+
filename: 'nxos.sample-n9k_EOR-1.0.0-7.0.3.I2.5.lib32_n9000.rpm'
|
18
18
|
name: 'nxos.sample-n9k_EOR'
|
19
|
-
version: '1.0.0-7.0.3.
|
19
|
+
version: '1.0.0-7.0.3.I2.5'
|
20
20
|
|
21
21
|
7_0_3_I4_1_:
|
22
22
|
filename: 'nxos.sample-n9k_EOR-1.0.0-7.0.3.I4.1.lib32_n9000.rpm'
|
@@ -28,11 +28,21 @@
|
|
28
28
|
name: 'nxos.sample-n9k_EOR'
|
29
29
|
version: '1.0.0-7.0.3.I4.2'
|
30
30
|
|
31
|
+
7_0_3_I4_5_:
|
32
|
+
filename: 'nxos.sample-n9k_EOR-1.0.0-7.0.3.I4.5.lib32_n9000.rpm'
|
33
|
+
name: 'nxos.sample-n9k_EOR'
|
34
|
+
version: '1.0.0-7.0.3.I4.5'
|
35
|
+
|
31
36
|
7_0_3_I5_1_:
|
32
37
|
filename: 'nxos.sample-n9k_ALL-1.0.0-7.0.3.I5.1.lib32_n9000.rpm'
|
33
38
|
name: 'nxos.sample-n9k_ALL'
|
34
39
|
version: '1.0.0-7.0.3.I5.1'
|
35
40
|
|
41
|
+
7_0_3_I5_2_:
|
42
|
+
filename: 'nxos.sample-n9k_ALL-1.0.0-7.0.3.I5.2.lib32_n9000.rpm'
|
43
|
+
name: 'nxos.sample-n9k_ALL'
|
44
|
+
version: '1.0.0-7.0.3.I5.2'
|
45
|
+
|
36
46
|
7_0_3_F1_1_:
|
37
47
|
filename: 'nxos.sample-n8k_EOR-1.0.0-7.0.3.F1.1.lib32_nxos.rpm'
|
38
48
|
name: 'nxos.sample-n8k_EOR'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cisco_node_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob Gries
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2017-
|
17
|
+
date: 2017-03-14 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: bundler
|
@@ -232,6 +232,7 @@ files:
|
|
232
232
|
- lib/cisco_node_utils/cmd_ref/radius_global.yaml
|
233
233
|
- lib/cisco_node_utils/cmd_ref/radius_server.yaml
|
234
234
|
- lib/cisco_node_utils/cmd_ref/radius_server_group.yaml
|
235
|
+
- lib/cisco_node_utils/cmd_ref/route_map.yaml
|
235
236
|
- lib/cisco_node_utils/cmd_ref/show_system.yaml
|
236
237
|
- lib/cisco_node_utils/cmd_ref/show_version.yaml
|
237
238
|
- lib/cisco_node_utils/cmd_ref/snmp_community.yaml
|
@@ -248,6 +249,7 @@ files:
|
|
248
249
|
- lib/cisco_node_utils/cmd_ref/tacacs_server.yaml
|
249
250
|
- lib/cisco_node_utils/cmd_ref/tacacs_server_group.yaml
|
250
251
|
- lib/cisco_node_utils/cmd_ref/tacacs_server_host.yaml
|
252
|
+
- lib/cisco_node_utils/cmd_ref/upgrade.yaml
|
251
253
|
- lib/cisco_node_utils/cmd_ref/vdc.yaml
|
252
254
|
- lib/cisco_node_utils/cmd_ref/virtual_service.yaml
|
253
255
|
- lib/cisco_node_utils/cmd_ref/vlan.yaml
|
@@ -298,6 +300,7 @@ files:
|
|
298
300
|
- lib/cisco_node_utils/radius_global.rb
|
299
301
|
- lib/cisco_node_utils/radius_server.rb
|
300
302
|
- lib/cisco_node_utils/radius_server_group.rb
|
303
|
+
- lib/cisco_node_utils/route_map.rb
|
301
304
|
- lib/cisco_node_utils/router_ospf.rb
|
302
305
|
- lib/cisco_node_utils/router_ospf_area.rb
|
303
306
|
- lib/cisco_node_utils/router_ospf_area_vlink.rb
|
@@ -315,6 +318,7 @@ files:
|
|
315
318
|
- lib/cisco_node_utils/tacacs_server.rb
|
316
319
|
- lib/cisco_node_utils/tacacs_server_group.rb
|
317
320
|
- lib/cisco_node_utils/tacacs_server_host.rb
|
321
|
+
- lib/cisco_node_utils/upgrade.rb
|
318
322
|
- lib/cisco_node_utils/vdc.rb
|
319
323
|
- lib/cisco_node_utils/version.rb
|
320
324
|
- lib/cisco_node_utils/vlan.rb
|
@@ -408,6 +412,7 @@ files:
|
|
408
412
|
- tests/test_radius_global.rb
|
409
413
|
- tests/test_radius_server.rb
|
410
414
|
- tests/test_radius_server_group.rb
|
415
|
+
- tests/test_route_map.rb
|
411
416
|
- tests/test_router_bgp.rb
|
412
417
|
- tests/test_router_ospf.rb
|
413
418
|
- tests/test_router_ospf_area.rb
|
@@ -426,6 +431,7 @@ files:
|
|
426
431
|
- tests/test_tacacs_server.rb
|
427
432
|
- tests/test_tacacs_server_group.rb
|
428
433
|
- tests/test_tacacs_server_host.rb
|
434
|
+
- tests/test_upgrade.rb
|
429
435
|
- tests/test_vdc.rb
|
430
436
|
- tests/test_vlan.rb
|
431
437
|
- tests/test_vlan_private.rb
|
@@ -437,6 +443,7 @@ files:
|
|
437
443
|
- tests/test_vxlan_vtep_vni.rb
|
438
444
|
- tests/test_yang.rb
|
439
445
|
- tests/test_yum.rb
|
446
|
+
- tests/upgrade_info.yaml.example
|
440
447
|
- tests/yum_package.yaml
|
441
448
|
homepage: https://github.com/cisco/cisco-network-node-utils
|
442
449
|
licenses:
|