0
votes

I could find some APIs to cancel a single item, such as a virtual guest or a storage. However, it is complex to cancel a virtual guest along with all other billing items, I could not find a API that could get all billing items of a virtual guest.

For example, there exists a virtual guest with disk2, disk3, when I cancel this virtual guest, I do not want to reserve the disks anymore. How could I achieve that?

Update:

The virtual guest has three storages (portal->Device details->Storage):

Block Device (Disk)(25GB)(System) --> first

Block Device (Disk)(2GB)(Swap) --> swap

Block Device (Disk)(10GB)(System) --> second

And I tried to upgrade the virtual guest's storage by API, so that when virtual guest is canceled, the storages could be remove along with it automatically.

I upgraded like this:

none_first_disk_list = {
    'local':{
        25:'GUEST_DISK_25_GB_LOCAL_3',
        100:'GUEST_DISK_100_GB_LOCAL_3',
        150:'GUEST_DISK_150_GB_LOCAL',
        200:'GUEST_DISK_200_GB_LOCAL',
        300:'GUEST_DISK_300_GB_LOCAL'
    },
    'san':{
        10:'GUEST_DISK_10_GB_SAN',
        20:'GUEST_DISK_20_GB_SAN',
        25:'GUEST_DISK_25_GB_SAN_4',
        30:'GUEST_DISK_30_GB_SAN',
        40:'GUEST_DISK_40_GB_SAN',
        50:'GUEST_DISK_50_GB_SAN',
        75:'GUEST_DISK_75_GB_SAN',
        100:'GUEST_DISK_100_GB_SAN_3',
        125:'GUEST_DISK_125_GB_SAN',
        150:'GUEST_DISK_150_GB_SAN',
        175:'GUEST_DISK_175_GB_SAN',
        200:'GUEST_DISK_200_GB_SAN',
        250:'GUEST_DISK_250_GB_SAN',
        300:'GUEST_DISK_300_GB_SAN',
        350:'GUEST_DISK_350_GB_SAN',
        400:'GUEST_DISK_400_GB_SAN',
        500:'GUEST_DISK_500_GB_SAN',
        750:'GUEST_DISK_750_GB_SAN_2',
        1000:'GUEST_DISK_1000_GB_SAN_2',
        1500:'GUEST_DISK_1500_GB_SAN',
        2000:'GUEST_DISK_2000_GB_SAN'
    }
}

class Server_Manager(VSManager):
    def __init__(self, client):
        super(Server_Manager, self).__init__(client)
        self.sl_virtual_guest = client['Virtual_Guest']
        self.sl_virtual_disk_image = client['Virtual_Disk_Image']
        self.sl_software_component = client['Software_Component']
    def get_disk_local_flag(self, instance_id):
        block_devices = self.sl_virtual_guest.getBlockDevices(id=instance_id)
        local_flag = False
        for device in block_devices:
            if device['device'] == 0:
                local_flag = self.sl_virtual_disk_image.getLocalDiskFlag(id=device['diskImageId'])
            else:
                continue

        return local_flag

    def disk_upgrade(self, instance_id, disk_upgrade_config):
        disk_type = 'LOCAL' if self.get_disk_local_flag(instance_id) else 'SAN'

        for volume in disk_upgrade_config:
            if volume not in none_first_disk_list[disk_type.lower()]:
                raise AttributeError('Invalid disk volume')

        mask = [
            'id',
            'billingItem[id, package[id, items[softwareDescriptionId, id, keyName, itemCategory[name], prices[id]]]]'
        ]
        items_list = self.sl_virtual_guest.getObject(id=instance_id, mask="mask[%s]" % ','.join(mask))['billingItem']['package']['items']
        prices = []
        for disk_volume in disk_upgrade_config:
            disk_keyName = none_first_disk_list[disk_type.lower()][disk_volume]
            for item in items_list:
                if item['keyName'] == disk_keyName and item['itemCategory']['name'] == 'Second Disk':
                    prices.append({'id': item['prices'][0]['id']})

        maintenance_window = datetime.datetime.now(utils.UTC())
        order = {
            'complexType': 'SoftLayer_Container_Product_Order_Virtual_Guest_'
                           'Upgrade',
            'prices': prices,
            'properties': [{
                'name': 'MAINTENANCE_WINDOW',
                'value': maintenance_window.strftime("%Y-%m-%d %H:%M:%S%z")
            }],
            'virtualGuests': [{'id': int(instance_id)}],
        }
        if prices:
            self.client['Product_Order'].placeOrder(order)
            return True

        return False

client = SoftLayer.create_client_from_env(username="XXX",api_key="XXXX")
server_mgt = Server_Manager(client)
disk_upgrade_config = [25, 30]
server_mgt.disk_upgrade(17732233, disk_upgrade_config)

It got an exception:

SoftLayerAPIError(SoftLayer_Exception_Public): Unable to add 30 GB (SAN) because a Second Disk price has already been added.

It seem that the error raises as virtual guest has a second already, but how could I upgrade a portable storage?

1

1 Answers

0
votes
  • All the items that you upgraded in your server would be canceled, for example, if you upgrade the hard disks all of them will be canceled when you cancel the billing item from the VSI.

  • In case that you have a Portable Storage which was ordered by separated, and you attached it to the server, The Control Portalprovides an option to cancel the server and this portable storage at once, but in the case that you want to try by API, you should cancel billing item from the VSI and create a standard ticket to cancel the Portable Storage.

  • For Block and File Storage, if you cancel the VSI, these storage objects will be detached from the VSI, there is no option to cancel them with the Server at once.

Updated

There is an issue at the moment to send prices, you need to specify "categories" property for each item price,

Here a a example that you need to send:

 order = {
        'complexType': 'SoftLayer_Container_Product_Order_Virtual_Guest_'
                       'Upgrade',
         'prices': [{'id': 2257, 'categories':[{'id': 82, 'name':'Second Disk', 'categoryCode': 'guest_disk2'}]},
                    {'id': 21861, 'categories':[{'id': 92, 'name':'Third Disk', 'categoryCode': 'guest_disk3'}]}],
        'properties': [{
            'name': 'MAINTENANCE_WINDOW',
            'value': maintenance_window.strftime("%Y-%m-%d %H:%M:%S%z")
        }],
        'virtualGuests': [{'id': int(instance_id)}],