├── .github └── workflows │ └── scorecard.yml ├── .gitignore ├── AUTHORS.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── FAQ.md ├── LICENSE ├── NOTICE ├── README.md ├── SECURITY.md ├── SPECS.md ├── installer ├── 01.install-docker.sh ├── 02.setup-docker-dns.sh ├── 03.install-docker-compose.sh └── 04.create-stack.sh └── stack ├── .env.example ├── README.md ├── doc └── img │ ├── architecture.png │ ├── carbon emissions │ └── carbon emissions - fretta.png │ ├── cost │ └── cost-nexus-ucs.png │ ├── overview power, carbon emissions │ ├── meraki.png │ ├── ncs, asr 9k, 8k - co2eq emissions.png │ ├── ncs, asr 9k, 8k.png │ ├── nexus - co2eq emissions.png │ └── nexus.png │ ├── pcr │ ├── bw-utilization-and-distribution-per-if.png │ ├── pcr-vs-bw-utilization-asr-9k-cisco-8k.png │ ├── pcr-vs-bw-utilization-concept.png │ ├── pcr-vs-bw-utilization-ncs.png │ └── pcr-vs-traffic-cisco-8k.png │ ├── pdus │ ├── eaton pdus.png │ └── raritan pdus.png │ └── ucs │ ├── ucs - power.png │ ├── ucs - rack view 1.png │ ├── ucs - rack view 2.png │ ├── ucs - rack view 3.png │ ├── ucs - temperature.png │ └── ucs - utilization.png ├── docker-compose.yml ├── grafana └── provisioning │ ├── dashboards │ ├── Carbon emissions.json │ ├── Cost - DC - Nexus and UCS.json │ ├── Cost.json │ ├── Detailed │ │ ├── Carbon emissions - historical.json │ │ └── PCR versus Traffic.json │ ├── Home.json │ ├── Meraki.json │ ├── PDUs │ │ ├── Eaton PDUs.json │ │ └── Raritan PDUs.json │ ├── Power.json │ ├── Recommendations │ │ └── Bandwidth utilization.json │ ├── Servers │ │ ├── UCS - Rack view.json │ │ └── UCS.json │ └── dashboards.yaml │ └── datasources │ └── influxdbv2.yaml ├── influxdb ├── influxdb-data-etc │ └── .empty └── influxdb-data-var │ └── lib │ └── influxdb2 │ └── .empty ├── mdt-config ├── asr-9903.cfg ├── asr-9904.cfg ├── cisco-router-8201.cfg ├── ncs-50xx.cfg ├── ncs-540.cfg ├── ncs-540L.cfg ├── ncs-560-er.cfg └── nexus9k-c9372px.cfg └── telegraf ├── Dockerfile ├── pip-licenses.md ├── requirements.txt ├── snmp └── .hidden ├── telegraf-sample.conf └── telegraf.d ├── apic └── get-switch-power.py ├── get-co2eqkwh.py ├── meraki └── get-meraki-power.py ├── raritan-power ├── get-raritan.py ├── raritan-credentials.yml ├── raritan-pdus.yml └── requirements.txt ├── telegraf-eaton-pdu.conf ├── telegraf-electricitymap.conf ├── telegraf-mapping.conf ├── telegraf-raritan-pdu.conf ├── telegraf-redfish.conf ├── telegraf-switch-apic.conf ├── telegraf-switch-meraki.conf ├── telegraf-ucs-cimc.conf ├── telegraf-ucsm.conf ├── telegraf-xr-and-nxos.conf └── ucs-power-temp-util ├── get-ucs-power-temp-util-idb.py ├── get-ucsm-power-temp-util-idb.py ├── requirements.txt ├── ucs-credentials.yml ├── ucs-servers.yml ├── ucsm-credentials.yml └── ucsm-domains.yml /.github/workflows/scorecard.yml: -------------------------------------------------------------------------------- 1 | name: scorecard 2 | 3 | on: 4 | push: 5 | branches: 6 | # Run on pushes to default branch 7 | - main 8 | schedule: 9 | # Run weekly on Saturdays 10 | - cron: "30 1 * * 6" 11 | # Run when branch protection rules change 12 | branch_protection_rule: 13 | # Run the workflow manually 14 | workflow_dispatch: 15 | 16 | # Declare default permissions as read-only 17 | permissions: read-all 18 | 19 | jobs: 20 | run-scorecard: 21 | # Call reusable workflow file 22 | uses: cisco-ospo/.github/.github/workflows/_scorecard.yml@main 23 | permissions: 24 | id-token: write 25 | security-events: write 26 | secrets: inherit 27 | with: 28 | # Publish results of Scorecard analysis 29 | publish-results: true 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.DS_Store 3 | *.my 4 | *.mib.txt 5 | stack/influxdb/influxdb-data-etc/influx-configs 6 | stack/influxdb/influxdb-data-var/lib/influxdb2/engine 7 | stack/influxdb/influxdb-data-var/lib/influxdb2/influxd.bolt -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | ## Authors 2 | 3 | - Cristina Precup 4 | - Guillaume Ladhuie 5 | - Jean-Baptiste Lefeuvre 6 | - Oren Brigg 7 | - Patrice Nivaggioli 8 | - Philippe Tubello 9 | - Salvatore Faraone 10 | - Steven Barth 11 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributor Covenant Code of Conduct 3 | 4 | ## Our Pledge 5 | 6 | We as members, contributors, and leaders pledge to make participation in our 7 | community a harassment-free experience for everyone, regardless of age, body 8 | size, visible or invisible disability, ethnicity, sex characteristics, gender 9 | identity and expression, level of experience, education, socio-economic status, 10 | nationality, personal appearance, race, caste, color, religion, or sexual 11 | identity and orientation. 12 | 13 | We pledge to act and interact in ways that contribute to an open, welcoming, 14 | diverse, inclusive, and healthy community. 15 | 16 | ## Our Standards 17 | 18 | Examples of behavior that contributes to a positive environment for our 19 | community include: 20 | 21 | * Demonstrating empathy and kindness toward other people 22 | * Being respectful of differing opinions, viewpoints, and experiences 23 | * Giving and gracefully accepting constructive feedback 24 | * Accepting responsibility and apologizing to those affected by our mistakes, 25 | and learning from the experience 26 | * Focusing on what is best not just for us as individuals, but for the overall 27 | community 28 | 29 | Examples of unacceptable behavior include: 30 | 31 | * The use of sexualized language or imagery, and sexual attention or advances of 32 | any kind 33 | * Trolling, insulting or derogatory comments, and personal or political attacks 34 | * Public or private harassment 35 | * Publishing others' private information, such as a physical or email address, 36 | without their explicit permission 37 | * Other conduct which could reasonably be considered inappropriate in a 38 | professional setting 39 | 40 | ## Enforcement Responsibilities 41 | 42 | Community leaders are responsible for clarifying and enforcing our standards of 43 | acceptable behavior and will take appropriate and fair corrective action in 44 | response to any behavior that they deem inappropriate, threatening, offensive, 45 | or harmful. 46 | 47 | Community leaders have the right and responsibility to remove, edit, or reject 48 | comments, commits, code, wiki edits, issues, and other contributions that are 49 | not aligned to this Code of Conduct, and will communicate reasons for moderation 50 | decisions when appropriate. 51 | 52 | ## Scope 53 | 54 | This Code of Conduct applies within all community spaces, and also applies when 55 | an individual is officially representing the community in public spaces. 56 | Examples of representing our community include using an official e-mail address, 57 | posting via an official social media account, or acting as an appointed 58 | representative at an online or offline event. 59 | 60 | ## Enforcement 61 | 62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 63 | reported to the community leaders responsible for enforcement at oss-conduct@cisco.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series of 86 | actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or permanent 93 | ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within the 113 | community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.1, available at 119 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 120 | 121 | Community Impact Guidelines were inspired by 122 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 123 | 124 | For answers to common questions about this code of conduct, see the FAQ at 125 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at 126 | [https://www.contributor-covenant.org/translations][translations]. 127 | 128 | [homepage]: https://www.contributor-covenant.org 129 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 130 | [Mozilla CoC]: https://github.com/mozilla/diversity 131 | [FAQ]: https://www.contributor-covenant.org/faq 132 | [translations]: https://www.contributor-covenant.org/translations 133 | 134 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Guidance on how to contribute 2 | 3 | Contributions to this code are welcome and appreciated. 4 | Please adhere to our [Code of Conduct](./CODE_OF_CONDUCT.md) at all times. 5 | 6 | > All contributions to this code will be released under the terms of the [LICENSE](./LICENSE) of this code. By submitting a pull request or filing a bug, issue, or feature request, you are agreeing to comply with this waiver of copyright interest. Details can be found in our [LICENSE](./LICENSE). 7 | 8 | There are two primary ways to contribute: 9 | 10 | 1. Using the issue tracker 11 | 2. Changing the codebase 12 | 13 | 14 | ## Using the issue tracker 15 | 16 | Use the issue tracker to suggest feature requests, report bugs, and ask questions. This is also a great way to connect with the developers of the project as well as others who are interested in this solution. 17 | 18 | Use the issue tracker to find ways to contribute. Find a bug or a feature, mention in the issue that you will take on that effort, then follow the _Changing the codebase_ guidance below. 19 | 20 | 21 | ## Changing the codebase 22 | 23 | Generally speaking, you should fork this repository, make changes in your own fork, and then submit a pull request. All new code should have associated unit tests (if applicable) that validate implemented features and the presence or lack of defects. 24 | 25 | Additionally, the code should follow any stylistic and architectural guidelines prescribed by the project. In the absence of such guidelines, mimic the styles and patterns in the existing codebase. -------------------------------------------------------------------------------- /FAQ.md: -------------------------------------------------------------------------------- 1 | # FAQ 2 | 3 | - [FAQ](#faq) 4 | - [Cleanup database](#cleanup-database) 5 | - [Set database credentials](#set-database-credentials) 6 | - [Support a non-local database instance](#support-a-non-local-database-instance) 7 | 8 | 9 | ## Cleanup database 10 | 11 | For change of configurations or data removal: 12 | 13 | ```bash 14 | docker stop influxdb; docker rm influxdb 15 | 16 | rm -r stack/influxdb/influxdb-data-* 17 | git checkout stack/influxdb/influxdb-data-etc/.empty stack/influxdb/influxdb-data-var/lib/influxdb2/.empty 18 | 19 | docker-compose up -d influxdb 20 | ``` 21 | 22 | ## Set database credentials 23 | When creating a `.env` file as per the `.env.example`, it is recommended to change the credentials for the database (`DOCKER_INFLUXDB_INIT_USERNAME` and `DOCKER_INFLUXDB_INIT_PASSWORD`). Consequently, InfluxDB token _regeneration_ may be needed when new credentials are used. Alternatively, change the credentials from Influx's CLI by following these instructions: https://docs.influxdata.com/influxdb/v2/admin/users/change-password. 24 | 25 | To generate a new token for InfluxDB, launch the InfluxDB service and access its UI at :8086. Follow these guidelines to generate a new token: https://docs.influxdata.com/influxdb/cloud/security/tokens/create-token and save this token in `.env` as `DOCKER_INFLUXDB_INIT_ADMIN_TOKEN`. 26 | 27 | Once ready, launch the Telegraf and Grafana services that will use the token to perform read/write operations on the database. 28 | 29 | ## Support a non-local database instance 30 | 31 | In order to use data from database instances that are different than the `influxdb` service, identified by UID _INFLUXDB2B082CADEA38E_, see this reference: https://github.com/grafana/grafana/discussions/45230#discussioncomment-4088203. 32 | 33 | In short, it is required to either make a change of UIDs for the dashboard file in question or to move to a generic approach by not specifying the UID. 34 | 35 | TBD. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | green-monitoring 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | Copyright (c) 2023, Cisco Systems, Inc. and/or its affiliates 16 | 17 | This project includes software developed at Cisco Systems, Inc. and/or its affiliates. 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Green Monitoring Stack 2 | 3 | [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](./LICENSE) 4 | [![Build For Better 2024 Winner](https://static.production.devnetcloud.com/codeexchange/assets/images/DevNet-Build_For_Better_2024_Winner-Blue.svg)](https://blogs.cisco.com/developer/announcing-the-build-for-better-code-challenge-winners) 5 | 6 | 7 | ## Table of contents 8 | 9 | - [Green Monitoring Stack](#green-monitoring-stack) 10 | - [Table of contents](#table-of-contents) 11 | - [About the project](#about-the-project) 12 | - [KPIs](#kpis) 13 | - [Technology stack](#technology-stack) 14 | - [Getting started](#getting-started) 15 | - [Prerequisites](#prerequisites) 16 | - [Configuration](#configuration) 17 | - [Installation](#installation) 18 | - [Usage](#usage) 19 | - [Access](#access) 20 | - [Dashboards](#dashboards) 21 | - [Specifications](#specifications) 22 | - [FAQ](#faq) 23 | - [Contributing](#contributing) 24 | - [License](#license) 25 | - [Contact](#contact) 26 | - [Acknowledgements](#acknowledgements) 27 | 28 | 29 | ## About the project 30 | 31 | A monitoring stack with samples for collection and data exploration for sustainability purposes. 32 | 33 | The data is collected from Network, DC (compute / storage) infrastructure, third-party devices and external sources to be able to understand the **energy consumption** and its relation to traffic and bandwidth, the **cost** and the **carbon footprint** of the environment at various levels of granularity. 34 | 35 | ### KPIs 36 | 37 | | Element | KPI | 38 | | :---------- | :------------ | 39 | | network device | power
power supply load
power supply efficiency

traffic
bandwidth utilization
power consumption ratio (PCR) - [reference](SPECS.md#power-consumption-ratio-pcr)

CO2-eq emissions (+ historical)
cost| 40 | | server | power
utilization
temperature

CO2-eq emissions
cost | 41 | | pdu | power | 42 | | rack | power
_TBD:_ temperature| 43 | 44 | ### Technology stack 45 | 46 | *Architecture* 47 | ![Architecture](stack/doc/img/architecture.png) 48 | 49 | Captures data from: 50 | - IOS-XR routers 51 | - NX-OS switches 52 | - Meraki switches 53 | - UCS servers 54 | - ACI APIC 55 | - Raritan PDUs 56 | - Eaton PDUs 57 | 58 | Stores data in: 59 | - InfluxDB v2 60 | 61 | Exposes data in: 62 | - Grafana 63 | 64 | Data Flow: 65 | 66 | IOS-XR 67 | NX-OS 68 | Meraki 69 | ACI APIC -> Telegraf -> InfluxDB -> Grafana 70 | UCS: REDFISH/CIMC/UCSM 71 | Raritan PDUs 72 | Eaton PDUs 73 | 74 | --- 75 | 76 | ## Getting started 77 | 78 | ### Prerequisites 79 | 80 | [Use these instructions](./stack/README.md#prerequisites). 81 | 82 | ### Configuration 83 | [Use these instructions](./stack/README.md#configuration). 84 | 85 | ### Installation 86 | [Use these instructions](./stack/README.md#installation). 87 | 88 | ## Usage 89 | 90 | ### Access 91 | 92 | Access the two following WebUIs by replacing the `HOST_IP` placeholder with the reachable IP address of the host that runs the stack: 93 | 94 | - [Grafana](http://HOST_IP:3000) - hosts custom visualizations. 95 | - [Influx](http://HOST_IP:8086) (_credentials based on [.env](./stack/.env)_) - for exploration of raw data. 96 | 97 | ### Dashboards 98 | 99 | Overview power - Meraki - organization/switches 100 | ![Overview power - Meraki - organization/switches](stack/doc/img/overview%20power,%20carbon%20emissions/meraki.png) 101 | 102 | Overview power - DC - Nexus 103 | ![Overview power - DC - Nexus](stack/doc/img/overview%20power%2C%20carbon%20emissions/nexus.png) 104 | 105 | Overview CO2-eq emissions - DC - Nexus 106 | ![Overview CO2-eq emissions - DC - Nexus](stack/doc/img/overview%20power,%20carbon%20emissions/nexus%20-%20co2eq%20emissions.png) 107 | 108 | Overview power - NCS, ASR 9K, Cisco 8K 109 | ![Overview power - NCS, ASR 9K, Cisco 8K](stack/doc/img/overview%20power%2C%20carbon%20emissions/ncs%2C%20asr%209k%2C%208k.png) 110 | 111 | Overview CO2-eq emissions - NCS, ASR 9K, Cisco 8K 112 | ![Overview CO2-eq emissions - NCS, ASR 9K, Cisco 8K](stack/doc/img/overview%20power,%20carbon%20emissions/ncs,%20asr%209k,%208k%20-%20co2eq%20emissions.png) 113 | 114 | Historical overview of CO2-eq emissions - Fretta 115 | ![Historical overview of CO2-eq emissions - Fretta](stack/doc/img/carbon%20emissions/carbon%20emissions%20-%20fretta.png) 116 | 117 | Power - DC - UCS 118 | ![Power - DC - UCS](stack/doc/img/ucs/ucs%20-%20power.png) 119 | 120 | Temperature - DC - UCS 121 | ![Temperature - DC - UCS](stack/doc/img/ucs/ucs%20-%20temperature.png) 122 | 123 | Utilization - DC - UCS 124 | ![Utilization - DC - UCS](stack/doc/img/ucs/ucs%20-%20utilization.png) 125 | 126 | Rack view - DC - UCS 1/3 127 | ![Rack view - DC - UCS 1/3](stack/doc/img/ucs/ucs%20-%20rack%20view%201.png) 128 | 129 | Rack view - DC - UCS 2/3 130 | ![Rack view - DC - UCS 2/3](stack/doc/img/ucs/ucs%20-%20rack%20view%202.png) 131 | 132 | Rack view - DC - UCS 3/3 133 | ![Rack view - DC - UCS 3/3](stack/doc/img/ucs/ucs%20-%20rack%20view%203.png) 134 | 135 | PDUs - Raritan 136 | ![PDUs - Raritan](stack/doc/img/pdus/raritan%20pdus.png) 137 | 138 | PDUs - Eaton 139 | ![PDUs - Eaton](stack/doc/img/pdus/eaton%20pdus.png) 140 | 141 | Cost - DC - Nexus and UCS 142 | ![Cost - DC - Nexus and UCS](stack/doc/img/cost/cost-nexus-ucs.png) 143 | 144 | PCR (Power consumption ratio) versus Traffic 145 | ![PCR versus traffic - Cisco 8201](stack/doc/img/pcr/pcr-vs-traffic-cisco-8k.png) 146 | 147 | PCR (Power consumption ratio) versus Bandwidth utilization - concept 148 | ![PCR versus bandwidth utilization](stack/doc/img/pcr/pcr-vs-bw-utilization-concept.png) 149 | 150 | PCR (Power consumption ratio) versus Bandwidth utilization - NCS 151 | ![PCR versus bandwidth utilization](stack/doc/img/pcr/pcr-vs-bw-utilization-ncs.png) 152 | 153 | PCR (Power consumption ratio) versus Bandwidth utilization - ASR 9K and Cisco 8K 154 | ![PCR versus bandwidth utilization](stack/doc/img/pcr/pcr-vs-bw-utilization-asr-9k-cisco-8k.png) 155 | 156 | Bandwidth utilization and distribution per interface 157 | ![PCR versus bandwidth utilization](stack/doc/img/pcr/bw-utilization-and-distribution-per-if.png) 158 | 159 | ## Specifications 160 | 161 | The collections available are documented in [SPECS.md](SPECS.md). 162 | 163 | ## FAQ 164 | 165 | See [FAQ.md](FAQ.md). 166 | 167 | ## Contributing 168 | 169 | Contributions are highly appreciated. Please follow the guidelines documented in [CONTRIBUTING.md](./CONTRIBUTING.md). 170 | 171 | ## License 172 | 173 | Distributed under the **Apache License Version 2.0**. See the [LICENSE](./LICENSE) for more information. 174 | 175 | ## Contact 176 | 177 | - Cristina Precup - cprecup@cisco.com 178 | - Guillaume Ladhuie - gladhuie@cisco.com 179 | - Jean-Baptiste Lefeuvre - jlefeuvr@cisco.com 180 | - Oren Brigg - obrigg@cisco.com 181 | - Patrice Nivaggioli - pnivaggi@cisco.com 182 | - Philippe Tubello - ptubello@cisco.com 183 | - Salvatore Faraone - sfaraone@cisco.com 184 | - Steven Barth - stbarth@cisco.com 185 | 186 | ## Acknowledgements 187 | 188 | - [Cisco](https://www.cisco.com) 189 | - [CO2 Signal](https://www.co2signal.com) 190 | - [Electricity Maps](https://www.electricitymaps.com) 191 | - [Influx Data](https://www.influxdata.com) 192 | - [Grafana Labs](https://grafana.com) 193 | - [Eaton](https://www.eaton.com) 194 | - [Raritan](https://www.raritan.com) 195 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policies and Procedures 2 | 3 | This document outlines security procedures and general policies for the 4 | VMClarity project. 5 | 6 | - [Reporting a Bug](#reporting-a-bug) 7 | - [Disclosure Policy](#disclosure-policy) 8 | - [Comments on this Policy](#comments-on-this-policy) 9 | 10 | ## Reporting a Bug 11 | 12 | The VMClarity team and community take all security bugs in 13 | VMClarity seriously. Thank you for improving the security of 14 | VMClarity. We appreciate your efforts and responsible disclosure and 15 | will make every effort to acknowledge your contributions. 16 | 17 | Report security bugs by emailing `oss-security@cisco.com`. 18 | 19 | The lead maintainer will acknowledge your email within 48 hours, and will send a 20 | more detailed response within 48 hours indicating the next steps in handling 21 | your report. After the initial reply to your report, the security team will 22 | endeavor to keep you informed of the progress towards a fix and full 23 | announcement, and may ask for additional information or guidance. 24 | 25 | ## Disclosure Policy 26 | 27 | When the security team receives a security bug report, they will assign it to a 28 | primary handler. This person will coordinate the fix and release process, 29 | involving the following steps: 30 | 31 | - Confirm the problem and determine the affected versions. 32 | - Audit code to find any potential similar problems. 33 | - Prepare fixes for all releases still under maintenance. These fixes will be 34 | released as quickly as possible. 35 | 36 | ## Comments on this Policy 37 | 38 | If you have suggestions on how this process could be improved please submit a 39 | pull request. 40 | -------------------------------------------------------------------------------- /installer/01.install-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bash shell script for installing Docker. 4 | # 5 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | # AUTHOR(s): Cristina Precup 20 | 21 | sudo apt-get update 22 | 23 | sudo apt-get -y install \ 24 | apt-transport-https \ 25 | ca-certificates \ 26 | curl \ 27 | gnupg \ 28 | lsb-release 29 | 30 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg 31 | 32 | echo \ 33 | "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ 34 | $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null 35 | 36 | sudo apt-get update 37 | 38 | sudo apt-get install -y docker-ce docker-ce-cli containerd.io 39 | 40 | sudo usermod -aG docker `whoami` 41 | sudo groupadd docker 42 | sudo usermod -aG docker $USER 43 | 44 | sudo systemctl enable docker.service 45 | sudo systemctl enable containerd.service 46 | 47 | docker --version 48 | -------------------------------------------------------------------------------- /installer/02.setup-docker-dns.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bash shell script for setting up Docker DNS. 4 | # 5 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | # AUTHOR(s): Cristina Precup 20 | 21 | # Define DNS for alpine mirrors 22 | touch /etc/docker/daemon.json 23 | cat <> /etc/docker/daemon.json 24 | { 25 | "dns": ["8.8.8.8"] 26 | } 27 | EOT 28 | -------------------------------------------------------------------------------- /installer/03.install-docker-compose.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bash shell script for installing Docker-compose. 4 | # 5 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | # AUTHOR(s): Cristina Precup 20 | 21 | if [ -z "$HTTPS_PROXY" ] ;\ 22 | then sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose;\ 23 | else sudo curl -L -x "$HTTPS_PROXY" "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose;\ 24 | fi 25 | 26 | sudo chmod +x /usr/local/bin/docker-compose 27 | 28 | sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose 29 | 30 | docker-compose --version 31 | -------------------------------------------------------------------------------- /installer/04.create-stack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bash shell script for launching the green monitoring stack. 4 | # 5 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | # AUTHOR(s): Cristina Precup 20 | 21 | cd ../stack 22 | docker-compose up -d influxdb telegraf grafana 23 | -------------------------------------------------------------------------------- /stack/.env.example: -------------------------------------------------------------------------------- 1 | # Environment variables for green monitoring stack. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | # CONTRIBUTOR(s): Patrice Nivaggioli 19 | # Guillaume Ladhuie 20 | # Steven Barth 21 | 22 | HTTPS_PROXY= 23 | 24 | HOST_IP=192.168.1.42 25 | 26 | 27 | # Token to carbon emission-equivalent data collection 28 | # New token: Electricity Maps 29 | # See https://api-portal.electricitymaps.com 30 | # EMAPS_TOKEN=djkffjkdg 31 | 32 | # Old token: CO2 Signal 33 | # Note: deprecated, see https://www.co2signal.com. 34 | CO2_SIGNAL_TOKEN=djkffjkdg 35 | 36 | 37 | # InfluxDB credentials and specs 38 | 39 | DOCKER_INFLUXDB_INIT_MODE=setup 40 | 41 | # 1. Authentication to db 42 | DOCKER_INFLUXDB_INIT_USERNAME=testuser 43 | DOCKER_INFLUXDB_INIT_PASSWORD=changeme123 44 | 45 | # 2. Resources for db 46 | DOCKER_INFLUXDB_INIT_ORG=cisco 47 | DOCKER_INFLUXDB_INIT_BUCKET=bucket1 48 | DOCKER_INFLUXDB_INIT_RETENTION=365d 49 | 50 | # 3. Authorization token for db operations 51 | # Note: InfluxDB token regeneration may be needed when 52 | # new credentials are used. Alternatively, change the credentials 53 | # from Influx's CLI by following these instructions: 54 | # https://docs.influxdata.com/influxdb/v2/admin/users/change-password. 55 | # 56 | # To generate a new token for InfluxDB, launch the InfluxDB service, 57 | # access its UI at :8086 and follow these guidelines: 58 | # https://docs.influxdata.com/influxdb/cloud/security/tokens/create-token/ 59 | # Once ready, launch the Telegraf and Grafana services that will use the token 60 | # to perform read/write operations on the database. 61 | DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=DG5J6k_TeJ7zPCmk4Z2WDDI2E9Yp0cX7r0HOYgEXMTKJfpXFCUzyfzf4q95NIc2y7Fa_tj_c3-eSimEnTUJyEw== 62 | -------------------------------------------------------------------------------- /stack/README.md: -------------------------------------------------------------------------------- 1 | # Prerequisites, Configuration and Installation 2 | 3 | - [Prerequisites, Configuration and Installation](#prerequisites-configuration-and-installation) 4 | - [Prerequisites](#prerequisites) 5 | - [Host environment](#host-environment) 6 | - [Container platform](#container-platform) 7 | - [Configuration](#configuration) 8 | - [IOS-XR routers and NX-OS switches](#ios-xr-routers-and-nx-os-switches) 9 | - [Meraki switches](#meraki-switches) 10 | - [ACI APIC nodes](#aci-apic-nodes) 11 | - [UCSs](#ucss) 12 | - [REDFISH API](#redfish-api) 13 | - [CIMC API](#cimc-api) 14 | - [UCSM API](#ucsm-api) 15 | - [Raritan PDUs](#raritan-pdus) 16 | - [Eaton PDUs](#eaton-pdus) 17 | - [CO2-eq emissions](#co2-eq-emissions) 18 | - [Telemetry streaming](#telemetry-streaming) 19 | - [Installation](#installation) 20 | - [Create the stack of containers](#create-the-stack-of-containers) 21 | 22 | 23 | 24 | ## Prerequisites 25 | 26 | 27 | ### Host environment 28 | 29 | Ubuntu 20.04 / 22.04, cloud image: 30 | 31 | | VCPUs | Disk (in GB) | RAM (in MB) | 32 | | :---: | -----------: | ----------: | 33 | | 4 | 80 | 8192 | 34 | | 8 | 160 | 16384 | 35 | 36 | 37 | ### Container platform 38 | 39 | Install Docker, Docker-compose: 40 | 41 | ```bash 42 | cd installer 43 | 44 | bash 01.install-docker.sh 45 | 46 | # Optional 47 | sudo bash 02.setup-docker-dns.sh 48 | 49 | bash 03.install-docker-compose.sh 50 | ``` 51 | ## Configuration 52 | 53 | Configure environment and input data sources. Follow the format in the following files. For more details, see also the numbered sections below. 54 | 55 | - Environment - see: 56 | - [.env](.env) 57 | - Data enrichment: mapping geo (country, region, cc) and rack to devices - see: 58 | - [telegraf-mapping.conf](telegraf/telegraf.d/telegraf-mapping.conf) 59 | - IOS-XR routers - see: 60 | - [Configure telemetry streaming](#configure-telemetry-streaming) 61 | - NX-OS switches - see: 62 | - [Configure telemetry streaming](#configure-telemetry-streaming) 63 | - [telegraf/telegraf.d/apic/get-switch-power.py](telegraf/telegraf.d/apic/get-switch-power.py) lines #12-#15 64 | - Meraki switches - see: 65 | - [telegraf/telegraf.d/meraki/get-meraki-power.py](telegraf/telegraf.d/meraki/get-meraki-power.py) 66 | - [telegraf/telegraf.d/telegraf-switch-meraki.conf](telegraf/telegraf.d/telegraf-switch-meraki.conf) 67 | - UCS servers - see: 68 | - [telegraf/telegraf.d/telegraf-redfish.conf](telegraf/telegraf.d/telegraf-redfish.conf) 69 | - [telegraf/telegraf.d/telegraf-ucs-cimc.conf](telegraf/telegraf.d/telegraf-ucs-cimc.conf) 70 | - [telegraf/telegraf.d/telegraf-ucsm.conf](telegraf/telegraf.d/telegraf-ucsm.conf) 71 | - [telegraf/telegraf.d/ucs-power-temp-util/ucs-credentials.yml](telegraf/telegraf.d/ucs-power-temp-util/ucs-credentials.yml) 72 | - [telegraf/telegraf.d/ucs-power-temp-util/ucs-servers.yml](telegraf/telegraf.d/ucs-power-temp-util/ucs-servers.yml) 73 | - [telegraf/telegraf.d/ucs-power-temp-util/get-ucs-power-temp-util-idb.py](telegraf/telegraf.d/ucs-power-temp-util/get-ucs-power-temp-util-idb.py) lines #15-#16 74 | - ACI APIC - see: 75 | - [telegraf/telegraf.d/apic/get-switch-power.py](telegraf/telegraf.d/apic/get-switch-power.py) 76 | - [telegraf/telegraf.d/telegraf-switch-apic.conf](telegraf/telegraf.d/telegraf-switch-apic.conf) 77 | - Raritan PDUs - see: 78 | - [telegraf/telegraf.d/raritan-power/get-raritan.py](telegraf/telegraf.d/raritan-power/get-raritan.py) 79 | - [telegraf/telegraf.d/telegraf-raritan-pdu.conf](telegraf/telegraf.d/telegraf-raritan-pdu.conf) 80 | - Eaton PDUs - see: 81 | - [telegraf/telegraf.d/telegraf-eaton-pdu.conf](telegraf/telegraf.d/telegraf-eaton-pdu.conf) 82 | - Electricity Maps (CO2 Signal) - see: 83 | - [telegraf/telegraf.d/get-co2eqkwh.py](telegraf/telegraf.d/get-co2eqkwh.py) 84 | - [telegraf/telegraf.d/telegraf-electricitymap.conf](telegraf/telegraf.d/telegraf-electricitymap.conf) 85 | 86 | 1. Define the host IP (host where the containers are located), the proxy (if required), set credentials for InfluxDB, the proxy and, ideally, obtain a token from [Electricity Maps](https://api-portal.electricitymaps.com) (_Note_: Support for CO2 Signal token from https://www.co2signal.com is deprecated). 87 | 88 | _Note_: InfluxDB token regeneration is needed when new credentials are used. To generate a new token, launch the InfluxDB service, access its UI at :8086 and follow these guidelines: https://docs.influxdata.com/influxdb/cloud/security/tokens/create-token. 89 | 90 | ```bash 91 | $ cd ../stack 92 | $ cp .env.example .env 93 | $ vi .env 94 | 95 | HTTPS_PROXY= 96 | 97 | HOST_IP= 98 | 99 | # New token: Electricity Maps 100 | # See https://api-portal.electricitymaps.com 101 | # EMAPS_TOKEN= 102 | # or 103 | # Old token: CO2 Signal 104 | # Deprecated, see https://www.co2signal.com. 105 | CO2_SIGNAL_TOKEN= 106 | 107 | DOCKER_INFLUXDB_INIT_MODE=setup 108 | # 1. Authentication to db 109 | DOCKER_INFLUXDB_INIT_USERNAME= 110 | DOCKER_INFLUXDB_INIT_PASSWORD= 111 | # 2. Resources or db 112 | DOCKER_INFLUXDB_INIT_ORG=cisco 113 | DOCKER_INFLUXDB_INIT_BUCKET=bucket1 114 | DOCKER_INFLUXDB_INIT_RETENTION=365d 115 | DOCKER_INFLUXDB_INIT_ADMIN_TOKEN= 116 | 117 | CO2_SIGNAL_TOKEN= 118 | ``` 119 | 120 | 2. Configure data sources information. 121 | 122 | _Note_: Consider backing up the configuration files outside the `telegraf.d` folder and keeping in this folder only the files relevant for your environment. 123 | 124 | ```bash 125 | cd telegraf/telegraf.d 126 | ``` 127 | 128 | ### IOS-XR routers and NX-OS switches 129 | The collector listens on port 57500 for incoming gRPC telemetry. 130 | 131 | Map devices to locations for Electricity Maps: 132 | ```bash 133 | vi telegraf-mapping.conf 134 | 135 | # See sections of processors.enum 136 | ``` 137 | ### Meraki switches 138 | The collector uses the Meraki Python SDK to retrieve the data from the Meraki Dashboard API. 139 | 140 | Configure API key and organization ID: 141 | ```bash 142 | vi meraki/get-meraki-power.py 143 | # Replace with your API key 144 | api_key = "sample-api-key" 145 | # Replace with your organization ID 146 | org_id = "sample-organization-id" 147 | ``` 148 | 149 | ### ACI APIC nodes 150 | Credentials and list of APICs: 151 | ```bash 152 | vi apic/get-switch-power.py 153 | 154 | # Example: 155 | apics = {"apic0.domain.com": ""} 156 | nodes = {"3331": {}, "3332": {}} 157 | username = 'user' 158 | password = 'fgklfgkfl' 159 | ``` 160 | 161 | ### UCSs 162 | 163 | #### REDFISH API 164 | 165 | List of servers, system identifiers and credentials: 166 | ```bash 167 | vi telegraf-redfish.conf 168 | 169 | # Create one inputs.redfish entry for each server, e.g.: 170 | 171 | [[inputs.redfish]] 172 | address = "https://server-1.domain.com" 173 | computer_system_id = "XXXXXXXXXXX" 174 | username = "admin" 175 | password = "dfgkldfgkl" 176 | [...] 177 | ``` 178 | 179 | Map servers to racks and locations for Electricity Maps: 180 | ```bash 181 | vi telegraf-mapping.conf 182 | 183 | # See sections of processors.enum 184 | ``` 185 | 186 | #### CIMC API 187 | 188 | Credentials: 189 | ```bash 190 | vi ucs-power-temp-util/ucs-credentials.yml 191 | 192 | ucs: 193 | username: 194 | password: 195 | ``` 196 | 197 | List of UCSs: 198 | ```bash 199 | vi ucs-power-temp-util/ucs-servers.yml 200 | 201 | # Example with format name: IP 202 | servers: 203 | # Rack X: 204 | server-1: 10.10.10.42 205 | ``` 206 | 207 | Map servers to racks and locations for Electricity Maps: 208 | ```bash 209 | vi telegraf-mapping.conf 210 | 211 | # See sections of processors.enum 212 | ``` 213 | 214 | #### UCSM API 215 | 216 | Credentials: 217 | ```bash 218 | vi ucs-power-temp-util/ucsm-credentials.yml 219 | 220 | ucs_domains: 221 | username: 222 | password: 223 | ``` 224 | 225 | List of UCSs: 226 | ```bash 227 | vi ucs-power-temp-util/ucsm-domains.yml 228 | 229 | ucs_domains: 230 | # Rack X: 231 | LAB1: 10.10.10.42 232 | ``` 233 | 234 | Map servers to racks and locations for Electricity Maps: 235 | ```bash 236 | vi telegraf-mapping.conf 237 | 238 | # See sections of processors.enum 239 | ``` 240 | 241 | ### Raritan PDUs 242 | 243 | Credentials: 244 | ```bash 245 | vi raritan-power/raritan-credentials.yml 246 | 247 | pdu: 248 | username: 249 | password: 250 | ``` 251 | 252 | List of PDUs: 253 | ```bash 254 | vi raritan-power/raritan-pdus.yml 255 | 256 | # Example with format name: IP 257 | pdus: 258 | pdu-1: 10.10.10.42 259 | ``` 260 | 261 | ### Eaton PDUs 262 | List of PDUs: 263 | ```bash 264 | vi telegraf-eaton-pdu.conf 265 | 266 | # Edit line #4. Example: 267 | [[inputs.snmp]] 268 | agents = ["10.10.10.42"] 269 | ``` 270 | 271 | ### CO2-eq emissions 272 | Customize countries for which to fetch the CO2-eq emissions data. See line #34 and lines #103-#119 in `get-co2eqkwh.py` 273 | ```bash 274 | countryCodes = ["DE", "ES", "FR", "IT-CNO", "IT-CSO", "IT-SO"] 275 | [...] 276 | ``` 277 | 278 | ### Telemetry streaming 279 | 280 | To configure telemetry streaming, see [the configuration files located here](./mdt-config). 281 | 282 | ## Installation 283 | 284 | ### Create the stack of containers 285 | 286 | Log out and log in or re-log in to allow the user to run the docker command: 287 | 288 | ```bash 289 | sudo su - 290 | ``` 291 | 292 | Bring up each service individually: 293 | ```bash 294 | $ cd stack 295 | 296 | $ docker-compose up -d influxdb 297 | $ docker-compose up -d telegraf 298 | $ docker-compose up -d grafana 299 | ``` 300 | 301 | Alternatively, bring up all services: 302 | ```bash 303 | $ cd ../../installer 304 | 305 | $ bash 04.create-stack.sh 306 | ``` 307 | -------------------------------------------------------------------------------- /stack/doc/img/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/architecture.png -------------------------------------------------------------------------------- /stack/doc/img/carbon emissions/carbon emissions - fretta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/carbon emissions/carbon emissions - fretta.png -------------------------------------------------------------------------------- /stack/doc/img/cost/cost-nexus-ucs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/cost/cost-nexus-ucs.png -------------------------------------------------------------------------------- /stack/doc/img/overview power, carbon emissions/meraki.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/overview power, carbon emissions/meraki.png -------------------------------------------------------------------------------- /stack/doc/img/overview power, carbon emissions/ncs, asr 9k, 8k - co2eq emissions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/overview power, carbon emissions/ncs, asr 9k, 8k - co2eq emissions.png -------------------------------------------------------------------------------- /stack/doc/img/overview power, carbon emissions/ncs, asr 9k, 8k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/overview power, carbon emissions/ncs, asr 9k, 8k.png -------------------------------------------------------------------------------- /stack/doc/img/overview power, carbon emissions/nexus - co2eq emissions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/overview power, carbon emissions/nexus - co2eq emissions.png -------------------------------------------------------------------------------- /stack/doc/img/overview power, carbon emissions/nexus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/overview power, carbon emissions/nexus.png -------------------------------------------------------------------------------- /stack/doc/img/pcr/bw-utilization-and-distribution-per-if.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/pcr/bw-utilization-and-distribution-per-if.png -------------------------------------------------------------------------------- /stack/doc/img/pcr/pcr-vs-bw-utilization-asr-9k-cisco-8k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/pcr/pcr-vs-bw-utilization-asr-9k-cisco-8k.png -------------------------------------------------------------------------------- /stack/doc/img/pcr/pcr-vs-bw-utilization-concept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/pcr/pcr-vs-bw-utilization-concept.png -------------------------------------------------------------------------------- /stack/doc/img/pcr/pcr-vs-bw-utilization-ncs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/pcr/pcr-vs-bw-utilization-ncs.png -------------------------------------------------------------------------------- /stack/doc/img/pcr/pcr-vs-traffic-cisco-8k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/pcr/pcr-vs-traffic-cisco-8k.png -------------------------------------------------------------------------------- /stack/doc/img/pdus/eaton pdus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/pdus/eaton pdus.png -------------------------------------------------------------------------------- /stack/doc/img/pdus/raritan pdus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/pdus/raritan pdus.png -------------------------------------------------------------------------------- /stack/doc/img/ucs/ucs - power.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/ucs/ucs - power.png -------------------------------------------------------------------------------- /stack/doc/img/ucs/ucs - rack view 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/ucs/ucs - rack view 1.png -------------------------------------------------------------------------------- /stack/doc/img/ucs/ucs - rack view 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/ucs/ucs - rack view 2.png -------------------------------------------------------------------------------- /stack/doc/img/ucs/ucs - rack view 3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/ucs/ucs - rack view 3.png -------------------------------------------------------------------------------- /stack/doc/img/ucs/ucs - temperature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/ucs/ucs - temperature.png -------------------------------------------------------------------------------- /stack/doc/img/ucs/ucs - utilization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/doc/img/ucs/ucs - utilization.png -------------------------------------------------------------------------------- /stack/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # Main stack. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | # CONTRIBUTOR(s): Patrice Nivaggioli 19 | # Guillaume Ladhuie 20 | # Steven Barth 21 | 22 | version: '3.8' 23 | services: 24 | 25 | telegraf: 26 | build: 27 | context: ./telegraf 28 | args: 29 | HTTPS_PROXY: $HTTPS_PROXY 30 | container_name: telegraf 31 | ports: 32 | - 57500:57500 33 | hostname: telegraf 34 | command: telegraf --watch-config inotify --config-directory /etc/telegraf/telegraf.d 35 | volumes: 36 | - "./telegraf/telegraf-sample.conf:/etc/telegraf/telegraf.conf:ro" 37 | - "./telegraf/telegraf.d:/etc/telegraf/telegraf.d:ro" 38 | env_file: 39 | - .env 40 | logging: 41 | driver: "json-file" 42 | options: 43 | max-size: "20m" 44 | max-file: "10" 45 | links: 46 | - influxdb 47 | depends_on: 48 | - influxdb 49 | networks: 50 | - green 51 | restart: always 52 | 53 | influxdb: 54 | image: influxdb:2.0.4-alpine 55 | container_name: influxdb 56 | ports: 57 | - 8086:8086 58 | volumes: 59 | - influxdb-data-etc:/etc/influxdb2 60 | - influxdb-data-var:/var/lib/influxdb2 61 | env_file: 62 | - .env 63 | networks: 64 | - green 65 | restart: always 66 | 67 | grafana: 68 | image: grafana/grafana:9.2.0 69 | container_name: grafana 70 | ports: 71 | - 3000:3000 72 | volumes: 73 | - grafana-data:/var/lib/grafana 74 | - ./grafana/provisioning:/etc/grafana/provisioning:ro 75 | - ./grafana/provisioning/dashboards:/var/lib/grafana/dashboards:ro 76 | env_file: 77 | - .env 78 | environment: 79 | # Grafana has to use Proxy mode for a successful connection; 80 | # Therefore, one accesses InfluxDB through the host network. 81 | INFLUX_HOST_v2: $HOST_IP 82 | links: 83 | - influxdb 84 | depends_on: 85 | - influxdb 86 | networks: 87 | - green 88 | restart: always 89 | 90 | volumes: 91 | grafana-data: 92 | driver: local 93 | influxdb-data-etc: 94 | driver: local 95 | driver_opts: 96 | o: bind 97 | type: none 98 | device: ${PWD}/influxdb/influxdb-data-etc 99 | influxdb-data-var: 100 | driver: local 101 | driver_opts: 102 | o: bind 103 | type: none 104 | device: ${PWD}/influxdb/influxdb-data-var/lib/influxdb2 105 | 106 | networks: 107 | green: 108 | driver: bridge 109 | -------------------------------------------------------------------------------- /stack/grafana/provisioning/dashboards/Cost - DC - Nexus and UCS.json: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Copyright (c) 2022 Cisco and/or its affiliates. Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. AUTHOR(s): Cristina Precup CONTRIBUTOR(s): Salvatore Faraone ", 3 | "annotations": { 4 | "list": [ 5 | { 6 | "builtIn": 1, 7 | "datasource": { 8 | "type": "datasource", 9 | "uid": "grafana" 10 | }, 11 | "enable": true, 12 | "hide": true, 13 | "iconColor": "rgba(0, 211, 255, 1)", 14 | "name": "Annotations & Alerts", 15 | "target": { 16 | "limit": 100, 17 | "matchAny": false, 18 | "tags": [], 19 | "type": "dashboard" 20 | }, 21 | "type": "dashboard" 22 | } 23 | ] 24 | }, 25 | "description": "Cost overview", 26 | "editable": true, 27 | "fiscalYearStartMonth": 0, 28 | "graphTooltip": 0, 29 | "id": 35, 30 | "links": [], 31 | "liveNow": false, 32 | "panels": [ 33 | { 34 | "datasource": { 35 | "type": "influxdb", 36 | "uid": "INFLUXDB2B082CADEA38E" 37 | }, 38 | "description": "", 39 | "fieldConfig": { 40 | "defaults": { 41 | "color": { 42 | "mode": "thresholds" 43 | }, 44 | "decimals": 2, 45 | "displayName": "${__field.labels.__values}", 46 | "mappings": [], 47 | "thresholds": { 48 | "mode": "absolute", 49 | "steps": [ 50 | { 51 | "color": "green", 52 | "value": null 53 | }, 54 | { 55 | "color": "#EAB839", 56 | "value": 500 57 | }, 58 | { 59 | "color": "orange", 60 | "value": 600 61 | }, 62 | { 63 | "color": "red", 64 | "value": 800 65 | }, 66 | { 67 | "color": "dark-red", 68 | "value": 1000 69 | } 70 | ] 71 | }, 72 | "unit": "currencyEUR" 73 | }, 74 | "overrides": [] 75 | }, 76 | "gridPos": { 77 | "h": 21, 78 | "w": 5, 79 | "x": 0, 80 | "y": 0 81 | }, 82 | "id": 198, 83 | "options": { 84 | "colorMode": "background", 85 | "graphMode": "none", 86 | "justifyMode": "auto", 87 | "orientation": "horizontal", 88 | "reduceOptions": { 89 | "calcs": ["lastNotNull"], 90 | "fields": "", 91 | "values": false 92 | }, 93 | "textMode": "auto" 94 | }, 95 | "pluginVersion": "9.2.0", 96 | "repeatDirection": "v", 97 | "targets": [ 98 | { 99 | "datasource": { 100 | "type": "influxdb", 101 | "uid": "INFLUXDB2B082CADEA38E" 102 | }, 103 | "hide": false, 104 | "query": "//Cost based on EUR variable (extrapolated to 1h x num_hours)\n\nnum_hours = float(v: 24*${nr_days})\n\nsrc = from(bucket: \"bucket1\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r._measurement == \"show environment power\" and\n r._field == \"powersup/power_summary/tot_pow_input_actual_draw\" // Get only the 93xx\n )\n |> last()\n |> map(fn: (r) => ({\n r with\n _value: float(v:r._value) * ${cost}/1000.0 * num_hours,\n })\n )\n |> keep(columns: [\"_value\", \"source\"])\n |> yield()\n", 105 | "refId": "Dynamic measures - Total carbon emissions - sorted" 106 | }, 107 | { 108 | "datasource": { 109 | "type": "influxdb", 110 | "uid": "INFLUXDB2B082CADEA38E" 111 | }, 112 | "hide": true, 113 | "query": "//Carbon emission (extrapolated to 1h x num_hours)\n\nnum_hours = float(v: 24*${nr_days})\n\nsrc = from(bucket: \"bucket1\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"apic-switch\")\n |> filter(fn: (r) => r[\"_field\"] == \"pIn\")\n |> last()\n |> map(fn: (r) => ({\n r with\n _value: float(v:r._value) * ${cost}/1000.0 * num_hours,\n })\n )\n |> keep(columns: [\"_value\", \"name\"])\n |> yield()", 114 | "refId": "APIC - Special case: 93xx GX2B" 115 | } 116 | ], 117 | "title": "Networking cost - ${nr_days} days", 118 | "transformations": [], 119 | "type": "stat" 120 | }, 121 | { 122 | "datasource": { 123 | "type": "influxdb", 124 | "uid": "INFLUXDB2B082CADEA38E" 125 | }, 126 | "description": "", 127 | "fieldConfig": { 128 | "defaults": { 129 | "color": { 130 | "mode": "thresholds" 131 | }, 132 | "decimals": 2, 133 | "displayName": "${__field.labels.__values}", 134 | "mappings": [], 135 | "thresholds": { 136 | "mode": "absolute", 137 | "steps": [ 138 | { 139 | "color": "green", 140 | "value": null 141 | }, 142 | { 143 | "color": "#EAB839", 144 | "value": 500 145 | }, 146 | { 147 | "color": "orange", 148 | "value": 600 149 | }, 150 | { 151 | "color": "red", 152 | "value": 800 153 | }, 154 | { 155 | "color": "dark-red", 156 | "value": 1000 157 | } 158 | ] 159 | }, 160 | "unit": "currencyEUR" 161 | }, 162 | "overrides": [] 163 | }, 164 | "gridPos": { 165 | "h": 21, 166 | "w": 5, 167 | "x": 8, 168 | "y": 0 169 | }, 170 | "id": 199, 171 | "options": { 172 | "colorMode": "background", 173 | "graphMode": "none", 174 | "justifyMode": "auto", 175 | "orientation": "horizontal", 176 | "reduceOptions": { 177 | "calcs": ["lastNotNull"], 178 | "fields": "", 179 | "values": false 180 | }, 181 | "textMode": "auto" 182 | }, 183 | "pluginVersion": "9.2.0", 184 | "repeatDirection": "v", 185 | "targets": [ 186 | { 187 | "datasource": { 188 | "type": "influxdb", 189 | "uid": "INFLUXDB2B082CADEA38E" 190 | }, 191 | "hide": false, 192 | "query": "//Cost based on EUR variable (extrapolated to 1h x num_hours)\n\nnum_hours = float(v: 24*${nr_days})\n\n\n from(bucket: \"bucket1\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"redfish_power_powersupplies\")\n |> filter(fn: (r) => r[\"_field\"] == \"power_input_watts\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> group(columns: [\"address\"], mode:\"by\")\n |> map(fn: (r) => ({\n r with\n _value: float(v:r._value) * ${cost}/1000.0 * num_hours,\n })\n\n )\n |>last()\n |> yield(name: \"mean\")", 193 | "refId": "Dynamic measures - Total carbon emissions - sorted" 194 | } 195 | ], 196 | "title": "Computing cost - ${nr_days} days", 197 | "transformations": [], 198 | "type": "stat" 199 | } 200 | ], 201 | "refresh": "", 202 | "schemaVersion": 37, 203 | "style": "dark", 204 | "tags": [], 205 | "templating": { 206 | "list": [ 207 | { 208 | "current": { 209 | "selected": false, 210 | "text": "0.12", 211 | "value": "0.12" 212 | }, 213 | "description": "average cost per kWh", 214 | "hide": 0, 215 | "label": "€ per kWh", 216 | "name": "cost", 217 | "options": [ 218 | { 219 | "selected": true, 220 | "text": "0.12", 221 | "value": "0.12" 222 | } 223 | ], 224 | "query": "0.12", 225 | "skipUrlSync": false, 226 | "type": "textbox" 227 | }, 228 | { 229 | "current": { 230 | "selected": false, 231 | "text": "yellow", 232 | "value": "0.2" 233 | }, 234 | "hide": 2, 235 | "includeAll": false, 236 | "multi": false, 237 | "name": "threshold_color_coding", 238 | "options": [ 239 | { 240 | "selected": true, 241 | "text": "yellow", 242 | "value": "0.2" 243 | }, 244 | { 245 | "selected": false, 246 | "text": "orange", 247 | "value": "0.3" 248 | }, 249 | { 250 | "selected": false, 251 | "text": "red", 252 | "value": "0.4" 253 | }, 254 | { 255 | "selected": false, 256 | "text": "darkred", 257 | "value": "0.5" 258 | } 259 | ], 260 | "query": "yellow : 0.2, orange : 0.3, red : 0.4, darkred : 0.5", 261 | "skipUrlSync": false, 262 | "type": "custom" 263 | }, 264 | { 265 | "current": { 266 | "selected": true, 267 | "text": "365", 268 | "value": "365" 269 | }, 270 | "hide": 0, 271 | "includeAll": false, 272 | "label": "number of days", 273 | "multi": false, 274 | "name": "nr_days", 275 | "options": [ 276 | { 277 | "selected": false, 278 | "text": "1", 279 | "value": "1" 280 | }, 281 | { 282 | "selected": false, 283 | "text": "30", 284 | "value": "30" 285 | }, 286 | { 287 | "selected": false, 288 | "text": "90", 289 | "value": "90" 290 | }, 291 | { 292 | "selected": false, 293 | "text": "180", 294 | "value": "180" 295 | }, 296 | { 297 | "selected": true, 298 | "text": "365", 299 | "value": "365" 300 | } 301 | ], 302 | "query": "1, 30, 90, 180, 365", 303 | "queryValue": "", 304 | "skipUrlSync": false, 305 | "type": "custom" 306 | } 307 | ] 308 | }, 309 | "time": { 310 | "from": "now-3h", 311 | "to": "now" 312 | }, 313 | "timepicker": {}, 314 | "timezone": "", 315 | "title": "Cost - Nexus and UCS", 316 | "uid": "g1REO3w4z", 317 | "version": 2, 318 | "weekStart": "" 319 | } 320 | -------------------------------------------------------------------------------- /stack/grafana/provisioning/dashboards/Detailed/Carbon emissions - historical.json: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Copyright (c) 2022 Cisco and/or its affiliates. Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. AUTHOR(s): Cristina Precup CONTRIBUTOR(s): Patrice Nivaggioli ", 3 | "annotations": { 4 | "list": [ 5 | { 6 | "builtIn": 1, 7 | "datasource": { 8 | "type": "datasource", 9 | "uid": "grafana" 10 | }, 11 | "enable": true, 12 | "hide": true, 13 | "iconColor": "rgba(0, 211, 255, 1)", 14 | "name": "Annotations & Alerts", 15 | "target": { 16 | "limit": 100, 17 | "matchAny": false, 18 | "tags": [], 19 | "type": "dashboard" 20 | }, 21 | "type": "dashboard" 22 | } 23 | ] 24 | }, 25 | "editable": true, 26 | "fiscalYearStartMonth": 0, 27 | "graphTooltip": 0, 28 | "id": 36, 29 | "links": [], 30 | "liveNow": false, 31 | "panels": [ 32 | { 33 | "collapsed": false, 34 | "datasource": { 35 | "type": "datasource", 36 | "uid": "grafana" 37 | }, 38 | "gridPos": { 39 | "h": 1, 40 | "w": 24, 41 | "x": 0, 42 | "y": 0 43 | }, 44 | "id": 10, 45 | "panels": [], 46 | "targets": [ 47 | { 48 | "datasource": { 49 | "type": "datasource", 50 | "uid": "grafana" 51 | }, 52 | "refId": "A" 53 | } 54 | ], 55 | "title": "Last 1d", 56 | "type": "row" 57 | }, 58 | { 59 | "datasource": { 60 | "type": "influxdb", 61 | "uid": "INFLUXDB2B082CADEA38E" 62 | }, 63 | "description": "At 1AM of next day shows the total of the previous day. Last value (for incomplete time window) is shown in the legend.", 64 | "fieldConfig": { 65 | "defaults": { 66 | "color": { 67 | "mode": "continuous-BlPu" 68 | }, 69 | "decimals": 3, 70 | "displayName": "${__field.labels}", 71 | "mappings": [], 72 | "min": 0, 73 | "thresholds": { 74 | "mode": "absolute", 75 | "steps": [ 76 | { 77 | "color": "green", 78 | "value": null 79 | }, 80 | { 81 | "color": "#EAB839", 82 | "value": 1000 83 | }, 84 | { 85 | "color": "#EF843C", 86 | "value": 1500 87 | }, 88 | { 89 | "color": "#E24D42", 90 | "value": 2000 91 | } 92 | ] 93 | }, 94 | "unit": "massg" 95 | }, 96 | "overrides": [] 97 | }, 98 | "gridPos": { 99 | "h": 7, 100 | "w": 24, 101 | "x": 0, 102 | "y": 1 103 | }, 104 | "id": 33, 105 | "interval": "1h", 106 | "options": { 107 | "displayMode": "gradient", 108 | "minVizHeight": 10, 109 | "minVizWidth": 0, 110 | "orientation": "auto", 111 | "reduceOptions": { 112 | "calcs": ["lastNotNull"], 113 | "fields": "", 114 | "values": false 115 | }, 116 | "showUnfilled": true 117 | }, 118 | "pluginVersion": "9.2.0", 119 | "targets": [ 120 | { 121 | "datasource": { 122 | "type": "influxdb", 123 | "uid": "INFLUXDB2B082CADEA38E" 124 | }, 125 | "hide": false, 126 | "query": "import \"dict\"\nimport \"date\" //import library to add date functions\n\n//months = [1:\"January\",2:\"February\",3:\"March\",4:\"April\",5:\"May\",6:\"June\",7:\"July\",8:\"August\",9:\"September\",10:\"October\",11:\"November\",12: \"December\"]\n//days = [0:\"Sunday\", 1:\"Monday\", 2:\"Tuesday\", 3:\"Wednesday\", 4:\"Thursday\",5:\"Friday\", 6:\"Saturday\"]\n\ntimeIntervalkWh = 1h\ntimeInterval = 1h\ntimeRange = 25h\n\nsrc = from(bucket: \"bucket1\")\n |> range(start: -timeRange)\n |> filter(fn: (r) =>\n r._measurement == \"Cisco-IOS-XR-sysadmin-fretta-envmon-ui:environment/oper/power/location/pem_attributes\" and\n r._field == \"system_power_input\")\n |> window(every: timeIntervalkWh)\n |> mean()\n |> duplicate(column: \"_start\", as: \"_time\")\n\nco2eqkwh = from(bucket: \"bucket1\")\n |> range(start: -timeRange)\n |> filter(fn: (r) =>\n \t r._measurement == \"electricity-map\" and\n r._field == \"carbonIntensity\")\n |> drop(columns: [\"_measurement\"])\n |> window(every: timeIntervalkWh)\n |> mean()\n |> duplicate(column: \"_start\", as: \"_time\")\n |> drop(columns: [\"_measurement\"])\n |> keep(columns: [\"_value\", \"_time\", \"cc\", \"country\", \"region\"])\n\nj = join(\n\ttables: {t1: src, t2: co2eqkwh},\n on: [\"cc\", \"_time\"],\n\t)\n |> map(fn: (r) => ({\n r with\n //system_power_input: r._value_t1,\n //carbonIntensity: r._value_t2,\n region: r.region_t1,\n country: r.country_t1,\n _value: float(v: r._value_t1) * float(v: r._value_t2) / 1000.0,\n }))\n |> keep(columns: [\"_value\", \"_time\",\"source\"])\n |> group()\n |> aggregateWindow(every: timeInterval, fn: sum)\n |> keep(columns: [\"_value\", \"_time\"])\n |> map(fn: (r) => ({ r with //Valuemapping of monthnumber to monthname\n namedHour: date.hour(t: r._time)\n }))\n |> keep(columns: [\"_value\", \"source\", \"namedHour\", \"_time\"])\n |> group(columns: [\"namedHour\"])\n |> first() // Trick to avoid double measurements from the last bucket\n |> group()\n |> sort(columns: [\"_time\"], desc: false)\n |> pivot(rowKey: [\"_time\"], columnKey: [\"namedHour\"], valueColumn: \"_value\") //formatting for Grafana\n |> yield()", 127 | "refId": "A" 128 | } 129 | ], 130 | "timeFrom": "25h", 131 | "title": "Last 24 hours", 132 | "transformations": [], 133 | "type": "bargauge" 134 | }, 135 | { 136 | "datasource": { 137 | "type": "influxdb", 138 | "uid": "INFLUXDB2B082CADEA38E" 139 | }, 140 | "fieldConfig": { 141 | "defaults": { 142 | "color": { 143 | "mode": "palette-classic" 144 | }, 145 | "custom": { 146 | "axisCenteredZero": false, 147 | "axisColorMode": "text", 148 | "axisLabel": "", 149 | "axisPlacement": "auto", 150 | "barAlignment": 0, 151 | "drawStyle": "line", 152 | "fillOpacity": 0, 153 | "gradientMode": "none", 154 | "hideFrom": { 155 | "legend": false, 156 | "tooltip": false, 157 | "viz": false 158 | }, 159 | "lineInterpolation": "linear", 160 | "lineWidth": 1, 161 | "pointSize": 5, 162 | "scaleDistribution": { 163 | "type": "linear" 164 | }, 165 | "showPoints": "auto", 166 | "spanNulls": false, 167 | "stacking": { 168 | "group": "A", 169 | "mode": "none" 170 | }, 171 | "thresholdsStyle": { 172 | "mode": "off" 173 | } 174 | }, 175 | "decimals": 3, 176 | "mappings": [], 177 | "thresholds": { 178 | "mode": "absolute", 179 | "steps": [ 180 | { 181 | "color": "green", 182 | "value": null 183 | } 184 | ] 185 | }, 186 | "unit": "massg" 187 | }, 188 | "overrides": [ 189 | { 190 | "matcher": { 191 | "id": "byName", 192 | "options": "Lyon-23" 193 | }, 194 | "properties": [ 195 | { 196 | "id": "color", 197 | "value": { 198 | "fixedColor": "green", 199 | "mode": "fixed" 200 | } 201 | } 202 | ] 203 | }, 204 | { 205 | "matcher": { 206 | "id": "byName", 207 | "options": "Palinuro-29" 208 | }, 209 | "properties": [ 210 | { 211 | "id": "color", 212 | "value": { 213 | "fixedColor": "purple", 214 | "mode": "fixed" 215 | } 216 | } 217 | ] 218 | }, 219 | { 220 | "matcher": { 221 | "id": "byName", 222 | "options": "Picerno-58" 223 | }, 224 | "properties": [ 225 | { 226 | "id": "color", 227 | "value": { 228 | "fixedColor": "red", 229 | "mode": "fixed" 230 | } 231 | } 232 | ] 233 | }, 234 | { 235 | "matcher": { 236 | "id": "byName", 237 | "options": "Ravello-51" 238 | }, 239 | "properties": [ 240 | { 241 | "id": "color", 242 | "value": { 243 | "fixedColor": "blue", 244 | "mode": "fixed" 245 | } 246 | } 247 | ] 248 | } 249 | ] 250 | }, 251 | "gridPos": { 252 | "h": 6, 253 | "w": 24, 254 | "x": 0, 255 | "y": 8 256 | }, 257 | "id": 5, 258 | "options": { 259 | "legend": { 260 | "calcs": [], 261 | "displayMode": "list", 262 | "placement": "bottom", 263 | "showLegend": true 264 | }, 265 | "tooltip": { 266 | "mode": "single", 267 | "sort": "none" 268 | } 269 | }, 270 | "pluginVersion": "8.3.0", 271 | "targets": [ 272 | { 273 | "datasource": { 274 | "type": "influxdb", 275 | "uid": "INFLUXDB2B082CADEA38E" 276 | }, 277 | "hide": false, 278 | "query": "// Look at last 26h because during the aggregations we lose 2 hrs.\n\nsrc = from(bucket: \"bucket1\")\n |> range(start: -26h)\n |> filter(fn: (r) =>\n r._measurement == \"Cisco-IOS-XR-sysadmin-fretta-envmon-ui:environment/oper/power/location/pem_attributes\" and\n r._field == \"system_power_input\")\n |> window(every: 1h)\n |> mean()\n |> duplicate(column: \"_stop\", as: \"_time\")\n |> keep(columns: [\"_value\", \"_time\",\"source\", \"cc\", \"country\", \"region\", \"measurement\"])\n \n\nco2eqkwh = from(bucket: \"bucket1\")\n |> range(start: -26h)\n |> filter(fn: (r) =>\n \t r._measurement == \"electricity-map\" and\n r._field == \"carbonIntensity\")\n |> window(every: 1h)\n |> mean()\n |> duplicate(column: \"_stop\", as: \"_time\")\n |> drop(columns: [\"_measurement\"])\n |> keep(columns: [\"_value\", \"_time\", \"cc\", \"country\", \"region\"])\n\nj = join(\n\ttables: {t1: src, t2: co2eqkwh},\n on: [\"cc\", \"_time\"],\n\t)\n |> map(fn: (r) => ({\n r with\n \tregion: r.region_t1,\n \tcountry: r.country_t1,\n _value: float(v: r._value_t1) * float(v: r._value_t2) / 1000.0,\n\t}))\n |> keep(columns: [\"_value\", \"_time\",\"source\"])\n |> yield()", 279 | "refId": "A" 280 | } 281 | ], 282 | "timeFrom": "25h", 283 | "title": "Last 24 h per device", 284 | "type": "timeseries" 285 | }, 286 | { 287 | "collapsed": false, 288 | "datasource": { 289 | "type": "datasource", 290 | "uid": "grafana" 291 | }, 292 | "gridPos": { 293 | "h": 1, 294 | "w": 24, 295 | "x": 0, 296 | "y": 14 297 | }, 298 | "id": 12, 299 | "panels": [], 300 | "targets": [ 301 | { 302 | "datasource": { 303 | "type": "datasource", 304 | "uid": "grafana" 305 | }, 306 | "refId": "A" 307 | } 308 | ], 309 | "title": "Last 1w", 310 | "type": "row" 311 | }, 312 | { 313 | "datasource": { 314 | "type": "influxdb", 315 | "uid": "INFLUXDB2B082CADEA38E" 316 | }, 317 | "description": "At 1AM of next day shows the total of the previous day. Last value (for incomplete time window) is shown in the legend.", 318 | "fieldConfig": { 319 | "defaults": { 320 | "color": { 321 | "mode": "continuous-BlPu" 322 | }, 323 | "decimals": 3, 324 | "displayName": "${__field.labels}", 325 | "mappings": [], 326 | "min": 0, 327 | "thresholds": { 328 | "mode": "absolute", 329 | "steps": [ 330 | { 331 | "color": "green", 332 | "value": null 333 | }, 334 | { 335 | "color": "#EAB839", 336 | "value": 10000 337 | }, 338 | { 339 | "color": "#EF843C", 340 | "value": 35000 341 | }, 342 | { 343 | "color": "#E24D42", 344 | "value": 45000 345 | } 346 | ] 347 | }, 348 | "unit": "massg" 349 | }, 350 | "overrides": [] 351 | }, 352 | "gridPos": { 353 | "h": 7, 354 | "w": 24, 355 | "x": 0, 356 | "y": 15 357 | }, 358 | "id": 27, 359 | "interval": "1h", 360 | "options": { 361 | "displayMode": "gradient", 362 | "minVizHeight": 10, 363 | "minVizWidth": 0, 364 | "orientation": "auto", 365 | "reduceOptions": { 366 | "calcs": ["lastNotNull"], 367 | "fields": "", 368 | "values": false 369 | }, 370 | "showUnfilled": true 371 | }, 372 | "pluginVersion": "9.2.0", 373 | "targets": [ 374 | { 375 | "datasource": { 376 | "type": "influxdb", 377 | "uid": "INFLUXDB2B082CADEA38E" 378 | }, 379 | "hide": false, 380 | "query": "import \"dict\"\nimport \"date\"\n\ndays = [0:\"Sunday\", 1:\"Monday\", 2:\"Tuesday\", 3:\"Wednesday\", 4:\"Thursday\",5:\"Friday\", 6:\"Saturday\"]\n\ntimeIntervalkWh = 1h\ntimeInterval = 1d\ntimeRange = 8d\n\nsrc = from(bucket: \"bucket1\")\n |> range(start: -timeRange)\n |> filter(fn: (r) =>\n r._measurement == \"Cisco-IOS-XR-sysadmin-fretta-envmon-ui:environment/oper/power/location/pem_attributes\" and\n r._field == \"system_power_input\")\n |> window(every: timeIntervalkWh)\n |> mean()\n |> duplicate(column: \"_start\", as: \"_time\")\n\nco2eqkwh = from(bucket: \"bucket1\")\n |> range(start: -timeRange)\n |> filter(fn: (r) =>\n \t r._measurement == \"electricity-map\" and\n r._field == \"carbonIntensity\")\n |> window(every: timeIntervalkWh)\n |> mean()\n |> duplicate(column: \"_start\", as: \"_time\")\n |> drop(columns: [\"_measurement\"])\n |> keep(columns: [\"_value\", \"_time\", \"cc\", \"country\", \"region\"])\n\nj = join(\n\ttables: {t1: src, t2: co2eqkwh},\n on: [\"cc\", \"_time\"],\n\t)\n |> map(fn: (r) => ({\n r with\n region: r.region_t1,\n country: r.country_t1,\n _value: float(v: r._value_t1) * float(v: r._value_t2) / 1000.0,\n}))\n |> keep(columns: [\"_value\", \"_time\",\"source\"])\n |> group()\n |> aggregateWindow(every: timeInterval, fn: sum)\n |> keep(columns: [\"_value\", \"_time\"])\n |> timeShift(duration: -2h) // Influx calculates the previous day and sets the value to the next day at 1AM. Here, we want to go back 2hrs to be able to have the correct day name. Therefore, subtract by 2h (=> 23:00 of previous day will be the timestamp).\n |> map(fn: (r) => ({ r with //Valuemapping of weeknumber to weekname\n namedDay: dict.get(dict: days, key:date.weekDay(t: r._time), default: \"\")\n }))\n |> keep(columns: [\"_value\", \"source\", \"namedDay\", \"_time\"])\n |> group(columns: [\"_time\", \"namedDay\"])\n |> truncateTimeColumn(unit: 1d)\n |> group()\n |> range(start: -timeRange, stop: now()) // recalibrate the range\n |> keep(columns: [\"_time\", \"_value\", \"namedDay\"])\n |> pivot(rowKey: [], columnKey: [\"namedDay\", \"_time\"], valueColumn: \"_value\") //formatting for Grafana\n |> yield()", 381 | "refId": "D" 382 | } 383 | ], 384 | "timeFrom": "7d", 385 | "title": "Last 7 days", 386 | "transformations": [], 387 | "type": "bargauge" 388 | }, 389 | { 390 | "collapsed": false, 391 | "datasource": { 392 | "type": "datasource", 393 | "uid": "grafana" 394 | }, 395 | "gridPos": { 396 | "h": 1, 397 | "w": 24, 398 | "x": 0, 399 | "y": 22 400 | }, 401 | "id": 14, 402 | "panels": [], 403 | "targets": [ 404 | { 405 | "datasource": { 406 | "type": "datasource", 407 | "uid": "grafana" 408 | }, 409 | "refId": "A" 410 | } 411 | ], 412 | "title": "Last 1mo", 413 | "type": "row" 414 | }, 415 | { 416 | "datasource": { 417 | "type": "influxdb", 418 | "uid": "INFLUXDB2B082CADEA38E" 419 | }, 420 | "description": "Month-wise: At 1AM of next day shows the total of the previous year. Last value (for incomplete time window) is shown in the legend. See: https://docs.influxdata.com/flux/v0.x/stdlib/universe/aggregatewindow/#calendar-months-and-years", 421 | "fieldConfig": { 422 | "defaults": { 423 | "color": { 424 | "mode": "continuous-BlPu" 425 | }, 426 | "mappings": [], 427 | "min": 0, 428 | "thresholds": { 429 | "mode": "absolute", 430 | "steps": [ 431 | { 432 | "color": "green", 433 | "value": null 434 | }, 435 | { 436 | "color": "#EAB839", 437 | "value": 100000 438 | }, 439 | { 440 | "color": "#EF843C", 441 | "value": 200000 442 | }, 443 | { 444 | "color": "#E24D42", 445 | "value": 300000 446 | } 447 | ] 448 | }, 449 | "unit": "massg" 450 | }, 451 | "overrides": [] 452 | }, 453 | "gridPos": { 454 | "h": 7, 455 | "w": 24, 456 | "x": 0, 457 | "y": 23 458 | }, 459 | "id": 34, 460 | "interval": "1h", 461 | "options": { 462 | "displayMode": "gradient", 463 | "minVizHeight": 10, 464 | "minVizWidth": 0, 465 | "orientation": "auto", 466 | "reduceOptions": { 467 | "calcs": ["lastNotNull"], 468 | "fields": "", 469 | "values": false 470 | }, 471 | "showUnfilled": true 472 | }, 473 | "pluginVersion": "9.2.0", 474 | "targets": [ 475 | { 476 | "datasource": { 477 | "type": "influxdb", 478 | "uid": "INFLUXDB2B082CADEA38E" 479 | }, 480 | "hide": false, 481 | "query": "import \"dict\"\nimport \"date\"\n\ntimeIntervalkWh = 1h\ntimeInterval = 1w\ntimeRange = 1mo\n\nsrc = from(bucket: \"bucket1\")\n |> range(start: -timeRange)\n |> filter(fn: (r) =>\n r._measurement == \"Cisco-IOS-XR-sysadmin-fretta-envmon-ui:environment/oper/power/location/pem_attributes\" and\n r._field == \"system_power_input\")\n |> window(every: timeIntervalkWh)\n |> mean()\n |> duplicate(column: \"_start\", as: \"_time\")\n |> keep(columns: [\"_value\", \"_time\",\"source\", \"cc\", \"country\", \"region\", \"measurement\"])\n \n\nco2eqkwh = from(bucket: \"bucket1\")\n |> range(start: -timeRange)\n |> filter(fn: (r) =>\n r._measurement == \"electricity-map\" and\n r._field == \"carbonIntensity\")\n |> window(every: timeIntervalkWh)\n |> mean()\n |> duplicate(column: \"_start\", as: \"_time\")\n |> drop(columns: [\"_measurement\"])\n |> keep(columns: [\"_value\", \"_time\", \"cc\", \"country\", \"region\"])\n\nj = join(\n\ttables: {t1: src, t2: co2eqkwh},\n on: [\"cc\", \"_time\"],\n\t)\n |> map(fn: (r) => ({\n r with\n region: r.region_t1,\n country: r.country_t1,\n _value: float(v: r._value_t1) * float(v: r._value_t2) / 1000.0,\n }))\n |> keep(columns: [\"_value\", \"_time\",\"source\"])\n |> group()\n |> aggregateWindow(every: timeInterval, fn: sum)\n |> map(fn: (r) => ({\n r with //Valuemapping of weeknumber\n namedweek: date.week(t: r._time)\n })) \n |> keep(columns: [\"_value\", \"source\", \"namedweek\"])\n |> group(columns: [\"namedweek\"])\n |> group()\n |> pivot(rowKey: [], columnKey: [\"namedweek\"], valueColumn: \"_value\") //formatting for Grafana\n |> yield()", 482 | "refId": "B" 483 | } 484 | ], 485 | "timeFrom": "1M", 486 | "title": "Last 1 mo", 487 | "transformations": [], 488 | "type": "bargauge" 489 | }, 490 | { 491 | "datasource": { 492 | "type": "datasource", 493 | "uid": "grafana" 494 | }, 495 | "gridPos": { 496 | "h": 1, 497 | "w": 24, 498 | "x": 0, 499 | "y": 30 500 | }, 501 | "id": 19, 502 | "targets": [ 503 | { 504 | "datasource": { 505 | "type": "datasource", 506 | "uid": "grafana" 507 | }, 508 | "refId": "A" 509 | } 510 | ], 511 | "title": "Last 1y", 512 | "type": "row" 513 | }, 514 | { 515 | "datasource": { 516 | "type": "influxdb", 517 | "uid": "INFLUXDB2B082CADEA38E" 518 | }, 519 | "description": "Month-wise: At 1AM of next day shows the total of the previous year. Last value (for incomplete time window) is shown in the legend. See: https://docs.influxdata.com/flux/v0.x/stdlib/universe/aggregatewindow/#calendar-months-and-years", 520 | "fieldConfig": { 521 | "defaults": { 522 | "color": { 523 | "mode": "continuous-BlPu" 524 | }, 525 | "mappings": [], 526 | "min": 0, 527 | "thresholds": { 528 | "mode": "absolute", 529 | "steps": [ 530 | { 531 | "color": "green" 532 | }, 533 | { 534 | "color": "#EAB839", 535 | "value": 100000 536 | }, 537 | { 538 | "color": "#EF843C", 539 | "value": 200000 540 | }, 541 | { 542 | "color": "#E24D42", 543 | "value": 300000 544 | } 545 | ] 546 | }, 547 | "unit": "massg" 548 | }, 549 | "overrides": [] 550 | }, 551 | "gridPos": { 552 | "h": 7, 553 | "w": 24, 554 | "x": 0, 555 | "y": 31 556 | }, 557 | "id": 32, 558 | "interval": "1h", 559 | "options": { 560 | "displayMode": "gradient", 561 | "orientation": "auto", 562 | "reduceOptions": { 563 | "calcs": ["last"], 564 | "fields": "", 565 | "values": true 566 | }, 567 | "showUnfilled": true 568 | }, 569 | "pluginVersion": "8.3.0", 570 | "targets": [ 571 | { 572 | "datasource": { 573 | "type": "influxdb", 574 | "uid": "INFLUXDB2B082CADEA38E" 575 | }, 576 | "hide": false, 577 | "query": "import \"dict\"\nimport \"date\"\n\nmonths = [1:\"January\",2:\"February\",3:\"March\",4:\"April\",5:\"May\",6:\"June\",7:\"July\",8:\"August\",9:\"September\",10:\"October\",11:\"November\",12: \"December\"]\n\nnumberHrsAggregationkWh = 6.0\ntimeIntervalkWh = duration(v: string(v: numberHrsAggregationkWh) + \"h\")\ntimeInterval = 30d\ntimeRange = 1y\n\nsrc = from(bucket: \"bucket1\")\n |> range(start: -timeRange)\n |> filter(fn: (r) =>\n r._measurement == \"Cisco-IOS-XR-sysadmin-fretta-envmon-ui:environment/oper/power/location/pem_attributes\" and\n r._field == \"system_power_input\")\n |> window(every: timeIntervalkWh)\n |> mean()\n |> duplicate(column: \"_start\", as: \"_time\")\n |> keep(columns: [\"_value\", \"_time\",\"source\", \"cc\", \"country\", \"region\", \"measurement\"])\n \n\nco2eqkwh = from(bucket: \"bucket1\")\n |> range(start: -timeRange)\n |> filter(fn: (r) =>\n r._measurement == \"electricity-map\" and\n r._field == \"carbonIntensity\")\n |> window(every: timeIntervalkWh)\n |> mean()\n |> duplicate(column: \"_start\", as: \"_time\")\n |> drop(columns: [\"_measurement\"])\n |> keep(columns: [\"_value\", \"_time\", \"cc\", \"country\", \"region\"])\n\nj = join(\n\ttables: {t1: src, t2: co2eqkwh},\n on: [\"cc\", \"_time\"],\n\t)\n |> map(fn: (r) => ({\n r with\n //system_power_input: r._value_t1,\n //carbonIntensity: r._value_t2,\n region: r.region_t1,\n country: r.country_t1,\n _value: float(v: r._value_t1) * numberHrsAggregationkWh * float(v: r._value_t2) / 1000.0,\n //_time: r._time_t1\n }))\n |> keep(columns: [\"_value\", \"_time\",\"source\"])\n |> group()\n |> aggregateWindow(every: timeInterval, fn: sum)\n |> map(fn: (r) => ({\n r with //Valuemapping of monthnumber to monthname\n namedMonth: dict.get(dict: months, key:date.month(t: r._time), default: \"\")\n })) \n |> keep(columns: [\"_value\", \"source\", \"namedMonth\"])\n |> group(columns: [\"namedMonth\"])\n |> group()\n //|> pivot(rowKey: [], columnKey: [\"namedMonth\"], valueColumn: \"_value\") //formatting for Grafana\n |> yield()", 578 | "refId": "B" 579 | } 580 | ], 581 | "timeFrom": "1y", 582 | "title": "Last 1 year", 583 | "transformations": [], 584 | "type": "bargauge" 585 | } 586 | ], 587 | "refresh": "5m", 588 | "schemaVersion": 37, 589 | "style": "dark", 590 | "tags": [], 591 | "templating": { 592 | "list": [] 593 | }, 594 | "time": { 595 | "from": "now-1m", 596 | "to": "now" 597 | }, 598 | "timepicker": { 599 | "refresh_intervals": ["5m", "15m", "30m", "1h", "1d", "1w"] 600 | }, 601 | "timezone": "", 602 | "title": "Carbon emissions - historical - Fretta", 603 | "uid": "TqS6nVS4z", 604 | "version": 1, 605 | "weekStart": "" 606 | } 607 | -------------------------------------------------------------------------------- /stack/grafana/provisioning/dashboards/Home.json: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Copyright (c) 2022 Cisco and/or its affiliates. Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. AUTHOR(s): Cristina Precup ", 3 | "annotations": { 4 | "list": [ 5 | { 6 | "builtIn": 1, 7 | "datasource": "-- Grafana --", 8 | "enable": true, 9 | "hide": true, 10 | "iconColor": "rgba(0, 211, 255, 1)", 11 | "name": "Annotations & Alerts", 12 | "target": { 13 | "limit": 100, 14 | "matchAny": false, 15 | "tags": [], 16 | "type": "dashboard" 17 | }, 18 | "type": "dashboard" 19 | } 20 | ] 21 | }, 22 | "editable": true, 23 | "fiscalYearStartMonth": 0, 24 | "graphTooltip": 0, 25 | "id": 12, 26 | "links": [], 27 | "liveNow": false, 28 | "panels": [ 29 | { 30 | "description": "", 31 | "gridPos": { 32 | "h": 3, 33 | "w": 24, 34 | "x": 0, 35 | "y": 0 36 | }, 37 | "id": 1, 38 | "options": { 39 | "content": "# Welcome to the Green Monitoring\n\n", 40 | "mode": "markdown" 41 | }, 42 | "pluginVersion": "8.3.0", 43 | "transparent": true, 44 | "type": "text" 45 | }, 46 | { 47 | "gridPos": { 48 | "h": 13, 49 | "w": 24, 50 | "x": 0, 51 | "y": 3 52 | }, 53 | "id": 3, 54 | "links": [], 55 | "options": { 56 | "maxItems": 30, 57 | "query": "", 58 | "showHeadings": true, 59 | "showRecentlyViewed": true, 60 | "showSearch": true, 61 | "showStarred": true, 62 | "tags": [] 63 | }, 64 | "pluginVersion": "8.3.0", 65 | "tags": [], 66 | "title": "Dashboards", 67 | "type": "dashlist" 68 | } 69 | ], 70 | "schemaVersion": 33, 71 | "style": "dark", 72 | "tags": [], 73 | "templating": { 74 | "list": [] 75 | }, 76 | "time": { 77 | "from": "now-6h", 78 | "to": "now" 79 | }, 80 | "timepicker": { 81 | "hidden": true, 82 | "refresh_intervals": [ 83 | "5s", 84 | "10s", 85 | "30s", 86 | "1m", 87 | "5m", 88 | "15m", 89 | "30m", 90 | "1h", 91 | "2h", 92 | "1d" 93 | ], 94 | "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"], 95 | "type": "timepicker" 96 | }, 97 | "timezone": "browser", 98 | "title": "Home", 99 | "uid": "lI5Bsy-7z", 100 | "version": 1, 101 | "weekStart": "" 102 | } 103 | -------------------------------------------------------------------------------- /stack/grafana/provisioning/dashboards/Meraki.json: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. AUTHOR(s): Cristina Precup , Oren Brigg ", 3 | "annotations": { 4 | "list": [ 5 | { 6 | "builtIn": 1, 7 | "datasource": { 8 | "type": "grafana", 9 | "uid": "-- Grafana --" 10 | }, 11 | "enable": true, 12 | "hide": true, 13 | "iconColor": "rgba(0, 211, 255, 1)", 14 | "name": "Annotations & Alerts", 15 | "target": { 16 | "limit": 100, 17 | "matchAny": false, 18 | "tags": [], 19 | "type": "dashboard" 20 | }, 21 | "type": "dashboard" 22 | } 23 | ] 24 | }, 25 | "editable": true, 26 | "fiscalYearStartMonth": 0, 27 | "graphTooltip": 0, 28 | "id": 17, 29 | "links": [], 30 | "liveNow": false, 31 | "panels": [ 32 | { 33 | "gridPos": { 34 | "h": 1, 35 | "w": 24, 36 | "x": 0, 37 | "y": 0 38 | }, 39 | "id": 5, 40 | "panels": [], 41 | "repeat": "org_id", 42 | "repeatDirection": "h", 43 | "title": "Organization: ${org_id}", 44 | "type": "row" 45 | }, 46 | { 47 | "datasource": { 48 | "type": "influxdb", 49 | "uid": "INFLUXDB2B082CADEA38E" 50 | }, 51 | "description": "", 52 | "fieldConfig": { 53 | "defaults": { 54 | "color": { 55 | "mode": "palette-classic" 56 | }, 57 | "custom": { 58 | "axisCenteredZero": false, 59 | "axisColorMode": "text", 60 | "axisLabel": "", 61 | "axisPlacement": "auto", 62 | "barAlignment": 0, 63 | "drawStyle": "line", 64 | "fillOpacity": 0, 65 | "gradientMode": "none", 66 | "hideFrom": { 67 | "legend": false, 68 | "tooltip": false, 69 | "viz": false 70 | }, 71 | "lineInterpolation": "linear", 72 | "lineWidth": 1, 73 | "pointSize": 5, 74 | "scaleDistribution": { 75 | "type": "linear" 76 | }, 77 | "showPoints": "auto", 78 | "spanNulls": false, 79 | "stacking": { 80 | "group": "A", 81 | "mode": "none" 82 | }, 83 | "thresholdsStyle": { 84 | "mode": "off" 85 | } 86 | }, 87 | "mappings": [], 88 | "thresholds": { 89 | "mode": "absolute", 90 | "steps": [ 91 | { 92 | "color": "green", 93 | "value": null 94 | }, 95 | { 96 | "color": "red", 97 | "value": 80 98 | } 99 | ] 100 | }, 101 | "unit": "watt" 102 | }, 103 | "overrides": [] 104 | }, 105 | "gridPos": { 106 | "h": 9, 107 | "w": 12, 108 | "x": 0, 109 | "y": 1 110 | }, 111 | "id": 9, 112 | "options": { 113 | "legend": { 114 | "calcs": [], 115 | "displayMode": "list", 116 | "placement": "bottom", 117 | "showLegend": true 118 | }, 119 | "tooltip": { 120 | "mode": "single", 121 | "sort": "none" 122 | } 123 | }, 124 | "targets": [ 125 | { 126 | "datasource": { 127 | "type": "influxdb", 128 | "uid": "INFLUXDB2B082CADEA38E" 129 | }, 130 | "hide": false, 131 | "query": "from(bucket: \"bucket1\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"meraki-switch\")\n |> filter(fn: (r) => r[\"_field\"] == \"power\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false, timeSrc: \"_start\")\n |> filter(fn: (r) => not exists r.switch_name and not exists r.switch_serial and exists r.org_id)\n |> filter(fn: (r) => r.org_id == \"${org_id}\")\n |> drop(columns: [\"host\", \"org_id\"])\n |> yield(name: \"mean\")", 132 | "refId": "A" 133 | } 134 | ], 135 | "title": "Organisation: switches power", 136 | "type": "timeseries" 137 | }, 138 | { 139 | "datasource": { 140 | "type": "influxdb", 141 | "uid": "INFLUXDB2B082CADEA38E" 142 | }, 143 | "fieldConfig": { 144 | "defaults": { 145 | "color": { 146 | "mode": "palette-classic" 147 | }, 148 | "custom": { 149 | "axisCenteredZero": false, 150 | "axisColorMode": "text", 151 | "axisLabel": "", 152 | "axisPlacement": "auto", 153 | "barAlignment": 0, 154 | "drawStyle": "line", 155 | "fillOpacity": 0, 156 | "gradientMode": "none", 157 | "hideFrom": { 158 | "legend": false, 159 | "tooltip": false, 160 | "viz": false 161 | }, 162 | "lineInterpolation": "linear", 163 | "lineWidth": 1, 164 | "pointSize": 5, 165 | "scaleDistribution": { 166 | "type": "linear" 167 | }, 168 | "showPoints": "auto", 169 | "spanNulls": false, 170 | "stacking": { 171 | "group": "A", 172 | "mode": "none" 173 | }, 174 | "thresholdsStyle": { 175 | "mode": "off" 176 | } 177 | }, 178 | "displayName": "${__field.labels.__values}", 179 | "mappings": [], 180 | "thresholds": { 181 | "mode": "absolute", 182 | "steps": [ 183 | { 184 | "color": "green", 185 | "value": null 186 | }, 187 | { 188 | "color": "red", 189 | "value": 80 190 | } 191 | ] 192 | }, 193 | "unit": "watt" 194 | }, 195 | "overrides": [] 196 | }, 197 | "gridPos": { 198 | "h": 9, 199 | "w": 12, 200 | "x": 12, 201 | "y": 1 202 | }, 203 | "id": 7, 204 | "options": { 205 | "legend": { 206 | "calcs": [], 207 | "displayMode": "table", 208 | "placement": "right", 209 | "showLegend": true 210 | }, 211 | "tooltip": { 212 | "mode": "single", 213 | "sort": "none" 214 | } 215 | }, 216 | "targets": [ 217 | { 218 | "datasource": { 219 | "type": "influxdb", 220 | "uid": "INFLUXDB2B082CADEA38E" 221 | }, 222 | "hide": false, 223 | "query": "import \"strings\"\n\nfrom(bucket: \"bucket1\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"meraki-switch\")\n |> filter(fn: (r) => r[\"_field\"] == \"power\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false, timeSrc: \"_start\")\n |> filter(fn: (r) => exists r.switch_name and exists r.switch_serial and exists r.org_id)\n |> filter(fn: (r) => r.org_id == \"${org_id}\")\n |> drop(columns: [\"host\", \"org_id\"])\n |> yield(name: \"mean\")", 224 | "refId": "A" 225 | } 226 | ], 227 | "title": "Organisation: switches PoE", 228 | "type": "timeseries" 229 | } 230 | ], 231 | "schemaVersion": 37, 232 | "style": "dark", 233 | "tags": [], 234 | "templating": { 235 | "list": [ 236 | { 237 | "current": { 238 | "selected": false, 239 | "text": "558157", 240 | "value": "558157" 241 | }, 242 | "datasource": { 243 | "type": "influxdb", 244 | "uid": "INFLUXDB2B082CADEA38E" 245 | }, 246 | "definition": "import \"influxdata/influxdb/v1\"\n\nv1.measurementTagValues(\n bucket: \"bucket1\",\n measurement: \"meraki-switch\",\n tag: \"org_id\"\n)", 247 | "description": "Meraki Organization ID", 248 | "hide": 0, 249 | "includeAll": false, 250 | "multi": false, 251 | "name": "org_id", 252 | "options": [], 253 | "query": "import \"influxdata/influxdb/v1\"\n\nv1.measurementTagValues(\n bucket: \"bucket1\",\n measurement: \"meraki-switch\",\n tag: \"org_id\"\n)", 254 | "refresh": 2, 255 | "regex": "", 256 | "skipUrlSync": false, 257 | "sort": 0, 258 | "type": "query" 259 | } 260 | ] 261 | }, 262 | "time": { 263 | "from": "now-3h", 264 | "to": "now" 265 | }, 266 | "timepicker": {}, 267 | "timezone": "", 268 | "title": "Meraki", 269 | "uid": "n8bbKD3Vk", 270 | "version": 2, 271 | "weekStart": "" 272 | } 273 | -------------------------------------------------------------------------------- /stack/grafana/provisioning/dashboards/PDUs/Eaton PDUs.json: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Copyright (c) 2022 Cisco and/or its affiliates. Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. AUTHOR(s): Cristina Precup ", 3 | "annotations": { 4 | "list": [ 5 | { 6 | "builtIn": 1, 7 | "datasource": { 8 | "type": "datasource", 9 | "uid": "grafana" 10 | }, 11 | "enable": true, 12 | "hide": true, 13 | "iconColor": "rgba(0, 211, 255, 1)", 14 | "name": "Annotations & Alerts", 15 | "target": { 16 | "limit": 100, 17 | "matchAny": false, 18 | "tags": [], 19 | "type": "dashboard" 20 | }, 21 | "type": "dashboard" 22 | } 23 | ] 24 | }, 25 | "editable": true, 26 | "fiscalYearStartMonth": 0, 27 | "graphTooltip": 0, 28 | "id": 31, 29 | "links": [], 30 | "liveNow": false, 31 | "panels": [ 32 | { 33 | "datasource": { 34 | "type": "influxdb", 35 | "uid": "INFLUXDB2B082CADEA38E" 36 | }, 37 | "description": "", 38 | "fieldConfig": { 39 | "defaults": { 40 | "color": { 41 | "mode": "palette-classic" 42 | }, 43 | "custom": { 44 | "axisCenteredZero": false, 45 | "axisColorMode": "text", 46 | "axisLabel": "", 47 | "axisPlacement": "auto", 48 | "barAlignment": 0, 49 | "drawStyle": "line", 50 | "fillOpacity": 0, 51 | "gradientMode": "none", 52 | "hideFrom": { 53 | "legend": false, 54 | "tooltip": false, 55 | "viz": false 56 | }, 57 | "lineInterpolation": "linear", 58 | "lineWidth": 1, 59 | "pointSize": 5, 60 | "scaleDistribution": { 61 | "type": "linear" 62 | }, 63 | "showPoints": "auto", 64 | "spanNulls": false, 65 | "stacking": { 66 | "group": "A", 67 | "mode": "none" 68 | }, 69 | "thresholdsStyle": { 70 | "mode": "off" 71 | } 72 | }, 73 | "mappings": [], 74 | "thresholds": { 75 | "mode": "absolute", 76 | "steps": [ 77 | { 78 | "color": "green", 79 | "value": null 80 | } 81 | ] 82 | }, 83 | "unit": "watt" 84 | }, 85 | "overrides": [] 86 | }, 87 | "gridPos": { 88 | "h": 9, 89 | "w": 12, 90 | "x": 0, 91 | "y": 0 92 | }, 93 | "id": 2, 94 | "options": { 95 | "legend": { 96 | "calcs": [], 97 | "displayMode": "list", 98 | "placement": "bottom", 99 | "showLegend": true 100 | }, 101 | "tooltip": { 102 | "mode": "single", 103 | "sort": "none" 104 | } 105 | }, 106 | "targets": [ 107 | { 108 | "datasource": { 109 | "type": "influxdb", 110 | "uid": "INFLUXDB2B082CADEA38E" 111 | }, 112 | "query": "from(bucket: \"bucket1\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"eaton_input_power\")\n |> filter(fn: (r) => r[\"_field\"] == \"inputWatts\")\n |> drop(columns: [\"phase\"])\n |> aggregateWindow(every: v.windowPeriod, fn: sum, createEmpty: false)", 113 | "refId": "A" 114 | } 115 | ], 116 | "title": "Input", 117 | "type": "timeseries" 118 | } 119 | ], 120 | "refresh": "30s", 121 | "schemaVersion": 37, 122 | "style": "dark", 123 | "tags": [], 124 | "templating": { 125 | "list": [] 126 | }, 127 | "time": { 128 | "from": "now-3h", 129 | "to": "now" 130 | }, 131 | "timepicker": {}, 132 | "timezone": "", 133 | "title": "Eaton PDUs", 134 | "uid": "EwCI54IVz", 135 | "version": 1, 136 | "weekStart": "" 137 | } 138 | -------------------------------------------------------------------------------- /stack/grafana/provisioning/dashboards/dashboards.yaml: -------------------------------------------------------------------------------- 1 | # Dashboards provisioning for the visualization tool. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | apiVersion: 1 20 | 21 | providers: 22 | - name: 'provider-1' 23 | orgId: 1 24 | folder: '' 25 | folderUid: '' 26 | type: file 27 | disableDeletion: false 28 | updateIntervalSeconds: 10 29 | allowUiUpdates: false 30 | options: 31 | path: /var/lib/grafana/dashboards 32 | foldersFromFilesStructure: true 33 | -------------------------------------------------------------------------------- /stack/grafana/provisioning/datasources/influxdbv2.yaml: -------------------------------------------------------------------------------- 1 | # Datasource configuration for the visualization tool. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | apiVersion: 1 20 | 21 | datasources: 22 | - name: InfluxDB-2 23 | type: influxdb 24 | uid: INFLUXDB2B082CADEA38E 25 | access: proxy 26 | url: http://$INFLUX_HOST_v2:8086 27 | secureJsonData: 28 | token: $DOCKER_INFLUXDB_INIT_ADMIN_TOKEN 29 | jsonData: 30 | version: Flux 31 | organization: $DOCKER_INFLUXDB_INIT_ORG 32 | defaultBucket: $DOCKER_INFLUXDB_INIT_BUCKET 33 | -------------------------------------------------------------------------------- /stack/influxdb/influxdb-data-etc/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/influxdb/influxdb-data-etc/.empty -------------------------------------------------------------------------------- /stack/influxdb/influxdb-data-var/lib/influxdb2/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/influxdb/influxdb-data-var/lib/influxdb2/.empty -------------------------------------------------------------------------------- /stack/mdt-config/asr-9903.cfg: -------------------------------------------------------------------------------- 1 | telemetry model-driven 2 | destination-group green 3 | address-family ipv4 HOST_IP port 57500 4 | encoding self-describing-gpb 5 | protocol grpc no-tls 6 | ! 7 | ! 8 | sensor-group green-envmon 9 | sensor-path Cisco-IOS-XR-sysadmin-asr9k-envmon-ui:environment/oper/power/location 10 | ! 11 | sensor-group green-envmon-data-rate 12 | sensor-path Cisco-IOS-XR-pfi-im-cmd-oper:interfaces/interface-briefs/interface-brief 13 | sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/total/data-rate/input-data-rate 14 | sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/total/data-rate/output-data-rate 15 | ! 16 | subscription green 17 | sensor-group-id green-envmon sample-interval 30000 18 | sensor-group-id green-envmon-data-rate sample-interval 120000 19 | destination-id green 20 | source-interface MgmtEth0/RP0/CPU0/0 21 | ! 22 | ! 23 | -------------------------------------------------------------------------------- /stack/mdt-config/asr-9904.cfg: -------------------------------------------------------------------------------- 1 | tpa 2 | vrf default OR MGMT 3 | address-family ipv4 4 | default-route mgmt 5 | update-source dataports MgmtEth0/RSP0/CPU0/0 6 | ! 7 | ! 8 | ! 9 | 10 | telemetry model-driven 11 | destination-group green 12 | address-family ipv4 HOST_IP port 57500 13 | encoding self-describing-gpb 14 | protocol grpc no-tls 15 | ! 16 | ! 17 | sensor-group green-envmon 18 | sensor-path Cisco-IOS-XR-sysadmin-asr9k-envmon-ui:environment/oper/power/location 19 | ! 20 | sensor-group green-envmon-data-rate 21 | sensor-path Cisco-IOS-XR-pfi-im-cmd-oper:interfaces/interface-briefs/interface-brief 22 | sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/total/data-rate/input-data-rate 23 | sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/total/data-rate/output-data-rate 24 | ! 25 | subscription green 26 | sensor-group-id green-envmon sample-interval 30000 27 | sensor-group-id green-envmon-data-rate sample-interval 120000 28 | destination-id green 29 | source-interface MgmtEth 0/RSP0/CPU0/0 30 | ! 31 | ! 32 | -------------------------------------------------------------------------------- /stack/mdt-config/cisco-router-8201.cfg: -------------------------------------------------------------------------------- 1 | telemetry model-driven 2 | destination-group green 3 | address-family ipv4 HOST_IP port 57500 4 | encoding self-describing-gpb 5 | protocol grpc no-tls 6 | ! 7 | ! 8 | sensor-group green-envmon 9 | sensor-path Cisco-IOS-XR-envmon-oper:environmental-monitoring 10 | sensor-path Cisco-IOS-XR-envmon-oper:power-management/rack/chassis 11 | sensor-path Cisco-IOS-XR-envmon-oper:power-management/rack/consumers 12 | sensor-path Cisco-IOS-XR-envmon-oper:power-management/rack/producers 13 | sensor-path Cisco-IOS-XR-invmgr-oper:inventory/entities/entity/attributes/env-sensor-info 14 | sensor-path Cisco-IOS-XR-pfi-im-cmd-oper:interfaces/interface-briefs/interface-brief 15 | sensor-path Cisco-IOS-XR-invmgr-oper:inventory/entities/entity/attributes/inv-basic-bag/power-capacity 16 | ! 17 | sensor-group green-envmon-data-rate 18 | sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/total/data-rate/input-data-rate 19 | sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/total/data-rate/output-data-rate 20 | 21 | subscription green 22 | sensor-group-id green-envmon sample-interval 30000 23 | sensor-group-id green-envmon-data-rate sample-interval 120000 24 | destination-id green 25 | source-interface MgmtEth0/RP0/CPU0/0 26 | ! 27 | ! 28 | -------------------------------------------------------------------------------- /stack/mdt-config/ncs-50xx.cfg: -------------------------------------------------------------------------------- 1 | tpa 2 | vrf default OR MGMT 3 | address-family ipv4 4 | default-route mgmt 5 | update-source dataports MgmtEth0/RP0/CPU0/0 6 | ! 7 | ! 8 | ! 9 | 10 | telemetry model-driven 11 | destination-group green 12 | address-family ipv4 HOST_IP port 57500 13 | encoding self-describing-gpb 14 | protocol grpc no-tls 15 | ! 16 | ! 17 | sensor-group green-envmon 18 | sensor-path Cisco-IOS-XR-sysadmin-fretta-envmon-ui:environment/oper/power 19 | ! 20 | sensor-group green-envmon-data-rate 21 | sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/total/data-rate/input-data-rate 22 | sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/total/data-rate/output-data-rate 23 | ! 24 | subscription green 25 | sensor-group-id green-envmon sample-interval 30000 26 | sensor-group-id green-envmon-data-rate sample-interval 120000 27 | destination-id green 28 | source-interface MgmtEth0/RP0/CPU0/0 29 | ! 30 | ! -------------------------------------------------------------------------------- /stack/mdt-config/ncs-540.cfg: -------------------------------------------------------------------------------- 1 | telemetry model-driven 2 | destination-group green 3 | address-family ipv4 HOST_IP port 57500 4 | encoding self-describing-gpb 5 | protocol grpc no-tls 6 | ! 7 | ! 8 | sensor-group green-envmon 9 | sensor-path Cisco-IOS-XR-sysadmin-fretta-envmon-ui:environment/oper/power 10 | ! 11 | sensor-group green-envmon-data-rate 12 | sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/total/data-rate/input-data-rate 13 | sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/total/data-rate/output-data-rate 14 | ! 15 | subscription green 16 | sensor-group-id green-envmon sample-interval 60000 17 | sensor-group-id green-envmon-data-rate sample-interval 120000 18 | destination-id green 19 | source-interface MgmtEth0/RP0/CPU0/0 20 | ! 21 | ! -------------------------------------------------------------------------------- /stack/mdt-config/ncs-540L.cfg: -------------------------------------------------------------------------------- 1 | telemetry model-driven 2 | destination-group green 3 | address-family ipv4 HOST_IP port 57500 4 | encoding self-describing-gpb 5 | protocol grpc no-tls 6 | ! 7 | ! 8 | sensor-group green-envmon 9 | sensor-path Cisco-IOS-XR-envmon-oper:environmental-monitoring 10 | sensor-path Cisco-IOS-XR-envmon-oper:power-management/rack/chassis 11 | sensor-path Cisco-IOS-XR-envmon-oper:power-management/rack/consumers 12 | sensor-path Cisco-IOS-XR-envmon-oper:power-management/rack/producers 13 | sensor-path Cisco-IOS-XR-pfi-im-cmd-oper:interfaces/interface-briefs/interface-brief 14 | ! 15 | sensor-group green-envmon-data-rate 16 | sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/total/data-rate/input-data-rate 17 | sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/total/data-rate/output-data-rate 18 | ! 19 | subscription green 20 | sensor-group-id green-envmon sample-interval 30000 21 | sensor-group-id green-envmon-data-rate sample-interval 120000 22 | destination-id green 23 | source-interface MgmtEth0/RP0/CPU0/0 24 | ! 25 | ! -------------------------------------------------------------------------------- /stack/mdt-config/ncs-560-er.cfg: -------------------------------------------------------------------------------- 1 | tpa 2 | vrf default 3 | address-family ipv4 4 | default-route mgmt 5 | update-source dataports MgmtEth 0/RP0/CPU0/0 6 | ! 7 | ! 8 | ! 9 | telemetry model-driven 10 | destination-group green 11 | address-family ipv4 HOST_IP port 57500 12 | encoding self-describing-gpb 13 | protocol grpc no-tls 14 | ! 15 | ! 16 | sensor-group green-envmon 17 | sensor-path Cisco-IOS-XR-sysadmin-uea-envmon-ui:environment/oper/power 18 | ! 19 | subscription green 20 | sensor-group-id green-envmon sample-interval 30000 21 | destination-id green 22 | source-interface MgmtEth0/RP0/CPU0/0 23 | ! 24 | ! -------------------------------------------------------------------------------- /stack/mdt-config/nexus9k-c9372px.cfg: -------------------------------------------------------------------------------- 1 | feature telemetry 2 | telemetry 3 | destination-group green 4 | ip address HOST_IP port 57500 protocol gRPC encoding GPB 5 | sensor-group green 6 | data-source NX-API 7 | path "show environment power" depth 0 8 | subscription 999 9 | dst-grp green 10 | snsr-grp green sample-interval 30000 11 | -------------------------------------------------------------------------------- /stack/telegraf/Dockerfile: -------------------------------------------------------------------------------- 1 | # Dockerfile for data collector. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | # CONTRIBUTOR(s): Steven Barth 19 | 20 | FROM telegraf:1.24-alpine 21 | 22 | ARG http_proxy=$HTTPS_PROXY \ 23 | env_pip_requirements="/requirements.txt" 24 | 25 | RUN apk add python3 py3-pip curl 26 | COPY snmp/* /usr/share/snmp/mibs/ 27 | ADD requirements.txt $env_requirements 28 | 29 | # Python dependencies 30 | RUN if [ -z "$HTTPS_PROXY" ] ;\ 31 | then pip3 install --upgrade pip && pip3 install -r $env_pip_requirements;\ 32 | else pip3 install --proxy $HTTPS_PROXY --upgrade pip && pip3 install --proxy $HTTPS_PROXY -r $env_pip_requirements;\ 33 | fi 34 | # Eaton dependencies 35 | RUN if [ -z "$HTTPS_PROXY" ] ;\ 36 | then curl --max-time 30 --user-agent 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1a) Gecko/20020619' https://www.eaton.com/content/dam/eaton/products/backup-power-ups-surge-it-power-distribution/Firmware/eaton-pdu-g3-firmware-mib.zip --output eaton-pdu-g3-firmware-mib.zip;\ 37 | else curl --proxy $HTTPS_PROXY --max-time 30 --user-agent 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1a) Gecko/20020619' https://www.eaton.com/content/dam/eaton/products/backup-power-ups-surge-it-power-distribution/Firmware/eaton-pdu-g3-firmware-mib.zip --output eaton-pdu-g3-firmware-mib.zip;\ 38 | fi;\ 39 | unzip eaton-pdu-g3-firmware-mib.zip -d eaton-pdu-g3-firmware-mib && cd eaton-pdu-g3-firmware-mib && unzip EATON-EPDU-MIB.zip -d EATON-EPDU-MIB && mv EATON-EPDU-MIB/*-MIB.txt /usr/share/snmp/mibs/;\ 40 | exit 0 -------------------------------------------------------------------------------- /stack/telegraf/pip-licenses.md: -------------------------------------------------------------------------------- 1 | ### Scan for licenses 2 | 3 | ```bash 4 | $ pip3 install pip-licenses 5 | $ pip-licenses --with-urls --with-system --format=markdown 6 | ``` 7 | 8 | | Name | Version | License | URL | 9 | |--------------------|------------|--------------------------------------|----------------------------------------------| 10 | | PyYAML | 6.0.1 | MIT License | https://pyyaml.org/ | 11 | | certifi | 2022.12.7 | Mozilla Public License 2.0 (MPL 2.0) | https://github.com/certifi/python-certifi | 12 | | charset-normalizer | 2.1.1 | MIT License | https://github.com/ousret/charset_normalizer | 13 | | idna | 3.4 | BSD License | https://github.com/kjd/idna | 14 | | imcsdk | 0.9.12 | Apache Software License | https://github.com/ciscoucs/imcsdk | 15 | | packaging | 21.3 | Apache Software License; BSD License | https://github.com/pypa/packaging | 16 | | pip | 23.1 | MIT License | https://pip.pypa.io/ | 17 | | pyparsing | 3.0.9 | MIT License | https://github.com/pyparsing/pyparsing/ | 18 | | pytz | 2023.3 | MIT License | http://pythonhosted.org/pytz | 19 | | raritan | 20210223.0 | BSD License | https://github.com/daxm/raritan-pdu-json-rpc | 20 | | requests | 2.31.0 | Apache Software License | https://requests.readthedocs.io | 21 | | retrying | 1.3.3 | Apache Software License | https://github.com/rholder/retrying | 22 | | setuptools | 65.6.0 | MIT License | https://github.com/pypa/setuptools | 23 | | six | 1.16.0 | MIT License | https://github.com/benjaminp/six | 24 | | ucsmsdk | 0.9.13 | Apache Software License | https://github.com/CiscoUcs/ucsmsdk | 25 | | urllib3 | 1.26.15 | MIT License | https://urllib3.readthedocs.io/ | -------------------------------------------------------------------------------- /stack/telegraf/requirements.txt: -------------------------------------------------------------------------------- 1 | pytz==2023.3 2 | raritan==20210223.0 3 | pyyaml==6.0.1 4 | imcsdk==0.9.12 5 | meraki==1.40.1 6 | requests==2.31.0 7 | ucsmsdk==0.9.13 -------------------------------------------------------------------------------- /stack/telegraf/snmp/.hidden: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisco-open/green-monitoring/5148a73830d79e63f75ebdb0aa484cef8d40ab1d/stack/telegraf/snmp/.hidden -------------------------------------------------------------------------------- /stack/telegraf/telegraf-sample.conf: -------------------------------------------------------------------------------- 1 | # Configuration file for the collection agent. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | [agent] 20 | interval = "10s" 21 | round_interval = true 22 | metric_batch_size = 1000 23 | metric_buffer_limit = 10000 24 | collection_jitter = "0s" 25 | flush_interval = "10s" 26 | flush_jitter = "0s" 27 | precision = "" 28 | hostname = "" 29 | omit_hostname = false -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/apic/get-switch-power.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Script for retrieving power information for nodes of the ACI APIC. 4 | 5 | Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | 19 | """ 20 | 21 | __author__ = "Cristina Precup " 22 | __copyright__ = "Copyright (c) 2022 Cisco and/or its affiliates." 23 | __license__ = "Apache License, Version 2.0" 24 | 25 | import os 26 | import re 27 | import pytz 28 | import json 29 | import requests 30 | import urllib3 31 | from datetime import datetime 32 | 33 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 34 | 35 | apics = {"apic0.domain.com": ""} 36 | nodes = {"3331": {}, "3332": {}} 37 | username = "user" 38 | password = "fgklfgkfl" 39 | 40 | 41 | def get_call(apic, token, call): 42 | cookie = {"APIC-cookie": token} 43 | r_nodes_json = requests.get( 44 | "https://" + apic + call, cookies=cookie, verify=False 45 | ).json() 46 | 47 | return r_nodes_json 48 | 49 | 50 | def read_power(node): 51 | node[1]["collection"] = [] 52 | psu_nrs = range(0, 10) 53 | 54 | for psu_nr in psu_nrs: 55 | r_power_json = get_call( 56 | node[1]["apic"], 57 | apics[node[1]["apic"]], 58 | "/api/node/mo/topology/pod-1/node-" 59 | + node[0] 60 | + "/sys/pie/env/psu-" 61 | + str(psu_nr) 62 | + "/psu_power_info.json?query-target=self", 63 | ) 64 | 65 | if ( 66 | r_power_json 67 | and "totalCount" in r_power_json 68 | and int(r_power_json["totalCount"]) > 0 69 | ): 70 | for i in range(0, int(r_power_json["totalCount"])): 71 | psu_id = re.search( 72 | "psu-.*/psu_power_info", 73 | r_power_json["imdata"][i]["piePsuPowerInfo"]["attributes"]["dn"], 74 | ).group(0)[0:-15] 75 | 76 | body = { 77 | # Assume UTC timezone 78 | "time": datetime.now() 79 | .astimezone(pytz.utc) 80 | .strftime("%Y-%m-%dT%H:%M:%S.000Z"), 81 | "dn": node[1]["dn"], 82 | "id": node[1]["id"], 83 | "name": node[1]["name"], 84 | "role": node[1]["role"], 85 | "model": node[1]["model"], 86 | "serial": node[1]["serial"], 87 | "address": node[1]["address"], 88 | "apic": node[1]["apic"], 89 | "psu_id": psu_id, 90 | "pIn": float( 91 | r_power_json["imdata"][i]["piePsuPowerInfo"]["attributes"][ 92 | "pIn" 93 | ] 94 | ), 95 | "pOut": float( 96 | r_power_json["imdata"][i]["piePsuPowerInfo"]["attributes"][ 97 | "pOut" 98 | ] 99 | ), 100 | } 101 | 102 | node[1]["collection"].append(body) 103 | 104 | 105 | def create_nodes(apic): 106 | r_nodes_json = get_call(apic[0], apic[1], "/api/node/class/fabricNode.json") 107 | 108 | # Search for node names 109 | for d in r_nodes_json["imdata"]: 110 | n_id = d["fabricNode"]["attributes"]["id"] 111 | if n_id in nodes: 112 | nodes[n_id]["time"] = ( 113 | datetime.now().astimezone(pytz.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z") 114 | ) 115 | nodes[n_id]["dn"] = d["fabricNode"]["attributes"]["dn"] 116 | nodes[n_id]["id"] = d["fabricNode"]["attributes"]["id"] 117 | nodes[n_id]["name"] = d["fabricNode"]["attributes"]["name"] 118 | nodes[n_id]["role"] = d["fabricNode"]["attributes"]["role"] 119 | nodes[n_id]["model"] = d["fabricNode"]["attributes"]["model"] 120 | nodes[n_id]["serial"] = d["fabricNode"]["attributes"]["serial"] 121 | nodes[n_id]["address"] = d["fabricNode"]["attributes"]["address"] 122 | nodes[n_id]["apic"] = apic[0] 123 | 124 | 125 | def get_token(apic): 126 | r_json = requests.post( 127 | "https://" + apic + "/api/aaaLogin.json", 128 | json={"aaaUser": {"attributes": {"name": username, "pwd": password}}}, 129 | verify=False, 130 | ).json() 131 | 132 | token = r_json["imdata"][0]["aaaLogin"]["attributes"]["token"] 133 | 134 | return token 135 | 136 | 137 | # Do not use proxy for the apics 138 | # Disable this in case proxy was preset and is needed 139 | os.environ["no_proxy"] = ",".join(apics) 140 | 141 | # Get authorization tokens 142 | for apic in apics.items(): 143 | apics[apic[0]] = get_token(apic[0]) 144 | 145 | # Get nodes 146 | for apic in apics.items(): 147 | create_nodes(apic) 148 | 149 | # Request power information for each node 150 | for node in nodes.items(): 151 | read_power(node) 152 | 153 | flat_collection = [item for node in nodes.items() for item in node[1]["collection"]] 154 | 155 | print(json.dumps(flat_collection)) 156 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/get-co2eqkwh.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Script for retrieving CO2 emissions / kWh. 4 | 5 | Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | 19 | """ 20 | 21 | __author__ = "Cristina Precup " 22 | __copyright__ = "Copyright (c) 2022 Cisco and/or its affiliates." 23 | __license__ = "Apache License, Version 2.0" 24 | 25 | import os 26 | import sys 27 | import pytz 28 | import json 29 | import time 30 | import logging as log 31 | from datetime import datetime 32 | import requests 33 | 34 | zones = ["DE", "ES", "FR", "IT-CNO", "IT-CSO", "IT-SO"] 35 | url_emaps = "https://api.electricitymap.org/v3/carbon-intensity/latest?zone=" 36 | url_co2signal = "https://api.co2signal.com/v1/latest?countryCode=" 37 | 38 | 39 | def read_emaps(js, zone, country, region): 40 | # Check if data exists 41 | if "carbonIntensity" not in js: 42 | return None 43 | 44 | return base_json_body(js, zone, country, region) 45 | 46 | 47 | def read_co2_signal(js, zone, country, region): 48 | # Check if data exists 49 | if "data" not in js: 50 | return None 51 | 52 | data = js["data"] 53 | 54 | if data["carbonIntensity"]: 55 | json_body = base_json_body(data, zone, country, region) 56 | json_body.update( 57 | { 58 | "unitCarbonIntensity": js["units"]["carbonIntensity"], 59 | "fossilFuelPercentage": data["fossilFuelPercentage"], 60 | } 61 | ) 62 | return json_body 63 | return None 64 | 65 | 66 | def base_json_body(data, zone, country, region): 67 | return { 68 | # Assume UTC timezone 69 | "time": datetime.now().astimezone(pytz.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z"), 70 | "acquired_time": data["datetime"], # TODO 71 | "cc": zone, 72 | "country": country, 73 | "region": region, 74 | "carbonIntensity": data["carbonIntensity"], 75 | } 76 | 77 | 78 | if __name__ == "__main__": 79 | 80 | collection = [] 81 | session = requests.Session() 82 | 83 | # Check if CO2_SIGNAL_TOKEN is set 84 | if "CO2_SIGNAL_TOKEN" in os.environ: 85 | headers = {"auth-token": os.environ["CO2_SIGNAL_TOKEN"]} 86 | url = url_co2signal 87 | 88 | # Check if EMAPS_TOKEN is set 89 | if "EMAPS_TOKEN" in os.environ: 90 | headers = {"auth-token": os.environ["EMAPS_TOKEN"]} 91 | url = url_emaps 92 | 93 | if "url" not in locals(): 94 | sys.exit("ERROR: Token not set.") 95 | 96 | for zone in zones: 97 | response = session.get(url + zone, headers=headers) 98 | if response.status_code != 200: 99 | log.warning(str(response.status_code) + ": " + response.text) 100 | continue 101 | js = response.json() 102 | 103 | if zone == "DE": 104 | country = "Germany" 105 | region = "Bavaria" 106 | elif zone == "ES": 107 | country = "Spain" 108 | region = "Catalonia" 109 | elif zone == "FR": 110 | country = "France" 111 | region = "Auvergne-Rhône-Alpes" 112 | else: 113 | country = "Italy" 114 | if zone == "IT-CNO": 115 | region = "Central North" 116 | elif zone == "IT-CSO": 117 | region = "Central South" 118 | elif zone == "IT-SO": 119 | region = "South" 120 | 121 | if url == url_co2signal: 122 | # Get CO2 Signal data 123 | collection.append(read_co2_signal(js, zone, country, region)) 124 | else: 125 | # Get EMAPS data 126 | collection.append(read_emaps(js, zone, country, region)) 127 | 128 | time.sleep(1) 129 | 130 | print(json.dumps(collection)) 131 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/meraki/get-meraki-power.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Script for retrieving total PoE information for Meraki switches. 4 | 5 | Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | 19 | """ 20 | 21 | __author__ = "Oren Brigg " 22 | __copyright__ = "Copyright (c) 2023 Cisco and/or its affiliates." 23 | __license__ = "Apache License, Version 2.0" 24 | 25 | import asyncio 26 | import json 27 | from datetime import datetime 28 | 29 | import meraki 30 | import meraki.aio 31 | import pytz 32 | 33 | # Replace with your API key 34 | api_key = "sample-api-key" 35 | # Replace with your organization ID 36 | org_id = "sample-organization-id" 37 | 38 | timespan = 3600 # 3600 seconds = 1 hour 39 | results = [] 40 | 41 | # Collect total PoE power usage for each switch 42 | async def get_switches_power(switch_list): 43 | async with meraki.aio.AsyncDashboardAPI( 44 | api_key=api_key, 45 | output_log=False, 46 | suppress_logging=True, 47 | maximum_concurrent_requests=5, 48 | wait_on_rate_limit=True, 49 | nginx_429_retry_wait_time=2, 50 | maximum_retries=100, 51 | ) as aiomeraki: 52 | get_power_task = [] 53 | for switch in switch_list: 54 | if switch["networkId"] != None: 55 | get_power_task.append( 56 | async_get_switch(aiomeraki, switch["serial"], switch["name"]) 57 | ) 58 | get_power_task.append( 59 | async_get_org(aiomeraki) 60 | ) 61 | 62 | for task in asyncio.as_completed(get_power_task): 63 | await task 64 | 65 | 66 | # Collect total switches power for an organisation 67 | async def async_get_org(aiomeraki: meraki.aio.AsyncDashboardAPI): 68 | power = 0 69 | try: 70 | org_power = await aiomeraki.organizations.getOrganizationSummaryTopSwitchesByEnergyUsage( 71 | org_id, timespan=timespan 72 | ) 73 | power = org_power[0]["usage"]["total"] 74 | except Exception as e: 75 | print(f"Some other ERROR: {e}") 76 | results.append( 77 | { 78 | # Assume UTC timezone 79 | "time": datetime.now() 80 | .astimezone(pytz.utc) 81 | .strftime("%Y-%m-%dT%H:%M:%S.000Z"), 82 | "org_id": org_id, 83 | "power": round(power), 84 | } 85 | ) 86 | 87 | 88 | # Collect total PoE power usage for a switch 89 | async def async_get_switch( 90 | aiomeraki: meraki.aio.AsyncDashboardAPI, serial: str, name: str 91 | ): 92 | poe = 0 93 | try: 94 | switch_ports = await aiomeraki.switch.getDeviceSwitchPortsStatuses( 95 | serial, timespan=timespan 96 | ) 97 | for port in switch_ports: 98 | if "powerUsageInWh" in port.keys(): 99 | poe += port["powerUsageInWh"] 100 | except Exception as e: 101 | print(f"Some other ERROR: {e}") 102 | results.append( 103 | { 104 | # Assume UTC timezone 105 | "time": datetime.now() 106 | .astimezone(pytz.utc) 107 | .strftime("%Y-%m-%dT%H:%M:%S.000Z"), 108 | "org_id": org_id, 109 | "switch_serial": serial, 110 | "switch_name": name, 111 | "power": round(poe), # Units are in Wh 112 | } 113 | ) 114 | 115 | 116 | # Initialize Meraki API 117 | dashboard = meraki.DashboardAPI(api_key=api_key, suppress_logging=True) 118 | 119 | # Get the list of switches 120 | switch_list = dashboard.organizations.getOrganizationInventoryDevices( 121 | org_id, productTypes=["switch"] 122 | ) 123 | 124 | loop = asyncio.get_event_loop() 125 | loop.run_until_complete(get_switches_power(switch_list)) 126 | 127 | print(json.dumps(results)) 128 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/raritan-power/get-raritan.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Script for retrieving power information for Raritan PDUs. 4 | 5 | Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | 19 | """ 20 | 21 | __author__ = "Cristina Precup " 22 | __copyright__ = "Copyright (c) 2022 Cisco and/or its affiliates." 23 | __license__ = "Apache License, Version 2.0" 24 | 25 | import os, sys 26 | import getopt 27 | import pytz 28 | import json 29 | import yaml 30 | import multiprocessing 31 | from datetime import datetime 32 | 33 | from raritan import rpc 34 | from raritan.rpc import pdumodel 35 | 36 | model = '/model/pdu/0' 37 | 38 | # Before running this script: edit the raritan-credentials.yml file 39 | # with the right credentials and the raritan-pdus.yml with the 40 | # right list of Raritan PDUs 41 | 42 | # Set default paths 43 | pdus_file = '/etc/telegraf/telegraf.d/raritan-power/raritan-pdus.yml' 44 | credentials_file = '/etc/telegraf/telegraf.d/raritan-power/raritan-credentials.yml' 45 | 46 | 47 | def retrieve_data(data): 48 | collection = [] 49 | name, ip = data 50 | name = model + '-' + name 51 | 52 | try: 53 | agent = rpc.Agent('https', ip, username, password) 54 | pdu = pdumodel.Pdu(model, agent) 55 | metadata = pdu.getMetaData() 56 | 57 | # Get current, voltage, activePower, phaseAngle readings from inlets 58 | inlets = pdu.getInlets() 59 | for i in inlets: 60 | 61 | json_body = { 62 | 'name': name, 63 | # Assume UTC timezone 64 | 'time': datetime.now().astimezone(pytz.utc). 65 | strftime("%Y-%m-%dT%H:%M:%S.000Z"), 66 | 'current': i.getSensors().current.getReading().value, # A 67 | 'unbalancedCurrent': i.getSensors().unbalancedCurrent.getReading().value, # % 68 | 'voltage': i.getSensors().voltage.getReading().value, # V 69 | 'activePower': i.getSensors().activePower.getReading().value/1000, # kW 70 | 'apparentPower': i.getSensors().apparentPower.getReading().value/1000, # kVA 71 | 'activeEnergy': i.getSensors().activeEnergy.getReading().value/1000000, # MWh 72 | 'lineFrequency': i.getSensors().lineFrequency.getReading().value # Hz 73 | } 74 | 75 | collection.append(json_body) 76 | 77 | except Exception as e: 78 | print(e) 79 | 80 | return collection 81 | 82 | def main(argv): 83 | global pdus_file, credentials_file, raritan_pdus, username, password 84 | 85 | try: 86 | opts, args = getopt.getopt(argv,"p:c:",["pdusyml=","credentialsyml="]) 87 | except getopt.GetoptError: 88 | print('get-raritan.py -p -c ') 89 | sys.exit(2) 90 | for opt, arg in opts: 91 | if opt in ("-p", "--pdusyml"): 92 | pdus_file = arg 93 | elif opt in ("-c", "--credentialsyml"): 94 | credentials_file = arg 95 | 96 | credentials = yaml.load( 97 | open(credentials_file), 98 | Loader=yaml.Loader) 99 | username = credentials['pdu']['username'] 100 | password = credentials['pdu']['password'] 101 | 102 | pdus = yaml.load( 103 | open(pdus_file), 104 | Loader=yaml.Loader) 105 | raritan_pdus = pdus['pdus'] 106 | 107 | # Do not use proxy for the Raritan IP addresses 108 | # Disable this in case proxy was preset and is needed 109 | os.environ['no_proxy'] = ','.join(list(raritan_pdus.values())) 110 | 111 | 112 | if __name__ == '__main__': 113 | main(sys.argv[1:]) 114 | 115 | with multiprocessing.Pool(processes=4) as p: 116 | collections = p.map(retrieve_data, raritan_pdus.items()) 117 | flat_collection = [item for collection in collections for item in collection] 118 | 119 | print(json.dumps(flat_collection)) 120 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/raritan-power/raritan-credentials.yml: -------------------------------------------------------------------------------- 1 | # Credentials for Raritan PDUs. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | pdu: 20 | username: 21 | password: 22 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/raritan-power/raritan-pdus.yml: -------------------------------------------------------------------------------- 1 | # List of Raritan PDUs. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | pdus: 20 | pdu-1: 10.10.10.42 21 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/raritan-power/requirements.txt: -------------------------------------------------------------------------------- 1 | # Package dependencies for retrieval of Raritan PDUs' data. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | pyyaml==6.0 20 | raritan==20210223.0 21 | pytz==2022.1 22 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/telegraf-eaton-pdu.conf: -------------------------------------------------------------------------------- 1 | # Configuration file for retrieving data from Eaton PDUs. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | # CONTRIBUTOR(s): Steven Barth 19 | 20 | [[inputs.snmp]] 21 | agents = ["10.10.10.42"] 22 | 23 | timeout = "15s" 24 | retries = 10 25 | version = 3 26 | 27 | interval = "60s" 28 | max_repetitions = 10 29 | 30 | # SNMP community string 31 | sec_name = "public" 32 | sec_level = "noAuthNoPriv" 33 | 34 | # hostname 35 | agent_host_tag = "agent_host" 36 | 37 | [[inputs.snmp.table]] 38 | oid = "EATON-EPDU-MIB::inputPowerTable" 39 | name = "eaton_input_power" 40 | 41 | # Fields of table 42 | [[inputs.snmp.table.field]] 43 | name = "phase" 44 | oid = "1.3.6.1.4.1.534.6.6.7.3.4.1.2" 45 | is_tag = true 46 | 47 | [[inputs.snmp.table]] 48 | oid = "EATON-EPDU-MIB::groupPowerTable" 49 | index_as_tag = true 50 | name = "eaton_output_power" 51 | 52 | [[outputs.influxdb_v2]] 53 | urls = ["http://influxdb:8086"] 54 | 55 | token = "$DOCKER_INFLUXDB_INIT_ADMIN_TOKEN" 56 | organization = "$DOCKER_INFLUXDB_INIT_ORG" 57 | bucket = "$DOCKER_INFLUXDB_INIT_BUCKET" 58 | 59 | precision = "s" 60 | timeout = "5s" 61 | namepass = ["eaton*"] 62 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/telegraf-electricitymap.conf: -------------------------------------------------------------------------------- 1 | # Configuration file for receiving data from CO2 Signal. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | [[inputs.exec]] 20 | ## Call the python script that retrieves the data 21 | commands = [ 22 | "python3 /etc/telegraf/telegraf.d/get-co2eqkwh.py" 23 | ] 24 | 25 | timeout = "20s" 26 | interval = "15m" 27 | 28 | name_override = "electricity-map" 29 | data_format = "json" 30 | json_time_key = "time" 31 | json_time_format = "2006-01-02T15:04:05.000Z" 32 | 33 | tag_keys = ["country", "region", "cc"] 34 | json_string_fields = ["unitCarbonIntensity"] 35 | 36 | [[processors.converter]] 37 | namepass = ["electricity-map"] 38 | ## Fields to convert 39 | [processors.converter.fields] 40 | float = ["carbonIntensity"] 41 | 42 | [[outputs.influxdb_v2]] 43 | urls = ["http://influxdb:8086"] 44 | 45 | token = "$DOCKER_INFLUXDB_INIT_ADMIN_TOKEN" 46 | organization = "$DOCKER_INFLUXDB_INIT_ORG" 47 | bucket = "$DOCKER_INFLUXDB_INIT_BUCKET" 48 | 49 | precision = "s" 50 | timeout = "5s" 51 | 52 | namepass = ["electricity-map"] -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/telegraf-mapping.conf: -------------------------------------------------------------------------------- 1 | # Data enrichment 2 | # This script sets tags: geo (country, region, cc), rack. 3 | # 4 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # AUTHOR(s): Cristina Precup 19 | 20 | ##### XR, NX-OS tags ##### 21 | [[processors.enum]] 22 | order = 1 23 | namepass = ["Cisco-IOS-XE-environment-oper:environment-sensors/environment-sensor", 24 | "Cisco-IOS-XR-sysadmin-fretta-envmon-ui:environment/oper/power/location/pem_attributes", 25 | "Cisco-IOS-XR-sysadmin-asr9k-envmon-ui:environment/oper/power/location/pem_attributes", 26 | "Cisco-IOS-XR-envmon-oper:power-management/rack/producers/producer-nodes/producer-node", 27 | "Cisco-IOS-XR-envmon-oper:power-management/rack/chassis", 28 | "show environment power"] 29 | 30 | # Set countries 31 | [[processors.enum.mapping]] 32 | tag = "source" 33 | dest = "country" 34 | default = "NA" 35 | 36 | [processors.enum.mapping.value_mappings] 37 | device-1 = "France" 38 | device-2 = "Germany" 39 | device-3 = "Italy" 40 | switch-1-core-1 = "Spain" 41 | 42 | # Set regions 43 | [[processors.enum.mapping]] 44 | tag = "source" 45 | dest = "region" 46 | default = "NA" 47 | 48 | [processors.enum.mapping.value_mappings] 49 | device-1 = "Lombardy" 50 | device-2 = "Bavaria" 51 | device-3 = "Central South" 52 | switch-1-core-1 = "Catalonia" 53 | 54 | # Set country codes - to be mapped with Electricity Map data 55 | [[processors.enum.mapping]] 56 | tag = "source" 57 | dest = "cc" 58 | default = "NA" 59 | 60 | [processors.enum.mapping.value_mappings] 61 | device-1 = "FR" 62 | device-2 = "DE" 63 | device-3 = "IT-CSO" 64 | switch-1-core-1 = "ES" 65 | 66 | # Set racks 67 | [[processors.enum.mapping]] 68 | tag = "source" 69 | dest = "rack" 70 | default = "NA" 71 | 72 | [processors.enum.mapping.value_mappings] 73 | device-1 = 41 74 | device-2 = 41 75 | device-3 = 42 76 | switch-1-core-1 = 43 77 | 78 | # Set device type 79 | [[processors.enum.mapping]] 80 | tag = "source" 81 | dest = "device_type" 82 | default = "NA" 83 | 84 | [processors.enum.mapping.value_mappings] 85 | device-2 = "cisco-8k" 86 | 87 | ##### Switch - APIC ##### 88 | [[processors.enum]] 89 | order = 2 90 | namepass = ["apic-switch"] 91 | 92 | # Set countries 93 | [[processors.enum.mapping]] 94 | tag = "name" 95 | dest = "country" 96 | default = "NA" 97 | 98 | [processors.enum.mapping.value_mappings] 99 | spine-3331 = "Spain" 100 | spine-3332 = "Spain" 101 | 102 | # Set regions 103 | [[processors.enum.mapping]] 104 | tag = "name" 105 | dest = "region" 106 | default = "NA" 107 | 108 | [processors.enum.mapping.value_mappings] 109 | spine-3331 = "Catalonia" 110 | spine-3332 = "Catalonia" 111 | 112 | # Set country codes 113 | [[processors.enum.mapping]] 114 | tag = "name" 115 | dest = "cc" 116 | default = "NA" 117 | 118 | [processors.enum.mapping.value_mappings] 119 | spine-3331 = "ES" 120 | spine-3332 = "ES" 121 | 122 | ##### UCS - REDFISH ##### 123 | [[processors.enum]] 124 | order = 3 125 | namepass = ["redfish_*"] 126 | 127 | # Set countries 128 | [[processors.enum.mapping]] 129 | tag = "name" 130 | dest = "country" 131 | default = "NA" 132 | 133 | [processors.enum.mapping.value_mappings] 134 | # Rack X 135 | server-1 = "Italy" 136 | 137 | # Set regions 138 | [[processors.enum.mapping]] 139 | tag = "name" 140 | dest = "region" 141 | default = "NA" 142 | 143 | [processors.enum.mapping.value_mappings] 144 | # Rack X 145 | server-1 = "Central-North" 146 | 147 | # Set country codes 148 | [[processors.enum.mapping]] 149 | tag = "name" 150 | dest = "cc" 151 | default = "NA" 152 | 153 | [processors.enum.mapping.value_mappings] 154 | # Rack X 155 | server-1 = "IT-CNO" 156 | 157 | # Set racks 158 | [[processors.enum.mapping]] 159 | tag = "name" 160 | dest = "rack" 161 | default = "NA" 162 | 163 | [processors.enum.mapping.value_mappings] 164 | # Rack X 165 | server-1 = "rack-X" 166 | 167 | ##### UCS - CIMC ##### 168 | [[processors.enum]] 169 | order = 4 170 | namepass = ["cimc-*"] 171 | 172 | # Set countries 173 | [[processors.enum.mapping]] 174 | tag = "name" 175 | dest = "country" 176 | default = "NA" 177 | 178 | [processors.enum.mapping.value_mappings] 179 | # Rack X 180 | server-2 = "Italy" 181 | 182 | # Set regions 183 | [[processors.enum.mapping]] 184 | tag = "name" 185 | dest = "region" 186 | default = "NA" 187 | 188 | [processors.enum.mapping.value_mappings] 189 | # Rack X 190 | server-2 = "Central-North" 191 | 192 | # Set country codes 193 | [[processors.enum.mapping]] 194 | tag = "name" 195 | dest = "cc" 196 | default = "NA" 197 | 198 | [processors.enum.mapping.value_mappings] 199 | # Rack X 200 | server-2 = "IT-CNO" 201 | 202 | # Set racks 203 | [[processors.enum.mapping]] 204 | tag = "name" 205 | dest = "rack" 206 | default = "NA" 207 | 208 | [processors.enum.mapping.value_mappings] 209 | # Rack X 210 | server-2 = "rack-X" 211 | 212 | ##### UCS - UCSM ##### 213 | [[processors.enum]] 214 | order = 5 215 | namepass = ["ucsm*"] 216 | 217 | # Set countries 218 | [[processors.enum.mapping]] 219 | tag = "name" 220 | dest = "country" 221 | default = "NA" 222 | 223 | [processors.enum.mapping.value_mappings] 224 | # Rack X 225 | server-3 = "Italy" 226 | 227 | # Set regions 228 | [[processors.enum.mapping]] 229 | tag = "name" 230 | dest = "region" 231 | default = "NA" 232 | 233 | [processors.enum.mapping.value_mappings] 234 | # Rack X 235 | server-3 = "Central-North" 236 | 237 | # Set country codes 238 | [[processors.enum.mapping]] 239 | tag = "name" 240 | dest = "cc" 241 | default = "NA" 242 | 243 | [processors.enum.mapping.value_mappings] 244 | # Rack X 245 | server-3 = "IT-CNO" 246 | 247 | # Set racks 248 | [[processors.enum.mapping]] 249 | tag = "name" 250 | dest = "rack" 251 | default = "NA" 252 | 253 | [processors.enum.mapping.value_mappings] 254 | # Rack X 255 | server-3 = "rack-X" 256 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/telegraf-raritan-pdu.conf: -------------------------------------------------------------------------------- 1 | # Configuration file for receiving data from Raritan PDUs. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | [[inputs.exec]] 20 | # Call the python script that retrieves the data 21 | commands = [ 22 | "python3 /etc/telegraf/telegraf.d/raritan-power/get-raritan.py -p etc/telegraf/telegraf.d/raritan-power/raritan-pdus.yml", 23 | ] 24 | 25 | timeout = "20s" 26 | interval = "1m" 27 | 28 | name_override = "raritan-pdu" 29 | data_format = "json" 30 | json_time_key = "time" 31 | json_time_format = "2006-01-02T15:04:05.000Z" 32 | 33 | tag_keys = ["name"] 34 | 35 | [[processors.converter]] 36 | namepass = ["raritan-pdu"] 37 | # Fields to convert 38 | [processors.converter.fields] 39 | float = ["current", "unbalancedCurrent", "voltage", "activePower", "apparentPower", "activeEnergy", "lineFrequency"] 40 | 41 | [[outputs.influxdb_v2]] 42 | urls = ["http://influxdb:8086"] 43 | 44 | token = "$DOCKER_INFLUXDB_INIT_ADMIN_TOKEN" 45 | organization = "$DOCKER_INFLUXDB_INIT_ORG" 46 | bucket = "$DOCKER_INFLUXDB_INIT_BUCKET" 47 | 48 | precision = "s" 49 | timeout = "5s" 50 | 51 | namepass = ["raritan-pdu"] -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/telegraf-redfish.conf: -------------------------------------------------------------------------------- 1 | # Configuration file for receiving data from Redfish-compatible systems. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Steven Barth 18 | # CONTRIBUTOR(s): Cristina Precup 19 | 20 | [[inputs.redfish]] 21 | address = "https://server-1.domain.com" 22 | computer_system_id = "XXXXXXXXXXX" 23 | username = "admin" 24 | password = "dfgkldfgkl" 25 | namepass = ["redfish_power_powersupplies","redfish_thermal_temperatures"] 26 | insecure_skip_verify = true 27 | 28 | [[outputs.influxdb_v2]] 29 | urls = ["http://influxdb:8086"] 30 | 31 | token = "$DOCKER_INFLUXDB_INIT_ADMIN_TOKEN" 32 | organization = "$DOCKER_INFLUXDB_INIT_ORG" 33 | bucket = "$DOCKER_INFLUXDB_INIT_BUCKET" 34 | 35 | precision = "s" 36 | timeout = "5s" 37 | 38 | namepass = ["redfish_power_powersupplies","redfish_thermal_temperatures"] 39 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/telegraf-switch-apic.conf: -------------------------------------------------------------------------------- 1 | # Configuration file for receiving data from ACI APIC. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | [[inputs.exec]] 20 | ## Call the python script that retrieves the data 21 | commands = [ 22 | "python3 /etc/telegraf/telegraf.d/apic/get-switch-power.py", 23 | ] 24 | 25 | timeout = "2m" 26 | interval = "3m" 27 | 28 | name_override = "apic-switch" 29 | data_format = "json" 30 | json_time_key = "time" 31 | json_time_format = "2006-01-02T15:04:05.000Z" 32 | 33 | tag_keys = ["name", "id", "dn", "address", "apic", "serial", "model", "psu_id"] 34 | 35 | json_string_fields = ["role"] 36 | 37 | [[outputs.influxdb_v2]] 38 | urls = ["http://influxdb:8086"] 39 | 40 | token = "$DOCKER_INFLUXDB_INIT_ADMIN_TOKEN" 41 | organization = "$DOCKER_INFLUXDB_INIT_ORG" 42 | bucket = "$DOCKER_INFLUXDB_INIT_BUCKET" 43 | 44 | precision = "s" 45 | timeout = "5s" 46 | 47 | namepass = ["apic-switch"] 48 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/telegraf-switch-meraki.conf: -------------------------------------------------------------------------------- 1 | # Configuration file for receiving data from Meraki switches. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | [[inputs.exec]] 20 | ## Call the python script that retrieves the data 21 | commands = [ 22 | "python3 /etc/telegraf/telegraf.d/meraki/get-meraki-power.py", 23 | ] 24 | 25 | timeout = "2m" 26 | interval = "1h" 27 | 28 | name_override = "meraki-switch" 29 | data_format = "json" 30 | json_time_key = "time" 31 | json_time_format = "2006-01-02T15:04:05.000Z" 32 | 33 | tag_keys = ["org_id", "switch_name", "switch_serial"] 34 | 35 | [[outputs.influxdb_v2]] 36 | urls = ["http://influxdb:8086"] 37 | 38 | token = "$DOCKER_INFLUXDB_INIT_ADMIN_TOKEN" 39 | organization = "$DOCKER_INFLUXDB_INIT_ORG" 40 | bucket = "$DOCKER_INFLUXDB_INIT_BUCKET" 41 | 42 | precision = "s" 43 | timeout = "5s" 44 | 45 | namepass = ["meraki-switch"] 46 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/telegraf-ucs-cimc.conf: -------------------------------------------------------------------------------- 1 | # Configuration file for receiving data from UCS CIMC. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | [[inputs.exec]] 20 | # Call the python script that retrieves the data 21 | commands = [ 22 | "python3 /etc/telegraf/telegraf.d/ucs-power-temp-util/get-ucs-power-temp-util-idb.py -s etc/telegraf/telegraf.d/ucs-power-temp-util/ucs-servers.yml", 23 | ] 24 | 25 | timeout = "4m" 26 | interval = "60m" 27 | 28 | name_override = "cimc-ucs" 29 | data_format = "json" 30 | json_time_key = "time" 31 | json_time_format = "2006-01-02T15:04:05.000Z" 32 | 33 | tag_keys = ["measurement", "name", "ip", "psu-id", "domain", "dn", "id"] 34 | 35 | json_string_fields = ["psu-pid"] 36 | 37 | [[processors.converter]] 38 | order = 1 39 | namepass = ["cimc-ucs"] 40 | [processors.converter.tags] 41 | measurement = ["measurement"] 42 | 43 | [[outputs.influxdb_v2]] 44 | urls = ["http://influxdb:8086"] 45 | 46 | token = "$DOCKER_INFLUXDB_INIT_ADMIN_TOKEN" 47 | organization = "$DOCKER_INFLUXDB_INIT_ORG" 48 | bucket = "$DOCKER_INFLUXDB_INIT_BUCKET" 49 | 50 | precision = "s" 51 | timeout = "5s" 52 | 53 | namepass = ["cimc-ucs-*"] -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/telegraf-ucsm.conf: -------------------------------------------------------------------------------- 1 | # Configuration file for receiving data from UCSM. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Jean-Baptiste Lefeuvre 18 | 19 | [[inputs.exec]] 20 | # Call the python script that retrieves the data 21 | commands = [ 22 | "python3 /etc/telegraf/telegraf.d/ucs-power-temp-util/get-ucsm-power-temp-util-idb.py", 23 | ] 24 | 25 | timeout = "4m" 26 | interval = "60m" 27 | 28 | name_override = "ucsm" 29 | data_format = "json" 30 | json_time_key = "time" 31 | json_time_format = "2006-01-02T15:04:05.000Z" 32 | 33 | tag_keys = ["measurement", "domain-name", "domain-ip", "type", "chassis", "id"] 34 | 35 | [[processors.converter]] 36 | order = 1 37 | namepass = ["ucsm"] 38 | [processors.converter.tags] 39 | measurement = ["measurement"] 40 | 41 | [[outputs.influxdb_v2]] 42 | urls = ["http://influxdb:8086"] 43 | 44 | token = "$DOCKER_INFLUXDB_INIT_ADMIN_TOKEN" 45 | organization = "$DOCKER_INFLUXDB_INIT_ORG" 46 | bucket = "$DOCKER_INFLUXDB_INIT_BUCKET" 47 | 48 | precision = "s" 49 | timeout = "5s" 50 | 51 | namepass = ["ucsm*"] -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/telegraf-xr-and-nxos.conf: -------------------------------------------------------------------------------- 1 | # Configuration file for receiving data from IOS-XR and NX-OS platforms. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | # CONTRIBUTOR(s): Steven Barth 19 | 20 | [agent] 21 | interval = "10s" 22 | round_interval = true 23 | metric_buffer_limit = 10000 24 | flush_buffer_when_full = true 25 | collection_jitter = "0s" 26 | flush_interval = "10s" 27 | flush_jitter = "0s" 28 | debug = true 29 | quiet = false 30 | hostname = "telegraf" 31 | 32 | # Listen for incoming gRPC messages on port 57500 33 | [[inputs.cisco_telemetry_mdt]] 34 | max_msg_size = 20000000 35 | transport = "grpc" 36 | service_address = ":57500" 37 | 38 | # NX-OS - remove tag from data (not required; conflicts with the aggregator.merge) 39 | tagexclude = ["row_number"] 40 | 41 | # IOS-XR - additional tags 42 | embedded_tags = [ 43 | "Cisco-IOS-XR-sysadmin-fretta-envmon-ui:environment/oper/power/location/pem_attributes/pem_id/value", 44 | "Cisco-IOS-XR-sysadmin-fretta-envmon-ui:environment/oper/power/location/pem_attributes/card_type/value", 45 | "Cisco-IOS-XR-sysadmin-fretta-envmon-ui:environment/oper/power/location/pem_attributes/supply_type/value", 46 | "Cisco-IOS-XR-sysadmin-fretta-envmon-ui:environment/oper/power/location/pem_attributes/confgd_power_redundancy_mode/value", 47 | 48 | "Cisco-IOS-XR-envmon-oper:environmental-monitoring/rack/nodes/node/sensor-types/sensor-type/sensor-names/sensor-name/location", 49 | "Cisco-IOS-XR-envmon-oper:environmental-monitoring/rack/nodes/node/sensor-types/sensor-type/sensor-names/sensor-name/fru_type", 50 | "Cisco-IOS-XR-envmon-oper:environmental-monitoring/rack/nodes/node/sensor-types/sensor-type/sensor-names/sensor-name/name_xr", 51 | 52 | "Cisco-IOS-XR-envmon-oper:power-management/rack/consumers/consumer-nodes/consumer-node/node_name", 53 | "Cisco-IOS-XR-envmon-oper:power-management/rack/consumers/consumer-nodes/consumer-node/node_status", 54 | "Cisco-IOS-XR-envmon-oper:power-management/rack/consumers/consumer-nodes/consumer-node/node_type", 55 | "Cisco-IOS-XR-envmon-oper:power-management/rack/consumers/consumer-nodes/consumer-node/slot", 56 | 57 | "Cisco-IOS-XR-envmon-oper:power-management/rack/producers/producer-nodes/producer-node/pem-info-array/node-name", 58 | "Cisco-IOS-XR-envmon-oper:power-management/rack/producers/producer-nodes/producer-node/pem-info-array/node-status", 59 | "Cisco-IOS-XR-envmon-oper:power-management/rack/producers/producer-nodes/producer-node/pem-info-array/node-type", 60 | 61 | "Cisco-IOS-XR-invmgr-oper:inventory/entities/entity/attributes/name", 62 | "Cisco-IOS-XR-invmgr-oper:inventory/entities/entity/attributes/env-sensor-info/device_id", 63 | "Cisco-IOS-XR-invmgr-oper:inventory/entities/entity/attributes/env-sensor-info/units", 64 | 65 | "Cisco-IOS-XR-pfi-im-cmd-oper:interfaces/interface-briefs/interface-brief/type", 66 | ] 67 | 68 | # NX-OS - merge fields with the same tags 69 | [[aggregators.merge]] 70 | namepass = ["show environment power"] 71 | drop_original = true 72 | period = "60s" 73 | grace = "60s" 74 | 75 | # NX-OS - remove the W from the string fields 76 | [[processors.strings]] 77 | order = 1 78 | namepass = ["show environment power"] 79 | # Trim the given suffix from the field 80 | [[processors.strings.trim_suffix]] 81 | field = "allocated" 82 | suffix = " W" 83 | [[processors.strings.trim_suffix]] 84 | field = "actual_out" 85 | suffix = " W" 86 | [[processors.strings.trim_suffix]] 87 | field = "actual_input" 88 | suffix = " W" 89 | [[processors.strings.trim_suffix]] 90 | field = "actual_draw" 91 | suffix = " W" 92 | [[processors.strings.trim_suffix]] 93 | field = "tot_capa" 94 | suffix = " W" 95 | [[processors.strings.trim_suffix]] 96 | field = "powersup/power_summary/tot_pow_capacity" 97 | suffix = " W" 98 | [[processors.strings.trim_suffix]] 99 | field = "powersup/power_summary/tot_gridA_capacity" 100 | suffix = " W" 101 | [[processors.strings.trim_suffix]] 102 | field = "powersup/power_summary/tot_gridB_capacity" 103 | suffix = " W" 104 | [[processors.strings.trim_suffix]] 105 | field = "powersup/power_summary/cumulative_power" 106 | suffix = " W" 107 | [[processors.strings.trim_suffix]] 108 | field = "powersup/power_summary/tot_pow_out_actual_draw" 109 | suffix = " W" 110 | [[processors.strings.trim_suffix]] 111 | field = "powersup/power_summary/tot_pow_input_actual_draw" 112 | suffix = " W" 113 | [[processors.strings.trim_suffix]] 114 | field = "powersup/power_summary/tot_pow_alloc_budgeted" 115 | suffix = " W" 116 | [[processors.strings.trim_suffix]] 117 | field = "powersup/power_summary/available_pow" 118 | suffix = " W" 119 | 120 | # NX-OS - convert the string fields into integer fields 121 | [[processors.converter]] 122 | order = 2 123 | namepass = ["show environment power"] 124 | [processors.converter.fields] 125 | integer = ["allocated", "actual_*", "tot_*", "powersup/power_summary/tot*", "powersup/power_summary/available_pow", "powersup/power_summary/cumulative_power"] 126 | 127 | # Cisco 8K - convert possible string fields to float 128 | [[processors.converter]] 129 | order = 3 130 | namepass = ["Cisco-IOS-XR-envmon-oper:power-management/rack/producers/producer-nodes/producer-node"] 131 | [processors.converter.fields] 132 | float = ["pem_info_array/current_in*", "pem_info_array/voltage_in*", "pem_info_array/current_out", "pem_info_array/voltage_out"] 133 | 134 | # NCS 5xxx/5xx - power (convert to integer and avoid entries with -) 135 | [[processors.parser]] 136 | order = 4 137 | namepass = ["Cisco-IOS-XR-sysadmin-fretta-envmon-ui:environment/oper/power/location/pem_attributes"] 138 | parse_fields = ["power_consumed/value"] 139 | drop_original = false 140 | 141 | merge = "override" 142 | data_format = "grok" 143 | 144 | grok_patterns = ['%{NUMBER:power_consumed_value_int:int}|-'] 145 | 146 | 147 | # ASR 9K - LC power field parsing (fixed ports / optional ports): format "" 148 | [[processors.converter]] 149 | order = 5 150 | namepass = ["Cisco-IOS-XR-sysadmin-asr9k-envmon-ui:environment/oper/power/location/pem_attributes"] 151 | drop_original = false 152 | [processors.converter.fields] 153 | integer = ["power_consumed/value"] 154 | 155 | # ASR 9K - Rename converted field if need be 156 | [[processors.rename]] 157 | order = 6 158 | namepass = ["Cisco-IOS-XR-sysadmin-asr9k-envmon-ui:environment/oper/power/location/pem_attributes"] 159 | drop_original = false 160 | [[processors.rename.replace]] 161 | field = "power_consumed/value" 162 | dest = "power_lc_consumed" 163 | 164 | # ASR 9K - LC power field parsing (fixed ports / optional ports) 165 | # format "// -c ") 149 | sys.exit(2) 150 | for opt, arg in opts: 151 | if opt in ("-s", "--serversyml"): 152 | servers_file = arg 153 | elif opt in ("-c", "--credentialsyml"): 154 | credentials_file = arg 155 | 156 | credentials = yaml.load(open(credentials_file), Loader=yaml.Loader) 157 | username = credentials["ucs"]["username"] 158 | password = credentials["ucs"]["password"] 159 | 160 | servers = yaml.load(open(servers_file), Loader=yaml.Loader) 161 | ucs_servers = servers["servers"] 162 | 163 | # Do not use proxy for the UCS server IP addresses 164 | # Disable this in case proxy was preset and is needed 165 | os.environ["no_proxy"] = ",".join(list(ucs_servers.values())) 166 | 167 | 168 | if __name__ == "__main__": 169 | main(sys.argv[1:]) 170 | 171 | with multiprocessing.Pool(processes=4) as p: 172 | collections = p.map(retrieve_data, ucs_servers.items()) 173 | flat_collection = [item for collection in collections for item in collection] 174 | 175 | print(json.dumps(flat_collection)) 176 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/ucs-power-temp-util/get-ucsm-power-temp-util-idb.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Script for retrieving power, temperature and utilization information 4 | for UCSM servers. 5 | 6 | Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | """ 21 | 22 | __author__ = "Jean-Baptiste Lefeuvre " 23 | __copyright__ = "Copyright (c) 2022 Cisco and/or its affiliates." 24 | __license__ = "Apache License, Version 2.0" 25 | 26 | import json 27 | import pytz 28 | import yaml 29 | import multiprocessing 30 | from datetime import datetime 31 | from ucsmsdk.ucshandle import UcsHandle 32 | 33 | # List of class IDs to be pulled from UCS 34 | class_ids = ["EquipmentPsuInputStats", "ComputeMbPowerStats", "equipmentChassisStats"] 35 | 36 | domains_file = "/etc/telegraf/telegraf.d/ucs-power-temp-util/ucsm-domains.yml" 37 | credentials_file = "/etc/telegraf/telegraf.d/ucs-power-temp-util/ucsm-credentials.yml" 38 | username = "" 39 | password = "" 40 | 41 | 42 | def get_ucs_domains(): 43 | """ 44 | update the ucs_domains variable with the list of ucs domains from ucsm-domains.yaml 45 | 46 | Parameters: 47 | None 48 | 49 | Returns: 50 | none 51 | 52 | list of ucs_domains formated like this: 53 | [(, , 18 | 19 | pyyaml==6.0 20 | imcsdk==0.9.12 21 | ucsmsdk==0.9.13 22 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/ucs-power-temp-util/ucs-credentials.yml: -------------------------------------------------------------------------------- 1 | # Credentials of UCS servers. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | ucs: 20 | username: 21 | password: 22 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/ucs-power-temp-util/ucs-servers.yml: -------------------------------------------------------------------------------- 1 | # List of UCS servers. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | servers: 20 | # Rack X: 21 | server-1: 10.10.10.42 22 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/ucs-power-temp-util/ucsm-credentials.yml: -------------------------------------------------------------------------------- 1 | # Credentials of UCS servers. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | ucs_domains: 20 | username: 21 | password: 22 | -------------------------------------------------------------------------------- /stack/telegraf/telegraf.d/ucs-power-temp-util/ucsm-domains.yml: -------------------------------------------------------------------------------- 1 | # List of UCS servers. 2 | # 3 | # Copyright (c) 2022 Cisco and/or its affiliates. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | # AUTHOR(s): Cristina Precup 18 | 19 | ucs_domains: 20 | # Rack X: 21 | LAB1: 10.10.10.42 --------------------------------------------------------------------------------