Facts
Consumers will have facts, provided when the consumer registers and requests
their UUID. These will contain all necessary data about that type of consumer,
CPU cores being the most common example used initially. This implies the
consumer client side code (potentially rhn_register) implicitly knows what
information it must gather and send to the server, although the server may not
use it all.
These attributes will likely need to be updated periodically.
Attributes
- Attributes can be thought of as a hint on some restriction on the usage of an
entitlement.
- They will not actually contain the logic on how to enforce the Attribute, but
basically just act as a constant the policy rules can look for, and a little
metadata that may be required to enforce.
- Attributes can be affiliated with a given product in the product database, or
they can be affiliated with entitlements granted within a particular
customer’s order/certificate.
- All Attributes must pass for the entitlement to be granted to a consumer. Not
sure if this statement will stand the test of time, may be some issues here
with “enabling” attributes vs “restricting” attributes and knowing when to
grant/not grant based on the outcome of multiple checks. Will see how it
goes.
- Attributes can be associated with a product, or more commonly with an order
of that product contained in the cert. For us, this probably means they’ll be
associated with entitlement pools in the database.
- If the same Attribute is found on both the product and the entitlement
pool, the entitlement pool’s version can be assumed as the authoritative
one to check.
Attribute Examples
- cpu-count NUM_CPUS
- Some kind of restriction on the number of CPUs.
- cpu-cores NUM_CPUS
- Some kind of restriction on the number of CPU cores.
- free-children NUM_CHILDREN
- Indicates NUM_CHILDREN child consumers can be entitled to this product as
well. (essentially for free, or rather included in the parent consumer’s
receiving the entitlement)
- I.e. if you have 10 entitlements to rhel-server with 5 max-free-children,
each physical system using an entitlement can have up to 5 guests also
subscribed to rhel-server without consuming one of the original 10
entitlements.
- If a child requested this entitlement, the parent already had 5 children
using rhel-server, entitlement would then consume one of the remaining 10
physical entitlements. (or fail if they were exhausted)
- This is one of the more tricky ones to represent in rules metadata as it’s
not a check against this consumer, but rather against the parent, and even
then involves a check for how many of the parents children already have
this product.
- max-guests
- Probably RHEL specific, a limitation on the number of virt guests allowed
on the host.
- Note difference with free-children entitlements to a product.
- max-version VERSION
- Max version of the product this entitlement is valid for.
- min-version VERSION
- max-ram RAM
- Entitlement can only be consumed by a system with less than or equal to
some amount of memory.
- consumer-type TYPE
- Limit this entitlement to only be given to consumers of a particular type.
- Could be a more flexible than the max-children idea above.
- architecture ARCH
- Entitlement only valid for given architecture.
- May need to specify multiple, which could be complicated if we assume all
Attribute tests must pass for a given consumer to be entitled.
- flex-consumption FLEX
- Allow entitlement even if over assigned quantity by some amount. (%age,
actual number, etc.)
- Ideally this would also know to warn if over quantity but granted by virtue
of being within the flex range.
- Is this a better fit if moved onto attributes themselves? I.e. every
attribute can specify a flex range in which the entitlement will still be
granted, but with a warning.
Policy
- Policy maps Attributes to the checks run against the attributes on a consumer
to determine if they can consume this entitlement or not.
- Policy will also define the flexibility around use of entitlements, and what
leeway we grant a customer if they run over.
- Policy will be pluggable, and can be updated in the future to accommodate new
Attributes, or just new ways of enforcing the existing ones.
- The actual implementation of the policy will also need to be pluggable.
Initial implementation will probably be a homebrew mix of YAML/json and a
custom rule parser. In the future we may want to implement a more robust
rules engine.
- Policy will assume an implicit quantity check.
- Results of this may be affected by the presence of a flex attribute.
Javascript Policy Engine
Proposed plan for leveraging the scripting language additions to Java 6.
- Assume a push model as with certificate uploads, and expose a REST method
which allows for the upload of new rules.
- We’re assuming these rules are one day distributed from some centralized
location.
- Assume whatever products are using Candlepin will be responsible for
scheduling these updates.
- Alternatively we can provide a small script that can be run via cron to
fetch new rules.
- Rules will be distributed and interpreted as Javascript.
- Design some restrictive read-only objects inside the Candlepin Java code
allowing access to objects such as the consumer (its type, facts,
entitlements, parent) and the product (its type, attributes, etc).
- Make these objects available to the Javascript engine.
- In the future, the rules will be verified for a valid GPG signature.
Sample Javascript, product specific checks are specified by a function matching the product label:
function virtualization_host() {
// Only physical servers can consume, and they must have no guests currently:
if (consumer.type == "server" && parseInt(consumer.fact["guest_count"]) == 0) {
return true;
}
// TODO: How to specify the post-entitlement actions, in this case something like:
// create-consumer-pool virt_guest 5
}
function rhel_5_server() {
// Guests can always get this if their parent has an entitlement
if (consumer.type == "virt_guest" && consumer.parent.has_entitlement("virtualization_host")) {
return true;
}
// Physical servers must have less than 8 cores, order defined this limitation
if (consumer.type == "server" && parseInt(consumer.fact["cpu_cores"]) <= order.attribute['max_cpus']) {
return true;
}
return false;
}
Outstanding Issues
- If a customer has multiple types of an entitlement for one product, when a consumer requests to be entitled, how do we know which type of entitlement to consume?
Last modified on 24 September 2024