安装ansible-tower
http://t.zoukankan.com/fusheng11711-p-12220932.html
https://www.milkfish.site/2021/05/13/1038.loli
链接: https://pan.baidu.com/s/1cbA71jJ9DtTWiLqFleL8TQ 提取码: 3rg5
--来自百度网盘超级会员v5的分享
安装包下载地址:
https://releases.ansible.com/ansible-tower/setup/
依赖地址:
https://releases.ansible.com/ansible-tower/rpm/dependencies/3.4/epel-7-x86_64/
postgresql地址:
https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-7-x86_64/
[root@localhost yum.repos.d]# mkdir bak [root@localhost yum.repos.d]# mv CentOS-* bak [root@localhost yum.repos.d]# cd bak/ [root@localhost bak]# mv CentOS-Base.repo ../ yum install epel-release -y mkdir /tmp/tower && cd /tmp/tower curl -k -O https://releases.ansible.com/ansible-tower/setup/ansible-tower-setup-latest.tar.gz cd ansible-tower-setup*/ sed -i "s#password=''#password='324215'#g" inventory sed -i "s#host=''#host='127.0.0.1'#g" inventory sed -i "s#port=''#port='5432'#g" inventory mkdir -p /var/log/tower ./setup.sh
[root@localhost ~]# cat /var/lib/awx/venv/awx/lib/python3.6/site-packages/awx/main/utils/licensing.py # Copyright (c) 2015 Ansible, Inc. # All Rights Reserved. ''' This is intended to be a lightweight license class for verifying subscriptions, and parsing subscription data from entitlement certificates. The Licenser class can do the following: - Parse an Entitlement cert to generate license ''' import base64 import configparser from datetime import datetime, timezone import collections import copy import io import json import logging import re import requests import time import zipfile from dateutil.parser import parse as parse_date from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives import hashes from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import padding from cryptography import x509 # Django from django.conf import settings from django.utils.translation import gettext_lazy as _ # AWX from awx.main.models import Host MAX_INSTANCES = 9999999 logger = logging.getLogger(__name__) def rhsm_config(): path = '/etc/rhsm/rhsm.conf' config = configparser.ConfigParser() config.read(path) return config def validate_entitlement_manifest(data): buff = io.BytesIO() buff.write(base64.b64decode(data)) try: z = zipfile.ZipFile(buff) except zipfile.BadZipFile as e: raise ValueError(_("Invalid manifest: a subscription manifest zip file is required.")) from e buff = io.BytesIO() files = z.namelist() if 'consumer_export.zip' not in files or 'signature' not in files: raise ValueError(_("Invalid manifest: missing required files.")) export = z.open('consumer_export.zip').read() sig = z.open('signature').read() with open('/etc/tower/candlepin-redhat-ca.crt', 'rb') as f: cert = x509.load_pem_x509_certificate(f.read(), backend=default_backend()) key = cert.public_key() try: key.verify(sig, export, padding=padding.PKCS1v15(), algorithm=hashes.SHA256()) except InvalidSignature as e: raise ValueError(_("Invalid manifest: signature verification failed.")) from e buff.write(export) z = zipfile.ZipFile(buff) subs = [] for f in z.filelist: if f.filename.startswith('export/entitlements') and f.filename.endswith('.json'): subs.append(json.loads(z.open(f).read())) if subs: return subs raise ValueError(_("Invalid manifest: manifest contains no subscriptions.")) class OpenLicense(object): def validate(self): return dict( license_type='enterprise', valid_key=True, subscription_name='mxd', product_name="AWX", ) class Licenser(object): # warn when there is a month (30 days) left on the subscription SUBSCRIPTION_TIMEOUT = 60 * 60 * 24 * 30 UNLICENSED_DATA = dict( subscription_name=None, sku=None, support_level=None, instance_count=MAX_INSTANCES, license_date=2567433600, license_type="enterprise", product_name="Red Hat Ansible Automation Platform", valid_key=False ) def __init__(self, **kwargs): self._attrs = dict( instance_count=0, license_date=0, license_type='enterprise', ) self.config = rhsm_config() if not kwargs: license_setting = getattr(settings, 'LICENSE', None) if license_setting is not None: kwargs = license_setting if 'company_name' in kwargs: kwargs.pop('company_name') self._attrs.update(kwargs) if 'valid_key' in self._attrs: if not self._attrs['valid_key']: self._unset_attrs() else: self._unset_attrs() def _unset_attrs(self): self._attrs = self.UNLICENSED_DATA.copy() def license_from_manifest(self, manifest): def is_appropriate_manifest_sub(sub): if sub['pool']['activeSubscription'] is False: return False now = datetime.now(timezone.utc) if parse_date(sub['startDate']) > now: return False if parse_date(sub['endDate']) < now: return False products = sub['pool']['providedProducts'] if any(product.get('productId') == '480' for product in products): return True return False def _can_aggregate(sub, license): # We aggregate multiple subs into a larger meta-sub, if they match # # No current sub in aggregate if not license: return True # Same SKU type (SER vs MCT vs others)? if license['sku'][0:3] != sub['pool']['productId'][0:3]: return False return True # Parse output for subscription metadata to build config license = dict() for sub in manifest: if not is_appropriate_manifest_sub(sub): logger.warning("Subscription %s (%s) in manifest is not active or for another product" % (sub['pool']['productName'], sub['pool']['productId'])) continue if not _can_aggregate(sub, license): logger.warning("Subscription %s (%s) in manifest does not match other manifest subscriptions" % (sub['pool']['productName'], sub['pool']['productId'])) continue license.setdefault('sku', sub['pool']['productId']) license.setdefault('subscription_name', sub['pool']['productName']) license.setdefault('pool_id', sub['pool']['id']) license.setdefault('product_name', sub['pool']['productName']) license.setdefault('valid_key', True) license.setdefault('license_type', 'enterprise') license.setdefault('satellite', False) # Use the nearest end date endDate = parse_date(sub['endDate']) currentEndDateStr = license.get('license_date', '4102462800') # 2100-01-01 currentEndDate = datetime.fromtimestamp(int(currentEndDateStr), timezone.utc) if endDate < currentEndDate: license['license_date'] = endDate.strftime('%s') instances = sub['quantity'] license['instance_count'] = license.get('instance_count', 0) + instances license['subscription_name'] = re.sub(r'[\d]* Managed Nodes', '%d Managed Nodes' % license['instance_count'], license['subscription_name']) if not license: logger.error("No valid subscriptions found in manifest") self._attrs.update(license) settings.LICENSE = self._attrs return self._attrs def update(self, **kwargs): # Update attributes of the current license. if 'instance_count' in kwargs: kwargs['instance_count'] = int(kwargs['instance_count']) if 'license_date' in kwargs: kwargs['license_date'] = int(kwargs['license_date']) self._attrs.update(kwargs) def validate_rh(self, user, pw): try: host = 'https://' + str(self.config.get("server", "hostname")) except Exception: logger.exception('Cannot access rhsm.conf, make sure subscription manager is installed and configured.') host = None if not host: host = getattr(settings, 'REDHAT_CANDLEPIN_HOST', None) if not user: raise ValueError('subscriptions_username is required') if not pw: raise ValueError('subscriptions_password is required') if host and user and pw: if 'subscription.rhsm.redhat.com' in host: json = self.get_rhsm_subs(host, user, pw) else: json = self.get_satellite_subs(host, user, pw) return self.generate_license_options_from_entitlements(json) return [] def get_rhsm_subs(self, host, user, pw): verify = getattr(settings, 'REDHAT_CANDLEPIN_VERIFY', True) json = [] try: subs = requests.get( '/'.join([host, 'subscription/users/{}/owners'.format(user)]), verify=verify, auth=(user, pw) ) except requests.exceptions.ConnectionError as error: raise error except OSError as error: raise OSError('Unable to open certificate bundle {}. Check that Ansible Tower is running on Red Hat Enterprise Linux.'.format(verify)) from error # noqa subs.raise_for_status() for sub in subs.json(): resp = requests.get( '/'.join([ host, 'subscription/owners/{}/pools/?match=*tower*'.format(sub['key']) ]), verify=verify, auth=(user, pw) ) resp.raise_for_status() json.extend(resp.json()) return json def get_satellite_subs(self, host, user, pw): port = None try: verify = str(self.config.get("rhsm", "repo_ca_cert")) port = str(self.config.get("server", "port")) except Exception as e: logger.exception('Unable to read rhsm config to get ca_cert location. {}'.format(str(e))) verify = getattr(settings, 'REDHAT_CANDLEPIN_VERIFY', True) if port: host = ':'.join([host, port]) json = [] try: orgs = requests.get( '/'.join([host, 'katello/api/organizations']), verify=verify, auth=(user, pw) ) except requests.exceptions.ConnectionError as error: raise error except OSError as error: raise OSError('Unable to open certificate bundle {}. Check that Ansible Tower is running on Red Hat Enterprise Linux.'.format(verify)) from error # noqa orgs.raise_for_status() for org in orgs.json()['results']: resp = requests.get( '/'.join([ host, '/katello/api/organizations/{}/subscriptions/?search=Red Hat Ansible Automation'.format(org['id']) ]), verify=verify, auth=(user, pw) ) resp.raise_for_status() results = resp.json()['results'] if results != []: for sub in results: # Parse output for subscription metadata to build config license = dict() license['productId'] = sub['product_id'] license['quantity'] = int(sub['quantity']) license['support_level'] = sub['support_level'] license['subscription_name'] = sub['name'] license['id'] = sub['upstream_pool_id'] license['endDate'] = sub['end_date'] license['productName'] = "Red Hat Ansible Automation" license['valid_key'] = True license['license_type'] = 'enterprise' license['satellite'] = True json.append(license) return json def is_appropriate_sat_sub(self, sub): if 'Red Hat Ansible Automation' not in sub['subscription_name']: return False return True def is_appropriate_sub(self, sub): if sub['activeSubscription'] is False: return False # Products that contain Ansible Tower products = sub.get('providedProducts', []) if any(product.get('productId') == '480' for product in products): return True return False def generate_license_options_from_entitlements(self, json): from dateutil.parser import parse ValidSub = collections.namedtuple('ValidSub', 'sku name support_level end_date trial quantity pool_id satellite') valid_subs = [] for sub in json: satellite = sub.get('satellite') if satellite: is_valid = self.is_appropriate_sat_sub(sub) else: is_valid = self.is_appropriate_sub(sub) if is_valid: try: end_date = parse(sub.get('endDate')) except Exception: continue now = datetime.utcnow() now = now.replace(tzinfo=end_date.tzinfo) if end_date < now: # If the sub has a past end date, skip it continue try: quantity = int(sub['quantity']) if quantity == -1: # effectively, unlimited quantity = MAX_INSTANCES except Exception: continue sku = sub['productId'] trial = sku.startswith('S') # i.e.,, SER/SVC support_level = '' pool_id = sub['id'] if satellite: support_level = sub['support_level'] else: for attr in sub.get('productAttributes', []): if attr.get('name') == 'support_level': support_level = attr.get('value') valid_subs.append(ValidSub( sku, sub['productName'], support_level, end_date, trial, quantity, pool_id, satellite )) if valid_subs: licenses = [] for sub in valid_subs: license = self.__class__(subscription_name='Red Hat Ansible Automation Platform') license._attrs['instance_count'] = int(sub.quantity) license._attrs['sku'] = sub.sku license._attrs['support_level'] = sub.support_level license._attrs['license_type'] = 'enterprise' if sub.trial: license._attrs['trial'] = True license._attrs['license_type'] = 'enterprise' license._attrs['instance_count'] = min( MAX_INSTANCES, license._attrs['instance_count'] ) human_instances = license._attrs['instance_count'] if human_instances == MAX_INSTANCES: human_instances = 'Unlimited' subscription_name = re.sub( r' \([\d]+ Managed Nodes', ' ({} Managed Nodes'.format(human_instances), sub.name ) license._attrs['subscription_name'] = subscription_name license._attrs['satellite'] = satellite license._attrs['valid_key'] = True license.update( license_date=int(sub.end_date.strftime('%s')) ) license.update( pool_id=sub.pool_id ) licenses.append(license._attrs.copy()) return licenses raise ValueError( 'No valid Red Hat Ansible Automation subscription could be found for this account.' # noqa ) def validate(self): # Return license attributes with additional validation info. attrs = copy.deepcopy(self._attrs) type = attrs.get('license_type', 'none') #if (type == 'UNLICENSED' or False): # attrs.update(dict(valid_key=False, compliant=False)) # return attrs attrs['valid_key'] = True if Host: current_instances = Host.objects.active_count() else: current_instances = 0 available_instances = int(attrs.get('instance_count', None) or 0) attrs['current_instances'] = current_instances attrs['available_instances'] = available_instances free_instances = (available_instances - current_instances) attrs['free_instances'] = max(0, free_instances) license_date = int(attrs.get('license_date', 0) or 0) current_date = int(time.time()) time_remaining = license_date - current_date attrs['time_remaining'] = time_remaining if attrs.setdefault('trial', False): attrs['grace_period_remaining'] = time_remaining else: attrs['grace_period_remaining'] = (license_date + 2592000) - current_date attrs['compliant'] = bool(time_remaining > 0 and free_instances >= 0) attrs['date_warning'] = bool(time_remaining < self.SUBSCRIPTION_TIMEOUT) attrs['date_expired'] = bool(time_remaining <= 0) return attrs