Skip to content

Commit af6f8d5

Browse files
Added Intersight and Hyperflex sourcetypes for licensing
1 parent 038e3a7 commit af6f8d5

File tree

5 files changed

+116
-22
lines changed

5 files changed

+116
-22
lines changed

README.md

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ An HTTP proxy server may be configured for the Add-on by clicking on Configurati
6262
- Proxy Type : Only `http` type is supported. Selecting `socks4` or `socks5` will cause all of the Inputs to fail.
6363
- Host : FQDN or IP address of the HTTP proxy server.
6464
- Port : TCP port number of the proxy service.
65-
- Username : Username for proxy servers that require Basic Authenitcation.
65+
- Username : Username for proxy servers that require Basic Authentication.
6666
- Password : Password for proxy servers that require Basic Authentication.
6767
- Remote DNS resolution : This option is not used and it's state doesn't matter.
6868

@@ -85,12 +85,15 @@ These inventory options are enabled via the multi-select in the input configurat
8585
| Compute | [compute/PhysicalSummaries][4] | cisco:intersight:computePhysicalSummaries |
8686
| Compute | [cond/HclStatuses][9] | cisco:intersight:condHclStatuses |
8787
| Contract | [asset/DeviceContractStatusInformations][10] | cisco:intersight:assetDeviceContractInformations |
88-
| Hyperflex | [hyperflex/Clusters][5] | cisco:intersight:hyperflexClusters |
89-
| Hyperflex | [hyperflex/Nodes][8] | cisco:intersight:hyperflexNodes |
90-
| Hyperflex | [hyperflex/StorageContainers][16] | cisco:intersight:hyperflexStorageContainers |
9188
| Hitachi | [storage/HitachiArrays][19] | cisco:intersight:storageHitachiClusters |
9289
| Hitachi | [storage/HitachiControllers][20] | cisco:intersight:storageHitachiControllers |
9390
| Hitachi | [storage/HitachiVolumes][21] | cisco:intersight:storageHitachiVolumes |
91+
| Hyperflex | [hyperflex/Clusters][5] | cisco:intersight:hyperflexClusters |
92+
| Hyperflex | [hyperflex/Nodes][8] | cisco:intersight:hyperflexNodes |
93+
| Hyperflex | [hyperflex/StorageContainers][16] | cisco:intersight:hyperflexStorageContainers |
94+
| Hyperflex | [hyperflex/Licenses][24] | cisco"intersight:hyperflexLicenses |
95+
| Licensing | [License/AccountLicenseData][22] | cisco:intersight:licenseAccountLicenseData |
96+
| Licensing | [license/LicenseInfos][23] | cisco:intersight:licenseLicenseInfos
9497
| NetApp | [storage/NetAppClusters][11] | cisco:intersight:storageNetAppClusters |
9598
| NetApp | [storage/NetAppNodes][12] | cisco:intersight:storageNetAppNodes |
9699
| NetApp | [storage/NetAppVolumes][17] | cisco:intersight:storageNetAppVolumes |
@@ -122,6 +125,10 @@ These inventory options are enabled via the multi-select in the input configurat
122125
[19]: https://intersight.com/apidocs/apirefs/api/v1/storage/HitachiArrays/model/
123126
[20]: https://intersight.com/apidocs/apirefs/api/v1/storage/HitachiControllers/model/
124127
[21]: https://intersight.com/apidocs/apirefs/api/v1/storage/HitachiVolumes/model/
128+
[22]: https://intersight.com/apidocs/apirefs/api/v1/license/AccountLicenseData/model/
129+
[23]: https://intersight.com/apidocs/apirefs/api/v1/license/LicenseInfos/model/
130+
[24]: https://intersight.com/apidocs/apirefs/api/v1/hyperflex/Licenses/model/
131+
125132

126133
All of the data from this Add-on can be queried in Splunk using the following [SPL](https://docs.splunk.com/Splexicon:SPL):
127134

@@ -159,6 +166,7 @@ One for each sourcetype...
159166
| cisco:intersight:hyperflexClusters | `index=* sourcetype=cisco:intersight:hyperflexClusters \| dedup Moid \| rename Summary.ResiliencyInfo.State as State \| rename RegisteredDevice.ConnectionStatus as ConnectionStatus \| rename Encryption.State as SoftwareEncryption \| eval SoftwareEncryption=case(isnull(SoftwareEncryption), "NONE", 1=1, replace(SoftwareEncryption, "_", " ")) \| Table source, Name, ConnectionStatus, State, HypervisorType, DeploymentType, DriveType, HxVersion, SoftwareEncryption, UtilizationPercentage` |
160167
| cisco:intersight:hyperflexNodes | `index=* sourcetype=cisco:intersight:hyperflexNodes \| dedup Moid \| rename "Drives{}.Usage" as DriveUsage \| rename "EmptySlotsList{}" as EmptySlots \| eval PersistenceDiskCount=mvcount(mvfilter(match(DriveUsage, "PERSISTENCE"))) \| eval OpenDiskSlots=mvcount(EmptySlots) \| table source, HostName, ModelNumber, SerialNumber, Role, Hypervisor, Status, PersistenceDiskCount, OpenDiskSlots` |
161168
| cisco:intersight:hyperflexStorageContainers | `index=* sourcetype=cisco:intersight:hyperflexStorageContainers \| dedup Moid \| table Cluster.Moid, Name, Type, InUse, EncryptionEnabled, MountStatus, MountSummary, VolumeCount` |
169+
| cisco:intersight:hyperflexLicenses | `index=* sourcetype=cisco:intersight:hyperflexLicenses \| dedup Moid \| table source, Cluster.Moid, ComplianceState, LicenseRegistration.Status, LicenseAuthorization.Status, SmartLicensingEnabled`
162170
| cisco: intersight:storageHitachiArrays | `index=* sourcetype=cisco:intersight:storageHitachiArrays \| dedup Moid \| table Name, Model, Serial, TargetCtl, Ctl1MicroVersion, Ctl2MicroVersion, StorageUtilization.CapacityUtilization` |
163171
| cisco: intersight:storageHitachiControllers | `index=* sourcetype=cisco:intersight:storageHitachiControllers \| dedup Moid \| table Array.Moid, Name, Status` |
164172
| cisco: intersight:storageHitachiVolumes | `index=* sourcetype=cisco:intersight:storageHitachiVolumes \| dedup Moid \| eval SizeTB = round(Size/1024/1024/1024/1024, 2) \| table Name, RaidLevel, RaidType, SizeTB` |
@@ -171,6 +179,8 @@ One for each sourcetype...
171179
| cisco:intersight:storagePureControllers | `index=* sourcetype=cisco:intersight:storagePureControllers \| dedup Moid \| table Name, Model, Serial, Version, Status, OperationalMode` |
172180
| cisco:intersight:storagePureVolumes | `index=* sourcetype=cisco:intersight:storagePureVolumes \| dedup Moid \| table Array.Moid, Name, StorageUtilization.CapacityUtilization` |
173181
| cisco:intersight:assetTargets | `index=* sourcetype=cisco:intersight:assetTargets \| dedup Moid \| table source, Name, Status, TargetType, ManagementLocation, ConnectorVersion` |
182+
| cisco:intersight:licenseLicenseInfos | `index=* sourcetype=cisco:intersight:licenseLicenseInfos \| dedup Moid \| eval InUse=round(LicenseCount/LicenseCountPurchased, 2) \| table source, LicenseType, LicenseState, LicenseCount, LicenseCountPurchased, InUse` |
183+
| cisco:intersight:licenseAccountLicenseData | `index=* sourcetype=cisco:intersight:licenseAccountLicenseData \| dedup Moid \| table source, RegistrationStatus, SyncStatus, DefaultLicenseType, HighestCompliantLicenseTier` |
174184

175185
And just a few more for fun...
176186

@@ -216,7 +226,7 @@ Becomes...
216226

217227
![Default Tag Decoding Example](images/default_spath.png)
218228

219-
So it seems very easy to search for Tags{}.Value=Premier if you wanted to find all of the things with a Premier Intersight.LicenseTier tag, but this is not safe. The problem is that if there is also a tag named, for example, SLA that also has a value of Premier you'd match it. In this default model, the Key and the Value have no relationship so using these fields is desceptively dangerous from a data integrity standpoint.
229+
So it seems very easy to search for Tags{}.Value=Premier if you wanted to find all of the things with a Premier Intersight.LicenseTier tag, but this is not safe. The problem is that if there is also a tag named, for example, SLA that also has a value of Premier you'd match it. In this default model, the Key and the Value have no relationship so using these fields is deceptively dangerous from a data integrity standpoint.
220230

221231
The solution that I've come up with using only native Splunk SPL is pretty complex but appears to be safe to use. Here is an example...
222232

@@ -256,7 +266,7 @@ A further look at the data will indicate that most of these are actually related
256266
index=* sourcetype=cisco:intersight:aaaAuditRecords Request=TRUNCATED MoType!=iam.UserPreference | rename MoDisplayNames.Name{} as name |table source, Email, Event, MoType, name
257267
```
258268

259-
Everything else has been pruned of unhelpful data to the point that it shouldn't exceed the 10KB limit. If anything does exceeed that 10KB, it will be logged...
269+
Everything else has been pruned of unhelpful data to the point that it shouldn't exceed the 10KB limit. If anything does exceed that 10KB, it will be logged...
260270

261271
`2022-07-15 12:45:20,726 INFO pid=12445 tid=MainThread file=base_modinput.py:log_warning:302 | EXAMPLE | Record exceeds 10k limit! Moid=62b22eeb656c6c2d32394990 Type=hyperflex.Node`
262272

@@ -268,8 +278,8 @@ The most useful thing will be the log file from the Add-on. This will be called
268278

269279
It should also be available via the following search...
270280

271-
```LOG
272-
index=_* sourcetype=taintersightaddon:log | rex field=_raw "\d+ (?<loglevel>\w+) pid.* \| (?<intersightinput>\w+) \| (?<logmessage>.*)" | search intersightinput=* | table _time, intersightinput, loglevel, logmessage
281+
```SPL
282+
index=_* sourcetype=taintersightaddon:log input=* | table _time input, severity, message
273283
```
274284

275285
Note that if you have multiple inputs (i.e. different Intersight accounts/appliances) configured in the Add-on, the log messages for all of the configured inputs will be interspersed. The Name from the 'Add Input' dialog above is used in the log to differentiate. In these logs, the name EXAMPLE was used.

input_module_intersight.py

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,31 @@ def write_splunk(index, source, sourcetype, data):
560560
write_splunk(index, account_name,
561561
'cisco:intersight:hyperflexStorageContainers', data)
562562

563+
# Licenses
564+
endpoint = "hyperflex/Licenses"
565+
if 'hyperflex' in opt_inventory and doInventory:
566+
helper.log_debug(
567+
f"{s} | Retrieving HX License Inventory Records")
568+
doHxLicenses = check_intersight(endpoint)
569+
570+
if 'hyperflex' in opt_inventory and doInventory and doHxLicenses:
571+
RESPONSE = r_intersight(f"{endpoint}?$count=True")
572+
count = RESPONSE.json()['Count']
573+
helper.log_info(
574+
f"{s} | Found {str(count)} Hyperflex license records to retrieve")
575+
results_per_page = 10 # adjust the number of results we pull per API call
576+
for i in range(0, count, results_per_page):
577+
RESPONSE = r_intersight(
578+
f"{endpoint}?$top={results_per_page}&$skip={str(i)}")
579+
for data in RESPONSE.json()['Results']:
580+
data = pop(['Ancestors', 'Owners', 'PermissionResources', 'SharedScope',
581+
'DomainGroupMoid', 'ClassId', 'ObjectType', 'RegisteredDevice'], data)
582+
for x in ['LicenseRegistration', 'LicenseAuthorization', 'Cluster']:
583+
data[x] = pop(['ClassId', 'ObjectType'], data[x])
584+
data['Cluster'] = pop(['link'], data['Cluster'])
585+
write_splunk(index, account_name,
586+
'cisco:intersight:hyperflexLicenses', data)
587+
563588
if not 'hyperflex' in opt_inventory:
564589
helper.log_debug(
565590
f"{s} | Hyperflex was not selected in the Inventory configuration")
@@ -797,7 +822,8 @@ def write_splunk(index, source, sourcetype, data):
797822
for data in RESPONSE.json()['Results']:
798823
data = pop(['Ancestors', 'DomainGroupMoid', 'ClassId', 'DeviceMoId', 'Owners',
799824
'Parent', 'ObjectType', 'PermissionResources', 'SharedScope', 'RegisteredDevice'], data)
800-
data['Array'] = pop(['ClassId', 'ObjectType', 'link'], data['Array'])
825+
data['Array'] = pop(
826+
['ClassId', 'ObjectType', 'link'], data['Array'])
801827
write_splunk(index, account_name,
802828
'cisco:intersight:storageHitachiControllers', data)
803829

@@ -830,6 +856,49 @@ def write_splunk(index, source, sourcetype, data):
830856
helper.log_debug(
831857
f"{s} | Hitachi was not selected in the Inventory configuration")
832858

859+
###
860+
# License Inventory
861+
###
862+
endpoint = "license/AccountLicenseData"
863+
if 'license' in opt_inventory and doInventory:
864+
helper.log_debug(f"{s} | Retrieving License Records")
865+
doLicense = check_intersight(endpoint)
866+
867+
if 'license' in opt_inventory and doInventory and doLicense:
868+
RESPONSE = r_intersight(f"{endpoint}?$count=True")
869+
count = RESPONSE.json()['Count']
870+
helper.log_info(
871+
f"{s} | Found {str(count)} license account records to retrieve")
872+
results_per_page = 10 # adjust the number of results we pull per API call
873+
for i in range(0, count, results_per_page):
874+
RESPONSE = r_intersight(
875+
f"{endpoint}?$top={results_per_page}&$skip={str(i)}")
876+
for data in RESPONSE.json()['Results']:
877+
data = pop(['Account', 'AgentData', 'Ancestors', 'DomainGroupMoid',
878+
'PermissionResources', 'Owners', 'SharedScope', 'ClassId', 'ObjectType'], data)
879+
write_splunk(
880+
index, account_name, 'cisco:intersight:licenseAccountLicenseData', data=data)
881+
882+
endpoint = "license/LicenseInfos"
883+
if 'license' in opt_inventory and doInventory and doLicense:
884+
RESPONSE = r_intersight(f"{endpoint}?$count=True")
885+
count = RESPONSE.json()['Count']
886+
helper.log_info(
887+
f"{s} | Found {str(count)} license info records to retrieve")
888+
results_per_page = 10 # adjust the number of results we pull per API call
889+
for i in range(0, count, results_per_page):
890+
RESPONSE = r_intersight(
891+
f"{endpoint}?$top={results_per_page}&$skip={str(i)}")
892+
for data in RESPONSE.json()['Results']:
893+
data = pop(['Ancestors', 'DomainGroupMoid', 'Parent',
894+
'PermissionResources', 'Owners', 'SharedScope', 'ClassId', 'ObjectType'], data)
895+
write_splunk(
896+
index, account_name, 'cisco:intersight:licenseLicenseInfos', data=data)
897+
898+
if not 'license' in opt_inventory:
899+
helper.log_debug(
900+
f"{s} | License was not selected in the Inventory configuration")
901+
833902
# Epilogue
834903
end = datetime.now()
835904
elapsed = end - start

splunk_em.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ def get_arg(self, arg_name):
3232
if arg_name == 'inventory':
3333
none = {}
3434
all = {'advisories', 'compute', 'contract', 'network',
35-
'hyperflex', 'target', 'pure', 'netapp', 'hitachi'}
36-
basic = {'advisories', 'compute', 'contract', 'network', 'target'}
35+
'hyperflex', 'target', 'pure', 'netapp', 'hitachi', 'license'}
36+
basic = {'advisories', 'compute', 'contract', 'network', 'target', 'license'}
3737
hyperflex = {'compute', 'hyperflex'}
3838
thirdpartystorage = {'pure', 'netapp', 'hitachi'}
3939
return all

splunkbase/details.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,25 @@
22

33
The Add-on leverages the [Cisco Intersight RESTful API](https://intersight.com/apidocs/introduction/overview/) to retrieve various kinds of data. Multiple inputs for different Intersight accounts/appliances are configurable and each account/appliance can optionally retrieve the following data types. Events are in JSON format.
44

5+
>New Inventory types are not automatically added to existing configurations. Please review your input configurations after upgrading to enable the new options.
6+
57
| Options | Intersight API | Splunk sourcetype |
68
| --- | --- | --- |
7-
| AAA Audit Records | [aaa/AuditRecords][1] | cisco:intersight:aaaAuditRecords |
8-
| Alarms | [cond/Alarms][2] | cisco:intersight:condAlarms |
9+
| Enable AAA Audit Records | [aaa/AuditRecords][1] | cisco:intersight:aaaAuditRecords |
10+
| Enable Alarms | [cond/Alarms][2] | cisco:intersight:condAlarms |
911
| Advisories | [tam/AdvisoryInstances][3] | cisco:intersight:tamAdvisoryInstances |
1012
| Compute | [compute/PhysicalSummaries][4] | cisco:intersight:computePhysicalSummaries |
1113
| Compute | [cond/HclStatuses][9] | cisco:intersight:condHclStatuses |
1214
| Contract | [asset/DeviceContractStatusInformations][10] | cisco:intersight:assetDeviceContractInformations |
13-
| Hyperflex | [hyperflex/Clusters][5] | cisco:intersight:hyperflexClusters |
14-
| Hyperflex | [hyperflex/Nodes][8] | cisco:intersight:hyperflexNodes |
15-
| Hyperflex | [hyperflex/StorageContainers][16] | cisco:intersight:hyperflexStorageContainers |
1615
| Hitachi | [storage/HitachiArrays][19] | cisco:intersight:storageHitachiClusters |
1716
| Hitachi | [storage/HitachiControllers][20] | cisco:intersight:storageHitachiControllers |
1817
| Hitachi | [storage/HitachiVolumes][21] | cisco:intersight:storageHitachiVolumes |
18+
| Hyperflex | [hyperflex/Clusters][5] | cisco:intersight:hyperflexClusters |
19+
| Hyperflex | [hyperflex/Nodes][8] | cisco:intersight:hyperflexNodes |
20+
| Hyperflex | [hyperflex/StorageContainers][16] | cisco:intersight:hyperflexStorageContainers |
21+
| Hyperflex | [hyperflex/Licenses][24] | cisco"intersight:hyperflexLicenses |
22+
| Licensing | [License/AccountLicenseData][22] | cisco:intersight:licenseAccountLicenseData |
23+
| Licensing | [license/LicenseInfos][23] | cisco:intersight:licenseLicenseInfos
1924
| NetApp | [storage/NetAppClusters][11] | cisco:intersight:storageNetAppClusters |
2025
| NetApp | [storage/NetAppNodes][12] | cisco:intersight:storageNetAppNodes |
2126
| NetApp | [storage/NetAppVolumes][17] | cisco:intersight:storageNetAppVolumes |
@@ -47,6 +52,9 @@ The Add-on leverages the [Cisco Intersight RESTful API](https://intersight.com/a
4752
[19]: https://intersight.com/apidocs/apirefs/api/v1/storage/HitachiArrays/model/
4853
[20]: https://intersight.com/apidocs/apirefs/api/v1/storage/HitachiControllers/model/
4954
[21]: https://intersight.com/apidocs/apirefs/api/v1/storage/HitachiVolumes/model/
55+
[22]: https://intersight.com/apidocs/apirefs/api/v1/license/AccountLicenseData/model/
56+
[23]: https://intersight.com/apidocs/apirefs/api/v1/license/LicenseInfos/model/
57+
[24]: https://intersight.com/apidocs/apirefs/api/v1/hyperflex/Licenses/model/
5058

5159
Further documentation, sample searches, and known issues are all available at [the Github repository](https://github.com/jerewill-cisco/intersight-splunk-addon).
5260

0 commit comments

Comments
 (0)