Example #1
0
def licenses_configured(name, licenses=None):
    '''
    Configures licenses on the cluster entity

    Checks if each license exists on the server:
        - if it doesn't, it creates it
    Check if license is assigned to the cluster:
        - if it's not assigned to the cluster:
            - assign it to the cluster if there is space
            - error if there's no space
        - if it's assigned to the cluster nothing needs to be done
    '''
    ret = {'name': name, 'changes': {}, 'result': None, 'comment': 'Default'}
    if not licenses:
        raise salt.exceptions.ArgumentValueError('No licenses provided')
    cluster_name, datacenter_name = \
            __salt__['esxcluster.get_details']()['cluster'], \
            __salt__['esxcluster.get_details']()['datacenter']
    display_name = '{0}/{1}'.format(datacenter_name, cluster_name)
    log.info('Running licenses configured for \'%s\'', display_name)
    log.trace('licenses = %s', licenses)
    entity = {
        'type': 'cluster',
        'datacenter': datacenter_name,
        'cluster': cluster_name
    }
    log.trace('entity = %s', entity)

    comments = []
    changes = {}
    old_licenses = []
    new_licenses = []
    has_errors = False
    needs_changes = False
    try:
        # Validate licenses
        log.trace('Validating licenses')
        schema = LicenseSchema.serialize()
        try:
            jsonschema.validate({'licenses': licenses}, schema)
        except jsonschema.exceptions.ValidationError as exc:
            raise salt.exceptions.InvalidLicenseError(exc)

        si = __salt__['vsphere.get_service_instance_via_proxy']()
        # Retrieve licenses
        existing_licenses = __salt__['vsphere.list_licenses'](
            service_instance=si)
        remaining_licenses = existing_licenses[:]
        # Cycle through licenses
        for license_name, license in licenses.items():
            # Check if license already exists
            filtered_licenses = [
                l for l in existing_licenses if l['key'] == license
            ]
            # TODO Update license description - not of interest right now
            if not filtered_licenses:
                # License doesn't exist - add and assign to cluster
                needs_changes = True
                if __opts__['test']:
                    # If it doesn't exist it clearly needs to be assigned as
                    # well so we can stop the check here
                    comments.append('State {0} will add license \'{1}\', '
                                    'and assign it to cluster \'{2}\'.'
                                    ''.format(name, license_name,
                                              display_name))
                    log.info(comments[-1])
                    continue
                else:
                    try:
                        existing_license = __salt__['vsphere.add_license'](
                            key=license,
                            description=license_name,
                            service_instance=si)
                    except salt.exceptions.VMwareApiError as ex:
                        comments.append(ex.err_msg)
                        log.error(comments[-1])
                        has_errors = True
                        continue
                    comments.append('Added license \'{0}\'.'
                                    ''.format(license_name))
                    log.info(comments[-1])
            else:
                # License exists let's check if it's assigned to the cluster
                comments.append('License \'{0}\' already exists. '
                                'Nothing to be done.'.format(license_name))
                log.info(comments[-1])
                existing_license = filtered_licenses[0]

            log.trace('Checking licensed entities...')
            assigned_licenses = __salt__['vsphere.list_assigned_licenses'](
                entity=entity,
                entity_display_name=display_name,
                service_instance=si)

            # Checking if any of the licenses already assigned have the same
            # name as the new license; the already assigned license would be
            # replaced by the new license
            #
            # Licenses with different names but matching features would be
            # replaced as well, but searching for those would be very complex
            #
            # the name check if good enough for now
            already_assigned_license = assigned_licenses[0] if \
                    assigned_licenses else None

            if already_assigned_license and \
               already_assigned_license['key'] == license:

                # License is already assigned to entity
                comments.append('License \'{0}\' already assigned to '
                                'cluster \'{1}\'. Nothing to be done.'
                                ''.format(license_name, display_name))
                log.info(comments[-1])
                continue

            needs_changes = True
            # License needs to be assigned to entity

            if existing_license['capacity'] <= existing_license['used']:
                # License is already fully used
                comments.append('Cannot assign license \'{0}\' to cluster '
                                '\'{1}\'. No free capacity available.'
                                ''.format(license_name, display_name))
                log.error(comments[-1])
                has_errors = True
                continue

            # Assign license
            if __opts__['test']:
                comments.append('State {0} will assign license \'{1}\' '
                                'to cluster \'{2}\'.'.format(
                                    name, license_name, display_name))
                log.info(comments[-1])
            else:
                try:
                    __salt__['vsphere.assign_license'](
                        license_key=license,
                        license_name=license_name,
                        entity=entity,
                        entity_display_name=display_name,
                        service_instance=si)
                except salt.exceptions.VMwareApiError as ex:
                    comments.append(ex.err_msg)
                    log.error(comments[-1])
                    has_errors = True
                    continue
                comments.append('Assigned license \'{0}\' to cluster \'{1}\'.'
                                ''.format(license_name, display_name))
                log.info(comments[-1])
                # Note: Because the already_assigned_license was retrieved
                # from the assignment license manager it doesn't have a used
                # value - that's a limitation from VMware. The license would
                # need to be retrieved again from the license manager to get
                # the value

                # Hide license keys
                assigned_license = __salt__['vsphere.list_assigned_licenses'](
                    entity=entity,
                    entity_display_name=display_name,
                    service_instance=si)[0]
                assigned_license['key'] = '<hidden>'
                if already_assigned_license:
                    already_assigned_license['key'] = '<hidden>'
                if already_assigned_license and \
                   already_assigned_license['capacity'] == sys.maxsize:

                    already_assigned_license['capacity'] = 'Unlimited'

                changes[license_name] = {
                    'new': assigned_license,
                    'old': already_assigned_license
                }
            continue
        __salt__['vsphere.disconnect'](si)

        ret.update({
            'result':
            True if (not needs_changes) else
            None if __opts__['test'] else False if has_errors else True,
            'comment':
            '\n'.join(comments),
            'changes':
            changes if not __opts__['test'] else {}
        })

        return ret
    except salt.exceptions.CommandExecutionError as exc:
        log.exception('Encountered error')
        if si:
            __salt__['vsphere.disconnect'](si)
        ret.update({'result': False, 'comment': exc.strerror})
        return ret
Example #2
0
    log.trace('licenses = %s', licenses)
    entity = {'type': 'cluster',
              'datacenter': datacenter_name,
              'cluster': cluster_name}
    log.trace('entity = %s', entity)

    comments = []
    changes = {}
    old_licenses = []
    new_licenses = []
    has_errors = False
    needs_changes = False
    try:
        # Validate licenses
        log.trace("Validating licenses")
        schema = LicenseSchema.serialize()
        try:
            jsonschema.validate({"licenses": licenses}, schema)
        except jsonschema.exceptions.ValidationError as exc:
            raise salt.exceptions.InvalidLicenseError(exc)

        si = __salt__["vsphere.get_service_instance_via_proxy"]()
        # Retrieve licenses
        existing_licenses = __salt__["vsphere.list_licenses"](service_instance=si)
        remaining_licenses = existing_licenses[:]
        # Cycle through licenses
        for license_name, license in licenses.items():
            # Check if license already exists
            filtered_licenses = [l for l in existing_licenses if l["key"] == license]
            # TODO Update license description - not of interest right now
            if not filtered_licenses:
Example #3
0
def licenses_configured(name, licenses=None):
    """
    Configures licenses on the cluster entity

    Checks if each license exists on the server:
        - if it doesn't, it creates it
    Check if license is assigned to the cluster:
        - if it's not assigned to the cluster:
            - assign it to the cluster if there is space
            - error if there's no space
        - if it's assigned to the cluster nothing needs to be done
    """
    ret = {"name": name, "changes": {}, "result": None, "comment": "Default"}
    if not licenses:
        raise salt.exceptions.ArgumentValueError("No licenses provided")
    cluster_name, datacenter_name = (
        __salt__["esxcluster.get_details"]()["cluster"],
        __salt__["esxcluster.get_details"]()["datacenter"],
    )
    display_name = "{0}/{1}".format(datacenter_name, cluster_name)
    log.info("Running licenses configured for '{0}'".format(display_name))
    log.trace("licenses = {0}".format(licenses))
    entity = {
        "type": "cluster",
        "datacenter": datacenter_name,
        "cluster": cluster_name
    }
    log.trace("entity = {0}".format(entity))

    comments = []
    changes = {}
    old_licenses = []
    new_licenses = []
    has_errors = False
    needs_changes = False
    try:
        # Validate licenses
        log.trace("Validating licenses")
        schema = LicenseSchema.serialize()
        try:
            jsonschema.validate({"licenses": licenses}, schema)
        except jsonschema.exceptions.ValidationError as exc:
            raise salt.exceptions.InvalidLicenseError(exc)

        si = __salt__["vsphere.get_service_instance_via_proxy"]()
        # Retrieve licenses
        existing_licenses = __salt__["vsphere.list_licenses"](
            service_instance=si)
        remaining_licenses = existing_licenses[:]
        # Cycle through licenses
        for license_name, license in licenses.items():
            # Check if license already exists
            filtered_licenses = [
                l for l in existing_licenses if l["key"] == license
            ]
            # TODO Update license description - not of interest right now
            if not filtered_licenses:
                # License doesn't exist - add and assign to cluster
                needs_changes = True
                if __opts__["test"]:
                    # If it doesn't exist it clearly needs to be assigned as
                    # well so we can stop the check here
                    comments.append("State {0} will add license '{1}', "
                                    "and assign it to cluster '{2}'."
                                    "".format(name, license_name,
                                              display_name))
                    log.info(comments[-1])
                    continue
                else:
                    try:
                        existing_license = __salt__["vsphere.add_license"](
                            key=license,
                            description=license_name,
                            service_instance=si)
                    except salt.exceptions.VMwareApiError as ex:
                        comments.append(ex.err_msg)
                        log.error(comments[-1])
                        has_errors = True
                        continue
                    comments.append("Added license '{0}'."
                                    "".format(license_name))
                    log.info(comments[-1])
            else:
                # License exists let's check if it's assigned to the cluster
                comments.append("License '{0}' already exists. "
                                "Nothing to be done.".format(license_name))
                log.info(comments[-1])
                existing_license = filtered_licenses[0]

            log.trace("Checking licensed entities...")
            assigned_licenses = __salt__["vsphere.list_assigned_licenses"](
                entity=entity,
                entity_display_name=display_name,
                service_instance=si)

            # Checking if any of the licenses already assigned have the same
            # name as the new license; the already assigned license would be
            # replaced by the new license
            #
            # Licenses with different names but matching features would be
            # replaced as well, but searching for those would be very complex
            #
            # the name check if good enough for now
            already_assigned_license = (assigned_licenses[0]
                                        if assigned_licenses else None)

            if already_assigned_license and already_assigned_license[
                    "key"] == license:

                # License is already assigned to entity
                comments.append("License '{0}' already assigned to "
                                "cluster '{1}'. Nothing to be done."
                                "".format(license_name, display_name))
                log.info(comments[-1])
                continue

            needs_changes = True
            # License needs to be assigned to entity

            if existing_license["capacity"] <= existing_license["used"]:
                # License is already fully used
                comments.append("Cannot assign license '{0}' to cluster "
                                "'{1}'. No free capacity available."
                                "".format(license_name, display_name))
                log.error(comments[-1])
                has_errors = True
                continue

            # Assign license
            if __opts__["test"]:
                comments.append("State {0} will assign license '{1}' "
                                "to cluster '{2}'.".format(
                                    name, license_name, display_name))
                log.info(comments[-1])
            else:
                try:
                    __salt__["vsphere.assign_license"](
                        license_key=license,
                        license_name=license_name,
                        entity=entity,
                        entity_display_name=display_name,
                        service_instance=si,
                    )
                except salt.exceptions.VMwareApiError as ex:
                    comments.append(ex.err_msg)
                    log.error(comments[-1])
                    has_errors = True
                    continue
                comments.append("Assigned license '{0}' to cluster '{1}'."
                                "".format(license_name, display_name))
                log.info(comments[-1])
                # Note: Because the already_assigned_license was retrieved
                # from the assignment license manager it doesn't have a used
                # value - that's a limitation from VMware. The license would
                # need to be retrieved again from the license manager to get
                # the value

                # Hide license keys
                assigned_license = __salt__["vsphere.list_assigned_licenses"](
                    entity=entity,
                    entity_display_name=display_name,
                    service_instance=si)[0]
                assigned_license["key"] = "<hidden>"
                if already_assigned_license:
                    already_assigned_license["key"] = "<hidden>"
                if (already_assigned_license and
                        already_assigned_license["capacity"] == sys.maxsize):

                    already_assigned_license["capacity"] = "Unlimited"

                changes[license_name] = {
                    "new": assigned_license,
                    "old": already_assigned_license,
                }
            continue
        __salt__["vsphere.disconnect"](si)

        ret.update({
            "result":
            True if (not needs_changes) else
            None if __opts__["test"] else False if has_errors else True,
            "comment":
            "\n".join(comments),
            "changes":
            changes if not __opts__["test"] else {},
        })

        return ret
    except salt.exceptions.CommandExecutionError as exc:
        log.error("Error: {0}\n{1}".format(exc, traceback.format_exc()))
        if si:
            __salt__["vsphere.disconnect"](si)
        ret.update({"result": False, "comment": exc.strerror})
        return ret