Ejemplo n.º 1
0
def _get_bandwidth_key(items, hourly=True, no_public=False, location=None):
    """Picks a valid Bandwidth Item, returns the KeyName"""

    keyName = None
    # 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

        keyName = item['keyName']
        for price in item['prices']:
            if not _matches_billing(price, hourly):
                continue
            if not _matches_location(price, location):
                continue
            return keyName

    raise SoftLayerError("Could not find valid price for bandwidth option")
Ejemplo n.º 2
0
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 SoftLayerError("Could not find valid location for: '%s'" % location)
Ejemplo n.º 3
0
    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 SoftLayerError("Could not find valid item for: '%s'" % flavor)
Ejemplo n.º 4
0
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 SoftLayerError("Could not find valid size for: '%s'" % size)
Ejemplo n.º 5
0
    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 SoftLayerError("Could not find valid price")
Ejemplo n.º 6
0
    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 SoftLayerError("Could not find valid location for: '%s'" %
                             datacenter)
Ejemplo n.º 7
0
    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 SoftLayerError("Could not find valid default router")
Ejemplo n.º 8
0
    def _get_id_from_username(self, username):
        """Looks up a username's id

        :param string username: Username to lookup
        :returns: The id that matches username.
        """
        _mask = "mask[id,username]"
        _filter = {
            'hubNetworkStorage': {
                'username': utils.query_filter(username)
            }
        }
        account = self.list_accounts(_mask, _filter)
        if len(account) == 1:
            return [account[0]['id']]
        elif len(account) > 1:
            raise SoftLayerError(
                "Multiple object storage accounts found with the name: {}".
                format(username))
        else:
            raise SoftLayerError(
                "Unable to find object storage account id for: {}".format(
                    username))
Ejemplo n.º 9
0
    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 as ex:
            raise SoftLayerError("Unable to find capacity Flavor.") from ex

        guest_object['flavor'] = flavor
        guest_object['datacenter'] = capacity['backendRouter']['datacenter'][
            'name']

        # Reserved capacity only supports SAN as of 20181008
        guest_object['local_disk'] = False
        # Reserved capacity only supports monthly ordering via Virtual_Guest::generateOrderTemplate
        # Hourly ordering would require building out the order manually.
        guest_object['hourly'] = 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
Ejemplo n.º 10
0
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 SoftLayerError("Could not find valid price for os: '%s'" % os)
Ejemplo n.º 11
0
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 SoftLayerError("Could not find valid price for '%s' option" % option)
Ejemplo n.º 12
0
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 SoftLayerError("Could not find valid price for extra option, '%s'" %
                         key_name)
Ejemplo n.º 13
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 SoftLayerError("Could not find valid price for port speed: '%s'" %
                         port_speed)
Ejemplo n.º 14
0
    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 = 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 SoftLayerError(
                "Unable to cancel hardware with running transaction")

        if 'billingItem' not in hw_billing:
            if utils.lookup(hw_billing, 'openCancellationTicket', 'id'):
                raise SoftLayerError(
                    "Ticket #%s already exists for this server" %
                    hw_billing['openCancellationTicket']['id'])
            raise 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
Ejemplo n.º 15
0
    def get_create_options(self, datacenter=None):
        """Returns valid options for ordering hardware.

        :param string datacenter: short name, like dal09
        """

        package = self._get_package()

        location_group_id = None
        if datacenter:
            _filter = {"name": {"operation": datacenter}}
            _mask = "mask[priceGroups]"
            dc_details = self.client.call('SoftLayer_Location',
                                          'getDatacenters',
                                          mask=_mask,
                                          filter=_filter,
                                          limit=1)
            if not dc_details:
                raise SoftLayerError(
                    "Unable to find a datacenter named {}".format(datacenter))
            # A DC will have several price groups, no good way to deal with this other than checking each.
            # An item should only belong to one type of price group.
            for group in dc_details[0].get('priceGroups', []):
                # We only care about SOME of the priceGroups, which all SHOULD start with `Location Group X`
                # Hopefully this never changes....
                if group.get('description').startswith('Location'):
                    location_group_id = group.get('id')

        # Locations
        locations = []
        for region in package['regions']:
            if datacenter is None or datacenter == region['location'][
                    'location']['name']:
                locations.append({
                    'name':
                    region['location']['location']['longName'],
                    'key':
                    region['location']['location']['name'],
                })
        # Sizes
        sizes = []
        for preset in package['activePresets'] + package[
                'accountRestrictedActivePresets']:
            sizes.append({
                'name':
                preset['description'],
                'key':
                preset['keyName'],
                'hourlyRecurringFee':
                _get_preset_cost(preset, package['items'], 'hourly',
                                 location_group_id),
                'recurringFee':
                _get_preset_cost(preset, package['items'], 'monthly',
                                 location_group_id)
            })

        operating_systems = []
        port_speeds = []
        extras = []
        for item in package['items']:
            category = item['itemCategory']['categoryCode']
            # Operating systems
            if category == 'os':
                operating_systems.append({
                    'name':
                    item['softwareDescription']['longDescription'],
                    'key':
                    item['keyName'],
                    'referenceCode':
                    item['softwareDescription']['referenceCode'],
                    'prices':
                    get_item_price(item['prices'], location_group_id)
                })
            # Port speeds
            elif category == 'port_speed':
                port_speeds.append({
                    'name':
                    item['description'],
                    'speed':
                    item['capacity'],
                    'key':
                    item['keyName'],
                    'prices':
                    get_item_price(item['prices'], location_group_id)
                })
            # Extras
            elif category in EXTRA_CATEGORIES:
                extras.append({
                    'name':
                    item['description'],
                    'key':
                    item['keyName'],
                    'prices':
                    get_item_price(item['prices'], location_group_id)
                })

        return {
            'locations': locations,
            'sizes': sizes,
            'operating_systems': operating_systems,
            'port_speeds': port_speeds,
            'extras': extras,
        }
Ejemplo n.º 16
0
    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 SoftLayerError("Could not find available routers")