2015-10-14 19 views
5

typy przykład: (t2.micro, t2.small, c4.large ...) wymienione tutaj: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.htmlboto3 AWS api - listingu dostępne typy instancji

Chcę otworzyć listę tych przez boto3 . coś takiego:

conn.get_all_instance_types() 

lub nawet

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

którym wszystko wydaje się wyglądać w tym dziwnym API.

Przeglądałem dokumenty dla klienta i usługi ServiceResource, ale nie mogę znaleźć niczego, co wydaje się bliskie. Nie znalazłem nawet hacky, które zawiera listę innych elementów reprezentujących wszystkie typy instancji.

Ktoś z większym doświadczeniem boto3?

Odpowiedz

5

Interfejs API EC2 nie zapewnia sposobu na uzyskanie listy wszystkich typów instancji EC2. Chciałbym, żeby tak było. Niektóre osoby skleiły ze sobą własne listy poprawnych typów poprzez skrobanie witryn takich jak this, ale na razie to jedyny sposób.

+0

Bałem się tego. Zrobiłem już własną listę w pliku json, ponieważ zrezygnowałem z wyszukiwania czegokolwiek po 2-3 godzinach szukania. – Oliver

+1

Od grudnia 2015 r. Istnieje sposób na uzyskanie tych informacji z interfejsu API cen AWS. Zobacz moją odpowiedź poniżej: https://stackoverflow.com/a/47610618/211734 –

1

Spróbuj

''' 
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

muszę go też jednak nie istnieją odpowiednie kody dla tego celu. Modyfikuję je sam. Cieszyć się! Niech ktoś też tego potrzebuje.

następujący kod jest modyfikowany libcloud/contrib/scrape-ec2-prices.py A ten program wygeneruje dict temat dostępnych typów instancji

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

To tak naprawdę nie odpowiada na pytanie. Jeśli masz inne pytanie, możesz je zadać, klikając [Zadaj pytanie] (http://stackoverflow.com/questions/ask). Możesz także [dodać nagrodę] (http://stackoverflow.com/help/privileges/set-bounties), aby zwrócić więcej uwagi na to pytanie, gdy już masz wystarczającą [reputację] (http://stackoverflow.com/help/ whats-reputation). - [Z recenzji] (/ review/low-quality-posts/16125989) – hivert

+0

Zanim skomentujesz tę odpowiedź, musisz uruchomić ten kod i zobaczyć. Myślę, że to najlepsza odpowiedź na to pytanie. –

+0

W AWS różne dostępne strefy mają różne dostępne typy instancji. Ten kod jest modyfikowany z kodu skradzenia cen. jednak ten kod może wykorzystywać informacje o cenie (np. n/a) do odfiltrowywania niedostępnych typów instancji w dostępnej strefie. na przykład. Instancja f1.2xlarge może pojawić się tylko w us-east-1 (a ~ e) i nie pojawi się w eu-west-1. Jeśli chcesz wyświetlić dostępne typy instancji w eu-west-1a, f1.2xlarge nie powinien pojawić się na liście wyników.Myślę, że ten kod jest jedynym kodem, który poradzi sobie z tym problemem. –

1

Informacje te mogą być pobierane w formacie JSON dostarczonych przez niedawno ogłoszono AWS Price List API. Jako prosty przykład za pomocą modułu 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) 

Należy pamiętać, że może to trochę potrwać ... na dzień dzisiejszy, obecny EC2 Propozycje plik JSON (https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonEC2/current/index.json) jest 173MB, więc to zajmuje trochę czasu, zarówno do odzyskać i parsować. Bieżący wynik to 99 różnych typów instancji.

Powiązane problemy