[PYTHON] Estimate VSI for Bluemix IaaS (formerly SoftLayer) via API

Contents

When estimating a new VSI, issue an estimate via API.

Premise

It is assumed that you understand the following articles. Learn more about the Bluemix Infrastructure (formerly SoftLayer) API.

ShinobiLayer: SoftLayer API Next Step: Data Type Object (1) --Qiita

Get locationId

I made a script to get the locationId, so please use it. (It is also possible to specify using keyname.)

script

getDcLocationId.py


import SoftLayer
import json
from prettytable import PrettyTable

# account info
client = SoftLayer.create_client_from_env()

#objectmask
objectmask = """
	longName,
	name,
	regions[keyname],
	locationAddress[
		locationId,
		address1,
		address2,
		city,
		country,
		postalCode,
		state
	]
"""
dcs = client['Location'].getDatacenters(mask=objectmask)
#dcs_jsonstring = json.dumps(dcs,indent=4)
#print(dcs_jsonstring) 

table = PrettyTable([
	'ID',
	'KeyName',
	'Name',
	'Detail',
	'Country',
	'State',
	'PostalCode',
	'City',
	'Address1',
	'Address2'
])

    
for key in range(len(dcs)):
	if 'locationAddress' in dcs[key]:
		if 'regions' in dcs[key]:
			table.add_row([
				dcs[key]['locationAddress']['locationId'],
				dcs[key]['regions'][0]['keyname'],
				dcs[key]['name'],
				dcs[key]['longName'],
				dcs[key]['locationAddress'].get('country',""),
				dcs[key]['locationAddress'].get('state',""),
				dcs[key]['locationAddress'].get('postalCode',"")[:11],
				dcs[key]['locationAddress'].get('city',""),
				dcs[key]['locationAddress'].get('address1',""),
				dcs[key]['locationAddress'].get('address2',"")
			])
		else:
			table.add_row([
				dcs[key]['locationAddress']['locationId'],
				dcs[key].get('regions',""),
				dcs[key]['name'],
				dcs[key]['longName'],
				dcs[key]['locationAddress'].get('country',""),
				dcs[key]['locationAddress'].get('state',""),
				dcs[key]['locationAddress'].get('postalCode',"")[:11],
				dcs[key]['locationAddress'].get('city',""),
				dcs[key]['locationAddress'].get('address1',""),
				dcs[key]['locationAddress'].get('address2',"")
			])
	else:
		table.add_row([
			dcs[key].get('locationAddress',""),
			dcs[key]['regions'][0]['keyname'],
			dcs[key]['name'],
			dcs[key]['longName'],
			dcs[key].get('locationAddress',""),
			dcs[key].get('locationAddress',""),
			dcs[key].get('locationAddress',""),
			dcs[key].get('locationAddress',""),
			dcs[key].get('locationAddress',""),
			dcs[key].get('locationAddress',"")
		])

print len(dcs)
print table.get_string(sortby="Name")

Example of execution result

#Execution command
python getDcLocationId.py 

#result
32
+---------+---------------+-------+--------------+---------+-------+-------------+----------------+----------------------------------------------------------------------------------+-----------------------+
|    ID   |    KeyName    |  Name |    Detail    | Country | State |  PostalCode |      City      |                                     Address1                                     |        Address2       |
+---------+---------------+-------+--------------+---------+-------+-------------+----------------+----------------------------------------------------------------------------------+-----------------------+
|  265592 |   AMSTERDAM   | ams01 | Amsterdam 1  |    NL   |       |   1096 BK   |   Amsterdam    |                           Paul van Vlissingenstraat 16                           |                       |
|  814994 |  AMSTERDAM03  | ams03 | Amsterdam 3  |    NL   |       |    1329BG   |     Almere     |                                    Flevoland                                     |    Rondebeltweg 62,   |
| 1004997 |    CHENNAI    | che01 |  Chennai 1   |    IN   |       |    600053   |    Chennai     |                               226, Red Hills Road                                | Kallikuppam, Ambattur |
|    3    |     DALLAS    | dal01 |   Dallas 1   |    US   |   TX  |    75207    |     Dallas     |                              1950 Stemmons Freeway                               |       Suite 3048      |
|         |    DALLAS02   | dal02 |   Dallas 2   |         |       |             |                |                                                                                  |                       |
|  138124 |    DALLAS05   | dal05 |   Dallas 5   |    US   |   TX  |    75244    |     Dallas     |                                 4849 Alpha Road                                  |                       |
|  154820 |    DALLAS06   | dal06 |   Dallas 6   |    US   |   TX  |    75207    |     Dallas     |                             1333 N. Stemmons Freeway                             |       Suite 110       |
|         |    DALLAS07   | dal07 |   Dallas 7   |         |       |             |                |                                                                                  |                       |
|  449494 |    DALLAS09   | dal09 |   Dallas 9   |    US   |   TX  |    75081    |   Richardson   |                                 900 Quality Way                                  |                       |
| 1441195 |    DALLAS10   | dal10 |  Dallas 10   |    US   |   TX  |    75063    |     Irving     |                               6431 Longhorn Drive                                |                       |
|  449506 |   FRANKFURT   | fra02 | Frankfurt 2  |    DE   |       |    65936    |   Frankfurt    |                           Leonard - Heisswolf - Str 4.                           |                       |
|  352494 |   HONGKONG02  | hkg02 | Hong Kong 2  |    HK   |       |             |   Hong Kong    | 33 Chun Choi Street, Tseung Kwan O Industrial Estate, New Territories, Hong Kong |                       |
|  142775 |   HOUSTON02   | hou02 |  Houston 2   |    US   |   TX  |    77067    |    Houston     |                                855 Greens Parkway                                |       Suite 300       |
|  358694 |    LONDON02   | lon02 |   London 2   |    GB   |       |   KT9 1SJ   |  Chessington   |                             Fountain Court, Cox Lane                             |   Suites 210 and 230  |
|  449596 |   MELBOURNE   | mel01 | Melbourne 1  |    AU   |       |   VIC 3032  |   Melbourne    |                            72 Radnor Drive, Deer Park                            |                       |
|  449600 |     MEXICO    | mex01 |   Mexico 1   |    MX   |       |             |   Querétaro   |                Km 2 200, Lateral Carretera Estatal 431 El Marques                |                       |
|  815394 |     MILAN     | mil01 |   Milan 1    |    IT   |       |    20010    |   CORNAREDO    |                                 VIA MONZORO 103                                  |                       |
|  449610 |    MONTREAL   | mon01 |  Montreal 1  |    CA   |   QC  |   J2C 7W2   | Drummondville  |                                2525 Rue Canadien                                 |                       |
| 1541257 |      OSLO     | osl01 |    Oslo 1    |    NO   |       |     1900    |    Fetsund     |                                 Fet Næringspark                                 |      Heiaveien 9      |
|  449500 |     PARIS     | par01 |   Paris 1    |    FR   |       |    92582    |     Clichy     |                 Société par Actions Simplifiée Unipersonnelle                 |     7-9 rue Petit     |
|  983497 |    SAOPAULO   | sao01 | Sao Paulo 1  |    BR   |       |   Km 67,7   |   Medeiros     |                          Rod Dom Gabriel Paulino Couto,                          |                       |
|  18171  |    SEATTLE    | sea01 |  Seattle 1   |    US   |   WA  |    98168    |    Tukwila     |                         3355 S. 120th Place, Suite# 331                          |                       |
| 1555995 |     SEOUL     | seo01 |   Seoul 1    |    KR   |       | Gyeonggi-do |  Seongnam-si   |                            46, Pangyo-ro 255beon-gil                             |       Bundang-gu      |
|  168642 |    SANJOSE    | sjc01 |  San Jose 1  |    US   |   CA  |    95054    |  Santa Clara   |                            3105 Alfred St, Suite 331                             |                       |
| 1004995 |   SANJOSE03   | sjc03 |  San Jose 3  |    US   |   CA  |    95054    |  Santa Clara   |                              1100 Space Park Drive                               |                       |
|  224092 |   SINGAPORE   | sng01 | Singapore 1  |    SG   |       |    139964   |  East Jurong   |                         29A International Business Park                          |                       |
|  449612 |     SYDNEY    | syd01 |   Sydney 1   |    AU   |       | Ultimo, NSW |     Ultimo     |                                273 Pymont Street                                 |                       |
| 2013295 |               | syd04 |   Sydney 4   |    AU   |       |    2759     |    Sydney      |                                1 13, Templar Road                                |      Erskine Park     |
|  449604 |     TOKYO     | tok02 |   Tokyo 2    |    JP   |       |   135-0061  | Koto-ku, Tokyo |                                  6-2-12 Toyosu                                   |                       |
|  448994 |    TORONTO    | tor01 |  Toronto 1   |    CA   |   ON  |   L3R 4B6   |    Markham     |                                    Suite 130                                     |       371 Gough       |
|  37473  | WASHINGTON_DC | wdc01 | Washington 1 |    US   |   VA  |    20151    |   Chantilly    |                           4030 Lafayette Center Drive                            |       Suite 331       |
|  957095 |   ASHBURN04   | wdc04 | Washington 4 |    US   |   VA  |    20147    |    Ashburn     |                           44060 Digital Loudoun Plaza                            |                       |
+---------+---------------+-------+--------------+---------+-------+-------------+----------------+----------------------------------------------------------------------------------+-----------------------+

Get PackageId

I made a script to get the PackageId, so please use it.

script

getActivePackages.py


# import
import SoftLayer
from prettytable import PrettyTable

#define objectmask
objectmask = """
    id,
    name,
    keyName,
    subDescription
"""

#define table
table = PrettyTable([
    'PackageID',
    'Name',
    'keyName',
    'subDescription'
])

# account info
client = SoftLayer.create_client_from_env()
getActivePackages = client['Account'].getActivePackages(mask=objectmask)

for key in range(len(getActivePackages)):
        table.add_row([
            getActivePackages[key]['id'],
            getActivePackages[key]['name'],
            getActivePackages[key]['keyName'],
            getActivePackages[key]['subDescription']
        ])

print len(getActivePackages)
print table.get_string(sortby="PackageID")

Example of execution result

#Execution command
python getActivePackages.py 

#result
35
+-----------+-------------------------------------+--------------------------------------+-------------------------------------+
| PackageID |                 Name                |               keyName                |            subDescription           |
+-----------+-------------------------------------+--------------------------------------+-------------------------------------+
|     46    |             Cloud Server            |             CLOUD_SERVER             |       Virtual Server Instance       |
|    174    |      Network Gateway Appliance      |      NETWORK_GATEWAY_APPLIANCE       |      Network Gateway Appliance      |
|    192    |    Application Delivery Appliance   |    APPLICATION_DELIVERY_APPLIANCE    |    Application Delivery Appliance   |
|    194    |            Load Balancers           |            LOAD_BALANCERS            |            Load Balancers           |
|    198    |           Portable Storage          |           PORTABLE_STORAGE           |           Portable Storage          |
|    200    |          Bare Metal Server          |          BARE_METAL_SERVER           |          Bare Metal Server          |
|    206    |            Object Storage           |            OBJECT_STORAGE            |            Object Storage           |
|    208    |       Content Delivery Network      |       CONTENT_DELIVERY_NETWORK       |       Content Delivery Network      |
|    210    |           SSL Certificate           |           SSL_CERTIFICATE            |           SSL Certificate           |
|    212    |            Message Queue            |            MESSAGE_QUEUE             |            Message Queue            |
|    216    |       Network Attached Storage      |       NETWORK_ATTACHED_STORAGE       |       Network Attached Storage      |
|    218    |            iSCSI Storage            |            ISCSI_STORAGE             |            iSCSI Storage            |
|    222    |             Performance             |     PERFORMANCE_STORAGE_SERVICE      |         Performance Storage         |
|    226    |       Authentication Services       |       AUTHENTICATION_SERVICES        |       Authentication Services       |
|    236    | Network Gateway Appliance (10 Gbps) | 2U_NETWORK_GATEWAY_APPLIANCE_1O_GBPS | Network Gateway Appliance (10 Gbps) |
|    242    |            POWER8 Servers           |            POWER8_SERVERS            |            POWER8 Servers           |
|    244    |              Monitoring             |              MONITORING              |              Monitoring             |
|    248    |  Dual E5-2600 v3 Series (36 Drives) |       DUAL_E52600_V3_36_DRIVES       |  Dual E5-2600 v3 Series (36 Drives) |
|    251    |  Dual E5-2600 v3 Series (12 Drives) |     2U_DUAL_E52600_V3_12_DRIVES      |  Dual E5-2600 v3 Series (12 Drives) |
|    253    |  Dual E5-2600 v3 Series (4 Drives)  |         DUAL_E52600_4_DRIVES         |  Dual E5-2600 v3 Series (4 Drives)  |
|    255    |      Single E3-1270 (4 Drives)      |        SINGLE_E31270_4_DRIVES        |      Single E3-1270 (4 Drives)      |
|    257    |     Single E3-1270 v3 (4 Drives)    |      SINGLE_E31270_V3_4_DRIVES       |      Single E3-1270 (4 Drives)      |
|    259    |   Single E5-2600 Series (4 Drives)  |        SINGLE_E52600_4_DRIVES        |   Single E5-2600 Series (4 Drives)  |
|    261    |      Single E3-1270 (2 Drives)      |        SINGLE_E31270_2_DRIVES        |      Single E3-1270 (2 Drives)      |
|    263    |   Dual E5-2600 Series (36 Drives)   |       4U_DUAL_E52600_36_DRIVES       |   Dual E5-2600 Series (36 Drives)   |
|    265    |   Dual E5-2600 Series (12 Drives)   |       2U_DUAL_E52600_12_DRIVES       |   Dual E5-2600 Series (12 Drives)   |
|    267    |   Quad E5-4600 Series (24 Drives)   |       4U_QUAD_E54600_24_DRIVES       |   Quad E5-4600 Series (24 Drives)   |
|    269    |   Quad E7-4800  Series (6 Drives)   |       2U_QUAD_E74800_6_DRIVES        |   Quad E7-4800  Series (6 Drives)   |
|    271    |  Quad E7-4800 v2 Series (24 Drives) |      2U_QUAD_E74800_V2_6_DRIVES      |  Quad E7-4800 v2 Series (24 Drives) |
|    273    |       Dual E5-2600 (4 Drives)       |        DUAL_E52600_4_DRIVES_2        |       Dual E5-2600 (4 Drives)       |
|    295    |          Certified Servers          |      SAP_HANA_CERTIFIED_SERVERS      |        SAP Certified Servers        |
|    297    |          Certified Servers          |   SAP_NETWEAVER_CERTIFIED_SERVERS    |        SAP Certified Servers        |
|    551    |  Dual E5-2600 v4 Series (4 Drives)  |       DUAL_E52600_V4_4_DRIVES        |  Dual E5-2600 v4 Series (4 Drives)  |
|    553    |  Dual E5-2600 v4 Series (12 Drives) |       DUAL_E52600_V4_12_DRIVES       |  Dual E5-2600 v4 Series (12 Drives) |
|    555    |  Dual E5-2600 v4 Series (36 Drives) |       DUAL_E52600_V4_36_DRIVES       |  Dual E5-2600 v4 Series (36 Drives) |
+-----------+-------------------------------------+--------------------------------------+-------------------------------------+

Get ItemId

I made a script to get ItemId, so please use it.

script

getCategoriesAndItemPrices.py


import SoftLayer
import json
from prettytable import PrettyTable
import operator
 
# Get the SoftLayer API client object
client = SoftLayer.create_client_from_env()
 
def getItems(pkgId):
    # Get a list of the categories that can be specified and the item prices within each category that you can choose from.
    # Build a dict of each category id and what its categoryCode is.  This is only used to build the item dict below.
    categories = client['Product_Package'].getConfiguration(id=pkgId, mask='isRequired, itemCategory.id, itemCategory.name, itemCategory.categoryCode')
    cats = {}
    for cat in categories:
        catid = cat['itemCategory']['id']
        cats[catid] = {'code':cat['itemCategory']['categoryCode'], 'name':cat['itemCategory']['name'], 'isRequired':(cat['isRequired'] == 1)}
 
    # Go thru the items for this pkg and put the key/id pair in the correct category
    # Note: the keys are only unique within categories, not between categories
    mask = 'id, itemId, recurringFee, hourlyRecurringFee, item.description, item.keyName, categories.id'
    itemPrices = client['Product_Package'].getItemPrices(id=pkgId, mask=mask)
    items = {}          # this is a 2 level dict: 1st key is categoryCode, 2nd key is item keyName, value is item price id and other info
    for itemP in itemPrices:
        if 'categories' not in itemP:  continue
        itemId = itemP['id']
        itemDesc = itemP['item']['description']
        itemKeyName = itemP['item']['keyName']
        if 'recurringFee' in itemP:  itemFee = itemP['recurringFee']
        else:  itemFee = '0'
        if 'hourlyRecurringFee' in itemP:  itemHourlyFee = itemP['hourlyRecurringFee']
        else:  itemHourlyFee = None
        # Go thru this item's supported categories
        for itemCat in itemP['categories']:
            itemCatId = itemCat['id']
            # We correlate the categories and items by the category id
            if itemCatId in cats:
                # This item supports a category in this package, so add it to the structure under this category
                categoryCode = cats[itemCatId]['code']
                # If we haven't yet added an entry for this categoryCode, create it now
                if categoryCode not in items:  items[categoryCode] = {'catName':cats[itemCatId]['name'], 'isRequired':cats[itemCatId]['isRequired'], 'items':{}}
                entry = {'id':itemId, 'description':itemDesc, 'fee':itemFee}
                if itemHourlyFee:  entry['hourlyFee'] = itemHourlyFee
                if itemKeyName in items[categoryCode]['items']:  print 'Warning: items['+categoryCode+"]['items']["+itemKeyName+'] already has a value of '+str(items[categoryCode]['items'][itemKeyName])+' and we are overwriting it with '+str(entry)
                # Now add the item to this category
                items[categoryCode]['items'][itemKeyName] = entry
    return items
 
pkgId = 46     # specify the package id you want = Virtual Server
#pkgId = 297     # SAP Certified Servers 
items = getItems(pkgId)
#jsonstring = json.dumps(items,indent=4)
#print(jsonstring) 

# define table
table = PrettyTable([
    'keyCategory',
    'isRequired',
    'catName',
    'id',
    'fee',
    'hourlyFee',
    'description'
])

for i in range(len(items)):
	eachItem = items.keys()[i]
	for j in range(len(items[eachItem]['items'].keys())):
		itemContent = items[eachItem].keys()[2]
		itemName = items[eachItem][itemContent].keys()[j]
		table.add_row([
			items.keys()[i],
			items[eachItem]['isRequired'],
			items[eachItem]['catName'],
			items[eachItem][itemContent][itemName].get('id',""),
			items[eachItem][itemContent][itemName].get('fee',""),
			items[eachItem][itemContent][itemName].get('hourlyFee',""),
			items[eachItem][itemContent][itemName].get('description',"")
		])

print table.get_string(sort_key=operator.itemgetter(1,7),sortby='keyCategory')

Example of execution result

#Execution command
python getCategoriesAndItemPrices.py 

#result
+-------------------------+------------+----------------------------------------+--------+---------+-----------+-----------------------------------------------------------------------+
|       keyCategory       | isRequired |                catName                 |   id   |   fee   | hourlyFee |                              description                              |
+-------------------------+------------+----------------------------------------+--------+---------+-----------+-----------------------------------------------------------------------+
|  av_spyware_protection  |   False    |    Anti-Virus & Spyware Protection     | 34536  |    0    |     0     |                      McAfee VirusScan Enterprise                      |
|        bandwidth        |    True    |            Public Bandwidth            | 24745  |   1500  |           |                 Unlimited Bandwidth (100 Mbps Uplink)                 |
|        bandwidth        |    True    |            Public Bandwidth            | 34183  |    0    |     0     |                             0 GB Bandwidth                            |
|        bandwidth        |    True    |            Public Bandwidth            | 35963  |    0    |           |                             0 GB Bandwidth                            |
|        bandwidth        |    True    |            Public Bandwidth            | 50253  |  494.45 |           |                           10000 GB Bandwidth                          |
|        bandwidth        |    True    |            Public Bandwidth            | 50369  |    0    |           |                            250 GB Bandwidth                           |
|        bandwidth        |    True    |            Public Bandwidth            | 78465  | 1448.56 |           |                           20000 GB Bandwidth                          |
|        bandwidth        |    True    |            Public Bandwidth            | 153549 |  745.74 |           |                           5000 GB Bandwidth                           |
|        bandwidth        |    True    |            Public Bandwidth            | 164857 |   90.7  |           |                           1000 GB Bandwidth                           |
|       bc_insurance      |   False    |               Insurance                | 24329  |    0    |     0     |                     Business Continuance Insurance                    |
|        cdp_backup       |   False    |               CDP Addon                | 32414  |  36.25  |           |                        Idera Disk Agent 10 Pack                       |
...

Issuing a new VSI quote

Make full use of the locationId, PackageId, and ItemId obtained above to issue a quote.

script

placeQuoteVsi.py


#import package
import SoftLayer
import json

# account info
client = SoftLayer.create_client_from_env()

order = {
	"orderContainers": [{
		'complexType': 'SoftLayer_Container_Product_Order_Virtual_Guest', 
		'quantity': 1,
		'virtualGuests': [{
        		'hostname': 'test', 
        		'domain': 'example.com',
      		}],
		'primaryDiskPartitionId': 1,
		'location': 449604, # Tokyo
		'packageId': 46,  # VSI
		'useHourlyPricing': False,
		'prices': [
           		{'id':26125},  # 1 x 2.0 GHz Core
           		{'id':32597},  # 1 GB RAM
           		{'id':23070},  # Reboot / Remote Console
        		{'id':26737},  # 100 Mbps Public & Private Networks
           		{'id':50369},  # 250 GB Bandwidth
           		{'id':34807},  # 1 IP Address
           		{'id':26466},  # 100 GB (LOCAL) First Disk
           		{'id':175779},  # Windows Server 2012 R2 Standard Edition (64 bit)
           		#{'id':171611},  # Ubuntu 16.04 (64 bit)
           		{'id':27023},  # Host Ping Monitoring
           		{'id':32500},  # Email and Ticket Notifications
           		{'id':32627},  # Automated Notification Response
           		{'id':33483},  # Unlimited SSL VPN Users & 1 PPTP VPN User per account
           		{'id':35310}   # Vulnerability Assessments & Management
		],
	},
	{
                'complexType': 'SoftLayer_Container_Product_Order_Virtual_Guest',
                'quantity': 1,
                'virtualGuests': [{ 
                        'hostname': 'test', 
                        'domain': 'example.com',
                }],
                "primaryDiskPartitionId": 1,
                'location': 449604, # Tokyo
                'packageId': 46,  # VSI
                'useHourlyPricing': False,
                'prices': [
                        {'id':26125},  # 1 x 2.0 GHz Core
                        {'id':32597},  # 1 GB RAM 
                        {'id':23070},  # Reboot / Remote Console
                        {'id':26737},  # 100 Mbps Public & Private Networks
                        {'id':50369},  # 250 GB Bandwidth
                        {'id':34807},  # 1 IP Address
                        {'id':26466},  # 100 GB (LOCAL) First Disk
                        #{'id':175779},  # Windows Server 2012 R2 Standard Edition (64 bit)
                        {'id':171611},  # Ubuntu 16.04 (64 bit)
                        {'id':27023},  # Host Ping Monitoring
                        {'id':32500},  # Email and Ticket Notifications
                        {'id':32627},  # Automated Notification Response
                        {'id':33483},  # Unlimited SSL VPN Users & 1 PPTP VPN User per account
                        {'id':35310}   # Vulnerability Assessments & Management
                ],
	}],
		'quoteName': "khayamaQuoteTest",
		'sendQuoteEmailFlag': True
}   

# placeQuote
placeQuote = client['Product_Order'].placeQuote(order)
#placeQuote = client['Product_Order'].verifyOrder(order)

#jsonstring = json.dumps(placeQuote,indent=4)
#print(jsonstring) 

Example of execution result

#Execution command
python placeQuoteVsi.py

#result
A quote for the name specified in "quoteName" is saved on the portal.

Output as PDF

See here. Save Bluemix IaaS (formerly SoftLayer) quotes to PDF via API --Qiita

Referenced site

Recommended Posts

Estimate VSI for Bluemix IaaS (formerly SoftLayer) via API
Save Bluemix IaaS (formerly SoftLayer) quotes to PDF via API