Repository: NetApp/harvest
Pull request #424 (2021-08-18 17:33:10)

docs: add asup eula


Patch:
diff --git a/.gitignore b/.gitignore
index 9376c15a..4c6543ca 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,4 +18,5 @@
 # build directories
 bin/
 dist/
-cert/
\ No newline at end of file
+cert/
+asup/
\ No newline at end of file
diff --git a/Makefile b/Makefile
index b03e68b1..a541e74f 100644
--- a/Makefile
+++ b/Makefile
@@ -24,6 +24,11 @@ GOOS ?= linux
 HARVEST_PACKAGE := harvest-${VERSION}-${RELEASE}_${GOOS}_${GOARCH}
 DIST := dist
 TMP := /tmp/${HARVEST_PACKAGE}
+ASUP_TMP := /tmp/asup
+ASUP_MAKE_TARGET ?= build #one of build/production
+GIT_TOKEN ?=
+CURRENT_DIR = $(shell pwd)
+
 
 help:  ## Display this help
 	@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n  make \033[36m\033[0m\n\nTargets:\n"} /^[a-zA-Z_-]+:.*?##/ { printf "  \033[36m%-10s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST)
@@ -60,7 +65,7 @@ endif
 
 clean: header ## Cleanup the project binary (bin) folders
 	@echo "Cleaning harvest files"
-	@rm -rf bin
+	@if test -d bin; then ls -d ./bin/* | grep -v "asup" | xargs rm -f; fi
 
 test: ## run tests
 	@echo "Running tests"
@@ -119,3 +124,13 @@ dist-tar:
 	@tar --directory /tmp --create --gzip --file ${DIST}/${HARVEST_PACKAGE}.tar.gz ${HARVEST_PACKAGE}
 	@rm -rf ${TMP}
 	@echo "tar artifact @" ${DIST}/${HARVEST_PACKAGE}.tar.gz
+
+asup:
+	@echo "Building AutoSupport"
+	@rm -rf bin/asup
+	@rm -rf ${ASUP_TMP}
+	@mkdir ${ASUP_TMP}
+	@git clone https://${GIT_TOKEN}@github.com/NetApp/harvest-private.git ${ASUP_TMP}
+	@cd ${ASUP_TMP}/harvest-asup && make ${ASUP_MAKE_TARGET} VERSION=$VERSION RELEASE=$RELEASE
+	@mkdir -p ${CURRENT_DIR}/bin
+	@cp ${ASUP_TMP}/harvest-asup/bin/asup ${CURRENT_DIR}/bin
diff --git a/SUPPORT.md b/SUPPORT.md
index 653ea735..76dbd1c1 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -1,6 +1,6 @@
 # Harvest Support and Getting Help
 
-Harvest is an open-source project developed and published by NetApp to collect performance, capacity and hardware metrics from ONTAP clusters. These metrics can then be delivered to a range of databases and displayed in Grafana dashboards. Harvest is not an officially supported NetApp product. NetApp maintains and updates Harvest with bug fixes, security updates, and feature development. For assistance refer [Getting Help](#getting%20help)
+Harvest is an open-source project developed and published by NetApp to collect performance, capacity and hardware metrics from ONTAP clusters. These metrics can then be delivered to a range of databases and displayed in Grafana dashboards. Harvest is not an officially supported NetApp product. NetApp maintains and updates Harvest with bug fixes, security updates, and feature development. For assistance refer [Getting Help](#getting-help)
 
 This document describes Harvest's release and support lifecycle as well as places you can get help.
 
@@ -22,7 +22,7 @@ We use GitHub for tracking bugs and feature requests.
 
 # Getting Help
 
-There is a vibrant community of Harvest users on NetApp's community discussion board and the `#harvest` channel in [NetApp's Slack team](https://netapppub.slack.com/archives/C02072M1UCD). Slack is a great place to ask general questions about the project and discuss related topics with like-minded peers.
+There is a vibrant community of Harvest users on the `#harvest` channel in [NetApp's Slack team](https://netapppub.slack.com/archives/C02072M1UCD). Slack is a great place to ask general questions about the project and discuss related topics with like-minded peers.
 
 ## Slack
 
@@ -30,14 +30,6 @@ Join [thePub workspace](https://www.netapp.io/slack). After joining, click the `
 
 ![Join channel image](/docs/slack.png)
 
-## NetApp Community Discussion Board
-
-The Harvest Community is active on the NetApp Community Discussion Board, you can post your questions there:
-
-* [NetApp Community Discussion Board](https://community.netapp.com/t5/Data-Infrastructure-Management-Software-Discussions/bd-p/oncommand-storage-management-software-discussions)
-
-  * Here are some tips on [how to ask good questions](https://stackoverflow.com/help/how-to-ask).
-
 ## Documentation
 
 * [Harvest Documentation](README.md)
diff --git a/autosupport/NetApp-EULA.md b/autosupport/NetApp-EULA.md
new file mode 100644
index 00000000..a3f4c907
--- /dev/null
+++ b/autosupport/NetApp-EULA.md
@@ -0,0 +1,319 @@
+# NetApp End User License Agreement for harvest-asup sidecar binary
+
+https://www.netapp.com/us/media/enduser-license-agreement-worldwide.pdf
+
+## 1. Definitions
+
+1.1 **Documentation** means technical documentation describing the features and
+functions of the Software. 
+
+1.2 **NetApp Cloud Provider** means a third party authorized by NetApp to offer
+or enable the use of the Software as part of such provider’s cloud-based service
+
+1.3 **NetApp Partner** means an authorized NetApp distributor, reseller or other
+channel partner. 
+
+1.4 **Open Source Software** means third party software that is openly and
+freely licensed under the terms of a public license designated by the third
+party.
+
+1.5 **Software** means all NetApp-branded software in object code format
+comprising backup and recovery, disaster recovery, storage efficiency and
+management software, operating systems, protocols, utilities and storage
+management tools. 
+ 
+## 2. SCOPE
+
+This end user license agreement (“EULA”) is between you (“You” or “Your”), and
+NetApp, Inc. and (as applicable) its subsidiaries and affiliates (“NetApp”).
+This EULA sets forth the terms under which NetApp licenses Software and
+Documentation to You. In the absence of a more specific written agreement, this
+EULA applies to Software and Documentation obtained by You directly from NetApp,
+indirectly from a NetApp Partner or a NetApp Cloud Provider or made available to
+you by NetApp at no charge. The types, quantities and other usage attributes
+related to Your Software licenses are specified in other documents the
+associated with Documentation, a NetApp quote or related document (for direct
+transactions), or the corresponding documents from a NetApp Partner or NetApp
+Cloud Provider (for indirect transactions). This EULA does not entitle You to
+receive Software updates, upgrades, technical support or professional services,
+which must be purchased separately unless otherwise provided at NetApp’s
+discretion.
+
+## 3. ACCEPTANCE
+
+By clicking the “I ACCEPT” button when downloading or installing the Software,
+or by copying, accessing or using the Software or Documentation, You agree that
+this EULA exclusively governs NetApp’s the Software and to You and Your use of
+Documentation unless You have a separate applicable written agreement with
+NetApp. If You are accepting this EULA on behalf of another person, company or
+other legal entity, whether as an employee, contractor, distributor, reseller,
+partner, agent or otherwise, You represent and warrant that You have full
+authority to bind them. If You do not agree to the terms of this EULA, do not
+download, install, copy, access, or use the Software or Documentation, or click
+the “I ACCEPT” button, and promptly return the Software and Documentation to the
+party from whom it was obtained.
+
+## 4. LICENSE GRANT 
+
+NetApp grants to You a personal, nonexclusive, non-transferrable, worldwide,
+limited and revocable license, without the right to sublicense, to i) install
+and use the Software for Your internal business purposes, and ii) use the
+Documentation in support of Your use of the Software. Your Software license is
+either bundled with a specific storage controller identified by a unique serial
+number (“Controller- based”) or is independent of a storage controller
+(“Standalone”), and is one of the following license types: 
+
+ a) **Life-of-controller**: Controller-based licenses granted for the period
+ during which Your storage controller is operable;
+
+ b) **Perpetual**: Standalone licenses granted in perpetuity;
+
+ c) **Term**: Controller-based licenses or Standalone licenses granted for a
+ fixed period; 
+ 
+ d) **Capacity**: Controller-based licenses or Standalone licenses granted for a
+ specified amount of raw storage capacity, number of hosts, or other measure of
+ usage as specified in the Documentation. 
+ 
+Each storage controller deployed in a cluster or a high-availability pair or
+group must have the same Controller-based license as the other storage
+controllers in that cluster, high-availability pair or group. Subject to
+NetApp’s separate written agreement, and in the context of non- disruptive
+operations within a cluster, You may deploy storage controllers with different
+Controller-based licenses and failover from one storage controller to another
+for the time required to remedy a failure, provided that all storage controllers
+in the cluster have the same hardware and software support offerings in effect
+at all times. Certain license types may require the enablement and use of
+NetApp’s remote support diagnostics systems. 
+
+## 5. LICENSE RESTRICTIONS
+
+You must comply with the EULA terms at all times when using the Software and
+Documentation. You will not, nor will You allow anyone else to: 
+
+ a) use the Software in breach or excess of the types, quantities and other
+ usage attributes related to Your Software licenses or other limitations
+ prescribed by NetApp in this EULA; 
+ 
+ b) reverse-engineer, decompile or disassemble the Software or otherwise reduce
+ it to human-readable format except to the extent required for interoperability
+ purposes under applicable laws or as expressly permitted in open-source
+ licenses; 
+ 
+ c) remove or conceal any product identification, proprietary, intellectual
+ property or other notices in the Software or Documentation; 
+ 
+ d) use the Software or Documentation to perform services for third parties in a
+ service bureau, managed services, commercial hosting services or similar
+ environment, unless i) the Software has been obtained from a NetApp Cloud
+ Provider, ii) is used in conjunction with a NetApp Cloud Provider service, iii)
+ or has been otherwise agreed in writing with NetApp; 
+ 
+ e) assign or otherwise transfer, in whole or in part, the Software or
+ Documentation licenses to another party or Controller- based licenses to a
+ different storage controller, unless otherwise agreed in writing with NetApp; 
+ 
+ f) install Controller-based licenses on or use them with third party hardware
+ or any second-hand or grey market NetApp hardware not purchased by You from
+ NetApp or a NetApp Partner; 
+ 
+ g) modify, adapt or create a derivative work of the Software or Documentation;
+ or 
+ 
+ h) publish or provide any Software benchmark or comparison test results.
+
+## 6. INTELLECTUAL PROPERTY RIGHTS
+
+The Software and Documentation is licensed, not sold, to You. It is protected by
+intellectual property laws and treaties worldwide, and contains trade secrets,
+in which NetApp and its licensors reserve and retain all rights not expressly
+granted to You. No right, title or interest to any trademark, service mark, logo
+or trade name, of NetApp or its licensors is granted to You. 
+ 
+## 7. WARRANTY
+
+NetApp warrants that for a period of 90 days from the date of first delivery of
+the Software to You or a NetApp Partner, whichever is the earlier, or such other
+minimum periods under applicable laws (the “Software Warranty Period”), the
+Software will materially conform to the then-current Documentation. NetApp does
+not warrant that Your use of the Software will be error-free or uninterrupted.
+If a material defect arises in the Software during the Software Warranty Period
+and if the defect is reproducible and verifiable, NetApp will, at its sole
+discretion and expense, repair or replace the defective Software or refund the
+amounts received by NetApp for the Software. Software that is obtained for use
+solely in conjunction with a NetApp Cloud Provider’s services is provided “AS
+IS” and without a warranty of any kind. You assume all risks arising from Your
+use of the Software together with a NetApp Cloud Provider’s offering. The
+Software warranty will be voided if You or any third parties misuse, neglect,
+attempt to repair or modify (unless authorized by NetApp), or use the Software
+beyond the range of the intended use. TO THE EXTENT PERMITTED BY APPLICABLE
+LAWS, THIS IS YOUR SOLE AND EXCLUSIVE WARRANTY AND REMEDY. NETAPP SPECIFICALLY
+DISCLAIMS ALL IMPLIED INCLUDING THOSE OF MERCHANTABILITY, WARRANTIES, ACCEPTABLE
+QUALITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. THE WARRANTY IN
+THIS SECTION 7 WILL NOT APPLY IF NETAPP MAKES THE SOFTWARE GENERALLY AVAILABLE
+AT NO COST.
+
+## 8. LIMITATION OF LIABILITY
+
+Regardless of the basis of the claim (e.g. contract, tort or statute), the total
+liability of NetApp and its licensors, under or in connection with this EULA,
+will not exceed the amounts actually received by NetApp for the Software or the
+minimum amounts permitted by applicable laws, if greater. NetApp and its
+licensors are not liable for: 
+
+ a) any indirect, consequential, incidental, exemplary or special damages; 
+ b) loss or corruption of data; 
+ c) loss of revenues, profits, goodwill or anticipated savings; 
+ d) procurement of substitute goods and/or services; 
+ e) interruption to business; or 
+ f) Your failure to comply with applicable “non-erasable” and “non-rewriteable” U.S. government regulations.
+ 
+The limitations and exclusions above will not apply to liability for death or
+bodily injury caused by negligence, gross negligence, willful misconduct, fraud
+or any other liability that cannot be excluded under applicable laws. 
+ 
+## 9. AUDIT
+
+Upon reasonable notice, You grant NetApp and its independent accountants the
+right to examine Your Software usage annually to verify compliance with this
+EULA. If the audit discloses over- usage or any other material non-compliance,
+then a) You will promptly pay to NetApp or to a NetApp Partner, as designated by
+NetApp, any additional fees that NetApp or a NetApp Partner notifies You are
+owed, and the reasonable costs of conducting the audit; and b) NetApp may
+conduct subsequent audits, upon reasonable notice, as NetApp reasonably
+determines is necessary to verify compliance with this EULA. 
+ 
+## 10. TERMINATION
+
+This EULA is effective until expiration or termination. You may terminate the
+EULA at any time on written notice to NetApp. NetApp may terminate the EULA
+immediately on written notice for material breach of the EULA. Any failure to
+remit payments in relation to the Software and Documentation when due, whether
+payable to NetApp or a NetApp Partner, constitutes a material breach of this
+EULA. Upon expiration or termination of this EULA, You will promptly return or
+destroy all copies of the Software and Documentation, including any license
+enablement keys. Sections 1, 2, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, and 15 survive
+expiration or termination of this EULA. 
+ 
+## 11. EXPORT CONTROLS
+
+You acknowledge that the Software and Documentation supplied by NetApp under
+this EULA is subject to export controls under the laws and regulations of the
+United States, the European Union and other countries (as applicable), and the
+Software may include technology controlled under export and import regulation,
+including encryption technology. You agree to comply with such laws and
+regulations and represent and warrant that You: 
+
+a) will not, unless authorized by U.S. export licenses or other government
+authorizations, directly or indirectly export or re- export the Software and
+Documentation to or use the Software and Documentation in countries subject to
+U.S. embargoes or trade sanctions programs; 
+
+b) are not a party, nor will You export or re-export to a party, identified on
+any applicable government export exclusion lists, including but not limited to
+the U.S. Denied Persons, Entity, and Specially Designated Nationals Lists; 
+
+c) will not use the Software and Documentation for any purposes prohibited by
+U.S. law, including the development, design, manufacture or production of
+nuclear, missile, chemical, or biological weaponry or other weapons of mass
+destruction; and 
+
+d) are responsible for compliance with all local encryption laws and
+regulations, where applicable, and for obtaining any permits and laws and
+regulations for your use of the Software. 
+
+You agree to provide NetApp destination end use and end user information upon
+NetApp’s request. You will obtain all required authorizations, permits, or
+licenses to export, re-export or import, as required. You agree to obligate, by
+contract or other similar assurances, the parties to whom You re-export or
+otherwise transfer the Software to comply with all obligations set forth in this
+Section 11. 
+ 
+## 12. U.S. FEDERAL GOVERNMENT END USERS
+
+This Section 12 applies to You only if You are a U.S. Federal Government end
+user. The Software and Documentation is “commercial” computer software and
+documentation and is licensed to You in accordance with the rights articulated
+in applicable U.S. government acquisition regulations (e.g. FAR, DFARs)
+pertaining to commercial computer software and documentation. You will not be
+subject to applicable audit costs specified in Section 9. Any dispute between
+You and NetApp will be subject to resolution pursuant to the Contract Disputes
+Act of 1978. Nothing contained in this EULA is meant to derogate the rights of
+the U.S. Department of Justice as identified in 28 U.S.C. §516. All other
+provisions of this EULA remain in effect as written. 
+ 
+## 13. EVALUATION OR PRE-RELEASE SOFTWARE
+
+This Section 13 applies to You only if You are acquiring generally available
+Software for the purposes of evaluation (“Evaluation Software”) or Software
+identified by NetApp as alpha, beta, pre-release, specifically demonstration or
+preview (“Pre-Release Software”). Unless otherwise agreed in writing by NetApp,
+Evaluation Software or Pre-Release Software may be used a) for a period not
+exceeding 90 days from the effective date of this EULA (“Evaluation Period”) and
+b) up to the maximum amounts of raw storage capacity, number of hosts or other
+measure of usage as specified in the Documentation. Unless otherwise agreed in
+writing by NetApp, Evaluation Software or Pre-Release 
+
+Software may only be used in non-production environments and not for commercial
+purposes. You agree to delete or deinstall the Evaluation Software or
+Pre-Release Software at the expiration of the Evaluation Period. For the
+avoidance of doubt, Software is considered in use when installed or deployed
+after expiry of the 90-day period regardless of whether or not the Evaluation
+Software or Pre-Release Software is used in a production environment. You will
+pay fees to NetApp, calculated in accordance with the applicable NetApp price
+list, within 30 days of NetApp’s demand for use exceeding the limits above. You
+agree to cooperate with NetApp in testing the Pre-Release Software and providing
+feedback, to NetApp, which NetApp can use without restriction, concerning the
+functionality and performance of the Pre-Release Software. (“Feedback”). You
+acknowledge that the Pre-Release Software and Feedback are proprietary and
+confidential information of NetApp (“Confidential Information”). You will not
+make the Confidential Information available in any form to any person other than
+to Your employees or consultants with a need to know and who are under an
+obligation of confidentiality not to disclose such Confidential Information. You
+will use the same degree of care to protect the confidentiality of such
+Confidential Information as You use to protect Your own confidential
+information. NOTWITHSTANDING SECTIONS 7 AND 8 ABOVE, THE EVALUATION SOFTWARE OR
+PRE-RELEASE SOFTWARE IS IS” WITHOUT ANY WARRANTIES OR PROVIDED REPRESENTATIONS
+EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF
+QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE AND
+NETAPP DISCLAIMS ALL LIABILITIES TO THE MAXIMUM EXTENT PERMITTED BY LAW. 
+ 
+## 14. PERFORMANCE DATA
+
+NetApp retains all right, title and interest in data and data elements collected
+by the Software systems configuration which, as applicable, pertains to the
+Software environment, the usage and performance of the Software, and the
+components managed by the Software, as applicable (“Performance Data”). Without
+limiting the “AS foregoing, NetApp may collect and use Performance Data to
+provide and improve the Software and NetApp’s other products and services. 
+ 
+## 15. GOVERNING LAW AND ENFORCEMENT RIGHTS
+
+This EULA will be construed pursuant to the laws of i) the State of California,
+United States, excluding its conflicts of law provisions, if You are in the
+United States or in a country in which NetApp has no local sales subsidiary, or
+ii) the country in which You are located if NetApp has a local sales subsidiary
+in that country. NetApp reserves the right to control all aspects of any lawsuit
+or claim that arises from Your use of the Software or Documentation. If required
+by NetApp’s agreement with a third-party licensor, NetApp’s licensor will be a
+direct and intended third party beneficiary of this EULA and may enforce it
+directly against You. To the extent that Software may include or be distributed
+with Open Source Software, the terms of the applicable license for the Open
+Source Software supersede the terms set forth in this EULA. 
+ 
+## 16. GENERAL
+
+NetApp does not waive any of its rights under this EULA by failing to or
+delaying the exercise of its rights or partially exercising its rights at any
+time. To the extent that any Section of this EULA, or part thereof, is
+determined to be invalid or unenforceable, the remainder of this EULA will
+remain in full force and effect. This EULA may not be changed except by a
+written amendment executed by an authorized representative of each party. In the
+event of a conflict between the English and non-English version of the EULA
+(where translated for local requirements), the English version of this EULA will
+govern, to the extent permitted by applicable laws. This EULA represents the
+entire agreement and understanding between NetApp and You with respect to the
+Software and Documentation. It supersedes any previous communications,
+representations or agreements between NetApp and You and prevails over any
+conflicting or additional terms in any quote, purchase order, acknowledgment, or
+similar communication between the parties.
diff --git a/autosupport/README.md b/autosupport/README.md
index d34cfd38..f13f86ca 100644
--- a/autosupport/README.md
+++ b/autosupport/README.md
@@ -9,11 +9,11 @@ Tools:
   autosupport_disabled: true
 ```
 
-This information is collected and sent via the `bin/asup` executable. Harvest
+This information is collected and sent via the `autosupport/asup` executable. Harvest
 autosupport does not gather or transmit Personally Identifiable Information
-(PII) or Personal Information. `bin/asup` comes with a
-[EULA](https://www.netapp.com/us/media/enduser-license-agreement-worldwide.pdf)
-that is not applicable to the other Harvest binaries in `./bin`. The EULA only applies to `bin/asup`. 
+(PII) or Personal Information. `autosupport/asup` comes with a [end user license
+agreement](NetApp-EULA.md) that is not applicable to the other Harvest binaries
+in `./bin`. This EULA only applies to `autosupport/asup`. 
 
 You can learn more about NetApp's commitment to data security and trust
 [here](https://www.netapp.com/us/company/trust-center/index.aspx).
@@ -29,43 +29,2309 @@ An example payload sent by Harvest looks like this. You can see exactly what Har
     "Model": "cdot",
     "Serial": "1-80-000011",
     "Ping": 0,
-    "ClusterUuid": "2c3877ad-7523-11eb-aafa-d039ea1fbe60"
+    "ClusterUuid": "37387241-8b57-11e9-8974-00a098e0219a"
   },
-  "Nodes": {
-    "Count": 4,
-    "DataPoints": 68,
-    "PollTime": 106202,
-    "ApiTime": 104031,
-    "ParseTime": 1127,
-    "PluginTime": 20,
-    "NodeUuid": [
-      "8ac0a65e-7522-11eb-aafa-d039ea1fbe60",
-      "88ef3daf-7522-11eb-bbf2-d039ea1febb4",
-      "88f1555f-7522-11eb-8d8c-d039ea1fa41d",
-      "88f7a00c-7522-11eb-9ca6-d039ea1fc4e0"
-    ]
-  },
-  "Volumes": {
-    "Count": 100,
-    "DataPoints": 69,
-    "PollTime": 1230,
-    "ApiTime": 2380,
-    "ParseTime": 10,
-    "PluginTime": 10
+  "Harvest": {
+    "HostHash": "df62c133cbd0fef8ccda100e3c04c33eb3b2d911",
+    "UUID": "fe19da98aea5c555d95292170e7251e037819ee6",
+    "Version": "2.0.2",
+    "Release": "rc2",
+    "Commit": "HEAD",
+    "BuildDate": "undefined",
+    "NumClusters": 1
   },
   "Platform": {
     "OS": "darwin",
     "Arch": "darwin",
-    "MemoryKb": 1106248,
-    "CPUs": 16
+    "Memory": {
+      "TotalKb": 33554432,
+      "AvailableKb": 13753660,
+      "UsedKb": 19800772
+    },
+    "CPUs": 1
   },
-  "Harvest": {
-    "UUID": "32799326289865b63dfe03689909333437491b4e",
-    "Version": "21.08.1809",
-    "Release": "v21.05.4",
-    "Commit": "06ef539",
-    "BuildDate": "2021-08-18T09:46:40-0400",
-    "NumClusters": 1
-  }
+  "Nodes": {
+    "Count": 2,
+    "DataPoints": 33,
+    "PollTime": 225683,
+    "ApiTime": 225158,
+    "ParseTime": 232,
+    "PluginTime": 5,
+    "Uuids": [
+      "95f94e8d-8b4e-11e9-8974-00a098e0219a",
+      "e0362156-8b4d-11e9-b263-00a098e0060e"
+    ]
+  },
+  "Volumes": {
+    "Count": 462,
+    "DataPoints": 16618,
+    "PollTime": 2151647,
+    "ApiTime": 632082,
+    "ParseTime": 66963,
+    "PluginTime": 2309
+  },
+  "Collectors": [
+    {
+      "Name": "Zapi",
+      "Query": "system-node-get-iter",
+      "BatchSize": "500",
+      "ClientTimeout": "180",
+      "Schedules": [
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "180s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 17,
+        "List": [
+          "node-details-info cpu-busytime",
+          "node-details-info env-failed-fan-count",
+          "node-details-info env-failed-fan-message",
+          "node-details-info env-failed-power-supply-count",
+          "node-details-info env-failed-power-supply-message",
+          "node-details-info env-over-temperature",
+          "node-details-info is-node-healthy",
+          "node-details-info maximum-aggregate-size",
+          "node-details-info maximum-number-of-volumes",
+          "node-details-info maximum-volume-size",
+          "node-details-info node",
+          "node-details-info node-location",
+          "node-details-info node-model",
+          "node-details-info node-serial-number",
+          "node-details-info node-uptime",
+          "node-details-info node-vendor",
+          "node-details-info product-version"
+        ]
+      }
+    },
+    {
+      "Name": "Zapi",
+      "Query": "aggr-get-iter",
+      "BatchSize": "500",
+      "ClientTimeout": "180",
+      "Schedules": [
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "180s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 46,
+        "List": [
+          "aggr-attributes aggregate-name",
+          "aggr-attributes aggregate-uuid",
+          "aggr-attributes aggr-ownership-attributes home-name",
+          "aggr-attributes aggr-raid-attributes aggregate-type",
+          "aggr-attributes aggr-raid-attributes disk-count",
+          "aggr-attributes aggr-raid-attributes plex-count",
+          "aggr-attributes aggr-raid-attributes raid-size",
+          "aggr-attributes aggr-raid-attributes state",
+          "aggr-attributes aggr-inode-attributes files-private-used",
+          "aggr-attributes aggr-inode-attributes files-total",
+          "aggr-attributes aggr-inode-attributes files-used",
+          "aggr-attributes aggr-inode-attributes inodefile-private-capacity",
+          "aggr-attributes aggr-inode-attributes inodefile-public-capacity",
+          "aggr-attributes aggr-inode-attributes maxfiles-available",
+          "aggr-attributes aggr-inode-attributes maxfiles-possible",
+          "aggr-attributes aggr-inode-attributes maxfiles-used",
+          "aggr-attributes aggr-inode-attributes percent-inode-used-capacity",
+          "aggr-attributes aggr-space-attributes capacity-tier-used",
+          "aggr-attributes aggr-space-attributes data-compacted-count",
+          "aggr-attributes aggr-space-attributes data-compaction-space-saved",
+          "aggr-attributes aggr-space-attributes data-compaction-space-saved-percent",
+          "aggr-attributes aggr-space-attributes hybrid-cache-size-total",
+          "aggr-attributes aggr-space-attributes percent-used-capacity",
+          "aggr-attributes aggr-space-attributes performance-tier-inactive-user-data",
+          "aggr-attributes aggr-space-attributes performance-tier-inactive-user-data-percent",
+          "aggr-attributes aggr-space-attributes physical-used",
+          "aggr-attributes aggr-space-attributes physical-used-percent",
+          "aggr-attributes aggr-space-attributes sis-shared-count",
+          "aggr-attributes aggr-space-attributes sis-space-saved",
+          "aggr-attributes aggr-space-attributes sis-space-saved-percent",
+          "aggr-attributes aggr-space-attributes size-available",
+          "aggr-attributes aggr-space-attributes size-total",
+          "aggr-attributes aggr-space-attributes size-used",
+          "aggr-attributes aggr-space-attributes total-reserved-space",
+          "aggr-attributes aggr-volume-count-attributes flexvol-count",
+          "aggr-attributes aggr-snapshot-attributes files-total",
+          "aggr-attributes aggr-snapshot-attributes files-used",
+          "aggr-attributes aggr-snapshot-attributes maxfiles-available",
+          "aggr-attributes aggr-snapshot-attributes maxfiles-possible",
+          "aggr-attributes aggr-snapshot-attributes maxfiles-used",
+          "aggr-attributes aggr-snapshot-attributes percent-inode-used-capacity",
+          "aggr-attributes aggr-snapshot-attributes percent-used-capacity",
+          "aggr-attributes aggr-snapshot-attributes size-available",
+          "aggr-attributes aggr-snapshot-attributes size-total",
+          "aggr-attributes aggr-snapshot-attributes size-used",
+          "aggr-attributes aggr-snapshot-attributes snapshot-reserve-percent"
+        ]
+      }
+    },
+    {
+      "Name": "Zapi",
+      "Query": "volume-get-iter",
+      "BatchSize": "500",
+      "ClientTimeout": "180",
+      "Schedules": [
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "180s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 38,
+        "List": [
+          "volume-attributes volume-autosize-attributes maximum-size",
+          "volume-attributes volume-autosize-attributes grow-threshold-percent",
+          "volume-attributes volume-id-attributes instance-uuid",
+          "volume-attributes volume-id-attributes name",
+          "volume-attributes volume-id-attributes node",
+          "volume-attributes volume-id-attributes owning-vserver-name",
+          "volume-attributes volume-id-attributes containing-aggregate-name",
+          "volume-attributes volume-id-attributes style-extended",
+          "volume-attributes volume-inode-attributes files-used",
+          "volume-attributes volume-inode-attributes files-total",
+          "volume-attributes volume-sis-attributes compression-space-saved",
+          "volume-attributes volume-sis-attributes deduplication-space-saved",
+          "volume-attributes volume-sis-attributes total-space-saved",
+          "volume-attributes volume-sis-attributes percentage-compression-space-saved",
+          "volume-attributes volume-sis-attributes percentage-deduplication-space-saved",
+          "volume-attributes volume-sis-attributes percentage-total-space-saved",
+          "volume-attributes volume-space-attributes expected-available",
+          "volume-attributes volume-space-attributes filesystem-size",
+          "volume-attributes volume-space-attributes logical-available",
+          "volume-attributes volume-space-attributes logical-used",
+          "volume-attributes volume-space-attributes logical-used-by-afs",
+          "volume-attributes volume-space-attributes logical-used-by-snapshots",
+          "volume-attributes volume-space-attributes logical-used-percent",
+          "volume-attributes volume-space-attributes physical-used",
+          "volume-attributes volume-space-attributes physical-used-percent",
+          "volume-attributes volume-space-attributes size",
+          "volume-attributes volume-space-attributes size-available",
+          "volume-attributes volume-space-attributes size-total",
+          "volume-attributes volume-space-attributes size-used",
+          "volume-attributes volume-space-attributes percentage-size-used",
+          "volume-attributes volume-space-attributes size-used-by-snapshots",
+          "volume-attributes volume-space-attributes size-available-for-snapshots",
+          "volume-attributes volume-space-attributes snapshot-reserve-available",
+          "volume-attributes volume-space-attributes snapshot-reserve-size",
+          "volume-attributes volume-space-attributes percentage-snapshot-reserve",
+          "volume-attributes volume-space-attributes percentage-snapshot-reserve-used",
+          "volume-attributes volume-state-attributes state",
+          "volume-attributes volume-state-attributes status"
+        ]
+      }
+    },
+    {
+      "Name": "Zapi",
+      "Query": "snapmirror-get-iter",
+      "BatchSize": "500",
+      "ClientTimeout": "180",
+      "Schedules": [
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "180s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 27,
+        "List": [
+          "snapmirror-info break-failed-count",
+          "snapmirror-info break-successful-count",
+          "snapmirror-info destination-volume",
+          "snapmirror-info destination-volume-node",
+          "snapmirror-info destination-vserver",
+          "snapmirror-info is-healthy",
+          "snapmirror-info lag-time",
+          "snapmirror-info last-transfer-duration",
+          "snapmirror-info last-transfer-end-timestamp",
+          "snapmirror-info last-transfer-size",
+          "snapmirror-info last-transfer-type",
+          "snapmirror-info newest-snapshot-timestamp",
+          "snapmirror-info relationship-id",
+          "snapmirror-info relationship-status",
+          "snapmirror-info relationship-type",
+          "snapmirror-info relationship-group-type",
+          "snapmirror-info resync-failed-count",
+          "snapmirror-info resync-successful-count",
+          "snapmirror-info schedule",
+          "snapmirror-info source-volume",
+          "snapmirror-info source-vserver",
+          "snapmirror-info source-node",
+          "snapmirror-info total-transfer-bytes",
+          "snapmirror-info total-transfer-time-secs",
+          "snapmirror-info unhealthy-reason",
+          "snapmirror-info update-failed-count",
+          "snapmirror-info update-successful-count"
+        ]
+      }
+    },
+    {
+      "Name": "Zapi",
+      "Query": "storage-disk-get-iter",
+      "BatchSize": "500",
+      "ClientTimeout": "180",
+      "Schedules": [
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "180s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 20,
+        "List": [
+          "storage-disk-info disk-uid",
+          "storage-disk-info disk-name",
+          "storage-disk-info disk-inventory-info bytes-per-sector",
+          "storage-disk-info disk-inventory-info capacity-sectors",
+          "storage-disk-info disk-inventory-info disk-type",
+          "storage-disk-info disk-inventory-info is-shared",
+          "storage-disk-info disk-inventory-info model",
+          "storage-disk-info disk-inventory-info serial-number",
+          "storage-disk-info disk-inventory-info shelf",
+          "storage-disk-info disk-inventory-info shelf-bay",
+          "storage-disk-info disk-ownership-info home-node-name",
+          "storage-disk-info disk-ownership-info owner-node-name",
+          "storage-disk-info disk-ownership-info is-failed",
+          "storage-disk-info disk-stats-info average-latency",
+          "storage-disk-info disk-stats-info disk-io-kbps",
+          "storage-disk-info disk-stats-info power-on-time-interval",
+          "storage-disk-info disk-stats-info sectors-read",
+          "storage-disk-info disk-stats-info sectors-written",
+          "storage-disk-info disk-raid-info disk-outage-info reason",
+          "storage-disk-info disk-raid-info disk-shared-info aggregate-list shared-aggregate-info aggregate-name"
+        ]
+      }
+    },
+    {
+      "Name": "Zapi",
+      "Query": "storage-shelf-info-get-iter",
+      "BatchSize": "500",
+      "ClientTimeout": "180",
+      "Schedules": [
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "180s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 9,
+        "List": [
+          "storage-shelf-info disk-count",
+          "storage-shelf-info module-type",
+          "storage-shelf-info serial-number",
+          "storage-shelf-info shelf",
+          "storage-shelf-info shelf-model",
+          "storage-shelf-info shelf-uid",
+          "storage-shelf-info state",
+          "storage-shelf-info vendor-name",
+          "storage-shelf-info op-status"
+        ]
+      }
+    },
+    {
+      "Name": "Zapi",
+      "Query": "diagnosis-status-get",
+      "ClientTimeout": "180",
+      "Schedules": [
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "180s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 1,
+        "List": [
+          "status"
+        ]
+      }
+    },
+    {
+      "Name": "Zapi",
+      "Query": "diagnosis-subsystem-config-get-iter",
+      "BatchSize": "500",
+      "ClientTimeout": "180",
+      "Schedules": [
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "180s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 4,
+        "List": [
+          "diagnosis-subsystem-config-info health",
+          "diagnosis-subsystem-config-info subsystem",
+          "diagnosis-subsystem-config-info outstanding-alert-count",
+          "diagnosis-subsystem-config-info suppressed-alert-count"
+        ]
+      }
+    },
+    {
+      "Name": "Zapi",
+      "Query": "lun-get-iter",
+      "BatchSize": "500",
+      "ClientTimeout": "180",
+      "Schedules": [
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "180s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 9,
+        "List": [
+          "lun-info node",
+          "lun-info path",
+          "lun-info qtree",
+          "lun-info size",
+          "lun-info size-used",
+          "lun-info state",
+          "lun-info uuid",
+          "lun-info volume",
+          "lun-info vserver"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "system:node",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 25,
+        "List": [
+          "instance_name",
+          "avg_processor_busy",
+          "cpu_elapsed_time",
+          "uptime",
+          "memory",
+          "total_data",
+          "total_latency",
+          "total_ops",
+          "cifs_ops",
+          "nfs_ops",
+          "iscsi_ops",
+          "fcp_ops",
+          "nvmf_ops",
+          "disk_data_read",
+          "disk_data_written",
+          "hdd_data_read",
+          "hdd_data_written",
+          "ssd_data_read",
+          "ssd_data_written",
+          "net_data_recv",
+          "net_data_sent",
+          "fcp_data_recv",
+          "fcp_data_sent",
+          "nvmf_data_recv",
+          "mvmf_data_sent"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "hostadapter",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 4,
+        "List": [
+          "instance_name",
+          "node_name",
+          "bytes_read",
+          "bytes_written"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "path",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 11,
+        "List": [
+          "instance_name",
+          "instance_uuid",
+          "node_name",
+          "read_iops",
+          "read_data",
+          "write_data",
+          "write_iops",
+          "total_data",
+          "total_iops",
+          "read_latency",
+          "write_latency"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "disk:constituent",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 23,
+        "List": [
+          "instance_uuid",
+          "instance_name",
+          "cp_read_chain",
+          "cp_read_latency",
+          "cp_reads",
+          "disk_busy",
+          "disk_capacity",
+          "disk_speed",
+          "io_pending",
+          "io_queued",
+          "node_name",
+          "physical_disk_name",
+          "raid_group",
+          "raid_type",
+          "total_transfers",
+          "user_read_chain",
+          "user_read_blocks",
+          "user_read_latency",
+          "user_reads",
+          "user_write_chain",
+          "user_write_blocks",
+          "user_write_latency",
+          "user_writes"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "fcvi",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 6,
+        "List": [
+          "instance_name",
+          "instance_uuid",
+          "node_name",
+          "rdma_write_throughput",
+          "rdma_write_ops",
+          "rdma_write_avg_latency"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "ext_cache_obj",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 20,
+        "List": [
+          "instance_name",
+          "instance_uuid",
+          "node_name",
+          "disk_reads_replaced",
+          "accesses",
+          "hit_percent",
+          "inserts",
+          "evicts",
+          "invalidates",
+          "usage",
+          "hit",
+          "hit_normal_lev0",
+          "hit_metadata_file",
+          "hit_directory",
+          "hit_indirect",
+          "miss",
+          "miss_normal_lev0",
+          "miss_metadata_file",
+          "miss_directory",
+          "miss_indirect"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "wafl",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 23,
+        "List": [
+          "instance_uuid",
+          "node_name",
+          "avg_non_wafl_msg_latency",
+          "avg_wafl_msg_latency",
+          "avg_wafl_repl_msg_latency",
+          "wafl_msg_total",
+          "wafl_repl_msg_total",
+          "non_wafl_msg_total",
+          "cp_count",
+          "cp_phase_times",
+          "read_io_type",
+          "total_cp_msecs",
+          "total_cp_util",
+          "wafl_memory_used",
+          "wafl_memory_free",
+          "wafl_reads_from_cache",
+          "wafl_reads_from_cloud",
+          "wafl_reads_from_cloud_s2c_bin",
+          "wafl_reads_from_disk",
+          "wafl_reads_from_ext_cache",
+          "wafl_reads_from_fc_miss",
+          "wafl_reads_from_pmem",
+          "wafl_reads_from_ssd"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "wafl_hya_per_aggr",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 19,
+        "List": [
+          "instance_name",
+          "node_name",
+          "ssd_total",
+          "ssd_total_used",
+          "ssd_available",
+          "ssd_read_cached",
+          "ssd_write_cached",
+          "read_ops_replaced",
+          "read_ops_replaced_percent",
+          "write_blks_replaced",
+          "write_blks_replaced_percent",
+          "hya_read_hit_latency_average",
+          "hya_read_miss_latency_average",
+          "hya_write_ssd_latency_average",
+          "hya_write_hdd_latency_average",
+          "read_cache_ins_rate",
+          "wc_write_blks_total",
+          "evict_remove_rate",
+          "evict_destage_rate"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "wafl_hya_sizer",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 3,
+        "List": [
+          "instance_name",
+          "node_name",
+          "cache_stats"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "nic_common",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 17,
+        "List": [
+          "instance_name",
+          "instance_uuid",
+          "node_name",
+          "rx_bytes",
+          "tx_bytes",
+          "link_speed",
+          "link_current_state",
+          "link_up_to_downs",
+          "nic_type",
+          "rx_alignment_errors",
+          "rx_crc_errors",
+          "rx_length_errors",
+          "rx_total_errors",
+          "rx_errors",
+          "tx_errors",
+          "tx_hw_errors",
+          "tx_total_errors"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "namespace",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 13,
+        "List": [
+          "instance_name",
+          "vserver_name",
+          "read_data",
+          "write_data",
+          "read_ops",
+          "write_ops",
+          "other_ops",
+          "avg_read_latency",
+          "avg_write_latency",
+          "avg_other_latency",
+          "queue_full",
+          "remote_bytes",
+          "remote_ops"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "nvmf_fc_lif",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 15,
+        "List": [
+          "instance_name",
+          "instance_uuid",
+          "vserver_name",
+          "node_name",
+          "port_id",
+          "read_data",
+          "read_ops",
+          "avg_read_latency",
+          "write_data",
+          "write_ops",
+          "avg_write_latency",
+          "other_ops",
+          "avg_other_latency",
+          "total_ops",
+          "avg_latency"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "fcp_port",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 54,
+        "List": [
+          "instance_name",
+          "instance_uuid",
+          "node_name",
+          "avg_other_latency",
+          "avg_read_latency",
+          "avg_write_latency",
+          "read_data",
+          "write_data",
+          "total_data",
+          "read_ops",
+          "write_ops",
+          "other_ops",
+          "total_ops",
+          "link_speed",
+          "link_down",
+          "link_failure",
+          "loss_of_signal",
+          "loss_of_sync",
+          "prim_seq_err",
+          "queue_full",
+          "reset_count",
+          "shared_int_count",
+          "spurious_int_count",
+          "threshold_full",
+          "discarded_frames_count",
+          "int_count",
+          "invalid_transmission_word",
+          "isr_count",
+          "invalid_crc",
+          "nvmf_avg_other_latency",
+          "nvmf_avg_read_latency",
+          "nvmf_avg_remote_other_latency",
+          "nvmf_avg_remote_read_latency",
+          "nvmf_avg_remote_write_latenc",
+          "nvmf_avg_write_latency",
+          "nvmf_caw_data",
+          "nvmf_caw_ops",
+          "nvmf_command_slots",
+          "nvmf_other_ops",
+          "nvmf_read_data",
+          "nvmf_read_ops",
+          "nvmf_remote_caw_data",
+          "nvmf_remote_caw_ops",
+          "nvmf_remote_other_ops",
+          "nvmf_remote_read_data",
+          "nvmf_remote_read_ops",
+          "nvmf_remote_total_data",
+          "nvmf_remote_total_ops",
+          "nvmf_remote_write_data",
+          "nvmf_remote_write_ops",
+          "nvmf_total_data",
+          "nvmf_total_ops",
+          "nvmf_write_data",
+          "nvmf_write_ops"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "object_store_client_op",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 8,
+        "List": [
+          "instance_name",
+          "instance_uuid",
+          "node_name",
+          "average_latency",
+          "get_throughput_bytes",
+          "put_throughput_bytes",
+          "stats",
+          "throughput_ops"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "volume:node",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 33,
+        "List": [
+          "instance_name",
+          "cifs_read_data",
+          "cifs_write_data",
+          "cifs_read_ops",
+          "cifs_write_ops",
+          "cifs_other_ops",
+          "cifs_read_latency",
+          "cifs_write_latency",
+          "cifs_other_latency",
+          "nfs_read_data",
+          "nfs_write_data",
+          "nfs_read_ops",
+          "nfs_write_ops",
+          "nfs_other_ops",
+          "nfs_read_latency",
+          "nfs_write_latency",
+          "nfs_other_latency",
+          "iscsi_read_data",
+          "iscsi_write_data",
+          "iscsi_read_ops",
+          "iscsi_write_ops",
+          "iscsi_other_ops",
+          "iscsi_read_latency",
+          "iscsi_write_latency",
+          "iscsi_other_latency",
+          "fcp_read_data",
+          "fcp_write_data",
+          "fcp_read_ops",
+          "fcp_write_ops",
+          "fcp_other_ops",
+          "fcp_read_latency",
+          "fcp_write_latency",
+          "fcp_other_latency"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "token_manager",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 12,
+        "List": [
+          "node_name",
+          "instance_name",
+          "instance_uuid",
+          "token_copy_success",
+          "token_create_success",
+          "token_zero_success",
+          "token_copy_failure",
+          "token_create_failure",
+          "token_zero_failure",
+          "token_copy_bytes",
+          "token_create_bytes",
+          "token_zero_bytes"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "resource_headroom_cpu",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 13,
+        "List": [
+          "instance_name",
+          "node_name",
+          "current_latency",
+          "current_ops",
+          "current_utilization",
+          "optimal_point_latency",
+          "optimal_point_ops",
+          "optimal_point_utilization",
+          "optimal_point_confidence_factor",
+          "ewma_daily",
+          "ewma_hourly",
+          "ewma_monthly",
+          "ewma_weekly"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "resource_headroom_aggr",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 13,
+        "List": [
+          "instance_name",
+          "node_name",
+          "current_latency",
+          "current_ops",
+          "current_utilization",
+          "optimal_point_latency",
+          "optimal_point_ops",
+          "optimal_point_utilization",
+          "optimal_point_confidence_factor",
+          "ewma_daily",
+          "ewma_hourly",
+          "ewma_monthly",
+          "ewma_weekly"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "processor",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 5,
+        "List": [
+          "node_name",
+          "instance_name",
+          "instance_uuid",
+          "domain_busy",
+          "processor_busy"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "cifs:node",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 11,
+        "List": [
+          "instance_name",
+          "cifs_op_count",
+          "cifs_ops",
+          "cifs_read_ops",
+          "cifs_write_ops",
+          "cifs_latency",
+          "cifs_read_latency",
+          "cifs_write_latency",
+          "connections",
+          "established_sessions",
+          "open_files"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "nfsv3:node",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 52,
+        "List": [
+          "instance_name",
+          "nfsv3_ops",
+          "nfsv3_read_ops",
+          "nfsv3_write_ops",
+          "nfsv3_throughput",
+          "nfsv3_read_throughput",
+          "nfsv3_write_throughput",
+          "read_avg_latency",
+          "write_avg_latency",
+          "latency",
+          "access_total",
+          "commit_total",
+          "create_total",
+          "fsinfo_total",
+          "fsstat_total",
+          "getattr_total",
+          "link_total",
+          "lookup_total",
+          "mkdir_total",
+          "mknod_total",
+          "null_total",
+          "pathconf_total",
+          "read_symlink_total",
+          "read_total",
+          "readdir_total",
+          "readdirplus_total",
+          "remove_total",
+          "rename_total",
+          "rmdir_total",
+          "setattr_total",
+          "symlink_total",
+          "write_total",
+          "access_avg_latency",
+          "commit_avg_latency",
+          "create_avg_latency",
+          "fsinfo_avg_latency",
+          "fsstat_avg_latency",
+          "getattr_avg_latency",
+          "link_avg_latency",
+          "lookup_avg_latency",
+          "mkdir_avg_latency",
+          "mknod_avg_latency",
+          "null_avg_latency",
+          "pathconf_avg_latency",
+          "read_symlink_avg_latency",
+          "readdir_avg_latency",
+          "readdirplus_avg_latency",
+          "remove_avg_latency",
+          "rename_avg_latency",
+          "rmdir_avg_latency",
+          "setattr_avg_latency",
+          "symlink_avg_latency"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "nfsv4:node",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 82,
+        "List": [
+          "instance_name",
+          "latency",
+          "total_ops",
+          "nfs4_read_throughput",
+          "nfs4_throughput",
+          "nfs4_write_throughput",
+          "access_total",
+          "close_total",
+          "commit_total",
+          "create_total",
+          "delegpurge_total",
+          "delegreturn_total",
+          "getattr_total",
+          "getfh_total",
+          "link_total",
+          "lock_total",
+          "lockt_total",
+          "locku_total",
+          "lookup_total",
+          "lookupp_total",
+          "null_total",
+          "nverify_total",
+          "open_confirm_total",
+          "open_downgrade_total",
+          "open_total",
+          "openattr_total",
+          "putfh_total",
+          "putpubfh_total",
+          "putrootfh_total",
+          "read_total",
+          "readdir_total",
+          "readlink_total",
+          "release_lock_owner_total",
+          "remove_total",
+          "rename_total",
+          "renew_total",
+          "restorefh_total",
+          "savefh_total",
+          "secinfo_total",
+          "setattr_total",
+          "setclientid_confirm_total",
+          "setclientid_total",
+          "verify_total",
+          "write_total",
+          "access_avg_latency",
+          "close_avg_latency",
+          "commit_avg_latency",
+          "create_avg_latency",
+          "delegpurge_avg_latency",
+          "delegreturn_avg_latency",
+          "getattr_avg_latency",
+          "getfh_avg_latency",
+          "link_avg_latency",
+          "lock_avg_latency",
+          "lockt_avg_latency",
+          "locku_avg_latency",
+          "lookup_avg_latency",
+          "lookupp_avg_latency",
+          "null_avg_latency",
+          "nverify_avg_latency",
+          "open_avg_latency",
+          "open_confirm_avg_latency",
+          "open_downgrade_avg_latency",
+          "openattr_avg_latency",
+          "putfh_avg_latency",
+          "putpubfh_avg_latency",
+          "putrootfh_avg_latency",
+          "read_avg_latency",
+          "readdir_avg_latency",
+          "readlink_avg_latency",
+          "release_lock_owner_avg_latency",
+          "remove_avg_latency",
+          "rename_avg_latency",
+          "renew_avg_latency",
+          "restorefh_avg_latency",
+          "savefh_avg_latency",
+          "secinfo_avg_latency",
+          "setattr_avg_latency",
+          "setclientid_avg_latency",
+          "setclientid_confirm_avg_latency",
+          "verify_avg_latency",
+          "write_avg_latency"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "nfsv4_1:node",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 110,
+        "List": [
+          "instance_name",
+          "latency",
+          "total_ops",
+          "nfs41_read_throughput",
+          "nfs41_throughput",
+          "nfs41_write_throughput",
+          "access_total",
+          "backchannel_ctl_total",
+          "bind_conn_to_session_total",
+          "close_total",
+          "commit_total",
+          "create_session_total",
+          "create_total",
+          "delegpurge_total",
+          "delegreturn_total",
+          "destroy_clientid_total",
+          "destroy_session_total",
+          "exchange_id_total",
+          "free_stateid_total",
+          "get_dir_delegation_total",
+          "getattr_total",
+          "getdeviceinfo_total",
+          "getdevicelist_total",
+          "getfh_total",
+          "layoutcommit_total",
+          "layoutget_total",
+          "layoutreturn_total",
+          "link_total",
+          "lock_total",
+          "lockt_total",
+          "locku_total",
+          "lookup_total",
+          "lookupp_total",
+          "null_total",
+          "nverify_total",
+          "open_downgrade_total",
+          "open_total",
+          "openattr_total",
+          "putfh_total",
+          "putpubfh_total",
+          "putrootfh_total",
+          "read_total",
+          "readdir_total",
+          "readlink_total",
+          "reclaim_complete_total",
+          "remove_total",
+          "rename_total",
+          "restorefh_total",
+          "savefh_total",
+          "secinfo_no_name_total",
+          "secinfo_total",
+          "sequence_total",
+          "set_ssv_total",
+          "setattr_total",
+          "test_stateid_total",
+          "verify_total",
+          "want_delegation_total",
+          "write_total",
+          "access_avg_latency",
+          "backchannel_ctl_avg_latency",
+          "bind_conn_to_session_avg_latency",
+          "close_avg_latency",
+          "commit_avg_latency",
+          "create_avg_latency",
+          "create_session_avg_latency",
+          "delegpurge_avg_latency",
+          "delegreturn_avg_latency",
+          "destroy_clientid_avg_latency",
+          "destroy_session_avg_latency",
+          "exchange_id_avg_latency",
+          "free_stateid_avg_latency",
+          "get_dir_delegation_avg_latency",
+          "getattr_avg_latency",
+          "getdeviceinfo_avg_latency",
+          "getdevicelist_avg_latency",
+          "getfh_avg_latency",
+          "layoutcommit_avg_latency",
+          "layoutget_avg_latency",
+          "layoutreturn_avg_latency",
+          "link_avg_latency",
+          "lock_avg_latency",
+          "lockt_avg_latency",
+          "locku_avg_latency",
+          "lookup_avg_latency",
+          "lookupp_avg_latency",
+          "null_avg_latency",
+          "nverify_avg_latency",
+          "open_avg_latency",
+          "open_downgrade_avg_latency",
+          "openattr_avg_latency",
+          "putfh_avg_latency",
+          "putpubfh_avg_latency",
+          "putrootfh_avg_latency",
+          "read_avg_latency",
+          "readdir_avg_latency",
+          "readlink_avg_latency",
+          "reclaim_complete_avg_latency",
+          "remove_avg_latency",
+          "rename_avg_latency",
+          "restorefh_avg_latency",
+          "savefh_avg_latency",
+          "secinfo_avg_latency",
+          "secinfo_no_name_avg_latency",
+          "sequence_avg_latency",
+          "set_ssv_avg_latency",
+          "setattr_avg_latency",
+          "test_stateid_avg_latency",
+          "verify_avg_latency",
+          "want_delegation_avg_latency",
+          "write_avg_latency"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "qtree",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 9,
+        "List": [
+          "instance_uuid",
+          "instance_name",
+          "vserver_name",
+          "node_name",
+          "parent_vol",
+          "cifs_ops",
+          "nfs_ops",
+          "internal_ops",
+          "total_ops"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "volume",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 15,
+        "List": [
+          "instance_uuid",
+          "instance_name",
+          "vserver_name",
+          "node_name",
+          "parent_aggr",
+          "read_data",
+          "write_data",
+          "read_ops",
+          "write_ops",
+          "other_ops",
+          "total_ops",
+          "read_latency",
+          "write_latency",
+          "other_latency",
+          "avg_latency"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "lun",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 23,
+        "List": [
+          "instance_name",
+          "vserver_name",
+          "read_data",
+          "write_data",
+          "read_ops",
+          "write_ops",
+          "xcopy_reqs",
+          "writesame_reqs",
+          "writesame_unmap_reqs",
+          "caw_reqs",
+          "avg_read_latency",
+          "avg_write_latency",
+          "avg_xcopy_latency",
+          "unmap_reqs",
+          "writesame_unmap_reqs",
+          "enospc",
+          "queue_full",
+          "remote_bytes",
+          "remote_ops",
+          "read_partial_blocks",
+          "write_partial_blocks",
+          "write_align_histo",
+          "read_align_histo"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "nfsv3",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 52,
+        "List": [
+          "instance_name",
+          "nfsv3_ops",
+          "nfsv3_read_ops",
+          "nfsv3_write_ops",
+          "nfsv3_throughput",
+          "nfsv3_read_throughput",
+          "nfsv3_write_throughput",
+          "read_avg_latency",
+          "write_avg_latency",
+          "latency",
+          "access_total",
+          "commit_total",
+          "create_total",
+          "fsinfo_total",
+          "fsstat_total",
+          "getattr_total",
+          "link_total",
+          "lookup_total",
+          "mkdir_total",
+          "mknod_total",
+          "null_total",
+          "pathconf_total",
+          "read_symlink_total",
+          "read_total",
+          "readdir_total",
+          "readdirplus_total",
+          "remove_total",
+          "rename_total",
+          "rmdir_total",
+          "setattr_total",
+          "symlink_total",
+          "write_total",
+          "access_avg_latency",
+          "commit_avg_latency",
+          "create_avg_latency",
+          "fsinfo_avg_latency",
+          "fsstat_avg_latency",
+          "getattr_avg_latency",
+          "link_avg_latency",
+          "lookup_avg_latency",
+          "mkdir_avg_latency",
+          "mknod_avg_latency",
+          "null_avg_latency",
+          "pathconf_avg_latency",
+          "read_symlink_avg_latency",
+          "readdir_avg_latency",
+          "readdirplus_avg_latency",
+          "remove_avg_latency",
+          "rename_avg_latency",
+          "rmdir_avg_latency",
+          "setattr_avg_latency",
+          "symlink_avg_latency"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "nfsv4",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 82,
+        "List": [
+          "instance_name",
+          "latency",
+          "total_ops",
+          "nfs4_read_throughput",
+          "nfs4_throughput",
+          "nfs4_write_throughput",
+          "access_total",
+          "close_total",
+          "commit_total",
+          "create_total",
+          "delegpurge_total",
+          "delegreturn_total",
+          "getattr_total",
+          "getfh_total",
+          "link_total",
+          "lock_total",
+          "lockt_total",
+          "locku_total",
+          "lookup_total",
+          "lookupp_total",
+          "null_total",
+          "nverify_total",
+          "open_confirm_total",
+          "open_downgrade_total",
+          "open_total",
+          "openattr_total",
+          "putfh_total",
+          "putpubfh_total",
+          "putrootfh_total",
+          "read_total",
+          "readdir_total",
+          "readlink_total",
+          "release_lock_owner_total",
+          "remove_total",
+          "rename_total",
+          "renew_total",
+          "restorefh_total",
+          "savefh_total",
+          "secinfo_total",
+          "setattr_total",
+          "setclientid_confirm_total",
+          "setclientid_total",
+          "verify_total",
+          "write_total",
+          "access_avg_latency",
+          "close_avg_latency",
+          "commit_avg_latency",
+          "create_avg_latency",
+          "delegpurge_avg_latency",
+          "delegreturn_avg_latency",
+          "getattr_avg_latency",
+          "getfh_avg_latency",
+          "link_avg_latency",
+          "lock_avg_latency",
+          "lockt_avg_latency",
+          "locku_avg_latency",
+          "lookup_avg_latency",
+          "lookupp_avg_latency",
+          "null_avg_latency",
+          "nverify_avg_latency",
+          "open_avg_latency",
+          "open_confirm_avg_latency",
+          "open_downgrade_avg_latency",
+          "openattr_avg_latency",
+          "putfh_avg_latency",
+          "putpubfh_avg_latency",
+          "putrootfh_avg_latency",
+          "read_avg_latency",
+          "readdir_avg_latency",
+          "readlink_avg_latency",
+          "release_lock_owner_avg_latency",
+          "remove_avg_latency",
+          "rename_avg_latency",
+          "renew_avg_latency",
+          "restorefh_avg_latency",
+          "savefh_avg_latency",
+          "secinfo_avg_latency",
+          "setattr_avg_latency",
+          "setclientid_avg_latency",
+          "setclientid_confirm_avg_latency",
+          "verify_avg_latency",
+          "write_avg_latency"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "nfsv4_1",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 110,
+        "List": [
+          "instance_name",
+          "latency",
+          "total_ops",
+          "nfs41_read_throughput",
+          "nfs41_throughput",
+          "nfs41_write_throughput",
+          "access_total",
+          "backchannel_ctl_total",
+          "bind_conn_to_session_total",
+          "close_total",
+          "commit_total",
+          "create_session_total",
+          "create_total",
+          "delegpurge_total",
+          "delegreturn_total",
+          "destroy_clientid_total",
+          "destroy_session_total",
+          "exchange_id_total",
+          "free_stateid_total",
+          "get_dir_delegation_total",
+          "getattr_total",
+          "getdeviceinfo_total",
+          "getdevicelist_total",
+          "getfh_total",
+          "layoutcommit_total",
+          "layoutget_total",
+          "layoutreturn_total",
+          "link_total",
+          "lock_total",
+          "lockt_total",
+          "locku_total",
+          "lookup_total",
+          "lookupp_total",
+          "null_total",
+          "nverify_total",
+          "open_downgrade_total",
+          "open_total",
+          "openattr_total",
+          "putfh_total",
+          "putpubfh_total",
+          "putrootfh_total",
+          "read_total",
+          "readdir_total",
+          "readlink_total",
+          "reclaim_complete_total",
+          "remove_total",
+          "rename_total",
+          "restorefh_total",
+          "savefh_total",
+          "secinfo_no_name_total",
+          "secinfo_total",
+          "sequence_total",
+          "set_ssv_total",
+          "setattr_total",
+          "test_stateid_total",
+          "verify_total",
+          "want_delegation_total",
+          "write_total",
+          "access_avg_latency",
+          "backchannel_ctl_avg_latency",
+          "bind_conn_to_session_avg_latency",
+          "close_avg_latency",
+          "commit_avg_latency",
+          "create_avg_latency",
+          "create_session_avg_latency",
+          "delegpurge_avg_latency",
+          "delegreturn_avg_latency",
+          "destroy_clientid_avg_latency",
+          "destroy_session_avg_latency",
+          "exchange_id_avg_latency",
+          "free_stateid_avg_latency",
+          "get_dir_delegation_avg_latency",
+          "getattr_avg_latency",
+          "getdeviceinfo_avg_latency",
+          "getdevicelist_avg_latency",
+          "getfh_avg_latency",
+          "layoutcommit_avg_latency",
+          "layoutget_avg_latency",
+          "layoutreturn_avg_latency",
+          "link_avg_latency",
+          "lock_avg_latency",
+          "lockt_avg_latency",
+          "locku_avg_latency",
+          "lookup_avg_latency",
+          "lookupp_avg_latency",
+          "null_avg_latency",
+          "nverify_avg_latency",
+          "open_avg_latency",
+          "open_downgrade_avg_latency",
+          "openattr_avg_latency",
+          "putfh_avg_latency",
+          "putpubfh_avg_latency",
+          "putrootfh_avg_latency",
+          "read_avg_latency",
+          "readdir_avg_latency",
+          "readlink_avg_latency",
+          "reclaim_complete_avg_latency",
+          "remove_avg_latency",
+          "rename_avg_latency",
+          "restorefh_avg_latency",
+          "savefh_avg_latency",
+          "secinfo_avg_latency",
+          "secinfo_no_name_avg_latency",
+          "sequence_avg_latency",
+          "set_ssv_avg_latency",
+          "setattr_avg_latency",
+          "test_stateid_avg_latency",
+          "verify_avg_latency",
+          "want_delegation_avg_latency",
+          "write_avg_latency"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "cifs:vserver",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 13,
+        "List": [
+          "instance_uuid",
+          "instance_name",
+          "cifs_op_count",
+          "cifs_ops",
+          "cifs_read_ops",
+          "cifs_write_ops",
+          "cifs_latency",
+          "cifs_read_latency",
+          "cifs_write_latency",
+          "connections",
+          "established_sessions",
+          "open_files",
+          "signed_sessions"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "lif",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 11,
+        "List": [
+          "instance_uuid",
+          "instance_name",
+          "node_name",
+          "vserver_name",
+          "current_port",
+          "recv_data",
+          "recv_packet",
+          "recv_errors",
+          "sent_data",
+          "sent_packet",
+          "sent_errors"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "iscsi_lif",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 15,
+        "List": [
+          "instance_name",
+          "instance_uuid",
+          "vserver_name",
+          "node_name",
+          "protocol_errors",
+          "read_data",
+          "write_data",
+          "iscsi_read_ops",
+          "avg_read_latency",
+          "iscsi_write_ops",
+          "avg_write_latency",
+          "iscsi_other_ops",
+          "avg_other_latency",
+          "cmd_transfered",
+          "avg_latency"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "fcp_lif",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 15,
+        "List": [
+          "instance_name",
+          "instance_uuid",
+          "vserver_name",
+          "node_name",
+          "port_id",
+          "read_data",
+          "read_ops",
+          "avg_read_latency",
+          "write_data",
+          "write_ops",
+          "avg_write_latency",
+          "other_ops",
+          "avg_other_latency",
+          "total_ops",
+          "avg_latency"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "copy_manager",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 7,
+        "List": [
+          "instance_name",
+          "instance_uuid",
+          "bce_copy_count_curr",
+          "ocs_copy_count_curr",
+          "sce_copy_count_curr",
+          "spince_copy_count_curr",
+          "KB_copied"
+        ]
+      }
+    },
+    {
+      "Name": "ZapiPerf",
+      "Query": "wafl_comp_aggr_vol_bin",
+      "ClientTimeout": "60s",
+      "Schedules": [
+        {
+          "Name": "counter",
+          "Schedule": "1200s"
+        },
+        {
+          "Name": "instance",
+          "Schedule": "600s"
+        },
+        {
+          "Name": "data",
+          "Schedule": "60s"
+        }
+      ],
+      "Exporters": [
+        "Prometheus"
+      ],
+      "Counters": {
+        "Count": 5,
+        "List": [
+          "instance_name",
+          "vserver_name",
+          "vol_name",
+          "cloud_bin_operation",
+          "cloud_bin_op_latency_average"
+        ]
+      }
+    }
+  ]
 }
+
 ```
\ No newline at end of file
diff --git a/cmd/collectors/zapi/collector/zapi.go b/cmd/collectors/zapi/collector/zapi.go
index 228fdf2b..9b50345b 100644
--- a/cmd/collectors/zapi/collector/zapi.go
+++ b/cmd/collectors/zapi/collector/zapi.go
@@ -1,9 +1,11 @@
 /*
  * Copyright NetApp Inc, 2021 All rights reserved
  */
+
 package zapi
 
 import (
+	"fmt"
 	"goharvest2/cmd/collectors/zapi/plugins/shelf"
 	"goharvest2/cmd/collectors/zapi/plugins/snapmirror"
 	"goharvest2/cmd/collectors/zapiperf/plugins/fcp"
@@ -412,6 +414,111 @@ func (me *Zapi) PollData() (*matrix.Matrix, error) {
 	return me.Matrix, nil
 }
 
+func (me *Zapi) CollectAutoSupport(p *collector.Payload) {
+	var exporterTypes []string
+	for _, exporter := range me.Exporters {
+		exporterTypes = append(exporterTypes, exporter.GetClass())
+	}
+
+	var counters = make([]string, 0)
+	if me.Params != nil {
+		c := me.Params.GetChildS("counters")
+		c.FlatList(&counters, "")
+	}
+
+	var schedules = make([]collector.Schedule, 0)
+	tasks := me.Params.GetChildS("schedule")
+	if tasks != nil && len(tasks.GetChildren()) > 0 {
+		for _, task := range tasks.GetChildren() {
+			schedules = append(schedules, collector.Schedule{
+				Name:     task.GetNameS(),
+				Schedule: task.GetContentS(),
+			})
+		}
+	}
+
+	clientTimeout := strconv.Itoa(client.DefaultTimeout)
+	clientNode := me.Params.GetChildS("client_timeout")
+	if clientNode != nil {
+		clientTimeout = clientNode.GetContentS()
+	}
+
+	// Add collector information
+	p.AddCollectorAsup(collector.AsupCollector{
+		Name:      me.Name,
+		Query:     me.Query,
+		BatchSize: me.batchSize,
+		Exporters: exporterTypes,
+		Counters: collector.Counters{
+			Count: len(counters),
+			List:  counters,
+		},
+		Schedules:     schedules,
+		ClientTimeout: clientTimeout,
+	})
+
+	if me.Name == "Zapi" && (me.Object == "Volume" || me.Object == "Node") {
+		p.Target.Version = me.GetHostVersion()
+		p.Target.Model = me.GetHostModel()
+		p.Target.Serial = me.GetHostUUID()
+		p.Target.ClusterUuid = me.Client.ClusterUuid()
+
+		md := me.GetMetadata()
+		info := collector.InstanceInfo{
+			Count:      md.LazyValueInt64("count", "instance"),
+			DataPoints: md.LazyValueInt64("count", "data"),
+			PollTime:   md.LazyValueInt64("poll_time", "data"),
+			ApiTime:    md.LazyValueInt64("api_time", "data"),
+			ParseTime:  md.LazyValueInt64("parse_time", "data"),
+			PluginTime: md.LazyValueInt64("plugin_time", "data"),
+		}
+
+		if me.Object == "Node" {
+			nodes, err := me.getNodeUuids()
+			if err != nil {
+				// log but don't return so the other info below is collected
+				me.Logger.Error().
+					Err(err).
+					Msg("Unable to get nodes.")
+				nodes = make([]string, 0)
+			}
+			info.Uuids = &nodes
+			p.Nodes = &info
+		} else if me.Object == "Volume" {
+			p.Volumes = &info
+		}
+	}
+}
+
+func (me *Zapi) getNodeUuids() ([]string, error) {
+	var (
+		response *node.Node
+		nodes    []*node.Node
+		err      error
+		uuids    []string
+	)
+
+	// 7-mode does not have this information
+	if !me.Client.IsClustered() {
+		return make([]string, 0), err
+	}
+	request := "cluster-node-get-iter"
+
+	if response, err = me.Client.InvokeRequestString(request); err != nil {
+		return nil, fmt.Errorf("failure invoking zapi: %s %w", request, err)
+	}
+
+	if attrs := response.GetChildS("attributes-list"); attrs != nil {
+		nodes = attrs.GetChildren()
+	}
+
+	for _, n := range nodes {
+		uuid := n.GetChildContentS("node-uuid")
+		uuids = append(uuids, uuid)
+	}
+	return uuids, nil
+}
+
 // Interface guards
 var (
 	_ collector.Collector = (*Zapi)(nil)
diff --git a/cmd/poller/collector/asup.go b/cmd/poller/collector/asup.go
new file mode 100644
index 00000000..3f85f3a6
--- /dev/null
+++ b/cmd/poller/collector/asup.go
@@ -0,0 +1,305 @@
+package collector
+
+import (
+	"context"
+	"crypto/sha1"
+	"encoding/hex"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/shirou/gopsutil/cpu"
+	"github.com/shirou/gopsutil/host"
+	"github.com/shirou/gopsutil/v3/mem"
+	"goharvest2/cmd/harvest/version"
+	"goharvest2/pkg/logging"
+	"goharvest2/pkg/matrix"
+	"os"
+	"os/exec"
+	"path"
+	"time"
+)
+
+type Payload struct {
+	Target     *TargetInfo
+	Harvest    *harvestInfo
+	Platform   *platformInfo
+	Nodes      *InstanceInfo
+	Volumes    *InstanceInfo
+	Collectors *[]AsupCollector
+	path       string
+}
+
+type TargetInfo struct {
+	Version     string
+	Model       string
+	Serial      string
+	Ping        float64
+	ClusterUuid string
+}
+
+type InstanceInfo struct {
+	Count      int64
+	DataPoints int64
+	PollTime   int64
+	ApiTime    int64
+	ParseTime  int64
+	PluginTime int64
+	Uuids      *[]string `json:"Uuids,omitempty"`
+}
+
+type platformInfo struct {
+	OS     string
+	Arch   string
+	Memory struct {
+		TotalKb     uint64
+		AvailableKb uint64
+		UsedKb      uint64
+	}
+	CPUs uint8
+}
+
+type harvestInfo struct {
+	HostHash    string
+	UUID        string
+	Version     string
+	Release     string
+	Commit      string
+	BuildDate   string
+	NumClusters uint8
+}
+
+type Counters struct {
+	Count int
+	List  []string
+}
+
+type Schedule struct {
+	Name     string
+	Schedule string
+}
+
+type AsupCollector struct {
+	Name          string
+	Query         string
+	BatchSize     string `json:"BatchSize,omitempty"`
+	ClientTimeout string
+	Schedules     []Schedule
+	Exporters     []string
+	Counters      Counters
+}
+
+const workingDir = "asup"
+
+func (p *Payload) AddCollectorAsup(a AsupCollector) {
+	if p.Collectors == nil {
+		p.Collectors = &[]AsupCollector{}
+	}
+	*p.Collectors = append(*p.Collectors, a)
+}
+
+func SendAutosupport(collectors []Collector, status *matrix.Matrix, pollerName string) error {
+
+	var (
+		msg *Payload
+		err error
+	)
+
+	if msg, err = BuildAndWriteAutoSupport(collectors, status, pollerName); err != nil {
+		return fmt.Errorf("failed to build ASUP message poller:%s %w", pollerName, err)
+	}
+
+	if err = sendAsupMessage(msg); err != nil {
+		return fmt.Errorf("failed to send ASUP message poller:%s %w", pollerName, err)
+	}
+
+	return nil
+}
+
+// This function forks the autosupport binary
+func sendAsupMessage(msg *Payload) error {
+	err := sendAsupVia(msg, "./bin/asup")
+	if errors.Is(err, os.ErrNotExist) {
+		err = sendAsupVia(msg, "../harvest-private/harvest-asup/bin/asup")
+	}
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func sendAsupVia(msg *Payload, asupExecPath string) error {
+	asupTimeOutLimit := 10 * time.Second
+
+	// Invoke autosupport binary
+	cont, cancel := context.WithTimeout(context.Background(), asupTimeOutLimit)
+	defer cancel()
+	logging.Get().Info().
+		Str("payloadPath", msg.path).
+		Msg("Fork autosupport binary.")
+
+	exitStatus := 0
+	err := exec.CommandContext(cont, asupExecPath, "--payload", msg.path, "--working-dir", workingDir).Run()
+	if err != nil {
+		if exitError, ok := err.(*exec.ExitError); ok {
+			exitStatus = exitError.ExitCode()
+		}
+	}
+
+	// make sure to timeout after x minutes, kill that process
+	if errors.Is(cont.Err(), context.DeadlineExceeded) {
+		return fmt.Errorf("autosupport call to %s timed out:%w", asupExecPath, err)
+	}
+
+	if err != nil {
+		logging.Get().Error().
+			Err(err).
+			Str("payloadPath", msg.path).
+			Msg("Unable to execute autosupport binary")
+		return err
+	}
+
+	logging.Get().Info().
+		Str("payloadPath", msg.path).
+		Int("exitStatus", exitStatus).
+		Msg("Autosupport binary forked successfully.")
+
+	return nil
+}
+
+func BuildAndWriteAutoSupport(collectors []Collector, status *matrix.Matrix, pollerName string) (*Payload, error) {
+
+	var (
+		msg  *Payload
+		arch string
+		cpus uint8
+	)
+
+	// add info about platform (where Harvest is running)
+	arch, cpus = getCPUInfo()
+	msg = &Payload{
+		Platform: &platformInfo{
+			Arch: arch,
+			CPUs: cpus,
+			OS:   getOSName(),
+		},
+		Target: &TargetInfo{
+			Ping: status.LazyValueFloat64("ping", "host"),
+		},
+	}
+	attachMemory(msg)
+
+	// give each collector the opportunity to attach autosupport information
+	for _, c := range collectors {
+		c.CollectAutoSupport(msg)
+	}
+
+	hostname, _ := os.Hostname()
+	// add harvest release info
+	msg.Harvest = &harvestInfo{
+		// harvest uuid creation from sha1 of cluster uuid
+		UUID:        sha1Sum(msg.Target.ClusterUuid),
+		Version:     version.VERSION,
+		Release:     version.Release,
+		Commit:      version.Commit,
+		BuildDate:   version.BuildDate,
+		HostHash:    sha1Sum(hostname),
+		NumClusters: 1,
+	}
+	payloadPath, err := writeAutoSupport(msg, pollerName)
+	if err != nil {
+		return nil, err
+	}
+	msg.path = payloadPath
+	return msg, nil
+}
+
+func writeAutoSupport(msg *Payload, pollerName string) (string, error) {
+	var (
+		payloadPath string
+		err         error
+	)
+
+	if payloadPath, err = getPayloadPath(workingDir, pollerName); err != nil {
+		return "", err
+	}
+
+	// name of the file: {poller_name}_payload.json
+	file, err := os.OpenFile(payloadPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
+	if err != nil {
+		return "", fmt.Errorf("autosupport failed to open payloadPath:%s %w", payloadPath, err)
+	}
+	defer func(file *os.File) {
+		_ = file.Close()
+	}(file)
+	encoder := json.NewEncoder(file)
+	encoder.SetIndent("", " ")
+	if err = encoder.Encode(msg); err != nil {
+		return "", fmt.Errorf("autosupport failed to encode payloadPath:%s %w", payloadPath, err)
+	}
+	return payloadPath, nil
+}
+
+func attachMemory(msg *Payload) {
+	virtualMemory, err := mem.VirtualMemory()
+	if err != nil {
+		return
+	}
+	msg.Platform.Memory.TotalKb = virtualMemory.Total / 1024
+	msg.Platform.Memory.AvailableKb = virtualMemory.Available / 1024
+	msg.Platform.Memory.UsedKb = virtualMemory.Used / 1024
+}
+
+func getCPUInfo() (string, uint8) {
+
+	var (
+		arch     string
+		cpuCount int
+		cpuInfo  []cpu.InfoStat
+		hostInfo *host.InfoStat
+		err      error
+	)
+
+	if cpuInfo, err = cpu.Info(); err == nil {
+		if cpuInfo != nil {
+			cpuCount = len(cpuInfo)
+		}
+	}
+
+	if hostInfo, err = host.Info(); err == nil {
+		if hostInfo != nil {
+			arch = (*hostInfo).Platform
+		}
+	}
+
+	return arch, uint8(cpuCount)
+}
+
+func getOSName() string {
+	info, err := host.Info()
+	if err != nil {
+		return ""
+	}
+	return info.OS
+}
+
+// Gives asup payload json file path based on input.
+// Ex. asupDir = asup, pollerName = poller-1
+// o/p would be asup/payload/poller-1_payload.json
+func getPayloadPath(asupDir string, pollerName string) (string, error) {
+	payloadDir := path.Join(asupDir, "payload")
+
+	// Create the asup payload directory if needed
+	if _, err := os.Stat(payloadDir); os.IsNotExist(err) {
+		if err = os.MkdirAll(payloadDir, 0777); err != nil {
+			return "", fmt.Errorf("could not create asup payload directory %s: %w", payloadDir, err)
+		}
+	}
+
+	return path.Join(payloadDir, fmt.Sprintf("%s_%s", pollerName, "payload.json")), nil
+}
+
+func sha1Sum(s string) string {
+	hash := sha1.New()
+	hash.Write([]byte(s))
+	return hex.EncodeToString(hash.Sum(nil))
+}
diff --git a/cmd/poller/collector/collector.go b/cmd/poller/collector/collector.go
index 8d27caeb..4ee6d850 100644
--- a/cmd/poller/collector/collector.go
+++ b/cmd/poller/collector/collector.go
@@ -8,7 +8,7 @@
 	A Harvest collector should normally "inherit" all these
 	attributes and implement only the PollData function.
 	The AbstractCollector will make sure that the collector
-	is properly initializied, metadata are updated and
+	is properly initialized, metadata are updated and
 	data poll(s) and plugins run as scheduled. The collector
 	can also choose to override any of the attributes
 	implemented by AbstractCollector.
@@ -49,10 +49,6 @@ type Collector interface {
 	GetObject() string
 	GetParams() *node.Node
 	GetOptions() *options.Options
-	GetMetadata() *matrix.Matrix
-	GetHostVersion() string
-	GetHostModel() string
-	GetHostUUID() string
 	GetCollectCount() uint64
 	AddCollectCount(uint64)
 	GetStatus() (uint8, string, string)
@@ -64,6 +60,7 @@ type Collector interface {
 	LinkExporter(exporter.Exporter)
 	LoadPlugins(*node.Node, Collector) error
 	LoadPlugin(string, *plugin.AbstractPlugin) plugin.Plugin
+	CollectAutoSupport(p *Payload)
 }
 
 // Status defines the possible states of a collector
@@ -218,8 +215,6 @@ func Init(c Collector) error {
 	md.NewMetricInt64("parse_time")
 	md.NewMetricInt64("calc_time")
 	md.NewMetricInt64("plugin_time")
-	md.NewMetricInt64("content_length")
-	md.NewMetricFloat64("api_time_percent")
 	md.NewMetricUint64("count")
 	//md.AddLabel("task", "")
 	//md.AddLabel("interval", "")
@@ -274,7 +269,9 @@ func (me *AbstractCollector) Start(wg *sync.WaitGroup) {
 
 	for {
 
-		me.Metadata.Reset()
+		// We can't reset metadata here because autosupport metadata is reset
+		// https://github.com/NetApp/harvest-private/issues/114 for details
+		//me.Metadata.Reset()
 
 		results := make([]*matrix.Matrix, 0)
 
@@ -289,6 +286,9 @@ func (me *AbstractCollector) Start(wg *sync.WaitGroup) {
 				taskTime, pluginTime time.Duration
 			)
 
+			// reset task metadata
+			me.Metadata.ResetInstance(task.Name)
+
 			start = time.Now()
 			data, err := task.Run()
 			taskTime = time.Since(start)
@@ -310,6 +310,10 @@ func (me *AbstractCollector) Start(wg *sync.WaitGroup) {
 						//logger.Error(me.Prefix, err.Error())
 						me.Logger.Warn().Msgf("target unreachable, entering standby mode (retry to connect in %d s)", retryDelay)
 					}
+					me.Logger.Debug().
+						Int("retryDelay", retryDelay).
+						Err(err).
+						Msg("Target unreachable, entering standby mode (retry in retryDelay s)")
 					me.Schedule.SetStandByMode(task, time.Duration(retryDelay)*time.Second)
 					me.SetStatus(1, errors.ERR_CONNECTION)
 				// there are no instances to collect
@@ -337,6 +341,7 @@ func (me *AbstractCollector) Start(wg *sync.WaitGroup) {
 			} else if me.Schedule.IsStandBy() {
 				// recover from standby mode
 				me.Schedule.Recover()
+				retryDelay = 1
 				me.SetStatus(0, "running")
 				me.Logger.Info().Msg("recovered from standby mode, back to normal schedule")
 			}
@@ -363,16 +368,11 @@ func (me *AbstractCollector) Start(wg *sync.WaitGroup) {
 					pluginTime = time.Since(pluginStart)
 					me.Metadata.LazySetValueInt64("plugin_time", task.Name, pluginTime.Microseconds())
 				}
-
-				// update some metadata
-				me.Metadata.LazySetValueInt64("poll_time", task.Name, task.GetDuration().Microseconds())
-				me.Metadata.LazySetValueInt64("task_time", task.Name, taskTime.Microseconds())
-
-				if apiTime, ok := me.Metadata.LazyGetValueInt64("api_time", task.Name); ok && apiTime != 0 {
-					me.Metadata.LazySetValueFloat64("api_time_percent", task.Name, float64(apiTime)/float64(taskTime.Microseconds())*100)
-				}
-
 			}
+
+			// update task metadata
+			me.Metadata.LazySetValueInt64("poll_time", task.Name, task.GetDuration().Microseconds())
+			me.Metadata.LazySetValueInt64("task_time", task.Name, taskTime.Microseconds())
 		}
 
 		// pass results to exporters
@@ -482,7 +482,7 @@ func (me *AbstractCollector) SetMetadata(m *matrix.Matrix) {
 	me.Metadata = m
 }
 
-// WantedExporters retrievs the names of the exporters to which the collector
+// WantedExporters retrieves the names of the exporters to which the collector
 // needs to export data
 func (me *AbstractCollector) WantedExporters(configFp string) []string {
 	names, err := conf.GetUniqueExporters(me.Params, configFp)
@@ -537,3 +537,7 @@ func (me *AbstractCollector) LoadPlugins(params *node.Node, c Collector) error {
 	me.Logger.Debug().Msgf("initialized %d plugins", len(me.Plugins))
 	return nil
 }
+
+// CollectAutoSupport allows a Collector to add autosupport information
+func (me *AbstractCollector) CollectAutoSupport(_ *Payload) {
+}
diff --git a/cmd/poller/poller.go b/cmd/poller/poller.go
index 6ba00c58..00e95cc5 100644
--- a/cmd/poller/poller.go
+++ b/cmd/poller/poller.go
@@ -38,7 +38,6 @@ import (
 	"goharvest2/cmd/poller/options"
 	"goharvest2/cmd/poller/plugin"
 	"goharvest2/cmd/poller/schedule"
-	"goharvest2/cmd/tools/asup"
 	"goharvest2/pkg/conf"
 	"goharvest2/pkg/errors"
 	"goharvest2/pkg/logging"
@@ -57,6 +56,7 @@ import (
 	"strings"
 	"sync"
 	"syscall"
+	"time"
 )
 
 // default params
@@ -67,6 +67,7 @@ var (
 	logMaxBackups   = logging.DefaultLogMaxBackups
 	logMaxAge       = logging.DefaultLogMaxAge
 	asupSchedule    = "24h" // send every 24 hours
+	asupFirstWrite  = "4m"  // after this time, write 1st autosupport payload (for testing)
 )
 
 // init with default configuration by default it gets logged both to console and  harvest.log
@@ -296,6 +297,19 @@ func (p *Poller) Init() error {
 		logger.Info().Msgf("Autosupport is disabled")
 	} else {
 		if p.targetIsOntap() {
+			// Write the payload after asupFirstWrite.
+			// This is to examine the autosupport contents
+			// Nothing is sent, sending happens based on the asupSchedule
+			duration, err := time.ParseDuration(asupFirstWrite)
+			if err != nil {
+				logger.Error().Err(err).
+					Str("asupFirstWrite", asupFirstWrite).
+					Msg("Failed to write 1st autosupport payload.")
+			} else {
+				time.AfterFunc(duration, func() {
+					p.firstAutoSupport()
+				})
+			}
 			if err = p.schedule.NewTaskString("asup", asupSchedule, p.startAsup, p.options.Asup); err != nil {
 				return err
 			}
@@ -314,9 +328,20 @@ func (p *Poller) Init() error {
 
 }
 
+func (p *Poller) firstAutoSupport() {
+	if p.collectors == nil {
+		return
+	}
+	if _, err := collector.BuildAndWriteAutoSupport(p.collectors, p.status, p.name); err != nil {
+		logger.Error().Err(err).
+			Str("poller", p.name).
+			Msg("First autosupport failed.")
+	}
+}
+
 func (p *Poller) startAsup() (*matrix.Matrix, error) {
 	if p.collectors != nil {
-		if err := asup.DoAsupMessage(p.options.Config, p.collectors, p.status, p.name); err != nil {
+		if err := collector.SendAutosupport(p.collectors, p.status, p.name); err != nil {
 			logger.Error().Err(err).
 				Str("poller", p.name).
 				Msg("Start autosupport failed.")
@@ -519,7 +544,7 @@ func (p *Poller) loadCollector(c conf.Collector, object string) error {
 		for _, t := range *c.Templates {
 			if subTemplate, err = collector.ImportTemplate(p.options.HomePath, t, class); err != nil {
 				logger.Warn().
-					Err(err).
+					Str("err", err.Error()).
 					Msg("Unable to load template.")
 				continue
 			}
diff --git a/cmd/tools/asup/asup.go b/cmd/tools/asup/asup.go
deleted file mode 100644
index 0ac761c4..00000000
--- a/cmd/tools/asup/asup.go
+++ /dev/null
@@ -1,441 +0,0 @@
-package asup
-
-import (
-	"context"
-	"crypto/sha1"
-	"encoding/hex"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"github.com/shirou/gopsutil/cpu"
-	"github.com/shirou/gopsutil/host"
-	"github.com/shirou/gopsutil/v3/mem"
-	"goharvest2/cmd/harvest/version"
-	"goharvest2/cmd/poller/collector"
-	client "goharvest2/pkg/api/ontapi/zapi"
-	"goharvest2/pkg/conf"
-	"goharvest2/pkg/logging"
-	"goharvest2/pkg/matrix"
-	"goharvest2/pkg/tree/node"
-	"os"
-	"os/exec"
-	"path"
-	"time"
-)
-
-type asupMessage struct {
-	Target   *targetInfo
-	Nodes    *NodeInstanceInfo
-	Volumes  *instanceInfo
-	Svms     *instanceInfo
-	Platform *platformInfo
-	Harvest  *harvestInfo
-}
-
-type targetInfo struct {
-	Version     string
-	Model       string
-	Serial      string
-	Ping        float64
-	ClusterUuid string
-}
-
-type NodeInstanceInfo struct {
-	Count      int64
-	DataPoints int64
-	PollTime   int64
-	ApiTime    int64
-	ParseTime  int64
-	PluginTime int64
-	NodeUuid   []string
-}
-
-type instanceInfo struct {
-	Count      int64
-	DataPoints int64
-	PollTime   int64
-	ApiTime    int64
-	ParseTime  int64
-	PluginTime int64
-}
-
-type platformInfo struct {
-	OS       string
-	Arch     string
-	MemoryKb uint64
-	CPUs     uint8
-}
-
-type harvestInfo struct {
-	UUID        string
-	Version     string
-	Release     string
-	Commit      string
-	BuildDate   string
-	NumClusters uint8
-}
-
-func DoAsupMessage(config string, collectors []collector.Collector, status *matrix.Matrix, pollerName string) error {
-
-	var (
-		msg *asupMessage
-		err error
-	)
-
-	connection := getdata(config, pollerName)
-
-	if msg, err = buildAsupMessage(collectors, status, connection); err != nil {
-		return fmt.Errorf("failed to build ASUP message poller:%s %w", pollerName, err)
-	}
-
-	if err = sendAsupMessage(msg, pollerName); err != nil {
-		return fmt.Errorf("failed to send ASUP message poller:%s %w", pollerName, err)
-	}
-
-	return nil
-}
-
-// This function forks the autosupport binary
-func sendAsupMessage(msg *asupMessage, pollerName string) error {
-	err := sendAsupVia(msg, pollerName, "./bin/asup")
-	if errors.Is(err, os.ErrNotExist) {
-		err = sendAsupVia(msg, pollerName, "../harvest-private/harvest-asup/bin/asup")
-	}
-	if err != nil {
-		return err
-	}
-	return nil
-}
-
-func sendAsupVia(msg *asupMessage, pollerName string, asupExecPath string) error {
-	var (
-		payloadPath string
-		err         error
-	)
-	asupTimeOutLimit := 10 * time.Second
-	workingDir := "asup"
-
-	if payloadPath, err = getPayloadPath(workingDir, pollerName); err != nil {
-		return err
-	}
-
-	// name of the file: {poller_name}_payload.json
-	file, err := os.OpenFile(payloadPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
-	if err != nil {
-		return fmt.Errorf("autosupport failed to open payloadPath:%s %w", payloadPath, err)
-	}
-	defer file.Close()
-	encoder := json.NewEncoder(file)
-	encoder.SetIndent("", " ")
-	if err = encoder.Encode(msg); err != nil {
-		return fmt.Errorf("autosupport failed to encode payloadPath:%s %w", payloadPath, err)
-	}
-
-	// Invoke autosupport binary
-	cont, cancel := context.WithTimeout(context.Background(), asupTimeOutLimit)
-	defer cancel()
-	logging.Get().Info().
-		Str("payloadPath", payloadPath).
-		Msg("Fork autosupport binary.")
-
-	out, err := exec.CommandContext(cont, asupExecPath, "--payload", payloadPath, "--working-dir", workingDir).Output()
-
-	// make sure to timeout after x minutes, kill that process
-	if errors.Is(cont.Err(), context.DeadlineExceeded) {
-		return fmt.Errorf("autosupport call to %s timed out:%w", asupExecPath, err)
-	}
-
-	if err != nil {
-		logging.Get().Error().
-			Err(err).
-			Str("payloadPath", payloadPath).
-			Msg("Unable to execute autosupport binary")
-		return err
-	}
-
-	logging.Get().Info().
-		Str("payloadPath", payloadPath).
-		Str("out", string(out)).
-		Msg("Autosupport binary forked successfully.")
-
-	return nil
-}
-
-func buildAsupMessage(collectors []collector.Collector, status *matrix.Matrix, connection *client.Client) (*asupMessage, error) {
-
-	var (
-		msg  *asupMessage
-		arch string
-		cpus uint8
-	)
-
-	msg = new(asupMessage)
-
-	// add info about platform (where Harvest is running)
-	msg.Platform = new(platformInfo)
-	arch, cpus = getCPUInfo()
-	msg.Platform.Arch = arch
-	msg.Platform.CPUs = cpus
-	msg.Platform.MemoryKb = getRamSize()
-	msg.Platform.OS = getOSName()
-
-	// info about ONTAP host and instances
-	msg.Target, msg.Nodes, msg.Volumes, msg.Svms = getInstanceInfo(collectors, status, connection)
-
-	// add harvest release info
-	msg.Harvest = new(harvestInfo)
-	// harvest uuid creation from sha1 of cluster uuid
-	msg.Harvest.UUID = getSha1Uuid(msg.Target.ClusterUuid)
-	msg.Harvest.Version = version.VERSION
-	msg.Harvest.Release = version.Release
-	msg.Harvest.Commit = version.Commit
-	msg.Harvest.BuildDate = version.BuildDate
-	msg.Harvest.NumClusters = getNumClusters(collectors)
-	return msg, nil
-}
-
-func getInstanceInfo(collectors []collector.Collector, status *matrix.Matrix, connection *client.Client) (*targetInfo, *NodeInstanceInfo, *instanceInfo, *instanceInfo) {
-	target := new(targetInfo)
-	nodes := new(NodeInstanceInfo)
-	vols := new(instanceInfo)
-	svms := new(instanceInfo)
-
-	// get ping value from poller metadata
-	target.Ping, _ = status.LazyGetValueFloat64("ping", "host")
-
-	// scan collectors
-	for _, c := range collectors {
-		if c.GetName() == "Zapi" {
-			if c.GetObject() == "Node" {
-				md := c.GetMetadata()
-
-				nodes.getNodeInfo(md, connection)
-
-				target.Version = c.GetHostVersion()
-				target.Model = c.GetHostModel()
-				target.Serial = c.GetHostUUID()
-				target.getClusterInfo(connection)
-
-			} else if c.GetObject() == "Volume" {
-				md := c.GetMetadata()
-				vols.Count, _ = md.LazyGetValueInt64("count", "instance")
-				vols.DataPoints, _ = md.LazyGetValueInt64("count", "data")
-				vols.PollTime, _ = md.LazyGetValueInt64("poll_time", "data")
-				vols.ApiTime, _ = md.LazyGetValueInt64("api_time", "data")
-				vols.ParseTime, _ = md.LazyGetValueInt64("parse_time", "data")
-				vols.PluginTime, _ = md.LazyGetValueInt64("plugin_time", "data")
-
-				//} else if c.GetObject() == "Svm" {
-				//	md := c.GetMetadata()
-				//	svms.Count, _ = md.LazyGetValueInt64("count", "instance")
-				//	svms.DataPoints, _ = md.LazyGetValueInt64("count", "data")
-				//	svms.PollTime, _ = md.LazyGetValueInt64("poll_time", "data")
-				//	svms.ApiTime, _ = md.LazyGetValueInt64("api_time", "data")
-				//	svms.ParseTime, _ = md.LazyGetValueInt64("parse_time", "data")
-				//	svms.PluginTime, _ = md.LazyGetValueInt64("plugin_time", "data")
-			}
-		} else if c.GetName() == "ZapiPerf" {
-			// TODO: SVM data population
-			if c.GetObject() == "Svm" {
-				md := c.GetMetadata()
-				svms.Count, _ = md.LazyGetValueInt64("count", "instance")
-				svms.DataPoints, _ = md.LazyGetValueInt64("count", "data")
-				svms.PollTime, _ = md.LazyGetValueInt64("poll_time", "data")
-				svms.ApiTime, _ = md.LazyGetValueInt64("api_time", "data")
-				svms.ParseTime, _ = md.LazyGetValueInt64("parse_time", "data")
-				svms.PluginTime, _ = md.LazyGetValueInt64("plugin_time", "data")
-			}
-		}
-	}
-
-	return target, nodes, vols, svms
-}
-
-func getCPUInfo() (string, uint8) {
-
-	var (
-		arch     string
-		cpuCount int
-		cpuinfo  []cpu.InfoStat
-		hostinfo *host.InfoStat
-		err      error
-	)
-
-	if cpuinfo, err = cpu.Info(); err == nil {
-		if cpuinfo != nil {
-			cpuCount = len(cpuinfo)
-		}
-	}
-
-	if hostinfo, err = host.Info(); err == nil {
-		if hostinfo != nil {
-			arch = (*hostinfo).Platform
-		}
-	}
-
-	return arch, uint8(cpuCount)
-}
-
-func getRamSize() uint64 {
-
-	var (
-		//output           []byte
-		err error
-		//line, sizeString string
-		//fields           []string
-		memory *mem.VirtualMemoryStat
-		size   uint64
-	)
-
-	if memory, err = mem.VirtualMemory(); err == nil {
-		fmt.Printf("%s", *memory)
-		size = memory.Free / 1024
-	}
-
-	return size
-}
-
-func getOSName() string {
-	info, err := host.Info()
-	if err != nil {
-		return ""
-	}
-	return info.OS
-}
-
-func getNumClusters(collectors []collector.Collector) uint8 {
-	var count uint8
-
-	for _, c := range collectors {
-		if c.GetName() == "Zapi" || c.GetName() == "ZapiPerf" {
-			count++
-			break
-		}
-	}
-
-	return count
-}
-
-// Gives asup payload json file path based on input.
-// Ex. asupDir = asup, pollerName = poller-1
-// o/p would be asup/payload/poller-1_payload.json
-func getPayloadPath(asupDir string, pollerName string) (string, error) {
-	payloadDir := path.Join(asupDir, "payload")
-
-	// Create the asup payload directory if needed
-	if _, err := os.Stat(payloadDir); os.IsNotExist(err) {
-		if err = os.MkdirAll(payloadDir, 0777); err != nil {
-			return "", fmt.Errorf("could not create asup payload directory %s: %w", payloadDir, err)
-		}
-	}
-
-	return path.Join(payloadDir, fmt.Sprintf("%s_%s", pollerName, "payload.json")), nil
-}
-
-func getClusterNodeInfo(client *client.Client) ([]string, error) {
-	var (
-		response *node.Node
-		nodes    []*node.Node
-		err      error
-		uuids    []string
-	)
-
-	request := "cluster-node-get-iter"
-
-	if response, err = client.InvokeRequestString(request); err != nil {
-		return nil, fmt.Errorf("failure invoking zapi: %s %w", request, err)
-	}
-
-	if attrs := response.GetChildS("attributes-list"); attrs != nil {
-		nodes = attrs.GetChildren()
-	}
-
-	for _, n := range nodes {
-		uuid := n.GetChildContentS("node-uuid")
-		uuids = append(uuids, uuid)
-	}
-
-	return uuids, nil
-}
-
-func (target *targetInfo) getClusterInfo(connection *client.Client) error {
-	var (
-		response *node.Node
-		err      error
-	)
-
-	isClustered := target.Model == "cdot"
-	// fetch system name and serial number
-	request := "cluster-identity-get"
-	if !isClustered {
-		request = "system-get-info"
-	}
-
-	if response, err = connection.InvokeRequestString(request); err != nil {
-		return fmt.Errorf("failure invoking zapi: %s %w", request, err)
-	}
-
-	if isClustered {
-		if attrs := response.GetChildS("attributes"); attrs != nil {
-			if info := attrs.GetChildS("cluster-identity-info"); info != nil {
-				target.ClusterUuid = info.GetChildContentS("cluster-uuid")
-			}
-		}
-	} else {
-		if info := response.GetChildS("system-info"); info != nil {
-			// There is no uuid for non cluster mode, using system-id.
-			target.ClusterUuid = info.GetChildContentS("system-id")
-		}
-	}
-	return nil
-}
-
-func (node *NodeInstanceInfo) getNodeInfo(md *matrix.Matrix, connection *client.Client) error {
-	var uuids []string
-	var err error
-	if uuids, err = getClusterNodeInfo(connection); err != nil {
-		fmt.Printf("issue while fetching node uuids")
-	}
-	node.Count, _ = md.LazyGetValueInt64("count", "instance")
-	node.DataPoints, _ = md.LazyGetValueInt64("count", "data")
-	node.PollTime, _ = md.LazyGetValueInt64("poll_time", "data")
-	node.ApiTime, _ = md.LazyGetValueInt64("api_time", "data")
-	node.ParseTime, _ = md.LazyGetValueInt64("parse_time", "data")
-	node.PluginTime, _ = md.LazyGetValueInt64("plugin_time", "data")
-	node.NodeUuid = uuids
-	return nil
-}
-
-func getdata(config, pollername string) *client.Client {
-	var (
-		params     *node.Node
-		err        error
-		connection *client.Client
-	)
-
-	if params, err = conf.GetPoller(config, pollername); err != nil {
-		fmt.Println(err)
-		os.Exit(1)
-	}
-
-	if connection, err = client.New(params); err != nil {
-		fmt.Println(err)
-		os.Exit(1)
-	}
-
-	if err = connection.Init(2); err != nil {
-		fmt.Println(err)
-		os.Exit(1)
-	}
-
-	return connection
-}
-
-func getSha1Uuid(clusterUuid string) string {
-	shaHash := sha1.New()
-	if _, err := shaHash.Write([]byte(clusterUuid)); err != nil {
-		fmt.Printf("issue while invoking sha1 of uuid")
-		return ""
-	}
-	return hex.EncodeToString(shaHash.Sum(nil))
-}
diff --git a/conf/zapi/7mode/8.6.0/aggr.yaml b/conf/zapi/7mode/8.6.0/aggr.yaml
index 835a0b81..c8a494a2 100644
--- a/conf/zapi/7mode/8.6.0/aggr.yaml
+++ b/conf/zapi/7mode/8.6.0/aggr.yaml
@@ -50,8 +50,10 @@ counters:
             - snapshot-size-used                    => snapshot_size_used
 
 plugins:
-  - LabelAgent:
+  LabelAgent:
     value_mapping: status state online `1`
+    # metric label zapi_value rest_value `default_value`
+    value_to_num: new_status state online online `0`
 
 export_options:
   instance_keys:
diff --git a/conf/zapi/7mode/8.6.0/disk.yaml b/conf/zapi/7mode/8.6.0/disk.yaml
index d61b8f8d..d0ebbbda 100644
--- a/conf/zapi/7mode/8.6.0/disk.yaml
+++ b/conf/zapi/7mode/8.6.0/disk.yaml
@@ -23,6 +23,8 @@ counters:
 plugins:
   - LabelAgent:
     value_mapping: status offline false `0`
+    # metric label zapi_value rest_value `default_value`
+    value_to_num: new_status offline - - `0` #ok_value is empty value, '-' would be converted to blank while processing.
 
 export_options:
   instance_keys:
diff --git a/conf/zapi/7mode/8.6.0/node.yaml b/conf/zapi/7mode/8.6.0/node.yaml
index 243cd92d..a113daea 100644
--- a/conf/zapi/7mode/8.6.0/node.yaml
+++ b/conf/zapi/7mode/8.6.0/node.yaml
@@ -19,6 +19,8 @@ counters:
 plugins:
   - LabelAgent:
     value_mapping: status healthy true `1`
+    # metric label zapi_value rest_value `default_value`
+    value_to_num: new_status healthy true up `0`
 
 export_options:
   require_instance_keys: false
diff --git a/conf/zapi/7mode/8.6.0/shelf.yaml b/conf/zapi/7mode/8.6.0/shelf.yaml
index df840290..74295bdb 100644
--- a/conf/zapi/7mode/8.6.0/shelf.yaml
+++ b/conf/zapi/7mode/8.6.0/shelf.yaml
@@ -71,6 +71,8 @@ plugins:
 #        - ^power-supply-is-not-installed
   LabelAgent:
     value_mapping: status state normal `1`
+    # metric label zapi_value rest_value `default_value`
+    value_to_num: new_status state normal ok `0`
 
 export_options:
   instance_keys:
diff --git a/conf/zapi/7mode/8.6.0/status.yaml b/conf/zapi/7mode/8.6.0/status.yaml
index 17de61eb..770b855a 100644
--- a/conf/zapi/7mode/8.6.0/status.yaml
+++ b/conf/zapi/7mode/8.6.0/status.yaml
@@ -14,6 +14,8 @@ no_max_records: true
 plugins:
   - LabelAgent:
     value_mapping: status status ok `1`
+    # metric label zapi_value rest_value `default_value`
+    value_to_num: new_status status ok ok `0`
 
 export_options:
   include_all_labels: true
diff --git a/conf/zapi/7mode/8.6.0/subsystem.yaml b/conf/zapi/7mode/8.6.0/subsystem.yaml
index 22cec314..665cb34a 100644
--- a/conf/zapi/7mode/8.6.0/subsystem.yaml
+++ b/conf/zapi/7mode/8.6.0/subsystem.yaml
@@ -14,6 +14,8 @@ counters:
 plugins:
   - LabelAgent:
     value_mapping: status health ok `1`
+    # metric label zapi_value rest_value `default_value`
+    value_to_num: new_status health ok todo `0`  # REST gap will be filled up later.
 
 export_options:
   instance_keys:
diff --git a/conf/zapi/7mode/8.6.0/volume.yaml b/conf/zapi/7mode/8.6.0/volume.yaml
index 88efe279..61a8199d 100644
--- a/conf/zapi/7mode/8.6.0/volume.yaml
+++ b/conf/zapi/7mode/8.6.0/volume.yaml
@@ -31,6 +31,8 @@ counters:
 plugins:
   LabelAgent:
     value_mapping: status state online `1`
+    # metric label zapi_value rest_value `default_value`
+    value_to_num: new_status state online online `0`
 
 export_options:
   instance_keys:
diff --git a/conf/zapiperf/7mode/8.2.5/cifs_node.yaml b/conf/zapiperf/7mode/8.2.5/cifs_node.yaml
index b2f70c81..1835a08b 100644
--- a/conf/zapiperf/7mode/8.2.5/cifs_node.yaml
+++ b/conf/zapiperf/7mode/8.2.5/cifs_node.yaml
@@ -2,6 +2,7 @@
 name:                     CIFSNode
 query:                    cifs
 object:                   node_cifs
+instance_key:             name
 
 counters:
   - instance_name            => node
diff --git a/conf/zapiperf/7mode/8.2.5/fcp.yaml b/conf/zapiperf/7mode/8.2.5/fcp.yaml
index e24481fa..497487fd 100644
--- a/conf/zapiperf/7mode/8.2.5/fcp.yaml
+++ b/conf/zapiperf/7mode/8.2.5/fcp.yaml
@@ -4,7 +4,7 @@ name:                     FcpPort
 query:                    fcp
 object:                   fcp
 
-instance_key:             uuid
+instance_key:             name
 
 counters:
   - instance_name           => port
diff --git a/conf/zapiperf/7mode/8.2.5/lun.yaml b/conf/zapiperf/7mode/8.2.5/lun.yaml
index af065c9d..420c80ee 100644
--- a/conf/zapiperf/7mode/8.2.5/lun.yaml
+++ b/conf/zapiperf/7mode/8.2.5/lun.yaml
@@ -2,7 +2,7 @@
 name:                     Lun
 query:                    lun
 object:                   lun
-
+instance_key:             name
 counters:
   - instance_name
   - read_data
diff --git a/conf/zapiperf/7mode/8.2.5/nfsv3_node.yaml b/conf/zapiperf/7mode/8.2.5/nfsv3_node.yaml
index 8405cca9..280ad4d9 100644
--- a/conf/zapiperf/7mode/8.2.5/nfsv3_node.yaml
+++ b/conf/zapiperf/7mode/8.2.5/nfsv3_node.yaml
@@ -2,6 +2,7 @@
 name:                     NFSv3Node
 query:                    nfsv3
 object:                   node_nfs
+instance_key:             name
 
 global_labels:
   - nfsv: v3
diff --git a/conf/zapiperf/7mode/8.2.5/nfsv4_node.yaml b/conf/zapiperf/7mode/8.2.5/nfsv4_node.yaml
index 13eee749..2bd08d99 100644
--- a/conf/zapiperf/7mode/8.2.5/nfsv4_node.yaml
+++ b/conf/zapiperf/7mode/8.2.5/nfsv4_node.yaml
@@ -2,6 +2,7 @@
 name:                     NFSv4Node
 query:                    nfsv4
 object:                   node_nfs
+instance_key:             name
 
 global_labels:
   - nfsv: v4
diff --git a/conf/zapiperf/7mode/8.2.5/system_node.yaml b/conf/zapiperf/7mode/8.2.5/system_node.yaml
index 571c9968..ff3bc318 100644
--- a/conf/zapiperf/7mode/8.2.5/system_node.yaml
+++ b/conf/zapiperf/7mode/8.2.5/system_node.yaml
@@ -8,6 +8,7 @@ instance_key:             name
 counters:
   - instance_name         => node
   - avg_processor_busy
+  - cpu_busy
   - cpu_elapsed_time
   - uptime
   - total_ops
diff --git a/conf/zapiperf/7mode/8.2.5/volume.yaml b/conf/zapiperf/7mode/8.2.5/volume.yaml
new file mode 100644
index 00000000..876c8d4f
--- /dev/null
+++ b/conf/zapiperf/7mode/8.2.5/volume.yaml
@@ -0,0 +1,31 @@
+name: Volume
+query: volume
+object: volume
+
+instance_key: name
+
+counters:
+  - instance_uuid
+  - instance_name
+  - vserver_name          => svm
+  - node_name             => node
+  - parent_aggr           => aggr
+  - read_data
+  - write_data
+  - read_ops
+  - write_ops
+  - other_ops
+  - total_ops
+  - read_latency
+  - write_latency
+  - other_latency
+  - avg_latency
+
+plugins:
+  - Volume
+
+export_options:
+  instance_keys:
+    - volume
+    - aggr
+    - type
\ No newline at end of file
diff --git a/conf/zapiperf/7mode/8.2.5/volume_node.yaml b/conf/zapiperf/7mode/8.2.5/volume_node.yaml
index 97596332..0038e12f 100644
--- a/conf/zapiperf/7mode/8.2.5/volume_node.yaml
+++ b/conf/zapiperf/7mode/8.2.5/volume_node.yaml
@@ -1,8 +1,8 @@
 
 name:                     VolumeNode
 query:                    volume
-object:                   volume
-
+object:                   node_vol
+instance_key:             name
 counters:
   - instance_name
   - cifs_read_data
diff --git a/conf/zapiperf/7mode/8.2.5/wafl.yaml b/conf/zapiperf/7mode/8.2.5/wafl.yaml
index ea2c4868..2fb84784 100644
--- a/conf/zapiperf/7mode/8.2.5/wafl.yaml
+++ b/conf/zapiperf/7mode/8.2.5/wafl.yaml
@@ -3,7 +3,7 @@ name:                     WAFL
 query:                    wafl
 object:                   wafl
 
-instance_key:             uuid
+instance_key:             name
 
 counters:
   - instance_uuid
diff --git a/integration/Jenkinsfile b/integration/Jenkinsfile
index b52422ad..6b7e5f08 100644
--- a/integration/Jenkinsfile
+++ b/integration/Jenkinsfile
@@ -9,9 +9,10 @@ pipeline {
             )
     }
     parameters {
-        string(name: 'BRANCH', defaultValue: 'main', description: '[Optional] Branch name to clone. Default (main) ')
-        string(name: 'DOCKER', defaultValue: '', description: 'http url of docker tar build or docker image')
-        string(name: 'NATIVE', defaultValue: '', description: 'http url of native tar file')
+        string(name: 'BRANCH',  defaultValue: 'main', description: '[Optional] Branch name to clone. Default (main) ')
+        string(name: 'DOCKER',  defaultValue: '', description: 'http url of docker tar build or docker image')
+        string(name: 'RPM',     defaultValue: '', description: 'http url of rpm file')
+        string(name: 'NATIVE',  defaultValue: '', description: 'http url of native tar file')
     }
 
     stages {
@@ -35,9 +36,7 @@ pipeline {
                         stage('Cleanup Workspace') {
                             steps {
                                 cleanWs()
-                                sh """
-                                echo "Cleaned Up Workspace For Project"
-                                """
+                                stopAndRemoveDockers()
                             }
                         }
 
@@ -61,16 +60,69 @@ pipeline {
 
                         stage('Install NATIVE pkg') {
                             steps {
-                                sh """
+                                sh '''
                                 echo "Installing"
                                 export PATH=$PATH:/usr/local/go/bin
                                 export BUILD_PATH=$NATIVE
                                 cd $WORKSPACE/harvest/integration/test/
-                                go mod vendor
                                 go test -tags=install_native
+                                '''
+                            }
+                        }
+                        stage('Running Test') {
+                            steps {
+                                sh """
+                                echo "Running Unit Tests"
+                                export PATH=$PATH:/usr/local/go/bin
+                                cd $WORKSPACE/harvest/integration/test/
+                                go test -tags=regression
                                 """
                             }
                         }
+                    }
+
+                }
+                stage('RPM') {
+                    agent {
+                        label "rhel"
+                    }
+                    stages('Test on RPM Pkg') {
+                        stage('Cleanup Workspace') {
+                            steps {
+                                cleanWs()
+                                stopAndRemoveDockers()
+                            }
+                        }
+
+                        stage('Setup GO') {
+                            steps {
+                                sh '''
+                                wget --quiet -O go.tar.gz "https://dl.google.com/go/$(curl https://golang.org/VERSION?m=text).linux-amd64.tar.gz"
+                                ls -ltrh
+                                rm -rf /usr/local/go && tar -C /usr/local -xzf ./go.tar.gz
+                                '''
+                            }
+                        }
+
+                        stage('Code Checkout') {
+                            steps {
+                               sh '''
+                               git clone --single-branch --branch $BRANCH https://github.com/NetApp/harvest.git
+                                '''
+                            }
+                        }
+
+                        stage('Install RPM pkg') {
+                            steps {
+                                sh '''
+                                echo "Installing"
+                                export PATH=$PATH:/usr/local/go/bin
+                                export BUILD_PATH=$RPM
+                                cd $WORKSPACE/harvest/integration/test/
+                                go test -tags=install_rpm
+                                '''
+                            }
+                        }
                         stage('Running Test') {
                             steps {
                                 sh """
@@ -92,9 +144,7 @@ pipeline {
                         stage('Cleanup Workspace') {
                             steps {
                                 cleanWs()
-                                sh """
-                                echo "Cleaned Up Workspace For Project"
-                                """
+                                stopAndRemoveDockers()
                             }
                         }
 
@@ -118,14 +168,21 @@ pipeline {
 
                         stage('Install Docker') {
                             steps {
-                                sh """
+                                sh '''
                                 echo "Installing"
                                 export PATH=$PATH:/usr/local/go/bin
-                                export BUILD_PATH=$DOCKER
+                                #export BUILD_PATH=$DOCKER
+                                cd $WORKSPACE/harvest
+                                cp -rf $WORKSPACE/harvest/integration/test/harvest.yml .
+                                make build
+                                ./bin/harvest stop
+                                ./bin/harvest generate docker full --port --output harvest-compose.yml
+                                docker login -u $DOCKER_USER -p $DOCKER_PWD
+                                docker build -f docker/onePollerPerContainer/Dockerfile -t rahulguptajss/harvest:latest . --no-cache
+                                docker-compose -f prom-stack.yml -f harvest-compose.yml up -d --remove-orphans
                                 cd $WORKSPACE/harvest/integration/test/
-                                go mod vendor
                                 go test -tags=install_docker
-                                """
+                                '''
                             }
                         }
                         stage('Running Test') {
@@ -144,4 +201,11 @@ pipeline {
             }
         }
     }
+}
+
+void stopAndRemoveDockers() {
+    sh '''
+        for container_id in $(docker ps -a -q);do docker stop $container_id && docker rm $container_id;done
+        for image_id in $(docker images -q);do docker rmi $image_id;done
+    '''
 }
\ No newline at end of file
diff --git a/integration/go.mod b/integration/go.mod
index 416909d6..d71ac2e1 100644
--- a/integration/go.mod
+++ b/integration/go.mod
@@ -11,6 +11,7 @@ require (
 	github.com/gorilla/mux v1.8.0 // indirect
 	github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
 	github.com/morikuni/aec v1.0.0 // indirect
+	github.com/stretchr/testify v1.7.0
 	goharvest2 v0.0.0-00010101000000-000000000000
 	golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
 	google.golang.org/grpc v1.39.1 // indirect
diff --git a/integration/go.sum b/integration/go.sum
index 73f85d6c..e9298175 100644
--- a/integration/go.sum
+++ b/integration/go.sum
@@ -385,7 +385,6 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
 github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
@@ -434,7 +433,6 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:
 github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
-github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
 github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
 github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
 github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
diff --git a/jenkins/artifacts/JenkinWorkflow b/jenkins/artifacts/JenkinWorkflow
index 8fecae62..c08a2747 100644
--- a/jenkins/artifacts/JenkinWorkflow
+++ b/jenkins/artifacts/JenkinWorkflow
@@ -5,8 +5,8 @@ pipeline {
         targetParentLocation = "/opt/home/nightly/"
         harvestPath = "harvest"
         imageName = "rahulguptajss/harvest"
-        VERSION=""
-        RELEASE=""
+        VERSION="1"
+        RELEASE="2"
     }
 
     stages {
@@ -49,7 +49,7 @@ pipeline {
         }
         stage('Build'){
             parallel {
-                stage('Build Harvest Tar gz') {
+                stage('Build Tar gz') {
                     steps {
                        sh '''
                        cd $harvestPath
@@ -57,7 +57,23 @@ pipeline {
                        targetLocation=$targetParentLocation$VERSION-$RELEASE
                        rm -rf dist
                        make package VERSION=$VERSION RELEASE=$RELEASE
-                       cp ./dist/*tar.gz ./dist/harvest.tar.gz
+                       #cp ./dist/*tar.gz ./dist/harvest.tar.gz
+                        '''
+                    }
+                }
+                stage('Build RPM/DEB') {
+                    steps {
+                       sh '''
+                       cd $harvestPath
+                       targetLocation=$targetParentLocation$VERSION-$RELEASE-$BRANCH
+                       rm -rf ./dist
+                       export PATH=$PATH:/usr/local/go/bin
+                       rm -rf /root/rpmbuild/
+                       mkdir -p $targetLocation
+                       #./package.sh deb x86_64 $VERSION $RELEASE
+                       #cp -RT ./dist/$VERSION-$RELEASE/ $targetLocation
+                       ./package.sh rpm x86_64 $VERSION $RELEASE
+                       #cp -RT ./dist/$VERSION-$RELEASE/x86_64/*.rpm  ./dist/harvest.rpm
                         '''
                     }
                 }
@@ -86,11 +102,12 @@ pipeline {
             steps {
                 script {
                     dockerBuild = "${BUILD_URL}/artifact/docker_harvest.tar"
-                    nativeBuild = "${BUILD_URL}/artifact/harvest.tar.gz"
-                    build job: 'harvest2_0/smoke', parameters: [string(name: 'BRANCH', value: "${GIT_BRANCH}"), string(name: 'NATIVE', value: "${nativeBuild}"), string(name: 'DOCKER', value: "${dockerBuild}")]
-            }    }
+                    nativeBuild = "${BUILD_URL}/artifact/harvest-1-2_linux_amd64.tar.gz"
+                    rpmBuild    = "${BUILD_URL}/artifact/1-2/x86_64/harvest-1-2.x86_64.rpm"
+                    build job: 'harvest2_0/smoke', parameters: [string(name: 'BRANCH', value: "${GIT_BRANCH}"), string(name: 'NATIVE', value: "${nativeBuild}"),  string(name: 'RPM', value: "${rpmBuild}"), string(name: 'DOCKER', value: "${dockerBuild}")]
+                }
+            }
         }
-
     }
 
 }
\ No newline at end of file
diff --git a/pkg/api/ontapi/zapi/client.go b/pkg/api/ontapi/zapi/client.go
index ccedffd2..e187abae 100644
--- a/pkg/api/ontapi/zapi/client.go
+++ b/pkg/api/ontapi/zapi/client.go
@@ -187,6 +187,11 @@ func (c *Client) Serial() string {
 	return c.system.serial
 }
 
+// ClusterUuid returns the cluster UUID of a c-mode system and system-id for 7-mode
+func (c *Client) ClusterUuid() string {
+	return c.system.clusterUuid
+}
+
 // Info returns a string with details about the ONTAP system identity
 func (c *Client) Info() string {
 	var model, version string
diff --git a/pkg/api/ontapi/zapi/system.go b/pkg/api/ontapi/zapi/system.go
index 6aa3d916..eff335b2 100644
--- a/pkg/api/ontapi/zapi/system.go
+++ b/pkg/api/ontapi/zapi/system.go
@@ -12,11 +12,12 @@ import (
 )
 
 type system struct {
-	name      string
-	serial    string
-	release   string
-	version   [3]int
-	clustered bool
+	name        string
+	serial      string
+	clusterUuid string
+	release     string
+	version     [3]int
+	clustered   bool
 }
 
 // See system_test.go for examples
@@ -123,12 +124,15 @@ func (c *Client) getSystem() error {
 			if info := attrs.GetChildS("cluster-identity-info"); info != nil {
 				s.name = info.GetChildContentS("cluster-name")
 				s.serial = info.GetChildContentS("cluster-serial-number")
+				s.clusterUuid = info.GetChildContentS("cluster-uuid")
 			}
 		}
 	} else {
 		if info := response.GetChildS("system-info"); info != nil {
 			s.name = info.GetChildContentS("system-name")
 			s.serial = info.GetChildContentS("system-serial-number")
+			// There is no uuid for non cluster mode, using system-id.
+			s.clusterUuid = info.GetChildContentS("system-id")
 		}
 	}
 	c.system = &s
diff --git a/pkg/matrix/lazy.go b/pkg/matrix/lazy.go
index a1b84c8f..66fd10b1 100644
--- a/pkg/matrix/lazy.go
+++ b/pkg/matrix/lazy.go
@@ -49,16 +49,10 @@ func (me *Matrix) LazyGetValueInt64(m, i string) (int64, bool) {
 	return 0, false
 }
 
-/*
-func (me *Matrix) LazyGetValueInt64(mkey, ikey string) int64 {
-	var v int64
-	if instance := me.GetInstance(ikey); instance != nil {
-		if metric := me.GetMetric(mkey); metric != nil {
-			v, _ = metric.GetValueInt64(instance)
-		}
-	}
-	return v
-}*/
+func (me *Matrix) LazyValueInt64(m, i string) int64 {
+	valueInt64, _ := me.LazyGetValueInt64(m, i)
+	return valueInt64
+}
 
 func (me *Matrix) LazyAddValueInt64(m, i string, v int64) error {
 	if metric := me.GetMetric(m); metric != nil {
@@ -128,3 +122,8 @@ func (me *Matrix) LazyGetValueFloat64(m, i string) (float64, bool) {
 	}
 	return 0.0, false
 }
+
+func (me *Matrix) LazyValueFloat64(m, i string) float64 {
+	valueFloat64, _ := me.LazyGetValueFloat64(m, i)
+	return valueFloat64
+}
diff --git a/pkg/matrix/matrix.go b/pkg/matrix/matrix.go
index 3d7bf494..c070dcec 100644
--- a/pkg/matrix/matrix.go
+++ b/pkg/matrix/matrix.go
@@ -224,6 +224,14 @@ func (me *Matrix) NewInstance(key string) (*Instance, error) {
 	return instance, nil
 }
 
+func (me *Matrix) ResetInstance(key string) {
+	if instance, has := me.instances[key]; has {
+		for _, metric := range me.GetMetrics() {
+			metric.SetValueNAN(instance)
+		}
+	}
+}
+
 func (me *Matrix) RemoveInstance(key string) {
 	if instance, has := me.instances[key]; has {
 		// re-arrange columns in metrics
diff --git a/pkg/tree/node/node.go b/pkg/tree/node/node.go
index 2370fd01..97dce9e9 100644
--- a/pkg/tree/node/node.go
+++ b/pkg/tree/node/node.go
@@ -10,6 +10,7 @@ import (
 	"fmt"
 	"goharvest2/pkg/color"
 	"goharvest2/pkg/util"
+	"regexp"
 	"strings"
 )
 
@@ -281,6 +282,41 @@ func (n *Node) UnmarshalXML(dec *xml.Decoder, root xml.StartElement) error {
 	return dec.DecodeElement((*node)(n), &root)
 }
 
+func (n *Node) FlatList(list *[]string, prefix string) {
+	if n == nil {
+		return
+	}
+	if len(n.Children) == 0 {
+		var sub string
+		if len(prefix) > 0 {
+			sub = prefix + " " + simpleName(n.GetContentS())
+		} else {
+			sub = simpleName(n.GetContentS())
+		}
+		*list = append(*list, sub)
+	} else {
+		nameS := n.GetNameS()
+		if len(nameS) > 0 && nameS != "counters" {
+			if prefix == "" {
+				prefix = nameS
+			} else {
+				prefix += " " + nameS
+			}
+		}
+		for _, child := range n.Children {
+			child.FlatList(list, prefix)
+		}
+	}
+}
+
+var wordRegex = regexp.MustCompile(`(\w|-)+`)
+
+// simpleName returns the first word in the string s
+// ignoring non-word characters. see node_test for examples
+func simpleName(s string) string {
+	return wordRegex.FindString(s)
+}
+
 func (n *Node) Print(depth int) {
 	name := "* "
 	content := " *"


Test patch:
diff --git a/integration/test/dashboard_jsons/harvest_dashboard_disk.json b/integration/test/dashboard_jsons/harvest_dashboard_disk.json
new file mode 100644
index 00000000..d9d4d7d9
--- /dev/null
+++ b/integration/test/dashboard_jsons/harvest_dashboard_disk.json
@@ -0,0 +1,2185 @@
+{
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "type": "dashboard"
+      }
+    ]
+  },
+  "editable": true,
+  "gnetId": null,
+  "graphTooltip": 0,
+  "id": 46,
+  "iteration": 1602106783730,
+  "links": [],
+  "panels": [
+    {
+      "collapsed": false,
+      "datasource": null,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 0
+      },
+      "id": 45,
+      "panels": [],
+      "title": "Highlights",
+      "type": "row"
+    },
+    {
+      "cacheTimeout": null,
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {},
+          "mappings": [
+            {
+              "id": 0,
+              "op": "=",
+              "text": "0",
+              "type": 1,
+              "value": "null"
+            }
+          ],
+          "nullValueMode": "connected",
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "rgb(31, 176, 196)",
+                "value": null
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 5,
+        "x": 0,
+        "y": 1
+      },
+      "id": 41,
+      "links": [],
+      "options": {
+        "colorMode": "value",
+        "graphMode": "none",
+        "justifyMode": "center",
+        "orientation": "horizontal",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "textMode": "auto"
+      },
+      "pluginVersion": "7.2.0",
+      "targets": [
+        {
+          "expr": "count( count by(disk) (disk_labels{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\"}) )",
+          "format": "time_series",
+          "hide": false,
+          "instant": false,
+          "interval": "",
+          "intervalFactor": 1,
+          "legendFormat": "",
+          "refId": "B"
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Total Disks",
+      "type": "stat"
+    },
+    {
+      "cacheTimeout": null,
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {},
+          "mappings": [
+            {
+              "id": 0,
+              "op": "=",
+              "text": "0",
+              "type": 1,
+              "value": "null"
+            }
+          ],
+          "nullValueMode": "connected",
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "rgb(222, 92, 107)",
+                "value": null
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 5,
+        "x": 5,
+        "y": 1
+      },
+      "id": 55,
+      "links": [],
+      "options": {
+        "colorMode": "value",
+        "graphMode": "none",
+        "justifyMode": "center",
+        "orientation": "horizontal",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "textMode": "auto"
+      },
+      "pluginVersion": "7.2.0",
+      "targets": [
+        {
+          "expr": "count( count by(serial_number) (disk_labels{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\",failed=\"true\"}) )",
+          "format": "time_series",
+          "hide": false,
+          "instant": false,
+          "interval": "",
+          "intervalFactor": 1,
+          "legendFormat": "",
+          "refId": "B"
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Failed Disks",
+      "type": "stat"
+    },
+    {
+      "cacheTimeout": null,
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {},
+          "mappings": [
+            {
+              "id": 0,
+              "op": "=",
+              "text": "0",
+              "type": 1,
+              "value": "null"
+            }
+          ],
+          "nullValueMode": "connected",
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "rgb(31, 176, 196)",
+                "value": null
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 5,
+        "x": 10,
+        "y": 1
+      },
+      "id": 47,
+      "links": [],
+      "options": {
+        "colorMode": "value",
+        "graphMode": "none",
+        "justifyMode": "center",
+        "orientation": "horizontal",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "textMode": "auto"
+      },
+      "pluginVersion": "7.2.0",
+      "targets": [
+        {
+          "expr": "count( count by(raid) (aggr_disk_busy{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\"}) )",
+          "format": "time_series",
+          "hide": false,
+          "instant": false,
+          "interval": "",
+          "intervalFactor": 1,
+          "legendFormat": "",
+          "refId": "B"
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Raid Groups",
+      "type": "stat"
+    },
+    {
+      "cacheTimeout": null,
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {},
+          "mappings": [
+            {
+              "id": 0,
+              "op": "=",
+              "text": "0",
+              "type": 1,
+              "value": "null"
+            }
+          ],
+          "nullValueMode": "connected",
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "rgb(31, 176, 196)",
+                "value": null
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 5,
+        "x": 15,
+        "y": 1
+      },
+      "id": 48,
+      "links": [],
+      "options": {
+        "colorMode": "value",
+        "graphMode": "none",
+        "justifyMode": "center",
+        "orientation": "horizontal",
+        "reduceOptions": {
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "textMode": "auto"
+      },
+      "pluginVersion": "7.2.0",
+      "targets": [
+        {
+          "expr": "count( count by(plex) (aggr_disk_busy{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\"}) )",
+          "format": "time_series",
+          "hide": false,
+          "instant": false,
+          "interval": "",
+          "intervalFactor": 1,
+          "legendFormat": "",
+          "refId": "B"
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Plexes",
+      "type": "stat"
+    },
+    {
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {
+            "align": null,
+            "displayMode": "auto",
+            "filterable": false
+          },
+          "decimals": 2,
+          "mappings": [],
+          "max": 100,
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "rgb(59, 186, 47)",
+                "value": null
+              },
+              {
+                "color": "light-orange",
+                "value": 75
+              },
+              {
+                "color": "rgb(255, 99, 89)",
+                "value": 85
+              }
+            ]
+          },
+          "unit": "percent"
+        },
+        "overrides": [
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Value #E"
+            },
+            "properties": [
+              {
+                "id": "displayName",
+                "value": "capacity"
+              },
+              {
+                "id": "unit",
+                "value": "bytes"
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Value #A"
+            },
+            "properties": [
+              {
+                "id": "custom.displayMode",
+                "value": "lcd-gauge"
+              },
+              {
+                "id": "displayName",
+                "value": "capacity used"
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Value #C"
+            },
+            "properties": [
+              {
+                "id": "displayName",
+                "value": "max IOPs"
+              },
+              {
+                "id": "unit",
+                "value": "short"
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Value #B"
+            },
+            "properties": [
+              {
+                "id": "displayName",
+                "value": "max utilization"
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "node"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 128
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "capacity"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 134
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "max IOPs"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 154
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "max utilization"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 167
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Value #D"
+            },
+            "properties": [
+              {
+                "id": "displayName",
+                "value": "disks"
+              },
+              {
+                "id": "unit",
+                "value": "short"
+              },
+              {
+                "id": "decimals",
+                "value": 0
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "disks"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 77
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "capacity used"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 362
+              }
+            ]
+          }
+        ]
+      },
+      "gridPos": {
+        "h": 9,
+        "w": 12,
+        "x": 0,
+        "y": 4
+      },
+      "id": 53,
+      "options": {
+        "showHeader": true,
+        "sortBy": [
+          {
+            "desc": true,
+            "displayName": "capacity used"
+          }
+        ]
+      },
+      "pluginVersion": "7.2.0",
+      "targets": [
+        {
+          "expr": "aggr_raid_disk_count{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\",aggr=~\"$Aggregate\"}",
+          "format": "table",
+          "instant": true,
+          "interval": "",
+          "legendFormat": "",
+          "refId": "D"
+        },
+        {
+          "expr": "aggr_space_total{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\",aggr=~\"$Aggregate\"}",
+          "format": "table",
+          "instant": true,
+          "interval": "",
+          "legendFormat": "",
+          "refId": "E"
+        },
+        {
+          "expr": "aggr_space_used_percent{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\",aggr=~\"$Aggregate\"}",
+          "format": "table",
+          "instant": true,
+          "interval": "",
+          "legendFormat": "",
+          "refId": "A"
+        },
+        {
+          "expr": "max by (node, aggr) (aggr_disk_total_transfers{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\",aggr=~\"$Aggregate\"})",
+          "format": "table",
+          "hide": true,
+          "instant": true,
+          "interval": "",
+          "legendFormat": "",
+          "refId": "C"
+        },
+        {
+          "expr": "max by (node, aggr) (aggr_disk_busy{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\",aggr=~\"$Aggregate\"})",
+          "format": "table",
+          "hide": true,
+          "instant": true,
+          "interval": "",
+          "legendFormat": "",
+          "refId": "B"
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Disk Capacity per Aggregate",
+      "transformations": [
+        {
+          "id": "filterFieldsByName",
+          "options": {
+            "include": {
+              "names": [
+                "aggregate",
+                "node",
+                "Value #A",
+                "Value #D",
+                "Value #E"
+              ]
+            }
+          }
+        },
+        {
+          "id": "merge",
+          "options": {}
+        }
+      ],
+      "type": "table"
+    },
+    {
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {
+            "align": null,
+            "displayMode": "auto",
+            "filterable": false
+          },
+          "decimals": 2,
+          "mappings": [],
+          "max": 100,
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "rgb(59, 186, 47)",
+                "value": null
+              },
+              {
+                "color": "light-orange",
+                "value": 75
+              },
+              {
+                "color": "rgb(255, 99, 89)",
+                "value": 85
+              }
+            ]
+          },
+          "unit": "percent"
+        },
+        "overrides": [
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Value #C"
+            },
+            "properties": [
+              {
+                "id": "displayName",
+                "value": "max IOPs"
+              },
+              {
+                "id": "unit",
+                "value": "short"
+              },
+              {
+                "id": "decimals"
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Value #B"
+            },
+            "properties": [
+              {
+                "id": "displayName",
+                "value": "max utilization"
+              },
+              {
+                "id": "custom.displayMode",
+                "value": "lcd-gauge"
+              },
+              {
+                "id": "max",
+                "value": 100
+              },
+              {
+                "id": "decimals",
+                "value": 3
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "max IOPs"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 153
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "max utilization"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 349
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "node"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 148
+              }
+            ]
+          }
+        ]
+      },
+      "gridPos": {
+        "h": 9,
+        "w": 12,
+        "x": 12,
+        "y": 4
+      },
+      "id": 54,
+      "options": {
+        "showHeader": true,
+        "sortBy": [
+          {
+            "desc": true,
+            "displayName": "max IOPs"
+          }
+        ]
+      },
+      "pluginVersion": "7.2.0",
+      "targets": [
+        {
+          "expr": "max by (node, aggr) (aggr_disk_total_transfers{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\",aggr=~\"$Aggregate\"})",
+          "format": "table",
+          "hide": false,
+          "instant": true,
+          "interval": "",
+          "legendFormat": "",
+          "refId": "C"
+        },
+        {
+          "expr": "max by (node, aggr) (aggr_disk_busy{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\",aggr=~\"$Aggregate\"})",
+          "format": "table",
+          "hide": false,
+          "instant": true,
+          "interval": "",
+          "legendFormat": "",
+          "refId": "B"
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Disk Utilization per Aggregate",
+      "transformations": [
+        {
+          "id": "filterFieldsByName",
+          "options": {
+            "include": {
+              "names": [
+                "aggregate",
+                "Value #C",
+                "Value #B",
+                "node"
+              ]
+            }
+          }
+        },
+        {
+          "id": "merge",
+          "options": {}
+        }
+      ],
+      "type": "table"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "Prometheus",
+      "description": "Highest Disk Utilization per Aggregate",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {}
+        },
+        "overrides": []
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 13
+      },
+      "hiddenSeries": false,
+      "id": 50,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": true,
+        "max": true,
+        "min": false,
+        "show": true,
+        "sort": "avg",
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "nullPointMode": "null",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "7.2.0",
+      "pointradius": 2,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "max by (node, aggr) (aggr_disk_busy{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\",aggr=~\"$Aggregate\"})",
+          "interval": "",
+          "legendFormat": "{{node}} - {{aggregate}}",
+          "refId": "A"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Disk Utiliziation",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "$$hashKey": "object:234",
+          "format": "percentunit",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "$$hashKey": "object:235",
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "Prometheus",
+      "description": "Total number of disk operations involving data transfer initiated per second\n",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {}
+        },
+        "overrides": []
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 13
+      },
+      "hiddenSeries": false,
+      "id": 51,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": true,
+        "max": true,
+        "min": false,
+        "show": true,
+        "sort": "avg",
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "nullPointMode": "null",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "7.2.0",
+      "pointradius": 2,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "max by (node, aggr) (aggr_disk_total_transfers{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\",aggr=~\"$Aggregate\"})",
+          "interval": "",
+          "legendFormat": "{{node}} - {{aggregate}}",
+          "refId": "A"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Disk Transfers",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "$$hashKey": "object:234",
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "$$hashKey": "object:235",
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "collapsed": false,
+      "datasource": "Prometheus",
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 21
+      },
+      "id": 22,
+      "panels": [],
+      "title": "List of Disks",
+      "type": "row"
+    },
+    {
+      "datasource": "Prometheus",
+      "description": "Some Clusters don't report average latency, so the values might be 0s.",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {
+            "align": "left",
+            "displayMode": "auto",
+            "filterable": false
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "rgb(31, 176, 196)",
+                "value": null
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": [
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "disk"
+            },
+            "properties": [
+              {
+                "id": "displayName",
+                "value": "Disk"
+              },
+              {
+                "id": "custom.width",
+                "value": 144
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "type"
+            },
+            "properties": [
+              {
+                "id": "displayName",
+                "value": "Type"
+              },
+              {
+                "id": "custom.width",
+                "value": 144
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Model"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 191
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Serial"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 185
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Value #B"
+            },
+            "properties": [
+              {
+                "id": "displayName",
+                "value": "Capacity"
+              },
+              {
+                "id": "unit",
+                "value": "decbytes"
+              },
+              {
+                "id": "decimals",
+                "value": 2
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Value #A"
+            },
+            "properties": [
+              {
+                "id": "displayName",
+                "value": "Avg IOPs"
+              },
+              {
+                "id": "unit",
+                "value": "KiBs"
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Value #D"
+            },
+            "properties": [
+              {
+                "id": "displayName",
+                "value": "Avg Latency"
+              },
+              {
+                "id": "unit",
+                "value": "ms"
+              },
+              {
+                "id": "decimals",
+                "value": 4
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Value #C"
+            },
+            "properties": [
+              {
+                "id": "displayName",
+                "value": "Power On Time"
+              },
+              {
+                "id": "unit",
+                "value": "clocks"
+              },
+              {
+                "id": "decimals",
+                "value": 2
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "shelf"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 69
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "diskStatus"
+            },
+            "properties": [
+              {
+                "id": "displayName",
+                "value": "Status"
+              },
+              {
+                "id": "mappings",
+                "value": [
+                  {
+                    "type": "value",
+                    "options": {
+                      " ": {
+                        "text": "Ok",
+                        "index": 0
+                      }
+                    }
+                  }
+                ]
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "shelf_bay"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 95
+              }
+            ]
+          }
+        ]
+      },
+      "gridPos": {
+        "h": 10,
+        "w": 24,
+        "x": 0,
+        "y": 22
+      },
+      "id": 18,
+      "interval": "1m",
+      "maxDataPoints": 2,
+      "options": {
+        "showHeader": true,
+        "sortBy": [
+          {
+            "desc": true,
+            "displayName": "Avg IOPs"
+          }
+        ]
+      },
+      "pluginVersion": "7.2.0",
+      "targets": [
+        {
+          "expr": "disk_bytes_per_sector * disk_sectors{datacenter=\"$Datacenter\",cluster=\"$Cluster\"}",
+          "format": "table",
+          "hide": false,
+          "instant": true,
+          "interval": "",
+          "intervalFactor": 1,
+          "legendFormat": "",
+          "refId": "B"
+        },
+        {
+          "expr": "disk_stats_io_kbps{datacenter=\"$Datacenter\",cluster=\"$Cluster\"}",
+          "format": "table",
+          "hide": false,
+          "instant": true,
+          "interval": "",
+          "intervalFactor": 1,
+          "legendFormat": "",
+          "refId": "A"
+        },
+        {
+          "expr": "disk_stats_average_latency{datacenter=\"$Datacenter\",cluster=\"$Cluster\"}",
+          "format": "table",
+          "hide": false,
+          "instant": true,
+          "interval": "",
+          "intervalFactor": 1,
+          "legendFormat": "",
+          "refId": "D"
+        },
+        {
+          "expr": "disk_uptime{datacenter=\"$Datacenter\",cluster=\"$Cluster\"}",
+          "format": "table",
+          "hide": false,
+          "instant": true,
+          "interval": "",
+          "intervalFactor": 1,
+          "legendFormat": "",
+          "refId": "C"
+        },
+        {
+          "expr": "label_join(disk_labels{datacenter=\"$Datacenter\",cluster=\"$Cluster\"}, \"diskStatus\", \" \",\"NonSupportedField\", \"outage\")",
+          "legendFormat": "",
+          "interval": "",
+          "exemplar": true,
+          "format": "table",
+          "hide": false,
+          "instant": true,
+          "intervalFactor": 1,
+          "refId": "E"
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Disks in Cluster",
+      "transformations": [
+        {
+          "id": "organize",
+          "options": {
+            "excludeByName": {
+              "Time": true,
+              "__name__": true,
+              "cluster": true,
+              "datacenter": true,
+              "instance": true,
+              "job": true,
+              "node": true,
+              "aggr": true,
+              "failed": true,
+              "model": true,
+              "shelf_bay": true,
+              "serial_number": true,
+              "owner_node": true,
+              "shared": true,
+              "shelf": true,
+              "Value #E": true,
+              "outage": true
+            },
+            "indexByName": {
+              "Time": 0,
+              "Value": 7,
+              "cluster": 2,
+              "datacenter": 1,
+              "disk": 3,
+              "instance": 10,
+              "job": 11,
+              "model": 4,
+              "serial_number": 5,
+              "shelf": 1,
+              "shelf_bay": 2,
+              "type": 4
+            },
+            "renameByName": {}
+          }
+        },
+        {
+          "id": "merge",
+          "options": {}
+        }
+      ],
+      "type": "table"
+    },
+    {
+      "collapsed": false,
+      "datasource": "Prometheus",
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 32
+      },
+      "id": 28,
+      "panels": [],
+      "title": "Disk Utilization: Node-level overview",
+      "type": "row"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {},
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "rgb(31, 176, 196)",
+                "value": null
+              }
+            ]
+          },
+          "unit": "µs"
+        },
+        "overrides": []
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 9,
+        "w": 8,
+        "x": 0,
+        "y": 33
+      },
+      "hiddenSeries": false,
+      "id": 32,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": true,
+        "max": true,
+        "min": false,
+        "rightSide": false,
+        "show": true,
+        "sort": "current",
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "nullPointMode": "null as zero",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "7.2.0",
+      "pointradius": 2,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "sum (node_disk_data_read{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\"}) by (node)",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "{{node}} - READ",
+          "refId": "A"
+        },
+        {
+          "expr": "sum (node_disk_data_written{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\"}) by (node)",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "{{node}} - WRITE",
+          "refId": "B"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Disk Throughput",
+      "tooltip": {
+        "shared": true,
+        "sort": 2,
+        "value_type": "individual"
+      },
+      "transformations": [],
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "$$hashKey": "object:153",
+          "decimals": null,
+          "format": "µs",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "$$hashKey": "object:154",
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {},
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "rgb(31, 176, 196)",
+                "value": null
+              }
+            ]
+          },
+          "unit": "µs"
+        },
+        "overrides": []
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 9,
+        "w": 8,
+        "x": 8,
+        "y": 33
+      },
+      "hiddenSeries": false,
+      "id": 34,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": true,
+        "max": true,
+        "min": false,
+        "rightSide": false,
+        "show": true,
+        "sort": "current",
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "nullPointMode": "null as zero",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "7.2.0",
+      "pointradius": 2,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "sum (hostadapter_bytes_written{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\"}) by (node)",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "{{node}} - WRITE",
+          "refId": "A"
+        },
+        {
+          "expr": "sum (hostadapter_bytes_read{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\"}) by (node)",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "{{node}} - READ",
+          "refId": "B"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Disk and Tape Drives Throughput",
+      "tooltip": {
+        "shared": true,
+        "sort": 2,
+        "value_type": "individual"
+      },
+      "transformations": [],
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "decimals": null,
+          "format": "µs",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {},
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "rgb(31, 176, 196)",
+                "value": null
+              }
+            ]
+          },
+          "unit": "µs"
+        },
+        "overrides": []
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 9,
+        "w": 8,
+        "x": 16,
+        "y": 33
+      },
+      "hiddenSeries": false,
+      "id": 40,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": true,
+        "max": true,
+        "min": false,
+        "rightSide": false,
+        "show": true,
+        "sort": "avg",
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "nullPointMode": "null as zero",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "7.2.0",
+      "pointradius": 2,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "sum(wafl_cp_count{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\"}) by (subcounter)",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "{{subcounter}}",
+          "refId": "A"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "CP (Consistency Points) Counts",
+      "tooltip": {
+        "shared": true,
+        "sort": 2,
+        "value_type": "individual"
+      },
+      "transformations": [],
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "decimals": null,
+          "format": "µs",
+          "label": "",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "decimals": null,
+          "format": "short",
+          "label": "HDD Reads Replaced",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": false
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {},
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "rgb(31, 176, 196)",
+                "value": null
+              }
+            ]
+          },
+          "unit": "µs"
+        },
+        "overrides": []
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 9,
+        "w": 8,
+        "x": 0,
+        "y": 42
+      },
+      "hiddenSeries": false,
+      "id": 36,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": true,
+        "max": true,
+        "min": false,
+        "rightSide": false,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "nullPointMode": "null as zero",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "7.2.0",
+      "pointradius": 2,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [
+        {
+          "alias": "HDD Reads Replaced",
+          "bars": true,
+          "lines": false,
+          "yaxis": 2
+        }
+      ],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "sum (flashcache_hit_percent{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\"})",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Hit %",
+          "refId": "A"
+        },
+        {
+          "expr": "sum (flashcache_disk_reads_replaced{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\"})",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "HDD Reads Replaced",
+          "refId": "B"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Flash Cache",
+      "tooltip": {
+        "shared": true,
+        "sort": 2,
+        "value_type": "individual"
+      },
+      "transformations": [],
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "decimals": null,
+          "format": "percent",
+          "label": "Hit %",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "decimals": null,
+          "format": "short",
+          "label": "HDD Reads Replaced",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "Prometheus",
+      "description": "",
+      "fieldConfig": {
+        "defaults": {
+          "custom": {},
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "rgb(31, 176, 196)",
+                "value": null
+              }
+            ]
+          },
+          "unit": "µs"
+        },
+        "overrides": []
+      },
+      "fill": 1,
+      "fillGradient": 0,
+      "gridPos": {
+        "h": 9,
+        "w": 8,
+        "x": 8,
+        "y": 42
+      },
+      "hiddenSeries": false,
+      "id": 38,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": true,
+        "max": true,
+        "min": false,
+        "rightSide": false,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "nullPointMode": "null as zero",
+      "options": {
+        "alertThreshold": true
+      },
+      "percentage": false,
+      "pluginVersion": "7.2.0",
+      "pointradius": 2,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [
+        {
+          "alias": "HDD Reads Replaced",
+          "bars": true,
+          "lines": false,
+          "yaxis": 2
+        }
+      ],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "sum (flashpool_read_ops_replaced_percent{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\"})",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "Hit %",
+          "refId": "A"
+        },
+        {
+          "expr": "sum (flashpool_read_ops_replaced{datacenter=\"$Datacenter\",cluster=\"$Cluster\",node=~\"$Node\"})",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "HDD Reads Replaced",
+          "refId": "B"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Flash Pool",
+      "tooltip": {
+        "shared": true,
+        "sort": 2,
+        "value_type": "individual"
+      },
+      "transformations": [],
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "decimals": null,
+          "format": "percent",
+          "label": "Hit %",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "decimals": null,
+          "format": "short",
+          "label": "HDD Reads Replaced",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    }
+  ],
+  "refresh": false,
+  "schemaVersion": 26,
+  "style": "dark",
+  "tags": [],
+  "templating": {
+    "list": [
+      {
+        "allValue": null,
+        "current": {
+          "selected": false,
+          "text": "CBC-Munich",
+          "value": "CBC-Munich"
+        },
+        "datasource": "Prometheus",
+        "definition": "label_values(datacenter)",
+        "hide": 0,
+        "includeAll": false,
+        "label": null,
+        "multi": false,
+        "name": "Datacenter",
+        "options": [],
+        "query": "label_values(datacenter)",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 0,
+        "tagValuesQuery": "",
+        "tags": [],
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      },
+      {
+        "allValue": null,
+        "current": {
+          "selected": false,
+          "text": "jamaica",
+          "value": "jamaica"
+        },
+        "datasource": "Prometheus",
+        "definition": "label_values(cluster)",
+        "hide": 0,
+        "includeAll": false,
+        "label": null,
+        "multi": false,
+        "name": "Cluster",
+        "options": [],
+        "query": "label_values(cluster)",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 0,
+        "tagValuesQuery": "",
+        "tags": [],
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      },
+      {
+        "allValue": null,
+        "current": {
+          "selected": false,
+          "text": "All",
+          "value": "$__all"
+        },
+        "datasource": "Prometheus",
+        "definition": "label_values(disk_labels{cluster=\"$Cluster\"}, node)",
+        "hide": 0,
+        "includeAll": true,
+        "label": null,
+        "multi": false,
+        "name": "Node",
+        "options": [],
+        "query": "label_values(disk_labels{cluster=\"$Cluster\"}, node)",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 0,
+        "tagValuesQuery": "",
+        "tags": [],
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      },
+      {
+        "allValue": null,
+        "current": {
+          "selected": false,
+          "text": "All",
+          "value": "$__all"
+        },
+        "datasource": "Prometheus",
+        "definition": "label_values(aggr_disk_busy{cluster=\"$Cluster\"}, aggr)",
+        "hide": 0,
+        "includeAll": true,
+        "label": null,
+        "multi": false,
+        "name": "Aggregate",
+        "options": [],
+        "query": "label_values(aggr_disk_busy{cluster=\"$Cluster\"}, aggr)",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 0,
+        "tagValuesQuery": "",
+        "tags": [],
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      },
+      {
+        "allValue": null,
+        "current": {
+          "selected": false,
+          "text": "5",
+          "value": "5"
+        },
+        "hide": 0,
+        "includeAll": false,
+        "label": null,
+        "multi": false,
+        "name": "TopResources",
+        "options": [
+          {
+            "selected": false,
+            "text": "1",
+            "value": "1"
+          },
+          {
+            "selected": false,
+            "text": "2",
+            "value": "2"
+          },
+          {
+            "selected": false,
+            "text": "3",
+            "value": "3"
+          },
+          {
+            "selected": false,
+            "text": "4",
+            "value": "4"
+          },
+          {
+            "selected": true,
+            "text": "5",
+            "value": "5"
+          },
+          {
+            "selected": false,
+            "text": "6",
+            "value": "6"
+          },
+          {
+            "selected": false,
+            "text": "8",
+            "value": "8"
+          },
+          {
+            "selected": false,
+            "text": "10",
+            "value": "10"
+          },
+          {
+            "selected": false,
+            "text": "15",
+            "value": "15"
+          },
+          {
+            "selected": false,
+            "text": "25",
+            "value": "25"
+          },
+          {
+            "selected": false,
+            "text": "50",
+            "value": "50"
+          },
+          {
+            "selected": false,
+            "text": "100",
+            "value": "100"
+          },
+          {
+            "selected": false,
+            "text": "250",
+            "value": "250"
+          },
+          {
+            "selected": false,
+            "text": "500",
+            "value": "500"
+          }
+        ],
+        "query": "1,2,3,4,5,6,8,10,15,25,50,100,250,500",
+        "queryValue": "",
+        "skipUrlSync": false,
+        "type": "custom"
+      },
+      {
+        "allValue": null,
+        "current": {
+          "selected": false,
+          "text": "All",
+          "value": "$__all"
+        },
+        "datasource": "Prometheus",
+        "definition": "label_values(disk_uptime{cluster=\"$Cluster\"}, type)",
+        "hide": 2,
+        "includeAll": true,
+        "label": null,
+        "multi": false,
+        "name": "DiskType",
+        "options": [],
+        "query": "label_values(disk_labels{cluster=\"$Cluster\"}, type)",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 0,
+        "tagValuesQuery": "",
+        "tags": [],
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      }
+    ]
+  },
+  "time": {
+    "from": "now-6h",
+    "to": "now"
+  },
+  "timepicker": {
+    "refresh_intervals": [
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ]
+  },
+  "timezone": "",
+  "title": "NetApp Detail: Disk",
+  "uid": "MZ4uALHGk",
+  "version": 21
+}
\ No newline at end of file
diff --git a/integration/test/dashboard_test.go b/integration/test/dashboard_test.go
new file mode 100644
index 00000000..29119746
--- /dev/null
+++ b/integration/test/dashboard_test.go
@@ -0,0 +1,133 @@
+//+build regression dashboard
+
+package main
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/Netapp/harvest-automation/test/docker"
+	"github.com/Netapp/harvest-automation/test/grafana"
+	"github.com/Netapp/harvest-automation/test/installer"
+	"github.com/Netapp/harvest-automation/test/utils"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/suite"
+	"log"
+	"testing"
+)
+
+const TOTAL_DASHBOARD = 11
+
+type DashboardImportTestSuite struct {
+	suite.Suite
+}
+
+type Folder struct {
+	Id    int64  `json:"id"`
+	Uid   string `json:"uid"`
+	Title string `json:"title"`
+}
+
+type Dashboard struct {
+	Id          int64  `json:"id"`
+	Uid         string `json:"uid"`
+	Title       string `json:"title"`
+	FolderTitle string `json:"folderTitle"`
+	FolderUrl   string `json:"folderUrl"`
+}
+
+func (suite *DashboardImportTestSuite) SetupSuite() {
+	log.Println("Verify Grafana and Prometheus are configured")
+	if !utils.IsUrlReachable(utils.GetGrafanaHttpUrl()) {
+		panic(fmt.Errorf("Grafana is not reachable."))
+	}
+	if !utils.IsUrlReachable(utils.GetPrometheusUrl()) {
+		panic(fmt.Errorf("Prometheus is not reachable."))
+	}
+	status, _ := new(grafana.GrafanaMgr).Import("grafana/dashboards")
+	if !status {
+		assert.Fail(suite.T(), "Grafana import operation is failed")
+	}
+}
+
+func (suite *DashboardImportTestSuite) TestImport() {
+	log.Println("Verify harvest folder")
+	data, err := utils.GetResponseBody(utils.GetGrafanaHttpUrl() + "/api/folders?limit=10")
+	utils.PanicIfNotNil(err)
+	var dataFolder []Folder
+	err = json.Unmarshal(data, &dataFolder)
+	utils.PanicIfNotNil(err)
+	for _, values := range dataFolder {
+		if values.Title == "Harvest 2.0" {
+			return
+		}
+	}
+	log.Println(data)
+	assert.Fail(suite.T(), "Unable to find harvest folder")
+}
+
+func (suite *DashboardImportTestSuite) TestDashboardCount() {
+	log.Println("Find harvest folder id")
+	data, err := utils.GetResponseBody(utils.GetGrafanaHttpUrl() + "/api/folders?limit=10")
+	utils.PanicIfNotNil(err)
+	var dataFolder []Folder
+	var folderId int64
+	err = json.Unmarshal(data, &dataFolder)
+	utils.PanicIfNotNil(err)
+	for _, values := range dataFolder {
+		if values.Title == "Harvest 2.0" {
+			folderId = values.Id
+			break
+		}
+	}
+	if !(folderId > 0) {
+		assert.Fail(suite.T(), "Folder id is empty or zero.")
+	}
+	log.Println(fmt.Sprintf("Find list of dashboard for folder %d", folderId))
+	url := utils.GetGrafanaHttpUrl() + fmt.Sprintf("/api/search?folderIds=%d", folderId)
+	log.Println(url)
+	data, err = utils.GetResponseBody(url)
+	utils.PanicIfNotNil(err)
+	var dataDashboard []Dashboard
+	err = json.Unmarshal(data, &dataDashboard)
+	utils.PanicIfNotNil(err)
+	assert.True(suite.T(), TOTAL_DASHBOARD == len(dataDashboard), fmt.Sprintf("Expected dashboard %d but found %d dashboards",
+		TOTAL_DASHBOARD, len(dataDashboard)))
+	var actualNames []string
+	var notFoundList []string
+	for _, values := range dataDashboard {
+		actualNames = append(actualNames, values.Title)
+	}
+	expectedName := []string{"Harvest Metadata", "NetApp Detail: Aggregate", "NetApp Detail: Cluster",
+		"NetApp Detail: Disk", "NetApp Detail: Network",
+		"NetApp Detail: Network with NVMe/FC", "NetApp Detail: Node",
+		"NetApp Detail: Shelf", "NetApp Detail: SnapMirror", "NetApp Detail: SVM", "NetApp Detail: Volume"}
+	for _, title := range expectedName {
+		if !(utils.Contains(actualNames, title)) {
+			notFoundList = append(notFoundList, title)
+		}
+	}
+	if len(notFoundList) > 0 {
+		log.Println("The following dashboards were not imported successfully.")
+		assert.Fail(suite.T(), fmt.Sprintf("One or more dashboards %s were missing/ not imported", notFoundList))
+	}
+}
+
+func (suite *DashboardImportTestSuite) TestImportForInvalidJson() {
+	jsonDir := "grafana/dashboard_jsons"
+	if docker.IsDockerBasedPoller() {
+		containerId := docker.GetOnePollerContainers()
+		docker.CopyFile(containerId, "dashboard_jsons", "/opt/harvest/"+jsonDir)
+	} else {
+		utils.Run("cp", "-R", "dashboard_jsons", installer.HarvestHome+"/grafana")
+	}
+	status, _ := new(grafana.GrafanaMgr).Import(jsonDir)
+	if status {
+		assert.Fail(suite.T(), "Grafana import should fail but it is succeeded")
+	}
+}
+
+// In order for 'go test' to run this suite, we need to create
+// a normal test function and pass our suite to suite.Run
+func TestDashboardImportSuite(t *testing.T) {
+	suite.Run(t, new(DashboardImportTestSuite))
+}
diff --git a/integration/test/docker/docker_mgr.go b/integration/test/docker/docker_mgr.go
index 46c64dbc..2fb562ee 100644
--- a/integration/test/docker/docker_mgr.go
+++ b/integration/test/docker/docker_mgr.go
@@ -4,6 +4,8 @@ import (
 	"context"
 	"encoding/base64"
 	"encoding/json"
+	"fmt"
+	"github.com/Netapp/harvest-automation/test/utils"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/client"
 	"io"
@@ -47,6 +49,16 @@ func GetAuth() string {
 	return authStr
 }
 
+func IsDockerBasedPoller() bool {
+	containerIDs := GetContainerID("poller")
+	return len(containerIDs) > 0
+}
+
+func GetOnePollerContainers() string {
+	containerIDs := GetContainerID("poller")
+	return containerIDs[0]
+}
+
 func HasAllStarted(commandSubString string, count int) bool {
 	ctx := context.Background()
 	actualCount := 0
@@ -61,9 +73,6 @@ func HasAllStarted(commandSubString string, count int) bool {
 	for _, container := range containers {
 		if strings.Contains(container.Command, commandSubString) && container.State == "running" {
 			actualCount++
-		} else {
-			log.Println(container.Command)
-			log.Println(container.State)
 		}
 	}
 	if actualCount != count {
@@ -73,6 +82,24 @@ func HasAllStarted(commandSubString string, count int) bool {
 	return true
 }
 
+func HasStarted(imageName string) bool {
+	ctx := context.Background()
+	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
+	if err != nil {
+		panic(err)
+	}
+	containers, err := cli.ContainerList(ctx, types.ContainerListOptions{})
+	if err != nil {
+		panic(err)
+	}
+	for _, container := range containers {
+		if strings.Contains(container.Image, imageName) && container.State == "running" {
+			return true
+		}
+	}
+	return false
+}
+
 func StopContainers(commandSubString string) {
 	ctx := context.Background()
 	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
@@ -84,7 +111,7 @@ func StopContainers(commandSubString string) {
 		panic(err)
 	}
 	for _, container := range containers {
-		if strings.Contains(container.Command, commandSubString) {
+		if strings.Contains(container.Command, commandSubString) || strings.Contains(container.Image, commandSubString) {
 			log.Println("Stopping container ", container.ID[:10], "... ")
 			if err := cli.ContainerStop(ctx, container.ID, nil); err != nil {
 				panic(err)
@@ -93,6 +120,29 @@ func StopContainers(commandSubString string) {
 	}
 }
 
+func CopyFile(containerId string, src string, dest string) {
+	utils.Run("docker", "cp", src, containerId+":"+dest)
+}
+
+func GetContainerID(commandSubString string) []string {
+	var containerIds []string
+	ctx := context.Background()
+	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
+	if err != nil {
+		panic(err)
+	}
+	containers, err := cli.ContainerList(ctx, types.ContainerListOptions{})
+	if err != nil {
+		panic(err)
+	}
+	for _, container := range containers {
+		if strings.Contains(container.Command, commandSubString) || strings.Contains(container.Image, commandSubString) {
+			containerIds = append(containerIds, fmt.Sprintf("%s", container.ID))
+		}
+	}
+	return containerIds
+}
+
 func RemoveImage(imageName string) {
 	ctx := context.Background()
 	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
@@ -108,9 +158,9 @@ func RemoveImage(imageName string) {
 		PruneChildren: true,
 	}
 	for _, image := range images {
-		log.Println("Removing image ", image.RepoTags, "... ")
 		imageSummary := strings.Join(image.RepoTags, " ")
 		if strings.Contains(imageSummary, imageName) {
+			log.Println("Removing image ", image.RepoTags, "... ")
 			if _, err := cli.ImageRemove(ctx, image.ID, options); err != nil {
 				panic(err)
 			}
diff --git a/integration/test/docker_installer_test.go b/integration/test/docker_installer_test.go
index e8be14f8..0704e978 100644
--- a/integration/test/docker_installer_test.go
+++ b/integration/test/docker_installer_test.go
@@ -3,27 +3,21 @@
 package main
 
 import (
+	"fmt"
+	"github.com/Netapp/harvest-automation/test/docker"
 	"github.com/Netapp/harvest-automation/test/installer"
-	"log"
-	"os"
+	"github.com/Netapp/harvest-automation/test/utils"
 	"testing"
 )
 
 func TestDockerInstall(t *testing.T) {
-	var path = os.Getenv("BUILD_PATH")
-	if len(path) == 0 {
-		panic("BUILD_PATH variable is not set.")
+	//it will create a grafana token and configure it for dashboard export
+	if !utils.IsUrlReachable(utils.GetGrafanaHttpUrl()) {
+		panic(fmt.Errorf("Grafana is not reachable."))
 	}
-	installObject, err := installer.GetInstaller(installer.DOCKER, path)
-	if err != nil {
-		log.Println("Unable to initialize installer object")
-		panic(err)
+	utils.WriteToken(utils.CreateGrafanaToken())
+	containerIds := docker.GetContainerID("poller")
+	for _, containerId := range containerIds {
+		docker.CopyFile(containerId, installer.HarvestConfigFile, installer.HarvestHome+"/"+installer.HarvestConfigFile)
 	}
-	if installObject.Install() {
-		log.Println("Installation is successful..")
-	} else {
-		log.Println("Setup completed")
-		panic("installation is failed.")
-	}
-
 }
diff --git a/integration/test/grafana/grafana_mgr.go b/integration/test/grafana/grafana_mgr.go
new file mode 100644
index 00000000..3fac8c5a
--- /dev/null
+++ b/integration/test/grafana/grafana_mgr.go
@@ -0,0 +1,45 @@
+package grafana
+
+import (
+	"fmt"
+	"github.com/Netapp/harvest-automation/test/docker"
+	"github.com/Netapp/harvest-automation/test/installer"
+	"github.com/Netapp/harvest-automation/test/utils"
+	"log"
+	"regexp"
+)
+
+type GrafanaMgr struct {
+}
+
+func (g *GrafanaMgr) Import(jsonDir string) (bool, string) {
+	var (
+		importOutput string
+		status       bool
+	)
+	log.Println("Verify Grafana and Prometheus are configured")
+	var re = regexp.MustCompile(`404|not-found|error`)
+	if !utils.IsUrlReachable(utils.GetGrafanaHttpUrl()) {
+		panic(fmt.Errorf("grafana is not reachable"))
+	}
+	if !utils.IsUrlReachable(utils.GetPrometheusUrl()) {
+		panic(fmt.Errorf("prometheus is not reachable"))
+	}
+	log.Println("Import dashboard from grafana/dashboards")
+	containerIDs := docker.GetContainerID("poller")
+	if !docker.IsDockerBasedPoller() {
+		//assuming non docker based harvest grafana
+		log.Println("It is non docker based harvest")
+		importOutput = utils.Exec(installer.HarvestHome, "bin/grafana", "import", "--addr", utils.GetGrafanaUrl(), "--directory", jsonDir)
+	} else {
+		params := []string{"exec", containerIDs[0], "bin/grafana", "import", "--addr", "grafana:3000", "--directory", jsonDir}
+		importOutput = utils.Run("docker", params...)
+	}
+	if re.MatchString(importOutput) {
+		status = false
+	} else {
+		status = true
+	}
+	log.Println(fmt.Sprintf("Grafana import status : %t", status))
+	return status, importOutput
+}
diff --git a/integration/test/harvest.yml b/integration/test/harvest.yml
index 8c0d4256..8185f306 100644
--- a/integration/test/harvest.yml
+++ b/integration/test/harvest.yml
@@ -33,4 +33,3 @@ Pollers:
     password: netapp1!
     exporters:
       - prometheus2
-Tools:
diff --git a/integration/test/installer/docker.go b/integration/test/installer/docker.go
index 1f5473fb..5c1576cd 100644
--- a/integration/test/installer/docker.go
+++ b/integration/test/installer/docker.go
@@ -23,7 +23,7 @@ func (d *Docker) Init(path string) {
 func (d *Docker) Install() bool {
 	log.Println("Docker build : " + d.path)
 	pollerProcessName := "bin/poller"
-	pollerNames, _ := conf.GetPollerNames(HARVEST_CONFIG_FILE)
+	pollerNames, _ := conf.GetPollerNames(HarvestConfigFile)
 	docker.StopContainers(pollerProcessName)
 	docker.RemoveImage("harvest")
 	var dockerImageName string
@@ -50,7 +50,9 @@ func (d *Docker) Install() bool {
 	for _, pollerName := range pollerNames {
 		port, _ := conf.GetPrometheusExporterPorts(pollerName)
 		portString := strconv.Itoa(port)
+		ipAddress := utils.GetOutboundIP()
 		cmd := exec.Command("docker", "run", "--rm", "-p", portString+":"+portString,
+			"--add-host=localhost:"+ipAddress,
 			"--volume", path+"/harvest.yml:/opt/harvest/harvest.yml",
 			dockerImageName, "--poller", pollerName)
 		cmd.Stdout = os.Stdout
diff --git a/integration/test/installer/grafana.go b/integration/test/installer/grafana.go
new file mode 100644
index 00000000..78928559
--- /dev/null
+++ b/integration/test/installer/grafana.go
@@ -0,0 +1,40 @@
+package installer
+
+import (
+	"github.com/Netapp/harvest-automation/test/docker"
+	"github.com/Netapp/harvest-automation/test/utils"
+	"log"
+	"os"
+	"os/exec"
+	"time"
+)
+
+type Grafana struct {
+	image string
+}
+
+func (d *Grafana) Init(image string) {
+	d.image = image
+}
+
+func (d *Grafana) Install() bool {
+	log.Println("Grafana image : " + d.image)
+	imageName := "grafana"
+	docker.StopContainers(imageName)
+	docker.RemoveImage(imageName)
+	docker.PullImage(d.image)
+	cmd := exec.Command("docker", "run", "-d", "-p", utils.GrafanaPort+":"+utils.GrafanaPort, "grafana/grafana")
+	cmd.Stdout = os.Stdout
+	err := cmd.Start()
+	utils.PanicIfNotNil(err)
+	waitCount := 0
+	for waitCount < 5 {
+		waitCount++
+		time.Sleep(20 * time.Second)
+		if utils.IsUrlReachable("http://localhost:" + utils.GrafanaPort) {
+			return true
+		}
+	}
+	log.Println("Reached maximum timeout. Grafana is failed to start after 1 min")
+	return false
+}
diff --git a/integration/test/installer/installerFactory.go b/integration/test/installer/installerFactory.go
index fe765b0b..7816c96c 100644
--- a/integration/test/installer/installerFactory.go
+++ b/integration/test/installer/installerFactory.go
@@ -3,10 +3,12 @@ package installer
 import "fmt"
 
 const (
-	DOCKER              = "docker"
-	RHEL                = "rpm"
-	NATIVE              = "tar"
-	HARVEST_CONFIG_FILE = "harvest.yml"
+	DOCKER            = "docker"
+	RHEL              = "rpm"
+	NATIVE            = "tar"
+	HarvestConfigFile = "harvest.yml"
+	GRAFANA           = "grafana"
+	PROMETHEUS        = "prometheus"
 )
 
 func GetInstaller(installType string, path string) (Installer, error) {
@@ -22,6 +24,14 @@ func GetInstaller(installType string, path string) (Installer, error) {
 		d := new(Native)
 		d.Init(path)
 		return d, nil
+	} else if installType == GRAFANA {
+		d := new(Grafana)
+		d.Init(path)
+		return d, nil
+	} else if installType == PROMETHEUS {
+		d := new(Prometheus)
+		d.Init(path)
+		return d, nil
 	}
 	return nil, fmt.Errorf("Wrong installer type passed " + installType)
 }
diff --git a/integration/test/installer/prometheus.go b/integration/test/installer/prometheus.go
new file mode 100644
index 00000000..dcede9cf
--- /dev/null
+++ b/integration/test/installer/prometheus.go
@@ -0,0 +1,44 @@
+package installer
+
+import (
+	"github.com/Netapp/harvest-automation/test/docker"
+	"github.com/Netapp/harvest-automation/test/utils"
+	"log"
+	"os"
+	"os/exec"
+	"time"
+)
+
+type Prometheus struct {
+	image string
+}
+
+func (d *Prometheus) Init(image string) {
+	d.image = image
+}
+
+func (d *Prometheus) Install() bool {
+	log.Println("Prometheus image : " + d.image)
+	imageName := "prometheus"
+	docker.StopContainers(imageName)
+	docker.RemoveImage(imageName)
+	docker.PullImage(d.image)
+	path, _ := os.Getwd()
+	ipAddress := utils.GetOutboundIP()
+	cmd := exec.Command("docker", "run", "-p", utils.PrometheusPort+":"+utils.PrometheusPort,
+		"--add-host=localhost:"+ipAddress, "-v",
+		path+"/prometheus.yml:/etc/prometheus/prometheus.yml", "prom/prometheus")
+	cmd.Stdout = os.Stdout
+	err := cmd.Start()
+	utils.PanicIfNotNil(err)
+	waitCount := 0
+	for waitCount < 5 {
+		waitCount++
+		time.Sleep(20 * time.Second)
+		if utils.IsUrlReachable("http://localhost:" + utils.PrometheusPort) {
+			return true
+		}
+	}
+	log.Println("Reached maximum timeout. Prometheus is failed to start after 1 min")
+	return false
+}
diff --git a/integration/test/installer/rpm.go b/integration/test/installer/rpm.go
index 9d6dd0c3..e8eb3869 100644
--- a/integration/test/installer/rpm.go
+++ b/integration/test/installer/rpm.go
@@ -28,8 +28,7 @@ func (r *RPM) Install() bool {
 	log.Println("Installing " + rpmFileName)
 	installOutput := utils.Run("yum", "install", "-y", rpmFileName)
 	log.Println(installOutput)
-	utils.RemoveSafely(harvestFile)
-	copyErr := utils.CopyFile(HarvestHome+"/harvest.yml", harvestFile)
+	copyErr := utils.CopyFile(harvestFile, HarvestHome+"/harvest.yml")
 	if copyErr != nil {
 		return false
 	} //use file directly from the repo
diff --git a/integration/test/metric_test.go b/integration/test/metric_test.go
index 14039a4e..8d2711fb 100644
--- a/integration/test/metric_test.go
+++ b/integration/test/metric_test.go
@@ -13,7 +13,7 @@ import (
 )
 
 func TestPollerMetrics(t *testing.T) {
-	pollerNames, _ := conf.GetPollerNames(installer.HARVEST_CONFIG_FILE)
+	pollerNames, _ := conf.GetPollerNames(installer.HarvestConfigFile)
 	for _, pollerName := range pollerNames {
 		port, _ := conf.GetPrometheusExporterPorts(pollerName)
 		portString := strconv.Itoa(port)
diff --git a/integration/test/native_installer_test.go b/integration/test/native_installer_test.go
index 45f7e687..e3150746 100644
--- a/integration/test/native_installer_test.go
+++ b/integration/test/native_installer_test.go
@@ -4,6 +4,7 @@ package main
 
 import (
 	"github.com/Netapp/harvest-automation/test/installer"
+	"github.com/Netapp/harvest-automation/test/utils"
 	"log"
 	"os"
 	"testing"
@@ -14,6 +15,17 @@ func TestNativeInstall(t *testing.T) {
 	if len(path) == 0 {
 		panic("BUILD_PATH variable is not set.")
 	}
+	installObject, err := installer.GetInstaller(installer.GRAFANA, "grafana/grafana")
+	if err != nil {
+		log.Println("Unable to initialize installer object for " + installer.GRAFANA)
+		panic(err)
+	}
+	if !installObject.Install() {
+		panic(installer.GRAFANA + " installation is failed.")
+	}
+	token := utils.CreateGrafanaToken()
+	utils.WriteToken(token)
+
 	installObject, error := installer.GetInstaller(installer.NATIVE, path)
 	if error != nil {
 		log.Println("Unable to initialize installer object")
@@ -31,5 +43,14 @@ func TestNativeInstall(t *testing.T) {
 	} else {
 		t.Errorf("One or more pollers are not running.")
 	}
+	installObject, err = installer.GetInstaller(installer.PROMETHEUS, "prom/prometheus")
+	if err != nil {
+		log.Println("Unable to initialize installer object for " + installer.PROMETHEUS)
+		panic(err)
+	}
+	if !installObject.Install() {
+		panic(installer.PROMETHEUS + " installation is failed.")
+	}
+	utils.AddPrometheusToGrafana()
 
 }
diff --git a/integration/test/prometheus.yml b/integration/test/prometheus.yml
new file mode 100644
index 00000000..9f4fca13
--- /dev/null
+++ b/integration/test/prometheus.yml
@@ -0,0 +1,36 @@
+# my global config
+global:
+  scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
+  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
+  # scrape_timeout is set to the global default (10s).
+
+# Alertmanager configuration
+alerting:
+  alertmanagers:
+    - static_configs:
+        - targets:
+          # - alertmanager:9093
+
+# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
+rule_files:
+# - "first_rules.yml"
+# - "second_rules.yml"
+
+# A scrape configuration containing exactly one endpoint to scrape:
+# Here it's Prometheus itself.
+scrape_configs:
+  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
+  - job_name: "prometheus"
+
+    # metrics_path defaults to '/metrics'
+    # scheme defaults to 'http'.
+
+    static_configs:
+      - targets: ["localhost:9090"]
+
+  - job_name: 'harvest'
+    scrape_interval: 60s
+    static_configs:
+      - targets:
+          - 'localhost:12990'
+          - 'localhost:12991'
\ No newline at end of file
diff --git a/integration/test/rpm_installer_test.go b/integration/test/rpm_installer_test.go
index b2337476..a349448d 100644
--- a/integration/test/rpm_installer_test.go
+++ b/integration/test/rpm_installer_test.go
@@ -4,6 +4,7 @@ package main
 
 import (
 	"github.com/Netapp/harvest-automation/test/installer"
+	"github.com/Netapp/harvest-automation/test/utils"
 	"log"
 	"os"
 	"testing"
@@ -14,6 +15,17 @@ func TestRHELInstall(t *testing.T) {
 	if len(path) == 0 {
 		panic("BUILD_PATH variable is not set.")
 	}
+	installObject, err := installer.GetInstaller(installer.GRAFANA, "grafana/grafana")
+	if err != nil {
+		log.Println("Unable to initialize installer object for " + installer.GRAFANA)
+		panic(err)
+	}
+	if !installObject.Install() {
+		panic(installer.GRAFANA + " installation is failed.")
+	}
+	token := utils.CreateGrafanaToken()
+	utils.WriteToken(token)
+
 	installObject, error := installer.GetInstaller(installer.RHEL, path)
 	if error != nil {
 		log.Println("Unable to initialize installer object")
@@ -31,5 +43,14 @@ func TestRHELInstall(t *testing.T) {
 	} else {
 		t.Errorf("One or more pollers are not running.")
 	}
+	installObject, err = installer.GetInstaller(installer.PROMETHEUS, "prom/prometheus")
+	if err != nil {
+		log.Println("Unable to initialize installer object for " + installer.PROMETHEUS)
+		panic(err)
+	}
+	if !installObject.Install() {
+		panic(installer.PROMETHEUS + " installation is failed.")
+	}
+	utils.AddPrometheusToGrafana()
 
 }
diff --git a/integration/test/utils/http_utils.go b/integration/test/utils/http_utils.go
index 532c83a2..7766db48 100644
--- a/integration/test/utils/http_utils.go
+++ b/integration/test/utils/http_utils.go
@@ -1,6 +1,9 @@
 package utils
 
 import (
+	"bytes"
+	"encoding/json"
+	"fmt"
 	"io/ioutil"
 	"log"
 	"net/http"
@@ -18,3 +21,37 @@ func GetResponse(url string) (string, error) {
 	}
 	return string(body), nil
 }
+
+func GetResponseBody(url string) ([]byte, error) {
+	resp, err := http.Get(url)
+	if err != nil {
+		log.Fatalln(err)
+	}
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		log.Fatalln(err)
+		return nil, err
+	}
+	return body, nil
+}
+
+func SendReqAndGetRes(url string, method string,
+	buf []byte) map[string]interface{} {
+	client := &http.Client{}
+	req, err := http.NewRequest(method, url, bytes.NewBuffer(buf))
+	if err != nil {
+		fmt.Println(err)
+		panic(err)
+	}
+	req.Header.Add("Content-Type", "application/json")
+	res, err := client.Do(req)
+	PanicIfNotNil(err)
+	defer res.Body.Close()
+	body, err := ioutil.ReadAll(res.Body)
+	PanicIfNotNil(err)
+	log.Println(string(body))
+	var data map[string]interface{}
+	err = json.Unmarshal([]byte(string(body)), &data)
+	PanicIfNotNil(err)
+	return data
+}
diff --git a/integration/test/utils/utils.go b/integration/test/utils/utils.go
index 6b84068c..1afbdaab 100644
--- a/integration/test/utils/utils.go
+++ b/integration/test/utils/utils.go
@@ -2,37 +2,54 @@ package utils
 
 import (
 	"bytes"
+	"encoding/json"
 	"fmt"
+	"goharvest2/pkg/conf"
+	"goharvest2/pkg/tree/node"
 	"io"
 	"log"
+	"net"
 	"net/http"
 	"os"
 	"os/exec"
+	"strings"
+	"time"
+)
+
+const (
+	GrafanaPort    = "3000"
+	PrometheusPort = "9090"
+	GrafanaTokeKey = "grafana_api_token"
 )
 
 func Run(command string, arg ...string) string {
+	return Exec("", command, arg...)
+}
+
+func Exec(dir string, command string, arg ...string) string {
+	cmdString := command + " "
+	for _, param := range arg {
+		cmdString = cmdString + param + " "
+	}
+	fmt.Println("CMD : " + cmdString)
 	cmd := exec.Command(command, arg...)
+	if len(dir) > 0 {
+		cmd.Dir = dir
+	}
 	var out bytes.Buffer
 	var stderr bytes.Buffer
 	cmd.Stdout = &out
 	cmd.Stderr = &stderr
 	err := cmd.Run()
-	if err != nil {
-		log.Println(stderr.String())
-		panic(err)
+	fmt.Println("----------Output---------")
+	if len(out.String()) > 0 {
+		fmt.Println(out.String())
 	}
-	return out.String()
-}
-
-func Exec(dir string, command string, arg ...string) string {
-	cmd := exec.Command(command, arg...)
-	cmd.Dir = dir
-	out, err := cmd.Output()
 	if err != nil {
-		panic(err)
+		fmt.Println(err)
 	}
-	output := string(out[:])
-	return output
+	fmt.Println("-------------------------")
+	return out.String()
 }
 
 // DownloadFile will download a url to a local file. It's efficient because it will
@@ -147,3 +164,125 @@ func copyFileContents(src, dst string) (err error) {
 	err = out.Sync()
 	return
 }
+
+func IsUrlReachable(url string) bool {
+	response, errors := http.Get(url)
+	if errors == nil && response.StatusCode == 200 {
+		return true
+	}
+	return false
+}
+
+func AddPrometheusToGrafana() {
+	log.Println("Add Prometheus into Grafana")
+	url := GetGrafanaHttpUrl() + "/api/datasources"
+	method := "POST"
+	jsonValue := []byte(fmt.Sprintf(`{"name": "Prometheus", "type": "prometheus", "access": "direct",
+		"url": "%s", "isDefault": true, "basicAuth": false}`, GetPrometheusUrl()))
+	var data map[string]interface{}
+	data = SendReqAndGetRes(url, method, jsonValue)
+	key := fmt.Sprintf("%v", data["message"])
+	if key == "Datasource added" {
+		log.Println("Prometheus has been added successfully into Grafana .")
+		return
+	}
+	panic(fmt.Errorf("ERROR: unable to add Prometheus into grafana"))
+}
+
+func CreateGrafanaToken() string {
+	log.Println("Creating grafana API Key.")
+	url := GetGrafanaHttpUrl() + "/api/auth/keys"
+	method := "POST"
+	name := fmt.Sprint(time.Now().Unix())
+	values := map[string]string{"name": name, "role": "Admin"}
+	jsonValue, _ := json.Marshal(values)
+	var data map[string]interface{}
+	data = SendReqAndGetRes(url, method, jsonValue)
+	key := fmt.Sprintf("%v", data["key"])
+	if len(key) > 0 {
+		log.Println("Grafana: Token has been created successfully.")
+		return key
+	}
+	panic(fmt.Errorf("ERROR: unable to create grafana token"))
+}
+
+func PanicIfNotNil(err error) {
+	if err != nil {
+		panic(err)
+	}
+}
+
+func GetOutboundIP() string {
+	if interfaces, err := net.Interfaces(); err == nil {
+		for _, interfac := range interfaces {
+			if interfac.HardwareAddr.String() != "" {
+				if strings.Index(interfac.Name, "en") == 0 ||
+					strings.Index(interfac.Name, "eth") == 0 {
+					if addrs, err := interfac.Addrs(); err == nil {
+						for _, addr := range addrs {
+							if addr.Network() == "ip+net" {
+								pr := strings.Split(addr.String(), "/")
+								if len(pr) == 2 && len(strings.Split(pr[0], ".")) == 4 {
+									return pr[0]
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	panic(fmt.Errorf("ERROR : Failed to get ip address of this system"))
+}
+
+func WriteToken(token string) {
+	var (
+		params, tools *node.Node
+		err           error
+	)
+	filename := "harvest.yml"
+	if params, err = conf.LoadConfig(filename); err != nil {
+		PanicIfNotNil(err)
+	} else if params == nil {
+		PanicIfNotNil(fmt.Errorf("config [%s] not found", filename))
+	}
+	if tools = params.GetChildS("Tools"); tools != nil {
+		token = tools.GetChildContentS("grafana_api_token")
+		if len(token) > 0 {
+			log.Println(filename + "  has an entry for grafana token")
+			return
+		}
+	}
+	f, err := os.OpenFile(filename, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0660)
+	if err != nil {
+		fmt.Println(err)
+		panic(err)
+	}
+	defer func(f *os.File) {
+		err := f.Close()
+		PanicIfNotNil(err)
+	}(f)
+	fmt.Fprintf(f, "\n%s\n", "Tools:")
+	fmt.Fprintf(f, "  %s: %s\n", GrafanaTokeKey, token)
+}
+
+func GetGrafanaHttpUrl() string {
+	return "http://admin:admin@" + GetGrafanaUrl()
+}
+
+func GetGrafanaUrl() string {
+	return "localhost:" + GrafanaPort
+}
+
+func GetPrometheusUrl() string {
+	return "http://localhost:" + PrometheusPort
+}
+
+func Contains(s []string, str string) bool {
+	for _, v := range s {
+		if v == str {
+			return true
+		}
+	}
+	return false
+}
diff --git a/pkg/tree/node/node_test.go b/pkg/tree/node/node_test.go
new file mode 100644
index 00000000..fef00b8e
--- /dev/null
+++ b/pkg/tree/node/node_test.go
@@ -0,0 +1,71 @@
+package node
+
+import (
+	"testing"
+)
+
+func Test_simpleName(t *testing.T) {
+	tests := []struct {
+		name string
+		s    string
+		want string
+	}{
+		{name: "empty", s: "", want: ""},
+		{name: "simple", s: "abc", want: "abc"},
+		{name: "simple 1 space", s: "abc ", want: "abc"},
+		{name: "simple more space", s: "abc      ", want: "abc"},
+		{name: "simple prefix", s: "^^abc  => asdf ", want: "abc"},
+		{name: "space prefix", s: "   abc  => asdf ", want: "abc"},
+		{name: "dashed", s: "cpu-busy => zig", want: "cpu-busy"},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := simpleName(tt.s); got != tt.want {
+				t.Errorf("simpleName() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestNode_FlatList(t *testing.T) {
+	tests := []struct {
+		name  string
+		tree  *Node
+		want  string
+		count int
+	}{
+		{name: "perf", tree: makeTree("counters", "instance_name"), want: "instance_name", count: 1},
+		{name: "conf", tree: makeTree("counters", "node-details-info", "cpu-busytime"),
+			want: "node-details-info cpu-busytime", count: 1},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			list := make([]string, 0)
+			tt.tree.FlatList(&list, "")
+			if len(list) != tt.count {
+				t.Errorf("flat list has size= %v, want %v", len(list), tt.count)
+			}
+			if list[0] != tt.want {
+				t.Errorf("flat list[0] got=[%v], want=[%v]", list[0], tt.want)
+			}
+		})
+	}
+}
+
+func makeTree(names ...string) *Node {
+	tree := Node{
+		name:     []byte("root"),
+		Children: make([]*Node, 0),
+	}
+	cursor := &tree
+	for i, n := range names {
+		if i == len(names)-1 {
+			cursor.AddChild(&Node{Content: []byte(n)})
+		} else {
+			child := &Node{name: []byte(n)}
+			cursor.AddChild(child)
+			cursor = child
+		}
+	}
+	return tree.GetChildS(names[0])
+}