├── .github └── workflows │ └── shellcheck.yml ├── 51-ec2-ena-ptp-device.rules ├── 51-ec2-hvm-devices.rules ├── 51-ec2-xen-vbd-devices.rules ├── 53-ec2-read-ahead-kb.rules ├── 60-cdrom_id.rules ├── 70-ec2-nvme-devices.rules ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── README.md ├── amazon-ec2-utils.spec ├── doc ├── ebsnvme-id.8 └── ec2-metadata.8 ├── ebsnvme ├── ebsnvme-id ├── ec2-metadata ├── ec2nvme-nsid ├── ec2udev-vbd └── sources /.github/workflows/shellcheck.yml: -------------------------------------------------------------------------------- 1 | name: shellcheck 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Install dependencies 18 | run: sudo apt-get update && DEBIAN_FRONTEND=noninteractive sudo apt-get -y install shellcheck 19 | - name: Run shellcheck 20 | run: shellcheck -s bash -S warning ec2-metadata ec2nvme-nsid ec2udev-vbd 21 | -------------------------------------------------------------------------------- /51-ec2-ena-ptp-device.rules: -------------------------------------------------------------------------------- 1 | SUBSYSTEM=="ptp", ATTR{clock_name}=="ena-ptp-*", SYMLINK += "ptp_ena" 2 | -------------------------------------------------------------------------------- /51-ec2-hvm-devices.rules: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the MIT License. See the LICENSE accompanying this file 4 | # for the specific language governing permissions and limitations under 5 | # the License. 6 | 7 | KERNEL=="xvd*", PROGRAM="/usr/sbin/ec2udev-vbd %k", SYMLINK+="%c" 8 | -------------------------------------------------------------------------------- /51-ec2-xen-vbd-devices.rules: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the MIT License. See the LICENSE accompanying this file 4 | # for the specific language governing permissions and limitations under 5 | # the License. 6 | 7 | # Set ID_PATH for xen virtual block devices (vbd) which are no longer 8 | # set by udev in systemd versions post v184 thus preserving prior 9 | # behaviour and with by-path links generated by corresponding rules from 10 | # 60-persistent-storage.rules 11 | SUBSYSTEM=="block", SUBSYSTEMS=="xen", DRIVERS=="vbd", ENV{ID_PATH}="xen-%b", ENV{ID_PATH_TAG}="xen-%b" 12 | -------------------------------------------------------------------------------- /53-ec2-read-ahead-kb.rules: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the MIT License. See the LICENSE accompanying this file 4 | # for the specific language governing permissions and limitations under 5 | # the License. 6 | 7 | 8 | # increase read_ahead_kb when a nfs/efs export is mounted to improve throughput 9 | SUBSYSTEM=="bdi", ACTION=="add", PROGRAM="/bin/awk -v bdi=$kernel 'BEGIN{ret=1} {if ($$4 == bdi) {ret=0}} END{exit ret}' /proc/fs/nfsfs/volumes", ATTR{read_ahead_kb}="15360" 10 | -------------------------------------------------------------------------------- /60-cdrom_id.rules: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the MIT License. See the LICENSE accompanying this file 4 | # for the specific language governing permissions and limitations under 5 | # the License. 6 | 7 | # This is an empty placeholder file used to signal udev to 8 | # skip probing for cd/dvd drive capabilities. 9 | -------------------------------------------------------------------------------- /70-ec2-nvme-devices.rules: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the MIT License. See the LICENSE accompanying this file 4 | # for the specific language governing permissions and limitations under 5 | # the License. 6 | 7 | ACTION=="remove", GOTO="ec2_nvme_devices_end" 8 | 9 | #nvme-ns-* devices 10 | KERNEL=="nvme[0-9]*n[0-9]*", ENV{DEVTYPE}=="disk", ATTRS{serial}=="?*", ATTRS{model}=="?*", SYMLINK+="disk/by-id/nvme-$attr{model}_$attr{serial}-ns-%n", OPTIONS+="string_escape=replace" 11 | 12 | #nvme partitions 13 | KERNEL=="nvme[0-9]*n[0-9]*p[0-9]*", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?*", ATTRS{model}=="?*", IMPORT{program}="/usr/sbin/ec2nvme-nsid %k" 14 | KERNEL=="nvme[0-9]*n[0-9]*p[0-9]*", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?*", ATTRS{model}=="?*", ENV{_NS_ID}=="?*", SYMLINK+="disk/by-id/nvme-$attr{model}_$attr{serial}-ns-$env{_NS_ID}-part%n", OPTIONS+="string_escape=replace" 15 | 16 | # ebs nvme devices 17 | KERNEL=="nvme[0-9]*n[0-9]*", ENV{DEVTYPE}=="disk", ATTRS{model}=="Amazon Elastic Block Store", PROGRAM="/usr/sbin/ebsnvme-id -u /dev/%k", SYMLINK+="%c" 18 | KERNEL=="nvme[0-9]*n[0-9]*p[0-9]*", ENV{DEVTYPE}=="partition", ATTRS{model}=="Amazon Elastic Block Store", PROGRAM="/usr/sbin/ebsnvme-id -u /dev/%k", SYMLINK+="%c%n" 19 | 20 | # Do not timeout I/O operations on EBS volumes. 21 | KERNEL=="nvme[0-9]*n[0-9]*", ENV{DEVTYPE}=="disk", ATTRS{model}=="Amazon Elastic Block Store", ATTR{queue/io_timeout}="4294967295" 22 | 23 | # instance store nvme devices 24 | KERNEL=="nvme[0-9]*n[0-9]*", ENV{DEVTYPE}=="disk", ATTRS{model}=="Amazon EC2 NVMe Instance Storage", ATTR{queue/io_timeout}="90000" 25 | 26 | LABEL="ec2_nvme_devices_end" 27 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the correct branch. 27 | Amazon Linux 2022 releases are made from the *main* branch, while 28 | Amazon Linux 2 releases are made from the *1.x* branch. Your pull 29 | requests should target the branch appropriate to the distribution 30 | you're targeting with your improvement. If you are targeting a 31 | distribution other than Amazon Linux, you should most likely be 32 | working on the *main* branch. 33 | 2. You check existing open, and recently merged, pull requests to make 34 | sure someone else hasn't addressed the problem already. 35 | 3. You open an issue to discuss any significant work - we would hate 36 | for your time to be wasted. 37 | 38 | To send us a pull request, please: 39 | 40 | 1. Fork the repository. 41 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 42 | 3. Ensure local tests pass. 43 | 4. Commit to your fork using clear commit messages. 44 | 5. Send us a pull request, answering any default questions in the pull request interface. 45 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 46 | 47 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 48 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 49 | 50 | 51 | ## Finding contributions to work on 52 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 53 | 54 | 55 | ## Code of Conduct 56 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 57 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 58 | opensource-codeofconduct@amazon.com with any additional questions or comments. 59 | 60 | 61 | ## Security issue notifications 62 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 63 | 64 | 65 | ## Licensing 66 | 67 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 68 | 69 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 70 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 4 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation the 5 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 6 | persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the 9 | Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 12 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 13 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 14 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | amazon-ec2-utils 2 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## amazon-ec2-utils 2 | 3 | amazon-ec2-utils contains a set of utilities and settings for Linux deployments in EC2. 4 | 5 | It includes: 6 | * ec2-metadata - Use to retrieve EC2 instance metadata from within a running EC2 instance 7 | * ebsnvme-id - Read EBS device information and provide information about the volume. 8 | * Various udev rules to ensure consistent device naming 9 | 10 | ## License 11 | 12 | The utilities in this package are published under the MIT License. The 13 | documentation in the doc subdirectory is licensed under the Creative Commons 14 | Attribution-ShareAlike 4.0 International License. 15 | 16 | -------------------------------------------------------------------------------- /amazon-ec2-utils.spec: -------------------------------------------------------------------------------- 1 | Name: amazon-ec2-utils 2 | Summary: A set of tools for running in EC2 3 | Version: 2.2.0 4 | Release: 1%{?dist} 5 | License: MIT 6 | Group: System Tools 7 | 8 | Source0: ec2-metadata 9 | Source1: ec2udev-vbd 10 | Source2: 51-ec2-hvm-devices.rules 11 | Source16: 60-cdrom_id.rules 12 | Source22: 70-ec2-nvme-devices.rules 13 | Source23: ec2nvme-nsid 14 | Source24: ebsnvme-id 15 | Source25: 51-ec2-xen-vbd-devices.rules 16 | Source26: 53-ec2-read-ahead-kb.rules 17 | Source27: 51-ec2-ena-ptp-device.rules 18 | Source28: ebsnvme 19 | 20 | URL: https://github.com/aws/amazon-ec2-utils 21 | BuildArch: noarch 22 | Provides: ec2-utils = %{version}-%{release} 23 | Obsoletes: ec2-utils < 2.2 24 | Provides: ec2-metadata = %{version}-%{release} 25 | Obsoletes: ec2-metadata <= 0.1.3 26 | Requires: curl 27 | Requires: python3 28 | BuildRequires: python3-devel 29 | BuildRequires: systemd-rpm-macros 30 | BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) 31 | 32 | %description 33 | amazon-ec2-utils contains a set of utilities for running in ec2. 34 | 35 | %prep 36 | 37 | %build 38 | 39 | %install 40 | rm -rf $RPM_BUILD_ROOT 41 | mkdir -p $RPM_BUILD_ROOT%{_bindir} 42 | mkdir -p $RPM_BUILD_ROOT%{_udevrulesdir} 43 | mkdir -p $RPM_BUILD_ROOT%{_sbindir} 44 | mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/udev/rules.d/ 45 | mkdir -p $RPM_BUILD_ROOT%{_mandir}/man8/ 46 | 47 | install -m755 %{SOURCE0} $RPM_BUILD_ROOT%{_bindir} 48 | install -m755 %{SOURCE1} $RPM_BUILD_ROOT%{_sbindir} 49 | install -m644 %{SOURCE2} $RPM_BUILD_ROOT%{_udevrulesdir} 50 | install -m755 %{SOURCE24} $RPM_BUILD_ROOT%{_sbindir} 51 | install -m644 %{SOURCE25} $RPM_BUILD_ROOT%{_udevrulesdir} 52 | install -m644 %{SOURCE26} $RPM_BUILD_ROOT%{_udevrulesdir} 53 | install -m644 %{SOURCE27} $RPM_BUILD_ROOT%{_udevrulesdir} 54 | install -m755 %{SOURCE28} $RPM_BUILD_ROOT%{_sbindir} 55 | # Install 60-cdrom_id.rules to /etc rather than %{_udevrulesdir} 56 | # because it is intended as an override of a systemd-provided rules 57 | # file: 58 | install -m644 %{SOURCE16} $RPM_BUILD_ROOT%{_sysconfdir}/udev/rules.d/ 59 | 60 | #udev rules for nvme block devices and supporting scripts 61 | install -m644 %{SOURCE22} $RPM_BUILD_ROOT%{_udevrulesdir} 62 | install -m755 %{SOURCE23} $RPM_BUILD_ROOT%{_sbindir}/ec2nvme-nsid 63 | 64 | %check 65 | %{python3} -m py_compile %{SOURCE24} 66 | 67 | %clean 68 | rm -rf $RPM_BUILD_ROOT 69 | 70 | %files 71 | %{_bindir}/ec2-metadata 72 | %{_sbindir}/ec2nvme-nsid 73 | %{_sbindir}/ebsnvme 74 | %{_sbindir}/ebsnvme-id 75 | %{_sbindir}/ec2udev-vbd 76 | /usr/lib/udev/rules.d/51-ec2-ena-ptp-device.rules 77 | /usr/lib/udev/rules.d/51-ec2-hvm-devices.rules 78 | /usr/lib/udev/rules.d/51-ec2-xen-vbd-devices.rules 79 | /usr/lib/udev/rules.d/53-ec2-read-ahead-kb.rules 80 | /usr/lib/udev/rules.d/70-ec2-nvme-devices.rules 81 | /etc/udev/rules.d/60-cdrom_id.rules 82 | 83 | %changelog 84 | * Wed May 29 2024 Kuniyuki Iwashima - 2.2.1 85 | - Add symlink for ENA PTP device. 86 | 87 | * Thu Jan 18 2024 Keith Gable - 2.2.0-1 88 | - Corrected issue where an ec2-metadata error was written to stdout 89 | - Change ec2nvme-nsid to use Bash string manipulation to improve 90 | performance and reliability 91 | 92 | * Mon Jun 5 2023 Guillaume Delacour - 2.2.0-1 93 | - Add `--quiet` option to `ec2-metadata --help` output 94 | - Add `-R`/`--region` option to `ec2-metadata` to discover the EC2 instance's region 95 | 96 | * Thu Apr 6 2023 Noah Meyerhans - 2.1.0-1 97 | - Add --quiet option to ec2-metadata 98 | - Add --partition support to ec2-metadata 99 | 100 | * Fri Feb 11 2022 Noah Meyerhans 2.0.1-1 101 | - Don't lose NVME symlinks on udev change events 102 | 103 | * Thu Jan 20 2022 Noah Meyerhans 2.0-1 104 | - Update to 2.0 105 | - Update python dependencies to python3 106 | - Install udev rules to %{_udevrulesdir} rather than a hardcoded /etc/udev 107 | location. 108 | - Install binaries to %{_sbindir} rather than hardcoded /sbin 109 | - Move ec2nvme-nsid to /usr/sbin rather than /usr/lib/udev 110 | - Drop ec2udev-vpcu and related udev rules 111 | - Fix an invalid substitution in 53-ec2-read-ahead-kb.rules 112 | - Drop the /opt/aws/bin/ec2-metadata symlink 113 | 114 | * Wed Nov 17 2021 Noah Meyerhans 1.3-5 115 | - Restrict NVME udev rules to "add" events 116 | 117 | * Wed Nov 17 2021 Hailey Mothershead 1.3-4 118 | - Add udev rule to increase read_ahead_kb when an NFS share is mounted 119 | 120 | * Wed Jul 14 2021 Sai Harsha 1.3-3 121 | - Disable timeout on EBS volumes 122 | 123 | * Thu Oct 29 2020 Frederick Lefebvre 1.3-2 124 | - Add testing of python syntax to spec file 125 | 126 | * Mon May 18 2020 Suraj Jitindar Singh 1.3-1 127 | - Add udev rule to add by-path links for xen vbd devices 128 | 129 | * Tue Apr 28 2020 Frederick Lefebvre 1.3-1 130 | - Rename the project to amazon-ec2-utils 131 | - Add README file 132 | 133 | * Tue Feb 25 2020 Frederick Lefebvre 1.2-1 134 | - Fix output of multi-line fields 135 | 136 | * Wed Jan 15 2020 Frederick Lefebvre 1.1-1 137 | - Add IMDSv2 support 138 | 139 | * Tue Aug 27 2019 Anchal Agarwal 1.0-2 140 | - Add udev rule to define lower timeout for instance storage volumes 141 | 142 | * Wed Sep 22 2010 Nathan Blackham 143 | - move to ec2-utils 144 | - add udev code for symlinking xvd* devices to sd* 145 | 146 | * Tue Sep 07 2010 Nathan Blackham 147 | - initial packaging of script as an rpm 148 | -------------------------------------------------------------------------------- /doc/ebsnvme-id.8: -------------------------------------------------------------------------------- 1 | .\" Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | .\" 3 | .\" This work is licensed under the Creative Commons 4 | \" Attribution-ShareAlike 4.0 International License. To view a copy 5 | \" of this license, visit 6 | \" http://creativecommons.org/licenses/by-sa/4.0/. 7 | \" SPDX-License-Identifier: CC-BY-SA-4.0 8 | .TH EBSNVME-ID 8 "May 4 2020" 9 | .SH NAME 10 | ebsnvme-id \- Reads and prints EBS information from NVMe devices 11 | .SH SYNOPSIS 12 | .B ebsnvme-id 13 | .RI [ options ] " DEVICE" 14 | .br 15 | .SH DESCRIPTION 16 | .B ebsnvme-id 17 | uses the NVME Management Interface to read various metadata about 18 | NVME-attached EBS storage volumes. It can be used to retrive the EBS 19 | Volume ID or EC2 API device mapping value given the local block device 20 | name. 21 | 22 | .SH OPTIONS 23 | .TP 24 | .B \-v, \-\-volume 25 | Return volume-id 26 | .TP 27 | .B \-b, \-\-block-dev 28 | Return block device mapping 29 | .TP 30 | .B \-u, \-\-udev 31 | Output data in format suitable for udev rules 32 | .TP 33 | .B \-h, \-\-help 34 | Show summary of options. 35 | .SH SEE ALSO 36 | .BR nvme (1), 37 | .BR ec2-metadata (1). 38 | .PP 39 | The storage chapter of the Amazon EC2 User Guide 40 | .br 41 | https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Storage.html 42 | -------------------------------------------------------------------------------- /doc/ec2-metadata.8: -------------------------------------------------------------------------------- 1 | .\" Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | .\" 3 | .\" This work is licensed under the Creative Commons 4 | \" Attribution-ShareAlike 4.0 International License. To view a copy 5 | \" of this license, visit 6 | \" http://creativecommons.org/licenses/by-sa/4.0/. 7 | \" SPDX-License-Identifier: CC-BY-SA-4.0 8 | .\" 9 | .\" Much of the text in the DESCRIPTION section is taken from 10 | .\" https://github.com/awsdocs/amazon-ec2-user-guide/blob/master/doc_source/ec2-instance-metadata.md 11 | .\" 12 | .TH EC2-METADATA 8 "May 4 2020" 13 | .SH NAME 14 | ec2-metadata \- Retrieve instance metadata from within a running EC2 instance 15 | .SH SYNOPSIS 16 | .B ec2-metadata 17 | .RI [ options ] 18 | .br 19 | .SH DESCRIPTION 20 | The 21 | .B ec2-metadata 22 | program is a utility to retrieve EC2 instance metadata from within a 23 | running EC2 instance. 24 | 25 | Instance metadata is data about your instance that you can use to 26 | configure or manage the running instance. Instance metadata is divided 27 | into categories, for example, host name, events, and security groups. 28 | 29 | You can also use instance metadata to access user data that you 30 | specified when launching your instance. For example, you can specify 31 | parameters for configuring your instance, or include a simple 32 | script. You can build generic AMIs and use user data to modify the 33 | configuration files supplied at launch time. For example, if you run 34 | web servers for various small businesses, they can all use the same 35 | generic AMI and retrieve their content from the Amazon S3 bucket that 36 | you specify in the user data at launch. To add a new customer at any 37 | time, create a bucket for the customer, add their content, and launch 38 | your AMI with the unique bucket name provided to your code in the user 39 | data. If you launch more than one instance at the same time, the user 40 | data is available to all instances in that reservation. Each instance 41 | that is part of the same reservation has a unique ami-launch-index 42 | number, allowing you to write code that controls what to do. For 43 | example, the first host might elect itself as an initial master node 44 | in a cluster. 45 | 46 | .PP 47 | .SH OPTIONS 48 | .B ec2-metadata 49 | will print all known metadata fields by default. The following 50 | options can be used to restrict the output to the selected fields. 51 | 52 | .TP 53 | .B \-\-all 54 | Show all metadata information for this host (also default). 55 | .TP 56 | .B \-a/\-\-ami-id 57 | The AMI ID used to launch this instance 58 | .TP 59 | .B \-l/\-\-ami-launch-index 60 | The index of this instance in the reservation (per AMI). 61 | .TP 62 | .B \-m/\-\-ami-manifest-path 63 | The manifest path of the AMI with which the instance was launched. 64 | .TP 65 | .B \-n/\-\-ancestor-ami-ids 66 | The AMI IDs of any instances that were rebundled to create this AMI. 67 | .TP 68 | .B \-b/\-\-block-device-mapping 69 | Defines native device names to use when exposing virtual devices. 70 | .TP 71 | .B \-i/\-\-instance-id 72 | The ID of this instance 73 | .TP 74 | .B \-t/\-\-instance-type 75 | The type of instance to launch. For more information, see Instance Types. 76 | .TP 77 | .B \-h/\-\-local-hostname 78 | The local hostname of the instance. 79 | .TP 80 | .B \-o/\-\-local-ipv4 81 | Public IP address if launched with direct addressing; private IP address if launched with public addressing. 82 | .TP 83 | .B \-k/\-\-kernel-id 84 | The ID of the kernel launched with this instance, if applicable. 85 | .TP 86 | .B \-z/\-\-availability-zone 87 | The availability zone in which the instance launched. Same as placement 88 | .TP 89 | .B \-R/\-\-region 90 | The region in which the instance launched. 91 | .TP 92 | .B \-c/\-\-product-codes 93 | Product codes associated with this instance. 94 | .TP 95 | .B \-p/\-\-public-hostname 96 | The public hostname of the instance. 97 | .TP 98 | .B \-v/\-\-public-ipv4 99 | NATted public IP Address 100 | .TP 101 | .B \-u/\-\-public-keys 102 | Public keys. Only available if supplied at instance launch time 103 | .TP 104 | .B \-r/\-\-ramdisk-id 105 | The ID of the RAM disk launched with this instance, if applicable. 106 | .TP 107 | .B \-e/\-\-reservation-id 108 | ID of the reservation. 109 | .TP 110 | .B \-s/\-\-security-groups 111 | Names of the security groups the instance is launched in. Only available if supplied at instance launch time 112 | .TP 113 | .B \-d/\-\-user-data 114 | User-supplied data.Only available if supplied at instance launch time. 115 | .TP 116 | .B \-t/\-\-tags 117 | Print EC2 resource tags if permitted in EC2 Instance Metadata Options. 118 | .TP 119 | .B \-\-quiet 120 | Don't print metadata keys 121 | .TP 122 | .B \-\-path 123 | Show metadata information from the specified path. Can be specified multiple times. 124 | .TP 125 | .B \-h, \-\-help 126 | Show summary of options. 127 | .SH SEE ALSO 128 | .br 129 | .IP " 1." 4 130 | Instance metadata and user data 131 | .RS 4 132 | https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html 133 | .RE 134 | .IP " 2." 4 135 | EC2 Instance Metadata Query Tool 136 | .RS 4 137 | https://aws.amazon.com/code/ec2-instance-metadata-query-tool/ 138 | .RE 139 | .IP " 3." 4 140 | Work with instance tags in instance metadata 141 | .RS 4 142 | https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS 143 | .RE 144 | 145 | -------------------------------------------------------------------------------- /ebsnvme: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the MIT License. See the LICENSE accompanying this file 6 | # for the specific language governing permissions and limitations under 7 | # the License. 8 | 9 | """ 10 | Usage: 11 | Reads EBS information from EBS NVMe device 12 | """ 13 | 14 | from __future__ import print_function 15 | import argparse 16 | from ctypes import Structure, Array, c_uint8, c_uint16, c_uint32, c_uint64, \ 17 | c_char, addressof, sizeof, byref 18 | from fcntl import ioctl 19 | import json 20 | import os 21 | import signal 22 | import sys 23 | import time 24 | 25 | NVME_ADMIN_IDENTIFY = 0x06 26 | NVME_GET_LOG_PAGE = 0x02 27 | NVME_IOCTL_ADMIN_CMD = 0xC0484E41 28 | 29 | AMZN_NVME_EBS_MN = "Amazon Elastic Block Store" 30 | AMZN_NVME_STATS_LOGPAGE_ID = 0xD0 31 | AMZN_NVME_STATS_MAGIC = 0x3C23B510 32 | AMZN_NVME_VID = 0x1D0F 33 | 34 | 35 | class structure_dict_mixin: 36 | def to_dict(self): 37 | return { 38 | field[0]: getattr(self, field[0]) 39 | for field in self._fields_ 40 | if not field[0].startswith("_") and 41 | not isinstance(getattr(self, field[0]), (Structure, Array)) 42 | } 43 | 44 | 45 | class nvme_admin_command(Structure): 46 | _pack_ = 1 47 | _fields_ = [("opcode", c_uint8), 48 | ("flags", c_uint8), 49 | ("cid", c_uint16), 50 | ("nsid", c_uint32), 51 | ("_reserved0", c_uint64), 52 | ("mptr", c_uint64), 53 | ("addr", c_uint64), 54 | ("mlen", c_uint32), 55 | ("alen", c_uint32), 56 | ("cdw10", c_uint32), 57 | ("cdw11", c_uint32), 58 | ("cdw12", c_uint32), 59 | ("cdw13", c_uint32), 60 | ("cdw14", c_uint32), 61 | ("cdw15", c_uint32), 62 | ("_reserved1", c_uint64)] 63 | 64 | 65 | class nvme_identify_controller_amzn_vs(Structure): 66 | _pack_ = 1 67 | _fields_ = [("bdev", c_char * 32), # block device name 68 | ("_reserved0", c_char * (1024 - 32))] 69 | 70 | 71 | class nvme_identify_controller_psd(Structure): 72 | _pack_ = 1 73 | _fields_ = [("mp", c_uint16), # maximum power 74 | ("_reserved0", c_uint16), 75 | ("enlat", c_uint32), # entry latency 76 | ("exlat", c_uint32), # exit latency 77 | ("rrt", c_uint8), # relative read throughput 78 | ("rrl", c_uint8), # relative read latency 79 | ("rwt", c_uint8), # relative write throughput 80 | ("rwl", c_uint8), # relative write latency 81 | ("_reserved1", c_char * 16)] 82 | 83 | 84 | class nvme_identify_controller(Structure): 85 | _pack_ = 1 86 | _fields_ = [("vid", c_uint16), # PCI Vendor ID 87 | ("ssvid", c_uint16), # PCI Subsystem Vendor ID 88 | ("sn", c_char * 20), # Serial Number 89 | ("mn", c_char * 40), # Module Number 90 | ("fr", c_char * 8), # Firmware Revision 91 | ("rab", c_uint8), # Recommend Arbitration Burst 92 | ("ieee", c_uint8 * 3), # IEEE OUI Identifier 93 | ("mic", c_uint8), # Multi-Interface Capabilities 94 | ("mdts", c_uint8), # Maximum Data Transfer Size 95 | ("_reserved0", c_uint8 * (256 - 78)), 96 | ("oacs", c_uint16), # Optional Admin Command Support 97 | ("acl", c_uint8), # Abort Command Limit 98 | ("aerl", c_uint8), # Asynchronous Event Request Limit 99 | ("frmw", c_uint8), # Firmware Updates 100 | ("lpa", c_uint8), # Log Page Attributes 101 | ("elpe", c_uint8), # Error Log Page Entries 102 | ("npss", c_uint8), # Number of Power States Support 103 | ("avscc", c_uint8), # Admin Vendor Specific Command Configuration # noqa 104 | ("_reserved1", c_uint8 * (512 - 265)), 105 | ("sqes", c_uint8), # Submission Queue Entry Size 106 | ("cqes", c_uint8), # Completion Queue Entry Size 107 | ("_reserved2", c_uint16), 108 | ("nn", c_uint32), # Number of Namespaces 109 | ("oncs", c_uint16), # Optional NVM Command Support 110 | ("fuses", c_uint16), # Fused Operation Support 111 | ("fna", c_uint8), # Format NVM Attributes 112 | ("vwc", c_uint8), # Volatile Write Cache 113 | ("awun", c_uint16), # Atomic Write Unit Normal 114 | ("awupf", c_uint16), # Atomic Write Unit Power Fail 115 | ("nvscc", c_uint8), # NVM Vendor Specific Command Configuration # noqa 116 | ("_reserved3", c_uint8 * (704 - 531)), 117 | ("_reserved4", c_uint8 * (2048 - 704)), 118 | ("psd", nvme_identify_controller_psd * 32), # Power State Descriptor # noqa 119 | ("vs", nvme_identify_controller_amzn_vs)] # Vendor Specific 120 | 121 | 122 | class nvme_histogram_bin(Structure, structure_dict_mixin): 123 | _pack_ = 1 124 | _fields_ = [("lower", c_uint64), 125 | ("upper", c_uint64), 126 | ("count", c_uint32), 127 | ("_reserved0", c_uint32)] 128 | 129 | def to_human_readable(self): 130 | print("[{0.lower:<8} - {0.upper:<8}] => {0.count}".format(self)) 131 | 132 | 133 | class ebs_nvme_histogram(Structure, structure_dict_mixin): 134 | _pack_ = 1 135 | _fields_ = [("num_bins", c_uint64), 136 | ("bins", nvme_histogram_bin * 64)] 137 | 138 | def to_dict(self): 139 | dict = super(ebs_nvme_histogram, self).to_dict() 140 | dict["bins"] = [self.bins[i].to_dict() for i in range(self.num_bins)] 141 | 142 | return dict 143 | 144 | def to_human_readable(self): 145 | print("Number of bins: {0}".format(self.num_bins)) 146 | 147 | print("=================================") 148 | print("Lower Upper IO Count") 149 | print("=================================") 150 | 151 | for i in range(self.num_bins): 152 | self.bins[i].to_human_readable() 153 | 154 | 155 | class nvme_get_amzn_stats_logpage(Structure, structure_dict_mixin): 156 | _pack_ = 1 157 | _fields_ = [("_magic", c_uint32), 158 | ("_reserved0", c_char * 4), 159 | ("total_read_ops", c_uint64), # total number of read operations 160 | ("total_write_ops", c_uint64), # total number of write operations 161 | ("total_read_bytes", c_uint64), # total bytes read 162 | ("total_write_bytes", c_uint64), # total bytes written 163 | ("total_read_time", c_uint64), # total time spent on read operations (in microseconds) 164 | ("total_write_time", c_uint64), # total time spent on write operations (in microseconds) 165 | ("ebs_volume_performance_exceeded_iops", c_uint64), # time EBS volume IOPS limit was exceeded (in microseconds) 166 | ("ebs_volume_performance_exceeded_tp", c_uint64), # time EBS volume throughput limit was exceeded (in microseconds) 167 | ("ec2_instance_ebs_performance_exceeded_iops", c_uint64), # time EC2 instance EBS IOPS limit was exceeded (in microseconds) 168 | ("ec2_instance_ebs_performance_exceeded_tp", c_uint64), # time EC2 instance EBS throughput limit was exceeded (in microseconds) 169 | ("volume_queue_length", c_uint64), # current volume queue length 170 | ("_reserved1", c_char * 416), 171 | ("read_io_latency_histogram", ebs_nvme_histogram), # histogram of read I/O latencies (in microseconds) 172 | ("write_io_latency_histogram", ebs_nvme_histogram), # histogram of write I/O latencies (in microseconds) 173 | ("_reserved2", c_char * 496)] 174 | 175 | def to_dict(self): 176 | dict = super(nvme_get_amzn_stats_logpage, self).to_dict() 177 | dict["read_io_latency_histogram"] = self.read_io_latency_histogram.to_dict() 178 | dict["write_io_latency_histogram"] = self.write_io_latency_histogram.to_dict() 179 | 180 | return dict 181 | 182 | def to_json(self): 183 | print(json.dumps(self.to_dict())) 184 | 185 | def to_human_readable(self): 186 | print("Total Ops") 187 | print(" Read: {0}".format(self.total_read_ops)) 188 | print(" Write: {0}".format(self.total_write_ops)) 189 | print("Total Bytes") 190 | print(" Read: {0}".format(self.total_read_bytes)) 191 | print(" Write: {0}".format(self.total_write_bytes)) 192 | print("Total Time (us)") 193 | print(" Read: {0}".format(self.total_read_time)) 194 | print(" Write: {0}".format(self.total_write_time)) 195 | 196 | print("EBS Volume Performance Exceeded (us)") 197 | print(" IOPS: {0}".format(self.ebs_volume_performance_exceeded_iops)) 198 | print(" Throughput: {0}".format(self.ebs_volume_performance_exceeded_tp)) 199 | print("EC2 Instance EBS Performance Exceeded (us)") 200 | print(" IOPS: {0}".format(self.ec2_instance_ebs_performance_exceeded_iops)) 201 | print(" Throughput: {0}".format(self.ec2_instance_ebs_performance_exceeded_tp)) 202 | 203 | print("Queue Length (point in time): {0} \n".format(self.volume_queue_length)) 204 | 205 | print("Read IO Latency Histogram (us)") 206 | self.read_io_latency_histogram.to_human_readable() 207 | 208 | print("\nWrite IO Latency Histogram (us)") 209 | self.write_io_latency_histogram.to_human_readable() 210 | 211 | 212 | class ebs_nvme_device: 213 | def __init__(self, device): 214 | self.device = device 215 | 216 | def _nvme_ioctl(self, admin_cmd): 217 | 218 | with open(self.device, "r") as dev: 219 | try: 220 | ioctl(dev, NVME_IOCTL_ADMIN_CMD, admin_cmd) 221 | except (OSError) as err: 222 | print("Failed to issue nvme cmd, err: ", err) 223 | sys.exit(1) 224 | 225 | 226 | class ebs_nvme_device_stats(ebs_nvme_device): 227 | def _query_stats_from_device(self): 228 | stats = nvme_get_amzn_stats_logpage() 229 | admin_cmd = nvme_admin_command( 230 | opcode=NVME_GET_LOG_PAGE, 231 | addr=addressof(stats), 232 | alen=sizeof(stats), 233 | nsid=1, 234 | cdw10=(AMZN_NVME_STATS_LOGPAGE_ID | (1024 << 16)) 235 | ) 236 | self._nvme_ioctl(admin_cmd) 237 | 238 | if stats._magic != AMZN_NVME_STATS_MAGIC: 239 | raise TypeError("[ERROR] Not an EBS device: {0}".format(self.device)) 240 | 241 | return stats 242 | 243 | def _get_stats_diff(self): 244 | curr = self._query_stats_from_device() 245 | if self.prev is None: 246 | self.prev = curr 247 | return curr 248 | 249 | diff = nvme_get_amzn_stats_logpage() 250 | diff.volume_queue_length = curr.volume_queue_length 251 | 252 | for field, _ in nvme_get_amzn_stats_logpage._fields_: 253 | if field.startswith('_') or field == "volume_queue_length": 254 | continue 255 | if isinstance(getattr(self.prev, field), (int)): 256 | setattr(diff, field, getattr(curr, field) - getattr(self.prev, field)) 257 | 258 | for histogram_field in ['read_io_latency_histogram', 'write_io_latency_histogram']: 259 | self._calculate_histogram_diff(diff, curr, self.prev, histogram_field) 260 | 261 | self.prev = curr 262 | return diff 263 | 264 | def _calculate_histogram_diff(self, diff, curr, prev, histogram_field): 265 | prev_hist = getattr(prev, histogram_field) 266 | curr_hist = getattr(curr, histogram_field) 267 | diff_hist = getattr(diff, histogram_field) 268 | 269 | diff_hist.num_bins = curr_hist.num_bins 270 | for i in range(diff_hist.num_bins): 271 | diff_hist.bins[i].lower = curr_hist.bins[i].lower 272 | diff_hist.bins[i].upper = curr_hist.bins[i].upper 273 | diff_hist.bins[i].count = curr_hist.bins[i].count - prev_hist.bins[i].count 274 | 275 | def _print_stats(self, stats, json_format=False): 276 | if json_format: 277 | print(json.dumps(stats.to_dict())) 278 | else: 279 | stats.to_human_readable() 280 | 281 | def _signal_handler(self, sig, frame): 282 | sys.exit(0) 283 | 284 | def get_stats(self, interval=0, json_format=False): 285 | if interval > 0: 286 | print("Polling EBS stats every {0} sec(s); press Ctrl+C to stop".format(interval)) 287 | signal.signal(signal.SIGINT, self._signal_handler) 288 | self.prev = None 289 | 290 | while True: 291 | self._print_stats(self._get_stats_diff(), json_format) 292 | time.sleep(interval) 293 | print("\n") 294 | 295 | else: 296 | self._print_stats(self._query_stats_from_device(), json_format) 297 | 298 | class ebs_nvme_device_id(ebs_nvme_device): 299 | def get_id(self, volume=False, block_dev=False, udev=False): 300 | id_ctrl = self._query_id_ctrl_from_device() 301 | 302 | if not (volume or block_dev or udev): 303 | print("Volume ID: {0}".format(self._get_volume_id(id_ctrl))) 304 | print(self._get_block_device(id_ctrl)) 305 | else: 306 | if volume: 307 | print("Volume ID: {0}".format(self._get_volume_id(id_ctrl))) 308 | if block_dev or udev: 309 | print(self._get_block_device(id_ctrl, udev)) 310 | 311 | def _query_id_ctrl_from_device(self): 312 | id_ctrl = nvme_identify_controller() 313 | admin_cmd = nvme_admin_command( 314 | opcode=NVME_ADMIN_IDENTIFY, 315 | addr=addressof(id_ctrl), 316 | alen=sizeof(id_ctrl), 317 | cdw10=1 318 | ) 319 | self._nvme_ioctl(admin_cmd) 320 | 321 | if id_ctrl.vid != AMZN_NVME_VID or id_ctrl.mn.decode().strip() != AMZN_NVME_EBS_MN: 322 | raise TypeError("[ERROR] Not an EBS device: ", self.device) 323 | 324 | return id_ctrl 325 | 326 | def _get_volume_id(self, id_ctrl): 327 | vol = id_ctrl.sn.decode() 328 | if vol.startswith("vol") and vol[3] != "-": 329 | vol = "vol-" + vol[3:] 330 | return vol 331 | 332 | def _get_block_device(self, id_ctrl, stripped=False): 333 | dev = id_ctrl.vs.bdev.decode().strip() 334 | if stripped and dev.startswith("/dev/"): 335 | dev = dev[5:] 336 | return dev 337 | 338 | 339 | if __name__ == "__main__": 340 | 341 | # check if the script is being called as ebsnvme-id 342 | if os.path.basename(sys.argv[0]) == 'ebsnvme-id': 343 | sys.argv.insert(1, 'id') 344 | 345 | parser = argparse.ArgumentParser(description="Reads EBS information from EBS NVMe devices.") 346 | cmd_parser = parser.add_subparsers(dest="cmd", help="Available commands") 347 | cmd_parser.required = True 348 | 349 | stats_parser = cmd_parser.add_parser("stats", help="Get EBS NVMe stats") 350 | stats_parser.add_argument("device", help="Device to query") 351 | stats_parser.required = True 352 | stats_parser.add_argument("-j", "--json", action="store_true", 353 | help="Output in json format") 354 | stats_parser.add_argument("-i", "--interval", type=int, default=0, 355 | help='Interval in seconds to poll ebs stats') 356 | 357 | id_parser = cmd_parser.add_parser("id", help="Display id options") 358 | id_parser.add_argument("device", help="Device to query") 359 | id_parser.required = True 360 | id_parser.add_argument("-v", "--volume", action="store_true", 361 | help="Return volume-id") 362 | id_parser.add_argument("-b", "--block-dev", action="store_true", 363 | help="Return block device mapping") 364 | id_parser.add_argument("-u", "--udev", action="store_true", 365 | help="Output data in format suitable for udev rules") 366 | 367 | args = parser.parse_args() 368 | 369 | try: 370 | if args.cmd == "stats": 371 | stats = ebs_nvme_device_stats(args.device) 372 | stats.get_stats(interval=args.interval, json_format=args.json) 373 | 374 | elif args.cmd == "id": 375 | id_info = ebs_nvme_device_id(args.device) 376 | id_info.get_id(volume=args.volume, block_dev=args.block_dev, udev=args.udev) 377 | except (IOError, TypeError) as err: 378 | print(err, file=sys.stderr) 379 | sys.exit(1) 380 | -------------------------------------------------------------------------------- /ebsnvme-id: -------------------------------------------------------------------------------- 1 | ebsnvme -------------------------------------------------------------------------------- /ec2-metadata: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the MIT License. See the LICENSE accompanying this file 6 | # for the specific language governing permissions and limitations under 7 | # the License. 8 | 9 | function print_help() 10 | { 11 | echo "ec2-metadata v0.1.5 12 | Use to retrieve EC2 instance metadata from within a running EC2 instance. 13 | e.g. to retrieve instance id: ec2-metadata -i 14 | to retrieve ami id: ec2-metadata -a 15 | to get help: ec2-metadata --help 16 | For more information on Amazon EC2 instance meta-data, refer to the documentation at 17 | https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html 18 | 19 | Usage: ec2-metadata