Cullen Taylor Cullen Taylor - 27 days ago 13
Python Question

Configuring Softlayer Disk Partitions at Order Time

I was wondering how it would be possible to specify an extra partition to add to the boot drive (in this case a RAID1 storage group) at order time via the Softlayer Ppython API. That way the extra partition would persist on the server after transactions like OS reloads.

I assume it would be added as an extra option, similar to the storage_groups in the example below (I have redacted some information to keep it as general as possible), but I'm unsure of how to add this.

RAID_1 = 2
SERVERS = [
{
"types": [
{ "name": "NAME", "type": "TYPE" },
],
"package": PACKAGE_DESCRIPTION
"prices": [
"CPU",
"RAM",
"OS",
"DISK_CONTROLLER_RAID", # RAID
"HARD_DRIVE_960GB_SSD",
"HARD_DRIVE_960GB_SSD",
"HARD_DRIVE_4_00_TB_SATA",
"NETWORKING AND EXTRA OPTIONS"
],
"storage_groups": [
{ "arrayTypeId": RAID_1, # RAID 1
"hardDrives": [0,1] },
],
}


I have not found a documentation page on this in the SLDN, though I have found this gist page from SoftLayer which details how to add partitions during an OS reload, which seems to be similar.

Answer

At the moment to order a bare metal server with RAID configuration for the first configured storage group you cannot set a custom partition, you only can pick out a partition template (see the code below to get the partition templates maybe one of them meet your requirements). this is documented here: http://sldn.softlayer.com/reference/datatypes/SoftLayer_Container_Product_Order_Storage_Group

"partitions

Defines the partitions for the storage group. If this storage group is not a secondary storage group, then this will not be used."

Just in case I added a code to order bare metal servers and configure a custom partition in the second storage group (see below).

Another approach to order the bare metal server, with the partition configurations you want, is to order a bare metal server, after it has been provisioned configure it with the partitions you want and create a image template from that server, then you can use that image template to create new bare metal servers and they should end up with the partition configuration that you wanted.

Here an example to get the valid partition templates.

"""
List the partition templates available for the first disk.
The partition templates available will depend on the OS selected and the disk type assigned.

Important manual pages:
http://sldn.softlayer.com/reference/services/SoftLayer_Hardware_Component_Partition_OperatingSystem/getByDescription
http://sldn.softlayer.com/reference/datatypes/SoftLayer_Hardware_Component_Partition_OperatingSystem/

License: http://sldn.softlayer.com/article/License
Author: SoftLayer Technologies, Inc. <sldn@softlayer.com>
"""

import SoftLayer
import json

USERNAME = 'set me'
API_KEY = 'set me'

# To get the valid list of description values use SoftLayer_Hardware_Component_Partition_OperatingSystem::getAllObjects method.
description = "linux"

client = SoftLayer.Client(username=USERNAME, api_key=API_KEY)
packageService = client['SoftLayer_Hardware_Component_Partition_OperatingSystem']

objectMask = "mask[partitionTemplates[data]]"

try:
    templates = packageService.getByDescription(description, mask=objectMask)
    print(json.dumps(templates, sort_keys=True, indent=2, separators=(',', ': ')))
except SoftLayer.SoftLayerAPIError as e:
    print("Unable to list the partition templates. faultCode=%s, faultString=%s" % (e.faultCode, e.faultString))

Here an example to order a server with Raid and set a custom partition for the second storage group:

"""
Order a new server with RAID configuration.

Important manual pages:
http://sldn.softlayer.com/reference/datatypes/SoftLayer_Container_Product_Order
http://sldn.softlayer.com/reference/datatypes/SoftLayer_Hardware_Server
http://sldn.softlayer.com/reference/datatypes/SoftLayer_Product_Item_Price
http://sldn.softlayer.com/reference/services/SoftLayer_Product_Order/verifyOrder
http://sldn.softlayer.com/reference/services/SoftLayer_Product_Order/placeOrder

License: http://sldn.softlayer.com/article/License
Author: SoftLayer Technologies, Inc. <sldn@softlayer.com>
"""

import SoftLayer
import json

# Your SoftLayer API username and key.
USERNAME = 'set me'
API_KEY = 'set me'

quantity = 1
location = 'AMSTERDAM03'
packageId = 265

# Building a skeleton SoftLayer_Hardware_Server object to model the hostname and
# domain we want for our server. If you set quantity greater then 1 then you
# need to define one hostname/domain pair per server you wish to order.
hardware = [
    {
        'hostname': 'test',
        'domain': 'example.org'
    }
]

# Building a skeleton SoftLayer_Product_Item_Price objects. These objects contain
# much more than ids, but SoftLayer's ordering system only needs the price's id
# to know what you want to order.
# Every item in SoftLayer's product catalog is assigned an id. Use these ids
# to tell the SoftLayer API which options you want in your new server. Use
# the getActivePackages() method in the SoftLayer_Account API service to get
# a list of available item and price options per available package.
prices = [
    {'id': 76175},  # Dual Intel Xeon E5-2690 (8 Cores, 2.90 GHz)
    {'id': 74095},  # 16 GB
    {'id': 44988},  # CentOS 7.x (64 bit)
    {'id': 75005},  # RAID
    {'id': 68789},  # 500 GB SATA
    {'id': 64817},  # 1.00 TB SATA
    {'id': 64817},  # 1.00 TB SATA
    {'id': 64817},  # 1.00 TB SATA
    {'id': 64817},  # 1.00 TB SATA
    {'id': 64817},  # 1.00 TB SATA
    {'id': 64817},  # 1.00 TB SATA
    {'id': 64817},  # 1.00 TB SATA
    {'id': 64817},  # 1.00 TB SATA
    {'id': 50357},  # 500 GB Bandwidth
    {'id': 273},  # 100 Mbps Public & Private Network Uplinks
    {'id': 76205},  # Redundant Power Supply
    {'id': 55},  # Host Ping
    {'id': 58},  # Automated Notification
    {'id': 420},  # Unlimited SSL VPN Users & 1 PPTP VPN User per account
    {'id': 418},  # Nessus Vulnerability Assessment & Reporting
    {'id': 21},  # 1 IP Address
    {'id': 57},  # Email and Ticket
    {'id': 906}  # Reboot / KVM over IP
]

# Building a skeleton SoftLayer_Container_Product_Order_Storage_Group object
# Storage groups will only be used if the 'RAID' disk controller price is selected.
# Any other disk controller types will ignore the storage groups set here.
# The first storage group in this array will be considered the primary storage group,
# which is used for the OS. Any other storage groups will act as data storage.
storageGroups = [
    {
         "arraySize": 1998,
         "arrayTypeId": 3,  # RAID_5
         "hardDrives": [
            1,
            2,
            3,
            4
         ],
         "partitionTemplateId": 6
     },
    {
         "arraySize": 500,
         "arrayTypeId": 9,
         "hardDrives": [
             0
         ],
         # The custom partitions only work on other storage groups
         # different from the primary one
         "partitions": [
             {
                 "isGrow": False,
                 "name": "/test",
                 "size": 100
             },
             {
                 "isGrow": True,
                 "name": "/test2",
                 "size": 200
             }
         ]
     },
    {
         "arraySize": 2264,
         "arrayTypeId": 1,  # RAID_0
         "hardDrives": [
             5,
             6,
             7,
             8
         ],
         "partitions": [
             {
                 "isGrow": False,
                 "name": "/rc",
                 "size": 500
             },
             {
                 "isGrow": True,
                 "name": "/tr",
                 "size": 200
             }
         ]
     }
]

# Building a skeleton SoftLayer_Container_Product_Order_Hardware_Server object
# containing the order you wish to place.
orderTemplate = {
    'quantity': quantity,
    'location': location,
    'packageId': packageId,
    'prices': prices,
    'hardware': hardware,
    'storageGroups': storageGroups
}

# Creating a SoftLayer API client object
client = SoftLayer.Client(username=USERNAME, api_key=API_KEY)

try:
    # verifyOrder() will check your order for errors. Replace this with a call
    # to placeOrder() when you're ready to order. Both calls return a receipt
    # object that you can use for your records.
    # Once your order is placed it'll go through SoftLayer's approval and
    # provisioning process. When it's done you'll have a new
    # SoftLayer_Hardware_Server object and server ready to use.
    receipt = client['Product_Order'].verifyOrder(orderTemplate)
    print(json.dumps(receipt, sort_keys=True, indent=2, separators=(',', ': ')))
except SoftLayer.SoftLayerAPIError as e:
    print("Unable to place a server order faultCode=%s, faultString=%s"
          % (e.faultCode, e.faultString))
    exit(1)
Comments