From 65f0668475f97a4bef6b761d07bd5d0f8470b370 Mon Sep 17 00:00:00 2001 From: Kevin Howell Date: Fri, 12 May 2017 14:10:41 -0400 Subject: [PATCH] Add pool_ids option to redhat_subscription (#23266) --- .../packaging/os/redhat_subscription.py | 117 +++++++++++++++--- 1 file changed, 99 insertions(+), 18 deletions(-) diff --git a/lib/ansible/modules/packaging/os/redhat_subscription.py b/lib/ansible/modules/packaging/os/redhat_subscription.py index ca15f2ee4f..3ef66d6b5a 100644 --- a/lib/ansible/modules/packaging/os/redhat_subscription.py +++ b/lib/ansible/modules/packaging/os/redhat_subscription.py @@ -88,9 +88,21 @@ options: version_added: "2.2" pool: description: - - Specify a subscription pool name to consume. Regular expressions accepted. + - | + Specify a subscription pool name to consume. Regular expressions accepted. Use I(pool_ids) instead if + possible, as it is much faster. Mutually exclusive with I(pool_ids). required: False default: '^$' + pool_ids: + description: + - | + Specify subscription pool IDs to consume. Prefer over I(pool) when possible as it is much faster. + A pool ID may be specified as a C(string) - just the pool ID (ex. C(0123456789abcdef0123456789abcdef)), + or as a C(dict) with the pool ID as the key, and a quantity as the value (ex. + C(0123456789abcdef0123456789abcdef: 2). If the quantity is provided, it is used to consume multiple + entitlements from a pool (the pool must support this). Mutually exclusive with I(pool). + default: [] + version_added: "2.4" consumer_type: description: - The type of unit to register, defaults to system @@ -122,39 +134,61 @@ options: ''' EXAMPLES = ''' -# Register as user (joe_user) with password (somepass) and auto-subscribe to available content. -- redhat_subscription: +- name: Register as user (joe_user) with password (somepass) and auto-subscribe to available content. + redhat_subscription: state: present username: joe_user password: somepass autosubscribe: true -# Same as above but with pulling existing system data. -- redhat_subscription: +- name: Same as above but subscribe to a specific pool by ID. + redhat_subscription: + state: present + username: joe_user + password: somepass + pool_ids: 0123456789abcdef0123456789abcdef + +- name: Register and subscribe to multiple pools. + redhat_subscription: + state: present + username: joe_user + password: somepass + pool_ids: + - 0123456789abcdef0123456789abcdef + - 1123456789abcdef0123456789abcdef + +- name: Same as above but consume multiple entitlements. + redhat_subscription: + state: present + username: joe_user + password: somepass + pool_ids: + - 0123456789abcdef0123456789abcdef: 2 + - 1123456789abcdef0123456789abcdef: 4 + +- name: Register and pull existing system data. + redhat_subscription: state: present username: joe_user password: somepass consumer_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -# Register with activationkey (1-222333444) and consume subscriptions matching -# the names (Red hat Enterprise Server) and (Red Hat Virtualization) -- redhat_subscription: +- name: Register with activationkey and consume subscriptions matching Red Hat Enterprise Server or Red Hat Virtualization + redhat_subscription: state: present activationkey: 1-222333444 org_id: 222333444 pool: '^(Red Hat Enterprise Server|Red Hat Virtualization)$' -# Update the consumed subscriptions from the previous example (remove the Red -# Hat Virtualization subscription) -- redhat_subscription: +- name: Update the consumed subscriptions from the previous example (remove Red Hat Virtualization subscription) + redhat_subscription: state: present activationkey: 1-222333444 org_id: 222333444 pool: '^Red Hat Enterprise Server$' -# Register as user credentials into given environment (against Red Hat -# Satellite 6.x), and auto-subscribe to available content. -- redhat_subscription: +- name: Register as user credentials into given environment (against Red Hat Satellite 6.x), and auto-subscribe. + redhat_subscription: state: present username: joe_user password: somepass @@ -395,6 +429,12 @@ class Rhsm(RegistrationBase): # no matches return [] + def subscribe_by_pool_ids(self, pool_ids): + for pool_id, quantity in pool_ids.items(): + args = [SUBMAN_CMD, 'attach', '--pool', pool_id, '--quantity', quantity] + rc, stderr, stdout = self.module.run_command(args, check_rc=True) + return pool_ids + def subscribe_pool(self, regexp): ''' Subscribe current system to available pools matching the specified @@ -445,6 +485,29 @@ class Rhsm(RegistrationBase): return {'changed': changed, 'subscribed_pool_ids': subscribed_pool_ids, 'unsubscribed_serials': serials} + def update_subscriptions_by_pool_ids(self, pool_ids): + changed = False + consumed_pools = RhsmPools(self.module, consumed=True) + + existing_pools = {} + for p in consumed_pools: + existing_pools[p.get_pool_id()] = p.QuantityUsed + + serials_to_remove = [p.Serial for p in consumed_pools if pool_ids.get(p.get_pool_id(), 0) != p.QuantityUsed] + serials = self.unsubscribe(serials=serials_to_remove) + + missing_pools = {} + for pool_id, quantity in pool_ids.items(): + if existing_pools.get(pool_id, 0) != quantity: + missing_pools[pool_id] = quantity + + self.subscribe_by_pool_ids(missing_pools) + + if missing_pools or serials: + changed = True + return {'changed': changed, 'subscribed_pool_ids': missing_pools.keys(), + 'unsubscribed_serials': serials} + class RhsmPool(object): ''' @@ -569,6 +632,9 @@ def main(): pool=dict(default='^$', required=False, type='str'), + pool_ids=dict(default=[], + required=False, + type='list'), consumer_type=dict(default=None, required=False), consumer_name=dict(default=None, @@ -579,7 +645,7 @@ def main(): type='bool'), ), required_together=[['username', 'password'], ['activationkey', 'org_id']], - mutually_exclusive=[['username', 'activationkey']], + mutually_exclusive=[['username', 'activationkey'], ['pool', 'pool_ids']], required_if=[['state', 'present', ['username', 'activationkey'], True]], ) @@ -595,6 +661,15 @@ def main(): org_id = module.params['org_id'] environment = module.params['environment'] pool = module.params['pool'] + pool_ids = {} + for value in module.params['pool_ids']: + if isinstance(value, dict): + if len(value) != 1: + module.fail_json(msg='Unable to parse pool_ids option.') + pool_id, quantity = value.items()[0] + else: + pool_id, quantity = value, 1 + pool_ids[pool_id] = str(quantity) consumer_type = module.params["consumer_type"] consumer_name = module.params["consumer_name"] consumer_id = module.params["consumer_id"] @@ -608,9 +683,12 @@ def main(): # Register system if rhsm.is_registered and not force_register: - if pool != '^$': + if pool != '^$' or pool_ids: try: - result = rhsm.update_subscriptions(pool) + if pool_ids: + result = rhsm.update_subscriptions_by_pool_ids(pool_ids) + else: + result = rhsm.update_subscriptions(pool) except Exception: e = get_exception() module.fail_json(msg="Failed to update subscriptions for '%s': %s" % (server_hostname, e)) @@ -625,7 +703,10 @@ def main(): rhsm.register(username, password, autosubscribe, activationkey, org_id, consumer_type, consumer_name, consumer_id, force_register, environment, rhsm_baseurl, server_insecure) - subscribed_pool_ids = rhsm.subscribe(pool) + if pool_ids: + subscribed_pool_ids = rhsm.subscribe_by_pool_ids(pool_ids) + else: + subscribed_pool_ids = rhsm.subscribe(pool) except Exception: e = get_exception() module.fail_json(msg="Failed to register with '%s': %s" % (server_hostname, e))