Skip to main content

One of my colleagues told me that some of our devices had licence issues.

output from show licence usage shows the issue easily, so custom command is the way to go

 

SOMEDEVICE# show license usage

Feature                      Ins  Lic   Status Expiry Date Comments

                                 Count

--------------------------------------------------------------------------------

….

NXOS_ESSENTIALS_M4            No    -   Unused             -

   -

FC_PORT_ACTIVATION_PKG        No    0   Unused             -

LAN_ENTERPRISE_SERVICES_PKG   No    -   In use             Honor Start 70D 15H

--------------------------------------------------------------------------------

 

The key part is to extract the features for the device, and check that the No is present, with In Use also present.

This is done via the following function, which determines valid input and detects violation.

blockData =
```
{feature:string} {active:string} {licenceCount:string} {status:string}
```;

customCommand = "show license usage";

getReportCustomCommand(device) =
foreach command in device.outputs.commands
where command.commandText == customCommand
let parsedResponse = parseConfigBlocks(device.platform.os, command.response)
let response = blockMatches(parsedResponse, blockData)


foreach data in response
let feature = data.data.feature
let active = data.data.active
where active in f"Yes", "No"]
let status = data.data.status
let violation = (active == "No" && status == "In")
let violationReason = if violation then join(" ", s"No licence applied for feature", feature]) else ""

select {
deviceName: device.name,
feature: feature,
status: status,
active: active,
violation: violation,
violationReason: violationReason
};

We also have another function that creates an empty report. This is to cover devices where the custom command hasn’t run. It’s often cleaner to determine if the command has run prior to requesting the response in previous function. If you don’t you get no information from the device at all. In our case, any missing information is a violation.

getEmptyReport(device) =
min(foreach x in .0]
select {
deviceName: device.name,
feature: "",
status: "",
active: "",
violation: true,
violationReason: "Custom Command Not Present"
});

We also have a detect function to determine for devices if the command has been run for the current network

export hasCustomCommand(validVendors: List<Vendor>, customCommand: String) =
foreach device in network.devices
where device.platform.vendor in validVendors
foreach command in device.outputs.commands
where command.commandText == customCommand
select device.name;

finally, we put it all together…

In our case, we have Cisco NX-OS as ACI leaves so we filtered those out with the tagNames. I’d be interested if there is another way here or perhaps a feature needs to be requested to allow us to do this without tags.

For reference the show licence usage isn’t valid on NX-OS if it’s in ACI mode, so this filter was to avoid noise in the response.

customCommand = "show license usage";

validVendors = tVendor.CISCO];

validOSs = tOS.NXOS];

foreach x in <0]
let deviceHasCustomCommands = hasCustomCommand(validVendors, customCommand)
foreach device in network.devices
where device.platform.vendor in validVendors && device.platform.os in validOSs && "deviceType:fabric" not in device.tagNames
let response = if device.name in deviceHasCustomCommands
then getReportCustomCommand(device)
else agetEmptyReport(device)]
foreach item in response
select {
device: device.name,
os: device.platform.os,
feature: item.feature,
active: item.active,
status: item.status,
violation: item.violation,
violationReason: item.violationReason
}

 

Be the first to reply!

Reply