summaryrefslogtreecommitdiffstats
path: root/lib/ansible/modules/hostname.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible/modules/hostname.py')
-rw-r--r--lib/ansible/modules/hostname.py908
1 files changed, 908 insertions, 0 deletions
diff --git a/lib/ansible/modules/hostname.py b/lib/ansible/modules/hostname.py
new file mode 100644
index 0000000..f6284df
--- /dev/null
+++ b/lib/ansible/modules/hostname.py
@@ -0,0 +1,908 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2013, Hiroaki Nakamura <hnakamur@gmail.com>
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+
+DOCUMENTATION = '''
+---
+module: hostname
+author:
+ - Adrian Likins (@alikins)
+ - Hideki Saito (@saito-hideki)
+version_added: "1.4"
+short_description: Manage hostname
+requirements: [ hostname ]
+description:
+ - Set system's hostname. Supports most OSs/Distributions including those using C(systemd).
+ - Windows, HP-UX, and AIX are not currently supported.
+notes:
+ - This module does B(NOT) modify C(/etc/hosts). You need to modify it yourself using other modules such as M(ansible.builtin.template)
+ or M(ansible.builtin.replace).
+ - On macOS, this module uses C(scutil) to set C(HostName), C(ComputerName), and C(LocalHostName). Since C(LocalHostName)
+ cannot contain spaces or most special characters, this module will replace characters when setting C(LocalHostName).
+options:
+ name:
+ description:
+ - Name of the host.
+ - If the value is a fully qualified domain name that does not resolve from the given host,
+ this will cause the module to hang for a few seconds while waiting for the name resolution attempt to timeout.
+ type: str
+ required: true
+ use:
+ description:
+ - Which strategy to use to update the hostname.
+ - If not set we try to autodetect, but this can be problematic, particularly with containers as they can present misleading information.
+ - Note that 'systemd' should be specified for RHEL/EL/CentOS 7+. Older distributions should use 'redhat'.
+ choices: ['alpine', 'debian', 'freebsd', 'generic', 'macos', 'macosx', 'darwin', 'openbsd', 'openrc', 'redhat', 'sles', 'solaris', 'systemd']
+ type: str
+ version_added: '2.9'
+extends_documentation_fragment:
+- action_common_attributes
+- action_common_attributes.facts
+attributes:
+ check_mode:
+ support: full
+ diff_mode:
+ support: full
+ facts:
+ support: full
+ platform:
+ platforms: posix
+'''
+
+EXAMPLES = '''
+- name: Set a hostname
+ ansible.builtin.hostname:
+ name: web01
+
+- name: Set a hostname specifying strategy
+ ansible.builtin.hostname:
+ name: web01
+ use: systemd
+'''
+
+import os
+import platform
+import socket
+import traceback
+
+import ansible.module_utils.compat.typing as t
+
+from ansible.module_utils.basic import (
+ AnsibleModule,
+ get_distribution,
+ get_distribution_version,
+)
+from ansible.module_utils.common.sys_info import get_platform_subclass
+from ansible.module_utils.facts.system.service_mgr import ServiceMgrFactCollector
+from ansible.module_utils.facts.utils import get_file_lines, get_file_content
+from ansible.module_utils._text import to_native, to_text
+from ansible.module_utils.six import PY3, text_type
+
+STRATS = {
+ 'alpine': 'Alpine',
+ 'debian': 'Systemd',
+ 'freebsd': 'FreeBSD',
+ 'generic': 'Base',
+ 'macos': 'Darwin',
+ 'macosx': 'Darwin',
+ 'darwin': 'Darwin',
+ 'openbsd': 'OpenBSD',
+ 'openrc': 'OpenRC',
+ 'redhat': 'RedHat',
+ 'sles': 'SLES',
+ 'solaris': 'Solaris',
+ 'systemd': 'Systemd',
+}
+
+
+class BaseStrategy(object):
+ def __init__(self, module):
+ self.module = module
+ self.changed = False
+
+ def update_current_and_permanent_hostname(self):
+ self.update_current_hostname()
+ self.update_permanent_hostname()
+ return self.changed
+
+ def update_current_hostname(self):
+ name = self.module.params['name']
+ current_name = self.get_current_hostname()
+ if current_name != name:
+ if not self.module.check_mode:
+ self.set_current_hostname(name)
+ self.changed = True
+
+ def update_permanent_hostname(self):
+ name = self.module.params['name']
+ permanent_name = self.get_permanent_hostname()
+ if permanent_name != name:
+ if not self.module.check_mode:
+ self.set_permanent_hostname(name)
+ self.changed = True
+
+ def get_current_hostname(self):
+ return self.get_permanent_hostname()
+
+ def set_current_hostname(self, name):
+ pass
+
+ def get_permanent_hostname(self):
+ raise NotImplementedError
+
+ def set_permanent_hostname(self, name):
+ raise NotImplementedError
+
+
+class UnimplementedStrategy(BaseStrategy):
+ def update_current_and_permanent_hostname(self):
+ self.unimplemented_error()
+
+ def update_current_hostname(self):
+ self.unimplemented_error()
+
+ def update_permanent_hostname(self):
+ self.unimplemented_error()
+
+ def get_current_hostname(self):
+ self.unimplemented_error()
+
+ def set_current_hostname(self, name):
+ self.unimplemented_error()
+
+ def get_permanent_hostname(self):
+ self.unimplemented_error()
+
+ def set_permanent_hostname(self, name):
+ self.unimplemented_error()
+
+ def unimplemented_error(self):
+ system = platform.system()
+ distribution = get_distribution()
+ if distribution is not None:
+ msg_platform = '%s (%s)' % (system, distribution)
+ else:
+ msg_platform = system
+ self.module.fail_json(
+ msg='hostname module cannot be used on platform %s' % msg_platform)
+
+
+class CommandStrategy(BaseStrategy):
+ COMMAND = 'hostname'
+
+ def __init__(self, module):
+ super(CommandStrategy, self).__init__(module)
+ self.hostname_cmd = self.module.get_bin_path(self.COMMAND, True)
+
+ def get_current_hostname(self):
+ cmd = [self.hostname_cmd]
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0:
+ self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err))
+ return to_native(out).strip()
+
+ def set_current_hostname(self, name):
+ cmd = [self.hostname_cmd, name]
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0:
+ self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err))
+
+ def get_permanent_hostname(self):
+ return 'UNKNOWN'
+
+ def set_permanent_hostname(self, name):
+ pass
+
+
+class FileStrategy(BaseStrategy):
+ FILE = '/etc/hostname'
+
+ def get_permanent_hostname(self):
+ if not os.path.isfile(self.FILE):
+ return ''
+
+ try:
+ return get_file_content(self.FILE, default='', strip=True)
+ except Exception as e:
+ self.module.fail_json(
+ msg="failed to read hostname: %s" % to_native(e),
+ exception=traceback.format_exc())
+
+ def set_permanent_hostname(self, name):
+ try:
+ with open(self.FILE, 'w+') as f:
+ f.write("%s\n" % name)
+ except Exception as e:
+ self.module.fail_json(
+ msg="failed to update hostname: %s" % to_native(e),
+ exception=traceback.format_exc())
+
+
+class SLESStrategy(FileStrategy):
+ """
+ This is a SLES Hostname strategy class - it edits the
+ /etc/HOSTNAME file.
+ """
+ FILE = '/etc/HOSTNAME'
+
+
+class RedHatStrategy(BaseStrategy):
+ """
+ This is a Redhat Hostname strategy class - it edits the
+ /etc/sysconfig/network file.
+ """
+ NETWORK_FILE = '/etc/sysconfig/network'
+
+ def get_permanent_hostname(self):
+ try:
+ for line in get_file_lines(self.NETWORK_FILE):
+ line = to_native(line).strip()
+ if line.startswith('HOSTNAME'):
+ k, v = line.split('=')
+ return v.strip()
+ self.module.fail_json(
+ "Unable to locate HOSTNAME entry in %s" % self.NETWORK_FILE
+ )
+ except Exception as e:
+ self.module.fail_json(
+ msg="failed to read hostname: %s" % to_native(e),
+ exception=traceback.format_exc())
+
+ def set_permanent_hostname(self, name):
+ try:
+ lines = []
+ found = False
+ content = get_file_content(self.NETWORK_FILE, strip=False) or ""
+ for line in content.splitlines(True):
+ line = to_native(line)
+ if line.strip().startswith('HOSTNAME'):
+ lines.append("HOSTNAME=%s\n" % name)
+ found = True
+ else:
+ lines.append(line)
+ if not found:
+ lines.append("HOSTNAME=%s\n" % name)
+ with open(self.NETWORK_FILE, 'w+') as f:
+ f.writelines(lines)
+ except Exception as e:
+ self.module.fail_json(
+ msg="failed to update hostname: %s" % to_native(e),
+ exception=traceback.format_exc())
+
+
+class AlpineStrategy(FileStrategy):
+ """
+ This is a Alpine Linux Hostname manipulation strategy class - it edits
+ the /etc/hostname file then run hostname -F /etc/hostname.
+ """
+
+ FILE = '/etc/hostname'
+ COMMAND = 'hostname'
+
+ def set_current_hostname(self, name):
+ super(AlpineStrategy, self).set_current_hostname(name)
+ hostname_cmd = self.module.get_bin_path(self.COMMAND, True)
+
+ cmd = [hostname_cmd, '-F', self.FILE]
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0:
+ self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err))
+
+
+class SystemdStrategy(BaseStrategy):
+ """
+ This is a Systemd hostname manipulation strategy class - it uses
+ the hostnamectl command.
+ """
+
+ COMMAND = "hostnamectl"
+
+ def __init__(self, module):
+ super(SystemdStrategy, self).__init__(module)
+ self.hostnamectl_cmd = self.module.get_bin_path(self.COMMAND, True)
+
+ def get_current_hostname(self):
+ cmd = [self.hostnamectl_cmd, '--transient', 'status']
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0:
+ self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err))
+ return to_native(out).strip()
+
+ def set_current_hostname(self, name):
+ if len(name) > 64:
+ self.module.fail_json(msg="name cannot be longer than 64 characters on systemd servers, try a shorter name")
+ cmd = [self.hostnamectl_cmd, '--transient', 'set-hostname', name]
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0:
+ self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err))
+
+ def get_permanent_hostname(self):
+ cmd = [self.hostnamectl_cmd, '--static', 'status']
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0:
+ self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err))
+ return to_native(out).strip()
+
+ def set_permanent_hostname(self, name):
+ if len(name) > 64:
+ self.module.fail_json(msg="name cannot be longer than 64 characters on systemd servers, try a shorter name")
+ cmd = [self.hostnamectl_cmd, '--pretty', '--static', 'set-hostname', name]
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0:
+ self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err))
+
+ def update_current_and_permanent_hostname(self):
+ # Must set the permanent hostname prior to current to avoid NetworkManager complaints
+ # about setting the hostname outside of NetworkManager
+ self.update_permanent_hostname()
+ self.update_current_hostname()
+ return self.changed
+
+
+class OpenRCStrategy(BaseStrategy):
+ """
+ This is a Gentoo (OpenRC) Hostname manipulation strategy class - it edits
+ the /etc/conf.d/hostname file.
+ """
+
+ FILE = '/etc/conf.d/hostname'
+
+ def get_permanent_hostname(self):
+ if not os.path.isfile(self.FILE):
+ return ''
+
+ try:
+ for line in get_file_lines(self.FILE):
+ line = line.strip()
+ if line.startswith('hostname='):
+ return line[10:].strip('"')
+ except Exception as e:
+ self.module.fail_json(
+ msg="failed to read hostname: %s" % to_native(e),
+ exception=traceback.format_exc())
+
+ def set_permanent_hostname(self, name):
+ try:
+ lines = [x.strip() for x in get_file_lines(self.FILE)]
+
+ for i, line in enumerate(lines):
+ if line.startswith('hostname='):
+ lines[i] = 'hostname="%s"' % name
+ break
+
+ with open(self.FILE, 'w') as f:
+ f.write('\n'.join(lines) + '\n')
+ except Exception as e:
+ self.module.fail_json(
+ msg="failed to update hostname: %s" % to_native(e),
+ exception=traceback.format_exc())
+
+
+class OpenBSDStrategy(FileStrategy):
+ """
+ This is a OpenBSD family Hostname manipulation strategy class - it edits
+ the /etc/myname file.
+ """
+
+ FILE = '/etc/myname'
+
+
+class SolarisStrategy(BaseStrategy):
+ """
+ This is a Solaris11 or later Hostname manipulation strategy class - it
+ execute hostname command.
+ """
+
+ COMMAND = "hostname"
+
+ def __init__(self, module):
+ super(SolarisStrategy, self).__init__(module)
+ self.hostname_cmd = self.module.get_bin_path(self.COMMAND, True)
+
+ def set_current_hostname(self, name):
+ cmd_option = '-t'
+ cmd = [self.hostname_cmd, cmd_option, name]
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0:
+ self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err))
+
+ def get_permanent_hostname(self):
+ fmri = 'svc:/system/identity:node'
+ pattern = 'config/nodename'
+ cmd = '/usr/sbin/svccfg -s %s listprop -o value %s' % (fmri, pattern)
+ rc, out, err = self.module.run_command(cmd, use_unsafe_shell=True)
+ if rc != 0:
+ self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err))
+ return to_native(out).strip()
+
+ def set_permanent_hostname(self, name):
+ cmd = [self.hostname_cmd, name]
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0:
+ self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err))
+
+
+class FreeBSDStrategy(BaseStrategy):
+ """
+ This is a FreeBSD hostname manipulation strategy class - it edits
+ the /etc/rc.conf.d/hostname file.
+ """
+
+ FILE = '/etc/rc.conf.d/hostname'
+ COMMAND = "hostname"
+
+ def __init__(self, module):
+ super(FreeBSDStrategy, self).__init__(module)
+ self.hostname_cmd = self.module.get_bin_path(self.COMMAND, True)
+
+ def get_current_hostname(self):
+ cmd = [self.hostname_cmd]
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0:
+ self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err))
+ return to_native(out).strip()
+
+ def set_current_hostname(self, name):
+ cmd = [self.hostname_cmd, name]
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0:
+ self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err))
+
+ def get_permanent_hostname(self):
+ if not os.path.isfile(self.FILE):
+ return ''
+
+ try:
+ for line in get_file_lines(self.FILE):
+ line = line.strip()
+ if line.startswith('hostname='):
+ return line[10:].strip('"')
+ except Exception as e:
+ self.module.fail_json(
+ msg="failed to read hostname: %s" % to_native(e),
+ exception=traceback.format_exc())
+
+ def set_permanent_hostname(self, name):
+ try:
+ if os.path.isfile(self.FILE):
+ lines = [x.strip() for x in get_file_lines(self.FILE)]
+
+ for i, line in enumerate(lines):
+ if line.startswith('hostname='):
+ lines[i] = 'hostname="%s"' % name
+ break
+ else:
+ lines = ['hostname="%s"' % name]
+
+ with open(self.FILE, 'w') as f:
+ f.write('\n'.join(lines) + '\n')
+ except Exception as e:
+ self.module.fail_json(
+ msg="failed to update hostname: %s" % to_native(e),
+ exception=traceback.format_exc())
+
+
+class DarwinStrategy(BaseStrategy):
+ """
+ This is a macOS hostname manipulation strategy class. It uses
+ /usr/sbin/scutil to set ComputerName, HostName, and LocalHostName.
+
+ HostName corresponds to what most platforms consider to be hostname.
+ It controls the name used on the command line and SSH.
+
+ However, macOS also has LocalHostName and ComputerName settings.
+ LocalHostName controls the Bonjour/ZeroConf name, used by services
+ like AirDrop. This class implements a method, _scrub_hostname(), that mimics
+ the transformations macOS makes on hostnames when enterened in the Sharing
+ preference pane. It replaces spaces with dashes and removes all special
+ characters.
+
+ ComputerName is the name used for user-facing GUI services, like the
+ System Preferences/Sharing pane and when users connect to the Mac over the network.
+ """
+
+ def __init__(self, module):
+ super(DarwinStrategy, self).__init__(module)
+
+ self.scutil = self.module.get_bin_path('scutil', True)
+ self.name_types = ('HostName', 'ComputerName', 'LocalHostName')
+ self.scrubbed_name = self._scrub_hostname(self.module.params['name'])
+
+ def _make_translation(self, replace_chars, replacement_chars, delete_chars):
+ if PY3:
+ return str.maketrans(replace_chars, replacement_chars, delete_chars)
+
+ if not isinstance(replace_chars, text_type) or not isinstance(replacement_chars, text_type):
+ raise ValueError('replace_chars and replacement_chars must both be strings')
+ if len(replace_chars) != len(replacement_chars):
+ raise ValueError('replacement_chars must be the same length as replace_chars')
+
+ table = dict(zip((ord(c) for c in replace_chars), replacement_chars))
+ for char in delete_chars:
+ table[ord(char)] = None
+
+ return table
+
+ def _scrub_hostname(self, name):
+ """
+ LocalHostName only accepts valid DNS characters while HostName and ComputerName
+ accept a much wider range of characters. This function aims to mimic how macOS
+ translates a friendly name to the LocalHostName.
+ """
+
+ # Replace all these characters with a single dash
+ name = to_text(name)
+ replace_chars = u'\'"~`!@#$%^&*(){}[]/=?+\\|-_ '
+ delete_chars = u".'"
+ table = self._make_translation(replace_chars, u'-' * len(replace_chars), delete_chars)
+ name = name.translate(table)
+
+ # Replace multiple dashes with a single dash
+ while '-' * 2 in name:
+ name = name.replace('-' * 2, '')
+
+ name = name.rstrip('-')
+ return name
+
+ def get_current_hostname(self):
+ cmd = [self.scutil, '--get', 'HostName']
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0 and 'HostName: not set' not in err:
+ self.module.fail_json(msg="Failed to get current hostname rc=%d, out=%s, err=%s" % (rc, out, err))
+
+ return to_native(out).strip()
+
+ def get_permanent_hostname(self):
+ cmd = [self.scutil, '--get', 'ComputerName']
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0:
+ self.module.fail_json(msg="Failed to get permanent hostname rc=%d, out=%s, err=%s" % (rc, out, err))
+
+ return to_native(out).strip()
+
+ def set_permanent_hostname(self, name):
+ for hostname_type in self.name_types:
+ cmd = [self.scutil, '--set', hostname_type]
+ if hostname_type == 'LocalHostName':
+ cmd.append(to_native(self.scrubbed_name))
+ else:
+ cmd.append(to_native(name))
+ rc, out, err = self.module.run_command(cmd)
+ if rc != 0:
+ self.module.fail_json(msg="Failed to set {3} to '{2}': {0} {1}".format(to_native(out), to_native(err), to_native(name), hostname_type))
+
+ def set_current_hostname(self, name):
+ pass
+
+ def update_current_hostname(self):
+ pass
+
+ def update_permanent_hostname(self):
+ name = self.module.params['name']
+
+ # Get all the current host name values in the order of self.name_types
+ all_names = tuple(self.module.run_command([self.scutil, '--get', name_type])[1].strip() for name_type in self.name_types)
+
+ # Get the expected host name values based on the order in self.name_types
+ expected_names = tuple(self.scrubbed_name if n == 'LocalHostName' else name for n in self.name_types)
+
+ # Ensure all three names are updated
+ if all_names != expected_names:
+ if not self.module.check_mode:
+ self.set_permanent_hostname(name)
+ self.changed = True
+
+
+class Hostname(object):
+ """
+ This is a generic Hostname manipulation class that is subclassed
+ based on platform.
+
+ A subclass may wish to set different strategy instance to self.strategy.
+
+ All subclasses MUST define platform and distribution (which may be None).
+ """
+
+ platform = 'Generic'
+ distribution = None # type: str | None
+ strategy_class = UnimplementedStrategy # type: t.Type[BaseStrategy]
+
+ def __new__(cls, *args, **kwargs):
+ new_cls = get_platform_subclass(Hostname)
+ return super(cls, new_cls).__new__(new_cls)
+
+ def __init__(self, module):
+ self.module = module
+ self.name = module.params['name']
+ self.use = module.params['use']
+
+ if self.use is not None:
+ strat = globals()['%sStrategy' % STRATS[self.use]]
+ self.strategy = strat(module)
+ elif platform.system() == 'Linux' and ServiceMgrFactCollector.is_systemd_managed(module):
+ # This is Linux and systemd is active
+ self.strategy = SystemdStrategy(module)
+ else:
+ self.strategy = self.strategy_class(module)
+
+ def update_current_and_permanent_hostname(self):
+ return self.strategy.update_current_and_permanent_hostname()
+
+ def get_current_hostname(self):
+ return self.strategy.get_current_hostname()
+
+ def set_current_hostname(self, name):
+ self.strategy.set_current_hostname(name)
+
+ def get_permanent_hostname(self):
+ return self.strategy.get_permanent_hostname()
+
+ def set_permanent_hostname(self, name):
+ self.strategy.set_permanent_hostname(name)
+
+
+class SLESHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Sles'
+ try:
+ distribution_version = get_distribution_version()
+ # cast to float may raise ValueError on non SLES, we use float for a little more safety over int
+ if distribution_version and 10 <= float(distribution_version) <= 12:
+ strategy_class = SLESStrategy # type: t.Type[BaseStrategy]
+ else:
+ raise ValueError()
+ except ValueError:
+ strategy_class = UnimplementedStrategy
+
+
+class RHELHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Redhat'
+ strategy_class = RedHatStrategy
+
+
+class CentOSHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Centos'
+ strategy_class = RedHatStrategy
+
+
+class AnolisOSHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Anolis'
+ strategy_class = RedHatStrategy
+
+
+class CloudlinuxserverHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Cloudlinuxserver'
+ strategy_class = RedHatStrategy
+
+
+class CloudlinuxHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Cloudlinux'
+ strategy_class = RedHatStrategy
+
+
+class AlinuxHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Alinux'
+ strategy_class = RedHatStrategy
+
+
+class ScientificHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Scientific'
+ strategy_class = RedHatStrategy
+
+
+class OracleLinuxHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Oracle'
+ strategy_class = RedHatStrategy
+
+
+class VirtuozzoLinuxHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Virtuozzo'
+ strategy_class = RedHatStrategy
+
+
+class AmazonLinuxHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Amazon'
+ strategy_class = RedHatStrategy
+
+
+class DebianHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Debian'
+ strategy_class = FileStrategy
+
+
+class KylinHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Kylin'
+ strategy_class = FileStrategy
+
+
+class CumulusHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Cumulus-linux'
+ strategy_class = FileStrategy
+
+
+class KaliHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Kali'
+ strategy_class = FileStrategy
+
+
+class ParrotHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Parrot'
+ strategy_class = FileStrategy
+
+
+class UbuntuHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Ubuntu'
+ strategy_class = FileStrategy
+
+
+class LinuxmintHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Linuxmint'
+ strategy_class = FileStrategy
+
+
+class LinaroHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Linaro'
+ strategy_class = FileStrategy
+
+
+class DevuanHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Devuan'
+ strategy_class = FileStrategy
+
+
+class RaspbianHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Raspbian'
+ strategy_class = FileStrategy
+
+
+class UosHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Uos'
+ strategy_class = FileStrategy
+
+
+class DeepinHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Deepin'
+ strategy_class = FileStrategy
+
+
+class GentooHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Gentoo'
+ strategy_class = OpenRCStrategy
+
+
+class ALTLinuxHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Altlinux'
+ strategy_class = RedHatStrategy
+
+
+class AlpineLinuxHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Alpine'
+ strategy_class = AlpineStrategy
+
+
+class OpenBSDHostname(Hostname):
+ platform = 'OpenBSD'
+ distribution = None
+ strategy_class = OpenBSDStrategy
+
+
+class SolarisHostname(Hostname):
+ platform = 'SunOS'
+ distribution = None
+ strategy_class = SolarisStrategy
+
+
+class FreeBSDHostname(Hostname):
+ platform = 'FreeBSD'
+ distribution = None
+ strategy_class = FreeBSDStrategy
+
+
+class NetBSDHostname(Hostname):
+ platform = 'NetBSD'
+ distribution = None
+ strategy_class = FreeBSDStrategy
+
+
+class NeonHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Neon'
+ strategy_class = FileStrategy
+
+
+class DarwinHostname(Hostname):
+ platform = 'Darwin'
+ distribution = None
+ strategy_class = DarwinStrategy
+
+
+class VoidLinuxHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Void'
+ strategy_class = FileStrategy
+
+
+class PopHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Pop'
+ strategy_class = FileStrategy
+
+
+class EurolinuxHostname(Hostname):
+ platform = 'Linux'
+ distribution = 'Eurolinux'
+ strategy_class = RedHatStrategy
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ name=dict(type='str', required=True),
+ use=dict(type='str', choices=list(STRATS.keys()))
+ ),
+ supports_check_mode=True,
+ )
+
+ hostname = Hostname(module)
+ name = module.params['name']
+
+ current_hostname = hostname.get_current_hostname()
+ permanent_hostname = hostname.get_permanent_hostname()
+
+ changed = hostname.update_current_and_permanent_hostname()
+
+ if name != current_hostname:
+ name_before = current_hostname
+ elif name != permanent_hostname:
+ name_before = permanent_hostname
+ else:
+ name_before = permanent_hostname
+
+ # NOTE: socket.getfqdn() calls gethostbyaddr(socket.gethostname()), which can be
+ # slow to return if the name does not resolve correctly.
+ kw = dict(changed=changed, name=name,
+ ansible_facts=dict(ansible_hostname=name.split('.')[0],
+ ansible_nodename=name,
+ ansible_fqdn=socket.getfqdn(),
+ ansible_domain='.'.join(socket.getfqdn().split('.')[1:])))
+
+ if changed:
+ kw['diff'] = {'after': 'hostname = ' + name + '\n',
+ 'before': 'hostname = ' + name_before + '\n'}
+
+ module.exit_json(**kw)
+
+
+if __name__ == '__main__':
+ main()