This notebook serves as a devops utility for the creation of Docker VM instances on SoftLayer.
This notebook uses SoftLayer services to provision a Student VMs.
We will use the SoftLayer (SL) Python Package and instructions here. If you have not already installed the Python Libraries for Softlayer on your KA Workbench, do the following:
!pip install Softlayer --upgrade
Create a Json file and add it to your workbench. The should look like this:
* Your SoftLayer Credentials
{ "username":"xxxxxxxxx", "api_key":"xxxxxxxxxxxxx" } ```
The subsequent code cell will prepare connections using your credential files for each IaaS provider.
In [ ]:
import re
import json
from SoftLayer import Client, VSManager, SshKeyManager
# Load SoftLayer Account Credentials
with file('/resources/dag-sl-apiconfig.json') as f:
sl_key = json.load(f)
# Establish Account Connection
client = Client(username=sl_key['username'], api_key=sl_key['api_key'])
# Create Manager Objects
vsmapi = VSManager(client) # Virtual Server Manager replaces CCI Mgr
sshapi = SshKeyManager(client)
In [ ]:
client['Account'].getObject()
In [ ]:
# Print readable Dictionaries
import pprint
prettyprinter = pprint.PrettyPrinter(indent=4)
# Print readable Json
def jazzyJson(jblob):
print json.dumps(jblob,sort_keys=True, indent=2, separators=(',', ': '))
In [ ]:
# Environmanet Prefix
ENVIRONMENT_PREFIX = 'bcs'
# A list of server names. This list allows for the creation of
# one or more servers for a variety of purposes such as testing the
# devops tools.
STUDENTS = 1
BASE_ID = 200
SERVER_PREFIX = 'student'
# A list of server labels.
# This value is used to create a note for the
# instantiated devices (VM instances).
# <adhoc prefix>; <label>
LABEL_PREFIX = 'BCS Meetup'
# Order Template Details
# The following values are used to contruct an order.
OTD_CPUS = '2'
OTD_RAM = '4'
OTD_HOURLY = 'False'
OTD_HOSTNAME = 'TBD' # Dynamically Modified
OTD_DOMAIN = 'meetup.com'
OTD_DATACENTER = 'wdc01'
OTD_ODCODE = 'UBUNTU_14_64'
OTD_PROVISIONING_SCRIPT = 'https://gist.githubusercontent.com/vinomaster/28da057b74c884e5e0e0/raw/f4d5bb5adebc6a7625a4bce189c5c0aa651a9a0c/Bootstrap_MI_Target_VM.sh'
OTD_SSH_ACCESSID = 86626 # Add ID for Boston Cloud Services Meetup key.
In [ ]:
# Generate a list of server identifiers based on desired
# quantity of servers.
# Returns: List of Server Prefix Identifiers
def generateServerIdentifiers(baseline,quantity):
prefix_list = []
limit = baseline+quantity
for s in range(baseline,limit):
prefix_list.append(SERVER_PREFIX+str(s))
return prefix_list
# Generate hostnames conforming to the convention:
# <hostname> = <env_prefix>.<studentId>
# Returns: List of Hostnames
def generateHostnames(host_server_names):
hnames = []
for name in host_server_names:
hnames.append(ENVIRONMENT_PREFIX + '.' + name)
return hnames
# Generate device labels.
# Returns: List of Labels
def generateEnvNotes(serverIds):
note_prefix = LABEL_PREFIX + '; '
labels = []
for student in serverIds:
labels.append(note_prefix + 'Workspace for ' + student)
return labels
# Generate a SoftLayer order.
# Returns: List of Orders
def generateOrders(template,serverIds):
hostnames = generateHostnames(serverIds)
orders = []
for h in hostnames:
order = template.copy()
order['hostname'] = h
orders.append(order)
return orders
# Generate a list of devices associated with the SoftLayer Account
# that match the provides list of hostnames.
# Returns: DataFrame of Devices
def displayDeviceDetails(hostnames):
import pandas as pd
df_masterDeviceList = pd.DataFrame()
for name in hostnames:
devices = vsmapi.list_instances(hostname=name)
df_subDeviceList = pd.DataFrame(devices)
print("Processing hostname {0} which has {1} associated device(s).".format(name, len(df_subDeviceList.index)))
df_filteredSubDeviceList = df_subDeviceList[['id','fullyQualifiedDomainName','primaryIpAddress']]
if df_masterDeviceList.empty:
df_masterDeviceList = pd.DataFrame(df_filteredSubDeviceList)
else:
df_masterDeviceList = df_masterDeviceList.append(df_filteredSubDeviceList, ignore_index=True)
df_masterDeviceList.rename(columns={'id':'Device ID'}, inplace=True)
df_masterDeviceList.rename(columns={'fullyQualifiedDomainName':'Device Name'}, inplace=True)
df_masterDeviceList.rename(columns={'primaryIpAddress':'Public IP'}, inplace=True)
return df_masterDeviceList
# Updates the "note" property for each device in a list of devices
# with a label from a list of corresponding labels.
# Set confirm parameter to True to commit change, otherwise
# the output is for debug purposes only.
# Prereq: Requires a call to displayDeviceDetails() to obtain
# Dataframe of devices.
def labelDevices(devices,labels,confirmed=False):
for index, row in devices.iterrows():
id = int(row['Device ID'])
note = labels[index]
if confirmed:
vsmapi.edit(id, notes=note)
print(">> Modified device {0} with label --> {1}.").format(id, note)
else:
print("Device {0} prepared for label [{1}].").format(id, note)
# Cancel a list of devices.
# Set confirm parameter to True to commit change, otherwise
# the output is for debug purposes only.
# Prereq: Requires a call to displayDeviceDetails() to obtain
# Dataframe of devices.
def cancelDevices(devices,confirmed=False):
for index, row in devices.iterrows():
id = int(row['Device ID'])
if confirmed:
vsmapi.cancel_instance(id)
print("Cancelled device {0}.").format(id)
else:
print("Device {0} prepared for termination.").format(id)
In [ ]:
# Create Baseline Order Template
orderTemplate = {}
orderTemplate.update({'cpus': OTD_CPUS})
orderTemplate.update({'memory': OTD_RAM})
orderTemplate.update({'hourly': OTD_HOURLY})
orderTemplate.update({'hostname': OTD_HOSTNAME})
orderTemplate.update({'domain': OTD_DOMAIN})
orderTemplate.update({'datacenter': OTD_DATACENTER})
orderTemplate.update({'os_code': OTD_ODCODE})
orderTemplate.update({'post_uri': OTD_PROVISIONING_SCRIPT})
etechKey = sshapi.get_key(OTD_SSH_ACCESSID).get('id')
ssh_keys = []
ssh_keys.append(etechKey)
orderTemplate.update({'ssh_keys': ssh_keys})
prettyprinter.pprint(orderTemplate.items())
In [ ]:
studentList = generateServerIdentifiers(BASE_ID,STUDENTS)
print studentList
In [ ]:
shoppingCart = generateOrders(orderTemplate,studentList)
invoice = vsmapi.create_instances(shoppingCart)
jazzyJson(invoice)
In [ ]:
hostnameList = generateHostnames(studentList)
deviceDetails = displayDeviceDetails(hostnameList)
deviceDetails
In [ ]:
COMMIT = True # Modifiy this value
# Generate Labels for Adhoc Environment
print "Building adhoc labels."
labels = generateEnvNotes(studentList)
labelDevices(deviceDetails,labels,confirmed=COMMIT)
In [ ]:
COMMIT = False # Modifiy this value
cancelDevices(deviceDetails,confirmed=COMMIT)