===== Python Implementierung vom netmanager ===== ===== Check DNS ===== === OS Programm Aufruf in Python === Hier als Beispiel als Aufruf vom Programm ''host'' mit einer beliebigen URL: import os def get_ip_address(url): command = "host " + url process = os.popen(command) Im ''dda'' miteinbauen? ''import sys'' Aufruf der unten angegebenen DNS-Tools. You can also use the named-checkzone utility that is part of the bind9 package: named-checkzone example.com /etc/bind/db.example.com and named-checkzone 1.168.192.in-addr.arpa. /etc/bind/db.192 This is a great way to make sure you haven't made any mistakes before restarting bind9. You can use the dig utility to test the reverse zone as well as the new domain name: dig 1.168.192.in-addr.arpa. AXFR You should see output resolving 1.168.192.in-addr.arpa. to your nameserver. === it.example.de/MX 'mail.it.example.de' has no address records (A or AAAA) === Um die Fehlermeldung zu beheben, muss in der MX-Zeile des Header-Files, der Hostname des Mail-Servers eingetragen werden. Ausserdem muss ein gültiger DNS-Eintag vorhanden sein. NS dhcp1 ; Master DNS NS dhcp2 ; Slave DNS MX 10 postfix1 ; Mail Server postfix1 A 192.168.178.20 Evtl. muss dieser Eintag auch in anderen Zonen gesetzt werden, mit anderen Domain Namen. ==== SUSE ==== Die Software befindet sich bei SUSE in folgenden Paketen: === named-checkzone === rpm -qf /usr/sbin/named-checkzone bind-9.9.9P1-63.7.1.x86_64 === dhcpd === rpm -qf /usr/sbin/dhcpd dhcp-server-4.3.3-10.14.1.x86_64 ==== Debian / Raspbian ==== sudo apt install bind9utils which named-checkzone /usr/sbin/named-checkzone ==== Check DHCP ==== The syntax you are looking for is dhcpd -t -cf /path/to/dhcpd.conf The -t option will do a config check: If the -t flag is specified, the server will simply test the configuration file for correct syntax, but will not attempt to perform any network operations. This can be used to test the new configuration file automatically before installing it. You do not need to use -cf if you are using the default config file path. /usr/sbin/dhcpd -t The one you tried with -tf /path/to/... is quite different and relates to tracing. ==== Packages ==== Mehrere Module können auch in einem Paket (package) zusammengefasst werden. Ein Paket ist im Prinzip ein Verzeichnis, welches Python-Module enthält. Zusätzlich dazu muss es noch eine Datei mit dem Namen ''__init__.py'' enthalten. Diese Datei kann leer sein oder Python-Code enthalten der bei Import des Paketes ausgeführt werden soll. Pakete werden wie normale Module importiert. ==== Mengen ==== Mit Mengen arbeiten um doppelte Elemente wie IP, Hostnamen und MAC Adr. zu beseitigen. Mengen im PDF Seite 39 ==== Eingabe ==== === Split === String in Liste umwandeln, zur Speicherung von Rechnername, MAC und VLAN EINGABE = input("Bitte Werte eingeben: ") LISTEA = EINGABE.split() print (type(LISTEA)) print(LISTEA[1]) ==== IP-Adressen generieren ==== IP-Adressen für VLAN erstellen mit for-Anweisung und der Funktion range(). Mit Seperator ''sep="."'' wird vor der Variablen ''i'' das Leerzeichen, welches Standardmäßig von ''print'' eingefügt wird, durch einem Punkt ersetzt. for i in range(1, 11): print("192.168.178",i,sep=".") ... 192.168.178.1 192.168.178.2 192.168.178.3 192.168.178.4 192.168.178.5 192.168.178.6 192.168.178.7 192.168.178.8 192.168.178.9 192.168.178.10 ==== Reverse IP ==== Hier ohne ipaddress Modul. Ein Beispiel welches sich auf IP übertragen lässt: >>> ip '172.16.1.20' >>> >>> >>> ip = ip.replace("."," ") >>> ip '172 16 1 20' >>> revword = ip.split() >>> >>> revword ['172', '16', '1', '20'] >>> revword.reverse() >>> revword ['20', '1', '16', '172'] >>> revword='.'.join(revword) >>> revword '20.1.16.172' ==== Strings bearbeiten ==== None Datentypen zusammensetzten, diese als Sting umwandeln und als nächstes mit Leerzeichen trennen. summemacs += "{} ".format(str(macvondeldev)) ==== Listen bearbeiten ==== >>> IPADR ['192', '168', '178', '2'] >>> >>> >>> IPADR[3] '2' >>> IPADR[3]="48" >>> IPADR ['192', '168', '178', '48'] Spalten aus zwei Listen zusammenführen. Hier zum Beispiel eine Liste mit Geräten und eine Liste mit MAC-Adr. welche zusammen geführt werden sollen. Als Ergebnis soll in der ersten Spalte die Geräte untereinander und in der zweiten die MAC-Adr. untereinander stehen. print ([x + y for x, y in zip(l_filter_devices,l_filter_mac)]) ==== Prüfung, ob Element in Sequenz enthalten ==== Zur Prüfung ob IP-Adr. schon vergeben im VLAN. Hier ist i.d.R. nur die letzte Nr. der IP-Adr. von Interesse. Es lässt sich ohne Probleme nur auf die letzte Nr. prüfen ohne das die vorderen Bereiche berücksichtigt werden. Bei Sequenzen kann man auch prüfen, ob (oder ob nicht) ein Element in einer Sequenz vorhanden ist. Dafür gibt es die Operatoren "in" und "not in". Die Arbeitsweise erkennt man im folgenden Protokoll einer interaktiven Sitzung: >>> IPADR ['192', '168', '178', '48'] >>> "178" in IPADR True >>> "178" in IPADR[3] False >>> "48" in IPADR[3] True ===== Dictionaries Zuordnungen ===== Die Hauptoperationen, die an einem Dictionary durchgeführt werden, sind die Ablage eines Wertes unter einem Schlüssel und der Abruf eines Wertes mit dem gegebenen Schlüssel. Es ist auch möglich ein Schlüssel-Wert-Paar per ''del'' zu löschen. Legt man einen Wert unter einem Schlüssel ab, der schon benutzt wird, Überschreibt man den alten Wert, der vorher mit diesem Schlüssel verknüpft war. Einen Wert mit einem nicht-existenten Schlüssel abrufen zu wollen, erzeugt eine Fehlermeldung. Der Aufruf ''list(d.keys())'' auf ein Dictionary gibt eine Liste aller Schlüssel in zufälliger Reihenfolge zurück (will man sie sortiert haben, verwendet man einfach die Funktion ''sorted(d.keys())'' stattdessen).2 Um zu über- prüfen ob ein einzelner Schlüssel im Dictionary ist, lässt sich das Schlüsselwort ''in'' benutzen. Ein Beispiel im Python Tut war eine typische Übersetzung von englisch/deutsch und deutsch/französisch. Durch Verknüpfung beider Dictionaries konnte man nun auch von Französisch nach Englisch übersetzen. Mit dem Wissen kann man das gleich nun auch auf Netzwerk ebene anwenden. Eine Übersetzung von IP/DEVICE und DEVICE/MAC ermöglich eine Zuordnung der abgefragten IP-Adr zu einem Geräte-Namen und einer MAC-Adr. >>> list(dda.keys()) ['e9999', 'e1234'] >>> list(dda.keys())[1] 'e1234' >>> list(dda.keys())[0] 'e9999' >>> list(dda.values()) ['66:55:44:33:22', '00:11:22:33:44'] >>> list(dda.values())[0] '66:55:44:33:22' - Konfig Dateien als Dict. einlesen - DHCP Konfig Dateien als ein Dict. erstellen - DNS Konfig Dateien als ein Dict. erstellen - Dict. verknüpfen ## Dictionaries Zuordnungen ## IP_DEVICE = {"172.16.1.1" : "e5101", "172.16.1.2" : "e5102", "172.16.1.3" : "e5103"} DEVICE_MAC = {"e5101" : "00:00:00:00:00:01", "e5102" : "00:00:00:00:00:02", "e5103" : "00:00:00:00:00:03"} print(IP_DEVICE["172.16.1.1"]) print(MAC_DEVICE["e5101"]) print(MAC_DEVICE[IP_DEVICE["172.16.1.1"]]) ==== Erzeuge Dict. aus zwei Eingabe Listen ==== # # Erzeuge Dict. aus zwei Eingabe Listen # l_devices = devices.split() l_macadr = macadr.split() d_eingabe = {} for dev, mac in zip(l_devices, l_macadr): d_eingabe[dev] = [ mac, None ] # ip = None print (d_eingabe) weitere Beispiele: >>> d_xxx = {} >>> for dev, mac, ips in zip(l_dev, m_dev, l_ips): ... d_xxx[dev, mac] = [ ips ] ... >>> d_xxx {('e111', '11:11:11'): ['172.16.6.14'], ('e222', '22:22:22'): ['172.16.6.11'], ('e333', '33:33:33'): ['172.16.6.12']} >>> for dev, mac, ips in zip(l_dev, m_dev, l_ips): ... d_xxx[dev, mac] = [ ips ] ... >>> d_xxx {('e111', '11:11:11'): ['172.16.6.14'], ('e222', '22:22:22'): ['172.16.6.11'], ('e333', '33:33:33'): ['172.16.6.12']} >>> l_ips ['172.16.6.14', '172.16.6.11', '172.16.6.12', '172.16.6.13', '172.16.6.16', '172.16.6.17'] >>> l_ips = ['192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.4', '192.168.1.5'] >>> >>> >>> for dev, mac, ips in zip(l_dev, m_dev, l_ips): ... d_xxx[dev, mac] = [ ips ] ... >>> >>> d_xxx {('e111', '11:11:11'): ['192.168.1.1'], ('e222', '22:22:22'): ['192.168.1.2'], ('e333', '33:33:33'): ['192.168.1.3']} >>> ==== Dictionarys zusammenfügen ==== Mit der Methode update() kann man ein zweites Dictionary in ein Dictionary einhängen. Enthält das zweite Dictionary Schlüssel, die auch im ersten vorkommen, so werden diese mit den Werten des zweiten überschrieben. >>> w={"house":"Haus","cat":"Katze","red":"rot"} >>> w1 = {"red":"rouge","blau":"bleu"} >>> w.update(w1) >>> print(w) {'house': 'Haus', 'blau': 'bleu', 'red': 'rouge', 'cat': 'Katze'} ===== Dateien ===== ==== startswith/endswith ==== https://www-user.tu-chemnitz.de/~hot/PYTHON/crash_kurs_py3/ ==== Einlesen ==== Datei als Liste einlesen: VLANDATEI = open("0600/vlan0600.in").readlines() print(VLANDATEI[2:8]) ==== Unterschiede beim Einlesen ==== >>> lines = [] >>> with open ('dda_dict/vlans/vlan0100.in') as file: ... lines = file.read().splitlines() ... >>> print(lines) ['e1001 01:22:33:44:55:16 172.16.1.1', 'e1002 02:22:33:44:55:16 172.16.1.2', 'e1003 03:22:33:44:55:16 172.16.1.3', 'e1004 04:22:33:44:55:16 172.16.1.4', 'e1005 05:22:33:44:55:16 172.16.1.5', 'e1006 06:22:33:44:55:16 172.16.1.6', 'e1007 07:22:33:44:55:16 172.16.1.7', 'e1008 08:22:33:44:55:16 172.16.1.8', 'e1009 09:22:33:44:55:16 172.16.1.9', 'e1010 10:22:33:44:55:16 172.16.1.10', 'e1011 11:22:33:44:55:16 172.16.1.11', 'e1012 12:22:33:44:55:16 172.16.1.12', 'e1013 13:22:33:44:55:16 172.16.1.13', 'e1014 14:22:33:44:55:16 172.16.1.14', 'e1015 15:22:33:44:55:16 172.16.1.15', 'e1016 16:22:33:44:55:16 172.16.1.16', 'e1017 17:22:33:44:55:16 172.16.1.17', 'e1018 18:22:33:44:55:16 172.16.1.18', 'e1019 19:22:33:44:55:16 172.16.1.19', 'e1020 20:22:33:44:55:16 172.16.1.20', 'e1021 21:22:33:44:55:16 172.16.1.21', 'e1022 22:22:33:44:55:16 172.16.1.22', 'e1023 23:22:33:44:55:16 172.16.1.23', 'e1024 24:22:33:44:55:16 172.16.1.24', 'e1025 25:22:33:44:55:16 172.16.1.25', 'e1026 26:22:33:44:55:16 172.16.1.26', 'e1027 27:22:33:44:55:16 172.16.1.27', 'e1028 28:22:33:44:55:16 172.16.1.28', 'e1029 29:22:33:44:55:16 172.16.1.29', 'e1030 30:22:33:44:55:16 172.16.1.30', 'e1031 31:22:33:44:55:16 172.16.1.31', 'e1032 32:22:33:44:55:16 172.16.1.32', 'e1033 33:22:33:44:55:16 172.16.1.33', 'e1034 34:22:33:44:55:16 172.16.1.34', 'e1035 35:22:33:44:55:16 172.16.1.35', 'e1036 36:22:33:44:55:16 172.16.1.36', 'e1037 37:22:33:44:55:16 172.16.1.37', 'e1038 38:22:33:44:55:16 172.16.1.38', 'e1039 39:22:33:44:55:16 172.16.1.39', 'e1040 40:22:33:44:55:16 172.16.1.40', 'e1041 41:22:33:44:55:16 172.16.1.41', 'e1042 42:22:33:44:55:16 172.16.1.42', 'e1043 43:22:33:44:55:16 172.16.1.43', 'e1044 44:22:33:44:55:16 172.16.1.44', 'e1045 45:22:33:44:55:16 172.16.1.45', 'e1046 46:22:33:44:55:16 172.16.1.46', 'e1047 47:22:33:44:55:16 172.16.1.47', 'e1048 48:22:33:44:55:16 172.16.1.48', 'e1049 49:22:33:44:55:16 172.16.1.49'] >>> >>> lines = [] >>> with open ('dda_dict/vlans/vlan0100.in') as file: ... lines = file.readlines() ... >>> print(lines) ['e1001 01:22:33:44:55:16 172.16.1.1\n', 'e1002 02:22:33:44:55:16 172.16.1.2\n', 'e1003 03:22:33:44:55:16 172.16.1.3\n', 'e1004 04:22:33:44:55:16 172.16.1.4\n', 'e1005 05:22:33:44:55:16 172.16.1.5\n', 'e1006 06:22:33:44:55:16 172.16.1.6\n', 'e1007 07:22:33:44:55:16 172.16.1.7\n', 'e1008 08:22:33:44:55:16 172.16.1.8\n', 'e1009 09:22:33:44:55:16 172.16.1.9\n', 'e1010 10:22:33:44:55:16 172.16.1.10\n', 'e1011 11:22:33:44:55:16 172.16.1.11\n', 'e1012 12:22:33:44:55:16 172.16.1.12\n', 'e1013 13:22:33:44:55:16 172.16.1.13\n', 'e1014 14:22:33:44:55:16 172.16.1.14\n', 'e1015 15:22:33:44:55:16 172.16.1.15\n', 'e1016 16:22:33:44:55:16 172.16.1.16\n', 'e1017 17:22:33:44:55:16 172.16.1.17\n', 'e1018 18:22:33:44:55:16 172.16.1.18\n', 'e1019 19:22:33:44:55:16 172.16.1.19\n', 'e1020 20:22:33:44:55:16 172.16.1.20\n', 'e1021 21:22:33:44:55:16 172.16.1.21\n', 'e1022 22:22:33:44:55:16 172.16.1.22\n', 'e1023 23:22:33:44:55:16 172.16.1.23\n', 'e1024 24:22:33:44:55:16 172.16.1.24\n', 'e1025 25:22:33:44:55:16 172.16.1.25\n', 'e1026 26:22:33:44:55:16 172.16.1.26\n', 'e1027 27:22:33:44:55:16 172.16.1.27\n', 'e1028 28:22:33:44:55:16 172.16.1.28\n', 'e1029 29:22:33:44:55:16 172.16.1.29\n', 'e1030 30:22:33:44:55:16 172.16.1.30\n', 'e1031 31:22:33:44:55:16 172.16.1.31\n', 'e1032 32:22:33:44:55:16 172.16.1.32\n', 'e1033 33:22:33:44:55:16 172.16.1.33\n', 'e1034 34:22:33:44:55:16 172.16.1.34\n', 'e1035 35:22:33:44:55:16 172.16.1.35\n', 'e1036 36:22:33:44:55:16 172.16.1.36\n', 'e1037 37:22:33:44:55:16 172.16.1.37\n', 'e1038 38:22:33:44:55:16 172.16.1.38\n', 'e1039 39:22:33:44:55:16 172.16.1.39\n', 'e1040 40:22:33:44:55:16 172.16.1.40\n', 'e1041 41:22:33:44:55:16 172.16.1.41\n', 'e1042 42:22:33:44:55:16 172.16.1.42\n', 'e1043 43:22:33:44:55:16 172.16.1.43\n', 'e1044 44:22:33:44:55:16 172.16.1.44\n', 'e1045 45:22:33:44:55:16 172.16.1.45\n', 'e1046 46:22:33:44:55:16 172.16.1.46\n', 'e1047 47:22:33:44:55:16 172.16.1.47\n', 'e1048 48:22:33:44:55:16 172.16.1.48\n', 'e1049 49:22:33:44:55:16 172.16.1.49\n'] >>> ==== Dateien schreiben ==== Eine Datei schreiben, Pfad angeben und Dateiendung vergeben: def write(self): ''' Schreiben der DNS-Zonefiles. Diese Dateien enthalten die Inhalte der modifizierten DNS-Header und VLAN-Dateien ''' output_path = '../output/' completehfileName = path.join(output_path, self.name+".de") # Aufruf der Fkt. zonefileformat() l_zfformatlines = self._zonefileformat() print ("update Datei: {}".format(completehfileName)) with open(completehfileName, 'w') as zonefile: zonefile.write(self._header) zonefile.writelines(l_zfformatlines) ==== Mehrere Lines aus Datei entfernen ==== Zum Beispiel aus einer Übergabe an das Python Programm sollen mehrere PC-Nr. aus einer Datei-Liste entfernt werden. Hier wird ''startswith'' verwendet. Eine for-Schleife mit ''enumerate'' und dessen Index hatte hier zu Problemen geführt, da beim löschen mit ''del lines[i]'' der Index verrutscht und nur jede zweite Zeile entfernt wird. An ''startswith'' kann man keine Eingabe Listen übergeben aber dafür eine **Tupel**. Die am Python Programm übergebenen PC-Nummern wurden in einer Liste gespeichert welche in eine Tupel gewandelt wurden. def remove_line_with_device(self): vlandatei = open(self._full_fn,"w") for line in self._lines: if not line.startswith(self.t_devices): vlandatei.write(line) print(line) vlandatei.close() **shelve-Modul** verwenden um Konfig-Dateien einzulesen und zu bearbeiten. Man kann ein shelve-Objekt auch einfach mit dem dict-Casting-Operator in ein Dictionary wandeln: >>> s ≤shelve.DbfilenameShelf object at 0xb7133dcc> >>> dict(s) {'city': 'London', 'street': 'Fleet Str'} >>> Im folgenden Beispiel demonstrieren wir, dass wir in einem Shelf-Eintrag auch komplexe Objekte, wie beispielsweise Dictionaries abspeichern können: >>> import shelve >>> tele = shelve.open("MyPhoneBook") >>> tele["Mike"] = {"first":"Mike", "last":"Miller", "phone":"4689"} >>> tele["Steve"] = {"first":"Stephan", "last":"Burns", "phone":"8745"} >>> tele["Eve"] = {"first":"Eve", "last":"Naomi", "phone":"9069"} >>> tele["Eve"]["phone"] '9069' Die Daten sind auch in diesem Fall persistent gespeichert, d.h. man kann Sie auch wieder in einem späteren Programmlauf benutzen. Alles was man tun muss, ist die Datei MyPhoneBook zu öffnen: $ python3 Python 3.2.3 (default, Feb 28 2014, 00:22:33) [GCC 4.7.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import shelve >>> tele = shelve.open("MyPhoneBook") >>> tele["Steve"]["phone"] '8745' >>> ===== Ablauf Optimierung mit cProfile ===== [[http://www.linux-magazin.de/ausgaben/2006/12/gut-gezielt/2/]] import cProfile import sys sys.argv.append("-update") f = open("dda.py") ef = f.read() f.close() cProfile.run(ef, "dda.stats") import pstats s = pstats.Stats("dda.stats") s.sort_stats('time') s.print_stats(10) Fri Jul 27 16:03:10 2018 dda.stats 9945 function calls (9898 primitive calls) in 0.235 seconds Ordered by: internal time List reduced from 274 to 10 due to restriction <10> ncalls tottime percall cumtime percall filename:lineno(function) 87 0.088 0.001 0.088 0.001 {built-in method builtins.print} 19 0.030 0.002 0.031 0.002 {built-in method io.open} 10/1 0.013 0.001 0.235 0.235 {built-in method builtins.exec} 9 0.010 0.001 0.010 0.001 {method 'read' of '_io.FileIO' objects} 9 0.007 0.001 0.007 0.001 {built-in method marshal.loads} 1 0.005 0.005 0.031 0.031 /home/ronni/Dokumente/Projekte/eric/dda/DnsZonefile.py:83(_reversefileformat) 26 0.005 0.000 0.024 0.001 {built-in method builtins.__build_class__} 1339 0.005 0.000 0.005 0.000 {method 'format' of 'str' objects} 1342 0.004 0.000 0.004 0.000 {method 'split' of 'str' objects} 721 0.002 0.000 0.002 0.000 {method 'join' of 'str' objects} >>> >>> [[https://stackoverflow.com/questions/7165465/optimizing-python-code]] Man kann eine Funktion in cProfile testen lassen wie folgt: import cProfile cProfile.run('myFunction()', 'myFunction.profile') Then to view the results: import pstats stats = pstats.Stats('myFunction.profile') stats.strip_dirs().sort_stats('time').print_stats() This will show you in which functions most of the time is spent.