2015-10-14 87 views
5

實例類型:(t2.micro,t2.small,c4.large ...)這裏列出: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.htmlboto3 AWS API - 列出可用實例類型

我想通過boto3訪問這些列表。 類似:

conn.get_all_instance_types() 

甚至

conn.describe_instance_types()['InstanceTypes'][0]['Name'] 

這一切似乎看起來像這種怪異的API。

我已經瀏覽了客戶端和ServiceResource的文檔,但我找不到任何似乎接近的內容。 我甚至還沒有找到一個hacky的解決方案,其中列出了其他可能代表所有實例類型的解決方案。

任何人都有更多的boto3經驗?

回答

5

EC2 API不提供獲取所有EC2實例類型列表的方法。我希望它。有些人通過拼湊像this這樣的網站拼湊出自己的有效類型列表,但現在這是唯一的方法。

+0

我很害怕這個。我已經把我自己的列表拼湊在json文件中,因爲我在放映2-3小時後放棄尋找任何東西。 – Oliver

+1

截至2015年12月,有一種方法可從AWS定價API獲取此信息。看到我的答案如下:https://stackoverflow.com/a/47610618/211734 –

1

試試這個

''' 
Created on Mar 22, 2017 

@author: ijessop 
''' 

import boto3 
import urllib2 
from bs4 import BeautifulSoup as soup 

class EnumEc2(): 

    def __init__(self, region): 

     self.client = boto3.client(
            'ec2', 
            aws_access_key_id = 'YOUR_KEY' , 
            aws_secret_access_key='YOUR_SECRET', 
            region_name = region 
            ) 
     self.instance_types = None 
     self.instance_table_headers = None 
     self.max_col_width = {} 


    def getInstanceTypes(self): 
     mp = soup(urllib2.urlopen('https://aws.amazon.com/ec2/instance-types').read(),'html.parser') 
     imx = mp.find(id="instance-type-matrix") 
     trs = imx.parent.parent.parent.next_sibling.next_sibling.find_all('tr') 

     rt = [] 
     first_row = True 
     for trow in trs: 
      td_strs = [] 

      for td in trow.find_all("td"): 
       td_nested = [] 
       for s in td.strings: 
        s.strip() 
        td_nested.append(s) 

       td_all = " ".join(td_nested).strip() 
       td_strs.append(td_all) 

      if first_row is True: 
       header_row = td_strs 
       for head in header_row: 
        self.max_col_width.update({head:(len(head) + 2)}) 
       first_row = False 

      else: 
       dr = dict(zip(header_row,td_strs)) 
       for k,v in dr.items(): 
        cw = len(v) 
        if k in self.max_col_width.keys(): 
         if cw >= self.max_col_width.get(k): 
          self.max_col_width.update({k:(cw +2)}) 

        else: 
         self.max_col_width.update({k:cw}) 

       rt.append(dr) 

     self.instance_table_headers = header_row 
     self.instance_types = rt 



if __name__ == '__main__': 

    myen = EnumEc2('us-west-2') 
    myen.getInstanceTypes() 
    heads_I_want_to_see = ['Instance Type', u'vCPU', u'Memory (GiB)', u'Storage (GB)','Physical Processor', u'Clock Speed (GHz)'] 
    out_str ="|" 
    for h in heads_I_want_to_see: 
     out_str = "%s%s|" % (out_str,h.ljust(myen.max_col_width.get(h))) 
    print "%s" % "-" * len(out_str) 
    print "%s" % out_str 
    print "%s" % "-" * len(out_str) 
    for i in myen.instance_types: 
     out_str ="|" 
     for k in myen.instance_table_headers: # to preserve the table column order 
      if k in heads_I_want_to_see: 
       out_str = "%s%s|" % (out_str, i.get(k).ljust(myen.max_col_width.get(k))) 
     print "%s" % out_str 
     print "%s" % "-" * len(out_str) 
0

我需要它太,但是,也有爲了這個目的沒有合適的代碼。我自己修改一個。請享用!可能有人也需要它。

下面的代碼是從libcloud /了contrib/scrape-ec2-prices.py 改性而這個程序將生成一個關於由提供的可用實例類型

#!/usr/bin/env python 

import os 
import re 
import json 
import time 
from collections import defaultdict, OrderedDict 

import requests 
import demjson 

LINUX_PRICING_URLS = [ 
    # Deprecated instances (JSON format) 
    'https://aws.amazon.com/ec2/pricing/json/linux-od.json', 
    # Previous generation instances (JavaScript file) 
    'https://a0.awsstatic.com/pricing/1/ec2/previous-generation/linux-od.min.js', 
    # New generation instances (JavaScript file) 
    'https://a0.awsstatic.com/pricing/1/ec2/linux-od.min.js' 
] 

EC2_REGIONS = [ 
    'us-east-1', 
    'us-east-2', 
    'us-west-1', 
    'us-west-2', 
    'us-gov-west-1', 
    'eu-west-1', 
    'eu-west-2', 
    'eu-central-1', 
    'ca-central-1', 
    'ap-southeast-1', 
    'ap-southeast-2', 
    'ap-northeast-1', 
    'ap-northeast-2', 
    'ap-south-1', 
    'sa-east-1', 
    'cn-north-1', 
] 

INSTANCE_SIZES = [ 
    'micro', 
    'small', 
    'medium', 
    'large', 
    'xlarge', 
    'x-large', 
    'extra-large' 
] 

RE_NUMERIC_OTHER = re.compile(r'(?:([0-9]+)|([-A-Z_a-z]+)|([^-0-9A-Z_a-z]+))') 

PRICING_FILE_PATH = './price.json' 
PRICING_FILE_PATH = os.path.abspath(PRICING_FILE_PATH) 


def scrape_ec2_pricing(): 
    result = {} 
    result['regions'] = [] 
    result['prices'] = defaultdict(OrderedDict) 
    result['models'] = defaultdict(OrderedDict) 

    for url in LINUX_PRICING_URLS: 
     response = requests.get(url) 

     if re.match('.*?\.json$', url): 
      data = response.json() 
     elif re.match('.*?\.js$', url): 
      data = response.content 
      match = re.match('^.*callback\((.*?)\);?$', data, 
          re.MULTILINE | re.DOTALL) 
      data = match.group(1) 
      # demjson supports non-strict mode and can parse unquoted objects 
      data = demjson.decode(data) 

     regions = data['config']['regions'] 

     for region_data in regions: 

      region_name = region_data['region'] 

      if region_name not in result['regions']: 
       result['regions'].append(region_name) 

      libcloud_region_name = region_name 
      instance_types = region_data['instanceTypes'] 

      for instance_type in instance_types: 
       sizes = instance_type['sizes'] 
       for size in sizes: 

        price = size['valueColumns'][0]['prices']['USD'] 
        if str(price).lower() == 'n/a': 
         # Price not available 
         continue 

        if not result['models'][libcloud_region_name].has_key(size['size']): 
         result['models'][libcloud_region_name][size['size']] = {} 
         result['models'][libcloud_region_name][size['size']]['CPU'] = int(size['vCPU']) 

         if size['ECU'] == 'variable': 
          ecu = 0 
         else: 
          ecu = float(size['ECU']) 

         result['models'][libcloud_region_name][size['size']]['ECU'] = ecu 

         result['models'][libcloud_region_name][size['size']]['memoryGiB'] = float(size['memoryGiB']) 

         result['models'][libcloud_region_name][size['size']]['storageGB'] = size['storageGB'] 

        result['prices'][libcloud_region_name][size['size']] = float(price) 

    return result 


def update_pricing_file(pricing_file_path, pricing_data): 
    ## with open(pricing_file_path, 'r') as fp: 
    #  content = fp.read() 

    data = {'compute': {}} # json.loads(content) 
    data['updated'] = int(time.time()) 
    data['compute'].update(pricing_data) 

    # Always sort the pricing info 
    data = sort_nested_dict(data) 

    content = json.dumps(data, indent=4) 
    lines = content.splitlines() 
    lines = [line.rstrip() for line in lines] 
    content = '\n'.join(lines) 

    with open(pricing_file_path, 'w') as fp: 
     fp.write(content) 


def sort_nested_dict(value): 
    """ 
    Recursively sort a nested dict. 
    """ 
    result = OrderedDict() 

    for key, value in sorted(value.items(), key=sort_key_by_numeric_other): 
     if isinstance(value, (dict, OrderedDict)): 
      result[key] = sort_nested_dict(value) 
     else: 
      result[key] = value 

    return result 


def sort_key_by_numeric_other(key_value): 
    """ 
    Split key into numeric, alpha and other part and sort accordingly. 
    """ 
    return tuple((
        int(numeric) if numeric else None, 
        INSTANCE_SIZES.index(alpha) if alpha in INSTANCE_SIZES else alpha, 
        other 
       ) for (numeric, alpha, other) in RE_NUMERIC_OTHER.findall(key_value[0])) 


def main(): 
    print('Scraping EC2 pricing data') 

    pricing_data = scrape_ec2_pricing() 
    update_pricing_file(pricing_file_path=PRICING_FILE_PATH, 
         pricing_data=pricing_data) 

    print('Pricing data updated') 


if __name__ == '__main__': 
    main() 
+0

這並沒有真正回答這個問題。如果您有不同的問題,可以通過單擊[提問](http://stackoverflow.com/questions/ask)來提問。您還可以[添加賞金](http://stackoverflow.com/help/privileges/set-bounties)在您擁有足夠的[聲譽](http://stackoverflow.com/help/)時吸引更多人關注此問題什麼聲譽)。 - [來自評論](/ review/low-quality-posts/16125989) – hivert

+0

在評論此答案之前,您必須運行此代碼並查看。我認爲這是這個問題的最佳答案。 –

+0

在AWS中,不同的可用區域具有不同的可用實例類型。此代碼是從價格刮擦代碼修改的。但是,此代碼可以使用價格信息(如n/a)來過濾可用區域中的不可用實例類型。例如。 f1.2xlarge實例只能出現在us-east-1(a〜e)中,並且不會出現在eu-west-1中。如果您想在eu-west-1a中列出可用的實例類型,則f1.2xlarge不應出現在結果列表中。我認爲這個代碼是唯一可以處理這個問題的代碼。 –

1

此信息可以在JSON檢索字典最近宣佈AWS Price List API。作爲使用Python requests模塊一個簡單的例子:

#!/usr/bin/env python 
# List EC2 Instance Types 
# see: https://aws.amazon.com/blogs/aws/new-aws-price-list-api/ 

import requests 

offers = requests.get(
    'https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/index.json' 
) 
ec2_offer_path = offers.json()['offers']['AmazonEC2']['currentVersionUrl'] 
ec2offer = requests.get(
    'https://pricing.us-east-1.amazonaws.com%s' % ec2_offer_path 
).json() 

uniq = set() 
for sku, data in ec2offer['products'].items(): 
    if data['productFamily'] != 'Compute Instance': 
     # skip anything that's not an EC2 Instance 
     continue 
    uniq.add(data['attributes']['instanceType']) 
for itype in sorted(uniq): 
    print(itype) 

注意,這可能需要一段時間......今天,目前的EC2信息JSON文件(https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonEC2/current/index.json)爲173MB,所以需要一段時間來都檢索和解析。當前結果是99個不同的實例類型。