def cancel_hardware(self, hardware_id, reason='unneeded', comment='', immediate=False): """Cancels the specified dedicated server. Example:: # Cancels hardware id 1234 result = mgr.cancel_hardware(hardware_id=1234) :param int hardware_id: The ID of the hardware to be cancelled. :param string reason: The reason code for the cancellation. This should come from :func:`get_cancellation_reasons`. :param string comment: An optional comment to include with the cancellation. :param bool immediate: If set to True, will automatically update the cancelation ticket to request the resource be reclaimed asap. This request still has to be reviewed by a human :returns: True on success or an exception """ # Get cancel reason reasons = self.get_cancellation_reasons() cancel_reason = reasons.get(reason, reasons['unneeded']) ticket_mgr = SoftLayer.TicketManager(self.client) mask = 'mask[id, hourlyBillingFlag, billingItem[id], openCancellationTicket[id], activeTransaction]' hw_billing = self.get_hardware(hardware_id, mask=mask) if 'activeTransaction' in hw_billing: raise SoftLayer.SoftLayerError("Unable to cancel hardware with running transaction") if 'billingItem' not in hw_billing: if utils.lookup(hw_billing, 'openCancellationTicket', 'id'): raise SoftLayer.SoftLayerError("Ticket #%s already exists for this server" % hw_billing['openCancellationTicket']['id']) raise SoftLayer.SoftLayerError("Cannot locate billing for the server. " "The server may already be cancelled.") billing_id = hw_billing['billingItem']['id'] if immediate and not hw_billing['hourlyBillingFlag']: LOGGER.warning("Immediate cancellation of monthly servers is not guaranteed." "Please check the cancellation ticket for updates.") result = self.client.call('Billing_Item', 'cancelItem', False, False, cancel_reason, comment, id=billing_id) hw_billing = self.get_hardware(hardware_id, mask=mask) ticket_number = hw_billing['openCancellationTicket']['id'] cancel_message = "Please reclaim this server ASAP, it is no longer needed. Thankyou." ticket_mgr.update_ticket(ticket_number, cancel_message) LOGGER.info("Cancelation ticket #%s has been updated requesting immediate reclaim", ticket_number) else: result = self.client.call('Billing_Item', 'cancelItem', immediate, False, cancel_reason, comment, id=billing_id) hw_billing = self.get_hardware(hardware_id, mask=mask) ticket_number = hw_billing['openCancellationTicket']['id'] LOGGER.info("Cancelation ticket #%s has been created", ticket_number) return result
def _get_backend_router(self, locations, item): """Returns valid router options for ordering a dedicated host.""" mask = ''' id, hostname ''' cpu_count = item['capacity'] for capacity in item['bundleItems']: for category in capacity['categories']: if category['categoryCode'] == 'dedicated_host_ram': mem_capacity = capacity['capacity'] if category['categoryCode'] == 'dedicated_host_disk': disk_capacity = capacity['capacity'] if locations is not None: for location in locations: if location['locationId'] is not None: loc_id = location['locationId'] host = { 'cpuCount': cpu_count, 'memoryCapacity': mem_capacity, 'diskCapacity': disk_capacity, 'datacenter': { 'id': loc_id } } routers = self.host.getAvailableRouters(host, mask=mask) return routers raise SoftLayer.SoftLayerError("Could not find available routers")
def _get_location(package, location): """Get the longer key with a short location name.""" for region in package['regions']: if region['location']['location']['name'] == location: return region raise SoftLayer.SoftLayerError("Could not find valid location for: '%s'" % location)
def cancel_hardware(self, hardware_id, reason='unneeded', comment='', immediate=False): """Cancels the specified dedicated server. Example:: # Cancels hardware id 1234 result = mgr.cancel_hardware(hardware_id=1234) :param int hardware_id: The ID of the hardware to be cancelled. :param string reason: The reason code for the cancellation. This should come from :func:`get_cancellation_reasons`. :param string comment: An optional comment to include with the cancellation. """ # Get cancel reason reasons = self.get_cancellation_reasons() cancel_reason = reasons.get(reason, reasons['unneeded']) hw_billing = self.get_hardware(hardware_id, mask='mask[id, billingItem.id]') if 'billingItem' not in hw_billing: raise SoftLayer.SoftLayerError( "No billing item found for hardware") billing_id = hw_billing['billingItem']['id'] return self.client.call('Billing_Item', 'cancelItem', immediate, False, cancel_reason, comment, id=billing_id)
def _get_preset_id(package, size): """Get the preset id given the keyName of the preset.""" for preset in package['activePresets'] + package['accountRestrictedActivePresets']: if preset['keyName'] == size or preset['id'] == size: return preset['id'] raise SoftLayer.SoftLayerError("Could not find valid size for: '%s'" % size)
def _get_bandwidth_price_id(items, hourly=True, no_public=False, location=None): """Choose a valid price id for bandwidth.""" # Prefer pay-for-use data transfer with hourly for item in items: capacity = float(item.get('capacity', 0)) # Hourly and private only do pay-as-you-go bandwidth if any([ utils.lookup(item, 'itemCategory', 'categoryCode') != 'bandwidth', (hourly or no_public) and capacity != 0.0, not (hourly or no_public) and capacity == 0.0 ]): continue for price in item['prices']: if not _matches_billing(price, hourly): continue if not _matches_location(price, location): continue return price['id'] raise SoftLayer.SoftLayerError( "Could not find valid price for bandwidth option")
def _get_price(self, package): """Returns valid price for ordering a dedicated host.""" for price in package['prices']: if not price.get('locationGroupId'): return price['id'] raise SoftLayer.SoftLayerError("Could not find valid price")
def _get_item(self, package, flavor): """Returns the item for ordering a dedicated host.""" for item in package['items']: if item['keyName'] == flavor: return item raise SoftLayer.SoftLayerError("Could not find valid item for: '%s'" % flavor)
def _get_location(self, regions, datacenter): """Get the longer key with a short location(datacenter) name.""" for region in regions: # list of locations if region['location']['location']['name'] == datacenter: return region raise SoftLayer.SoftLayerError( "Could not find valid location for: '%s'" % datacenter)
def _get_default_router(self, routers, router_name=None): """Returns the default router for ordering a dedicated host.""" if router_name is None: for router in routers: if router['id'] is not None: return router['id'] else: for router in routers: if router['hostname'] == router_name: return router['id'] raise SoftLayer.SoftLayerError("Could not find valid default router")
def _get_default_price_id(items, option, hourly, location): """Returns a 'free' price id given an option.""" for item in items: if utils.lookup(item, 'itemCategory', 'categoryCode') != option: continue for price in item['prices']: if all([float(price.get('hourlyRecurringFee', 0)) == 0.0, float(price.get('recurringFee', 0)) == 0.0, _matches_billing(price, hourly), _matches_location(price, location)]): return price['id'] raise SoftLayer.SoftLayerError( "Could not find valid price for '%s' option" % option)
def create_guest(self, capacity_id, test, guest_object): """Turns an empty Reserve Capacity into a real Virtual Guest :param int capacity_id: ID of the RESERVED_CAPACITY_GROUP to create this guest into :param bool test: True will use verifyOrder, False will use placeOrder :param dictionary guest_object: Below is the minimum info you need to send in guest_object = { 'domain': 'test.com', 'hostname': 'A1538172419', 'os_code': 'UBUNTU_LATEST_64', 'primary_disk': '25', } """ vs_manager = VSManager(self.client) mask = "mask[instances[id, billingItem[id, item[id,keyName]]], backendRouter[id, datacenter[name]]]" capacity = self.get_object(capacity_id, mask=mask) try: capacity_flavor = capacity['instances'][0]['billingItem']['item'][ 'keyName'] flavor = _flavor_string(capacity_flavor, guest_object['primary_disk']) except KeyError: raise SoftLayer.SoftLayerError("Unable to find capacity Flavor.") guest_object['flavor'] = flavor guest_object['datacenter'] = capacity['backendRouter']['datacenter'][ 'name'] # Reserved capacity only supports SAN as of 20181008 guest_object['local_disk'] = False template = vs_manager.verify_create_instance(**guest_object) template['reservedCapacityId'] = capacity_id if guest_object.get('ipv6'): ipv6_price = self.ordering_manager.get_price_id_list( 'PUBLIC_CLOUD_SERVER', ['1_IPV6_ADDRESS']) template['prices'].append({'id': ipv6_price[0]}) if test: result = self.client.call('Product_Order', 'verifyOrder', template) else: result = self.client.call('Product_Order', 'placeOrder', template) return result
def _get_extra_price_id(items, key_name, hourly, location): """Returns a price id attached to item with the given key_name.""" for item in items: if utils.lookup(item, 'keyName') != key_name: continue for price in item['prices']: if not _matches_billing(price, hourly): continue if not _matches_location(price, location): continue return price['id'] raise SoftLayer.SoftLayerError( "Could not find valid price for extra option, '%s'" % key_name)
def _get_os_price_id(items, os, location): """Returns the price id matching.""" for item in items: if any([ utils.lookup(item, 'itemCategory', 'categoryCode') != 'os', utils.lookup(item, 'keyName') != os ]): continue for price in item['prices']: if not _matches_location(price, location): continue return price['id'] raise SoftLayer.SoftLayerError("Could not find valid price for os: '%s'" % os)
def _get_package(self): """Get the package related to simple hardware ordering.""" mask = ''' items[ keyName, capacity, description, attributes[id,attributeTypeKeyName], itemCategory[id,categoryCode], softwareDescription[id,referenceCode,longDescription], prices ], activePresets, regions[location[location[priceGroups]]] ''' package_keyname = 'BARE_METAL_SERVER' package = self.ordering_manager.get_package_by_key(package_keyname, mask=mask) if package is None: raise SoftLayer.SoftLayerError("Ordering package not found") return package
def _get_package(self): """Get the package related to simple hardware ordering.""" mask = ''' items[ keyName, capacity, description, attributes[id,attributeTypeKeyName], itemCategory[id,categoryCode], softwareDescription[id,referenceCode,longDescription], prices ], activePresets, regions[location[location[priceGroups]]] ''' package_type = 'BARE_METAL_CPU_FAST_PROVISION' packages = self.ordering_manager.get_packages_of_type([package_type], mask=mask) if len(packages) != 1: raise SoftLayer.SoftLayerError("Ordering package not found") return packages[0]
def _get_port_speed_price_id(items, port_speed, no_public, location): """Choose a valid price id for port speed.""" for item in items: if utils.lookup(item, 'itemCategory', 'categoryCode') != 'port_speed': continue # Check for correct capacity and if the item matches private only if any([ int(utils.lookup(item, 'capacity')) != port_speed, _is_private_port_speed_item(item) != no_public, not _is_bonded(item) ]): continue for price in item['prices']: if not _matches_location(price, location): continue return price['id'] raise SoftLayer.SoftLayerError( "Could not find valid price for port speed: '%s'" % port_speed)
def _get_package(self): """Get the package related to simple dedicated host ordering.""" mask = ''' items[ id, description, prices, capacity, keyName, itemCategory[categoryCode], bundleItems[capacity, categories[categoryCode]] ], regions[location[location[priceGroups]]] ''' package_keyname = 'DEDICATED_HOST' package = self.ordering_manager.get_package_by_key(package_keyname, mask=mask) if package is None: raise SoftLayer.SoftLayerError("Ordering package not found") return package
def _get_backend_router(self, locations, item): """Returns valid router options for ordering a dedicated host.""" mask = ''' id, hostname ''' cpu_count = item['capacity'] for capacity in item['bundleItems']: for category in capacity['categories']: if category['categoryCode'] == 'dedicated_host_ram': mem_capacity = capacity['capacity'] if category['categoryCode'] == 'dedicated_host_disk': disk_capacity = capacity['capacity'] for hardwareComponent in item['bundleItems']: if hardwareComponent['keyName'].find("GPU") != -1: hardwareComponentType = hardwareComponent[ 'hardwareGenericComponentModel']['hardwareComponentType'] gpuComponents = [{ 'hardwareComponentModel': { 'hardwareGenericComponentModel': { 'id': hardwareComponent['hardwareGenericComponentModel'] ['id'], 'hardwareComponentType': { 'keyName': hardwareComponentType['keyName'] } } } }, { 'hardwareComponentModel': { 'hardwareGenericComponentModel': { 'id': hardwareComponent['hardwareGenericComponentModel'] ['id'], 'hardwareComponentType': { 'keyName': hardwareComponentType['keyName'] } } } }] if locations is not None: for location in locations: if location['locationId'] is not None: loc_id = location['locationId'] host = { 'cpuCount': cpu_count, 'memoryCapacity': mem_capacity, 'diskCapacity': disk_capacity, 'datacenter': { 'id': loc_id } } if item['keyName'].find("GPU") != -1: host['pciDevices'] = gpuComponents routers = self.host.getAvailableRouters(host, mask=mask) return routers raise SoftLayer.SoftLayerError("Could not find available routers")