forked from amazonlinux/amazon-ec2-utils
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ebsnvme-id
177 lines (139 loc) · 3.81 KB
/
ebsnvme-id
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!/usr/bin/bash
# Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved.
#
# Licensed under the MIT License. See the LICENSE accompanying this file
# for the specific language governing permissions and limitations under
# the License.
# Bash/Unix implementation of ebsnvme-id that requires nvme-cli >= 1.13
# Since this has to run inside initramfs, this is not using getopt/getopts.
# Change this in case your distro puts nvme-cli in a different location
NVME=/usr/sbin/nvme
# The EBS model name
EBS_MN="Amazon Elastic Block Store"
##
# Ensures that the kernel device name in $1 is actually an EBS volume.
ensure_ebs_volume() {
local device=$1
local mn
if [[ ! -b /dev/$device ]]; then
echo "[ERROR] /dev/$device is not a block device" >&2
exit 1
fi
mn="$(read_nvme_attr "$device" mn)"
if [[ "$mn" != "${EBS_MN}" ]]; then
echo "[ERROR] /dev/$device is not an EBS device, but is ${mn:-<unknown>}" >&2
exit 1
fi
}
##
# Prints the block device mapping name for the device specified in $1
print_block_device_mapping() {
local device=$1
local block_device_name
block_device_name=$(read_block_device_name "$device")
echo "${block_device_name}"
}
##
# Prints udev env vars for the device specified in $1
print_udev_env() {
local device=$1
local bdev
local volid
bdev=$(read_block_device_name "$device")
volid=$(read_volume_id "$device")
if [[ -z $bdev ]] || [[ -z $volid ]]; then
echo "[ERROR] /dev/$device cannot determine udev environment" >&2
exit 1
fi
echo "_EC2_BLOCK_DEVICE_MAPPING=${bdev}"
echo "_EBS_VOLUME_ID=${volid}"
}
##
# Prints the volume ID for the device specified in $1
print_volume_id() {
local device=$1
local vol_id
vol_id=$(read_volume_id "$device")
echo "Volume ID: ${vol_id}"
}
##
# Reads the block device name from the device specified in $1 and strips off
# any leading /dev/ that might be present
read_block_device_name() {
local device=$1
local bdev
ensure_ebs_volume "$device"
bdev=$(read_nvme_attr "$device" bdev)
if [[ -z $bdev ]]; then
echo "[ERROR] /dev/$device has no block device mapping available" >&2
exit 1
fi
printf "%s" "${bdev#/dev/}"
}
##
# Reads the NVMe attribute specified by $2 from the device specified in $1
read_nvme_attr() {
local device=$1
local nvme_attr=$2
${NVME} amzn id-ctrl "/dev/${device}" | while read -r line; do
if [[ $line =~ ^${nvme_attr}[[:space:]]*: ]]; then
printf "%s" "${line#*: }"
return 0
fi
done
return 1
}
##
# Reads the volume ID for the device specified in $1 and parses it into a
# regular EBS vol-abcdef12345 format.
read_volume_id() {
local device=$1
local sn
ensure_ebs_volume "$device"
sn=$(read_nvme_attr "$device" sn)
if [[ -z $sn ]]; then
echo "[ERROR] /dev/$device has no volume ID available" >&2
exit 1
fi
# Strip the prefix, which is usually vol, but we should tolerate vol- too
local without_prefix=${sn#vol}
# Print out vol-XXX after stripping the - prefix which is probably not present
printf "vol-%s" "${without_prefix#-}"
}
##
# Prints program usage information and exits
usage() {
echo "usage: ebsnvme-id [OPTION]
Reads EBS information from NVMe devices.
Options:
-h show this help message and exit
-v DEVICE Return volume ID
-b DEVICE Return block device mapping
-u DEVICE Deprecated alias for -b DEVICE
-U DEVICE Output data in a format suitable to be used as an IMPORT{program} in a udev rule
"
}
# Check if we have enough arguments
if [[ $# -ne 2 ]]; then
usage
exit 1
fi
# Name the arguments and strip any leading /dev
option="$1"
device="${2#/dev/}"
# Parse options
case $option in
-U)
print_udev_env "$device"
;;
-b | -u)
print_block_device_mapping "$device"
;;
-v)
print_volume_id "$device"
;;
*)
usage
exit 1
;;
esac