2015-10-14 21 views
5

インスタンスのタイプ:(t2.micro、t2.small、c4.large ...)ここに記載されているもの: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.htmlboto3 AWS API - 使用可能なインスタンスタイプをリスト

私はboto3を通じて、これらのリストにアクセスしたいです。すべては、この奇妙なAPIのように見えるようだ

conn.get_all_instance_types() 

あるいは

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

:よう 何か。

私はクライアントとServiceResourceのドキュメントを調べましたが、近いと思われるものは見つかりませんでした。 私は、すべてのインスタンスタイプを表現する何か他のものをリストアップしたハックな解決策を発見したことさえありません。

boto3の経験が豊富な人は誰ですか?

答えて

5

EC2 APIは、すべてのEC2インスタンスタイプのリストを取得する方法を提供しません。私はそれが欲しかった。いくつかの人々は、thisのようなサイトを掻き集めることによって、有効なタイプのリストを一緒に修復しましたが、今のところこれが唯一の方法です。

+0

私はこれを恐れていました。私は2〜3時間後に何かを見つけることをあきらめたので、私はすでにjsonファイルで自分のリストをまとめました。 – Oliver

+1

2015年12月現在、この情報をAWS Pricing 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 から変更されており、このプログラムは、この情報はによって提供されるJSONで取得することができる

#!/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

これは本当に質問に答えるものではありません。別の質問がある場合は、[Ask Question](http://stackoverflow.com/questions/ask)をクリックして質問することができます。十分な[評判](http://stackoverflow.com/help/)があれば、[賞金を追加](http://stackoverflow.com/help/privileges/set-bounties)でもこの質問にもっと注意を引くことができます。何が評判か)。 - [レビューの投稿](レビュー/低品質の投稿/ 16125989) – hivert

+0

この回答にコメントする前に、このコードを実行して確認する必要があります。私はそれがこの質問の最良の答えだと思う。 –

+0

AWSでは、異なる使用可能なゾーンに異なるインスタンスタイプがあります。このコードは価格スクレープコードから変更されています。ただし、このコードでは、利用可能なゾーンで使用できないインスタンスの種類を除外するために価格情報(n/aなど)を使用できます。例えば。 f1.2xlargeインスタンスはus-east-1(a〜e)にしか現れず、eu-west-1には現れません。 eu-west-1aで利用可能なインスタンスの種類を一覧表示する場合は、f1.2xlargeを結果リストに表示しないでください。私はこのコードがこの問題を処理できる唯一のコードだと思います。 –

1

利用可能なインスタンスタイプについて辞書を生成します最近発表されたAWS Price List API。 Pythonのrequestsモジュール使用して簡単な例として:これは今日のように、現在のEC2は、JSONファイル(https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonEC2/current/index.json)を提供しています...しばらく時間がかかる可能性があることを

#!/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) 

注意することは173メガバイトであるので、両方しばらく時間がかかります検索し、解析する。現在の結果は、99の異なるインスタンス・タイプです。

関連する問題