1#!/usr/bin/python 2# -*- coding: utf-8 -*- 3 4# Copyright: (c) 2013, Hiroaki Nakamura <hnakamur@gmail.com> 5# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 7from __future__ import absolute_import, division, print_function 8__metaclass__ = type 9 10 11DOCUMENTATION = ''' 12--- 13module: hostname 14author: 15 - Adrian Likins (@alikins) 16 - Hideki Saito (@saito-hideki) 17version_added: "1.4" 18short_description: Manage hostname 19requirements: [ hostname ] 20description: 21 - Set system's hostname, supports most OSs/Distributions, including those using systemd. 22 - Note, this module does *NOT* modify C(/etc/hosts). You need to modify it yourself using other modules like template or replace. 23 - Windows, HP-UX and AIX are not currently supported. 24options: 25 name: 26 description: 27 - Name of the host 28 required: true 29 use: 30 description: 31 - Which strategy to use to update the hostname. 32 - If not set we try to autodetect, but this can be problematic, specially with containers as they can present misleading information. 33 choices: ['generic', 'debian','sles', 'redhat', 'alpine', 'systemd', 'openrc', 'openbsd', 'solaris', 'freebsd'] 34 version_added: '2.9' 35''' 36 37EXAMPLES = ''' 38- name: Set a hostname 39 ansible.builtin.hostname: 40 name: web01 41''' 42 43import os 44import platform 45import socket 46import traceback 47 48from ansible.module_utils.basic import ( 49 AnsibleModule, 50 get_distribution, 51 get_distribution_version, 52) 53from ansible.module_utils.common.sys_info import get_platform_subclass 54from ansible.module_utils.facts.system.service_mgr import ServiceMgrFactCollector 55from ansible.module_utils._text import to_native 56 57STRATS = {'generic': 'Generic', 'debian': 'Debian', 'sles': 'SLES', 'redhat': 'RedHat', 'alpine': 'Alpine', 58 'systemd': 'Systemd', 'openrc': 'OpenRC', 'openbsd': 'OpenBSD', 'solaris': 'Solaris', 'freebsd': 'FreeBSD'} 59 60 61class UnimplementedStrategy(object): 62 def __init__(self, module): 63 self.module = module 64 65 def update_current_and_permanent_hostname(self): 66 self.unimplemented_error() 67 68 def update_current_hostname(self): 69 self.unimplemented_error() 70 71 def update_permanent_hostname(self): 72 self.unimplemented_error() 73 74 def get_current_hostname(self): 75 self.unimplemented_error() 76 77 def set_current_hostname(self, name): 78 self.unimplemented_error() 79 80 def get_permanent_hostname(self): 81 self.unimplemented_error() 82 83 def set_permanent_hostname(self, name): 84 self.unimplemented_error() 85 86 def unimplemented_error(self): 87 system = platform.system() 88 distribution = get_distribution() 89 if distribution is not None: 90 msg_platform = '%s (%s)' % (system, distribution) 91 else: 92 msg_platform = system 93 self.module.fail_json( 94 msg='hostname module cannot be used on platform %s' % msg_platform) 95 96 97class Hostname(object): 98 """ 99 This is a generic Hostname manipulation class that is subclassed 100 based on platform. 101 102 A subclass may wish to set different strategy instance to self.strategy. 103 104 All subclasses MUST define platform and distribution (which may be None). 105 """ 106 107 platform = 'Generic' 108 distribution = None 109 strategy_class = UnimplementedStrategy 110 111 def __new__(cls, *args, **kwargs): 112 new_cls = get_platform_subclass(Hostname) 113 return super(cls, new_cls).__new__(new_cls) 114 115 def __init__(self, module): 116 self.module = module 117 self.name = module.params['name'] 118 self.use = module.params['use'] 119 120 if self.use is not None: 121 strat = globals()['%sStrategy' % STRATS[self.use]] 122 self.strategy = strat(module) 123 elif self.platform == 'Linux' and ServiceMgrFactCollector.is_systemd_managed(module): 124 self.strategy = SystemdStrategy(module) 125 else: 126 self.strategy = self.strategy_class(module) 127 128 def update_current_and_permanent_hostname(self): 129 return self.strategy.update_current_and_permanent_hostname() 130 131 def get_current_hostname(self): 132 return self.strategy.get_current_hostname() 133 134 def set_current_hostname(self, name): 135 self.strategy.set_current_hostname(name) 136 137 def get_permanent_hostname(self): 138 return self.strategy.get_permanent_hostname() 139 140 def set_permanent_hostname(self, name): 141 self.strategy.set_permanent_hostname(name) 142 143 144class GenericStrategy(object): 145 """ 146 This is a generic Hostname manipulation strategy class. 147 148 A subclass may wish to override some or all of these methods. 149 - get_current_hostname() 150 - get_permanent_hostname() 151 - set_current_hostname(name) 152 - set_permanent_hostname(name) 153 """ 154 155 def __init__(self, module): 156 self.module = module 157 self.changed = False 158 self.hostname_cmd = self.module.get_bin_path('hostnamectl', False) 159 if not self.hostname_cmd: 160 self.hostname_cmd = self.module.get_bin_path('hostname', True) 161 162 def update_current_and_permanent_hostname(self): 163 self.update_current_hostname() 164 self.update_permanent_hostname() 165 return self.changed 166 167 def update_current_hostname(self): 168 name = self.module.params['name'] 169 current_name = self.get_current_hostname() 170 if current_name != name: 171 if not self.module.check_mode: 172 self.set_current_hostname(name) 173 self.changed = True 174 175 def update_permanent_hostname(self): 176 name = self.module.params['name'] 177 permanent_name = self.get_permanent_hostname() 178 if permanent_name != name: 179 if not self.module.check_mode: 180 self.set_permanent_hostname(name) 181 self.changed = True 182 183 def get_current_hostname(self): 184 cmd = [self.hostname_cmd] 185 rc, out, err = self.module.run_command(cmd) 186 if rc != 0: 187 self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err)) 188 return to_native(out).strip() 189 190 def set_current_hostname(self, name): 191 cmd = [self.hostname_cmd, name] 192 rc, out, err = self.module.run_command(cmd) 193 if rc != 0: 194 self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err)) 195 196 def get_permanent_hostname(self): 197 return 'UNKNOWN' 198 199 def set_permanent_hostname(self, name): 200 pass 201 202 203class DebianStrategy(GenericStrategy): 204 """ 205 This is a Debian family Hostname manipulation strategy class - it edits 206 the /etc/hostname file. 207 """ 208 209 HOSTNAME_FILE = '/etc/hostname' 210 211 def get_permanent_hostname(self): 212 if not os.path.isfile(self.HOSTNAME_FILE): 213 try: 214 open(self.HOSTNAME_FILE, "a").write("") 215 except IOError as e: 216 self.module.fail_json(msg="failed to write file: %s" % 217 to_native(e), exception=traceback.format_exc()) 218 try: 219 f = open(self.HOSTNAME_FILE) 220 try: 221 return f.read().strip() 222 finally: 223 f.close() 224 except Exception as e: 225 self.module.fail_json(msg="failed to read hostname: %s" % 226 to_native(e), exception=traceback.format_exc()) 227 228 def set_permanent_hostname(self, name): 229 try: 230 f = open(self.HOSTNAME_FILE, 'w+') 231 try: 232 f.write("%s\n" % name) 233 finally: 234 f.close() 235 except Exception as e: 236 self.module.fail_json(msg="failed to update hostname: %s" % 237 to_native(e), exception=traceback.format_exc()) 238 239 240class SLESStrategy(GenericStrategy): 241 """ 242 This is a SLES Hostname strategy class - it edits the 243 /etc/HOSTNAME file. 244 """ 245 HOSTNAME_FILE = '/etc/HOSTNAME' 246 247 def get_permanent_hostname(self): 248 if not os.path.isfile(self.HOSTNAME_FILE): 249 try: 250 open(self.HOSTNAME_FILE, "a").write("") 251 except IOError as e: 252 self.module.fail_json(msg="failed to write file: %s" % 253 to_native(e), exception=traceback.format_exc()) 254 try: 255 f = open(self.HOSTNAME_FILE) 256 try: 257 return f.read().strip() 258 finally: 259 f.close() 260 except Exception as e: 261 self.module.fail_json(msg="failed to read hostname: %s" % 262 to_native(e), exception=traceback.format_exc()) 263 264 def set_permanent_hostname(self, name): 265 try: 266 f = open(self.HOSTNAME_FILE, 'w+') 267 try: 268 f.write("%s\n" % name) 269 finally: 270 f.close() 271 except Exception as e: 272 self.module.fail_json(msg="failed to update hostname: %s" % 273 to_native(e), exception=traceback.format_exc()) 274 275 276class RedHatStrategy(GenericStrategy): 277 """ 278 This is a Redhat Hostname strategy class - it edits the 279 /etc/sysconfig/network file. 280 """ 281 NETWORK_FILE = '/etc/sysconfig/network' 282 283 def get_permanent_hostname(self): 284 try: 285 f = open(self.NETWORK_FILE, 'rb') 286 try: 287 for line in f.readlines(): 288 if line.startswith('HOSTNAME'): 289 k, v = line.split('=') 290 return v.strip() 291 finally: 292 f.close() 293 except Exception as e: 294 self.module.fail_json(msg="failed to read hostname: %s" % 295 to_native(e), exception=traceback.format_exc()) 296 297 def set_permanent_hostname(self, name): 298 try: 299 lines = [] 300 found = False 301 f = open(self.NETWORK_FILE, 'rb') 302 try: 303 for line in f.readlines(): 304 if line.startswith('HOSTNAME'): 305 lines.append("HOSTNAME=%s\n" % name) 306 found = True 307 else: 308 lines.append(line) 309 finally: 310 f.close() 311 if not found: 312 lines.append("HOSTNAME=%s\n" % name) 313 f = open(self.NETWORK_FILE, 'w+') 314 try: 315 f.writelines(lines) 316 finally: 317 f.close() 318 except Exception as e: 319 self.module.fail_json(msg="failed to update hostname: %s" % 320 to_native(e), exception=traceback.format_exc()) 321 322 323class AlpineStrategy(GenericStrategy): 324 """ 325 This is a Alpine Linux Hostname manipulation strategy class - it edits 326 the /etc/hostname file then run hostname -F /etc/hostname. 327 """ 328 329 HOSTNAME_FILE = '/etc/hostname' 330 331 def update_current_and_permanent_hostname(self): 332 self.update_permanent_hostname() 333 self.update_current_hostname() 334 return self.changed 335 336 def get_permanent_hostname(self): 337 if not os.path.isfile(self.HOSTNAME_FILE): 338 try: 339 open(self.HOSTNAME_FILE, "a").write("") 340 except IOError as e: 341 self.module.fail_json(msg="failed to write file: %s" % 342 to_native(e), exception=traceback.format_exc()) 343 try: 344 f = open(self.HOSTNAME_FILE) 345 try: 346 return f.read().strip() 347 finally: 348 f.close() 349 except Exception as e: 350 self.module.fail_json(msg="failed to read hostname: %s" % 351 to_native(e), exception=traceback.format_exc()) 352 353 def set_permanent_hostname(self, name): 354 try: 355 f = open(self.HOSTNAME_FILE, 'w+') 356 try: 357 f.write("%s\n" % name) 358 finally: 359 f.close() 360 except Exception as e: 361 self.module.fail_json(msg="failed to update hostname: %s" % 362 to_native(e), exception=traceback.format_exc()) 363 364 def set_current_hostname(self, name): 365 cmd = [self.hostname_cmd, '-F', self.HOSTNAME_FILE] 366 rc, out, err = self.module.run_command(cmd) 367 if rc != 0: 368 self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err)) 369 370 371class SystemdStrategy(GenericStrategy): 372 """ 373 This is a Systemd hostname manipulation strategy class - it uses 374 the hostnamectl command. 375 """ 376 377 def get_current_hostname(self): 378 cmd = [self.hostname_cmd, '--transient', 'status'] 379 rc, out, err = self.module.run_command(cmd) 380 if rc != 0: 381 self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err)) 382 return to_native(out).strip() 383 384 def set_current_hostname(self, name): 385 if len(name) > 64: 386 self.module.fail_json(msg="name cannot be longer than 64 characters on systemd servers, try a shorter name") 387 cmd = [self.hostname_cmd, '--transient', 'set-hostname', name] 388 rc, out, err = self.module.run_command(cmd) 389 if rc != 0: 390 self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err)) 391 392 def get_permanent_hostname(self): 393 cmd = [self.hostname_cmd, '--static', 'status'] 394 rc, out, err = self.module.run_command(cmd) 395 if rc != 0: 396 self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err)) 397 return to_native(out).strip() 398 399 def set_permanent_hostname(self, name): 400 if len(name) > 64: 401 self.module.fail_json(msg="name cannot be longer than 64 characters on systemd servers, try a shorter name") 402 cmd = [self.hostname_cmd, '--pretty', 'set-hostname', name] 403 rc, out, err = self.module.run_command(cmd) 404 if rc != 0: 405 self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err)) 406 cmd = [self.hostname_cmd, '--static', 'set-hostname', name] 407 rc, out, err = self.module.run_command(cmd) 408 if rc != 0: 409 self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err)) 410 411 412class OpenRCStrategy(GenericStrategy): 413 """ 414 This is a Gentoo (OpenRC) Hostname manipulation strategy class - it edits 415 the /etc/conf.d/hostname file. 416 """ 417 418 HOSTNAME_FILE = '/etc/conf.d/hostname' 419 420 def get_permanent_hostname(self): 421 name = 'UNKNOWN' 422 try: 423 try: 424 f = open(self.HOSTNAME_FILE, 'r') 425 for line in f: 426 line = line.strip() 427 if line.startswith('hostname='): 428 name = line[10:].strip('"') 429 break 430 except Exception as e: 431 self.module.fail_json(msg="failed to read hostname: %s" % 432 to_native(e), exception=traceback.format_exc()) 433 finally: 434 f.close() 435 436 return name 437 438 def set_permanent_hostname(self, name): 439 try: 440 try: 441 f = open(self.HOSTNAME_FILE, 'r') 442 lines = [x.strip() for x in f] 443 444 for i, line in enumerate(lines): 445 if line.startswith('hostname='): 446 lines[i] = 'hostname="%s"' % name 447 break 448 f.close() 449 450 f = open(self.HOSTNAME_FILE, 'w') 451 f.write('\n'.join(lines) + '\n') 452 except Exception as e: 453 self.module.fail_json(msg="failed to update hostname: %s" % 454 to_native(e), exception=traceback.format_exc()) 455 finally: 456 f.close() 457 458 459class OpenBSDStrategy(GenericStrategy): 460 """ 461 This is a OpenBSD family Hostname manipulation strategy class - it edits 462 the /etc/myname file. 463 """ 464 465 HOSTNAME_FILE = '/etc/myname' 466 467 def get_permanent_hostname(self): 468 if not os.path.isfile(self.HOSTNAME_FILE): 469 try: 470 open(self.HOSTNAME_FILE, "a").write("") 471 except IOError as e: 472 self.module.fail_json(msg="failed to write file: %s" % 473 to_native(e), exception=traceback.format_exc()) 474 try: 475 f = open(self.HOSTNAME_FILE) 476 try: 477 return f.read().strip() 478 finally: 479 f.close() 480 except Exception as e: 481 self.module.fail_json(msg="failed to read hostname: %s" % 482 to_native(e), exception=traceback.format_exc()) 483 484 def set_permanent_hostname(self, name): 485 try: 486 f = open(self.HOSTNAME_FILE, 'w+') 487 try: 488 f.write("%s\n" % name) 489 finally: 490 f.close() 491 except Exception as e: 492 self.module.fail_json(msg="failed to update hostname: %s" % 493 to_native(e), exception=traceback.format_exc()) 494 495 496class SolarisStrategy(GenericStrategy): 497 """ 498 This is a Solaris11 or later Hostname manipulation strategy class - it 499 execute hostname command. 500 """ 501 502 def set_current_hostname(self, name): 503 cmd_option = '-t' 504 cmd = [self.hostname_cmd, cmd_option, name] 505 rc, out, err = self.module.run_command(cmd) 506 if rc != 0: 507 self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err)) 508 509 def get_permanent_hostname(self): 510 fmri = 'svc:/system/identity:node' 511 pattern = 'config/nodename' 512 cmd = '/usr/sbin/svccfg -s %s listprop -o value %s' % (fmri, pattern) 513 rc, out, err = self.module.run_command(cmd, use_unsafe_shell=True) 514 if rc != 0: 515 self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err)) 516 return to_native(out).strip() 517 518 def set_permanent_hostname(self, name): 519 cmd = [self.hostname_cmd, name] 520 rc, out, err = self.module.run_command(cmd) 521 if rc != 0: 522 self.module.fail_json(msg="Command failed rc=%d, out=%s, err=%s" % (rc, out, err)) 523 524 525class FreeBSDStrategy(GenericStrategy): 526 """ 527 This is a FreeBSD hostname manipulation strategy class - it edits 528 the /etc/rc.conf.d/hostname file. 529 """ 530 531 HOSTNAME_FILE = '/etc/rc.conf.d/hostname' 532 533 def get_permanent_hostname(self): 534 535 name = 'UNKNOWN' 536 if not os.path.isfile(self.HOSTNAME_FILE): 537 try: 538 open(self.HOSTNAME_FILE, "a").write("hostname=temporarystub\n") 539 except IOError as e: 540 self.module.fail_json(msg="failed to write file: %s" % 541 to_native(e), exception=traceback.format_exc()) 542 try: 543 try: 544 f = open(self.HOSTNAME_FILE, 'r') 545 for line in f: 546 line = line.strip() 547 if line.startswith('hostname='): 548 name = line[10:].strip('"') 549 break 550 except Exception as e: 551 self.module.fail_json(msg="failed to read hostname: %s" % 552 to_native(e), exception=traceback.format_exc()) 553 finally: 554 f.close() 555 556 return name 557 558 def set_permanent_hostname(self, name): 559 try: 560 try: 561 f = open(self.HOSTNAME_FILE, 'r') 562 lines = [x.strip() for x in f] 563 564 for i, line in enumerate(lines): 565 if line.startswith('hostname='): 566 lines[i] = 'hostname="%s"' % name 567 break 568 f.close() 569 570 f = open(self.HOSTNAME_FILE, 'w') 571 f.write('\n'.join(lines) + '\n') 572 except Exception as e: 573 self.module.fail_json(msg="failed to update hostname: %s" % 574 to_native(e), exception=traceback.format_exc()) 575 finally: 576 f.close() 577 578 579class FedoraHostname(Hostname): 580 platform = 'Linux' 581 distribution = 'Fedora' 582 strategy_class = SystemdStrategy 583 584 585class SLESHostname(Hostname): 586 platform = 'Linux' 587 distribution = 'Sles' 588 try: 589 distribution_version = get_distribution_version() 590 # cast to float may raise ValueError on non SLES, we use float for a little more safety over int 591 if distribution_version and 10 <= float(distribution_version) <= 12: 592 strategy_class = SLESStrategy 593 else: 594 raise ValueError() 595 except ValueError: 596 strategy_class = UnimplementedStrategy 597 598 599class OpenSUSEHostname(Hostname): 600 platform = 'Linux' 601 distribution = 'Opensuse' 602 strategy_class = SystemdStrategy 603 604 605class OpenSUSELeapHostname(Hostname): 606 platform = 'Linux' 607 distribution = 'Opensuse-leap' 608 strategy_class = SystemdStrategy 609 610 611class OpenSUSETumbleweedHostname(Hostname): 612 platform = 'Linux' 613 distribution = 'Opensuse-tumbleweed' 614 strategy_class = SystemdStrategy 615 616 617class AsteraHostname(Hostname): 618 platform = 'Linux' 619 distribution = '"astralinuxce"' 620 strategy_class = SystemdStrategy 621 622 623class ArchHostname(Hostname): 624 platform = 'Linux' 625 distribution = 'Arch' 626 strategy_class = SystemdStrategy 627 628 629class ArchARMHostname(Hostname): 630 platform = 'Linux' 631 distribution = 'Archarm' 632 strategy_class = SystemdStrategy 633 634 635class AlmaLinuxHostname(Hostname): 636 platform = 'Linux' 637 distribution = 'Almalinux' 638 strategy_class = SystemdStrategy 639 640 641class ManjaroHostname(Hostname): 642 platform = 'Linux' 643 distribution = 'Manjaro' 644 strategy_class = SystemdStrategy 645 646 647class RHELHostname(Hostname): 648 platform = 'Linux' 649 distribution = 'Redhat' 650 strategy_class = RedHatStrategy 651 652 653class CentOSHostname(Hostname): 654 platform = 'Linux' 655 distribution = 'Centos' 656 strategy_class = RedHatStrategy 657 658 659class ClearLinuxHostname(Hostname): 660 platform = 'Linux' 661 distribution = 'Clear-linux-os' 662 strategy_class = SystemdStrategy 663 664 665class CloudlinuxserverHostname(Hostname): 666 platform = 'Linux' 667 distribution = 'Cloudlinuxserver' 668 strategy_class = RedHatStrategy 669 670 671class CloudlinuxHostname(Hostname): 672 platform = 'Linux' 673 distribution = 'Cloudlinux' 674 strategy_class = RedHatStrategy 675 676 677class CoreosHostname(Hostname): 678 platform = 'Linux' 679 distribution = 'Coreos' 680 strategy_class = SystemdStrategy 681 682 683class FlatcarHostname(Hostname): 684 platform = 'Linux' 685 distribution = 'Flatcar' 686 strategy_class = SystemdStrategy 687 688 689class ScientificHostname(Hostname): 690 platform = 'Linux' 691 distribution = 'Scientific' 692 strategy_class = RedHatStrategy 693 694 695class OracleLinuxHostname(Hostname): 696 platform = 'Linux' 697 distribution = 'Oracle' 698 strategy_class = RedHatStrategy 699 700 701class VirtuozzoLinuxHostname(Hostname): 702 platform = 'Linux' 703 distribution = 'Virtuozzo' 704 strategy_class = RedHatStrategy 705 706 707class AmazonLinuxHostname(Hostname): 708 platform = 'Linux' 709 distribution = 'Amazon' 710 strategy_class = RedHatStrategy 711 712 713class DebianHostname(Hostname): 714 platform = 'Linux' 715 distribution = 'Debian' 716 strategy_class = DebianStrategy 717 718 719class KylinHostname(Hostname): 720 platform = 'Linux' 721 distribution = 'Kylin' 722 strategy_class = DebianStrategy 723 724 725class CumulusHostname(Hostname): 726 platform = 'Linux' 727 distribution = 'Cumulus-linux' 728 strategy_class = DebianStrategy 729 730 731class KaliHostname(Hostname): 732 platform = 'Linux' 733 distribution = 'Kali' 734 strategy_class = DebianStrategy 735 736 737class UbuntuHostname(Hostname): 738 platform = 'Linux' 739 distribution = 'Ubuntu' 740 strategy_class = DebianStrategy 741 742 743class LinuxmintHostname(Hostname): 744 platform = 'Linux' 745 distribution = 'Linuxmint' 746 strategy_class = DebianStrategy 747 748 749class LinaroHostname(Hostname): 750 platform = 'Linux' 751 distribution = 'Linaro' 752 strategy_class = DebianStrategy 753 754 755class DevuanHostname(Hostname): 756 platform = 'Linux' 757 distribution = 'Devuan' 758 strategy_class = DebianStrategy 759 760 761class RaspbianHostname(Hostname): 762 platform = 'Linux' 763 distribution = 'Raspbian' 764 strategy_class = DebianStrategy 765 766 767class GentooHostname(Hostname): 768 platform = 'Linux' 769 distribution = 'Gentoo' 770 strategy_class = OpenRCStrategy 771 772 773class ALTLinuxHostname(Hostname): 774 platform = 'Linux' 775 distribution = 'Altlinux' 776 strategy_class = RedHatStrategy 777 778 779class AlpineLinuxHostname(Hostname): 780 platform = 'Linux' 781 distribution = 'Alpine' 782 strategy_class = AlpineStrategy 783 784 785class OpenBSDHostname(Hostname): 786 platform = 'OpenBSD' 787 distribution = None 788 strategy_class = OpenBSDStrategy 789 790 791class SolarisHostname(Hostname): 792 platform = 'SunOS' 793 distribution = None 794 strategy_class = SolarisStrategy 795 796 797class FreeBSDHostname(Hostname): 798 platform = 'FreeBSD' 799 distribution = None 800 strategy_class = FreeBSDStrategy 801 802 803class NetBSDHostname(Hostname): 804 platform = 'NetBSD' 805 distribution = None 806 strategy_class = FreeBSDStrategy 807 808 809class NeonHostname(Hostname): 810 platform = 'Linux' 811 distribution = 'Neon' 812 strategy_class = DebianStrategy 813 814 815class OsmcHostname(Hostname): 816 platform = 'Linux' 817 distribution = 'Osmc' 818 strategy_class = SystemdStrategy 819 820 821class VoidLinuxHostname(Hostname): 822 platform = 'Linux' 823 distribution = 'Void' 824 strategy_class = DebianStrategy 825 826 827class PopHostname(Hostname): 828 platform = 'Linux' 829 distribution = 'Pop' 830 strategy_class = DebianStrategy 831 832 833def main(): 834 module = AnsibleModule( 835 argument_spec=dict( 836 name=dict(type='str', required=True), 837 use=dict(type='str', choices=STRATS.keys()) 838 ), 839 supports_check_mode=True, 840 ) 841 842 hostname = Hostname(module) 843 name = module.params['name'] 844 845 current_hostname = hostname.get_current_hostname() 846 permanent_hostname = hostname.get_permanent_hostname() 847 848 changed = hostname.update_current_and_permanent_hostname() 849 850 if name != current_hostname: 851 name_before = current_hostname 852 elif name != permanent_hostname: 853 name_before = permanent_hostname 854 855 kw = dict(changed=changed, name=name, 856 ansible_facts=dict(ansible_hostname=name.split('.')[0], 857 ansible_nodename=name, 858 ansible_fqdn=socket.getfqdn(), 859 ansible_domain='.'.join(socket.getfqdn().split('.')[1:]))) 860 861 if changed: 862 kw['diff'] = {'after': 'hostname = ' + name + '\n', 863 'before': 'hostname = ' + name_before + '\n'} 864 865 module.exit_json(**kw) 866 867 868if __name__ == '__main__': 869 main() 870