diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index b8c1f768e..a5e578760 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -96,7 +96,7 @@ class Asset(models.Model): return False, warning def is_unixlike(self): - if self.platform not in ("Windows", "Other"): + if self.platform not in ("Windows",): return True else: return False @@ -132,6 +132,15 @@ class Asset(models.Model): info["gateways"] = [d.id for d in self.domain.gateway_set.all()] return info + def get_auth_info(self): + if self.admin_user: + return { + 'username': self.admin_user.username, + 'password': self.admin_user.password, + 'private_key': self.admin_user.private_key_file, + 'become': self.admin_user.become_info, + } + def _to_secret_json(self): """ Ansible use it create inventory, First using asset user, @@ -175,4 +184,3 @@ class Asset(models.Model): except IntegrityError: print('Error continue') continue - diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index c8224c8c8..e2f318f71 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -29,7 +29,6 @@ class BaseHost(Host): } "groups": [], "vars": {}, - "other_ansbile_vars": } """ self.host_data = host_data @@ -79,7 +78,7 @@ class BaseInventory(InventoryManager): variable_manager_class = VariableManager host_manager_class = BaseHost - def __init__(self, host_list=None): + def __init__(self, host_list=None, group_list=None): """ 用于生成动态构建Ansible Inventory. super().__init__ 会自动调用 host_list: [{ @@ -98,11 +97,14 @@ class BaseInventory(InventoryManager): "vars": {}, }, ] + group_list: [ + {"name: "", children: [""]}, + ] :param host_list: + :param group_list """ - if host_list is None: - host_list = [] - self.host_list = host_list + self.host_list = host_list or [] + self.group_list = group_list or [] assert isinstance(host_list, list) self.loader = self.loader_class() self.variable_manager = self.variable_manager_class() @@ -114,24 +116,34 @@ class BaseInventory(InventoryManager): def get_group(self, name): return self._inventory.groups.get(name, None) - def parse_sources(self, cache=False): - group_all = self.get_group('all') - ungrouped = self.get_group('ungrouped') + def get_or_create_group(self, name): + group = self.get_group(name) + if not group: + self.add_group(name) + return self.get_or_create_group(name) + else: + return group + def parse_groups(self): + for g in self.group_list: + parent = self.get_or_create_group(g.get("name")) + children = [self.get_or_create_group(n) for n in g.get('children', [])] + for child in children: + parent.add_child_group(child) + + def parse_hosts(self): for host_data in self.host_list: host = self.host_manager_class(host_data=host_data) self.hosts[host_data['hostname']] = host groups_data = host_data.get('groups') if groups_data: for group_name in groups_data: - group = self.get_group(group_name) - if group is None: - self.add_group(group_name) - group = self.get_group(group_name) + group = self.get_or_create_group(group_name) group.add_host(host) - else: - ungrouped.add_host(host) - group_all.add_host(host) + + def parse_sources(self, cache=False): + self.parse_groups() + self.parse_hosts() def get_matched_hosts(self, pattern): return self.get_hosts(pattern) diff --git a/apps/ops/inventory.py b/apps/ops/inventory.py index 6e3d6325c..6230e8167 100644 --- a/apps/ops/inventory.py +++ b/apps/ops/inventory.py @@ -9,29 +9,18 @@ __all__ = [ ] -def make_proxy_command(asset): - gateway = asset.domain.random_gateway() - - proxy_command = [ - "ssh", "-p", str(gateway.port), - "{}@{}".format(gateway.username, gateway.ip), - "-W", "%h:%p", "-q", - ] - - if gateway.password: - proxy_command.insert(0, "sshpass -p {}".format(gateway.password)) - if gateway.private_key: - proxy_command.append("-i {}".format(gateway.private_key_file)) - - return {"ansible_ssh_common_args": "'-o ProxyCommand={}'".format(" ".join(proxy_command))} - - class JMSInventory(BaseInventory): """ JMS Inventory is the manager with jumpserver assets, so you can write you own manager, construct you inventory """ def __init__(self, hostname_list, run_as_admin=False, run_as=None, become_info=None): + """ + :param hostname_list: ["test1", ] + :param run_as_admin: True 是否使用管理用户去执行, 每台服务器的管理用户可能不同 + :param run_as: 是否统一使用某个系统用户去执行 + :param become_info: 是否become成某个用户去执行 + """ self.hostname_list = hostname_list self.using_admin = run_as_admin self.run_as = run_as @@ -41,23 +30,14 @@ class JMSInventory(BaseInventory): host_list = [] for asset in assets: - vars = {} - if run_as_admin: - info = asset._to_secret_json() - else: - info = asset.to_json() - - info["vars"] = vars - if asset.domain and asset.domain.has_gateway(): - vars.update(make_proxy_command(asset)) - info.update(vars) - + info = self.convert_to_ansible(asset, run_as_admin=run_as_admin) host_list.append(info) if run_as: run_user_info = self.get_run_user_info() for host in host_list: host.update(run_user_info) + if become_info: for host in host_list: host.update(become_info) @@ -67,9 +47,57 @@ class JMSInventory(BaseInventory): assets = get_assets_by_hostname_list(self.hostname_list) return assets + def convert_to_ansible(self, asset, run_as_admin=False): + info = { + 'id': asset.id, + 'hostname': asset.hostname, + 'ip': asset.ip, + 'port': asset.port, + 'vars': dict(), + 'groups': [], + } + if asset.domain and asset.domain.has_gateway(): + info["vars"].update(self.make_proxy_command(asset)) + if run_as_admin: + info.update(asset.get_auth_info()) + for node in asset.nodes.all(): + info["groups"].append(node.value) + for label in asset.labels.all(): + info["vars"].update({ + label.name: label.value + }) + info["groups"].append("{}:{}".format(label.name, label.value)) + if asset.domain: + info["vars"].update({ + "domain": asset.domain.name, + }) + info["groups"].append("domain_"+asset.domain.name) + return info + def get_run_user_info(self): system_user = get_system_user_by_name(self.run_as) if not system_user: return {} else: return system_user._to_secret_json() + + @staticmethod + def make_proxy_command(asset): + gateway = asset.domain.random_gateway() + proxy_command_list = [ + "ssh", "-p", str(gateway.port), + "{}@{}".format(gateway.username, gateway.ip), + "-W", "%h:%p", "-q", + ] + + if gateway.password: + proxy_command_list.insert( + 0, "sshpass -p {}".format(gateway.password) + ) + if gateway.private_key: + proxy_command_list.append("-i {}".format(gateway.private_key_file)) + + proxy_command = "'-o ProxyCommand={}'".format( + " ".join(proxy_command_list) + ) + return {"ansible_ssh_common_args": proxy_command}