KVM, video QXL und video virtio Treiber – Video-Auflösung des Gnome-Desktops eines Debian 8-Gastystems einstellen

Das Gespann KVM/Qemu ist großartig und aus meinem Linux-Leben nicht mehr wegzudenken. Vorgestern habe ich ein “Debian 8”-Gast-System für Testzwecke auf einem KVM-Host aufgesetzt, der unter “Opensuse Leap 42.2” betrieben wird. Dabei fiel mir auf, dass bzgl. des Punktes “Video” (-System) während der Konfiguration der virtuellen Maschine mittels “virt-manager” nun neben dem guten und vertrauten qxl auch eine “virtio”-Komponente zur Auswahl bereitsteht. Beide Varianten verkörpern unterschiedliche “Treiber” mit denen das Gastsystem eine virtuelle Grafikkarte ansprechen kann. Als Kommunikationsprotokoll für den Transport der Grafikinformation zum Host setze ich typischerweise Spice ein.

Mir stellte sich dann die Frage, wie man eigentlich als User die Auflösung bestimmen kann, mit der das Spice-Fenster für den Gast-Desktop (hier: Gnome 3) unter dem X-Window-System des Hosts (hier: unter KDE-Plasma5) dargestellt wird. Das ist vor allem für den Fall des “virtio”-Treiber interessant. Da der Hypervisor hier wohl direkt über die Hostsystem-Treiber auf die Grafikkarte des Hostes (bzw. Speicheradressen der Graka) zugreift, war es für mich unklar, was ich an Einstellmöglichkeiten erwarten darf. Die Maximalauflösung des Hauptschirms am Host? Eine Liste von verschiedenen Auflösungen unterhalb einer Maximalauflösung?

Voraussetzung

Auf meinem Test-Host betreibe ich 3 Schirme im “xinerama”-Verbund an einer Nvidia-Grafikkarte (GTX 960; proprietärer Treiber der Version 375). Ich möchte natürlich das KVM-Fenster (genauer das Spice-Fenster) für den Gast nicht mit der Maximalauflösung des xinerama-Verbunds (7040×1440 Pixel) betreiben. Umso wichtiger ist für den User also eine angemessene, einfache Einstellmöglichkeiten im Gast-System selbst, die sich dann auf die Darstellung des Gast-Fensters auf dem Host niederschlagen soll.

Unterschiede in den Einstellmöglichkeiten beim Einsatz von QXL und virtio

Installiert man einen KVM-Gast unter “virt-manager” und kümmert sich nicht weiter um die Konsolen-Auflösung, so richtet geht libvirt von einer Standardauflösung von 800x600x16 für die Darstellung der GUI des Gast-Systems unter dem Spice-Protokoll aus. Diese Auflösung schlägt dann typischerweise auch auf einen Gnome- oder KDE-Desktop des Gastes durch. Entsprechend klein ist dann anfänglich auch das Spice-Display-Fenster auf dem Host.

Nun wird man als Standarduser versuchen, diese Auflösung im Gastsystem über die Einstellmöglichkeiten des jeweiligen Gast-Desktop-Systems (Gnome’s “gnome-control-center” bzw. KDE’s “systemsettings5”) zu verändern.

Hat man man als Video-Einheit, also die virtuelle Graka, des Gastsystems qxl gewählt, so kann man unter der Gnome- oder KDE-GUI des Gastes die Auflösung des Desktops tatsächlich dynamisch – d.h. im laufenden Betrieb – abändern.

Entscheidet man sich bei der Konfiguration des Gastes allerdings für “virtio” als Video-System, so erleidet man unter Debian 8 Schiffbruch: Die Einstellmöglichkeit beschränkt sich dann genau auf die bereits vorgegebene Größe von 800×600.

Ich bespreche die Standard-Einstellmöglichkeiten nachfolgend zunächst für QXL, den Gnome-Desktop und auch für TTYs; anschließend gehe ich auch kurz auf eine Einstellmöglichkeit für “virtio” ein. Weitergehende Einstellmöglichkeiten – wie etwa über “xrandr” werde ich auf Wunsch eines Lesers in einem späteren Artikel aufgreifen.

Gnome-Desktop-Auflösung des Gastes unter qxl setzen

Das nachfolgende Bild zeigt den Gnome 3 Desktop eines Debian-8-Gastes mit “qxl” in einer Auflösung von 1920x1080x32 auf einem KDE-Schirm des SuSE-KVM-Hostes mit einer 2560x1440x32-Auflösung.

Die Auflösung des Gnome-Desktops eines KVM-Gastsystems kann man (zumindest im Falle von QXL) sehr einfach über die “Gnome-Einstellungen=>Monitore” festlegen.

Das mögliche Auflösungsspektrum wird dabei offenbar nur durch die Auflösung der aktuellen Host-Schirme begrenzt. De facto bietet mir das System in meinem Fall Auflösungen bis zu 4K an. Diese Einstellungen beziehen sich aber nur auf den Desktop des Gastes – nicht jedoch dessen Konsolen-TTYs !

Hinweis: Hat man einen KVM-Gast mit KDE-Plasma5 so verwendet man “systemsettings5 &” und dort den Punkt “Anzeige und Monitor”, um die KDE-Auflösung festzulegen.

Das Tolle ist: Man kann unter QXL/Spice auch bei den gezeigten hohen Auflösungen wirklich flüssig arbeiten! Auch mit transparenten Fenstern! Da ist in den letzten Jahren ganze Arbeit geleistet worden. Vielen Dank an die Entwickler! (Vor allem wohl bei Red Hat.)

Auflösung der Debian8-Gast-TTYs setzen

Das “virt-manager”-Unterfenster zur Anzeige eines Gastes über Spice bietet einem dankenswerterweise einen Menüpunkt “Send Key” an, mit dessen Hilfe man Steuersequenzen wie Ctrl-Alt-F1 auch an den KVM-Gast schicken kann. So gelangt man dann u.a zu den Gast-Konsolen-TTYs “tty1” bis tty6. Um deren Auflösung von 800×600 auf vernünftige Werte abzuändern, muss der Framebuffer-Support des Hypervisors beeinflusst werden. Dies ist unter Debian 8 über Grub-Einstellungen möglich.

Hierzu editiert man mit Root-Rechten die Datei “/etc/default/grub” bzgl. zweier Zeilen (eine davon ist auszukommentieren):

GRUB_GFXMODE=1920x1080x32
GRUB_GFXPAYLOAD_LINUX=keep

Natürlich kann man auch eine andere definierte Standard-Auflösung als die für meinen Fall angegebene wählen.

Danach ist nach einem unten angegebenen Link nur noch das Absetzen eines “update-grub” (erfordert Root-Rechte) nötig. Und tatsächlich: Nach einem Reboot wiesen meine TTYs die gewünschte Konsolenauflösung auf.

Was kann man bei einem Wechsel von QXL zu “virtio” tun?

Wie gesagt, bietet die unter Opensuse Leap 42.2 verfügbare KVM-Implementierung die Möglichkeit an, für das Video-Device eines KVM-Gastes “virtio” statt QXL (oder weit weniger leistungsfähigen Treibern) zu wählen.

Welche Folgen hat ein Wechsel zu dieser Darstellungsart, bei der direkt auf die Host-HW zugegriffen wird?
Auf meinem System bislang keinerlei offenkundig negativen. Das Zeichnen der einzelnen Gnome-Fenster auf dem Gastdesktop geht bei sehr schnellen Bewegungen dieser Fenster über die Fläche des Gastdesktops gefühlt noch etwas flüssiger
als beim Einsatz von QXL. Das ganze grafische Verhalten des Gastes im “virt-manager”-Fenster ist danach so gut, dass man auch bei höchster Auflösung von der 2D-Grafik her praktisch keinen Unterschied zur Arbeit auf einem nativen System mehr merkt. Das ist wirklich beeindruckend gut!

Einen Wehrmutstropfen muss man als Standard-User unter Debian 8 (mit Kernel 3.16) aber dennoch hinnehmen:

Unter den “Gnome-Einstellungen=>Monitore” lässt sich die Auflösung nicht mehr dynamisch wie im Fall von QXL ändern. Für das Einblenden des grafischen Gast-Outputs in den Speicherbereich der realen Graka zählt unter Debian 8 offenbar allein die Auflösung, die man wie oben beschrieben für die Unterstützung des virtuellen Gast-Framebuffers durch den Hypervisor eingestellt hat.

Immerhin steht einem dadurch aber eine Einstellmöglichkeit zur Verfügung – wenn auch keine dynamische! Damit kann ich aber gut leben; wenn ich jemals eine dynamische Änderung des Gnome-Desktops eines KVM-Gastes brauchen sollte, verwende ich halt “qxl”.

Nachtrag, 29.06.2017:
Faktisch gilt die obige festgestellte Einschränkung für Debian 8 nur für Kernel 3.X. Mindestens ab Kernel 4.9 bietet der virtio-Treiber eine ganze Liste an Auflösungen an, aus denen man wählen kann. Siehe hierzu den Artikel

KVM, video virtio, Debian 8 guest, host with Intel HD 4000 – install a 4.9 kernel on the guest for optimal 2D graphics performance!

Nachtrag, 03.07.2017:
Ein User hat mich angeschrieben und zu Recht angemerkt, dass die im Gastsystem angebotenen Auflösungen unter “qxl” nicht immer an die Maximal-Auflösung der Schirme des Hosts heranreichen. Auf die Frage, was man dann tun kann, gehe ich gerne in einem weiteren Artikel ein. Sobald ich Zeit finde, den zu schreiben … Den entsprechenden Link werde ich dann hier nachtragen. Der Schlüssel liegt dabei vor allem in der Nutzung von “xrandr”. Bei der Gelegenheit gehe ich dann auch kurz auf das Thema von mehreren “virtuellen” Monitoren unter qxl ein.

Skalierung des Fensterinhaltes

Hingewiesen sei auch darauf, dass sich die Darstellung das gesamte Fenster zur Darstellung des KVM/Qemu-Gastes, das man vom virt-manager aus geöffnet hat, bei entsprechender Einstellung unter dem Menüpunkt “View” dynamisch skalieren lässt.

Auch das geht sehr flüssig und verzögerungsfrei!

Viel Freude weiterhin mit Linux und KVM/Qemu!

Links

https://superuser.com/questions/598374/how-to-change-the-resolution-of-the-bash-for-a-debian-vm

ufw auf Strato-vServern mit Debian 8 – fehlende iptables Log-Meldungen im systemd-Journal – rsyslogd

Gestern hatte ich das Vergnügen, ein Debian-Server-System auf einer aktuellen vServer-Plattform bei Strato einzurichten. Ich bereite entsprechende Arbeiten in der Regel vor, indem ich elementare Konfigurationsschritte – im Besonderen solche, die sicherheitsrelevant sind – vorab auf einem ähnlichen KVM-Gast-System in unserem Hausnetz simuliere und teste.

Diese Art von vorbereitenden Tests hat jedoch ihre Grenzen; nicht alles ist vergleichbar. Gestern bin ich mal wieder auf einen Unterschied im Zusammenhang mit iptables, ufw und den zugehörigen LOG-Meldungen unter systemd gestoßen. Letztere fehlten nämlich im systemd-Journal des Strato-vServers völlig.

Da fragt man sich schon, wie man denn unter solchen Voraussetzungen das gehostete System bzgl. von Angriffsmustern monitoren soll. Ich finde, diese Frage ist so relevant, dass sie sich auch andere Strato-Kunden besser vor dem Mieten eines vServers beantworten sollten. Deshalb dieser Post. Die gute Nachricht ist: Es gibt unabhängig von den Ursachen für das Fehlen der LOG-Meldungen einen Workaround.

Die schlechte Nachricht ist: Die Ursache der fehlenden Kernel-Meldungen im systemd-Journal ist unklar; zumindest mir. Auf einem KVM-Host funktioniert alles wie erwartet. Unterschiede zu gehosteten Servern sind meist auf einen anderen Ansatz in der Virtualisierung zurückzuführen (Stichwort: Container-Technologie vs. Hypervisor für Full/Para-Virtualisierung).

In diesem Falle erscheint mir das aber als Erklärungsansatz nicht plausibel und hinreichend. Ich gehe nachfolgend auf die Gründe etwas genauer ein. Zudem ist bei Debian 8 (leider) eben auch systemd in den Logging-Prozess involviert. Defizite von “systemd” in der Interaktion mit bestimmten Virtualisierungsumgebungen halte ich für durchaus möglich. Der Irrwitz, dass ein Programm beim Systemstart die Umgebung analysieren und für jeden Fall die richtige Antwort ziehen muss, hat halt seinen Preis …

ufw, netfilter/iptables und das Logging-Problem

Ich bin eigentlich ein Freund von Firewall-Builder (FWB). Für Debian-Systeme verwende ich aber auch “ufw“, um initial die wichtigsten Paketfilter-Regeln, also iptables-Anweisungen, bequem und zeitsparend aufzusetzen. Die drehen sich zunächst um den SSH-Zugang von außen und die Erlaubnis, dass der gehostete Server DNS-Server, NTP-Server und bestimmte Update-Server kontaktieren darf. Auch “pings” und “traceroute” vom Server nach außen erlaube ich. Alles andere wird von mir anfänglich rigoros geblockt. Später wird dann für die angestrebten Services des Servers gezielt nachgearbeitet. (Off topic: Viele Dienste, die mein Kunde benötigt, tunnele ich auf dem Server über eine SSH-Verbindung; ein direkter SSH-Zugang des Users root wird sowieso unterbunden und der SSH-Port verschoben.)

Anfänglich ist hinsichtlich eines minimalen Regelsatzes gar nicht viel zu tun. Im Anschluss an das Etablieren der ersten Paketfilter-Regeln möchte ich gerne die Arbeit von “netfilter” testen und das zugehörige Logging mitverfolgen. Typischerweise lasse ich dann “nmap” von außen auf das gehostete System los. Für einen Test des Serverzugriffs auf externe DNS-Dienste und Zugriffe auf Update-Server tut es dagegen “apt-get”. In beiden Fällen verfolge ich per SSH auf einem (Remote-) Terminal den Strom der Meldungen der (ufw-)”Firewall”.

Das erhoffte Verfolgen der iptables-Log-Meldungen schlug auf dem Strato-vServer mit installiertem Debian 8 aber fehl.

Debian 8.x nutzt wie gesagt systemd. Ufw schreibt die iptables-Log-Daten mit eigenen Zusätzen in das Log-System des Servers – bei einem systemd-basierten Systemen also in das dortige binäre Journal. Das systemd-Journal fängt im Normalfall neben System-Meldungen und Meldungen aus dem Userspace auch Kernel-Messages auf. Da systemd den gesamten Mix aus Messages in ein
binäres Datenformat in einer Datei überführt, muss man das Kommando “journalctl” mit geeigneten Filtern bzw. der Option “-f -nxxx” benutzen, um Log-Einträge auswerten bzw. direkt am Schirm mitverfolgen zu können.

Gesagt, getan. Leider tauchen auf einem Strato-vServer im Journal von “systemd” generell nur sehr wenig Informationen auf; hinsichtlich der Paketfilter-LOG-Meldungen findet man dort jedoch leider gar nichts.

Das iptables-Target “LOG” mündet auf einem mit “rsyslogd” ausgestatteten Log- und Warnsystem dagegen in Meldungen in der Datei “/var/log/kern.log” – schließlich handelt es sich ja um Kernel-Meldungen.

Die aus meiner Sicht schon immer kritikwürdige Idee, alle systemrelevanten Meldungen an einer Stelle in einem Binärformat zu sammeln, wird uns auf einem Strato vServer nun offenbar zum Verhängnis: Nur mit systemd können wir kleine und große externe Zugriffsversuche auf einen vServer offenbar nicht überwachen!

Ich bin übrigens nicht der Einzige, der dieses Problem hatte; siehe:
http://linux.debian.user.german.narkive.com/8AbyxJTP/keine-eintrage-von-dmesg-im-journal-systemd
Erstaunlich ist dennoch, dass man ansonsten im Internet fast nichts zu dieser Thematik findet.

Ob das Problem nun etwas mit systemd-Defiziten oder einer speziellen Konfiguration der systemd-Interaktion mit der Virtualisierungsumgebung bei Strato zu tun hat, muss man natürlich ein wenig austesten.

Firewall-Logging, Virtualisierung und Container

Tatsächlich erweist sich das Verhalten von Debian 8 mit “ufw” auf einem KVM-Gastsystem als gänzlich anders. Hier ein Auszug der ufw-Meldungen von einem KVM-Gast mit Debian 8, die mittels des Befehls

“journalctl -f -n20”

zur Anzeige gebracht wurden:

Apr 05 16:05:52 deb11 kernel: [UFW BLOCK] IN=eth0 OUT= MAC=52:54:00:d5:4a:9b:52:54:00:fc:27:c5:08:00 SRC=192.168.10.1 DST=192.168.10.11 LEN=44 TOS=0x00 PREC=0x00 TTL=54 ID=25556 PROTO=TCP SPT=64358 DPT=110 WINDOW=1024 RES=0x00 SYN URGP=0 
Apr 05 16:05:52 deb11 kernel: [UFW BLOCK] IN=eth0 OUT= MAC=52:54:00:d5:4a:9b:52:54:00:fc:27:c5:08:00 SRC=192.168.10.1 DST=192.168.10.11 LEN=44 TOS=0x00 PREC=0x00 TTL=59 ID=47868 PROTO=TCP SPT=64358 DPT=135 WINDOW=1024 RES=0x00 SYN URGP=0 
Apr 05 16:05:52 deb11 kernel: [UFW BLOCK] IN=eth0 OUT= MAC=52:54:00:d5:4a:9b:52:54:00:fc:27:c5:08:00 SRC=192.168.10.1 DST=192.168.10.11 LEN=44 TOS=0x00 PREC=0x00 TTL=45 ID=41401 PROTO=TCP SPT=64358 DPT=53 WINDOW=1024 RES=0x00 SYN URGP=0 
Apr 05 16:05:52 deb11 kernel: [UFW ALLOW] IN=eth0 OUT= MAC=52:54:00:d5:4a:9b:52:54:00:fc:27:c5:08:00 SRC=192.168.10.1 DST=192.168.10.11 LEN=44 TOS=0x00 PREC=0x00 TTL=42 ID=10106 PROTO=TCP SPT=64358 DPT=22 WINDOW=1024 RES=0x00 SYN URGP=0 
Apr 05 16:05:52 deb11 kernel: [UFW BLOCK] IN=eth0 OUT= MAC=52:54:00:d5:4a:9b:52:54:00:fc:27:c5:08:00 SRC=192.168.10.1 DST=192.168.10.11 LEN=44 TOS=0x00 PREC=0x00 TTL=54 ID=65381 PROTO=TCP SPT=64358 DPT=113 WINDOW=1024 RES=0x00 SYN URGP=0 
Apr 05 16:05:52 deb11 kernel: [UFW BLOCK] IN=eth0 OUT= MAC=52:54:00:d5:4a:9b:52:54:00:fc:27:c5:08:00 SRC=192.168.10.1 DST=192.168.10.11 LEN=44 TOS=0x00 PREC=0x00 TTL=47 ID=1758 PROTO=TCP SPT=64358 DPT=587 WINDOW=1024 RES=0x00 SYN URGP=0 
Apr 05 16:05:52 deb11 kernel: [UFW BLOCK] IN=eth0 OUT= MAC=52:54:00:d5:4a:9b:52:54:00:fc:27:c5:08:00 SRC=192.168.10.1 DST=192.168.10.11 LEN=44 TOS=0x00 PREC=0x00 TTL=47 ID=22236 PROTO=TCP SPT=64358 DPT=443 WINDOW=1024 RES=0x00 SYN URGP=0 
Apr 05 16:05:52 deb11 kernel: [UFW BLOCK] IN=eth0 OUT= MAC=52:54:00:d5:4a:9b:52:54:00:fc:27:c5:08:00 SRC=192.168.10.1 DST=192.168.10.11 LEN=44 TOS=0x00 PREC=0x00 TTL=55 ID=60478 PROTO=TCP SPT=64358 DPT=23 WINDOW=1024 RES=0x00 SYN URGP=0 
Apr 
05 16:05:52 deb11 kernel: [UFW BLOCK] IN=eth0 OUT= 

 
Offensichtlich führt im obigen Fall das System 192.168.10.1 einen Portscan auf dem betroffenen KVM-Host mit der IP 192.168.10.11 durch.

Ähnliche Meldungen erhält man bei einem Portscan auf einem vServer aber – wie gesagt – nicht.

Wie könnte man das erklären?
Ein naheliegender Erklärungsansatz wäre etwa folgender:
Das Logging von Kernel-Messages klappt auf einem KVM-Gast, also unter dem QEMU-Hypervisor (sog. Typ 2 Hypervisor), der über “virtio” auf dem Host nur partiell Paravirtualisierung und keine Container-Technologie einsetzt, natürlich problemfrei. Das Betriebssystem des KVM-Gastes und dessen Kernel arbeiten ja weitgehend autonom und greifen nur über Vermittlungsschichten auf den Kernel des Hosts und dessen HW-Unterstützung zu. Es besteht von Haus aus kein Problem bzgl. des Loggings von Kernel-Meldungen – sie beziehen sich immer auf den Kernel des Gastsystems.

Dagegen setzt Strato Container-Technologie ein – genauer VZ-Container unter Virtuozzo; selbiges basiert auf OpenVZ. Zu Grundeigenschaften siehe :
https://openvz.org/Main_Page und https://openvz.org/Features

Es handelt sich bei Strato wohl um Version 4.7 oder eine frühe 6er Version von “Virtuozzo Containers”. Dafür gibt es Indizien (u.a, dass sich Docker nicht installieren lässt); um einen genauen Nachweis habe ich mich aber (noch) nicht gekümmert. Ist auch egal.

In einer Container-Lösung wird jedenfalls die Kapazität und Funktionalität des Host-Kernels zwischen den Containern, die keinen eigenen Kernel besitzen, geteilt (schlanker “Single-Kernel-Approach”). Der Zugriff auf Netze erfolgt über eine entsprechende Netzwerk- und Schnittstellen-Virtualisierung. Typischerweise werden virtuelle venet- oder veth-NICs eingesetzt; je nachdem, auf welcher Ebene OSI-Stacks man arbeiten will. (veth-NICs setze ich selbst vielfach auch in komplexeren KVM/Qemu-Umgebungen bei der Netzwerkvirtualisierung ein.)

Die notwendige Separation der Container und ihrer Netzwerk-Kommunikation gegeneinander und gegenüber dem Host muss vom Host-Kernel bzw. dessen Modulen auf der Basis von Konfigurationsvorgaben für unpriviligierte Container (in ihren separaten Namespaces und bei modernen Ansätzen ggf. in cGroups) gewährleistet werden. Man wird den Container-Systemen jedenfalls nicht erlauben, alles einzusehen, was auf dem für alle zuständigen Host-Kernel abläuft. Dies bedeutet u.a., dass Containersysteme nicht beliebige Kernel-Module (z.B. für Packettracking unter Wireshark) laden dürfen.

Wer “iptables” im Zusammenhang mit Virtualisierungshosts aber ein wenig genauer kennt, kann sich vorstellen, dass man eine Host-Firewall natürlich immer so konfigurieren kann, dass die einzelnen virtuellen Netzwerkschnittstellen der (Container-) Gäste gegeneinander geblockt werden, aber dass generelle Forward-Regeln für physikalische Interfaces des Hosts nicht in Konflikt mit speziellen Filter-Regeln für ein spezifisches (virtuelles) Gast-Interface geraten müssen.

OpenVZ kann man deshalb sehr wohl so einrichten, dass der Admin eines Container-Systems seine eigenen iptables-Regeln für seine gastspezifischen NICs definieren kann. Siehe hierzu z.B.:
https://openvz.org/Setting_up_an_iptables_firewall.

Wesentliche Teile der verschiedenen netfilter-Module – im Besonderen für die Schicht 3 – stehen also auch Gästen zur Verfügung. Voraussetzung ist in einer Container-Architektur natürlich, dass grundlegende “netfilter”-Module auf dem OpenVZ-Host selbst geladen wurden.

Aber: Es wäre fahrlässig, wenn ein Container-Host alle netzwerkspezifischen Kernel-Meldungen (darunter iptables-Meldungen) auch für die Einsichtnahme durch die root-User der Container preisgeben würde. Das würde u.a ein
Ausspionieren der virtuellen Netzwerkumgebung und darauf aufbauend bestimmte Angriffsszenarien ermöglichen. Wenn wir überhaupt etwas im Container sehen, dann höchstens Meldungen zu selbst gesetzten Paketfilterregeln für die Container-spezifische NIC.

Zwischenfazit:

  • Wir dürfen uns in einer Container-Umgebung u.a. nicht darüber wundern, dass man bestimmte Kernel-Module vom Container aus erst gar nicht laden darf und z.B. lsmod eine vernünftige Antwort schuldig bleibt.
  • Wir dürfen uns nicht wundern, dass bestimmte sysctl-Befehle, die im Container abgesetzt werden, ggf. ignoriert werden.
  • Wir dürfen uns in einer Container-Umgebung nicht wundern, wenn man bestimmte Teile des systemd-Logs auf einem Container – und damit auf einem Strato-V-Server – nicht ggf. zu Gesicht bekommt. (Im Gegensatz zu einem KVM-Gast).

Der erste Punkt ist u.a. für den Betrieb der ufw relevant; s.u..

Bzgl. des zweiten Punktes ist zu beachten, dass OpenVZ, genauer der OpenVZ-Kernel, (network-) “Namespaces” nutzt. (“Namespaces” werden natürlich aber auch von aktuellen Linux-Kerneln unterstützt. Zu “Namespaces” siehe etwa
https://jvns.ca/blog/2016/10/10/what-even-is-a-container/
https://de.slideshare.net/jpetazzo/anatomy-of-a-container-namespaces-cgroups-some-filesystem-magic-linuxcon
https://openvz.org/WP/What_are_containers.

Deshalb lassen sich bestimmte Einstellung unterhalb von “/proc/sys” durchaus auch vom Container aus anpassen. Was in der jeweiligen OpenVZ-Umgebung erlaubt ist und was nicht, muss man ggf. durch Probieren herausfinden.

Den dritten Punkt werden wir in den nächsten Abschnitten für vServer kritisch hinterfragen.

Erste Konsequenzen für den Einsatz von “ufw”

Auch durch Probieren wird man herausfinden, dass “ufw” auch auf einem mit Debian 8 betriebenen vServer von Strato läuft – und man eigene iptables-Regeln problemfrei an den OpenVZ-Kernel weiterreichen kann.

Achtung:

Nach der Installation von ufw auf dem vServer NICHT unmittelbar “ufw enable” absetzen!! Zuerst den Port, auf dem man SSH betreibt, freischalten. Also etwa durch “ufw allow 22”, wenn man den SSH-Standardport benutzt. Ihr wollt euch ja nicht durch Anschalten der Firewall selbst aussperren!

Wie man schnell (hier durch einen Blick in das systemd-Journal feststellt), ist der Start von ufw auf einem vServer – auch im Rahmen eines Systemstarts – mit ein paar Fehlermeldungen verbunden.

Apr 05 14:21:03 xxx.stratoserver.net ufw[147]: Starting firewall: ufw...modprobe: ERROR: ../libkmod/libkmod.c:557 kmod_search_moddep() could not ope
Apr 05 14:21:03 xxx.stratoserver.net ufw[147]: modprobe: ERROR: ../libkmod/libkmod.c:557 kmod_search_moddep() could not open moddep file '/lib/modul
Apr 05 14:21:03 xxx.stratoserver.net ufw[147]: modprobe: ERROR: ../libkmod/libkmod.c:557 kmod_search_moddep() could not open moddep file '/lib/modul
Apr 05 14:21:03 xxx.stratoserver.net systemd-journal[114]: Permanent journal is using 24.0M (max allowed 4.0G, trying to leave 4.0G free of 499.5G a
Apr 05 14:21:03 xxx.stratoserver.net systemd-journal[114]: Time spent on flushing to /var is 1.770ms for 8 entries.
Apr 05 14:21:03 xxx.stratoserver.net ufw[147]: sysctl: permission denied on key 'net.ipv4.tcp_sack'
Apr 05 14:21:03 xxx.stratoserver.net ufw[147]: Setting kernel variables (/etc/ufw/sysctl.conf)...done.

r
 
Diese Meldungen rühren u.a. daher, dass ufw mit Hilfe von modprobe versucht, bestimmte “conntrack”-Sub-Module zu laden. Zudem versucht ufw per sysctl Kernel-Parameter abzuändern. Vorgegeben sind diese Schritte in den Dateien “/etc/default/ufw” und “/etc/ufw/sysctl.conf“.

Die genannten Fehler blockieren den Start aktueller ufw-Versionen aber nicht; wer sich dennoch an den Meldungen stört, kann die über Modifikationen der genannten Dateien, nämlich durch Auskommentieren der fehlerträchtigen Statements, verhindern. Siehe auch
https://www.hosteurope.de/faq/server/virtual-server/besonderheiten-firewall-virtual-server/; im Unterschied zu den dortigen Tipps aber beachten, dass auf dem vServer nur einer der sysctl-Befehle problematisch ist.)

Übrigens: Über das Starten von ufw bei einem Reboot des vServers muss man sich nach einem Absetzen von

systemctl enable ufw

keine Gedanken mehr machen. Debian 8 beinhaltet für ufw einen passenden LSB-Service, der beim Hochfahren ausgeführt wird.

Monitoring von ufw-iptables-Meldungen auf dem vServer mit Hilfe von dmesg

Nachdem man in systemd-Journal nichts findet: Gibt es andere Möglichkeiten, die LOG-Messages von ufw-/iptables zu verfolgen?

Da es sich um Kernel-Messages handelt, liegt ein versuchsweiser Blick auf den “dmesg”-Output nahe. Und tatsächlich – auf meinem vServer:

    
root@xxx:~ # dmesg
[1240949.664984] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=45.55.2.201 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=244 ID=54321 PROTO=TCP SPT=40788 DPT=3306 WINDOW=65535 RES=0x00 SYN URGP=0 
[1240954.051018] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=93.174.93.136 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=250 ID=4710 PROTO=TCP SPT=43745 DPT=3128 WINDOW=1024 RES=0x00 SYN URGP=0 
[1240986.448807] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=45.55.1.72 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=244 ID=54321 PROTO=TCP SPT=46822 DPT=1900 WINDOW=65535 RES=0x00 SYN URGP=0 
[1241002.495868] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=88.100.184.82 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=50 ID=13380 PROTO=TCP SPT=35180 DPT=23 WINDOW=44554 RES=0x00 SYN URGP=0 
[1241015.141452] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=89.163.144.224 DST=xxx LEN=445 TOS=0x00 PREC=0x00 TTL=57 ID=32820 DF PROTO=UDP SPT=5180 DPT=5046 LEN=425 
[1241132.233004] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=197.44.69.222 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=239 ID=44476 PROTO=TCP SPT=53226 DPT=1433 WINDOW=1024 RES=0x00 SYN URGP=0 
[1241145.520318] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=208.100.26.228 DST=xxx LEN=40 TOS=0x08 PREC=0x00 TTL=242 ID=51210 PROTO=TCP SPT=47975 DPT=15672 WINDOW=1024 RES=0x00 SYN URGP=0 
[1241185.158299] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=89.163.144.224 DST=xxx LEN=443 TOS=0x00 PREC=0x00 TTL=57 ID=56812 DF PROTO=UDP SPT=5400 DPT=4000 LEN=423 
[1241297.661764] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=186.45.130.20 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=241 ID=12134 PROTO=TCP SPT=63715 DPT=23 WINDOW=14600 RES=0x00 SYN URGP=0 
[1241350.742715] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=89.163.144.224 DST=xxx LEN=446 TOS=0x00 PREC=0x00 TTL=57 ID=14769 DF PROTO=UDP SPT=5320 DPT=5172 LEN=426 
[1241353.098569] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=5.53.113.195 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=51 ID=48667 PROTO=TCP SPT=46919 DPT=23 WINDOW=39535 RES=0x00 SYN URGP=0 
[1241377.620483] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=46.152.41.83 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=240 ID=40038 PROTO=TCP SPT=12600 DPT=23 WINDOW=14600 RES=0x00 SYN URGP=0 
[1241386.187457] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=122.114.187.140 DST=xxx LEN=40 TOS=0x00 
PREC=0x00 TTL=238 ID=8477 PROTO=TCP SPT=46170 DPT=23 WINDOW=1024 RES=0x00 SYN URGP=0 
[1241437.193431] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=218.91.210.142 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=48 ID=4557 PROTO=TCP SPT=45821 DPT=23 WINDOW=27541 RES=0x00 SYN URGP=0 
[1241512.054090] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=89.163.144.224 DST=xxx LEN=443 TOS=0x00 PREC=0x00 TTL=57 ID=37720 DF PROTO=UDP SPT=5179 DPT=1028 LEN=423 
[1241553.246515] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=49.4.143.59 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=104 ID=256 PROTO=TCP SPT=6000 DPT=135 WINDOW=16384 RES=0x00 SYN URGP=0 
[1241632.706391] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=39.71.216.3 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=48 ID=4841 PROTO=TCP SPT=57398 DPT=22 WINDOW=55725 RES=0x00 SYN URGP=0 
[1241643.559480] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=196.202.5.43 DST=xxx LEN=44 TOS=0x00 PREC=0x00 TTL=48 ID=53691 PROTO=TCP SPT=34866 DPT=23 WINDOW=33710 RES=0x00 SYN URGP=0 
[1241674.241572] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=89.163.144.224 DST=xxx LEN=446 TOS=0x00 PREC=0x00 TTL=57 ID=60393 DF PROTO=UDP SPT=5288 DPT=1029 LEN=426 
[1241683.411659] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=124.167.232.138 DST=xxx LEN=60 TOS=0x00 PREC=0x00 TTL=47 ID=40536 DF PROTO=TCP SPT=57844 DPT=22 WINDOW=14600 RES=0x00 SYN URGP=0 
[1241686.407572] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=124.167.232.138 DST=xxx LEN=60 TOS=0x00 PREC=0x00 TTL=47 ID=40537 DF PROTO=TCP SPT=57844 DPT=22 WINDOW=14600 RES=0x00 SYN URGP=0   

 
Ja, die Welt ist schlecht – und wir tun offenbar gut daran, den Zugang zum Server zu blocken bzw. die Logs auch mal auszuwerten und später Blacklists einzusetzen. “fail2ban” zu konfigurieren schadet nebenbei auch nichts.

Wer periodische Updates des Outputs von dmesg ähnlich zu “tail -f” verfolgen will, probiere mal das Kommando

watch -n 0,2 “dmesg | tail -n $((LINES-6))”

in einem Terminal aus. (Ggf. das Terminalfenster etwas vergößern. Auf englischsprachigen Systemen “0.2” statt wie hier “0,2” ! Auf neueren Kerneln als dem der aktuellen vServer gibt es übrigens auch die dmesg-Option “-w”).

Aber das eigentlich Feststellenswerte ist ja, dass wir überhaupt was sehen!

Natürlich ist das, was man unter OpenVZ unter dmesg zu Gesicht bekommt, eingeschränkt (s. etwa https://bugs.openvz.org/browse/OVZ-5328).
Aber:
Der OpenVZ-Kernel liefert dem Container zulässige, relevante Informationen in den lokalen Message-Ringpuffer, die dort von root eingesehen werden können. Darunter auch die ersehnten iptables-Meldungen!

Nun stellt sich die große Frage, wie systemd mit diesen Kernelmeldungen interagiert und warum das, was unter dmesg erschient, nicht ins Journal der OpenVZ-Container-Umgebung eingestellt wird.

Das Problematische an systemd ist, wie immer, dass man das ohne seitenweises Lesen in systemd Blogs etc. und/oder gar Codestudium vermutlich nicht beantworten kann. Logisch erscheint mir das Ganze jedenfalls nicht. OpenVZ sorgt offenbar für eine Reduktion der Kernelinformationen auf das, was root im Container sehen sollte. iptables-Meldungen zur lokalen NIC des Containers werden dabei nicht ausgespart. Sie sollten daher eigentlich auch im systemd-Journal erscheinen!

Monitoring mittels rsyslogd ? !

Durch den dmesg-Test ermutigt, fragte ich mich, was wohl passieren würde, wenn rsyslog auf dem vServer-Debian-System installiert und aktiviert wäre. Das ist insofern interessant, als systemd ja externe Linux System-Logging-Services über Schnittstellen bedient und trotzdem sein eigenes Journal weiter versorgt. Man loggt dann im Normalfall sozusagen zweimal …

Eigentlich würde man nun erwarten, dass die Meldungen von dmesg auch in den verschiedenen Dateien, die der rsyslog-Dämon bedient, nicht auftauchen sollten. Weil systemd ja schon den
Transfer in die eigene Binärdatei verweigert. Also machen wir mal die Probe:

root@xxx:~# apt-get rsyslog
root@xxx:~# systemctl start rsyslog
root@xxx:~# systemctl enable rsyslog

Wenn nun doch etwas passieren sollte, so müssten iptables-Meldungen als Einträge unter “/var/log/kern.log” und/oder in der von ufw vorgesehenen Datei “/var/log/ufw.log” auftauchen.

Und tatsächlich finden wir (wider Erwarten) nach einer Weile in “kern.log” iptables-LOG-Meldungen:

  
Apr  6 13:19:57 xxx kernel: [1245761.082097] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=118.163.90.134 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=48 ID=14764 PROTO=TCP SPT=33202 DPT=23 WINDOW=44186 RES=0x00 SYN URGP=0 
Apr  6 13:21:03 xxx kernel: [1245827.018789] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=85.90.163.248 DST=xxx LEN=44 TOS=0x00 PREC=0x00 TTL=52 ID=358 PROTO=TCP SPT=21965 DPT=23 WINDOW=12453 RES=0x00 SYN URGP=0 
Apr  6 13:21:16 xxx kernel: [1245840.027789] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=89.163.144.224 DST=xxx LEN=445 TOS=0x00 PREC=0x00 TTL=57 ID=61654 DF PROTO=UDP SPT=5201 DPT=4011 LEN=425 
Apr  6 13:22:26 xxx kernel: [1245910.326051] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=91.98.36.115 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=46 ID=3739 PROTO=TCP SPT=31242 DPT=23 WINDOW=22306 RES=0x00 SYN URGP=0 
Apr  6 13:23:13 xxx kernel: [1245957.077099] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=117.193.182.117 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=48 ID=29137 PROTO=TCP SPT=12209 DPT=22 WINDOW=52845 RES=0x00 SYN URGP=0 
Apr  6 13:23:54 xxx kernel: [1245997.536218] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=45.55.1.114 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=244 ID=54321 PROTO=TCP SPT=43185 DPT=8123 WINDOW=65535 RES=0x00 SYN URGP=0 
Apr  6 13:23:56 xxx kernel: [1246000.108495] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=192.151.169.29 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=51 ID=46742 PROTO=TCP SPT=54014 DPT=23 WINDOW=49390 RES=0x00 SYN URGP=0 
Apr  6 13:24:05 xxx kernel: [1246008.982092] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=89.163.144.224 DST=xxx LEN=445 TOS=0x00 PREC=0x00 TTL=57 ID=19866 DF PROTO=UDP SPT=5391 DPT=4012 LEN=425 
Apr  6 13:24:08 xxx kernel: [1246011.450635] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=163.172.204.214 DST=xxx LEN=447 TOS=0x00 PREC=0x00 TTL=58 ID=25411 DF PROTO=UDP SPT=5440 DPT=5060 LEN=427 
Apr  6 13:24:18 xxx kernel: [1246022.133966] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=181.193.99.26 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=48 ID=47683 PROTO=TCP SPT=36520 DPT=23 WINDOW=41856 RES=0x00 SYN URGP=0 
Apr  6 13:24:29 xxx kernel: [1246032.599018] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=89.248.166.146 DST=xxx LEN=48 TOS=0x00 PREC=0x00 TTL=123 ID=26103 PROTO=TCP SPT=11206 DPT=2083 WINDOW=65535 RES=0x00 SYN URGP=0 
Apr  6 13:24:50 xxx kernel: [1246053.507827] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=71.165.26.106 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=50 ID=381 PROTO=TCP SPT=29725 DPT=23 WINDOW=3178 RES=0x00 SYN URGP=0 
Apr  6 13:25:44 xxx kernel: [1246108.065452] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=139.162.118.251 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=246 ID=54321 PROTO=TCP SPT=56219 DPT=6379 WINDOW=65535 RES=0x00 SYN URGP=0 
Apr  6 13:26:16 xxx kernel: [1246139.839711] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=174.16.249.159 DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=240 ID=54734 PROTO=TCP SPT=43074 DPT=23 WINDOW=14600 RES=0x00 SYN URGP=0 
Apr  6 13:26:28 xxx kernel: [1246151.805797] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=117.1.220.212 DST=xxx LEN=44 TOS=0x00 PREC=0x00 TTL=242 ID=2085 PROTO=TCP SPT=14216 DPT=5358 WINDOW=14600 RES=0x00 SYN URGP=0 
Apr  6 13:26:50 xxx kernel: [1246174.013725] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=123.151.42.61 DST=xxx LEN=135 TOS=0x00 PREC=0x00 TTL=47 ID=32696 PROTO=UDP SPT=9019 DPT=1701 LEN=115 
Apr  6 13:27:01 xxx kernel: [1246184.993843] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=89.163.144.224 DST=xxx LEN=445 TOS=0x00 
PREC=0x00 TTL=57 ID=44551 DF PROTO=UDP SPT=5365 DPT=4013 LEN=425 
Apr  6 13:27:27 xxx kernel: [1246211.300971] [UFW BLOCK] IN=venet0 OUT= MAC= SRC=89.120.177.89 DST=xxx LEN=44 TOS=0x00 PREC=0x00 TTL=55 ID=64605 PROTO=TCP SPT=59589 DPT=23 WINDOW=64213 RES=0x00 SYN URGP=0 

 
Die Welt ist inzwischen nicht besser geworden, aber nun können wir das Schlechte wenigstens mal verfolgen. (Dieselben Einträge erscheinen übrigens auch in ufw.log).

Tja, nicht alles im Leben mit systemd ist offenbar nachvollziehbar ….

Fazit

Das erwartete native Zusammenspiel zwischen einem Strato OpenVZ vServer und systemd unter Debian 8 funktioniert bzgl. der Protokollierung der LOG-Target-Meldungen von iptables nicht. Kernel-Meldungen zu iptables-Rules für die Container-NIC erschienen nicht im Journal von systemd.

Workarounds bestehen darin

  • den Output von dmesg kontinuierlich per Skript abzufragen und in eine Datei umzulenken.
  • rsyslog zu installieren und die Arbeit dem Zusammenspiel von systemd mit dem rsyslog-Dämon zu überlassen. Man protokolliert dann doppelt, aber man erhält wenigstens dauerhafte Log-Protokolle, die jeder sicherheitsbewußte Admin zur vorsorglichen Gefahrenabwehr benötigt.

Da die gewünschten Kernel-Meldungen bei gleicher Debian- und Systemd-Version in einem KVM-Gast erscheinen, ist das Problem mit dem systemd-Journal entweder

  • auf einen Fehler oder ein Sicherheitsfeature der OpenVZ-Umgebung,
  • oder auf ein seltsames (gewolltes oder fehlerhaftes) Zusammenspiel des OpenVZ-Kernels mit systemd in den Container-Umgebungen,
  • oder schlicht auf ein fehlerhaftes, bislang nicht erkanntes/bedachtes Verhalten von systemd in einem OpenVZ-Container

zurückzuführen.

Für letzteres spricht die Tatsache, dass der OpenVZ-Kernel iptables-Meldungen zur Container-NIC unter dmesg offenbart und dass systemd die Meldungen, die unter dmesg auftauchen wohl korrekt an weitere System-Logging-Services wie rsyslog weiterleitet.

Eine entsprechende Anfrage bei Strato, die hoffentlich Virtuozzo einschalten, läuft.

Das Fehlen von iptables-Log-Protokolle ist im Sinne der ISO 27000 (Strato hat da ein Zertifikat!) zudem als Sicherheitsproblem einzustufen, das Kunden kommentarlos zugemutet wird und von diesen Kunden selbst gelöst werden muss.

Weiterführende Links

Fehlende Einträge im systemd-Journal
http://linux.debian.user.german.narkive.com/8AbyxJTP/keine-eintrage-von-dmesg-im-journal-systemd

Container, Virtuozzo, OpenVZ und iptables, ufw
http://forum.openvirtuozzo.org/index.php?t=msg&goto=37264&&srch=container
https://openvz.org/Setting_up_an_iptables_firewall
http://askubuntu.com/questions/399624/ubuntu-server-12-04-and-ufw-failure-on-startup-and-several-module-not-found-err
https://www.hosteurope.de/faq/server/virtual-server/besonderheiten-firewall-virtual-server/
https://superuser.com/questions/659236/permission-denied-when-setting-values-in-sysctl-on-ubuntu-12-04
https://help.
ubuntu.com/community/UFW

https://help.virtuozzo.com/customer/en/portal/articles/2509437?_ga=1.206607316.635252319.1491384754
ab S. 317 in folgender Referenz
http://www.odin.com/fileadmin/parallels/documents/hosting-cloud-enablement/pvc/Production_Documents/VzLinuxUG_03132013.pdf
https://bugs.openvz.org/browse/OVZ-5328

Namespaces
http://www.netdevconf.org/1.1/proceedings/slides/rosen-namespaces-cgroups-lxc.pdf

LXC vs. OpenVZ
https://www.janoszen.com/2013/01/22/lxc-vs-openvz/
https://en.wikipedia.org/wiki/LXC
https://openvz.org/Comparison

OpenVZ integrates KVM/Qemu
http://openvz.livejournal.com/tag/criu
https://www.heise.de/ix/meldung/Virtualisierungsplattform-OpenVZ-wird-eigenstaendige-Distribution-3278115.html
https://openvz.org/Virtuozzo
https://openvz.org/QEMU
https://www.heise.de/ix/meldung/Virtualisierungsplattform-OpenVZ-wird-eigenstaendige-Distribution-3278115.html
https://openvz.org/FAQ
https://virtuozzo.com/virtual-machines-in-virtuozzo-7/
https://openvz.org/WP/What_are_containers#Networking

Virtualisierungsangebote in D – Vergleich
https://timreeves.de/trip-content/uploads/dokumente/Internet-Mietserver-Typen_im-Vergleich.pdf

Watch dmesg Output
http://unix.stackexchange.com/questions/95842/how-can-i-see-dmesg-output-as-it-changes

Webclipse JSjet, Eclipse Neon 2 and the Outline View – what I like and what I do not like – part III

JSjet is an Eclipse plugin intended for Javascript developers, who are dissatisfied with the sparse information the present JSDT version provides you with in the Outline View and the code completion boxes. See:
Webclipse JSjet, Eclipse Neon 2 and the Outline View – what I like and what not – part I.

But a professional user would check the quality of the information provided by JSjet, too. In my last post of this mini series about JSjet
Webclipse JSjet, Eclipse Neon 2 and the Outline View – what I like and what not – part II
I discussed some strong indications that – given certain circumstances – one unfortunately cannot always trust the information JSjet provides in the Outline View. Equally important: Uncritically picking information from JSjet’s code completion dialog in Eclipse Neon 2/3 may – again under certain circumstances – lead to unintended errors in your Javascript code. It depends very much on your programming style and the philosophy behind it. Adding new properties and methods to specific objects may have severe consequences. And JSjet (Vers. 1.72.201703081933 / 2017 CI 3b) is not handling a prototypal inheritance pattern well. You should test this out in case you want to use JSjet for professional work!

Still, one may hope that Genuitec overcomes these problems in future versions. I base this hope on the fact that a conservative simple inheritance pattern is analyzed correctly with respect to variables and functions the code completion dialog can offer as valid choices. So, the required code analysis capabilities are there in the background of the duo JSjet/Tern – but they are not used properly in all cases, yet.

Are there more aspects you should think about when planning to use JSjet? Yes, in my opinion, there are. They have to do with licensing and license conditions – and what you or your company tolerates regarding data gathering about a developer’s interaction with Eclipse.

License fees – a really fair prize for one seat installations

You should be aware of the fact that Webclipse JSjet is not for free if you plan to do serious development work with it. By serious I mean work that requires more than just 8 days per month. JSjet follows your interaction with JSjet – after having used it on more of 8 days you will be asked to get a license. If I remember correctly it was not important how much you used it on these 8 days. There are company licenses and personal licenses available. Note that you would license the Webclipse product which contains much more than just JSjet; e.g., you would also get an Angular IDE.

For me as a freelancer the personal license was the interesting one. I think a price around 30 $ per year for one workstation and 2 different Eclipse installations on this machine is a fair offer. After the comments on the quality in my last post you may think differently – but, hey, what has the present JSDT to offer you instead? And their are more things included in Webclipse than just JSjet and the Outline view …

License terms – and the question of surveillance …

Now, we come to a much more critical and frustrating point – at least for Europeans with an increasing awareness of and about data gathering by IT providers. And I make a clear distinction between services which I do not have to pay money for and licensed services, which I pay in Euros or Dollars. Personally, I do not want to pay for a license and have no option to stop information gathering about my interactions with the computer and/or used programs. I do not want to pay extra with data that potentially allow for a personal work or
interest profile that an IT provider can and wants to distribute/sell to third parties without my consent. So, I get pretty annoyed when a reference to personal data is directly included in frequent information transfers about my work, interest or habits.

Actually, the license statement shown during installation of Webclipse makes it very clear that you accept data gathering when licensing. We read:

8.0 Consent to Collect, Store, and Use Information. Licensor respects your privacy rights and recognizes the importance of protecting any information collected about you. Solely for the purpose of improving Licensor Services to you, you hereby authorize and consent to the collection, storage and use of aggregate information and data related to or derived from your use of the Software and any information or data (including personally identifiable information) that you elect to provide to Licensor in connection with your use of the Software. By installing, accessing or using the Software, you consent to these information collection and usage terms, including (where applicable) the transfer of data into a country outside of the European Union and/or the European Economic Area or the United States of America. Licensor assumes no obligation to protect confidential or proprietary information that you elect to provide to Licensor (other than personally identifiable information) from disclosure, and Licensor will be free to reproduce, use, and distribute the Information (other than personally identifiable information) to others without restriction.

(Marking parts of the text with strong or cursive letters was done by me.) Ja, ja – we should trust you … It is all in our own interest …. Really? Why does it all remind me of MS Win 10? And how bad that I do not trust in any data provision via the Internet to providers where I have no control about what they do with my personalized or possibly personalizable data. So, what does Genuitec gather – and when is this information sent from Eclipse to Genuitec? Let us start with the second question first:

Information is at least sent to Genuitec via https each and every time you start Eclipse with installed Webclipse components. This will probably happen at least daily. How can you test it? I recommend Linux users to find the IP address of Genuitec (same as the website), set up corresponding firewall and log statements on your machine or network segment for outgoing traffic and analyze the packets sent. Check also for additional (!) traffic and come to your own conclusions about the frequency of information transfer !

Equally interesting is the question what kind of data is “accumulated” and where is it stored in between 2 sending processes. Regarding this question I recommend to look thoroughly through the “.metadata/.plugins” folder inside your Eclipse workspace folders. One interesting folder you find there should be “com.genuitec.eclipse.monitor“. Have a look at the contents of the file located there. Or even better: Follow its changes via a “tail -f -nxxx” command during your working processes and your interaction with Eclipse. Then think a bit about the fact that the monitoring file includes hashes for your machine/workspace. And that your license information is directly included in this file. And remember that your original license order required the provision of quite a lot of personal data. Now think once again about the frequency of data transmission. Come to your own conclusions ….

If you did what I suggested above, you may get the idea that one gets a relatively fine granular image in time of what you as a developer personally do with Eclipse – at least over each day at your workstation. And then you may start questioning what Genuitec means by “data (including personally identifiable information) that you elect to
provide to Licensor”
.

Elect“??? Where, actually, is the possibility within Eclipse or Webclipse settings to choose? If you find any possibility to “elect”, please inform me, via e-mail …. I would like to see the options for restricting the data gathered, setting the accumulation period and controlling the relation to my personal license. I did not find such options ….. Or do we need more rigorous measures to “elect“?

Needless to point out for my German readers that alone the gathering of the various of time based information on a person’s interaction with Eclipse/Webclipse is not compliant with German labor legislation. Which forbids even the possibility of following personal work activities closely without anonymization. But the data gathered in the file

.../.plugins/com.genuitec.eclipse.monitor/myeclipse-usage.properties

provides no anonymization at all and neither you nor your boss have any control about how these data are treated by Genuitec.

And in addition: By following the changes of this file closely even some of your colleagues with sufficient access rights to your workspace folder could build up a profile of your daily work and your efforts – down to a millisecond. Nice, eh …? All of course in your interest … And in the interest of all your other colleagues having separate installations on their workplaces … The collected data of a company wide Webclipse installation would allow for a work load profile of the developer department, which could be broken down to individuals. By people with sufficient rights inside your company but, of course, by Genuitec in the US, too.

Now, it may be the right time to inform the officer for personal data protection in your company. And your IT network administrator, who probably is as a friend of Linux, may start with some deeper meditation on file access rights and firewall policies for the development department of your company. And both may agree upon taking their chances to “elect” and enforce company wide data protection policies.

But be aware – simply blocking the https data transfer to Genuitec servers would have an impact on any updates based on Eclipse repositories (due to automatic dependency checks). Such updates would hang … However, if you and your admins have come to this point – you/they would know what to do to solve this problem – if it is one for you or your company, at all.

My dear friends at Genuitec – I like the direction of your work, BUT you should profoundly rethink your data gathering policies – independent of the fact that your new government recently allowed for data gathering on US users without asking for the users’ consent. Checking a license can be done totally independent of data gathering. And it would be easy to offer (European) users options on the type of data to be collected and the frequency of collection. Be sure – European Linux users will take their chances to “elect” – or leave your product.

Final conclusion

JSjet as a part of Webclipse looked and looks very promising with respect to providing a better Eclipse Outline structure for Javascript coders. You definitely get more information about the code structure than provided by JSDT.

However, in its present status the combination of JSjet/Tern also showed some profound weaknesses – and provided (in my opinion) even misleading information on classes and prototypes. As a developer you would have to adapt your coding style to these deficits to avoid unintended code errors when picking up functions from JSjet’s code completion window. And beware of using prototypal inheritance patterns! However, there is a good chance that the present problems may disappear in future versions of JSjet.

Regarding license policies: JSjet is not for free, if you have a serious workload. The license conditions include your consent to a substantial information gathering – and
you cannot separate this from the transfer of information about your personal license and workplace. The gathering of information on my interaction with Eclipse is clearly far beyond what I personally accept as tolerable. German companies should evaluate the consequences closely and in relation to the German “Arbeitsrecht” as well as local company policies. There are options to enforce such policies on the network administration side.

From Genuitec I expect options to control the data gathering on various levels, the data transfer period and a clear separation between license checks and gathering of data on user interactions with parts of Eclipse/Webclipse for the future. And of course corrections to the information presented in the Outliner – but here they may depend on the Tern project.

 

Webclipse JSjet, Eclipse Neon 2 and the Outline View – what I like and what I do not like – part II

My last blog post
Webclipse JSjet, Eclipse Neon 2 and the Outline View – what I like and what not – part I
started a mini series about JSjet, a product sold by the company Genuitec. In the first post I discussed some advantages “Webclipse JSjet” offers regarding the Outline View for Javascript code in Eclipse Neon 2 and 3 – at least in comparison with Eclipse’s present JSDT. A first test showed that we get a lot more information – especially on ES6 classes or constructor functions – than the present JSDT plugin of Eclipse is able to provide. This was a promising result and proofed basic claims of Genuitec.

However, I also indicated already in the last post that there are some points of JSjet’s information provision which are ambivalent and could be criticized. I even raised the question whether all the information presented by JSjet in the Eclipse Outline View is really valid. For a better analysis I set up a test file with valid Javascript code – but a relatively chaotic code structure.

The objectives and the results of my limited test are discussed below. The results were a bit surprising.

For reasons of completeness I add that I used a licensed Webclipse JSjet version 1.72.201703081933 / 2017 CI 3b. JSjet internally uses Tern modules. I do not distinguish between these two below and shall not speculate which component is responsible for what. When I name JSjet I always mean the duo of Webclipse JSjet and Tern. And I must warn you: This is going to be a long article – not only about JSjet but also about some Javascript aspects, which not everybody may be familiar with.

Excursion : Code analysis capabilities and the presentation of variables, of properties of objects and prototypes in an Outline View

The presentation of code hierarchy levels in an Outline view is not all one needs during a Javascript coding process; in addition one expects a reasonable quality of the code analysis concerning variable types and variable/function association with objects or classes.

Any information regarding the origin of variables and a clear distinction between the following variables/functions would be valuable for a Javascript developer – especially if he/she had to deal with code designed by others:

  • specific variables/functions set for and added to a specific object by related explicit statements in the JS code after object creation,
  • member variables/functions set by a constructor function at the creation of an object. (Rmemeber: the “this”-operator in a constructor function refers to the object being created by the constructor!)
  • and variables inherited as members of a prototype object (e.g. the prototype of a constructor function). (Remember: the protoype object of a constructor function is linked to the __proto__ property of the objects created with the help of the constructor).

Actually, JSjet and Tern do provide type hints in the Outline View and mark things they regard as “prototypes” with a “P” and specific objects derived from a constructor function (and its prototype) with an “O“. (The latter is, of course, also true for object literals.) Elements of classes, constructor functions and prototypes are displayed as sub-elements of a related “P“-section in the Outline View. The type of such variables and functions is revealed – if JSjet can determine it.

JSjet does, however, not distinguish between (this.)elements of a constructor function or elements (functions, variables) added explicitly to the prototype of the constructor function. Under a “P” section for a constructor function ”
F()” you would see everything that would be available in a specific object created by a “new F()” statement.

This is a bit problematic as it mixes different categories of variables/functions – the one’s that are directly created in a new object by the constructor and the variables plus functions coming from the inherent prototype object of the function F(). But OK …

The relation of a specific object with its constructor and prototype is indicated in the Outline View (at least in most cases) by a reference to the name of the basic class or the constructor function used during object creation.

Thus the type of information JSjet basically provides would certainly be sufficient

  • if you never changed the type of defined properties (i.e. member variables) by assigning “values” or code elements with different types after object creation in your code. I.e. if the types of member variables defined in the constructor or in parent prototypes would be kept throughout the whole code execution.
  • if you never extended certain objects by new (!) properties and methods.
  • if you only used conventional prototype or class oriented patterns for inheritance.
  • if you never used some specific objects directly as a prototype for Child constructor functions.

Meaning: If you followed a strict and conservative coding philosophy, where everything (!; i.e. all variables and methods used in the code), is based on classes or explicitly defined elements (properties/functions) of constructor functions and/or (their) prototypes.

But Javascript allows for two interesting things which give you a lot of flexibility:

  • The extension of existing specific objects by explicitly adding new property variables and new functions/methods – i.e. beyond the prototype members and the constructor variables provided at the object’s creation. You can always perform such an extension without modifying prototypes/constructors in the inheritance chain up to your specific object. Such properties/functions would, however, only be accessible by and through the particular object.
  • A direct prototypal pattern for object inheritance where the prototype of a temporary constructor (e.g. K()={};), which later on is used to create a “Child object” (e.g. “C”), is directly linked to an existing “Parent object” (e.g. “U”; K.prototype = U; C=new K();). This works because a prototype basically is nothing else than a special object. This is a kind of classless and very pragmatic inheritance pattern; it concentrates on the reuse of an existing object and its properties/methods for yet other derived objects. The latter then inherit all properties and functions defined so far for its/their Parent object. In contrast to other inheritance patterns we do not care about the history of the Parent object or the existence of a constructor function for it. In this approach – and close to the very core of Javascript – all that counts are objects and not abstract “classes”.

Note that the prototypal pattern is implemented in ES5 via the function Object.create().

A first warning regarding prototypal patterns:
As we shall see, JSjet does NOT display an existing specific object, which is used as the prototype of a new constructor function, as a structured “P” element in the Outline View.
I guess it was difficult to decide whether one should stress the role of such an object as an existing “object” or as a “prototype” for other objects. Whatever the reason, my JSjet version had no solution to offer for indicating both aspects of an object, which was used both in its role as an object AND as a prototype for other objects. But all properties/functions of such an object
would appear below the new constructor function “K()“.

But I would have hoped that at least the dependency of the new Child constructor function on the specific object was somehow indicated. But this is not the case either – as we shall see.

Expectation: Distinction of object specific properties from properties created by constructors or delivered via prototypes
However, as JSjet distinguishes between a constructor function (including its prototype) and objects derived from it, we would expect a proper distinction of variables added to a specific object on one side and the variables of the constructor function/prototype used to build the object on the other side. In addition variables or functions added to an object, which itself is used as a new prototype for further CHILD objects in the prototypal pattern should be associated correctly.

Unfortunately, regarding these points I stumbled over – in my opinion – problematic aspects of JSjet/Tern, which I want to discuss below.

A reasonably “chaotic” test script

Let us now look at a “chaotic” test script and the resulting Outline information of JSjet. Why do I want to use a seemingly unorganized “chaotic” code example instead of a ordered one? Well, I do not exactly know how a code analyzer works; but it seems reasonable to assume that it must pick up information whilst parsing the Javascript code of a file; furthermore the gathered information has to be systematically ordered afterwards and analyzed for relations between objects and their constructors/prototypes. Global variables have to be detected, global functions have to be distinguished form encapsulated ones, and, and, and … A code analysator for Outline purposes probably will not be so “intelligent” as the interpreter itself, but it must do a reasonable reordering of code fragments to display the structural code and object hierarchy and to point out relations between defined elements correctly.

For testing a code analysis tool a test script, therefore, should contain code in “chaotic” order – and it should, of course, comprise not only the most simple language constructs. Actually, for the purpose of a provocative testing we would also like to do things, which we normally would not do. The test code displayed in the next picture was compressed to get it onto one page; it has an erratic, jumpy order of statements – on purpose. Normally, I do not write such chaotic code; but the more unstructured, the better for this type of a test. If you do not understand it at once – why should a machine ….

So, how does it look like – and what does JSjet make of it and what does it reveal in the Outline View? Just click on image or download it in case it is too small to read its content. Or download the following txt file with the code jsjet_test_code – if you want to experiment with it.

With the exception of the statements in the last line – this is all valid Javascript code and can be tested. I used “alerts” instead of “console.log” statements to save some space. As you see, I have included some relatively advanced constructs like closures, immediate function declarations, callbacks and two most simple inheritance patterns. Note in addition that each of the last six statements would result in a Javascript error. All in all this limited script is certainly not a totally simple test task for the code analysis capabilities of JSjet.

So… what do we make of the information in the Outline View? Let me walk through some aspects of the information displayed
in the Outliner. I have closed some hierarchy parts of the Outline View to get it onto one page; but I shall show the contents of these points where necessary.

All global variables are detected by JSjet

I start with a positive point: Global variables not explicitly declared via “var” or “let” statements are gathered at the end of the Outline View – in our case starting with the variable “x”. Yes, in contrast to JSDT JSjet detects all global variables and displays them! However, one would wish a better distinction of these variables introduced in the code on the fly from explicitly declared variables.

Furthermore the object “GOC” included as a property in class Ufo’s constructor is analyzed for its elements:

Note, that the local variable “z” is missing however. We shall come back to this point.

But there are other more confusing things to talk about first ….

A new member variable “s” of class “Ufo”?

The first line that really looks fishy in the Outline View is the line that displays a property “s” : If we take the information of the Outliner literally we would assume that “s” is an element of our class Ufo (or of the respective internal constructor function and the latter’s prototype). However, we never declared any “s” as part of the class Ufo, Ufo‘s constructor or Ufo‘s methods!

Instead: “s” is added to a specific object “U” based on the constructor of class “Ufo” in the course of our test code (line 24 and 30).

Hmm, who else besides object U in our code example would really know about this property “s”? Who could use it? Have a look at the U-based objects “V” (line 26) and “L” (line 29). We recognize a very simple prototypal inheritance pattern for “L” in line 28/29 and for V via Object.create() in line 26. Yes, I mixed the ES6 class syntax with old fashioned prototype manipulations in lines 28/29. Not nice, but valid. What does it mean for the derived new constructor function “K()” – and how is the relation between K() and U represented in the Outline view?

The constructor function “K()” and its prototype U are analyzed by JSjet; reasonably enough all U-properties, including those coming from its class “Ufo”, are shown in the Outline view. We, therefore, expect the properties “x” and “y” to appear below K. But we would also expect the newly added property “s” of “U” in K’s outline, because U is used as a prototype for “K()“. (Ignore the other elements for a moment.)

Note, however, that the relation of the new constructor function K() to U is not directly reflected in the Outline View; but this is no real issue.

Technical aspects: The prototype of the constructor function K() points to object U. So, actually, object L, which is based on K(), should also know about a property “s” : namely by or the provided through prototype object U. The “Object.create()” function does something similar when creating object “V“. Also object “LL” defined in
line 30 knows about “s”.

But note: Any change of “U.s” would show up in the derived objects, too – at least and as long as we do not assign own s-value to our objects L, V, LL. So the outcome for the alert statement in line 31 is:

However, neither the constructor function of class Ufo nor its prototype are really affected by all these manipulations of object “U” and the objects based on “U” ! So, it makes NOT much sense to display “s” as an element of Ufo; it is an element of U, i.e. K’s prototype, of V, L, LL.

This is very clearly tested by creating an additional object “W” based on Ufo after all the fuss with the extension of U. As expected W does NOT know anything about a property “s”.

Nevertheless, even the code completion context menu of JSjet offers “s” as a possible property element of W. The next picture resulted from the code completion support triggered via “Ctrl+Space” after typing a “W.” in the code:

Is this problematic? Well, in our simple example picking up an “undefined” property form the code completion dialog would not matter much. But things would become much more dangerous if the JSjet code completion window offered undefined functions/methods! Guess what: It does! See below.

First conclusion

From our example we get the following impression: During code analysis JSjet picks up new properties (and possibly functions,too,) added to specific objects, which themselves were derived from a class constructor. JSjet then associates these properties/functions with the original class constructor; JSjet presents them as if they were elements of the related constructor/prototype and thus at the inheritance origin of all derived objects. This is misleading.

Just a strange way to analyze the ES6 “class” syntax? Well, you see this (misleading) pattern again when you look at how the property “ufo”, which is added to object L at the end of line 31, is reflected in the Outline information about the constructor function “K()” (see the picture on K above).

Undefined method/functions pfn() and fx()?

Note that in addition to “s” JSjet displays two methods/functions “pfn()” and “fx()” as elements of our class “Ufo” [better: its constructor/prototype] . But again: We never declared these methods for class “Ufo”!

Instead we did something very different: We added function “pfn()” to the prototype of K() (and thus indirectly to object U) (line 28). And much later (after the creation of V and L) we added function “fx()” directly to our object U (see line 40). So, after this point in the code both V, L and LL would know about fx(), too, and could execute it properly. Normally, one would not program in this dangerous way – but it is possible.

But what about W and another object “Z” based on the original class “Ufo“?
W and Z never see anything of pnf() or fx(). They do nothing about these functions! Therefore, if we called W.pfn() the Javascript code would run into an exception and stop. And as expected it really does at the first statement of the last code line:

Nevertheless, we get both functions offered as valid elements in the JSjet code completion support window when typing “W.“:

So:

Picking functions from the JSjet code completion dialog window whilst coding in Eclipse can under certain circumstances lead to code errors!

We additionally check that the original class properties are kept and are not modified throughout the code via our object “Z“; see line 42 (result : false) and line 59 (error).

Second conclusion

Presenting variables and functions, which are added to a specific object, as elements of and within the scope of the object’s “class” in the JSjet Outline View is at least misleading. Personally, I would even say that it is wrong! Offering such functions in the code completion dialog as possible elements of newly created objects, which are based on the original class, may lead to errors!

Is this a systematic bug or does it somehow depend on the relatively new ES6 class definition syntax? Nope, it goes wrong also for prototype based declarations of objects; see below.

Deficits when Object.create() of ES5 is used

Interestingly enough JSjet does NOT see what object V inherits from the prototype delivered to “Object.create()” – in this case the object “U” itself. In the Outline View V is only presented as a literal object – for whatever reasons.

Only one variable, “x”, is displayed as an element of V. That it appears at all probably results from an analysis of Ufo‘s function alpha() which is called a bit later via “V.alpha()” … [This assumption can be tested by modifying alpha().] So JSjet knows about the indirect dependency of “V” on class Ufo – but this knowledge is not used for V‘s presentation the Outline View.

No display of private variables

The next remarkable point in our Outline View is that we do not see our private variable “z” defined in the constructor of class “Ufo”. This is unfortunate; especially as we have defined a (different) global variable “z”, too. And even more unfortunate, the JSjet code completion dialog offers us only an unspecific “z” (described as an element of our js-file) when requesting code completion:

So, here we see a clear limitation of the analysis depth of JSjet/Tern: Private variables are neither shown in the Outline View nor do they appear in a safe and distinguished way in the code completion dialogs.

In general: Private variables defined in any kind of function are out of the scope of the Outliner. This is annoying; especially because the code analysis actually does seem to know something about the existence and even the
type of “z”: the type of the return value of the GOC-method funx(), namely “z”, is detected correctly.

Wrong backward association of variable type changes in distinct objects with the variable types in constructor functions/prototypes

Let us turn to the constructor function “DO()” (and its prototype): The Outliner tells us that there is a variable “x” having 3 different types. It is claimed that “x” is an object! But we did NOT define any string or array values for the variable “x” of function “DO()” or its prototype. Neither did we declare “x” as a function! Instead “x” was explicitly given a number-value in the DO-function’s body!

Again, our problem is that JSjet’s Outliner does not distinguish sufficiently enough between variables and functions of a specific object and variables/functions of the constructor or prototype, from which the object was derived. In the course of our (chaotic) code we assigned a string to an object “D“, which is based on the DO() constructor function, via D[‘x’] = ‘str13’ (line 27). In addition, near the end of the test code, we assigned an array to “D.x” via the statement “D.x=[‘1′,’2’]” (line 54). And in between we assigned a function to the member variable “x” of an object “E” via “E.x=closuretest(..)”; “E” was derived from the constructor function “DO()“, too.

But what do these object specific changes of properties have to do with the original variable “x” of the constructor function and its type there? Answer: Nothing! So, again JSjet/Tern provides us with somewhat misleading information about the elements of the DO() constructor.

In my opinion, the object specific modifications should have been displayed beneath the affected objects and not below the DO() function. The constructor itself will always deliver a “number” for the “x”-variable of any object created by “new DO()”.

The only piece of information that would make us suspicious in this case is the presentation of “x” as an object (!) in the Outliner. We could interpret this as a warning about how the variable “x” is used later on in specific objects; but even this would be confusing as, unfortunately, the original type of a number is not displayed.

Wrong association of added object variables and functions with constructor functions and parent prototypes

As we did for our class “Ufo” we tested the consequences of an extension of objects created by a “new DO()“. We added again a variable “s” to some of these objects. Furthermore, we also supplemented functions – directly or indirectly. See the statements “D[‘s’]=5” in line 27, “E.s = closuretest(..);”, “E.x = closuretest(..);” in line 36 and E.e = E.show(‘s’) in line 37.

As a first consequence we get a variable “s” in the information about the constructor DO() (or its prototype). Which – in my opinion – is misleading and wrong. Again, “s” also and wrongly appears in the code completion dialog.

The presentation of the functions “hilfe()“, “help()“, “hilf()” as elements of DO() is equally problematic. Again these functions are assigned to and cross referenced by properties added of specific objects! They are not part of the constructor function or its prototype. The Outliner does not make this clear! And the code completion window offers these functions unconditionally! E.g. for object D when typing “D.” followed by “Ctrl+Space”:

Now let us have a look at the information about ”
E.e“. The type of this member variable is not specified in the Outline View. This is interesting because “E.s” was correctly detected as a function before. “E.s” is a function assigned by a closure, and E.e uses E.s. But the fact that we set “E.e=E.show[‘s’]”, which only indirectly points to a the function E.s(), seems to block the type recognition. And after that even the explicit call as a function “E.e();” in the code does not help. But OK — it is always difficult to follow indirect assignments … What we must complain about, however, is again the fact that “e()” nevertheless is offered as a legitimate function (!) in the code completion menu for object D (see the picture above). But: E.e() will never be available for object D !

Third Conclusion

The problematic display of variables and functions, which are added to specific objects, as elements of the “prototype”, from which the object was derived, is also found when we use classical constructor functions (and their prototypes) for creating objects. In addition JSjet either does not recognize the relation of an object with a prototype object when Object.create() is used, or JSjet does not indicate this relation in the Outline View.

No display of private variables in closures

Regarding the global function “closuretest()” we again bemoan the missing display of the private variable “i”, which actually makes this function a closure (“i” is manipulated in the returned and encapsulated function’s body). Closures are one of the possibilities to provide real private variables in a lot of JS patterns – but JSjet/Tern does not help us here. In the code completion dialog the origin of the offered “i” is not specified either (we are only told that “i” appears in JS file). In this case i’s location and meaning would be clear; but what in longer real life codes?

Infinite recursion of the display of named functions encapsulated in immediate function brackets

The next strange point is the handling of an immediate function statement with a named (!) function inside; see the declaration of “var tt”, whose resulting type is recognized correctly. I admit: The naming (“ft”) of the encapsulated function does not make much sense, but interestingly the analysis of JSjet seems to run into an infinite loop for displaying the internal structure of the “anonymous” function block – containing the “ft()”. See the following picture! Really confusing! And compare this with the unnamed immediate function in the declaration of variable “var t”.

The use of “var” impacts the display of immediate named functions

But it gets even more confusing! In the code that follows after the definition of “ft()” we find a direct counterexample – namely the definition for the variable “fun” in line 43 – which was not declared via a “var”-statement. Here we also have used a named function encapsulated in brackets for immediate execution. However, in this case we do NOT get a display of a seemingly infinite hierarchy structure in the Outline View!

And something positive In addition: The type of the global variable “fun” is recognized correctly as an object defined by a literal. But the encapsulated immediate function is ignored in the Outline View; function “duper()” does not appear there at all.

However: As soon as you replace the assignment statement by “var fun = “, an infinite hierarchy recursion appears for function “duper()” in the Outliner, too! Try it yourself, if you do not believe it!

Association of added object properties/
functions with Child constructors?

At the end of our example code we test a simple kind of a 2 step inheritance pattern. The statement “DOChild.prototype = new DO();” leads to the fact that the internal structure displayed for “DOChild()” is exactly the same (and wrong) one as displayed above for DO itself.

Also there the variable “s” and functions as “hilfe()” etc. appear – which we know is wrong. But now we are a step further down in the prototype chain! So, it is even more misleading to display the elements in question in the Outline View for the Child constructor!

But it would be more dangerous if the code completion dialog of JSjet offered functions as “hilfe()” as valid elements of objects created with the DOChild() constructor! No object created with the help of the DOChild constructor (and its prototype) would know anything about these properties/functions! If we put “CH.hilfe();” as the first statement in line 59, we would get:

So, what happens in the code completion dialog? Actually, and somewhat surprisingly:

Good news! We do not see anything wrong! The information in the code completion dialog about available elements of a child object following a standard inheritance pattern is totally correct! This makes the appearance of the critical functions in the Outline View as elements of the constructor function DOChild() (or its prototype) even more mysterious!

OK, but what about the information transport across a prototypal inheritance pattern? To be able to test this we had created an object “B” based on Ufo in line 25. We equipped B with an added method “b()“. Now, e.g. LL is based on K() which uses U as a prototype. But not B! So, we should not see b() as a valid function offered for LL in the code completion. We are optimistic! However:

What a mess ! A method added to particular object derived from a parent class appears in the list of functions offered by JSjet’s code completion as valid members of a Child object created by the constructor of a prototypal chain based on another object. Not good !

Eventually, we may also remark that the results of the code analysis reflected in the Outline View depend a bit on the order of statements. I recommend to play a bit yourself with similar test codes and the order of statements before buying a license.

Summary and conclusions

The amount of information given by JSjet/Tern in the Outliner is significantly bigger and contains more structural elements and type hints than the information provided by today’s JSDT. However, the depth and quality of the code and object structure analysis is limited – and some information is actually misleading.

In my opinion the most critical point is the fact that properties/functions added or supplemented to specific objects are gathered and displayed as if they were elements of the objects’ constructor function, its prototype or the objects’ basic class (if you used the ES6 class syntax) – i.e. as elements of the elementary constructor/prototype from which the particular objects were
derived.

This way of gathering and associating added variables and functions of specific objects can even affect the structural information about CHILD constructor functions defined in simple inheritance pattern: The Outline View displays all variables/functions added incoherently to various specific objects derived from a PARENT Constructor as valid elements of the CHILD constructor function (or its prototype).

The wrong association of new and object specific variables/functions with the basic constructor/prototype of these objects is unfortunately also transferred to the code completion support. This, already, may lead to coding mistakes! But, even worse: The information about the wrong association is transferred across a prototypal inheritance chain: Functions added only to specific objects, which are different from an object “U” but based on the same constructor as “U”, will appear in the code completion dialog for any Child object created with the help of a new constructor K() that used “U” (!) directly as its prototype.

I regard this as a really negative aspect of the JSjet/Tern toolset – which may even lead to coding errors!

However – and really surprisingly – as long as we follow a standard inheritance pattern for a Child constructor function the code completion dialog does NOT offer any critical undefined variables or functions. In contrast to the information provided in the Outline View! And in contrast to a prototypal approach.

What I would have expected of JSjet in any case is to display object specific elements below the respective objects in the Outline View and not below their classes/constructors. In addition: Such specific properties/functions of a particular object should only appear in a derived CHILD constructor function when and if this constructor function uses the particular object explicitly as its (i.e. the function’s) prototype.

I must say that the findings described above frustrated and depressed me a bit. However, you can still use the information in the JSjet Outline VIEW for navigation purposes. But you should be extremely careful with its interpretation and the use of the code completion!

And you should program cautiously and very conservatively!

Outlook on the last post of this series

I am a person who is very concerned about digital data privacy. So, beyond technical aspects I thought it would be interesting to investigate a bit whether and what data a licensed JSjet installation may gather about you or your interaction with Eclipse. See my next blog post for this topic:

Webclipse JSjet, Eclipse Neon 2 and the Outline View – what I like and what not – part III

Webclipse JSjet, Eclipse Neon 2 and the Outline View – what I like and what I do not like – part I

Some time ago I wrote a blog post about the still unsatisfactory Javascript support by the JSDT plugin for Eclipse – at that time for “Eclipse Neon R”. See:
Eclipse Neon 1 – Standard-JSDT mit Schwächen – zusätzliche Plugins

I can very well imagine how difficult it must be to create a new and better basis for JSDT. In addition there may be general limitations imposed by the Eclipse Neon platform itself. However, this kind of awareness won’t help me much as a web developer who needs or at least wants to use Eclipse Neon 2 or 3 for Javascript projects or PHP projects with Ajax/Ajaj clients.

In particular, I did and do not like the present limitations of the JSDT Outline View. I shall describe some of these deficits only briefly below. Anyone who recently used Eclipse Neon for Javascript development knows what I am talking about.

The Eclipse plugin Webclipse JSjet offered by the US company Genuitec (in combination with Tern) helps to overcome some of these deficits. So, I found it interesting to try using JSjet within Eclipse Neon 2 in a real project I am presently working on. Instead of going back to Eclipse Mars …

At first I was very happy to get more information in the Outline view than with JSDT when coding Javascript objects and methods. Compared with Neon’s JSDT it felt like a big step forward. However, not all that shines is real gold. So, in a second round of testing I looked a bit closer at code analysis capabilities of JSjet/Tern. And already with a relatively small test file I found some problematic aspects of the JSjet Outline information presented for object oriented Javascript code. This is the topic of a second post coming soon.

In addition I must say, that JSjet is not for free – at least not for a reasonable amount of development work per month. And ordering a license comes with a – in my opinion – strong negative side aspect – which I do not like at all. It has to do with the automatic and periodic information transfer to the company behind JSjet. This is the topic of a third post.

Deficits of the Outline View information presented by JSDT for Neon 2

JSDT supports ES6 and ES2015 – at least as far as I have tested. But for conventional prototype based object and inheritance structures the JSDT Outline View was/is not of much practical use in Neon R or Neon 2. Reason: It did and does not show the full internal structure of Javascript functions, of constructor functions and their prototypes, of ES6 classes, of objects derived from constructor functions or classes or of objects in a prototype chain.

When testing “Neon R” I still hoped for an improvement in Eclipse Neon 2. Now I work with PHP on a Neon 2 and Neon 3 platform. But the JSDT Outliner has become even worse. An editorial of the company Genuitec – although cluttered with advertisement – rightly criticizes some major deficits of JSDT in Eclipse Neon; see: https://www.genuitec.com/boost-eclipse-neon-javascript-development-with-jsjet/. In my own words:

The present JSDT Outliner provides only some deeper information on classes and methods declared by the newer “class” statement of Ecmascript 6. However, even then we do not see properties (member variables) of a ES6 “class”. For constructor functions we cannot see see any deeper hierarchy structure at all – only the topmost class/function declaration itself. But no internal structure. E.g. no functions and , their prototype based “methods” (i.e. defined functions of the prototype)

So, no “methods” (i.e. functions of prototype objects) are listed in the Outliner. Tested on a freshly installed Neon 2. See below the very simple test code (really,
only for testing; I normally do avoid global variables … ).

Frankly, I think this is a bit of a mess; you may also note that the global variable “x”, which is not declared explicitly with a “var” or let statement, does not appear at all in the JSDT Outliner.

You can’t work and navigate with such an Outliner in real world projects, especially when you do some more complex Ajax/Ajaj development ….. Also code changes show up in the JSDT Outliner only when and after a you explicitly save your JS file.

Probably, I am not the only one who has to support older Javascript modules based on the prototype declarations of objects and prototype based inheritance patterns. In times before and up to Eclipse Mars I used the Outliner a lot for navigation and quick oversight purposes. If you have more than just one object in a code and more than only a few methods your coding efficiency depends on a reasonable IDE functionality presenting the code structure and its hierarchy over a sufficient amount of hierarchy levels. The present JSDT does not help you much regarding this point.

Alternatives for JSDT? Webclipse JSjet?

So, I started to look for alternatives for or supplements to JSDT in Eclipse Neon. One could think about Aptana Studio. However, the Jenkins repository for Aptana 3.4.x on the Eclipse marketplace is presently not working (since midth of Feb 2017 by the way; due to license and legal aspects). And for the Aptana studio plugin for Eclipse I have always experienced some conflicts with other plugin packages and their editor components in the past. So, I tried some other things as e.g. Vjet, but nothing really convinced me.

Eventually, some weeks ago, I came across “Webclipse JSjet” of the US company Genuitec. Genuitec claims that JSjet provides significantly more information about the code and object structure than pure JSDT. Basically, this is true. However, not all and everything is satisfactory with the JSjet solution either. Below and in the forthcoming posts I discuss only some more or less obvious points regarding the Outline View – so this is not going to be an in depth review. But it may at least give other Eclipse users some orientation. However, and to be fair: There are more interesting JSjet/Webclipse features than covered in my small blog post series. And some of these features are really worth a closer look and some tests. One example is the support of Javascript code debugging.

JSjet and the Eclipse Outliner – What is good?

I should first of all mention the following 2 points – which are related to the presentation of the code hierarchy, objects and object elements in the Outliner:

  • Information about the code hierarchy structure and internals of constructor functions and classes
    JSjet provides you with information about all global variables and functions it finds during its analysis of your Javascript code. In contrast to JSDT, JSjet detects all global variables – whether they explicitly declared by “var” or “let” statements or not.

    Functions that are used as constructors in a “new” statement or functions with explicit prototype declarations are marked with a “P” for “prototype”. This is certainly helpful for a quick orientation.

    JSjet provides you with information about general objects (e.g. declared by using literals). It informs you about their member variables and their functions/methods – i.e. you get an overview over the first inner hierarchy level of objects. (For comparison: The present PHP Outliner of PDT does not
    provide you with more hierarchy levels.)

    Because a function is an object itself in Javascript you expect an overview about the elements of any constructor function and its prototype, too. And yes, JSjet provides you with information gathered about elements of a constructor functions and their prototype.

    For concrete objects derived from a constructor function, only the relation with the constructor and its prototype is indicated in the Outline View. This also works for objects defined via simple inheritance patterns using a prototype chain. In most cases this is sufficient – as you can look up inherited properties in the displayed structure of the constructor. (The interesting question, how changes of properties applied for object instances or extensions of concrete object instances with additional properties or methods are handled, will be discussed in the forthcoming post.)

    For arrays you get an oversight over the different types of the array’s elements. See the test example of my next post for a display of this property of JSjet.

    By the way: The same depth of information is provided by the “Quick Outliner” which one can activate by pressing “Ctrl O” or via opening a context menu point after a “right mouse click” on a code element.

  • Project wide or local code analysis of the present file via “Tern”
    When you install JSjet some more Eclipse plugin modules from the French “Tern” project are installed. Tern itself uses a local “node.js”-installation provided automatically in your home directory under the subdirectory “~/.webclipse”. The basic task of Tern is a project wide code analysis.

    In the “preferences” settings for “Javascript” new menu points for the Tern configuration appear; in addition you will find a point named “Performance”. It gives you a dialog where you can set the scope, quality and performance of the Tern-based analysis.

    The default for the scope is “Entire project“. For this setting you will e.g. notice that that e.g. (global) variables or functions previously defined in some other files of your project are NOT shown in the Outliner. You may get more information about missing points and their location via an additional context feature, namely the “Call Hierarchy“.

    In the beginning I found this type of analysis and display a bit confusing. Meanwhile, I consider it helpful because it forces you to watch your naming of variables, objects, functions, prototypes and to think about the proper use of namespaces or modules.

    On the other side: If you want to keep several versions of a Javascript-file inside one and the same project folder structure the Tern analysis may lead to trouble and misunderstandings. In such cases the Tern scope can be reduced to the “Current File“. However, just switching via Eclipses’s preferences won’t always make this change work at once. Probably due to caching. Most of the time, however, I got success with closing all js-files and opening them again.

  • Availability of information on variables, functions, objects, prototypes in the code completion dialog Knowledge which the duo JSjet/Tern has gathered on global variables, functions, constructor functions, elements of prototypes and classes is also made available in the code completion dialog window. This helps a lot when coding – at least theoretically (see, however, the next post!).

The analysis of a realistic Javascript code example with several objects included, therefore, provides a sufficient amount of information to get an overview and to support navigation throughout the code. See the following picture:

So – this looks good on a first glimpse. A deeper analysis
is the topic of the next blog post. With ambivalent results …

JSjet and the Outliner – what is missing?

There are more things which felt not satisfactory when testing JSjet. There are some obvious deficits, which you find very quickly when doing real work with it.

  • No display of “private” variables
    As will be discussed in more detail in the next post, no private variables defined either with the old “var” or the new “let” statements inside functions, constructor functions, closures or class methods are shown. This is really a pity! One would like to now what a developer wanted/wants to keep private in a piece of code. Especially, if you work with code not designd by yourself.

    However, private variables defined inside functions or object methods do appear in the code completion dialog! But using it you may get confused, if there exists a global variable with the same name as a variable declared for the present function scope! The code completion window of JSjet will not make a clear distinction between these two different variables. The variable name will only be referenced once – and the only hint you get is its general occurrence in the code file. We shall see more on this topic in the next blog post.

  • Missing shortcut icons and control actions for the Outline view
    Another missing feature is a collection of shortcut icons at the top of the Outline View for useful operations like a simple full collapse of the code hierarchy structure. Instead the icon area at the top of the JSjet Outline view is extremely reduced in comparison to the standard one for JSDT.

    You start missing an overall collapse option as soon as you have real life and complicated code structures. JSjet opens the Outline View in a mode where the all hierarchy levels of constructor functions and classes are displayed fully expanded. So you must collapse object for object and hierarchy level for hierarchy level by yourself.

    In addition there is no option to set on/off a link to the editor actions. JSjet is automatically linked to the editor – which is not always desirable.

  • No filter options for the Outline View
    The worst deficit in my opinion is the lack of filters – in the sense of e.g. “show only objects”, “show functions only”, “do not show variables”, … . Just to avoid clattering of the Outline view with presently uninteresting things during the development of longer, complex programs.

Most of these points were working at last in old versions of JSDT (Kepler, Mars).

Are there usage problems?

Yes, I experienced that the outliner did not always give me complete information on objects – even when reducing Tern’s scope to the present file. This tends to happen sometimes after having used the “hierarchy call” feature of Eclipse JSDT, sometimes after a long time doing nothing on a project in the same workspace or after having worked on another project in the same workspace. It also happens when you switch the Tern analysis scope. …. or when you work with 2 eclipse windows …. It is unclear to me, what the real cause is – but it happened a few times with Eclipse 2. Maybe computing the Outline contents is not triggered correctly under some circumstances. The behavior became better after a recent update to Neon 3 and setting the Tern settings to quality instead of performance. In most cases closing all “.js” files and opening them again helped.

First conclusion

JSjet and Tern overcome the problem of JSDT which provides too few information in the Eclipse Neon Outline view. From JSjet you get sufficient information for keeping an overview over your code and object structure and for navigating between functions, prototypes and derived objects.

However, after some real work with JSjet/Tern I got a bit confused about some hints in the Outliner which
seemed to be at least misleading. So, I decided to test the code analysis of JSjet roughly. And this led to the question :

Is all of the information provided by JSjet in the Outline view really valid?

See the next blog post
Webclipse JSjet, Eclipse Neon 2 and the Outline View – what I like and what not – part II
for the results!