[PYTHON] Ansible selbstgemachte Modul U / min Betrieb

Hintergrund und Notizen

Ansible hat kein rpm Modul.

Das ist richtig, denn es gibt "lecker".

Da es sich um ein Konfigurationsmanagement-Tool handelt, wird "rpm", das als "--force" bezeichnet werden kann, in "Ansible" nicht empfohlen.

Es gibt jedoch einige Sites, die frühere Systeme durch Zusammenfügen entwickelt haben, und es gibt Zeiten, in denen Sie wirklich eine 32-Bit-Drehzahl in eine 64-Bit-Maschine einfügen möchten. Wenn dies mit "yum" implementiert wird, kann es sein, dass "ich es nicht einfügen werde, weil es ein 64-Bit-Paket gibt".

Die ideale Form ist die Entwicklung im Hinblick auf das Konfigurationsmanagement. Dies ist ein veraltetes Modul. </ font>

Was Sie erreichen wollen

Ich werde es nicht so schwer machen

  • Die rpm-Datei wurde bereits mit copy usw. auf dem Knoten abgelegt.
  • Ich möchte in der Lage sein, eines Tages Dateien mit einem eingebauten Äquivalent zu copy zu platzieren. --Erhalten Sie die Option des Befehls rpm und verwenden Sie ihn so wie er ist ――Ich möchte eines Tages Flaggen verwalten
  • Bestätigen Sie, dass die angegebene rpm-Datei vorhanden ist
  • Vergewissern Sie sich, dass die angegebene Drehzahl nicht installiert ist --Installieren Sie die angegebene Drehzahl zusammen mit den angegebenen Optionen

Geht es darum?

Erstellen Sie eine Vorlage

Siehe frühere Artikel.

rpm.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

from ansible.module_utils.basic import AnsibleModule

#Hauptverarbeitung
#-----------------------------------------------------------
def main():
    #AnsibleModule-Klasse:Modul erstellen
    module = AnsibleModule(

        #Argumentempfang
        argument_spec=dict(

            #Schreiben Sie hier den Argumentempfangsprozess

        ),
        #Aktivieren Sie die Argumentprüfung
        supports_check_mode=True
    )

    #Überprüfen Sie, ob die angegebene Datei vorhanden ist

    #Beurteilung der Notwendigkeit einer Änderung
    changed = False

    #RPM-Installation

    #Verarbeitung beenden

if __name__ == '__main__':
    main()

Ich frage mich, ob dies der richtige Ort ist

Argumente erhalten

Die diesmal akzeptierten Argumente lauten wie folgt

Argumentname Verpflichtend Standardwert Bedeutung der Argumente
pkgs - Liste der Pakete
opts -Uvh Optionen für den Befehl rpm
chdir / Paketspeicherverzeichnis

Übrigens wusste ich nicht, wie ich die "Liste" erhalten sollte, also habe ich sie in einem bestimmten Q & A gepostet, aber am nächsten Tag habe ich sie selbst gelöst. Referenz: So verwenden Sie das in Ansible with_list übergebene Array für eine Schleife in einem Modul

rpm.py


:#(Kürzung)

#Argumentempfang
argument_spec=dict(
    #Paketliste(Verpflichtend,Listentyp)
    pkgs = dict(required = True, type = list),
    #Möglichkeit(str Typ,[-Uvh])
    opts = dict(required = False, type = str, default = '-Uvh'),
    #Paketspeicherverzeichnis(str Typ)
    chdir = dict(required = False, type = str, default = '/'),
),
#Aktivieren Sie die Argumentprüfung
supports_check_mode=True

:#(Kürzung)

Außerdem wird bei einem Teilauszug wie oben der Einzug am Zeilenanfang gelöscht. Weil es seitwärts lang sein wird.

Überprüfen Sie, ob die angegebene Datei vorhanden ist

Als ich das letzte Mal ein Modul für mkfifo erstellt habe, habe ich den Befehl stat und den Befehl test verwendet, ohne an irgendetwas zu denken, aber ich dachte, dass es so viele Module geben würde.

Referenz: Überprüfen Sie die Existenz der Datei mit Python

rpm.py


:#(Kürzung)

from ansible.module_utils.basic import AnsibleModule
import os

:#(Kürzung)

#Da es redundant wird, geben Sie die Variablen erneut ein
pkgs = module.params['pkgs']
chdir = module.params['chdir']

#Schleife für jede Paketliste
for pkg in pkgs:
    #Überprüfen Sie, ob die angegebene Datei vorhanden ist
    if (os.path.isfile(chdir + '/' + pkg)):
        #Datei wird nicht platziert
        module.fail_json(msg = chdir + '/' + pkg + ' is not found.')

:#(Kürzung)

Ich mache mir Sorgen, also lasst uns die Operation hier überprüfen. Ich habe rpm noch nicht in / tmp / platziert.

test.yml


- name: ntp install
  rpm:
    pkgs: '{{ item }}'
    opts: '-ivh'
    chdir: '/tmp'
  with_list:
    - [ 'ntp-4.2.6p5-15.el6.centos.x86_64.rpm','ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm' ]

Funktionsprüfung


$ ansible-playbook -i test_grp -l test_srv -u root test.yml -vvv
:#(Kürzung)

ok: [192.168.56.104] => (item=[u'ntp-4.2.6p5-15.el6.centos.x86_64.rpm', u'ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm']) => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "chdir": "/tmp",
            "opts": "-ivh",
            "pkgs": [
                "ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
                "ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
            ]
        }
    },
    "item": [
        "ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
        "ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
    ]
}

Das ... ein kleines Debug.

rpm.py


#Da es redundant wird, geben Sie die Variablen erneut ein
pkgs = module.params['pkgs']
chdir = module.params['chdir']
num = 0
hog = 0
#Schleife für jede Paketliste
for pkg in pkgs:
    num += 1
    #Überprüfen Sie, ob die angegebene Datei vorhanden ist
    if (os.path.isfile(chdir + '/' + pkg)):
        hog += 1
        #Datei wird nicht platziert
        module.fail_json(msg = chdir + '/' + pkg + ' is not found.')

:#(Kürzung)

module.exit_json(num = num, hog = hog)

Ausführungsergebnis


ok: [192.168.56.104] => (item=[u'ntp-4.2.6p5-15.el6.centos.x86_64.rpm', u'ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm']) => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "ansible_loop_var": "item",
    "changed": false,
    "hog": 0,  ★
    "invocation": {
        "module_args": {
            "chdir": "/tmp",
            "opts": "-ivh",
            "pkgs": [
                "ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
                "ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
            ]
        }
    },
    "item": [
        "ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
        "ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
    ],
    "num": 2  ★
}

Hmmm if (os.path.isfile (chdir + '/' + pkg)): ist falsch. Als Ergebnis verschiedener Versuche hat if os.path.isfile (chdir + '/' + pkg) == False: funktioniert. Hmm warum?

rpm.py


:#(Kürzung)

from ansible.module_utils.basic import AnsibleModule
import os

:#(Kürzung)

#Da es redundant wird, geben Sie die Variablen erneut ein
pkgs = module.params['pkgs']
chdir = module.params['chdir']

#Schleife für jede Paketliste
for pkg in pkgs:
    #Überprüfen Sie, ob die angegebene Datei vorhanden ist
    if os.path.isfile(chdir + '/' + pkg) == False:
        #Datei wird nicht platziert
        module.fail_json(msg = chdir + '/' + pkg + ' is not found.')

:#(Kürzung)

Beurteilung der Notwendigkeit einer Änderung

Keine Notwendigkeit zu ändern, das heißt, wenn alle pkg bereits installiert sind. Mit dem folgenden Befehl können Sie feststellen, ob das Paket "rpm" installiert ist.

$ rpm -q ntp-4.2.6p5-15.el6.centos.x86_64
ntp-4.2.6p5-15.el6.centos.x86_64
$ echo $?
0

$ rpm -q hoge
Package Hoge ist nicht installiert.
$ echo $?
1

Die rpm-Datei ist jedoch nicht immer der Paketname ohne die .rpm am Ende des Dateinamens.

$ ls -1 jdk-8u192-linux-x64.rpm
jdk-8u192-linux-x64.rpm

$ rpm -q jdk-8u192-linux-x64
Paket jdk-8u192-linux-x64 ist nicht installiert.

$ rpm -qa | grep jdk
jdk1.8-1.8.0_192-fcs.x86_64

Im obigen Beispiel lautet der Dateiname "jdk-8u192-linux-x64.rpm", der Paketname jedoch "jdk1.8-1.8.0_192-fcs.x86_64".

Um dies festzustellen, müssen Sie den Paketnamen mit rpm -qp rpm file name nachschlagen.

$ rpm -qp jdk-8u192-linux-x64.rpm
Warnung: jdk-8u192-linux-x64.rpm:Header V3 RSA/SHA256 Signature, key ID ec551f03: NOKEY
jdk1.8-1.8.0_192-fcs.x86_64

Der Paketname wird aus der obigen Standardausgabe erhalten.

Integrieren Sie diesen Prozess in das Modul

rpm.py


:#(Kürzung)

#Da es redundant wird, geben Sie die Variablen erneut ein
pkgs = module.params['pkgs']
chdir = module.params['chdir']

#Beurteilung der Notwendigkeit einer Änderung
changed = False

#Liste der zu installierenden RPM-Dateien
rpms = []

#Schleife für jede Paketliste
for pkg in pkgs:

    #Erstellen Sie den vollständigen Dateipfad
    fpath = chdir + '/' + pkg

    #Überprüfen Sie, ob die angegebene Datei vorhanden ist
    if os.path.exists(fpath) == False:
        #Datei wird nicht platziert
        module.fail_json(msg = fpath + ' is not found.')

    #Rufen Sie den Paketnamen aus der RPM-Datei ab
    rc, pkg_name, stderr = module.run_command('rpm -qp ' + fpath)

    #Überprüfen Sie den Installationsstatus des Pakets
    rc, stdout, stderr = module.run_command('rpm -q ' + pkg_name)

    #Ist es installiert?
    if rc != 0:
        #Nicht installiert, daher Änderung erforderlich
        changed = True
        #Zum Installationsziel hinzufügen
        rpms.append(fpath)

:#(Kürzung)

RPM-Installation

Wenn die RPM-Liste des Installationsziels rpms leer ist, endet sie ... Sie wird chagned! = True überlassen.

rpm.py


:#(Kürzung)

#Beurteilung der Notwendigkeit der Drehzahlinstallation
if changed != True:
    #Nicht zu installieren
    module.exit_json()

#RPM-Listenerstellung
rpm_line = ' '.join(rpms)

#RPM-Installation
rc, stdout, stderr = module.run_command('rpm ' + module.params['opts'] + ' ' + rpm_line)

#U / min Beurteilung des Installationsergebnisses
if rc != 0:
    #Installation fehlgeschlagen
    module.fail_json(stdout = stdout, stderr = stderr)

#Verarbeitung beenden
module.exit_json(changed = changed)

:#(Kürzung)

Probelauf

test.yml


- name: ntp install
  rpm:
    pkgs: '{{ item }}'
    opts: '-ivh'
    chdir: '/tmp'
  with_list:
    - [ 'ntp-4.2.6p5-15.el6.centos.x86_64.rpm','ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm' ]
#Stellen Sie sicher, dass die Paketdatei vorhanden ist
$ ssh [email protected] "ls -l /tmp/*rpm"
-rw-rw-r--.1 Wurzel Wurzel 614364 11. Mai 17:01 2020 /tmp/ntp-4.2.6p5-15.el6.centos.x86_64.rpm
-rw-rw-r--.1 Wurzel Wurzel 80836 11. Mai 17:00 2020 /tmp/ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm

#Stellen Sie sicher, dass die Paketdatei nicht installiert ist
$ ssh [email protected] "rpm -qa | grep ntp"
$

#Lauf!
$ ansible-playbook -i test_grp -l test_srv -u root test.yml -vvv
:#(Kürzung)
changed: [192.168.56.104] => (item=[u'ntp-4.2.6p5-15.el6.centos.x86_64.rpm', u'ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm']) => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "ansible_loop_var": "item",
    "changed": true,
    "invocation": {
        "module_args": {
            "chdir": "/tmp",
            "opts": "-ivh",
            "pkgs": [
                "ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
                "ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
            ]
        }
    },
    "item": [
        "ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
        "ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
    ],
    "msg": "/tmp/ntp-4.2.6p5-15.el6.centos.x86_64.rpm /tmp/ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
}

#Führen Sie erneut aus, um die Gleichheit zu überprüfen!
$ ansible-playbook -i test_grp -l test_srv -u root test.yml -vvv
ok: [192.168.56.104] => (item=[u'ntp-4.2.6p5-15.el6.centos.x86_64.rpm', u'ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm']) => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "chdir": "/tmp",
            "opts": "-ivh",
            "pkgs": [
                "ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
                "ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
            ]
        }
    },
    "item": [
        "ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
        "ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
    ]
}

Ist es nicht okay?

Modul erstellt

rpm.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

from ansible.module_utils.basic import AnsibleModule
import os

#Hauptverarbeitung
#-----------------------------------------------------------
def main():
    #AnsibleModule-Klasse:Modul erstellen
    module = AnsibleModule(

        #Argumentempfang
        argument_spec=dict(
            #Paketliste(Verpflichtend,Listentyp)
            pkgs = dict(required = True, type = list),
            #Möglichkeit(str Typ,[-Uvh])
            opts = dict(required = False, type = str, default = '-Uvh'),
            #Paketspeicherverzeichnis(str Typ)
            chdir = dict(required = False, type = str, default = '/'),
        ),
        #Aktivieren Sie die Argumentprüfung
        supports_check_mode=True
    )

    #Da es redundant wird, geben Sie die Variablen erneut ein
    pkgs = module.params['pkgs']
    chdir = module.params['chdir']

    #Beurteilung der Notwendigkeit einer Änderung
    changed = False

    #Liste der zu installierenden RPM-Dateien
    rpms = []

    #Schleife für jede Paketliste
    for pkg in pkgs:

        #Erstellen Sie den vollständigen Dateipfad
        fpath = chdir + '/' + pkg

        #Überprüfen Sie, ob die angegebene Datei vorhanden ist
        if os.path.exists(fpath) == False:
            #Datei wird nicht platziert
            module.fail_json(msg = fpath + ' is not found.')

        #Rufen Sie den Paketnamen aus der RPM-Datei ab
        rc, pkg_name, stderr = module.run_command('rpm -qp ' + fpath)

        #Überprüfen Sie den Installationsstatus des Pakets
        rc, stdout, stderr = module.run_command('rpm -q ' + pkg_name)

        #Ist es installiert?
        if rc != 0:
            #Nicht installiert, daher Änderung erforderlich
            changed = True
            #Zum Installationsziel hinzufügen
            rpms.append(fpath)

    #Beurteilung der Notwendigkeit der Drehzahlinstallation
    if changed != True:
        #Nicht zu installieren
        module.exit_json()

    #RPM-Listenerstellung
    rpm_line = ' '.join(rpms)

    #RPM-Installation
    rc, stdout, stderr = module.run_command('rpm ' + module.params['opts'] + ' ' + rpm_line)

    #U / min Beurteilung des Installationsergebnisses
    if rc != 0:
        #Installation fehlgeschlagen
        module.fail_json(stdout = stdout, stderr = stderr)

    #Verarbeitung beenden
    module.exit_json(changed = changed)

if __name__ == '__main__':
    main()

Recommended Posts

Ansible selbstgemachte Modul U / min Betrieb
Ansible selbst erstellte Modulerstellung - Teil 2: Das Leben will nur Befehle ausführen -
Ansible Erstellen Sie Ihr eigenes Modul - Teil 1: Leben, das Sie Argumente erhalten möchten -