github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/client/fingerprint/env_aws.go (about) 1 package fingerprint 2 3 import ( 4 "fmt" 5 "net/http" 6 "net/url" 7 "os" 8 "regexp" 9 "strings" 10 "time" 11 12 "github.com/aws/aws-sdk-go/aws" 13 "github.com/aws/aws-sdk-go/aws/awserr" 14 "github.com/aws/aws-sdk-go/aws/ec2metadata" 15 "github.com/aws/aws-sdk-go/aws/session" 16 log "github.com/hashicorp/go-hclog" 17 18 cleanhttp "github.com/hashicorp/go-cleanhttp" 19 "github.com/hashicorp/nomad/nomad/structs" 20 ) 21 22 const ( 23 // AwsMetadataTimeout is the timeout used when contacting the AWS metadata 24 // services. 25 AwsMetadataTimeout = 2 * time.Second 26 ) 27 28 // map of instance type to approximate speed, in Mbits/s 29 // Estimates from http://stackoverflow.com/a/35806587 30 // This data is meant for a loose approximation 31 var ec2NetSpeedTable = map[*regexp.Regexp]int{ 32 regexp.MustCompile("t2.nano"): 30, 33 regexp.MustCompile("t2.micro"): 70, 34 regexp.MustCompile("t2.small"): 125, 35 regexp.MustCompile("t2.medium"): 300, 36 regexp.MustCompile("m3.medium"): 400, 37 regexp.MustCompile("c4.8xlarge"): 4000, 38 regexp.MustCompile("x1.16xlarge"): 5000, 39 regexp.MustCompile(`.*\.large`): 500, 40 regexp.MustCompile(`.*\.xlarge`): 750, 41 regexp.MustCompile(`.*\.2xlarge`): 1000, 42 regexp.MustCompile(`.*\.4xlarge`): 2000, 43 regexp.MustCompile(`.*\.8xlarge`): 10000, 44 regexp.MustCompile(`.*\.10xlarge`): 10000, 45 regexp.MustCompile(`.*\.16xlarge`): 10000, 46 regexp.MustCompile(`.*\.32xlarge`): 10000, 47 } 48 49 type ec2Specs struct { 50 mhz float64 51 cores int 52 model string 53 } 54 55 func (e ec2Specs) ticks() int { 56 return int(e.mhz) * e.cores 57 } 58 59 func specs(ghz float64, vCores int, model string) ec2Specs { 60 return ec2Specs{ 61 mhz: ghz * 1000, 62 cores: vCores, 63 model: model, 64 } 65 } 66 67 // Map of instance type to documented CPU speed. 68 // 69 // Most values are taken from https://aws.amazon.com/ec2/instance-types/. 70 // Values for a1 & m6g (Graviton) are taken from https://en.wikichip.org/wiki/annapurna_labs/alpine/al73400 71 // Values for inf1 are taken from launching a inf1.xlarge and looking at /proc/cpuinfo 72 // 73 // In a few cases, AWS has upgraded the generation of CPU while keeping the same 74 // instance designation. Since it is possible to launch on the lower performance 75 // CPU, that one is used as the spec for the instance type. 76 // 77 // This table is provided as a best-effort to determine the number of CPU ticks 78 // available for use by Nomad tasks. If an instance type is missing, the fallback 79 // behavior is to use values from go-psutil, which is only capable of reading 80 // "current" CPU MHz. 81 var ec2ProcSpeedTable = map[string]ec2Specs{ 82 // -- General Purpose -- 83 84 // a1 85 "a1.medium": specs(2.3, 1, "AWS Graviton"), 86 "a1.large": specs(2.3, 2, "AWS Graviton"), 87 "a1.xlarge": specs(2.3, 4, "AWS Graviton"), 88 "a1.2xlarge": specs(2.3, 8, "AWS Graviton"), 89 "a1.4xlarge": specs(2.3, 16, "AWS Graviton"), 90 "a1.metal": specs(2.3, 16, "AWS Graviton"), 91 92 // t3 93 "t3.nano": specs(2.5, 2, "2.5 GHz Intel Scalable"), 94 "t3.micro": specs(2.5, 2, "2.5 GHz Intel Scalable"), 95 "t3.small": specs(2.5, 2, "2.5 GHz Intel Scalable"), 96 "t3.medium": specs(2.5, 2, "2.5 GHz Intel Scalable"), 97 "t3.large": specs(2.5, 2, "2.5 GHz Intel Scalable"), 98 "t3.xlarge": specs(2.5, 4, "2.5 GHz Intel Scalable"), 99 "t3.2xlarge": specs(2.5, 8, "2.5 GHz Intel Scalable"), 100 101 // t3a 102 "t3a.nano": specs(2.5, 2, "2.5 GHz AMD EPYC 7000 series"), 103 "t3a.micro": specs(2.5, 2, "2.5 GHz AMD EPYC 7000 series"), 104 "t3a.small": specs(2.5, 2, "2.5 GHz AMD EPYC 7000 series"), 105 "t3a.medium": specs(2.5, 2, "2.5 GHz AMD EPYC 7000 series"), 106 "t3a.large": specs(2.5, 2, "2.5 GHz AMD EPYC 7000 series"), 107 "t3a.xlarge": specs(2.5, 4, "2.5 GHz AMD EPYC 7000 series"), 108 "t3a.2xlarge": specs(2.5, 8, "2.5 GHz AMD EPYC 7000 series"), 109 110 // t2 111 "t2.nano": specs(3.3, 1, "3.3 GHz Intel Scalable"), 112 "t2.micro": specs(3.3, 1, "3.3 GHz Intel Scalable"), 113 "t2.small": specs(3.3, 1, "3.3 GHz Intel Scalable"), 114 "t2.medium": specs(3.3, 2, "3.3 GHz Intel Scalable"), 115 "t2.large": specs(3.0, 2, "3.0 GHz Intel Scalable"), 116 "t2.xlarge": specs(3.0, 4, "3.0 GHz Intel Scalable"), 117 "t2.2xlarge": specs(3.0, 8, "3.0 GHz Intel Scalable"), 118 119 // m6g 120 "m6g.medium": specs(2.3, 1, "AWS Graviton2 Neoverse"), 121 "m6g.large": specs(2.3, 2, "AWS Graviton2 Neoverse"), 122 "m6g.xlarge": specs(2.3, 4, "AWS Graviton2 Neoverse"), 123 "m6g.2xlarge": specs(2.3, 8, "AWS Graviton2 Neoverse"), 124 "m6g.4xlarge": specs(2.3, 16, "AWS Graviton2 Neoverse"), 125 "m6g.8xlarge": specs(2.3, 32, "AWS Graviton2 Neoverse"), 126 "m6g.12xlarge": specs(2.3, 48, "AWS Graviton2 Neoverse"), 127 "m6g.16xlarge": specs(2.3, 64, "AWS Graviton2 Neoverse"), 128 129 // m5, m5d 130 "m5.large": specs(3.1, 2, "3.1 GHz Intel Xeon Platinum"), 131 "m5.xlarge": specs(3.1, 4, "3.1 GHz Intel Xeon Platinum"), 132 "m5.2xlarge": specs(3.1, 8, "3.1 GHz Intel Xeon Platinum"), 133 "m5.4xlarge": specs(3.1, 16, "3.1 GHz Intel Xeon Platinum"), 134 "m5.8xlarge": specs(3.1, 32, "3.1 GHz Intel Xeon Platinum"), 135 "m5.12xlarge": specs(3.1, 48, "3.1 GHz Intel Xeon Platinum"), 136 "m5.16xlarge": specs(3.1, 64, "3.1 GHz Intel Xeon Platinum"), 137 "m5.24xlarge": specs(3.1, 96, "3.1 GHz Intel Xeon Platinum"), 138 "m5.metal": specs(3.1, 96, "3.1 GHz Intel Xeon Platinum"), 139 "m5d.large": specs(3.1, 2, "3.1 GHz Intel Xeon Platinum"), 140 "m5d.xlarge": specs(3.1, 4, "3.1 GHz Intel Xeon Platinum"), 141 "m5d.2xlarge": specs(3.1, 8, "3.1 GHz Intel Xeon Platinum"), 142 "m5d.4xlarge": specs(3.1, 16, "3.1 GHz Intel Xeon Platinum"), 143 "m5d.8xlarge": specs(3.1, 32, "3.1 GHz Intel Xeon Platinum"), 144 "m5d.12xlarge": specs(3.1, 48, "3.1 GHz Intel Xeon Platinum"), 145 "m5d.16xlarge": specs(3.1, 64, "3.1 GHz Intel Xeon Platinum"), 146 "m5d.24xlarge": specs(3.1, 96, "3.1 GHz Intel Xeon Platinum"), 147 "m5d.metal": specs(3.1, 96, "3.1 GHz Intel Xeon Platinum"), 148 149 // m5a, m5ad 150 "m5a.large": specs(2.5, 2, "2.5 GHz AMD EPYC 7000 series"), 151 "m5a.xlarge": specs(2.5, 4, "2.5 GHz AMD EPYC 7000 series"), 152 "m5a.2xlarge": specs(2.5, 8, "2.5 GHz AMD EPYC 7000 series"), 153 "m5a.4xlarge": specs(2.5, 16, "2.5 GHz AMD EPYC 7000 series"), 154 "m5a.8xlarge": specs(2.5, 32, "2.5 GHz AMD EPYC 7000 series"), 155 "m5a.12xlarge": specs(2.5, 48, "2.5 GHz AMD EPYC 7000 series"), 156 "m5a.16xlarge": specs(2.5, 64, "2.5 GHz AMD EPYC 7000 series"), 157 "m5a.24xlarge": specs(2.5, 96, "2.5 GHz AMD EPYC 7000 series"), 158 "m5ad.large": specs(2.5, 2, "2.5 GHz AMD EPYC 7000 series"), 159 "m5ad.xlarge": specs(2.5, 4, "2.5 GHz AMD EPYC 7000 series"), 160 "m5ad.2xlarge": specs(2.5, 8, "2.5 GHz AMD EPYC 7000 series"), 161 "m5ad.4xlarge": specs(2.5, 16, "2.5 GHz AMD EPYC 7000 series"), 162 "m5ad.12xlarge": specs(2.5, 48, "2.5 GHz AMD EPYC 7000 series"), 163 "m5ad.24xlarge": specs(2.5, 96, "2.5 GHz AMD EPYC 7000 series"), 164 165 // m5n, m5dn 166 "m5n.large": specs(3.1, 2, "3.1 GHz Intel Xeon Scalable"), 167 "m5n.xlarge": specs(3.1, 4, "3.1 GHz Intel Xeon Scalable"), 168 "m5n.2xlarge": specs(3.1, 8, "3.1 GHz Intel Xeon Scalable"), 169 "m5n.4xlarge": specs(3.1, 16, "3.1 GHz Intel Xeon Scalable"), 170 "m5n.8xlarge": specs(3.1, 32, "3.1 GHz Intel Xeon Scalable"), 171 "m5n.12xlarge": specs(3.1, 48, "3.1 GHz Intel Xeon Scalable"), 172 "m5n.16xlarge": specs(3.1, 64, "3.1 GHz Intel Xeon Scalable"), 173 "m5n.24xlarge": specs(3.1, 96, "3.1 GHz Intel Xeon Scalable"), 174 "m5dn.large": specs(3.1, 2, "3.1 GHz Intel Xeon Scalable"), 175 "m5dn.xlarge": specs(3.1, 4, "3.1 GHz Intel Xeon Scalable"), 176 "m5dn.2xlarge": specs(3.1, 8, "3.1 GHz Intel Xeon Scalable"), 177 "m5dn.4xlarge": specs(3.1, 16, "3.1 GHz Intel Xeon Scalable"), 178 "m5dn.8xlarge": specs(3.1, 32, "3.1 GHz Intel Xeon Scalable"), 179 "m5dn.12xlarge": specs(3.1, 48, "3.1 GHz Intel Xeon Scalable"), 180 "m5dn.16xlarge": specs(3.1, 64, "3.1 GHz Intel Xeon Scalable"), 181 "m5dn.24xlarge": specs(3.1, 96, "3.1 GHz Intel Xeon Scalable"), 182 183 // m4 184 "m4.large": specs(2.3, 2, "2.3 GHz Intel Xeon® E5-2686 v4"), 185 "m4.xlarge": specs(2.3, 4, "2.3 GHz Intel Xeon® E5-2686 v4"), 186 "m4.2xlarge": specs(2.3, 8, "2.3 GHz Intel Xeon® E5-2686 v4"), 187 "m4.4xlarge": specs(2.3, 16, "2.3 GHz Intel Xeon® E5-2686 v4"), 188 "m4.10xlarge": specs(2.3, 40, "2.3 GHz Intel Xeon® E5-2686 v4"), 189 "m4.16xlarge": specs(2.3, 64, "2.3 GHz Intel Xeon® E5-2686 v4"), 190 191 // -- Compute Optimized -- 192 193 // c5, c5d 194 "c5.large": specs(3.4, 2, "3.4 GHz Intel Xeon Platinum 8000"), 195 "c5.xlarge": specs(3.4, 4, "3.4 GHz Intel Xeon Platinum 8000"), 196 "c5.2xlarge": specs(3.4, 8, "3.4 GHz Intel Xeon Platinum 8000"), 197 "c5.4xlarge": specs(3.4, 16, "3.4 GHz Intel Xeon Platinum 8000"), 198 "c5.9xlarge": specs(3.4, 36, "3.4 GHz Intel Xeon Platinum 8000"), 199 "c5.12xlarge": specs(3.6, 48, "3.6 GHz Intel Xeon Scalable"), 200 "c5.18xlarge": specs(3.6, 72, "3.6 GHz Intel Xeon Scalable"), 201 "c5.24xlarge": specs(3.6, 96, "3.6 GHz Intel Xeon Scalable"), 202 "c5.metal": specs(3.6, 96, "3.6 GHz Intel Xeon Scalable"), 203 "c5d.large": specs(3.4, 2, "3.4 GHz Intel Xeon Platinum 8000"), 204 "c5d.xlarge": specs(3.4, 4, "3.4 GHz Intel Xeon Platinum 8000"), 205 "c5d.2xlarge": specs(3.4, 8, "3.4 GHz Intel Xeon Platinum 8000"), 206 "c5d.4xlarge": specs(3.4, 16, "3.4 GHz Intel Xeon Platinum 8000"), 207 "c5d.9xlarge": specs(3.4, 36, "3.4 GHz Intel Xeon Platinum 8000"), 208 "c5d.12xlarge": specs(3.6, 48, "3.6 GHz Intel Xeon Scalable"), 209 "c5d.18xlarge": specs(3.6, 72, "3.6 GHz Intel Xeon Scalable"), 210 "c5d.24xlarge": specs(3.6, 96, "3.6 GHz Intel Xeon Scalable"), 211 "c5d.metal": specs(3.6, 96, "3.6 GHz Intel Xeon Scalable"), 212 213 // c5n 214 "c5n.large": specs(3.0, 2, "3.0 GHz Intel Xeon Platinum"), 215 "c5n.xlarge": specs(3.0, 4, "3.0 GHz Intel Xeon Platinum"), 216 "c5n.2xlarge": specs(3.0, 8, "3.0 GHz Intel Xeon Platinum"), 217 "c5n.4xlarge": specs(3.0, 16, "3.0 GHz Intel Xeon Platinum"), 218 "c5n.9xlarge": specs(3.0, 36, "3.0 GHz Intel Xeon Platinum"), 219 "c5n.18xlarge": specs(3.0, 72, "3.0 GHz Intel Xeon Platinum"), 220 "c5n.metal": specs(3.0, 72, "3.0 GHz Intel Xeon Platinum"), 221 222 // c4 223 "c4.large": specs(2.9, 2, "2.9 GHz Intel Xeon E5-2666 v3"), 224 "c4.xlarge": specs(2.9, 4, "2.9 GHz Intel Xeon E5-2666 v3"), 225 "c4.2xlarge": specs(2.9, 8, "2.9 GHz Intel Xeon E5-2666 v3"), 226 "c4.4xlarge": specs(2.9, 16, "2.9 GHz Intel Xeon E5-2666 v3"), 227 "c4.8xlarge": specs(2.9, 36, "2.9 GHz Intel Xeon E5-2666 v3"), 228 229 // -- Memory Optimized -- 230 231 // r5, r5d 232 "r5.large": specs(3.1, 2, "3.1 GHz Intel Xeon Platinum 8175"), 233 "r5.xlarge": specs(3.1, 4, "3.1 GHz Intel Xeon Platinum 8175"), 234 "r5.2xlarge": specs(3.1, 8, "3.1 GHz Intel Xeon Platinum 8175"), 235 "r5.4xlarge": specs(3.1, 16, "3.1 GHz Intel Xeon Platinum 8175"), 236 "r5.8xlarge": specs(3.1, 32, "3.1 GHz Intel Xeon Platinum 8175"), 237 "r5.12xlarge": specs(3.1, 48, "3.1 GHz Intel Xeon Platinum 8175"), 238 "r5.16xlarge": specs(3.1, 64, "3.1 GHz Intel Xeon Platinum 8175"), 239 "r5.24xlarge": specs(3.1, 96, "3.1 GHz Intel Xeon Platinum 8175"), 240 "r5.metal": specs(3.1, 96, "3.1 GHz Intel Xeon Platinum 8175"), 241 "r5d.large": specs(3.1, 2, "3.1 GHz Intel Xeon Platinum 8175"), 242 "r5d.xlarge": specs(3.1, 4, "3.1 GHz Intel Xeon Platinum 8175"), 243 "r5d.2xlarge": specs(3.1, 8, "3.1 GHz Intel Xeon Platinum 8175"), 244 "r5d.4xlarge": specs(3.1, 16, "3.1 GHz Intel Xeon Platinum 8175"), 245 "r5d.8xlarge": specs(3.1, 32, "3.1 GHz Intel Xeon Platinum 8175"), 246 "r5d.12xlarge": specs(3.1, 48, "3.1 GHz Intel Xeon Platinum 8175"), 247 "r5d.16xlarge": specs(3.1, 64, "3.1 GHz Intel Xeon Platinum 8175"), 248 "r5d.24xlarge": specs(3.1, 96, "3.1 GHz Intel Xeon Platinum 8175"), 249 "r5d.metal": specs(3.1, 96, "3.1 GHz Intel Xeon Platinum 8175"), 250 251 // r5a, r5ad 252 "r5a.large": specs(2.5, 2, "2.5 GHz AMD EPYC 7000 series"), 253 "r5a.xlarge": specs(2.5, 4, "2.5 GHz AMD EPYC 7000 series"), 254 "r5a.2xlarge": specs(2.5, 8, "2.5 GHz AMD EPYC 7000 series"), 255 "r5a.4xlarge": specs(2.5, 16, "2.5 GHz AMD EPYC 7000 series"), 256 "r5a.8xlarge": specs(2.5, 32, "2.5 GHz AMD EPYC 7000 series"), 257 "r5a.12xlarge": specs(2.5, 48, "2.5 GHz AMD EPYC 7000 series"), 258 "r5a.16xlarge": specs(2.5, 64, "2.5 GHz AMD EPYC 7000 series"), 259 "r5a.24xlarge": specs(2.5, 96, "2.5 GHz AMD EPYC 7000 series"), 260 "r5ad.large": specs(2.5, 2, "2.5 GHz AMD EPYC 7000 series"), 261 "r5ad.xlarge": specs(2.5, 4, "2.5 GHz AMD EPYC 7000 series"), 262 "r5ad.2xlarge": specs(2.5, 8, "2.5 GHz AMD EPYC 7000 series"), 263 "r5ad.4xlarge": specs(2.5, 16, "2.5 GHz AMD EPYC 7000 series"), 264 "r5ad.8xlarge": specs(2.5, 32, "2.5 GHz AMD EPYC 7000 series"), 265 "r5ad.12xlarge": specs(2.5, 48, "2.5 GHz AMD EPYC 7000 series"), 266 "r5ad.16xlarge": specs(2.5, 64, "2.5 GHz AMD EPYC 7000 series"), 267 "r5ad.24xlarge": specs(2.5, 96, "2.5 GHz AMD EPYC 7000 series"), 268 269 // r5n 270 "r5n.large": specs(3.1, 2, "3.1 GHz Intel Xeon Scalable"), 271 "r5n.xlarge": specs(3.1, 4, "3.1 GHz Intel Xeon Scalable"), 272 "r5n.2xlarge": specs(3.1, 8, "3.1 GHz Intel Xeon Scalable"), 273 "r5n.4xlarge": specs(3.1, 16, "3.1 GHz Intel Xeon Scalable"), 274 "r5n.8xlarge": specs(3.1, 32, "3.1 GHz Intel Xeon Scalable"), 275 "r5n.12xlarge": specs(3.1, 48, "3.1 GHz Intel Xeon Scalable"), 276 "r5n.16xlarge": specs(3.1, 64, "3.1 GHz Intel Xeon Scalable"), 277 "r5n.24xlarge": specs(3.1, 96, "3.1 GHz Intel Xeon Scalable"), 278 "r5dn.large": specs(3.1, 2, "3.1 GHz Intel Xeon Scalable"), 279 "r5dn.xlarge": specs(3.1, 4, "3.1 GHz Intel Xeon Scalable"), 280 "r5dn.2xlarge": specs(3.1, 8, "3.1 GHz Intel Xeon Scalable"), 281 "r5dn.4xlarge": specs(3.1, 16, "3.1 GHz Intel Xeon Scalable"), 282 "r5dn.8xlarge": specs(3.1, 32, "3.1 GHz Intel Xeon Scalable"), 283 "r5dn.12xlarge": specs(3.1, 48, "3.1 GHz Intel Xeon Scalable"), 284 "r5dn.16xlarge": specs(3.1, 64, "3.1 GHz Intel Xeon Scalable"), 285 "r5dn.24xlarge": specs(3.1, 96, "3.1 GHz Intel Xeon Scalable"), 286 287 // r4 288 "r4.large": specs(2.3, 2, "2.3 GHz Intel Xeon E5-2686 v4"), 289 "r4.xlarge": specs(2.3, 4, "2.3 GHz Intel Xeon E5-2686 v4"), 290 "r4.2xlarge": specs(2.3, 8, "2.3 GHz Intel Xeon E5-2686 v4"), 291 "r4.4xlarge": specs(2.3, 16, "2.3 GHz Intel Xeon E5-2686 v4"), 292 "r4.8xlarge": specs(2.3, 32, "2.3 GHz Intel Xeon E5-2686 v4"), 293 "r4.16xlarge": specs(2.3, 64, "2.3 GHz Intel Xeon E5-2686 v4"), 294 295 // x1e 296 "x1e.xlarge": specs(2.3, 4, "2.3 GHz Intel Xeon E7-8880 v3"), 297 "x1e.2xlarge": specs(2.3, 8, "2.3 GHz Intel Xeon E7-8880 v3"), 298 "x1e.4xlarge": specs(2.3, 16, "2.3 GHz Intel Xeon E7-8880 v3"), 299 "x1e.8xlarge": specs(2.3, 32, "2.3 GHz Intel Xeon E7-8880 v3"), 300 "x1e.16xlarge": specs(2.3, 64, "2.3 GHz Intel Xeon E7-8880 v3"), 301 "x1e.32xlarge": specs(2.3, 128, "2.3 GHz Intel Xeon E7-8880 v3"), 302 303 // x1 304 "x1.16xlarge": specs(2.3, 64, "2.3 GHz Intel Xeon E7-8880 v3"), 305 "x1.32xlarge": specs(2.3, 64, "2.3 GHz Intel Xeon E7-8880 v3"), 306 307 // high-memory 308 "u-6tb1.metal": specs(2.1, 448, "2.1 GHz Intel Xeon Platinum 8176M"), 309 "u-9tb1.metal": specs(2.1, 448, "2.1 GHz Intel Xeon Platinum 8176M"), 310 "u-12tb1.metal": specs(2.1, 448, "2.1 GHz Intel Xeon Platinum 8176M"), 311 "u-18tb1.metal": specs(2.7, 448, "2.7 GHz Intel Xeon Scalable"), 312 "u-24tb1.metal": specs(2.7, 448, "2.7 GHz Intel Xeon Scalable"), 313 314 // z1d 315 "z1d.large": specs(4.0, 2, "4.0 GHz Intel Xeon Scalable"), 316 "z1d.xlarge": specs(4.0, 4, "4.0 GHz Intel Xeon Scalable"), 317 "z1d.2xlarge": specs(4.0, 8, "4.0 GHz Intel Xeon Scalable"), 318 "z1d.3xlarge": specs(4.0, 12, "4.0 GHz Intel Xeon Scalable"), 319 "z1d.6xlarge": specs(4.0, 24, "4.0 GHz Intel Xeon Scalable"), 320 "z1d.12xlarge": specs(4.0, 48, "4.0 GHz Intel Xeon Scalable"), 321 "z1d.metal": specs(4.0, 48, "4.0 GHz Intel Xeon Scalable"), 322 323 // -- Accelerated Computing -- 324 325 // p3, p3dn 326 "p3.2xlarge": specs(2.3, 8, "2.3 GHz Intel Xeon E5-2686 v4"), 327 "p3.8xlarge": specs(2.3, 32, "2.3 GHz Intel Xeon E5-2686 v4"), 328 "p3.16xlarge": specs(2.3, 64, "2.3 GHz Intel Xeon E5-2686 v4"), 329 "p3dn.24xlarge": specs(2.5, 96, "2.5 GHz Intel Xeon P-8175M"), 330 331 // p2 332 "p2.xlarge": specs(2.3, 4, "2.3 GHz Intel Xeon E5-2686 v4"), 333 "p2.8xlarge": specs(2.3, 32, "2.3 GHz Intel Xeon E5-2686 v4"), 334 "p2.16xlarge": specs(2.3, 64, "2.3 GHz Intel Xeon E5-2686 v4"), 335 336 // inf1 337 "inf1.xlarge": specs(3.0, 4, "3.0 GHz Intel Xeon Platinum 8275CL"), 338 "inf1.2xlarge": specs(3.0, 8, "3.0 GHz Intel Xeon Platinum 8275CL"), 339 "inf1.6xlarge": specs(3.0, 24, "3.0 GHz Intel Xeon Platinum 8275CL"), 340 "inf1.24xlarge": specs(3.0, 96, "3.0 GHz Intel Xeon Platinum 8275CL"), 341 342 // g4dn 343 "g4dn.xlarge": specs(2.5, 4, "2.5 GHz Cascade Lake 24C"), 344 "g4dn.2xlarge": specs(2.5, 8, "2.5 GHz Cascade Lake 24C"), 345 "g4dn.4xlarge": specs(2.5, 16, "2.5 GHz Cascade Lake 24C"), 346 "g4dn.8xlarge": specs(2.5, 32, "2.5 GHz Cascade Lake 24C"), 347 "g4dn.16xlarge": specs(2.5, 64, "2.5 GHz Cascade Lake 24C"), 348 "g4dn.12xlarge": specs(2.5, 48, "2.5 GHz Cascade Lake 24C"), 349 "g4dn.metal": specs(2.5, 96, "2.5 GHz Cascade Lake 24C"), 350 351 // g3 352 "g3s.xlarge": specs(2.3, 4, "2.3 GHz Intel Xeon E5-2686 v4"), 353 "g3s.4xlarge": specs(2.3, 16, "2.3 GHz Intel Xeon E5-2686 v4"), 354 "g3s.8xlarge": specs(2.3, 32, "2.3 GHz Intel Xeon E5-2686 v4"), 355 "g3s.16xlarge": specs(2.3, 64, "2.3 GHz Intel Xeon E5-2686 v4"), 356 357 // f1 358 "f1.2xlarge": specs(2.3, 8, "Intel Xeon E5-2686 v4"), 359 "f1.4xlarge": specs(2.3, 16, "Intel Xeon E5-2686 v4"), 360 "f1.16xlarge": specs(2.3, 64, "Intel Xeon E5-2686 v4"), 361 362 // -- Storage Optimized -- 363 364 // i3 365 "i3.large": specs(2.3, 2, "2.3 GHz Intel Xeon E5 2686 v4"), 366 "i3.xlarge": specs(2.3, 4, "2.3 GHz Intel Xeon E5 2686 v4"), 367 "i3.2xlarge": specs(2.3, 8, "2.3 GHz Intel Xeon E5 2686 v4"), 368 "i3.4xlarge": specs(2.3, 16, "2.3 GHz Intel Xeon E5 2686 v4"), 369 "i3.8xlarge": specs(2.3, 32, "2.3 GHz Intel Xeon E5 2686 v4"), 370 "i3.16xlarge": specs(2.3, 64, "2.3 GHz Intel Xeon E5 2686 v4"), 371 "i3.metal": specs(2.3, 72, "2.3 GHz Intel Xeon E5 2686 v4"), 372 373 // i3en 374 "i3en.large": specs(3.1, 2, "3.1 GHz Intel Xeon Scalable"), 375 "i3en.xlarge": specs(3.1, 4, "3.1 GHz Intel Xeon Scalable"), 376 "i3en.2xlarge": specs(3.1, 8, "3.1 GHz Intel Xeon Scalable"), 377 "i3en.3xlarge": specs(3.1, 12, "3.1 GHz Intel Xeon Scalable"), 378 "i3en.6xlarge": specs(3.1, 24, "3.1 GHz Intel Xeon Scalable"), 379 "i3en.12xlarge": specs(3.1, 48, "3.1 GHz Intel Xeon Scalable"), 380 "i3en.24xlarge": specs(3.1, 96, "3.1 GHz Intel Xeon Scalable"), 381 "i3en.metal": specs(3.1, 96, "3.1 GHz Intel Xeon Scalable"), 382 383 // d2 384 "d2.xlarge": specs(2.4, 4, "2.4 GHz Intel Xeon E5-2676 v3"), 385 "d2.2xlarge": specs(2.4, 8, "2.4 GHz Intel Xeon E5-2676 v3"), 386 "d2.4xlarge": specs(2.4, 16, "2.4 GHz Intel Xeon E5-2676 v3"), 387 "d2.8xlarge": specs(2.4, 36, "2.4 GHz Intel Xeon E5-2676 v3"), 388 389 // h1 390 "h1.2xlarge": specs(2.3, 8, "2.3 GHz Intel Xeon E5 2686 v4"), 391 "h1.4xlarge": specs(2.3, 16, "2.3 GHz Intel Xeon E5 2686 v4"), 392 "h1.8xlarge": specs(2.3, 32, "2.3 GHz Intel Xeon E5 2686 v4"), 393 "h1.16xlarge": specs(2.3, 64, "2.3 GHz Intel Xeon E5 2686 v4"), 394 } 395 396 // EnvAWSFingerprint is used to fingerprint AWS metadata 397 type EnvAWSFingerprint struct { 398 StaticFingerprinter 399 400 // endpoint for EC2 metadata as expected by AWS SDK 401 endpoint string 402 403 logger log.Logger 404 } 405 406 // NewEnvAWSFingerprint is used to create a fingerprint from AWS metadata 407 func NewEnvAWSFingerprint(logger log.Logger) Fingerprint { 408 f := &EnvAWSFingerprint{ 409 logger: logger.Named("env_aws"), 410 endpoint: strings.TrimSuffix(os.Getenv("AWS_ENV_URL"), "/meta-data/"), 411 } 412 return f 413 } 414 415 func (f *EnvAWSFingerprint) Fingerprint(request *FingerprintRequest, response *FingerprintResponse) error { 416 cfg := request.Config 417 418 timeout := AwsMetadataTimeout 419 420 // Check if we should tighten the timeout 421 if cfg.ReadBoolDefault(TightenNetworkTimeoutsConfig, false) { 422 timeout = 1 * time.Millisecond 423 } 424 425 ec2meta, err := ec2MetaClient(f.endpoint, timeout) 426 if err != nil { 427 return fmt.Errorf("failed to setup ec2Metadata client: %v", err) 428 } 429 430 if !isAWS(ec2meta) { 431 return nil 432 } 433 434 // Keys and whether they should be namespaced as unique. Any key whose value 435 // uniquely identifies a node, such as ip, should be marked as unique. When 436 // marked as unique, the key isn't included in the computed node class. 437 keys := map[string]bool{ 438 "ami-id": false, 439 "hostname": true, 440 "instance-id": true, 441 "instance-type": false, 442 "local-hostname": true, 443 "local-ipv4": true, 444 "public-hostname": true, 445 "public-ipv4": true, 446 "placement/availability-zone": false, 447 } 448 449 for k, unique := range keys { 450 resp, err := ec2meta.GetMetadata(k) 451 v := strings.TrimSpace(resp) 452 if v == "" { 453 f.logger.Debug("read an empty value", "attribute", k) 454 continue 455 } else if awsErr, ok := err.(awserr.RequestFailure); ok { 456 f.logger.Debug("could not read attribute value", "attribute", k, "error", awsErr) 457 continue 458 } else if awsErr, ok := err.(awserr.Error); ok { 459 // if it's a URL error, assume we're not in an AWS environment 460 // TODO: better way to detect AWS? Check xen virtualization? 461 if _, ok := awsErr.OrigErr().(*url.Error); ok { 462 return nil 463 } 464 465 // not sure what other errors it would return 466 return err 467 } 468 469 // assume we want blank entries 470 key := "platform.aws." + strings.Replace(k, "/", ".", -1) 471 if unique { 472 key = structs.UniqueNamespace(key) 473 } 474 475 response.AddAttribute(key, v) 476 } 477 478 // accumulate resource information, then assign to response 479 var resources *structs.Resources 480 var nodeResources *structs.NodeResources 481 482 // copy over network specific information 483 if val, ok := response.Attributes["unique.platform.aws.local-ipv4"]; ok && val != "" { 484 response.AddAttribute("unique.network.ip-address", val) 485 nodeResources = new(structs.NodeResources) 486 nodeResources.Networks = []*structs.NetworkResource{ 487 { 488 Device: "eth0", 489 IP: val, 490 CIDR: val + "/32", 491 MBits: f.throughput(request, ec2meta, val), 492 }, 493 } 494 } 495 496 // copy over CPU speed information 497 if specs := f.lookupCPU(ec2meta); specs != nil { 498 response.AddAttribute("cpu.modelname", specs.model) 499 response.AddAttribute("cpu.frequency", fmt.Sprintf("%.0f", specs.mhz)) 500 response.AddAttribute("cpu.numcores", fmt.Sprintf("%d", specs.cores)) 501 f.logger.Debug("lookup ec2 cpu", "cores", specs.cores, "MHz", log.Fmt("%.0f", specs.mhz), "model", specs.model) 502 503 if ticks := specs.ticks(); request.Config.CpuCompute <= 0 { 504 response.AddAttribute("cpu.totalcompute", fmt.Sprintf("%d", ticks)) 505 f.logger.Debug("setting ec2 cpu ticks", "ticks", ticks) 506 resources = new(structs.Resources) 507 resources.CPU = ticks 508 if nodeResources == nil { 509 nodeResources = new(structs.NodeResources) 510 } 511 nodeResources.Cpu = structs.NodeCpuResources{CpuShares: int64(ticks)} 512 } 513 } else { 514 f.logger.Warn("failed to find the cpu specification for this instance type") 515 } 516 517 response.Resources = resources 518 response.NodeResources = nodeResources 519 520 // populate Links 521 response.AddLink("aws.ec2", fmt.Sprintf("%s.%s", 522 response.Attributes["platform.aws.placement.availability-zone"], 523 response.Attributes["unique.platform.aws.instance-id"])) 524 response.Detected = true 525 526 return nil 527 } 528 529 func (f *EnvAWSFingerprint) instanceType(ec2meta *ec2metadata.EC2Metadata) (string, error) { 530 response, err := ec2meta.GetMetadata("instance-type") 531 if err != nil { 532 return "", err 533 } 534 return strings.TrimSpace(response), nil 535 } 536 537 func (f *EnvAWSFingerprint) lookupCPU(ec2meta *ec2metadata.EC2Metadata) *ec2Specs { 538 instanceType, err := f.instanceType(ec2meta) 539 if err != nil { 540 f.logger.Warn("failed to read EC2 metadata instance-type", "error", err) 541 return nil 542 } 543 for iType, specs := range ec2ProcSpeedTable { 544 if strings.EqualFold(iType, instanceType) { 545 return &specs 546 } 547 } 548 return nil 549 } 550 551 func (f *EnvAWSFingerprint) throughput(request *FingerprintRequest, ec2meta *ec2metadata.EC2Metadata, ip string) int { 552 throughput := request.Config.NetworkSpeed 553 if throughput != 0 { 554 return throughput 555 } 556 557 throughput = f.linkSpeed(ec2meta) 558 if throughput != 0 { 559 return throughput 560 } 561 562 if request.Node.Resources != nil && len(request.Node.Resources.Networks) > 0 { 563 for _, n := range request.Node.Resources.Networks { 564 if n.IP == ip { 565 return n.MBits 566 } 567 } 568 } 569 570 return defaultNetworkSpeed 571 } 572 573 // EnvAWSFingerprint uses lookup table to approximate network speeds 574 func (f *EnvAWSFingerprint) linkSpeed(ec2meta *ec2metadata.EC2Metadata) int { 575 instanceType, err := f.instanceType(ec2meta) 576 if err != nil { 577 f.logger.Error("error reading instance-type", "error", err) 578 return 0 579 } 580 581 netSpeed := 0 582 for reg, speed := range ec2NetSpeedTable { 583 if reg.MatchString(instanceType) { 584 netSpeed = speed 585 break 586 } 587 } 588 589 return netSpeed 590 } 591 592 func ec2MetaClient(endpoint string, timeout time.Duration) (*ec2metadata.EC2Metadata, error) { 593 client := &http.Client{ 594 Timeout: timeout, 595 Transport: cleanhttp.DefaultTransport(), 596 } 597 598 c := aws.NewConfig().WithHTTPClient(client).WithMaxRetries(0) 599 if endpoint != "" { 600 c = c.WithEndpoint(endpoint) 601 } 602 603 sess, err := session.NewSession(c) 604 if err != nil { 605 return nil, err 606 } 607 return ec2metadata.New(sess, c), nil 608 } 609 610 func isAWS(ec2meta *ec2metadata.EC2Metadata) bool { 611 v, err := ec2meta.GetMetadata("ami-id") 612 v = strings.TrimSpace(v) 613 return err == nil && v != "" 614 }