mirror of
https://github.com/ansible/awx.git
synced 2026-05-07 09:27:36 -02:30
Adding license checks for Tower inventory source
* For Tower the license must match between the source and destination * For AWX the check is disabled * Hosts imported from another Tower don't count against your license in the local Tower * Fix up some issues with enablement * Prevent slashes from being used in the instance filter * Add &all=1 filter to make sure we pick up all hosts
This commit is contained in:
@@ -2443,7 +2443,7 @@ class InventoryScriptView(RetrieveAPIView):
|
|||||||
for host in obj.hosts.filter(**hosts_q):
|
for host in obj.hosts.filter(**hosts_q):
|
||||||
data['_meta']['hostvars'][host.name] = host.variables_dict
|
data['_meta']['hostvars'][host.name] = host.variables_dict
|
||||||
if towervars:
|
if towervars:
|
||||||
tower_dict = dict(remote_tower_enabled=host.enabled,
|
tower_dict = dict(remote_tower_enabled=str(host.enabled).lower(),
|
||||||
remote_tower_id=host.id)
|
remote_tower_id=host.id)
|
||||||
data['_meta']['hostvars'][host.name].update(tower_dict)
|
data['_meta']['hostvars'][host.name].update(tower_dict)
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import logging
|
|||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django.db.models import Sum
|
from django.db.models import Sum, Q
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from awx.main.utils.filters import SmartFilter
|
from awx.main.utils.filters import SmartFilter
|
||||||
@@ -21,9 +21,9 @@ class HostManager(models.Manager):
|
|||||||
"""Custom manager class for Hosts model."""
|
"""Custom manager class for Hosts model."""
|
||||||
|
|
||||||
def active_count(self):
|
def active_count(self):
|
||||||
"""Return count of active, unique hosts for licensing."""
|
"""Return count of active, unique hosts for licensing. Exclude ones source from another Tower"""
|
||||||
try:
|
try:
|
||||||
return self.order_by('name').distinct('name').count()
|
return self.filter(~Q(inventory_sources__source='tower')).order_by('name').distinct('name').count()
|
||||||
except NotImplementedError: # For unit tests only, SQLite doesn't support distinct('name')
|
except NotImplementedError: # For unit tests only, SQLite doesn't support distinct('name')
|
||||||
return len(set(self.values_list('name', flat=True)))
|
return len(set(self.values_list('name', flat=True)))
|
||||||
|
|
||||||
|
|||||||
@@ -1914,6 +1914,7 @@ class RunInventoryUpdate(BaseTask):
|
|||||||
env[str(env_k)] = unicode(inventory_update.source_vars_dict[env_k])
|
env[str(env_k)] = unicode(inventory_update.source_vars_dict[env_k])
|
||||||
elif inventory_update.source == 'tower':
|
elif inventory_update.source == 'tower':
|
||||||
env['TOWER_INVENTORY'] = inventory_update.instance_filters
|
env['TOWER_INVENTORY'] = inventory_update.instance_filters
|
||||||
|
env['TOWER_LICENSE_TYPE'] = get_licenser().validate()['license_type']
|
||||||
elif inventory_update.source == 'file':
|
elif inventory_update.source == 'file':
|
||||||
raise NotImplementedError('Cannot update file sources through the task system.')
|
raise NotImplementedError('Cannot update file sources through the task system.')
|
||||||
# add private_data_files
|
# add private_data_files
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ def test_default_cred_types():
|
|||||||
'satellite6',
|
'satellite6',
|
||||||
'scm',
|
'scm',
|
||||||
'ssh',
|
'ssh',
|
||||||
|
'tower',
|
||||||
'vault',
|
'vault',
|
||||||
'vmware',
|
'vmware',
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ def parse_configuration():
|
|||||||
password = os.environ.get("TOWER_PASSWORD", None)
|
password = os.environ.get("TOWER_PASSWORD", None)
|
||||||
ignore_ssl = os.environ.get("TOWER_IGNORE_SSL", "1").lower() in ("1", "yes", "true")
|
ignore_ssl = os.environ.get("TOWER_IGNORE_SSL", "1").lower() in ("1", "yes", "true")
|
||||||
inventory = os.environ.get("TOWER_INVENTORY", None)
|
inventory = os.environ.get("TOWER_INVENTORY", None)
|
||||||
|
license_type = os.environ.get("TOWER_LICENSE_TYPE", "enterprise")
|
||||||
|
|
||||||
errors = []
|
errors = []
|
||||||
if not host_name:
|
if not host_name:
|
||||||
@@ -74,14 +75,30 @@ def parse_configuration():
|
|||||||
tower_user=username,
|
tower_user=username,
|
||||||
tower_pass=password,
|
tower_pass=password,
|
||||||
tower_inventory=inventory,
|
tower_inventory=inventory,
|
||||||
|
tower_license_type=license_type,
|
||||||
ignore_ssl=ignore_ssl)
|
ignore_ssl=ignore_ssl)
|
||||||
|
|
||||||
|
|
||||||
def read_tower_inventory(tower_host, tower_user, tower_pass, inventory, ignore_ssl=False):
|
def read_tower_inventory(tower_host, tower_user, tower_pass, inventory, license_type, ignore_ssl=False):
|
||||||
if not re.match('(?:http|https)://', tower_host):
|
if not re.match('(?:http|https)://', tower_host):
|
||||||
tower_host = "https://{}".format(tower_host)
|
tower_host = "https://{}".format(tower_host)
|
||||||
inventory_url = urljoin(tower_host, "/api/v2/inventories/{}/script/?hostvars=1&towervars=1".format(inventory))
|
inventory_url = urljoin(tower_host, "/api/v2/inventories/{}/script/?hostvars=1&towervars=1&all=1".format(inventory.replace('/', '')))
|
||||||
|
config_url = urljoin(tower_host, "/api/v2/config/")
|
||||||
try:
|
try:
|
||||||
|
if license_type != "open":
|
||||||
|
config_response = requests.get(config_url,
|
||||||
|
auth=HTTPBasicAuth(tower_user, tower_pass),
|
||||||
|
verify=not ignore_ssl)
|
||||||
|
if config_response.ok:
|
||||||
|
source_type = config_response.json()['license_info']['license_type']
|
||||||
|
if not source_type == license_type:
|
||||||
|
print("Tower server licenses must match: source: {} local: {}".format(source_type,
|
||||||
|
license_type))
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
print("Failed to validate the license of the remote Tower: {}".format(config_response.data))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
response = requests.get(inventory_url,
|
response = requests.get(inventory_url,
|
||||||
auth=HTTPBasicAuth(tower_user, tower_pass),
|
auth=HTTPBasicAuth(tower_user, tower_pass),
|
||||||
verify=not ignore_ssl)
|
verify=not ignore_ssl)
|
||||||
@@ -101,6 +118,7 @@ def main():
|
|||||||
config['tower_user'],
|
config['tower_user'],
|
||||||
config['tower_pass'],
|
config['tower_pass'],
|
||||||
config['tower_inventory'],
|
config['tower_inventory'],
|
||||||
|
config['tower_license_type'],
|
||||||
ignore_ssl=config['ignore_ssl'])
|
ignore_ssl=config['ignore_ssl'])
|
||||||
print(
|
print(
|
||||||
json.dumps(
|
json.dumps(
|
||||||
|
|||||||
Reference in New Issue
Block a user