安装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/

1
2
3
4
5
6
7
8
9
10
11
12
13
[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

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
[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

 

posted @   linuxws  阅读(279)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
历史上的今天:
2018-05-23 ldap第一天 编译安装LDAP + ldapadmin
点击右上角即可分享
微信分享提示