From 7933eb7ef68d3bfe170e4cd7afc44a7802c3255e Mon Sep 17 00:00:00 2001 From: Najihel <1873677+Najihel@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:48:32 +0200 Subject: [PATCH 1/5] feat(driver): :sparkles: Versa Networks Flex VNF : Initial version --- .../drivers/Versa-Networks_VOS-FlexVNF.js | 635 ++++++++++++++++++ 1 file changed, 635 insertions(+) create mode 100644 src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js diff --git a/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js b/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js new file mode 100644 index 00000000..a6b24219 --- /dev/null +++ b/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js @@ -0,0 +1,635 @@ +/** + * Copyright 2013-2025 Netshot + * + * This file is part of Netshot project. + * + * Netshot is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Netshot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Netshot. If not, see . + */ + +var Info = { + name: "VersaNetworksFlexVNF", + description: "Versa Networks FlexVNF (VOS)", + author: "Najihel", + version: "1.0" +}; + +// -------------------------------------------------------------------------------------------------- + +var Config = { + "vosVersion": { + type: "Text", + title: "Versa FlexVNF Version", + comparable: true, + searchable: true, + dump: { + pre: "!! VOS version:", + preLine: "!! " + } + }, + "configuration": { + type: "LongText", + title: "Configuration (curly)", + comparable: true, + searchable: true, + checkable: true + }, + "configurationAsSet": { + type: "LongText", + title: "Configuration (set)", + comparable: true, + searchable: true, + checkable: true, + dump: { + pre: "!! Configuration (taken on %when%):", + post: "!! End of configuration" + } + } +}; + +// -------------------------------------------------------------------------------------------------- + +var Device = { + "vosOSPackage": { /* This stores VOS OS Package information. */ + type: "Text", + title: "Versa FlexVNF OS Package Version", + searchable: true, + checkable: true, + }, + "vosSecurityPackage": { /* This stores VOS Security Package information. */ + type: "Text", + title: "Versa FlexVNF Security Package Version", + searchable: true, + checkable: true, + }, + "vosOSSecurityPackage": { /* This stores VOS OS Security Package information. */ + type: "Text", + title: "Versa FlexVNF OS Security Package Version", + searchable: true, + checkable: true, + }, + "hostVersion": { /* This stores the Host Version. */ + type: "Text", + title: "Versa Host OS Version", + searchable: true, + checkable: true, + } +}; + +// -------------------------------------------------------------------------------------------------- + +var CLI = { + ssh: { + macros: { + bash: { + options: [ "bash" ], + target: "bash" + }, + operate: { + options: [ "operate" ], + target: "operate" + }, + configure: { + options: [ "operate" ], + target: "configure" + } + } + }, + username: { + prompt: /^login: $/, + macros: { + auto: { + cmd: "$$NetshotUsername$$", + options: [ "password" ] + } + } + }, + password: { + prompt: /^Password:$/, + macros: { + auto: { + cmd: "$$NetshotPassword$$", + options: [ "bash" ] + } + } + }, + bash: { + prompt: /^(\[[A-Za-z0-9\.\-_]+@[A-Za-z\-_0-9\.]+: ~\] [\$|#] )$/m, + macros: { + operate: { + cmd: "cli", + options: [ "operate" ], + target: "operate" + } + } + }, + operate: { + prompt: /^([A-Za-z0-9\.\-_]+@[A-Za-z\-_0-9\.]+\-cli> )$/m, + error: /^(unknown command|syntax error|error: Unrecognized command)/m, + pager: { + match: /^--More--/, + response: " " + }, + macros: { + configure: { + cmd: "configure", + options: [ "operate", "configure" ], + target: [ "configure" ] + }, + exit: { + cmd: "exit", + options: [ "bash", "operate" ], + target: [ "bash" ] + } + } + }, + configure: { + prompt: /^([A-Za-z0-9\.\-_]+@[A-Za-z\-_0-9\.]+-cli\(config\)% )$/m, + error: /^(unknown command|syntax error|invalid )/m, + clearPrompt: true, + macros: { + exit: { + cmd: "exit", + options: [ "bash", "operate", "configure" ], + target: "operate" + }, + top: { + cmd: "top", + options: [ "configure" ], + target: "configure" + }, + commit: { + cmd: "commit", + options: [ "configure" ], + target: "configure" + } + } + } +}; + +// -------------------------------------------------------------------------------------------------- + +function snapshot(cli, device, config) { + + var configCleanup = function(config) { + // Remove [ok] and empty lines + config = config + .replace(/^\[ok\].*$/gm, '') // lignes [ok] + .replace(/^\s*$/gm, ''); // lignes vides + + var p = config.search(/^[a-z]/m); + if (p > 0) { + config = config.slice(p); + } + + return config; + }; + + //var configCleanup = function(config) { + // var p = config.search(/^[a-z]/m); + // if (p > 0) { + // config = config.slice(p); + // } + // return config; + //}; + + // -------------------------------------------------------------------------------------------------- + + // CleanUp JSON (no thanks Versa...) + + function parseJsonSafe(jsonString) { + const lastBraceIndex = jsonString.lastIndexOf('}'); + let cleanJson = jsonString; + if (lastBraceIndex !== -1) { + cleanJson = jsonString.substring(0, lastBraceIndex + 1); + } + let jsonData; + try { + jsonData = JSON.parse(cleanJson); + } catch (e) { + cli.debug(`ERROR | JSON Error : ${e}`); + jsonData = null; + } + return jsonData; + } + + // -------------------------------------------------------------------------------------------------- + + // Set networkClass of the Device + + //cli.debug(`Set networkClass of the Device`); + device.set("networkClass", "ROUTER"); + + // -------------------------------------------------------------------------------------------------- + + // Initiate bash state + + //cli.debug(`Initiate bash state`); + cli.macro("bash"); + + // -------------------------------------------------------------------------------------------------- + + // Retreive OS version + + //cli.debug(`Retreive OS version via bash`); + var showOSVersion = cli.command("/usr/bin/lsb_release -a"); + var OSVersionLines = showOSVersion.split('\n').filter(line => line.includes(':')); + var OSVersionInfos ={}; + OSVersionLines.forEach(line => { + const [key, value] = line.split(':').map(s => s.trim()); + OSVersionInfos[key] = value; + }); + var hostVersion = `${OSVersionInfos['Description']} (${OSVersionInfos['Codename']})`; + + if (hostVersion) { + device.set("hostVersion", hostVersion); + } + else { + device.set("Unknown Host version", hostVersion); + } + //cli.debug(`hostVersion: ${hostVersion}`); + + // -------------------------------------------------------------------------------------------------- + + // Initiate operate state + + //cli.debug(`Initiate operate state`); + cli.macro("operate"); + + // -------------------------------------------------------------------------------------------------- + + // Retreive + cleanup configuration in curly output + + //cli.debug(`Retreive + cleanup configuration in curly output`); + var configuration = cli.command("show configuration | nomore"); + configuration = configCleanup(configuration); + //configuration = configuration.replace(/^\[ok\].*$/m, '').trim(); + config.set("configuration", configuration); + + // -------------------------------------------------------------------------------------------------- + + // Retreive + cleanup configuration in set output + + //cli.debug(`Retreive + cleanup configuration in set output`); + var configurationAsSet = cli.command("show configuration | display set | nomore"); + configurationAsSet = configCleanup(configurationAsSet); + //configurationAsSet = configurationAsSet.replace(/^\[ok\].*$/m, '').trim(); + config.set("configurationAsSet", configurationAsSet); + + // -------------------------------------------------------------------------------------------------- + + // Retrieve the author and the protocol used for the current configuration + + //cli.debug(`Retrieve the author and the protocol used for the current configuration`); + var latestCommit = cli.command("show commit list 1"); + var latestCommitMatch = latestCommit.match(/^0\s*[0-9]*\s*(\S*)\s*(\S*)\s*([0-9\-\s\:]{19})/m); + if (latestCommitMatch != null) { + var authorUser = latestCommitMatch[1]; + var authorProtocol = latestCommitMatch[2]; + if (authorProtocol != null) { + var author = authorUser + ' via ' + authorProtocol; + } + else { + var author = authorUser; + } + if (author != null) { + config.set("author", author); + } + } + //cli.debug(`author: ${author}`); + + // -------------------------------------------------------------------------------------------------- + + // Retrieve HostName + + //cli.debug(`Retrieve HostName`); + var showHostname = cli.command("show configuration system identification name | display set"); + var hostname = showHostname.match(/^set system identification name (\S*)$/m); + if (hostname != null) { + device.set("name", hostname[1]); + //cli.debug(`hostname: ${hostname[1]}`); + } + else { + device.set("name", "versa-flexvnf"); + //cli.debug(`hostname: Not Defined !`); + } + + // -------------------------------------------------------------------------------------------------- + + // Retrieve vosVersion, vosOSPackage + + var showPackageInfoJSON = cli.command("show system package-info | display json | nomore"); + const jsonPackageInfo = parseJsonSafe(showPackageInfoJSON); + + if (jsonPackageInfo) { + const packageInfo = jsonPackageInfo?.data?.["system:system"]?.["package-info"]?.[0] || {}; + + const packageBranch = packageInfo["branch"] || ""; + const packageRelType = packageInfo["reltype"] || ""; + const packageId = packageInfo["package-id"] || "Unknown"; + const packageDate = packageInfo["date"] || ""; + //const packageName = packageInfo["package-name"] || "Unknown"; + //const packageMajor = packageInfo["major"] ?? ""; + //const packageMinor = packageInfo["minor"] ?? ""; + //const packageService = packageInfo["service"] ?? ""; + //const osVersion = packageInfo["os_version"] || ""; + + // -------------------------------------------------------------------------------------------------- + + // vosVersion + + const vosVersion = `Versa FlexVNF software ${packageBranch} ${packageRelType}`.trim(); + + if (vosVersion && !vosVersion.includes("undefined")) { + config.set("vosVersion", vosVersion); + device.set("softwareVersion", vosVersion); + } else { + config.set("vosVersion", "Unknown version"); + device.set("softwareVersion", "Unknown version"); + } + // cli.debug(`vosVersion: ${vosVersion}`); + + // -------------------------------------------------------------------------------------------------- + + // vosVersion + + const vosOSPackage = `ID ${packageId} - Date ${packageDate}`.trim(); + + if (vosOSPackage && !vosOSPackage.includes("undefined")) { + device.set("vosOSPackage", vosOSPackage); + } else { + device.set("vosOSPackage", "Unknown package version"); + } + // cli.debug(`vosOSPackage: ${vosOSPackage}`); + + } else { + config.set("vosVersion", "Unknown version"); + device.set("softwareVersion", "Unknown version"); + device.set("vosOSPackage", "Unknown package version"); + } + +// -------------------------------------------------------------------------------------------------- + + // Retrieve Manufacturer, SKU, SerialNumber, vosOSSecurityPackage, vosOSSecurityPackage, etc. of the Device + + var showSystemDetailsJSON = cli.command("show system details | display json | nomore"); + const jsonSystemDetails = parseJsonSafe(showSystemDetailsJSON); + + if (jsonSystemDetails) { + const systemDetails = jsonSystemDetails?.data?.["system:system"]?.details?.[0] || {}; + + // -------------------------------------------------------------------------------------------------- + + // Device Family + + const systemHypervisorType = systemDetails["hypervisor"] || "unknown"; + // cli.debug(`systemHypervisorType: ${systemHypervisorType}`); + + let family; + + if (systemHypervisorType === "baremetal") { + family = "BareMetal"; + } else if (["vmware", "kvm"].includes(systemHypervisorType.toLowerCase())) { + family = "VirtualMachine"; + } else { + family = "Versa FlexVNF generic device"; + } + + device.set("family", family); + // cli.debug(`family: ${family}`); + + // -------------------------------------------------------------------------------------------------- + + // vosOSSecurityPackage and vosOSSecurityPackage + + const spackArray = Array.isArray(systemDetails["spack-info"]) ? systemDetails["spack-info"] : []; + const ossArray = Array.isArray(systemDetails["osspack-info"]) ? systemDetails["osspack-info"] : []; + + var vosSecurityPackage = spackArray + .map(s => `Version ${s.version} - API ${s["api-version"]} - Flavour ${s.flavor} - Update type ${s["update-type"]}`) + .join(", "); + + var vosOSSecurityPackage = ""; + + if (ossArray.length > 0) { + const notInstalled = ossArray.some(o => o.version === "OSSPACK Not Installed"); + + if (notInstalled) { + vosOSSecurityPackage = "OSSPACK Not Installed"; + } else { + vosOSSecurityPackage = ossArray + .map(o => `Version ${o.version} - Update type ${o["update-type"]}`) + .join(", "); + } + } + + device.set("vosSecurityPackage", vosSecurityPackage || "Unknown"); + device.set("vosOSSecurityPackage", vosOSSecurityPackage || "Unknown"); + // cli.debug(`vosSecurityPackage: ${vosSecurityPackage}`); + // cli.debug(`vosOSSecurityPackage: ${vosOSSecurityPackage}`); + + // -------------------------------------------------------------------------------------------------- + + // Serial number, Manufacturer, SKU + + const serialNumber = systemDetails["hw-serial"] || ""; + const systemDetailsManufacturer = systemDetails["manufacturer"] || ""; + const systemDetailsSKU = systemDetails["sku"] || ""; + + if (serialNumber) { + device.set("serialNumber", serialNumber); + } else { + device.set("serialNumber", "Unknown"); + } + //cli.debug(`serialNumber: ${serialNumber}`); + //cli.debug(`systemDetailsManufacturer: ${systemDetailsManufacturer}`); + //cli.debug(`systemDetailsSKU: ${systemDetailsSKU}`); + + if (systemDetailsManufacturer && systemDetailsSKU && serialNumber) { + const module = { + slot: "Chassis", + partNumber: `${systemDetailsManufacturer} ${systemDetailsSKU}`, + serialNumber: serialNumber + }; + device.add("module", module); + } + } + + // -------------------------------------------------------------------------------------------------- + + // Retrieve SNMP Information + + //cli.debug(`Retrieve SNMP Information`); + var snmpConfig = cli.findSections(configuration, /^snmp /m); + if (snmpConfig.length > 0) { + var location = snmpConfig[0].config.match(/^ *location ("(.+)"|(.+));/m); + if (location) { + device.set("location", location[2] || location[3]); + } + else { + device.set("location", ""); + } + //cli.debug(`location: ${location}`); + var contact = snmpConfig[0].config.match(/^ *contact ("(.+)"|(.+));/m); + if (contact) { + device.set("contact", contact[2] || contact[3]); + } + else { + device.set("contact", ""); + } + //cli.debug(`contact: ${contact}`); + } + + // -------------------------------------------------------------------------------------------------- + + // Retrieve Interfaces + + //cli.debug(`Retrieve Interfaces`); + var showInterfacesBrief = cli.command("show interfaces brief | display json | nomore"); + var showInterfacesDetail = cli.command("show interfaces detail | display json | nomore"); + + const jsonDataBrief = parseJsonSafe(showInterfacesBrief); + const jsonDataDetail = parseJsonSafe(showInterfacesDetail); + + if (jsonDataBrief && jsonDataDetail) { + + const briefIfaces = jsonDataBrief?.data?.["interfaces:interfaces"]?.brief || []; + const detailIfaces = jsonDataDetail?.data?.["interfaces:interfaces"]?.detail || []; + + const detailMap = {}; + detailIfaces.forEach(d => { + if (d.name) detailMap[d.name] = d; + }); + + const networkInterfaces = briefIfaces.map(iface => { + const ifaceObj = {}; + + // -------------------------------------------------------------------------------------------------- + + // Interface Name + + if (iface.name) { + ifaceObj.name = iface.name; + ifaceObj.level3 = false; + //cli.debug(`Parsing networkInterfaces ${ifaceObj.name}`); + } + + // -------------------------------------------------------------------------------------------------- + + // Interface Administrative Status + + if (typeof iface["if-admin-status"] !== "undefined") { + ifaceObj.enabled = iface["if-admin-status"] === "up"; + //cli.debug(`Parsing networkInterfaces ${ifaceObj.name} enabled: ${ifaceObj.enabled}`); + } + + // -------------------------------------------------------------------------------------------------- + + // Interface MAC Address + + if (typeof iface.mac === "string") { + const macClean = iface.mac.trim().toLowerCase(); + if (macClean && macClean !== "n/a") { + ifaceObj.mac = iface.mac.trim(); + //cli.debug(`Parsing networkInterfaces ${ifaceObj.name} mac: ${ifaceObj.mac}`); + } + } + // -------------------------------------------------------------------------------------------------- + + // Interface VRF + + if (iface.vrf) { + ifaceObj.vrf = iface.vrf; + //cli.debug(`Parsing networkInterfaces ${ifaceObj.name} vrf: ${ifaceObj.vrf}`); + } + + // -------------------------------------------------------------------------------------------------- + + // Interface Description and Host Interface mapping + + const detail = detailMap[iface.name]; + if (detail) { + if (detail["host-inf"] && detail["host-inf"].toLowerCase() !== "n/a") { + ifaceObj.virtualDevice = detail["host-inf"]; + //cli.debug(`Parsing networkInterfaces ${ifaceObj.name} virtualDevice: ${ifaceObj.virtualDevice}`); + } + if (detail["intf-descr"]) { + ifaceObj.description = detail["intf-descr"]; + //cli.debug(`Parsing networkInterfaces ${ifaceObj.name} description: ${ifaceObj.description}`); + } + } + + // Interface IP / IPv6 + if (Array.isArray(iface.address) && iface.address.length > 0) { + ifaceObj.level3 = true; + //cli.debug(`Parsing networkInterfaces ${ifaceObj.name} level3: ${ifaceObj.level3}`); + + ifaceObj.ip = []; + + let ipv4Index = 0; + let ipv6Index = 0; + + iface.address + .filter(addr => addr.ip) + .forEach(addr => { + const [addrValue, maskStr] = String(addr.ip).split("/"); + const mask = Number(maskStr); + const isIPv6 = addrValue.includes(":"); + + if (isIPv6) { + ifaceObj.ip.push({ + ipv6: addrValue, + mask: mask, + usage: ipv6Index === 0 ? "PRIMARY" : "SECONDARY" + }); + ipv6Index++; + } else { + ifaceObj.ip.push({ + ip: addrValue, + mask: mask, + usage: ipv4Index === 0 ? "PRIMARY" : "SECONDARY" + }); + ipv4Index++; + } + }); + } + + //cli.debug(`Sending interface ${ifaceObj.name} JSON:\n${JSON.stringify(ifaceObj, null, 2)}`); + return ifaceObj; + }); + + if (networkInterfaces.length) { + for (const netIf of networkInterfaces) { + device.add("networkInterface", netIf); + } + } else { + cli.debug(`ERROR | No network interfaces detected !`); + } + } + +}; + +function analyzeSyslog(message) { + //Maybe later + return false; +}; + +function analyzeTrap(trap, debug) { + //Maybe later + return false; +}; + +function snmpAutoDiscover(sysObjectID, sysDesc) { + return sysObjectID.startsWith("1.3.6.1.4.1.42359.2.2.") && + sysDesc.match(/Versa Appliance/); +}; From f7269c1a78b0d4423451d3a75af5fa9b049d9807 Mon Sep 17 00:00:00 2001 From: Najihel <1873677+Najihel@users.noreply.github.com> Date: Thu, 19 Mar 2026 10:41:23 +0100 Subject: [PATCH 2/5] fix(driver): :adhesive_bandage: Versa Networks Flex VNF - CleanUp useless comments --- .../drivers/Versa-Networks_VOS-FlexVNF.js | 47 ------------------- 1 file changed, 47 deletions(-) diff --git a/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js b/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js index a6b24219..1ee08240 100644 --- a/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js +++ b/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js @@ -195,14 +195,6 @@ function snapshot(cli, device, config) { return config; }; - //var configCleanup = function(config) { - // var p = config.search(/^[a-z]/m); - // if (p > 0) { - // config = config.slice(p); - // } - // return config; - //}; - // -------------------------------------------------------------------------------------------------- // CleanUp JSON (no thanks Versa...) @@ -226,22 +218,16 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Set networkClass of the Device - - //cli.debug(`Set networkClass of the Device`); device.set("networkClass", "ROUTER"); // -------------------------------------------------------------------------------------------------- // Initiate bash state - - //cli.debug(`Initiate bash state`); cli.macro("bash"); // -------------------------------------------------------------------------------------------------- // Retreive OS version - - //cli.debug(`Retreive OS version via bash`); var showOSVersion = cli.command("/usr/bin/lsb_release -a"); var OSVersionLines = showOSVersion.split('\n').filter(line => line.includes(':')); var OSVersionInfos ={}; @@ -257,20 +243,15 @@ function snapshot(cli, device, config) { else { device.set("Unknown Host version", hostVersion); } - //cli.debug(`hostVersion: ${hostVersion}`); // -------------------------------------------------------------------------------------------------- // Initiate operate state - - //cli.debug(`Initiate operate state`); cli.macro("operate"); // -------------------------------------------------------------------------------------------------- // Retreive + cleanup configuration in curly output - - //cli.debug(`Retreive + cleanup configuration in curly output`); var configuration = cli.command("show configuration | nomore"); configuration = configCleanup(configuration); //configuration = configuration.replace(/^\[ok\].*$/m, '').trim(); @@ -279,8 +260,6 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Retreive + cleanup configuration in set output - - //cli.debug(`Retreive + cleanup configuration in set output`); var configurationAsSet = cli.command("show configuration | display set | nomore"); configurationAsSet = configCleanup(configurationAsSet); //configurationAsSet = configurationAsSet.replace(/^\[ok\].*$/m, '').trim(); @@ -289,8 +268,6 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Retrieve the author and the protocol used for the current configuration - - //cli.debug(`Retrieve the author and the protocol used for the current configuration`); var latestCommit = cli.command("show commit list 1"); var latestCommitMatch = latestCommit.match(/^0\s*[0-9]*\s*(\S*)\s*(\S*)\s*([0-9\-\s\:]{19})/m); if (latestCommitMatch != null) { @@ -306,28 +283,22 @@ function snapshot(cli, device, config) { config.set("author", author); } } - //cli.debug(`author: ${author}`); // -------------------------------------------------------------------------------------------------- // Retrieve HostName - - //cli.debug(`Retrieve HostName`); var showHostname = cli.command("show configuration system identification name | display set"); var hostname = showHostname.match(/^set system identification name (\S*)$/m); if (hostname != null) { device.set("name", hostname[1]); - //cli.debug(`hostname: ${hostname[1]}`); } else { device.set("name", "versa-flexvnf"); - //cli.debug(`hostname: Not Defined !`); } // -------------------------------------------------------------------------------------------------- // Retrieve vosVersion, vosOSPackage - var showPackageInfoJSON = cli.command("show system package-info | display json | nomore"); const jsonPackageInfo = parseJsonSafe(showPackageInfoJSON); @@ -441,7 +412,6 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Serial number, Manufacturer, SKU - const serialNumber = systemDetails["hw-serial"] || ""; const systemDetailsManufacturer = systemDetails["manufacturer"] || ""; const systemDetailsSKU = systemDetails["sku"] || ""; @@ -451,9 +421,6 @@ function snapshot(cli, device, config) { } else { device.set("serialNumber", "Unknown"); } - //cli.debug(`serialNumber: ${serialNumber}`); - //cli.debug(`systemDetailsManufacturer: ${systemDetailsManufacturer}`); - //cli.debug(`systemDetailsSKU: ${systemDetailsSKU}`); if (systemDetailsManufacturer && systemDetailsSKU && serialNumber) { const module = { @@ -468,8 +435,6 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Retrieve SNMP Information - - //cli.debug(`Retrieve SNMP Information`); var snmpConfig = cli.findSections(configuration, /^snmp /m); if (snmpConfig.length > 0) { var location = snmpConfig[0].config.match(/^ *location ("(.+)"|(.+));/m); @@ -479,7 +444,6 @@ function snapshot(cli, device, config) { else { device.set("location", ""); } - //cli.debug(`location: ${location}`); var contact = snmpConfig[0].config.match(/^ *contact ("(.+)"|(.+));/m); if (contact) { device.set("contact", contact[2] || contact[3]); @@ -487,14 +451,11 @@ function snapshot(cli, device, config) { else { device.set("contact", ""); } - //cli.debug(`contact: ${contact}`); } // -------------------------------------------------------------------------------------------------- // Retrieve Interfaces - - //cli.debug(`Retrieve Interfaces`); var showInterfacesBrief = cli.command("show interfaces brief | display json | nomore"); var showInterfacesDetail = cli.command("show interfaces detail | display json | nomore"); @@ -521,7 +482,6 @@ function snapshot(cli, device, config) { if (iface.name) { ifaceObj.name = iface.name; ifaceObj.level3 = false; - //cli.debug(`Parsing networkInterfaces ${ifaceObj.name}`); } // -------------------------------------------------------------------------------------------------- @@ -530,7 +490,6 @@ function snapshot(cli, device, config) { if (typeof iface["if-admin-status"] !== "undefined") { ifaceObj.enabled = iface["if-admin-status"] === "up"; - //cli.debug(`Parsing networkInterfaces ${ifaceObj.name} enabled: ${ifaceObj.enabled}`); } // -------------------------------------------------------------------------------------------------- @@ -541,7 +500,6 @@ function snapshot(cli, device, config) { const macClean = iface.mac.trim().toLowerCase(); if (macClean && macClean !== "n/a") { ifaceObj.mac = iface.mac.trim(); - //cli.debug(`Parsing networkInterfaces ${ifaceObj.name} mac: ${ifaceObj.mac}`); } } // -------------------------------------------------------------------------------------------------- @@ -550,7 +508,6 @@ function snapshot(cli, device, config) { if (iface.vrf) { ifaceObj.vrf = iface.vrf; - //cli.debug(`Parsing networkInterfaces ${ifaceObj.name} vrf: ${ifaceObj.vrf}`); } // -------------------------------------------------------------------------------------------------- @@ -561,18 +518,15 @@ function snapshot(cli, device, config) { if (detail) { if (detail["host-inf"] && detail["host-inf"].toLowerCase() !== "n/a") { ifaceObj.virtualDevice = detail["host-inf"]; - //cli.debug(`Parsing networkInterfaces ${ifaceObj.name} virtualDevice: ${ifaceObj.virtualDevice}`); } if (detail["intf-descr"]) { ifaceObj.description = detail["intf-descr"]; - //cli.debug(`Parsing networkInterfaces ${ifaceObj.name} description: ${ifaceObj.description}`); } } // Interface IP / IPv6 if (Array.isArray(iface.address) && iface.address.length > 0) { ifaceObj.level3 = true; - //cli.debug(`Parsing networkInterfaces ${ifaceObj.name} level3: ${ifaceObj.level3}`); ifaceObj.ip = []; @@ -604,7 +558,6 @@ function snapshot(cli, device, config) { }); } - //cli.debug(`Sending interface ${ifaceObj.name} JSON:\n${JSON.stringify(ifaceObj, null, 2)}`); return ifaceObj; }); From 908db08fe3cef0e4977685b6e09a5880307330dc Mon Sep 17 00:00:00 2001 From: Najihel <1873677+Najihel@users.noreply.github.com> Date: Thu, 19 Mar 2026 14:12:36 +0100 Subject: [PATCH 3/5] fix(driver): :adhesive_bandage: Versa Networks Flex VNF - CleanUp useless comments + ES6 compliance --- .../drivers/Versa-Networks_VOS-FlexVNF.js | 101 ++++++------------ 1 file changed, 33 insertions(+), 68 deletions(-) diff --git a/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js b/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js index 1ee08240..d9516fd9 100644 --- a/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js +++ b/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js @@ -17,7 +17,7 @@ * along with Netshot. If not, see . */ -var Info = { +const Info = { name: "VersaNetworksFlexVNF", description: "Versa Networks FlexVNF (VOS)", author: "Najihel", @@ -26,7 +26,7 @@ var Info = { // -------------------------------------------------------------------------------------------------- -var Config = { +const Config = { "vosVersion": { type: "Text", title: "Versa FlexVNF Version", @@ -59,7 +59,7 @@ var Config = { // -------------------------------------------------------------------------------------------------- -var Device = { +const Device = { "vosOSPackage": { /* This stores VOS OS Package information. */ type: "Text", title: "Versa FlexVNF OS Package Version", @@ -88,7 +88,7 @@ var Device = { // -------------------------------------------------------------------------------------------------- -var CLI = { +const CLI = { ssh: { macros: { bash: { @@ -181,24 +181,16 @@ var CLI = { function snapshot(cli, device, config) { - var configCleanup = function(config) { + const configCleanup = function(text) { // Remove [ok] and empty lines - config = config - .replace(/^\[ok\].*$/gm, '') // lignes [ok] - .replace(/^\s*$/gm, ''); // lignes vides - - var p = config.search(/^[a-z]/m); - if (p > 0) { - config = config.slice(p); - } - - return config; + return text + .replace(/^\[ok\].*$/gm, '') + .replace(/^\s*$/gm, ''); }; // -------------------------------------------------------------------------------------------------- // CleanUp JSON (no thanks Versa...) - function parseJsonSafe(jsonString) { const lastBraceIndex = jsonString.lastIndexOf('}'); let cleanJson = jsonString; @@ -228,14 +220,14 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Retreive OS version - var showOSVersion = cli.command("/usr/bin/lsb_release -a"); - var OSVersionLines = showOSVersion.split('\n').filter(line => line.includes(':')); - var OSVersionInfos ={}; + const showOSVersion = cli.command("/usr/bin/lsb_release -a"); + const OSVersionLines = showOSVersion.split('\n').filter(line => line.includes(':')); + const OSVersionInfos ={}; OSVersionLines.forEach(line => { const [key, value] = line.split(':').map(s => s.trim()); OSVersionInfos[key] = value; }); - var hostVersion = `${OSVersionInfos['Description']} (${OSVersionInfos['Codename']})`; + const hostVersion = `${OSVersionInfos['Description']} (${OSVersionInfos['Codename']})`; if (hostVersion) { device.set("hostVersion", hostVersion); @@ -252,33 +244,28 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Retreive + cleanup configuration in curly output - var configuration = cli.command("show configuration | nomore"); + let configuration = cli.command("show configuration | nomore"); configuration = configCleanup(configuration); - //configuration = configuration.replace(/^\[ok\].*$/m, '').trim(); config.set("configuration", configuration); // -------------------------------------------------------------------------------------------------- // Retreive + cleanup configuration in set output - var configurationAsSet = cli.command("show configuration | display set | nomore"); + let configurationAsSet = cli.command("show configuration | display set | nomore"); configurationAsSet = configCleanup(configurationAsSet); - //configurationAsSet = configurationAsSet.replace(/^\[ok\].*$/m, '').trim(); config.set("configurationAsSet", configurationAsSet); // -------------------------------------------------------------------------------------------------- // Retrieve the author and the protocol used for the current configuration - var latestCommit = cli.command("show commit list 1"); - var latestCommitMatch = latestCommit.match(/^0\s*[0-9]*\s*(\S*)\s*(\S*)\s*([0-9\-\s\:]{19})/m); + const latestCommit = cli.command("show commit list 1"); + const latestCommitMatch = latestCommit.match(/^0\s*[0-9]*\s*(\S*)\s*(\S*)\s*([0-9\-\s\:]{19})/m); if (latestCommitMatch != null) { - var authorUser = latestCommitMatch[1]; - var authorProtocol = latestCommitMatch[2]; - if (authorProtocol != null) { - var author = authorUser + ' via ' + authorProtocol; - } - else { - var author = authorUser; - } + const authorUser = latestCommitMatch[1]; + const authorProtocol = latestCommitMatch[2]; + const author = authorProtocol != null + ? authorUser + ' via ' + authorProtocol + : authorUser; if (author != null) { config.set("author", author); } @@ -287,8 +274,8 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Retrieve HostName - var showHostname = cli.command("show configuration system identification name | display set"); - var hostname = showHostname.match(/^set system identification name (\S*)$/m); + const showHostname = cli.command("show configuration system identification name | display set"); + const hostname = showHostname.match(/^set system identification name (\S*)$/m); if (hostname != null) { device.set("name", hostname[1]); } @@ -299,7 +286,7 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Retrieve vosVersion, vosOSPackage - var showPackageInfoJSON = cli.command("show system package-info | display json | nomore"); + const showPackageInfoJSON = cli.command("show system package-info | display json | nomore"); const jsonPackageInfo = parseJsonSafe(showPackageInfoJSON); if (jsonPackageInfo) { @@ -309,16 +296,10 @@ function snapshot(cli, device, config) { const packageRelType = packageInfo["reltype"] || ""; const packageId = packageInfo["package-id"] || "Unknown"; const packageDate = packageInfo["date"] || ""; - //const packageName = packageInfo["package-name"] || "Unknown"; - //const packageMajor = packageInfo["major"] ?? ""; - //const packageMinor = packageInfo["minor"] ?? ""; - //const packageService = packageInfo["service"] ?? ""; - //const osVersion = packageInfo["os_version"] || ""; // -------------------------------------------------------------------------------------------------- // vosVersion - const vosVersion = `Versa FlexVNF software ${packageBranch} ${packageRelType}`.trim(); if (vosVersion && !vosVersion.includes("undefined")) { @@ -328,12 +309,10 @@ function snapshot(cli, device, config) { config.set("vosVersion", "Unknown version"); device.set("softwareVersion", "Unknown version"); } - // cli.debug(`vosVersion: ${vosVersion}`); // -------------------------------------------------------------------------------------------------- - // vosVersion - + // vosOSPackage const vosOSPackage = `ID ${packageId} - Date ${packageDate}`.trim(); if (vosOSPackage && !vosOSPackage.includes("undefined")) { @@ -341,7 +320,6 @@ function snapshot(cli, device, config) { } else { device.set("vosOSPackage", "Unknown package version"); } - // cli.debug(`vosOSPackage: ${vosOSPackage}`); } else { config.set("vosVersion", "Unknown version"); @@ -352,8 +330,7 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Retrieve Manufacturer, SKU, SerialNumber, vosOSSecurityPackage, vosOSSecurityPackage, etc. of the Device - - var showSystemDetailsJSON = cli.command("show system details | display json | nomore"); + const showSystemDetailsJSON = cli.command("show system details | display json | nomore"); const jsonSystemDetails = parseJsonSafe(showSystemDetailsJSON); if (jsonSystemDetails) { @@ -362,10 +339,7 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Device Family - const systemHypervisorType = systemDetails["hypervisor"] || "unknown"; - // cli.debug(`systemHypervisorType: ${systemHypervisorType}`); - let family; if (systemHypervisorType === "baremetal") { @@ -377,20 +351,18 @@ function snapshot(cli, device, config) { } device.set("family", family); - // cli.debug(`family: ${family}`); // -------------------------------------------------------------------------------------------------- // vosOSSecurityPackage and vosOSSecurityPackage - const spackArray = Array.isArray(systemDetails["spack-info"]) ? systemDetails["spack-info"] : []; const ossArray = Array.isArray(systemDetails["osspack-info"]) ? systemDetails["osspack-info"] : []; - var vosSecurityPackage = spackArray + const vosSecurityPackage = spackArray .map(s => `Version ${s.version} - API ${s["api-version"]} - Flavour ${s.flavor} - Update type ${s["update-type"]}`) .join(", "); - var vosOSSecurityPackage = ""; + let vosOSSecurityPackage = ""; if (ossArray.length > 0) { const notInstalled = ossArray.some(o => o.version === "OSSPACK Not Installed"); @@ -406,8 +378,6 @@ function snapshot(cli, device, config) { device.set("vosSecurityPackage", vosSecurityPackage || "Unknown"); device.set("vosOSSecurityPackage", vosOSSecurityPackage || "Unknown"); - // cli.debug(`vosSecurityPackage: ${vosSecurityPackage}`); - // cli.debug(`vosOSSecurityPackage: ${vosOSSecurityPackage}`); // -------------------------------------------------------------------------------------------------- @@ -435,16 +405,16 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Retrieve SNMP Information - var snmpConfig = cli.findSections(configuration, /^snmp /m); + const snmpConfig = cli.findSections(configuration, /^snmp /m); if (snmpConfig.length > 0) { - var location = snmpConfig[0].config.match(/^ *location ("(.+)"|(.+));/m); + const location = snmpConfig[0].config.match(/^ *location ("(.+)"|(.+));/m); if (location) { device.set("location", location[2] || location[3]); } else { device.set("location", ""); } - var contact = snmpConfig[0].config.match(/^ *contact ("(.+)"|(.+));/m); + const contact = snmpConfig[0].config.match(/^ *contact ("(.+)"|(.+));/m); if (contact) { device.set("contact", contact[2] || contact[3]); } @@ -456,8 +426,8 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Retrieve Interfaces - var showInterfacesBrief = cli.command("show interfaces brief | display json | nomore"); - var showInterfacesDetail = cli.command("show interfaces detail | display json | nomore"); + const showInterfacesBrief = cli.command("show interfaces brief | display json | nomore"); + const showInterfacesDetail = cli.command("show interfaces detail | display json | nomore"); const jsonDataBrief = parseJsonSafe(showInterfacesBrief); const jsonDataDetail = parseJsonSafe(showInterfacesDetail); @@ -478,7 +448,6 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Interface Name - if (iface.name) { ifaceObj.name = iface.name; ifaceObj.level3 = false; @@ -487,7 +456,6 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Interface Administrative Status - if (typeof iface["if-admin-status"] !== "undefined") { ifaceObj.enabled = iface["if-admin-status"] === "up"; } @@ -495,7 +463,6 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Interface MAC Address - if (typeof iface.mac === "string") { const macClean = iface.mac.trim().toLowerCase(); if (macClean && macClean !== "n/a") { @@ -505,7 +472,6 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Interface VRF - if (iface.vrf) { ifaceObj.vrf = iface.vrf; } @@ -513,7 +479,6 @@ function snapshot(cli, device, config) { // -------------------------------------------------------------------------------------------------- // Interface Description and Host Interface mapping - const detail = detailMap[iface.name]; if (detail) { if (detail["host-inf"] && detail["host-inf"].toLowerCase() !== "n/a") { From 5b7aaa1f60b67d6b81d2f7b801f96d97c980f63a Mon Sep 17 00:00:00 2001 From: Najihel <1873677+Najihel@users.noreply.github.com> Date: Thu, 19 Mar 2026 14:19:33 +0100 Subject: [PATCH 4/5] fix(driver): :adhesive_bandage: Versa Networks Flex VNF - SonarCloud compliance --- src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js b/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js index d9516fd9..50d30935 100644 --- a/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js +++ b/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js @@ -259,7 +259,7 @@ function snapshot(cli, device, config) { // Retrieve the author and the protocol used for the current configuration const latestCommit = cli.command("show commit list 1"); - const latestCommitMatch = latestCommit.match(/^0\s*[0-9]*\s*(\S*)\s*(\S*)\s*([0-9\-\s\:]{19})/m); + const latestCommitMatch = latestCommit.match(/^0\s*[0-9]*\s*(\S+)\s+(\S+)\s+(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/m); if (latestCommitMatch != null) { const authorUser = latestCommitMatch[1]; const authorProtocol = latestCommitMatch[2]; From 2764cd046a31280d079534af4bff20bfbe2610d1 Mon Sep 17 00:00:00 2001 From: Najihel <1873677+Najihel@users.noreply.github.com> Date: Thu, 19 Mar 2026 14:28:54 +0100 Subject: [PATCH 5/5] fix(driver): :adhesive_bandage: Versa Networks Flex VNF - SonarCloud compliance for latestCommit --- .../drivers/Versa-Networks_VOS-FlexVNF.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js b/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js index 50d30935..7006feb2 100644 --- a/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js +++ b/src/main/resources/drivers/Versa-Networks_VOS-FlexVNF.js @@ -259,14 +259,15 @@ function snapshot(cli, device, config) { // Retrieve the author and the protocol used for the current configuration const latestCommit = cli.command("show commit list 1"); - const latestCommitMatch = latestCommit.match(/^0\s*[0-9]*\s*(\S+)\s+(\S+)\s+(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/m); - if (latestCommitMatch != null) { - const authorUser = latestCommitMatch[1]; - const authorProtocol = latestCommitMatch[2]; - const author = authorProtocol != null - ? authorUser + ' via ' + authorProtocol - : authorUser; - if (author != null) { + const latestCommitLine = latestCommit.split('\n').find(line => line.trimStart().startsWith('0')); + if (latestCommitLine != null) { + const tokens = latestCommitLine.trim().split(/\s+/); + if (tokens.length >= 4) { + const authorUser = tokens[2]; + const authorProtocol = tokens[3]; + const author = authorProtocol != null + ? authorUser + ' via ' + authorProtocol + : authorUser; config.set("author", author); } }