December 10, 2012

Classes
Tags blog

Dedicated server ordering with Flex Image and Python
<p>Automating server provisioning is not only fun, it can also save you the time and pain recovering from the carpal tun

Automating server provisioning is not only fun, it can also save you the time and pain recovering from the carpal tunnel all of the clicking and typing ordering 100's of servers from the managment portal can cause. To save you from that fate I have put together this guide in hopes to help you explore the world of order automation with the SoftLayer API :)

We will assume that at some earlier point in time we have created a Flex Image. Each image is a point in time snapshot of your primary drive, complete with OS and software configurations which means less work once the server is online.

To create an dedicated server order using Flex Image we must define the following:
*ID of the Flex Image template
*Package ID
*Location
*Item prices(a list of items the new server will have: RAM, CPUs, storage, etc...)
*List of "hardware"
*Quantity of servers to order
Let us start our journey into the depths of server ordering by grathering the template id of our Flex Image. However, as with most people we could not be bothered to remember the actual integer which defines our template; we simply remember the name we gave it.
So off we are to search for the Flex Image's ID, armed with our trusty template name...

import SoftLayer.API
from pprint import pprint as pp
apiUsername = ''
apiKey = ''
 
 
def getImageTemplateId(templateName):
   client = SoftLayer.API.Client('SoftLayer_Account', None, apiUsername, apiKey)
   # Retrieve a list of all images
   templates = client.getBlockDeviceTemplateGroups()
   # Loop through each template and return the ID of our target template
   for template in templates:
       if template['name'] == templateName:
           return template['id']
 
 
pp(getImageTemplateId('Image Name Here'))

We can put a checkmark next to imageTemplateId and for this example package ID and location will be a given(if you have trouble ascertaining what values to use here let me know).
We will be using:

   'packageId': 23,  # Intel Xeon 3200 Series
   'location': 'SANJOSE',  # San Jose 1

Now for the fun one: item prices. The item prices can be a bit daunting to gather at first. Each package has a configuration which defines what type of items must be included in each order. It achieves this by grouping items in categories which can be listed as optional or required. To determine a list of options from categories which must include we will use this script:

import SoftLayer.API
 
apiUsername = ''
apiKey = ''
package = 23
 
client = SoftLayer.API.Client('SoftLayer_Product_Package', package, apiUsername, apiKey)
# Only retrieve the bool to determine if this category is required and the category
# name and ID
categoryObjectMask = "mask[isRequired, itemCategory[id, name]]"
client.set_object_mask(categoryObjectMask)
 
# Retrieve a list of category confgurations associated with our chosen package
configurations = client.getConfiguration()
 
# For each price we only want the id, the ID of the category(ies) it is a memeber of,
# and the item description
pricesObjectMask = "mask[id;item.description;categories.id]"
 
client.set_object_mask(pricesObjectMask)
 
# Get all itemPrices for this package
prices = client.getItemPrices()
 
# Text format for our prettified output
headerFormat = '%s - %s:'
priceFormat = '    %s -- %s'
 
for configuration in configurations:
   # We are only concerned with reuqired categories...
   # skip it if we do not need it!
   if (not configuration['isRequired']):
       continue
   print headerFormat % (configuration['itemCategory']['name'], \\
       configuration['itemCategory']['id'])
   for price in prices:
       if ('categories' not in price):
           continue
       if len(filter(lambda x: x.get('id') == \\
           configuration['itemCategory']['id'], price['categories'])):
           print priceFormat % (price['id'], price['item']['description'])

Now we can just choose an option from each of the categories listed to populate our itemPrices property.

This is the entire order script with the priceId options I chose:

import SoftLayer.API
from pprint import pprint as pp
 
apiUsername = 'abcd'
apiKey = 'abcd1234'
templateId = 1234
 
client = SoftLayer.API.Client('SoftLayer_Product_Order', None, apiUsername, apiKey)
 
order = {
 
    # The API appreciates knowing what type of object we are sending...
    'complexType': 'SoftLayer_Container_Product_Order_Hardware_Server',
    'quantity': 2,
    # An array of SoftLayer_Virtual_Guest objects with at minimum the
    # ‘hostname’ and ‘domain’ properties defined. Provide SoftLayer_Hardware
    # objects equal to the quanity defined above
    'hardware': [
        {'hostname': 'host1', 'domain': 'example.com'},
        {'hostname': 'host2', 'domain': 'example.com'}
    ],
    'location': 'SANJOSE',  # San Jose 1
    'packageId': 23,  # Intel Xeon 3200 Series
    'imageTemplateId': templateId,
    'prices': [
        {'id':  1613},  # Server - Single Processor Quad Core Xeon 3230 - 2.60GHz  (Kentsfield) - 2 x 4MB cache
        {'id': 21001},  # Ram - 4 GB DDR2 667
        {'id':   876},  # Disk Controller - Non-RAID
        {'id':  1272},  # First Hard Drive - 73GB SA-SCSI 10K RPM
        {'id':   131},  # Public Bandwidth - 10000 GB Bandwidth
        {'id':   272},  # Uplink Port Speeds - 10 Mbps Public & Private Networks
        {'id':   906},  # Remote Management - Reboot / KVM over IP
        {'id':    21},  # Primary IP Addresses - 1 IP Address
        {'id':    51},  # Lockbox - 1 GB Lockbox
        {'id':    55},  # Monitoring - Host Ping
        {'id':    57},  # Notification - Email and Ticket
        {'id':    60},  # Response - 24x7x365 NOC Monitoring, Notification, and Response
        {'id':   420},  # VPN Management - Private Network - Unlimited SSL VPN Users & 1 PPTP VPN User per account
        {'id':   418},  # Vulnerability Assessments & Management - Nessus Vulnerability Assessment & Reporting
    ]
}
 
result = client.verifyOrder(order)
pp(result)

There is no particular need to have all of these scripts in this discrete format. In fact, they are most useful when combined together into a super-automation-script...but that task I leave to you. Hopefully this will help light your path on the way to no-hands server ordering!

-Phil
Get image template by name
Get required item prices for package listed by category
Place a Server with a Flex Image specified


Feedback?

We would love to hear it
Open an issue