SoftLayer API
Bluemix, IBM's cloud solution. In October 2016, the IaaS layer and the PaaS layer were integrated, and one solution called Bluemix can support all service ranges.
Bluemix Infrastructure provides the infrastructure part, that is, the server, network, and storage parts. One of its features is the automation of management by API (SoftLayer API).
With Bluemix Infrastructure, it is possible to perform all operations through API, from deploying physical servers and creating users, to registering with DNS, acquiring location information of each data center and issuing support tickets. ..
That should be the case, and in fact, the customer portal provided for Bluemix Infrastructure users is also created using the API, so all the operations that can be performed on the portal are provided with the API. ..
There are several articles on the SoftLayer API on the Web, so please refer to that as well. It is organized here. Reference site for SoftLayer API programming
In February 2016, IBM collaborated with VMware to make VMware components available in full stack on Bluemix. For that reason, there are many opportunities to hold hands-on VMware on IBM Cloud with IBM alone or with Bluemix Infrastructure partners such as SoftBank Commerce & Service.
vSphere "6.5" on IBM Bluemix Infrastructure (SoftLayer) Hands-on For example, we regularly carry out the above hands-on, so please come and visit us.
However, the problem here is building a hands-on environment. Hands-on will provide one bare metal server and one working virtual server for each participant. It would be nice if the number of participants was still small, but when the number of participants is large, it is difficult to do it manually.
Besides that, there are many small tasks such as setting VLAN and issuing tickets, and if you do it manually, mistakes will occur. (sorry···) So, this time, I will automate the construction of the hands-on environment, reduce mistakes as much as possible, and reduce my burden.
The hands-on environment is simply configured as follows.
Participants remotely log in to their assigned working virtual server via SSL VPN and install ESXi or vCenter on the bare metal server from that virtual server. Therefore, the bare metal server and the virtual server must be on the same VLAN. Also, since we do not use the Internet, we do not need to connect to the Public VLAN, so we will order Private Only.
The work for building the environment is listed below.
It requires a lot of work. It takes time, and I can't sleep the night before due to typos or selection mistakes. So I will automate all these tasks.
This time I will write a script using Python. By the way, I'm not familiar with Python, so please tell me secretly if you prefer to write this way.
The completed script is as follows.
handson.py
# coding:utf-8
#Prepare for hands-on environment
import SoftLayer
import json
import SoftLayer.API
import sys
import csv
from time import sleep
#API key of master account
username = "username"
apiKey = "apikey"
client = SoftLayer.Client(username= username, api_key = apiKey)
bms_allhosts = ''
counter = 0
#Import csv file
csvfile = "list.csv"
f = open(csvfile, "rU")
reader = csv.reader(f)
header = next(reader)
for (num,row) in enumerate(reader):
#Count numbers
counter += 1
##############################################################################################
#Create new user
##############################################################################################
#Input user information
user_template = {
'username': row[0],
'firstName': row[1],
'lastName': row[2],
'email': row[3],
'companyName': 'company name',
'address1': 'address',
'city': 'city',
'country': 'JP',
'state': 'OT',
'postalCode': 'xxx-xxxx',
'officePhone': row[5],
'userStatusId': 1001,
'timezoneId': 158,
'localeId': 22,
'sslVpnAllowedFlag': True
}
#Create new user
try:
new_user = client['User_Customer'].createObject(user_template, row[4], row[4])
print("complete user creation!")
except SoftLayer.SoftLayerAPIError as e:
print("Error: %s, %s" % (e.faultCode, e.faultString))
exit()
##############################################################################################
#Set permissions
##############################################################################################
#Define permission template
permission_template = [
{'keyName':'ACCOUNT_SUMMARY_VIEW'},
{'keyName':'ANTI_MALWARE_MANAGE'},
{'keyName':'BANDWIDTH_MANAGE'},
{'keyName':'CDN_BANDWIDTH_VIEW'},
{'keyName':'DEDICATED_HOST_VIEW'},
{'keyName':'DNS_MANAGE'},
{'keyName':'FIREWALL_MANAGE'},
{'keyName':'FIREWALL_RULE_MANAGE'},
{'keyName':'HARDWARE_VIEW'},
{'keyName':'HOST_ID_MANAGE'},
{'keyName':'IP_ADD'},
{'keyName':'LICENSE_VIEW'},
{'keyName':'LOADBALANCER_MANAGE'},
{'keyName':'MONITORING_MANAGE'},
{'keyName':'NETWORK_MESSAGE_DELIVERY_MANAGE'},
{'keyName':'NTF_SUBSCRIBER_MANAGE'},
{'keyName':'PORT_CONTROL'},
{'keyName':'REMOTE_MANAGEMENT'},
{'keyName':'SERVER_ADD'},
{'keyName':'SOFTWARE_FIREWALL_MANAGE'},
{'keyName':'TICKET_EDIT'},
{'keyName':'TICKET_SEARCH'},
{'keyName':'TICKET_VIEW'},
{'keyName':'TICKET_VIEW_BY_HARDWARE'},
{'keyName':'TICKET_VIEW_BY_VIRTUAL_GUEST'},
{'keyName':'VIRTUAL_GUEST_VIEW'},
{'keyName':'VPN_MANAGE'},
{'keyName':'VULN_SCAN_MANAGE'}
]
#Set permissions
try:
client['User_Customer'].addBulkPortalPermission(permission_template, id=new_user['id'])
print("complete setting user permission!")
except SoftLayer.SoftLayerAPIError as e:
print("Error: %s, %s" % (e.faultCode, e.faultString))
exit()
##############################################################################################
#Order hourly BMS
##############################################################################################
#Set BMS order template
bare_metal_server = {
'datacenter': {'name': 'hkg02'},
'hostname': 'handson.bms' + str(num+1),
'domain': 'softlayer.com',
'hourlyBillingFlag': True,
'fixedConfigurationPreset': {'keyName': 'S1270_32GB_1X1TBSATA_NORAID'},
'networkComponents': [{
'maxSpeed': 1000,
}],
'privateNetworkOnlyFlag': True,
'operatingSystemReferenceCode': 'CUSTOS_1_64'
}
#Order BMS
try:
order_bms = client['Hardware'].createObject(bare_metal_server)
print("complete order BMS!")
except SoftLayer.SoftLayerAPIError as e:
print("Error: %s, %s" % (e.faultCode, e.faultString))
exit()
#Add FQDN for ticket contents
bms_allhosts = bms_allhosts + (order_bms['hostname'] + order_bms['domain'] + '\n')
##############################################################################################
#Retrieve BMS information
##############################################################################################
#Get BMS id from Global ID
mask_1 = "mask[id;globalIdentifier]"
new_bms_id = 0
while True:
bms_infor = client['Account'].getHardware(mask=mask_1)
for bms_id in bms_infor:
try:
if bms_id['globalIdentifier'] == order_bms['globalIdentifier']:
new_bms_id = bms_id['id']
break
except KeyError:
print('please wait for a minutes... now provisioning BMS...')
sleep(120)
if new_bms_id > 0:
break
print(new_bms_id)
#Get BMS private VLAN ID
mask_2 = "mask[id]"
bms_vlan_id = 0
while True:
bms_vlan = client['Hardware'].getNetworkVlans(id=new_bms_id,mask=mask_2)
bms_vlan_id = bms_vlan[0]['id']
if bms_vlan_id > 0:
break
##############################################################################################
#Order hourly VSI
##############################################################################################
#Set VSI order template
virtual_server = {
'datacenter': {'name': 'hkg02'},
'hostname': 'handson.vsi' + str(num+1),
'domain': 'softlayer.com',
'hourlyBillingFlag': True,
'startCpus': 2,
'maxMemory': 4096,
'blockDeviceTemplateGroup':{
'globalIdentifier': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
},
'localDiskFlag': False,
'primaryBackendNetworkComponent':{
'networkVlan':{
'id': bms_vlan_id
}
},
'networkComponents': [{
'maxSpeed': 1000,
}],
'privateNetworkOnlyFlag': True,
}
#Order VSI
try:
order_vsi = client['Virtual_Guest'].createObject(virtual_server)
print("complete order VSI!")
except SoftLayer.SoftLayerAPIError as e:
print("Error: %s, %s" % (e.faultCode, e.faultString))
exit()
##############################################################################################
#Retrieve VSI information
##############################################################################################
#Get VSI id from Global ID
mask_3 = "mask[id;globalIdentifier]"
new_vsi_id = 0
while True:
vsi_infor = client['Account'].getVirtualGuests(mask=mask_3)
for vsi_id in vsi_infor:
try:
if vsi_id['globalIdentifier'] == order_vsi['globalIdentifier']:
new_vsi_id = vsi_id['id']
break
except KeyError:
print('please wait for a minutes... now provisioning VSI...')
sleep(60)
if new_vsi_id > 0:
break
##############################################################################################
#Server access control
##############################################################################################
#Remove all access
client['User_Customer'].removeAllHardwareAccessForThisUser(id=new_user['id'])
client['User_Customer'].removeAllVirtualAccessForThisUser(id=new_user['id'])
#Create lists of new server id
new_bms_idset = [new_bms_id]
new_vsi_idset = [new_vsi_id]
#Add specific server access
client['User_Customer'].addBulkHardwareAccess(new_bms_idset,id=new_user['id'])
client['User_Customer'].addBulkVirtualGuestAccess(new_vsi_idset,id=new_user['id'])
f.close()
##############################################################################################
#Issue ticket
##############################################################################################
#Create ticket template
ticket_template = {
'subjectId': 1021, # Hardware Issue
'assignedUserId': userid,
'title': 'IPMI privilege and UEFI mode'
}
ticket_contents = 'I have three requests. I would like to boot server from ISO and install vSphere(BYOL).\nI want to change the setting of following ' + counter + ' servers.\n\n' + bms_allhosts + '1. Could you change the privilege of IPMI control from Operator to Administrator?\n2. Please raise a start priority of ISO.\n3. Please change the IPMI\'s UEFI mode into legacy only mode.\n\nI agree to enforcement if you need to reboot the servers'
#Issue ticket
created_ticket = client['Ticket'].createStandardTicket(ticket_template, ticket_contents)
Also, put the .csv file of the participant list in the same folder.
list.csv
Username,First Name,Last Name,IBMid,password,office phone
test1,Toro,Yamada,[email protected],password1,xx-xxxx-xxxx
test2,Jiro,Takahashi,[email protected],password1,xxx-xxxx-xxxx
・ ・ ・
The simple script flow is to read a line in the csv file, create the user listed there, set permissions, and order the bare metal and virtual servers to assign to that user. It is shaped like repeating it until the last line.
From here, I will explain how to use the API part by part. It is also assumed that you understand the basic ideas and simple terms of the SoftLayer API (services, methods, data types, object masks, etc.).
handson.py
#Import csv file
csvfile = "list.csv"
f = open(csvfile, "rU")
reader = csv.reader(f)
header = next(reader)
for (num,row) in enumerate(reader):
Here, the list file of participants is read and processed line by line. The first line contains the process of skipping as a header.
handson.py
##############################################################################################
#Create new user
##############################################################################################
#Input user information
user_template = {
'username': row[0],
'firstName': row[1],
'lastName': row[2],
'email': row[3],
'companyName': 'company name',
'address1': 'address',
'city': 'city',
'country': 'JP',
'state': 'OT',
'postalCode': 'xxx-xxxx',
'officePhone': row[5],
'userStatusId': 1001,
'timezoneId': 158,
'localeId': 22,
'sslVpnAllowedFlag': True
}
#Create new user
try:
new_user = client['User_Customer'].createObject(user_template, row[4], row[4])
print("complete user creation!")
except SoftLayer.SoftLayerAPIError as e:
print("Error: %s, %s" % (e.faultCode, e.faultString))
exit()
Here, it is created using the createObject method of the User_Customer service. The following three parameters can be entered in the createObject of this service.
Parameters | Overview | Data type |
---|---|---|
templateObject | User-created template. | User_Customer |
password | Account password. | string |
vpnPassword | Password for using SSL VPN. | string |
The User_Customer data type is shaped like a dictionary object in Python, and the available keys and values are listed here [http://sldn.softlayer.com/reference/datatypes/SOftLayer_User_Customer). I am.
The data read from the csv file is embedded when this user template is created.
Also, the password parameter is ignored for "VPN-only users" and "Users created with IBM id". All newly created users are supposed to use IBMid authentication, so this is ignored. (By the way, in that case, the user needs to initialize the password within 24 hours.)
handson.py
##############################################################################################
#Set permissions
##############################################################################################
#Define permission template
permission_template = [
{'keyName':'ACCOUNT_SUMMARY_VIEW'},
{'keyName':'ANTI_MALWARE_MANAGE'},
{'keyName':'BANDWIDTH_MANAGE'},
{'keyName':'CDN_BANDWIDTH_VIEW'},
{'keyName':'DEDICATED_HOST_VIEW'},
{'keyName':'DNS_MANAGE'},
{'keyName':'FIREWALL_MANAGE'},
{'keyName':'FIREWALL_RULE_MANAGE'},
{'keyName':'HARDWARE_VIEW'},
{'keyName':'HOST_ID_MANAGE'},
{'keyName':'IP_ADD'},
{'keyName':'LICENSE_VIEW'},
{'keyName':'LOADBALANCER_MANAGE'},
{'keyName':'MONITORING_MANAGE'},
{'keyName':'NETWORK_MESSAGE_DELIVERY_MANAGE'},
{'keyName':'NTF_SUBSCRIBER_MANAGE'},
{'keyName':'PORT_CONTROL'},
{'keyName':'REMOTE_MANAGEMENT'},
{'keyName':'SERVER_ADD'},
{'keyName':'SOFTWARE_FIREWALL_MANAGE'},
{'keyName':'TICKET_EDIT'},
{'keyName':'TICKET_SEARCH'},
{'keyName':'TICKET_VIEW'},
{'keyName':'TICKET_VIEW_BY_HARDWARE'},
{'keyName':'TICKET_VIEW_BY_VIRTUAL_GUEST'},
{'keyName':'VIRTUAL_GUEST_VIEW'},
{'keyName':'VPN_MANAGE'},
{'keyName':'VULN_SCAN_MANAGE'}
]
#Set permissions
try:
client['User_Customer'].addBulkPortalPermission(permission_template, id=new_user['id'])
print("complete setting user permission!")
except SoftLayer.SoftLayerAPIError as e:
print("Error: %s, %s" % (e.faultCode, e.faultString))
exit()
Next, set the portal permissions for the created user. Use the addBulkPortalPermission method of the User_Customer service to set the permissions.
Assign the list of permissions you want to set as a parameter to this method. Also, the name that can be specified as the value of keyName in the template is Listable in the getAllObjects method of the User_Customer_CustomerPermission_Permission service.
handson.py
##############################################################################################
#Order hourly BMS
##############################################################################################
#Set BMS order template
bare_metal_server = {
'datacenter': {'name': 'hkg02'},
'hostname': 'handson.bms' + str(num+1),
'domain': 'softlayer.com',
'hourlyBillingFlag': True,
'fixedConfigurationPreset': {'keyName': 'S1270_32GB_1X1TBSATA_NORAID'},
'networkComponents': [{
'maxSpeed': 1000,
}],
'privateNetworkOnlyFlag': True,
'operatingSystemReferenceCode': 'CUSTOS_1_64'
}
#Order BMS
try:
order_bms = client['Hardware'].createObject(bare_metal_server)
print("complete order BMS!")
except SoftLayer.SoftLayerAPIError as e:
print("Error: %s, %s" % (e.faultCode, e.faultString))
exit()
#Add FQDN for ticket contents
bms_allhosts = bms_allhosts + (order_bms['hostname'] + order_bms['domain'] + '\n')
The hourly billing bare metal server is preset and several templates are preconfigured.
Here we are using the CreateObject method of the Hardware service. By the way, if you want to order a more customizable bare metal server with monthly billing, use the Container_Product_Order data type and set more options. is needed.
You must enter the template as a parameter in the createObject method. The template is a dictionary object, in which you specify the data center, OS, etc. Each key and value can be found here [http://sldn.softlayer.com/reference/services/softlayer_hardware/createobject). I will explain briefly below.
Parameters | Overview | Data type |
---|---|---|
datacenter.name | Data center designation | string |
hostname | Server hostname | string |
domain | Server domain name | string |
hourlyBillingFlag | If True, it will be an hourly billing server. | boolean |
fixedConfigurationPreset.keyName | Select a preset type. | string |
networkComponents.maxSpeed | Specifies the port speed of the NIC. | int |
privateNetworkOnlyFlag | If True, it will be deployed only on the private NIC. | boolean |
operatingSystemReferenceCode | Specify the OS. | string |
You can check the list of values that can be specified for each parameter by using the getCreateObjectOptions method of the Hardware service. By the way, you cannot specify the VLAN by the primaryNetworkComponent.networkVlan.id parameter etc. only for the hourly billing bare metal server. Even if you ask the Bluemix side with a ticket, you can not do it.
The last bms_allhosts contains the FQDN of the bare metal server. It is used when issuing a ticket.
handson.py
##############################################################################################
#Retrieve BMS information
##############################################################################################
#Get BMS id from Global ID
mask_1 = "mask[id;globalIdentifier]"
new_bms_id = 0
while True:
bms_infor = client['Account'].getHardware(mask=mask_1)
for bms_id in bms_infor:
try:
if bms_id['globalIdentifier'] == order_bms['globalIdentifier']:
new_bms_id = bms_id['id']
break
except KeyError:
print('please wait for a minutes... now provisioning BMS...')
sleep(120)
if new_bms_id > 0:
break
print(new_bms_id)
#Get BMS private VLAN ID
mask_2 = "mask[id]"
bms_vlan_id = 0
while True:
bms_vlan = client['Hardware'].getNetworkVlans(id=new_bms_id,mask=mask_2)
bms_vlan_id = bms_vlan[0]['id']
if bms_vlan_id > 0:
break
When you ordered the bare metal server with createObject earlier, the server information is stored in order_bms as the return value of the API. However, when the order is confirmed, the server id and VLAN information are not confirmed. An example of the return value is shown below.
handson.py
{'datacenter': {'statusId': '', 'id': '', 'name': 'hkg02'}, 'domain': 'softlayer.com', 'hostname': 'handson.bms1', 'provisionDate': '', 'fixedConfigurationPreset': {'keyName': 'S1270_32GB_1X1TBSATA_NORAID', 'id': '', 'packageId': ''}, 'bareMetalInstanceFlag': '', 'privateNetworkOnlyFlag': True, 'hardwareStatusId': '', 'globalIdentifier': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 'operatingSystemReferenceCode': 'CUSTOS_1_64', 'hourlyBillingFlag': True, 'serviceProviderResourceId': '', 'networkComponents': [{'maxSpeed': 1000, 'modifyDate': '', 'networkVlanId': '', 'hardwareId': '', 'id': '', 'speed': '', 'port': ''}], 'serviceProviderId': '', 'id': '', 'accountId': xxxxxxxx}
The id and networkVlanId values are empty. At this stage, provisioning has not yet been completed, so this information cannot be obtained.
Therefore, the id is pulled out from the getHardware method of the Account service using the globalIdentifier that is confirmed at the moment of ordering. If provisioning is not finished, I try to wait for a while.
The VLAN ID can also be found from getNetworkVlans of the Account service.
By the way, the id of the server will be used to set the access authority after this, and the VLAN ID will be used to specify the VLAN for the virtual server.
handson.py
##############################################################################################
#Order hourly VSI
##############################################################################################
#Set VSI order template
virtual_server = {
'datacenter': {'name': 'hkg02'},
'hostname': 'handson.vsi' + str(num+1),
'domain': 'softlayer.com',
'hourlyBillingFlag': True,
'startCpus': 2,
'maxMemory': 4096,
'blockDeviceTemplateGroup':{
'globalIdentifier': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
},
'localDiskFlag': False,
'primaryBackendNetworkComponent':{
'networkVlan':{
'id': bms_vlan_id
}
},
'networkComponents': [{
'maxSpeed': 1000,
}],
'privateNetworkOnlyFlag': True,
}
#Order VSI
try:
order_vsi = client['Virtual_Guest'].createObject(virtual_server)
print("complete order VSI!")
except SoftLayer.SoftLayerAPIError as e:
print("Error: %s, %s" % (e.faultCode, e.faultString))
exit()
Order an hourly virtual server. You can order in much the same way as you would with a bare metal server. Use the createObject method of the Virtual_Guest service.
The difference from the bare metal server is that the primaryBackendNetworkComponent.networkVlan parameter first specifies the VLAN to deploy. Since the virtual server can select the VLAN even if it is charged hourly, it is deployed on the same VLAN as the bare metal server ordered earlier. You can also order from an image by specifying the globalIdentifier of the image template in blockDeviceTemplateGroup. In this case, you cannot specify the OS or disk.
By the way, you can specify public or private in the image template, but of course you can order from either. If it is public, you can get the list from the getPublicImages method of the Virtual_Guest_Block_Device_Template_Group service, and if it is private, you can get the list from the getBlockDeviceTemplateGroups method of the Account service.
handson.py
##############################################################################################
#Retrieve VSI information
##############################################################################################
#Get VSI id from Global ID
mask_3 = "mask[id;globalIdentifier]"
new_vsi_id = 0
while True:
vsi_infor = client['Account'].getVirtualGuests(mask=mask_3)
for vsi_id in vsi_infor:
try:
if vsi_id['globalIdentifier'] == order_vsi['globalIdentifier']:
new_vsi_id = vsi_id['id']
break
except KeyError:
print('please wait for a minutes... now provisioning VSI...')
sleep(60)
if new_vsi_id > 0:
break
Get the id of the virtual server as you did for a bare metal server.
handson.py
##############################################################################################
#Server access control
##############################################################################################
#Remove all access
client['User_Customer'].removeAllHardwareAccessForThisUser(id=new_user['id'])
client['User_Customer'].removeAllVirtualAccessForThisUser(id=new_user['id'])
#Create lists of new server id
new_bms_idset = [new_bms_id]
new_vsi_idset = [new_vsi_id]
#Add specific server access
client['User_Customer'].addBulkHardwareAccess(new_bms_idset,id=new_user['id'])
client['User_Customer'].addBulkVirtualGuestAccess(new_vsi_idset,id=new_user['id'])
f.close()
Grant the server access authority to the created user. First, use the removeAllHardwareAccessForThisUser method and removeAllVirtualAccessForThisUser method of the User_Customer service to remove the access authority to all servers.
After that, grant access to the server created earlier using the addBulkHardwareAccess method and addBulkVirtualGuestAccess method.
Please note that "hardwareIds" and "virtualGuestIds" in Parameters to be assigned to addBulkHardwareAccess and addBulkVirtualGuestAccess are arrays, not int types. Don't forget to put it in list format.
handson.py
##############################################################################################
#Issue ticket
##############################################################################################
#Create ticket template
ticket_template = {
'subjectId': 1021, # Hardware Issue
'assignedUserId': userid,
'title': 'IPMI privilege and UEFI mode'
}
ticket_contents = 'I have three requests. I would like to boot server from ISO and install vSphere(BYOL).\nI want to change the setting of following ' + str(counter) + ' servers.\n\n' + bms_allhosts + '1. Could you change the privilege of IPMI control from Operator to Administrator?\n2. Please raise a start priority of ISO.\n3. Please change the IPMI\'s UEFI mode into legacy only mode.\n\nI agree to enforcement if you need to reboot the servers'
#Issue ticket
created_ticket = client['Ticket'].createStandardTicket(ticket_template, ticket_contents)
Finally, issue a ticket and finish. Use the createStandardTicket method of the Ticket service. The subjectId specified in the template can be Get List with the getAllObjects method of the Ticket_Subject service.
Also, since the list of hosts is stored in bms_allhosts so that all the servers can be changed at the same time, I am using it.
This time, we automated the time-consuming hands-on environment creation with the SoftLayer API. Of course, in addition to the hands-on environment, I think it is very attractive to be able to order 10 servers, issue tickets many times, and automate various management.
Please use it by all means! !!
In addition, VMware on IBM Cloud hands-on is held every month, so if you want to touch Bluemix or love VMware, please use it. It's free. vSphere "6.5" on IBM Bluemix Infrastructure (SoftLayer) Hands-on
Recommended Posts