pax_global_header00006660000000000000000000000064132252303520014507gustar00rootroot0000000000000052 comment=8d6710f2aa6b4a0737a5cd5fa8dcee81af7144e6 apt-dater-host-1.0.1/000077500000000000000000000000001322523035200143425ustar00rootroot00000000000000apt-dater-host-1.0.1/ChangeLog000066400000000000000000000067441322523035200161270ustar00rootroot00000000000000apt-dater-host (1.0.1-adp0.7) unstable; urgency=low * Features: - Add support for Alpine Linux. (Contributed by Henrik Riomar @HRio) - Add RPM spec file. (Pull Request #15 by Mike Gerber @neingeist) * Changes/Fixes: - Fix aptitude on Jessie support. (Pull Request #18 by @drousseau) - Add ASSUME_YES support for yum. (Pull Request #14 by @megabert) - Move README to Markdown. (Pull Request #20 by Lukas Kallies @kallies) -- Thomas Liske Tue, 09 Jan 2018 22:00:49 +0100 apt-dater-host (1.0.0-adp0.7) unstable; urgency=low * Detect new Debian distro kernels correctly. (Closes Debian Bug#697330 by Time Weingärtner) * Debian: apt-dater-host should use apt-get as default. (Contributed by Simon Deziel) * yum: Fix apt-dater-host with newlines in yum. (Closes issue #15 reported by Jonas; fix contributed by Sebastian Schmidt) * Integrate needrestart(1): kernel version detection stuff will be removed - needrestart does contain a more advanced approach including kFreeBSD support. * Disable --assume-yes if any packages are scheduled for removal. (Fixes issue DE-IBH/apt-dater#28) * Debian: detect upgrades of foreign arch packages. (Closes Debian Bug#757329 by Patrick Matthäi ) * Cleanup source tree: - drop automake stuff - rename debian/ to dpkg/ -- Thomas Liske Wed, 24 Sep 2014 23:04:39 +0200 apt-dater-host (0.9.0-adp0.6) unstable; urgency=low * Some pedantic stuff (use long options for aptitude and apt-get to ease code reading). Don't fail on untrusted/unauthenticated packages when checking for upgrades (still check for the upgrade itself). (Contributed by Mathieu PARENT due SF Bug#3158198) * Check for updates (refresh) using dist-upgrade. This show ABI-incompatible upgrades (like the recent bind9 one: http://www.debian.org/security/2010/dsa-2130.en.html). (Contributed by Mathieu PARENT due SF Bug#3158198) * Make upgrade method customizable and change default to dist-upgrade. (Inspired by Mathieu PARENT due SF Bug#3158198) * Allow apt-dater-host to be used with ssh keys. (Inspired by 'Chromosom' due SF Bug#2862139) * Implement multiple cluster support (debian, rug, yum, zypper). * zypper: - Fixed: zypper did not report any updates (reported by Ivan De Masi). - Use 'zypper refresh' for refreshing package repositories. * Add RELEASE header to version string on RPM queries. * Use apt-get as default package manager. (Closes Debian Bug#635048 by Felix Bartels) * Add dummy man page apt-dater-host.1 (contributed by Pattrik Matthäi). * Enable apt's update download cronjob. * Track kernel updates using /etc/kernel/postinst.d. * Catch and report config file errors. * Use ImVirt.pm instead of the legacy imvirt binary on Debian. -- Thomas Liske Tue, 29 May 2012 14:17:14 +0200 apt-dater-host (0.8.x-adp0.6) unstable; urgency=low * apt-dater-host split-off * ADP 0.6: - cluster support - archive source support * Don't fail if apt-dater-host could not get the installed kernel packages; fallback to unknown reboot status. (Closes SF Bug#2991717 by Karoly Molnar) * Use $DPKGTOOL to detect packages with updates. (Contributed by Alexandre Anriot) * Fix unknown yum based hosts (reported on Fedora) due bad package status interpretation. (Reported by Patrick Matthäi) -- Thomas Liske Mon, 22 Mar 2010 19:58:59 +0100 apt-dater-host-1.0.1/README.md000066400000000000000000000024061322523035200156230ustar00rootroot00000000000000README for apt-dater-host ========================= Setup hosts managed by apt-dater: --------------------------------- You need a SSH server and `sudo` installed. Create a user (`the-user` in this example) which will be used to install updates (using root is NOT recommended). useradd the-user Modify the sudoers rules, e.g. `/etc/sudoers` or `/etc/sudoers.d/apt-dater-host`: Defaults env_reset,env_keep=MAINTAINER the-user ALL=NOPASSWD: /usr/bin/apt-get, /usr/sbin/needrestart For non apt-based distributions you need to replace `/usr/bin/apt-get` with the equivalent, e.g. `/usr/bin/yum`. You can verify the setup by calling sudo -l -U the-user Additional steps for a manual `apt-dater-host` installation: ------------------------------------------------------------ Put `apt-dater-host` on the managed host (folder must be present in `$PATH` of `the-user`). Put `apt-dater-host.conf` to `$CFGFILE` (default is `/etc/apt-dater-host.conf`). At your management server: -------------------------- Create a user on your management server which perform updates on your hosts. Generate a SSH keypair: ssh-keygen [..] -f ~/.ssh/apt-dater Distribute the public key(s) e.g.: ssh-copy-id -i ~/.ssh/apt-dater.pub the-user@managed-host apt-dater-host-1.0.1/apk/000077500000000000000000000000001322523035200151155ustar00rootroot00000000000000apt-dater-host-1.0.1/apk/Makefile000066400000000000000000000003701322523035200165550ustar00rootroot00000000000000clean: check: ./test-apt-dater-host install: install -D -m0755 apt-dater-host \ $(DESTDIR)/usr/bin/apt-dater-host install -m0750 -d $(DESTDIR)/etc/sudoers.d install -m0640 apt-dater-host-sudoers \ $(DESTDIR)/etc/sudoers.d/apt-dater-host apt-dater-host-1.0.1/apk/apt-dater-host000077500000000000000000000107401322523035200177010ustar00rootroot00000000000000#!/bin/sh # apt-dater - terminal-based remote package update manager # # Implementation of the protocol described in # https://github.com/DE-IBH/apt-dater-host/blob/master/doc/ADP-0.6 # using Busybox ash, awk and sed for use with Alpine Linux # # Author: # Henrik Riomar # # Copyright Holder: # 2016, 2017 (C) Henrik Riomar # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # ADP_VERSION="0.6" ROOT_CMD="sudo" APK_CMD="/sbin/apk" VIRT_WHAT_CMD="/usr/sbin/virt-what --test-root=/" err=255 # exit code returned by Perl from die() # LSBREL: ${Distri}|{Version}|${Codename} get_lsbrel() { name=$(awk -F= '/^ID/ {print $NF}' /etc/os-release) version=$(awk -F= '/^VERSION_ID/ {print $NF}' /etc/os-release) echo "LSBREL: ${name}|${version}|" } # PRL: ${URI} get_prl() { sed -n 's/^http/PRL: http/p' /etc/apk/repositories } # check if a pkg is held back is_held() { grep -E -q -e ^$1\= -e ^$1\< /etc/apk/world } # check if $1 > $2 newer_then() { [ x"$($APK_CMD version -t $1 $2)" = x">" ] && return 0 return 1 } # STATUS: ${Package}|${InstVersion}|${Status}... get_pkg_stat() { tmp=$(mktemp) $APK_CMD version -v | grep -v "^Installed:" > $tmp $APK_CMD info | while read -r pkg do line=$(grep -E "^${pkg}-[0-9]" $tmp) new_ver=$(echo $line | sed 's/ @.\+$//' | awk '{print $NF}') cur_ver=$(echo $line | awk '{print $1}' | sed "s/$pkg-//") if [ x"$new_ver" = x"$cur_ver" ]; then echo "STATUS: $pkg|$cur_ver|i" elif is_held $pkg; then echo "STATUS: $pkg|$cur_ver|h" elif [ x"$new_ver" = x"?" ]; then echo "STATUS: $pkg|$cur_ver|x" elif newer_then $new_ver $cur_ver; then echo "STATUS: $pkg|$cur_ver|u=$new_ver" else # newer installed ($cur_ver) than available, # ADP 0.6 does not describe this case # x should be suitable for now. echo "STATUS: $pkg|$cur_ver|x" fi done rm $tmp } # VIRT: ${Name} get_virt() { virt=$(dmesg | awk '/Hypervisor detected:/ {print $NF}') if [ -n "$virt" ]; then echo "VIRT: $virt" else virt=$($VIRT_WHAT_CMD 2> /dev/null) ret=$? if [ -z "$virt" ]; then [ $ret -eq 0 ] && echo "VIRT: Physical" || echo "VIRT: Unknown" else echo "VIRT: $(echo $virt | awk '{print $1}')" fi fi } # UNAME: ${KERNEL-NAME}|${MACHINE} get_uname() { echo "UNAME: $(uname -s)|$(uname -m)" } # KERNELINFO: ${Code} ${Release} get_kern() { # 0 - latest running # 1 - reboot # 9 - Unknown running=$(uname -r) flavor=$(uname -r | awk -F- '{print $NF}') vmlinuz="/boot/vmlinuz-$flavor" if [ -r $vmlinuz ]; then installed=$($APK_CMD info --who-owns $vmlinuz | grep -E -o "[0-9]+.[0-9]+.[0-9]+-r[0-9]") with_r=$(echo $running | sed -e "s/[0-9]-${flavor}$/r&/g" | sed "s/-${flavor}//") if [ x"$($APK_CMD version -t $with_r $installed)" = x'=' ]; then echo "KERNELINFO: 0 $running" else echo "KERNELINFO: 1 $running" fi else echo "KERNELINFO: 9 $running" fi } # FORBID: ${Operations} check_forbid() { echo "FORBID: 0" } # ADPROTO: ${ProtoVersion} say_hi() { echo "ADPROTO: $ADP_VERSION" } do_status() { get_lsbrel get_prl get_virt get_uname check_forbid get_pkg_stat get_kern } run_as_root() { err_str="ADPERR:" interactive=$1 [ $interactive -eq 1 ] && err_str="ERROR:" shift proxy="/etc/profile.d/proxy.sh" [ -r $proxy ] && source $proxy cmd="$ROOT_CMD $*" $cmd ret=$? if [ $ret -ne 0 ]; then echo "$err_str \"$cmd\" returned $ret" exit $err fi } if [ -z "$1" ]; then echo "Don't call this script directly!" exit $err fi case "$1" in refresh) say_hi run_as_root 0 $APK_CMD update do_status ;; status) say_hi do_status ;; upgrade) run_as_root 1 $APK_CMD upgrade ;; install) shift echo "Installing PKG: $*" run_as_root 1 $APK_CMD add $* ;; kernel) say_hi get_kern ;; source-only) # do nothing (used for unit testing) ;; *) echo Invalid command \'$1\'\! exit $err ;; esac apt-dater-host-1.0.1/apk/apt-dater-host-sudoers000066400000000000000000000003611322523035200213560ustar00rootroot00000000000000# apt-dater-host sudoers.d config file # ------------------------------------ # # Keep http_proxy environment variable #Defaults env_keep += http_proxy # Allow members of group adm to execute the apk command #%adm ALL=NOPASSWD: /sbin/apk apt-dater-host-1.0.1/apk/test-apt-dater-host000077500000000000000000000010361322523035200206540ustar00rootroot00000000000000#!/usr/bin/env bats source ./apt-dater-host source-only check_tag() { TAG=$1 STR=$2 [ $(echo $STR | grep -E -v -c "^$TAG:") -eq 0 ] } @test "say_hi()" { result="$(say_hi)" check_tag ADPROTO $result [ "$result" = "ADPROTO: 0.6" ] } @test "get_lsbrel()" { result="$(get_lsbrel)" check_tag LSBREL $result } @test "get_pkg_stat()" { result="$(get_pkg_stat)" check_tag STATUS $result } @test "get_virt()" { result="$(get_virt)" check_tag VIRT $result } @test "get_kern()" { result="$(get_kern)" check_tag KERNELINFO $result } apt-dater-host-1.0.1/apt-dater-host.spec000066400000000000000000000023131322523035200200510ustar00rootroot00000000000000Name: apt-dater-host Version: 1.0.1 Release: 1%{?dist} BuildArch: noarch Summary: Host helper application for apt-dater License: GPL2 URL: https://github.com/DE-IBH/apt-dater-host/ Source0: https://github.com/DE-IBH/apt-dater-host/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz %description Host helper application for apt-dater, a terminal-based remote package update manager. apt-dater provides an easy to use ncurses frontend for managing package updates on a large number of remote hosts using SSH. It supports Debian-based managed hosts as well as OpenSUSE and CentOS based systems. %prep %autosetup %build %install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT/%{_bindir}/ mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/ mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man1/ install yum/apt-dater-host $RPM_BUILD_ROOT/%{_bindir}/ install yum/apt-dater-host.conf $RPM_BUILD_ROOT/%{_sysconfdir}/ install man/apt-dater-host.1 $RPM_BUILD_ROOT/%{_mandir}/man1/ %files %doc README %{_bindir}/apt-dater-host %config %{_sysconfdir}/apt-dater-host.conf %{_mandir}/man1/apt-dater-host.1* %changelog * Sat Dec 3 2016 Mike Gerber - First package apt-dater-host-1.0.1/doc/000077500000000000000000000000001322523035200151075ustar00rootroot00000000000000apt-dater-host-1.0.1/doc/ADP-0.1000066400000000000000000000060401322523035200157320ustar00rootroot00000000000000apt-dater protocol 0.6 ====================== This file documents the protocol between apt-dater and the apt-dater-host command called via ssh on remote hosts. The protocol is designed to be a generic package management interface and cover most common GNU/Linux based package manager philosophies. Hosts managed by apt-dater musst have the apt-dater-host command in the search path. User interactive commands (see below) will be shown to the user unfiltered. Non-user interactive commands are parse by apt-dater. Non-user interactive sessions should start with the protocol version: ADPROTO: ${ProtoVersion} The current protocol version is 0.1. Example: ADPROTO: 0.1 Calling syntax ============== An apt-dater-host script must accept the following command parameters: refresh ------- Updates the package list (i.e. apt-get update) and retrieve status informations (see next command). This command is called none user interactive. status ------ Prints status informations about installed distribution and packages. This command is non user interactive. There should be an LSB release line of the format: LSBREL: ${Distri}|{Version}|${Codename} Example for Debian Etch: LSBREL: Debian|4.0|etch For each installed package there must be a status line: STATUS: ${Package}|${InstVersion}|${Status}... Supported status values: i : installed h : hold back u=${NewVersion} : update available x : extra (no version found in any repository, this might be an obsoleted package) Example for an installed package: STATUS: g++-4.1|4.1.1-21|i Example for an installed package with an update available: STATUS: dnsutils|1:9.3.4-2etch1|u=1:9.3.4-2etch3 There should be a kernel info line (see also 'kernel' command). upgrade ------- Install all available upgrades, this is user interactive. install ------- Install package(s) given as parameters to this command. This command is user interactive. kernel ------ Retrieves informations about the running kernel. This command is non user interactive. The result line has the following format: KERNELINFO: ${Code} ${Release} The following codes are supported: 0 - The running kernel is the latest distri kernel. No reboot required. 1 - The running kernel is an distri kernel but it's older then the latest installed. A reboot is recommended. 2 - No distri kernel is running. 9 - Unknown. The release field should be the output of `uname -r`. Example ======= The following lines show an example output of the 'status' command for a Debian Etch installation (the 'STATUS:' lines are truncated): ADPROTO: 0.1 LSBREL: Debian|4.0|etch STATUS: groff-base|1.18.1.1-12|i STATUS: libgnome2-0|2.16.0-2|i STATUS: m4|1.4.8-2|i STATUS: liblwres9|1:9.3.4-2etch1|u=1:9.3.4-2etch3 STATUS: linux-image-2.6-686|2.6.24+13|h STATUS: apache2-mpm-prefork|2.2.3-4+etch4|i STATUS: iceweasel-l10n-de|2.0.0.3+debian-1etch1|i STATUS: mutt|1.5.17+20080114-1~bpo40+1|u=1.5.18-2~bpo40+1 STATUS: libperl5.8|5.8.8-7etch3|i STATUS: autoconf|2.61-4|i KERNELINFO: 2 2.6.18-028stab053.5-openvz apt-dater-host-1.0.1/doc/ADP-0.2000066400000000000000000000076421322523035200157440ustar00rootroot00000000000000apt-dater protocol 0.6 ====================== This file documents the protocol between apt-dater and the apt-dater-host command called via ssh on remote hosts. The protocol is designed to be a generic package management interface and cover most common GNU/Linux based package manager philosophies. Hosts managed by apt-dater musst have the apt-dater-host command in the search path. User interactive commands (see below) will be shown to the user unfiltered. Non-user interactive commands are parse by apt-dater. Non-user interactive sessions should start with the protocol version: ADPROTO: ${ProtoVersion} The current protocol version is 0.2. Example: ADPROTO: 0.2 Calling syntax ============== An apt-dater-host script must accept the following command parameters: refresh ------- Updates the package list (i.e. apt-get update) and retrieve status informations (see next command). This command is called none user interactive. status ------ Prints status informations about installed distribution and packages. This command is non user interactive. There should be an LSB release line of the format: LSBREL: ${Distri}|{Version}|${Codename} Example for Debian Etch: LSBREL: Debian|4.0|etch There sould be an VIRTualization line of the format: VIRT: ${Name} This will only work if the remote host has the imvirt script installed. Detected virtualizations: Microsoft Corporation / Virtual Machine: VIRT: Virtual Machine VMware, Inc. / VMware Virtual Platform: VIRT: VMware Virtual Platform QEMU or KVM: VIRT: QEMU Xen: VIRT: Xen non detected: VIRT: Physical imvirt not installed: VIRT: Unknown There might be a FORBID line of the format: FORBID: ${Operations} This is a mask of forbidded apt-dater-host operations. An single operation is represented by the following values: 1: refresh 2: upgrade 4: install These values are binary ORed. Default value is 0 if no there is no FORBID line (allows all operations). The apt-dater-host executable on the client will refused operations marked as forbidden. For each installed package there must be a status line: STATUS: ${Package}|${InstVersion}|${Status}... Supported status values: i : installed h : hold back u=${NewVersion} : update available x : extra (no version found in any repository, this might be an obsoleted package) Example for an installed package: STATUS: g++-4.1|4.1.1-21|i Example for an installed package with an update available: STATUS: dnsutils|1:9.3.4-2etch1|u=1:9.3.4-2etch3 There should be a kernel info line (see also 'kernel' command). upgrade ------- Install all available upgrades, this is user interactive. install ------- Install package(s) given as parameters to this command. This command is user interactive. kernel ------ Retrieves informations about the running kernel. This command is non user interactive. The result line has the following format: KERNELINFO: ${Code} ${Release} The following codes are supported: 0 - The running kernel is the latest distri kernel. No reboot required. 1 - The running kernel is an distri kernel but it's older then the latest installed. A reboot is recommended. 2 - No distri kernel is running. 9 - Unknown. The release field should be the output of `uname -r`. Example ======= The following lines show an example output of the 'status' command for a Debian Etch installation (the 'STATUS:' lines are truncated): ADPROTO: 0.2 LSBREL: Debian|4.0|etch VIRT: Physical STATUS: groff-base|1.18.1.1-12|i STATUS: libgnome2-0|2.16.0-2|i STATUS: m4|1.4.8-2|i STATUS: liblwres9|1:9.3.4-2etch1|u=1:9.3.4-2etch3 STATUS: linux-image-2.6-686|2.6.24+13|h STATUS: apache2-mpm-prefork|2.2.3-4+etch4|i STATUS: iceweasel-l10n-de|2.0.0.3+debian-1etch1|i STATUS: mutt|1.5.17+20080114-1~bpo40+1|u=1.5.18-2~bpo40+1 STATUS: libperl5.8|5.8.8-7etch3|i STATUS: autoconf|2.61-4|i KERNELINFO: 2 2.6.18-028stab053.5-openvz apt-dater-host-1.0.1/doc/ADP-0.3000066400000000000000000000102661322523035200157410ustar00rootroot00000000000000apt-dater protocol 0.6 ====================== This file documents the protocol between apt-dater and the apt-dater-host command called via ssh on remote hosts. The protocol is designed to be a generic package management interface and cover most common GNU/Linux based package manager philosophies. Hosts managed by apt-dater musst have the apt-dater-host command in the search path. User interactive commands (see below) will be shown to the user unfiltered. Non-user interactive commands are parse by apt-dater. Non-user interactive sessions should start with the protocol version: ADPROTO: ${ProtoVersion} The current protocol version is 0.3. Example: ADPROTO: 0.3 Calling syntax ============== An apt-dater-host script must accept the following command parameters: refresh ------- Updates the package list (i.e. apt-get update) and retrieve status informations (see next command). This command is called none user interactive. status ------ Prints status informations about installed distribution and packages. This command is non user interactive. There should be an LSB release line of the format: LSBREL: ${Distri}|{Version}|${Codename} Example for Debian Etch: LSBREL: Debian|4.0|etch There sould be an VIRTualization line of the format: VIRT: ${Name} This will only work if the remote host has the imvirt script installed. Detected virtualizations: Microsoft Corporation / Virtual Machine: VIRT: Virtual Machine VMware, Inc. / VMware Virtual Platform: VIRT: VMware Virtual Platform QEMU or KVM: VIRT: QEMU Xen: VIRT: Xen non detected: VIRT: Physical imvirt not installed: VIRT: Unknown There sould be an UNAME line of the format: UNAME: ${KERNEL-NAME}|${MACHINE} The values are taken from the uname command: KERNEL-NAME: uname -s MACHINE : uname -m There might be a FORBID line of the format: FORBID: ${Operations} This is a mask of forbidded apt-dater-host operations. An single operation is represented by the following values: 1: refresh 2: upgrade 4: install These values are binary ORed. Default value is 0 if no there is no FORBID line (allows all operations). The apt-dater-host executable on the client will refused operations marked as forbidden. For each installed package there must be a status line: STATUS: ${Package}|${InstVersion}|${Status}... Supported status values: i : installed h : hold back u=${NewVersion} : update available x : extra (no version found in any repository, this might be an obsoleted package) b=${AddInfo} : package is installed but broken (i.e. not configured) Example for an installed package: STATUS: g++-4.1|4.1.1-21|i Example for an installed package with an update available: STATUS: dnsutils|1:9.3.4-2etch1|u=1:9.3.4-2etch3 There should be a kernel info line (see also 'kernel' command). upgrade ------- Install all available upgrades, this is user interactive. install ------- Install package(s) given as parameters to this command. This command is user interactive. kernel ------ Retrieves informations about the running kernel. This command is non user interactive. The result line has the following format: KERNELINFO: ${Code} ${Release} The following codes are supported: 0 - The running kernel is the latest distri kernel. No reboot required. 1 - The running kernel is an distri kernel but it's older then the latest installed. A reboot is recommended. 2 - No distri kernel is running. 9 - Unknown. The release field should be the output of `uname -r`. Example ======= The following lines show an example output of the 'status' command for a Debian Etch installation (the 'STATUS:' lines are truncated): ADPROTO: 0.3 LSBREL: Debian|4.0|etch VIRT: Physical UNAME: Linux|i686 STATUS: groff-base|1.18.1.1-12|i STATUS: libgnome2-0|2.16.0-2|i STATUS: m4|1.4.8-2|i STATUS: liblwres9|1:9.3.4-2etch1|u=1:9.3.4-2etch3 STATUS: linux-image-2.6-686|2.6.24+13|h STATUS: apache2-mpm-prefork|2.2.3-4+etch4|i STATUS: iceweasel-l10n-de|2.0.0.3+debian-1etch1|i STATUS: mutt|1.5.17+20080114-1~bpo40+1|u=1.5.18-2~bpo40+1 STATUS: libperl5.8|5.8.8-7etch3|i STATUS: autoconf|2.61-4|i KERNELINFO: 2 2.6.18-028stab053.5-openvz apt-dater-host-1.0.1/doc/ADP-0.4000066400000000000000000000107211322523035200157360ustar00rootroot00000000000000apt-dater protocol 0.6 ====================== This file documents the protocol between apt-dater and the apt-dater-host command called via ssh on remote hosts. The protocol is designed to be a generic package management interface and cover most common GNU/Linux based package manager philosophies. Hosts managed by apt-dater musst have the apt-dater-host command in the search path. User interactive commands (see below) will be shown to the user unfiltered. Non-user interactive commands are parse by apt-dater. Non-user interactive sessions should start with the protocol version: ADPROTO: ${ProtoVersion} The current protocol version is 0.4. Example: ADPROTO: 0.4 Calling syntax ============== An apt-dater-host script must accept the following command parameters: refresh ------- Updates the package list (i.e. apt-get update) and retrieve status informations (see next command). This command is called none user interactive. status ------ Prints status informations about installed distribution and packages. This command is non user interactive. There should be an LSB release line of the format: LSBREL: ${Distri}|{Version}|${Codename} Example for Debian Etch: LSBREL: Debian|4.0|etch There sould be an VIRTualization line of the format: VIRT: ${Name} This will only work if the remote host has the imvirt script installed. Detected virtualizations: Microsoft Corporation / Virtual Machine: VIRT: Virtual Machine VMware, Inc. / VMware Virtual Platform: VIRT: VMware Virtual Platform QEMU or KVM: VIRT: QEMU Xen: VIRT: Xen non detected: VIRT: Physical imvirt not installed: VIRT: Unknown There sould be an UNAME line of the format: UNAME: ${KERNEL-NAME}|${MACHINE} The values are taken from the uname command: KERNEL-NAME: uname -s MACHINE : uname -m There might be a FORBID line of the format: FORBID: ${Operations} This is a mask of forbidded apt-dater-host operations. An single operation is represented by the following values: 1: refresh 2: upgrade 4: install These values are binary ORed. Default value is 0 if no there is no FORBID line (allows all operations). The apt-dater-host executable on the client will refused operations marked as forbidden. There should be an UUID line: UUID: {$UUID} This is the DCE 1.1, ISO/IEC 11578:1996 and RFC 4122 compliant Universally Unique Identifier (UUID) of the host. It should be a DCE version 1 (time and node based) UUID, generated at the installation time of the apt-dater-host client. For each installed package there must be a status line: STATUS: ${Package}|${InstVersion}|${Status}... Supported status values: i : installed h : hold back u=${NewVersion} : update available x : extra (no version found in any repository, this might be an obsoleted package) b=${AddInfo} : package is installed but broken (i.e. not configured) Example for an installed package: STATUS: g++-4.1|4.1.1-21|i Example for an installed package with an update available: STATUS: dnsutils|1:9.3.4-2etch1|u=1:9.3.4-2etch3 There should be a kernel info line (see also 'kernel' command). upgrade ------- Install all available upgrades, this is user interactive. install ------- Install package(s) given as parameters to this command. This command is user interactive. kernel ------ Retrieves informations about the running kernel. This command is non user interactive. The result line has the following format: KERNELINFO: ${Code} ${Release} The following codes are supported: 0 - The running kernel is the latest distri kernel. No reboot required. 1 - The running kernel is an distri kernel but it's older then the latest installed. A reboot is recommended. 2 - No distri kernel is running. 9 - Unknown. The release field should be the output of `uname -r`. Example ======= The following lines show an example output of the 'status' command for a Debian Etch installation (the 'STATUS:' lines are truncated): ADPROTO: 0.3 LSBREL: Debian|4.0|etch VIRT: Physical UNAME: Linux|i686 STATUS: groff-base|1.18.1.1-12|i STATUS: libgnome2-0|2.16.0-2|i STATUS: m4|1.4.8-2|i STATUS: liblwres9|1:9.3.4-2etch1|u=1:9.3.4-2etch3 STATUS: linux-image-2.6-686|2.6.24+13|h STATUS: apache2-mpm-prefork|2.2.3-4+etch4|i STATUS: iceweasel-l10n-de|2.0.0.3+debian-1etch1|i STATUS: mutt|1.5.17+20080114-1~bpo40+1|u=1.5.18-2~bpo40+1 STATUS: libperl5.8|5.8.8-7etch3|i STATUS: autoconf|2.61-4|i KERNELINFO: 2 2.6.18-028stab053.5-openvz apt-dater-host-1.0.1/doc/ADP-0.5000066400000000000000000000112721322523035200157410ustar00rootroot00000000000000apt-dater protocol 0.6 ====================== This file documents the protocol between apt-dater and the apt-dater-host command called via ssh on remote hosts. The protocol is designed to be a generic package management interface and cover most common GNU/Linux based package manager philosophies. Hosts managed by apt-dater musst have the apt-dater-host command in the search path. User interactive commands (see below) will be shown to the user unfiltered. Non-user interactive commands are parse by apt-dater. Non-user interactive sessions must start with the protocol version: ADPROTO: ${ProtoVersion} The current protocol version is 0.5. Example: ADPROTO: 0.5 If apt-dater-host detects an error (i.e. from the package manager) during a non-interactive command it must add an error line containing an user readable error message: ADPERR: ${Message} The message string should not be empty. Calling syntax ============== An apt-dater-host script must accept the following command parameters: refresh ------- Updates the package list (i.e. apt-get update) and retrieve status informations (see next command). This command is called none user interactive. status ------ Prints status informations about installed distribution and packages. This command is non user interactive. There should be an LSB release line of the format: LSBREL: ${Distri}|{Version}|${Codename} Example for Debian Etch: LSBREL: Debian|4.0|etch There sould be an VIRTualization line of the format: VIRT: ${Name} This will only work if the remote host has the imvirt script installed. Detected virtualizations: Microsoft Corporation / Virtual Machine: VIRT: Virtual Machine VMware, Inc. / VMware Virtual Platform: VIRT: VMware Virtual Platform QEMU or KVM: VIRT: QEMU Xen: VIRT: Xen non detected: VIRT: Physical imvirt not installed: VIRT: Unknown There sould be an UNAME line of the format: UNAME: ${KERNEL-NAME}|${MACHINE} The values are taken from the uname command: KERNEL-NAME: uname -s MACHINE : uname -m There might be a FORBID line of the format: FORBID: ${Operations} This is a mask of forbidded apt-dater-host operations. An single operation is represented by the following values: 1: refresh 2: upgrade 4: install These values are binary ORed. Default value is 0 if no there is no FORBID line (allows all operations). The apt-dater-host executable on the client will refused operations marked as forbidden. There should be an UUID line: UUID: {$UUID} This is the DCE 1.1, ISO/IEC 11578:1996 and RFC 4122 compliant Universally Unique Identifier (UUID) of the host. It should be a DCE version 1 (time and node based) UUID, generated at the installation time of the apt-dater-host client. For each installed package there must be a status line: STATUS: ${Package}|${InstVersion}|${Status}... Supported status values: i : installed h : hold back u=${NewVersion} : update available x : extra (no version found in any repository, this might be an obsoleted package) b=${AddInfo} : package is installed but broken (i.e. not configured) Example for an installed package: STATUS: g++-4.1|4.1.1-21|i Example for an installed package with an update available: STATUS: dnsutils|1:9.3.4-2etch1|u=1:9.3.4-2etch3 There should be a kernel info line (see also 'kernel' command). upgrade ------- Install all available upgrades, this is user interactive. install ------- Install package(s) given as parameters to this command. This command is user interactive. kernel ------ Retrieves informations about the running kernel. This command is non user interactive. The result line has the following format: KERNELINFO: ${Code} ${Release} The following codes are supported: 0 - The running kernel is the latest distri kernel. No reboot required. 1 - The running kernel is an distri kernel but it's older then the latest installed. A reboot is recommended. 2 - No distri kernel is running. 9 - Unknown. The release field should be the output of `uname -r`. Example ======= The following lines show an example output of the 'status' command for a Debian Etch installation (the 'STATUS:' lines are truncated): ADPROTO: 0.3 LSBREL: Debian|4.0|etch VIRT: Physical UNAME: Linux|i686 STATUS: groff-base|1.18.1.1-12|i STATUS: libgnome2-0|2.16.0-2|i STATUS: m4|1.4.8-2|i STATUS: liblwres9|1:9.3.4-2etch1|u=1:9.3.4-2etch3 STATUS: linux-image-2.6-686|2.6.24+13|h STATUS: apache2-mpm-prefork|2.2.3-4+etch4|i STATUS: iceweasel-l10n-de|2.0.0.3+debian-1etch1|i STATUS: mutt|1.5.17+20080114-1~bpo40+1|u=1.5.18-2~bpo40+1 STATUS: libperl5.8|5.8.8-7etch3|i STATUS: autoconf|2.61-4|i KERNELINFO: 2 2.6.18-028stab053.5-openvz apt-dater-host-1.0.1/doc/ADP-0.6000066400000000000000000000130621322523035200157410ustar00rootroot00000000000000apt-dater protocol 0.6 ====================== This file documents the protocol between apt-dater and the apt-dater-host command called via ssh on remote hosts. The protocol is designed to be a generic package management interface and cover most common GNU/Linux based package manager philosophies. Hosts managed by apt-dater musst have the apt-dater-host command in the search path. User interactive commands (see below) will be shown to the user unfiltered. Non-user interactive commands are parse by apt-dater. Non-user interactive sessions must start with the protocol version: ADPROTO: ${ProtoVersion} The current protocol version is 0.6. Example: ADPROTO: 0.6 If apt-dater-host detects an error (i.e. from the package manager) during a non-interactive command it must add an error line containing an user readable error message: ADPERR: ${Message} The message string should not be empty. Calling syntax ============== An apt-dater-host script must accept the following command parameters: refresh ------- Updates the package list (i.e. apt-get update) and retrieve status informations (see next command). This command is called none user interactive. status ------ Prints status informations about installed distribution and packages. This command is non user interactive. There should be an LSB release line of the format: LSBREL: ${Distri}|{Version}|${Codename} Example for Debian Etch: LSBREL: Debian|4.0|etch There sould be PRL (Package Resource List) lines for the archive sources the packaging system is using: PRL: ${URI} The PRL lines must be in a normalized form (no unnecessary spaces). There must be a PRL line for each archive source or no PRL lines at all. Example for Debian Squeezy: PRL: http://ftp.de.debian.org/debian/ squeezy main PRL: http://security.debian.org/ squeeze/updates main PRL: deb http://www.debian-multimedia.org squeeze main A host might be part of one or more cluster (heartbeat, drbd, ...). Cluster nodes should not be updated simultanously. apt-dater will detect cluster nodes by identical CLUSTER lines and avoid updating nodes of the same cluster simultanously: CLUSTER: ${Cluster-A} CLUSTER: ${Cluster-B} The cluster might be any ASCII string and must be identical on all cluster nodes. A node can be part of multiple clusters. There sould be an VIRTualization line of the format: VIRT: ${Name} This will only work if the remote host has the imvirt script installed. Detected virtualizations: Microsoft Corporation / Virtual Machine: VIRT: Virtual Machine VMware, Inc. / VMware Virtual Platform: VIRT: VMware Virtual Platform QEMU or KVM: VIRT: QEMU Xen: VIRT: Xen non detected: VIRT: Physical imvirt not installed: VIRT: Unknown There sould be an UNAME line of the format: UNAME: ${KERNEL-NAME}|${MACHINE} The values are taken from the uname command: KERNEL-NAME: uname -s MACHINE : uname -m There might be a FORBID line of the format: FORBID: ${Operations} This is a mask of forbidded apt-dater-host operations. An single operation is represented by the following values: 1: refresh 2: upgrade 4: install These values are binary ORed. Default value is 0 if no there is no FORBID line (allows all operations). The apt-dater-host executable on the client will refused operations marked as forbidden. There should be an UUID line: UUID: {$UUID} This is the DCE 1.1, ISO/IEC 11578:1996 and RFC 4122 compliant Universally Unique Identifier (UUID) of the host. It should be a DCE version 1 (time and node based) UUID, generated at the installation time of the apt-dater-host client. For each installed package there must be a status line: STATUS: ${Package}|${InstVersion}|${Status}... Supported status values: i : installed h : hold back u=${NewVersion} : update available x : extra (no version found in any repository, this might be an obsoleted package) b=${AddInfo} : package is installed but broken (i.e. not configured) Example for an installed package: STATUS: g++-4.1|4.1.1-21|i Example for an installed package with an update available: STATUS: dnsutils|1:9.3.4-2etch1|u=1:9.3.4-2etch3 There should be a kernel info line (see also 'kernel' command). upgrade ------- Install all available upgrades, this is user interactive. install ------- Install package(s) given as parameters to this command. This command is user interactive. kernel ------ Retrieves informations about the running kernel. This command is non user interactive. The result line has the following format: KERNELINFO: ${Code} ${Release} The following codes are supported: 0 - The running kernel is the latest distri kernel. No reboot required. 1 - The running kernel is an distri kernel but it's older then the latest installed. A reboot is recommended. 2 - No distri kernel is running. 9 - Unknown. The release field should be the output of `uname -r`. Example ======= The following lines show an example output of the 'status' command for a Debian Etch installation (the 'STATUS:' lines are truncated): ADPROTO: 0.3 LSBREL: Debian|4.0|etch VIRT: Physical UNAME: Linux|i686 STATUS: groff-base|1.18.1.1-12|i STATUS: libgnome2-0|2.16.0-2|i STATUS: m4|1.4.8-2|i STATUS: liblwres9|1:9.3.4-2etch1|u=1:9.3.4-2etch3 STATUS: linux-image-2.6-686|2.6.24+13|h STATUS: apache2-mpm-prefork|2.2.3-4+etch4|i STATUS: iceweasel-l10n-de|2.0.0.3+debian-1etch1|i STATUS: mutt|1.5.17+20080114-1~bpo40+1|u=1.5.18-2~bpo40+1 STATUS: libperl5.8|5.8.8-7etch3|i STATUS: autoconf|2.61-4|i KERNELINFO: 2 2.6.18-028stab053.5-openvz apt-dater-host-1.0.1/doc/ADP-0.7000066400000000000000000000154421322523035200157460ustar00rootroot00000000000000apt-dater protocol 0.7 ====================== This file documents the protocol between apt-dater and the apt-dater-host command called via ssh on remote hosts. The protocol is designed to be a generic package management interface and cover most common GNU/Linux based package manager philosophies. Hosts managed by apt-dater musst have the apt-dater-host command in the search path. User interactive commands (see below) will be shown to the user unfiltered. Non-user interactive commands are parse by apt-dater. Non-user interactive sessions must start with the protocol version: ADPROTO: ${ProtoVersion} The current protocol version is 0.7. Example: ADPROTO: 0.7 If apt-dater-host detects an error (i.e. from the package manager) during a non-interactive command it must add an error line containing an user readable error message: ADPERR: ${Message} The message string should not be empty. Calling syntax ============== An apt-dater-host script must accept the following command parameters: refresh ------- Updates the package list (i.e. apt-get update) and retrieve status informations (see next command). This command is called none user interactive. status ------ Prints status informations about installed distribution and packages. This command is non user interactive. There should be an LSB release line of the format: LSBREL: ${Distri}|{Version}|${Codename} Example for Debian Etch: LSBREL: Debian|4.0|etch There sould be PRL (Package Resource List) lines for the archive sources the packaging system is using: PRL: ${URI} The PRL lines must be in a normalized form (no unnecessary spaces). There must be a PRL line for each archive source or no PRL lines at all. Example for Debian Squeezy: PRL: http://ftp.de.debian.org/debian/ squeezy main PRL: http://security.debian.org/ squeeze/updates main PRL: deb http://www.debian-multimedia.org squeeze main A host might be part of one or more cluster (heartbeat, drbd, ...). Cluster nodes should not be updated simultanously. apt-dater will detect cluster nodes by identical CLUSTER lines and avoid updating nodes of the same cluster simultanously: CLUSTER: ${Cluster-A} CLUSTER: ${Cluster-B} The cluster might be any ASCII string and must be identical on all cluster nodes. A node can be part of multiple clusters. There sould be an VIRTualization line of the format: VIRT: ${Name} This will only work if the remote host has the imvirt(1) script installed. Detected virtualizations: Microsoft Corporation / Virtual Machine: VIRT: Virtual Machine VMware, Inc. / VMware Virtual Platform: VIRT: VMware Virtual Platform QEMU or KVM: VIRT: QEMU Xen: VIRT: Xen non detected: VIRT: Physical imvirt not installed: VIRT: Unknown There sould be an UNAME line of the format: UNAME: ${KERNEL-NAME}|${MACHINE} The values are taken from the uname command: KERNEL-NAME: uname -s MACHINE : uname -m There might be a FORBID line of the format: FORBID: ${Operations} This is a mask of forbidded apt-dater-host operations. An single operation is represented by the following values: 1: refresh 2: upgrade 4: install These values are binary ORed. Default value is 0 if no there is no FORBID line (allows all operations). The apt-dater-host executable on the client will refused operations marked as forbidden. There should be an UUID line: UUID: {$UUID} This is the DCE 1.1, ISO/IEC 11578:1996 and RFC 4122 compliant Universally Unique Identifier (UUID) of the host. It should be a DCE version 1 (time and node based) UUID, generated at the installation time of the apt-dater-host client. This UUID is to be used to identify the installation by inventory tools or other 3rd party software. For each installed package there must be a status line: STATUS: ${Package}|${InstVersion}|${Status}... Supported status values: i : installed h : hold back u=${NewVersion} : update available x : extra (no version found in any repository, this might be an obsoleted package) b=${AddInfo} : package is installed but broken (i.e. not configured) Example for an installed package: STATUS: g++-4.1|4.1.1-21|i Example for an installed package with an update available: STATUS: dnsutils|1:9.3.4-2etch1|u=1:9.3.4-2etch3 There should be a kernel info line (see also 'kernel' command). There should be NEEDRESTART line indicating the presence and the version of the needrestart(1) script: NEEDRESTART-VER: ${Version} needrestart(1) is called in batch mode printing informations about services requiring restarts and outdated running kernels. The definition of the lines prefixed with 'NEEDRESTART-' are defined by the needrestart package. The following lines are currently known: NEEDRESTART-KCUR: ${running kernel version} NEEDRESTART-KEXP: ${expected kernel version} NEEDRESTART-KSTA: ${kernel status} NEEDRESTART-SVC: ${service} upgrade ------- Install all available upgrades, this is user interactive. install ------- Install package(s) given as parameters to this command. This command is user interactive. kernel ------ Retrieves informations about the running kernel. This command is non user interactive. The result line has the following format: KERNELINFO: ${Code} ${Release} The following codes are supported: 0 - The running kernel is the latest distri kernel. No reboot required. 1 - The running kernel is an distri kernel but it's older then the latest installed. A reboot is recommended. 2 - No distri kernel is running. 9 - Unknown. The release field should be the output of `uname -r`. Examples ======== The following lines show an example output of the 'status' command for a Debian Etch installation (the 'STATUS:' lines are truncated): ADPROTO: 0.3 LSBREL: Debian|4.0|etch VIRT: Physical UNAME: Linux|i686 STATUS: groff-base|1.18.1.1-12|i STATUS: libgnome2-0|2.16.0-2|i STATUS: m4|1.4.8-2|i STATUS: liblwres9|1:9.3.4-2etch1|u=1:9.3.4-2etch3 STATUS: linux-image-2.6-686|2.6.24+13|h STATUS: apache2-mpm-prefork|2.2.3-4+etch4|i STATUS: iceweasel-l10n-de|2.0.0.3+debian-1etch1|i STATUS: mutt|1.5.17+20080114-1~bpo40+1|u=1.5.18-2~bpo40+1 STATUS: libperl5.8|5.8.8-7etch3|i STATUS: autoconf|2.61-4|i KERNELINFO: 2 2.6.18-028stab053.5-openvz Another example for ADP 0.7 on Debian Jessie (the 'STATUS:' lines are truncated again): ADPROTO: 0.7 LSBREL: Debian|testing|jessie VIRT: Physical UNAME: Linux|x86_64 FORBID: 0 UUID: 40a437f0-9f1e-11de-a398-001a4d577e31 NEEDRESTART-VER: 1.1 NEEDRESTART-KCUR: 3.16.1-tl1 NEEDRESTART-KEXP: 3.16.1-tl1 NEEDRESTART-KSTA: 1 NEEDRESTART-SVC: apache2.service STATUS: libboost-filesystem1.55.0|1.55.0+dfsg-2|u=1.55.0+dfsg-3 STATUS: libxine1-bin|1:1.1.21-dmo2|d STATUS: cups-filters-core-drivers|1.0.58-1|i STATUS: linux-headers-3.2.0-0.bpo.2-common|3.2.18-1~bpo60+1|x KERNELINFO: 2 3.16.1-tl1 apt-dater-host-1.0.1/doc/README.sshkey000066400000000000000000000004441322523035200172760ustar00rootroot00000000000000Bind to ssh keys ================ apt-dater-host can be bind on a ssh key: $ cat ~/.ssh/authorized_key command="/usr/bin/apt-dater-host sshkey",no-port-forwarding ssh-dss apt-dater@ibh.net This will prevent you from using 'connect' within apt-dater to open a shell on the client. apt-dater-host-1.0.1/dpkg/000077500000000000000000000000001322523035200152675ustar00rootroot00000000000000apt-dater-host-1.0.1/dpkg/Makefile000066400000000000000000000010031322523035200167210ustar00rootroot00000000000000clean: install: mkdir -p $(DESTDIR)/usr/bin cp apt-dater-host $(DESTDIR)/usr/bin mkdir -p $(DESTDIR)/etc cp apt-dater-host.conf $(DESTDIR)/etc mkdir -p $(DESTDIR)/etc/kernel/postinst.d cp scripts/apt-dater-host_reboot $(DESTDIR)/etc/kernel/postinst.d mkdir -p $(DESTDIR)/etc/apt/apt.conf.d cp scripts/99apt-dater-host_periodic $(DESTDIR)/etc/apt/apt.conf.d mkdir -p $(DESTDIR)/etc/sudoers.d cp scripts/apt-dater-host $(DESTDIR)/etc/sudoers.d/ chown 0440 $(DESTDIR)/etc/sudoers.d/apt-dater-host apt-dater-host-1.0.1/dpkg/apt-dater-host000077500000000000000000000227231322523035200200570ustar00rootroot00000000000000#!/usr/bin/perl # apt-dater - terminal-based remote package update manager # # Authors: # Andre Ellguth # Thomas Liske # # Copyright Holder: # 2008-2014 (C) IBH IT-Service GmbH [http://www.ibh.de/apt-dater/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # use AptPkg::Config '$_config'; use AptPkg::System '$_system'; use AptPkg::Cache; use ImVirt; use strict; use warnings; my $CFGFILE = '/etc/apt-dater-host.conf'; my $DPKGTOOL = 'apt-get'; my $APTUPGRADE = 'dist-upgrade'; my $ASSUMEYES = 0; my $GETROOT = 'sudo'; my $CLEANUP = 0; my $FORBID_REFRESH = 0; my $FORBID_UPGRADE = 0; my $FORBID_INSTALL = 0; my $UUIDFILE = '/etc/apt-dater-host.uuid'; my @CLUSTERS; my $NEEDRESTART; my $RUNNEEDREST; my $CMD = shift; my $ADPROTO = '0.7'; $ENV{'LC_ALL'} = 'C'; if (-r $CFGFILE) { eval `cat "$CFGFILE"` ; if($@ ne '') { print "ADPROTO: $ADPROTO\n"; print "ADPERR: Invalid config $CFGFILE: $@\n"; exit; } } $GETROOT = '' if($> == 0); die "Don't call this script directly!\n" unless (defined($CMD)); if($CMD eq 'sshkey') { die "Sorry, no shell access allowed!\n" unless(defined($ENV{'SSH_ORIGINAL_COMMAND'})); @ARGV = split(' ', $ENV{'SSH_ORIGINAL_COMMAND'}); shift; $CMD = shift; } die "Invalid command '$CMD'!\n" unless ($CMD=~/^(refresh|status|upgrade|install|kernel)$/); if ($CMD eq 'refresh') { print "ADPROTO: $ADPROTO\n"; if ($FORBID_REFRESH) { print STDERR "\n\n** Sorry, apt-dater based refreshs on this host are disabled! **\n\n" } else { &do_refresh; } &do_status; &do_kernel; } elsif ($CMD eq 'status') { print "ADPROTO: $ADPROTO\n"; &do_status; &do_kernel; } elsif ($CMD eq 'upgrade') { if ($FORBID_UPGRADE) { print STDERR "\n\n** Sorry, apt-dater based upgrades on this host are disabled! **\n\n"; } else { &do_upgrade; &do_cleanup; } } elsif ($CMD eq 'install') { if ($FORBID_INSTALL) { print STDERR "\n\n** Sorry, apt-dater based installations on this host are disabled! **\n\n"; } else { &do_install(@ARGV); &do_cleanup; } } elsif ($CMD eq 'kernel') { print "ADPROTO: $ADPROTO\n"; &do_kernel; } else { die "Internal error!\n"; } sub do_refresh() { if(system(($GETROOT ? $GETROOT : ()), $DPKGTOOL, 'update')) { print "\nADPERR: Failed to execute '$GETROOT $DPKGTOOL update' ($?).\n"; exit(1); } } sub get_virt() { return imv_get(IMV_PROB_DEFAULT); } sub get_uname() { my $kernel; my $machine; chomp($kernel = `uname -s`); chomp($machine = `uname -m`); return "$kernel|$machine"; } sub do_status() { # initialise the global config object with the default values and # setup the $_system object $_config->init; $_system = $_config->system; # supress cache building messages $_config->{quiet} = 2; # set up the cache my $cache = AptPkg::Cache->new; # retrieve lsb informations unless (open(HLSB, "lsb_release -a 2> /dev/null |")) { print "\nADPERR: Failed to execute 'lsb_release -a' ($!).\n"; exit(1); } my %lsb; while() { chomp; $lsb{$1}=$2 if (/^(Distributor ID|Release|Codename):\s+(\S.*)$/); } close(HLSB); if($?) { print "\nADPERR: Error executing 'lsb_release -a' ($?).\n"; exit(1); } print "LSBREL: $lsb{'Distributor ID'}|$lsb{'Release'}|$lsb{'Codename'}\n"; # retrieve virtualization informations print "VIRT: ".&get_virt."\n"; # retrieve uname informations print "UNAME: ".&get_uname."\n"; # calculate forbid mask my $mask = 0; $mask |= 1 if ($FORBID_REFRESH); $mask |= 2 if ($FORBID_UPGRADE); $mask |= 4 if ($FORBID_INSTALL); print "FORBID: $mask\n"; # add installation UUID if available if(-r $UUIDFILE && -s $UUIDFILE) { print "UUID: ", `head -n 1 "$UUIDFILE"`; } # add cluster name if available foreach my $CLUSTER (@CLUSTERS) { print "CLUSTER: $CLUSTER\n"; } # add needrestart batch output system(($GETROOT ? $GETROOT : ()), $NEEDRESTART, '-b') if($NEEDRESTART); # get packages which might be upgraded my %updates; my %holds; my $pos = 0; my $DPKGARGS; if($DPKGTOOL eq "apt-get") { $DPKGARGS = "--quiet --simulate --fix-broken --allow-unauthenticated"; } elsif($DPKGTOOL eq "aptitude") { $DPKGARGS = "--verbose --assume-yes --quiet --simulate -f --allow-untrusted"; } else { # unkown DPKG frontend - fallback to apt-get $DPKGTOOL = "apt-get"; $DPKGARGS = "--quiet --simulate --fix-broken --allow-unauthenticated"; } unless(open(HAPT, "$DPKGTOOL $DPKGARGS dist-upgrade |")) { print "\nADPERR: Failed to execute '$DPKGTOOL $DPKGARGS dist-upgrade' ($!).\n"; exit(1); } while() { chomp; if($pos == 0) { $pos=1 if (/^The following packages have been kept back/); $pos=2 if (/^The following packages will be upgraded:/); next; } if($pos == 1) { unless (/^\s/) { $pos++; next; } while(/^\s*(\S+)(\s(.+))?$/) { $holds{$1} = 1; if(defined($2)) { $_ = $2; } else { $_ = ''; } } } $updates{$1} = $2 if (/^Inst (\S+) \[.+\] \((\S+) /); } close(HAPT); if($?) { print "\nADPERR: Error executing '$DPKGTOOL $DPKGARGS dist-upgrade' ($?).\n"; exit(1); } # get version of installed packages my %installed; my %status; my $arch = `dpkg --print-architecture`; chomp($arch); unless(open(HDPKG, "dpkg-query --show --showformat='\${Package} \${Version} \${Status} \${Architecture}\\n' |")) { print "\nADPERR: Failed to execute \"dpkg-query --show --showformat='\${Package} \${Version} \${Status} \${Architecture}\\n'\" ($!).\n"; exit(1); } while() { chomp; next unless (/^(\S+) (\S+) (\S+) (\S+) (\S+) (\S+)$/); my $pkg = $1; $pkg .= ":$6" if($6 ne q(all) && $6 ne $arch); $installed{$pkg} = $2 ; if($holds{$pkg}) { $status{$pkg} = 'h'; } elsif($updates{$pkg}) { $status{$pkg} = 'u'; } else { $status{$pkg} = substr($3, 0, 1); if ($status{$pkg} eq 'i') { my $p = $cache->{$1}; unless ($5 eq 'installed') { $status{$pkg} = "b=$5"; } elsif ($p) { if (my $available = $p->{VersionList}) { my $extra = 1; for my $v (@$available) { for my $f (map $_->{File}, @{$v->{FileList}}) { $extra = 0 unless ($f->{FileName} eq '/var/lib/dpkg/status'); } } $status{$pkg} = 'x' if($extra); } } } } } close(HDPKG); if($?) { print "\nADPERR: Error executing \"dpkg-query --show --showformat='\${Package} \${Version} \${Status}\\n'\" ($?).\n"; exit(1); } foreach my $pkg (keys %installed) { print "STATUS: $pkg|$installed{$pkg}|$status{$pkg}"; if (exists($updates{$pkg})) { print "=$updates{$pkg}" ; } print "\n"; } } sub do_upgrade() { my $UpgradeCmd = "$DPKGTOOL "; $UpgradeCmd .= '-o Aptitude::Delete-Unused=false ' if($DPKGTOOL eq 'aptitude'); $UpgradeCmd .= $APTUPGRADE; # drop -y if any packages would be removed if($ASSUMEYES) { unless(open(HAPT, "$UpgradeCmd --simulate --assume-yes |")) { print "\nADPERR: Failed to execute '$UpgradeCmd --simulate' ($!).\n"; exit(1); } while() { chomp; if(/^The following packages will be REMOVED:/) { $ASSUMEYES = undef; last; } last if(/^\d+ upgraded, \d+ newly installed/); } close(HAPT); $UpgradeCmd .= ' --assume-yes' if($ASSUMEYES); } system("$GETROOT $UpgradeCmd"); } sub do_install() { system(($GETROOT ? $GETROOT : ()), $DPKGTOOL, 'install', @_); } sub do_kernel() { my $infostr = 'KERNELINFO:'; my $verfile = '/proc/version'; my $versignfile = '/proc/version_signature'; my $version = `uname -r`; chomp($version); unless(-r $verfile) { print "$infostr 9 $version\n"; return; } my $vers = ''; if (-r $versignfile) { unless(`cat $versignfile` =~ /^Ubuntu (\S+)-\S+ \S+$/) { print "$infostr 2 $version\n"; return; } $vers = $1; } else { my $vstr = `cat $verfile`; unless($vstr =~ /^\S+ \S+ \S+ \(Debian ([^\)]+)\)/ || $vstr =~ /^\S+ \S+ \S+ \(debian-kernel\@lists\.debian\.org\) .+ Debian (\S+)$/) { print "$infostr 2 $version\n"; return; } $vers = $1; } my $reboot = 0; unless(open(HDPKG, "dpkg-query -W -f='\${Version} \${Status;20} \${Maintainer} \${Provides}\n' 'linux-image*'|grep -E 'install ok installed (Debian|Ubuntu) Kernel Team'|grep linux-image|")) { print "$infostr 9 $version\n"; return; } while() { next unless (/^(\S+)\s/); $reboot=1 unless (system("dpkg", "--compare-versions", $vers, "lt", $1) >> 8); } close(HDPKG); print "$infostr $reboot $version\n"; } sub do_cleanup() { system(($GETROOT ? $GETROOT : ()), $NEEDRESTART) if($RUNNEEDREST); return unless $CLEANUP; system(($GETROOT ? $GETROOT : ()), $DPKGTOOL, 'clean'); } apt-dater-host-1.0.1/dpkg/apt-dater-host.conf000066400000000000000000000027521322523035200210000ustar00rootroot00000000000000# front-end for dpkg to use # Supported: apt-get, aptitude $DPKGTOOL="apt-get"; # Method to do upgrades, possible values (depends on $DPKGTOOL): # upgrade (apt-get, aptitude on Etch) # safe-upgrade (aptitude) # dist-upgrade (recommended default) # # You should use dist-upgrade to get ABI-incompatible upgrades. $APTUPGRADE='dist-upgrade'; # enable use of --assume-yes on safe-upgrade $ASSUMEYES=1; # use this command to become root $GETROOT="sudo"; # clean package cache after upgrade/install $CLEANUP=0; # the installation UUID $UUIDFILE = '/etc/apt-dater-host.uuid'; # If this host is part of (multiple) cluster(s), you might set a # symbolic name. Hosts with the same cluster name won't be upgraded # simultaneously by apt-dater (requires apt-dater 0.9 or above). #@CLUSTERS = qw(my-db-cluster); # Check if needrestart is available. This requires the needrestart # package to be installed. $NEEDRESTART = (-x '/usr/sbin/needrestart' ? '/usr/sbin/needrestart' : undef); # On apt-based systems needrestart should to be called by apt directly, # no need to run it in an interactive mode from within apt-dater-host. #$RUNNEEDREST++; ## ## If this host is a mission critical system and ## needs scheduled downtimes for upgrades, enable ## (some) of the following $FORBID_* lines: ## # prevent apt-dater-host from refreshing package lists #$FORBID_REFRESH=1; # prevent apt-dater-host from upgrading packages #$FORBID_UPGRADE=1; # prevent apt-dater-host from installing packages #$FORBID_INSTALL=1; apt-dater-host-1.0.1/dpkg/scripts/000077500000000000000000000000001322523035200167565ustar00rootroot00000000000000apt-dater-host-1.0.1/dpkg/scripts/99apt-dater-host_periodic000066400000000000000000000002011322523035200235660ustar00rootroot00000000000000APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Download-Upgradeable-Packages "1"; APT::Periodic::AutocleanInterval "7"; apt-dater-host-1.0.1/dpkg/scripts/apt-dater-host000066400000000000000000000005521322523035200215370ustar00rootroot00000000000000# apt-dater-host sudoers.d config file # ------------------------------------ # # Please consider a look at /etc/sudoers.d/README howto enable this file. # # Keep apt-dater's MAINTAINER environment variable #Defaults env_keep += MAINTAINER # Allow members of group adm to execute the apt-get command #%adm ALL=NOPASSWD: /usr/bin/apt-get,/usr/sbin/needrestart apt-dater-host-1.0.1/dpkg/scripts/apt-dater-host_reboot000077500000000000000000000000601322523035200231060ustar00rootroot00000000000000#!/bin/sh touch /var/run/apt-dater-host_reboot apt-dater-host-1.0.1/man/000077500000000000000000000000001322523035200151155ustar00rootroot00000000000000apt-dater-host-1.0.1/man/apt-dater-host.1000066400000000000000000000012261322523035200200340ustar00rootroot00000000000000.TH "APT-DATER-HOST" "1" .SH "NAME" apt\-dater\-host \- host helper application for apt\-dater. .SH "SYNOPSIS" \fBapt\-dater\-host\fR .SH "DESCRIPTION" This manual page documents briefly the \fBapt\-dater\-host\fR helper. \fBapt\-dater\-host\fR is the host helper application for apt\-dater for watching and updating the targeted application about apt\-dater. .SH "AUTHOR" This manual page was written by Patrick Matth\[:a]i for apt\-dater\-host. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 any later version published by the Free Software Foundation. apt-dater-host-1.0.1/rpm/000077500000000000000000000000001322523035200151405ustar00rootroot00000000000000apt-dater-host-1.0.1/rpm/apt-dater-host000077500000000000000000000127171322523035200177320ustar00rootroot00000000000000#!/usr/bin/perl -w # apt-dater - terminal-based remote package update manager # # Authors: # Andre Ellguth # Thomas Liske # # Copyright Holder: # 2008-2012 (C) IBH IT-Service GmbH [http://www.ibh.de/apt-dater/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # use strict; my $CMD = shift; my $ADPROTO = '0.5'; my $UUIDFILE = '/etc/apt-dater-host.uuid'; $ENV{'LC_ALL'} = 'C'; die "Don't call this script directly!\n" unless (defined($CMD)); if($CMD eq 'sshkey') { die "Sorry, no shell access allowed!\n" unless(defined($ENV{'SSH_ORIGINAL_COMMAND'})); @ARGV = split(' ', $ENV{'SSH_ORIGINAL_COMMAND'}); shift; $CMD = shift; } die "Invalid command '$CMD'!\n" unless ($CMD=~/^(refresh|status|upgrade|install|kernel)$/); if ($CMD eq 'refresh') { print "ADPROTO: $ADPROTO\n"; &do_status; &do_kernel; } elsif ($CMD eq 'status') { print "ADPROTO: $ADPROTO\n"; &do_status; &do_kernel; } elsif ($CMD eq 'upgrade') { &do_upgrade; } elsif ($CMD eq 'install') { &do_install(@ARGV); } elsif ($CMD eq 'kernel') { print "ADPROTO: $ADPROTO\n"; &do_kernel; } else { die "Internal error!\n"; } sub get_virt() { return "Unknown" unless (-x '/usr/bin/imvirt'); my $imvirt; chomp($imvirt = `/usr/bin/imvirt`); return $imvirt; } sub get_uname() { my $kernel; my $machine; chomp($kernel = `uname -s`); chomp($machine = `uname -m`); return "$kernel|$machine"; } sub do_status() { # retrieve lsb informations unless (open(HLSB, "lsb_release -a 2> /dev/null |")) { print "\nADPERR: Failed to execute 'lsb_release -a' ($!).\n"; exit(1); } my %lsb; while() { chomp; $lsb{$1}=$2 if (/^(Distributor ID|Release|Codename):\s+(\S.*)$/); } close(HLSB); print "LSBREL: $lsb{'Distributor ID'}|$lsb{'Release'}|$lsb{'Codename'}\n"; # retrieve virtualization informations print "VIRT: ".&get_virt."\n"; # retrieve uname informations print "UNAME: ".&get_uname."\n"; # rpm is readonly, so forbid anything! print "FORBID: 255\n"; # add installation UUID if available if(-r $UUIDFILE && -s $UUIDFILE) { print "UUID: ", `head -n 1 "$UUIDFILE"`; } # get version of installed packages my %installed; my %status; unless(open(HDPKG, "rpm -qa --qf '%{NAME}\t%{VERSION}-%{RELEASE}\ti\n' |")) { print "\nADPERR: Failed to execute 'rpm -qa --qf '%{NAME}\\t%{VERSION}-%{RELEASE}\\ti\\n' ($!).\n"; exit(1); } while() { chomp; next unless (/^(\S+)\s+(\S+)\s+(\S+)/); $installed{$1} = $2 ; $status{$1} = substr($3, 0, 1); } close(HDPKG); foreach my $pkg (keys %installed) { print "STATUS: $pkg|$installed{$pkg}|$status{$pkg}\n"; } } sub do_upgrade() { # not implemented print STDERR "\n\n** Sorry, apt-dater based upgrades on this host are not supported! **\n\n"; } sub do_install() { # not implemented print STDERR "\n\n** Sorry, apt-dater based installations on this host are not supported! **\n\n"; } sub do_kernel() { my $infostr = 'KERNELINFO:'; my $version = `uname -r`; chomp($version); my $ver = $version; my $rel = ''; my $add = ''; $add = $1 if($version =~ /([a-z]+)$/); ($ver, $rel) = ($1, $2) if($version =~ /(.+)-([^-]+)$add$/); $add = "-$add" if($add); my $kinstalled; my $distri = 0; unless(open(HKERNEL, "rpm -q --whatprovides kernel$add --qf '%{NAME}\t%{VERSION}\t%{RELEASE}\n' |")) { print "\nADPERR: Failed to execute 'rpm -q --whatprovides kernel$add --qf '%{NAME}\\t%{VERSION}\\t%{RELEASE}\\n' ($!).\n"; exit(1); } while() { if(/^\S+\s+(\S+)\s+(\S+)/) { if($ver eq $1) { $distri = 1; if(!$kinstalled) { $kinstalled = $2; } else { $kinstalled = $2 if(&versioncmp($kinstalled, $2) < 0); } } } } close(HKERNEL); unless($distri) { print "$infostr 2 $version\n"; return; } unless($kinstalled cmp $rel) { print "$infostr 0 $version\n"; return; } print "$infostr 1 $version\n"; } ## # Taken from Sort::Versions 1.4 # Copyright (c) 1996, Kenneth J. Albanowski. ## sub versioncmp() { my @A = ($_[0] =~ /([-.]|\d+|[^-.\d]+)/g); my @B = ($_[1] =~ /([-.]|\d+|[^-.\d]+)/g); my ($A, $B); while (@A and @B) { $A = shift @A; $B = shift @B; if ($A eq '-' and $B eq '-') { next; } elsif ( $A eq '-' ) { return -1; } elsif ( $B eq '-') { return 1; } elsif ($A eq '.' and $B eq '.') { next; } elsif ( $A eq '.' ) { return -1; } elsif ( $B eq '.' ) { return 1; } elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/) { if ($A =~ /^0/ || $B =~ /^0/) { return $A cmp $B if $A cmp $B; } else { return $A <=> $B if $A <=> $B; } } else { $A = uc $A; $B = uc $B; return $A cmp $B if $A cmp $B; } } @A <=> @B; } apt-dater-host-1.0.1/rug/000077500000000000000000000000001322523035200151375ustar00rootroot00000000000000apt-dater-host-1.0.1/rug/apt-dater-host000077500000000000000000000157261322523035200177340ustar00rootroot00000000000000#!/usr/bin/perl # apt-dater - terminal-based remote package update manager # # Authors: # Andre Ellguth # Thomas Liske # # Copyright Holder: # 2008-2014 (C) IBH IT-Service GmbH [http://www.ibh.de/apt-dater/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # use strict; use warnings; my $CFGFILE = '/etc/apt-dater-host.conf'; my $GETROOT = 'sudo'; my $FORBID_UPGRADE = 0; my $FORBID_INSTALL = 0; my $UUIDFILE = '/etc/apt-dater-host.uuid'; my @CLUSTERS; my $NEEDRESTART; my $RUNNEEDREST; my $CMD = shift; my $ADPROTO = '0.7'; $ENV{'LC_ALL'} = 'C'; if (-r $CFGFILE) { eval `cat "$CFGFILE"` ; if($@ ne '') { print "ADPROTO: $ADPROTO\n"; print "ADPERR: Invalid config $CFGFILE: $@\n"; exit; } } $GETROOT = '' if($> == 0); die "Don't call this script directly!\n" unless (defined($CMD)); if($CMD eq 'sshkey') { die "Sorry, no shell access allowed!\n" unless(defined($ENV{'SSH_ORIGINAL_COMMAND'})); @ARGV = split(' ', $ENV{'SSH_ORIGINAL_COMMAND'}); shift; $CMD = shift; } die "Invalid command '$CMD'!\n" unless ($CMD=~/^(refresh|status|upgrade|install|kernel)$/); if ($CMD eq 'refresh') { print "ADPROTO: $ADPROTO\n"; &do_status; &do_kernel; } elsif ($CMD eq 'status') { print "ADPROTO: $ADPROTO\n"; &do_status; &do_kernel; } elsif ($CMD eq 'upgrade') { if ($FORBID_UPGRADE) { print STDERR "\n\n** Sorry, apt-dater based upgrades on this host are disabled! **\n\n" } else { &do_upgrade; system(($GETROOT ? $GETROOT : ()), $NEEDRESTART) if($RUNNEEDREST); } } elsif ($CMD eq 'install') { if ($FORBID_INSTALL) { print STDERR "\n\n** Sorry, apt-dater based installations on this host are disabled! **\n\n" } else { &do_install(@ARGV); system(($GETROOT ? $GETROOT : ()), $NEEDRESTART) if($RUNNEEDREST); } } elsif ($CMD eq 'kernel') { print "ADPROTO: $ADPROTO\n"; &do_kernel; } else { die "Internal error!\n"; } sub get_virt() { return "Unknown" unless (-x '/usr/bin/imvirt'); my $imvirt; chomp($imvirt = `/usr/bin/imvirt`); return $imvirt; } sub get_uname() { my $kernel; my $machine; chomp($kernel = `uname -s`); chomp($machine = `uname -m`); return "$kernel|$machine"; } sub do_status() { # retrieve lsb informations unless(open(HLSB, "lsb_release -a 2> /dev/null |")) { print "\nADPERR: Failed to execute 'lsb_release -a' ($!).\n"; exit(1); } my %lsb; while() { chomp; $lsb{$1}=$2 if (/^(Distributor ID|Release|Codename):\s+(\S.*)$/); } close(HLSB); if($?) { print "\nADPERR: Error executing 'lsb_release -a' ($?).\n"; exit(1); } print "LSBREL: $lsb{'Distributor ID'}|$lsb{'Release'}|$lsb{'Codename'}\n"; # retrieve virtualization informations print "VIRT: ".&get_virt."\n"; # retrieve uname informations print "UNAME: ".&get_uname."\n"; # calculate forbid mask my $mask = 1; # $mask |= 1 if ($FORBID_REFRESH); NOT SUPPORTED $mask |= 2 if ($FORBID_UPGRADE); $mask |= 4 if ($FORBID_INSTALL); print "FORBID: $mask\n"; # add installation UUID if available if(-r $UUIDFILE && -s $UUIDFILE) { print "UUID: ", `head -n 1 "$UUIDFILE"`; } # add cluster name if available foreach my $CLUSTER (@CLUSTERS) { print "CLUSTER: $CLUSTER\n"; } # add needrestart batch output system(($GETROOT ? $GETROOT : ()), $NEEDRESTART, '-b') if($NEEDRESTART); # get packages which might be upgraded my %updates; unless(open(HAPT, "$GETROOT rug --terse list-updates |")) { print "\nADPERR: Failed to execute '$GETROOT rug --terse list-updates' ($!).\n"; exit(1); }; while() { chomp; $updates{$1} = $2 if (/^.*\|.*\|.*\|([^|]+)\|([^|]+)\|/); } close(HAPT); if($?) { print "\nADPERR: Error executing '$GETROOT rug --terse list-updates' ($?).\n"; exit(1); } # get version of installed packages my %installed; my %status; unless(open(HDPKG, "rpm -qa --qf '%{NAME}|%{VERSION}-%{RELEASE}|\n' |")) { print "\nADPERR: Failed to execute \"rpm -qa --qf '%{NAME}|%{VERSION}-%{RELEASE}|\\n'\" ($!).\n"; exit(1); }; while() { chomp; next unless (/^(\S+)\|\S+\|/); print "STATUS: "; print; if($updates{$1}) { print 'u=', $updates{$1}; } else { print 'i'; } print "\n"; } close(HDPKG); if($?) { print "\nADPERR: Error executing \"rpm -qa --qf '%{NAME}|%{VERSION}-%{RELEASE}|\\n'\" ($?).\n"; exit(1); }; } sub do_upgrade() { system("$GETROOT rug update"); } sub do_install() { if($GETROOT) { system($GETROOT, 'rug', 'install', @_); } else { system('rug', 'install', @_); } } sub do_kernel() { my $infostr = 'KERNELINFO:'; my $version = `uname -r`; chomp($version); my $add = ''; $add = $1 if($version =~ /(-[a-z]+)$/); my $pos = 0; my $kinstalled; my %distri; unless(open(HKERNEL, "rpm -q --whatprovides kernel --qf '%{NAME}|%{VERSION}-%{RELEASE}\n' |")) { print "$infostr 9 $version\n"; return; } while() { chomp; if(/^kernel$add\|(.+)/) { my $ver = $1; $distri{$ver.$add} = 1; if(!$kinstalled) { $kinstalled = $ver; } else { $kinstalled = $ver if(&versioncmp($kinstalled, $ver) < 0); } } } close(HKERNEL); if($?) { print "$infostr 9 $version\n"; return; } unless($distri{$version}) { print "$infostr 2 $version\n"; return; } unless($kinstalled.$add cmp $version) { print "$infostr 0 $version\n"; return; } print "$infostr 1 $version\n"; } ## # Taken from Sort::Versions 1.4 # Copyright (c) 1996, Kenneth J. Albanowski. ## sub versioncmp() { my @A = ($_[0] =~ /([-.]|\d+|[^-.\d]+)/g); my @B = ($_[1] =~ /([-.]|\d+|[^-.\d]+)/g); my ($A, $B); while (@A and @B) { $A = shift @A; $B = shift @B; if ($A eq '-' and $B eq '-') { next; } elsif ( $A eq '-' ) { return -1; } elsif ( $B eq '-') { return 1; } elsif ($A eq '.' and $B eq '.') { next; } elsif ( $A eq '.' ) { return -1; } elsif ( $B eq '.' ) { return 1; } elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/) { if ($A =~ /^0/ || $B =~ /^0/) { return $A cmp $B if $A cmp $B; } else { return $A <=> $B if $A <=> $B; } } else { $A = uc $A; $B = uc $B; return $A cmp $B if $A cmp $B; } } @A <=> @B; } apt-dater-host-1.0.1/rug/apt-dater-host.conf000066400000000000000000000017321322523035200206450ustar00rootroot00000000000000# use this command to become root $GETROOT="sudo"; # the installation UUID $UUIDFILE = '/etc/apt-dater-host.uuid'; # If this host is part of (multiple) cluster(s), you might set a # symbolic name. Hosts with the same cluster name won't be upgraded # simultaneously by apt-dater (requires apt-dater 0.9 or above). #@CLUSTERS = qw(my-db-cluster); # Check if needrestart is available. This requires the needrestart # package to be installed. $NEEDRESTART = (-x '/usr/sbin/needrestart' ? '/usr/sbin/needrestart' : undef); # On apt-based systems needrestart should to be called by apt directly, # no need to run it in an interactive mode from within apt-dater-host. $RUNNEEDREST = $NEEDRESTART; ## ## If this host is a mission critical system and ## needs scheduled downtimes for upgrades, enable ## (some) of the following $FORBID_* lines: ## # prevent apt-dater-host from upgrading packages #$FORBID_UPGRADE=1; # prevent apt-dater-host from installing packages #$FORBID_INSTALL=1; apt-dater-host-1.0.1/wua/000077500000000000000000000000001322523035200151365ustar00rootroot00000000000000apt-dater-host-1.0.1/wua/README.wua000066400000000000000000000024171322523035200166150ustar00rootroot00000000000000apt-dater-host for Windows Update Agent ======================================= This scripts support the Windows Update Agent to search for updates on MS Windows based hosts. You need to have to install a SSH daemon which supports public key authentification and allows bash like command line syntax. Cygwin OpenSSH ============== This SSH daemon is known to work with apt-dater. First install OpenSSH with der Cygwin Installer. Open a shell and run: $ ssh-host-config -y This will generate a initial config, host keys and creates a ssh service. To start the ssh daemon run: $ cygrunsrv.exe -S sshd Finaly you have to create a symlink or script in /usr/local/bin which is named apt-dater-host and calls the apt-dater-host.cmd. Since apt-dater uses SSH public key authentification, apt-dater-host must be run as the SYSTEM user (SID S-1-5-18) to be able to search for updates. To be able to login via SSH as SYSTEM, edit /etc/passwd and add a home directory: SYSTEM:*:18:544:,S-1-5-18:/home/SYSTEM: Create the .ssh directory in the home directory: $ mkdir -p /home/SYSTEM/.ssh And add your public key to the 'authorized_keys' file in the .ssh directory. Remember: SYSTEM has all kinds of dangerous rights, sort of an uber-root account. apt-dater-host-1.0.1/wua/apt-dater-host.cmd000077500000000000000000000000711322523035200204600ustar00rootroot00000000000000@echo off cscript cscript-apt-dater-host.vbs //Nologo %*apt-dater-host-1.0.1/wua/cscript-apt-dater-host.vbs000077500000000000000000000112661322523035200221640ustar00rootroot00000000000000'~ apt-dater - terminal-based remote package update manager '~ '~ Authors: '~ Andre Ellguth '~ Thomas Liske '~ '~ Copyright Holder: '~ 2008-2012 (C) IBH IT-Service GmbH [http://www.ibh.de/apt-dater/] '~ '~ License: '~ This program is free software; you can redistribute it and/or modify '~ it under the terms of the GNU General Public License as published by '~ the Free Software Foundation; either version 2 of the License, or '~ (at your option) any later version. '~ '~ This program is distributed in the hope that it will be useful, '~ but WITHOUT ANY WARRANTY; without even the implied warranty of '~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the '~ GNU General Public License for more details. '~ '~ You should have received a copy of the GNU General Public License '~ along with this package; if not, write to the Free Software '~ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA '~ Dim sh, adproto adproto = "0.2" If WScript.Arguments.Count < 1 Then WScript.Echo "Don't call this script directly!" WScript.Quit End If Set sh = CreateObject("WScript.Shell") cmd = WScript.Arguments.Item(0) If cmd = "refresh" Then WScript.Echo "ADPROTO: " & adproto WScript.Echo WScript.Echo "Sorry, apt-dater based refreshs on this host are disabled!" WScript.Echo do_status do_kernel ElseIf cmd = "status" Then WScript.Echo "ADPROTO: " & adproto do_status do_kernel ElseIf cmd = "upgrade" Then WScript.Echo WScript.Echo "** Sorry, apt-dater based upgrades on this host are disabled! **" WScript.Echo ElseIf cmd = "install" Then WScript.Echo WScript.Echo "** Sorry, apt-dater based upgrades on this host are disabled! **" WScript.Echo ElseIf cmd = "kernel" Then WScript.Echo "ADPROTO: " & adproto do_kernel Else WScript.Echo "IInvalid command " & cmd & "!" End If Sub do_status() If sh.ExpandEnvironmentStrings("%OS%") = "Windows_NT" Then regkey = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\" lsbrel = sh.regread(regkey & "ProductName") & "|" & sh.regread(regkey & "CurrentVersion") & "|" & sh.regread(regkey & "CurrentBuildNumber") Else regkey = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\" lsbrel = sh.regread(regkey & "ProductName") & "|" & sh.regread(regkey & "VersionNumber") & "|" End If WScript.Echo "LSBREL: " & lsbrel WScript.Echo "FORBID: 7" get_installed Set updateSession = CreateObject("Microsoft.Update.Session") Set updateSearcher = updateSession.CreateupdateSearcher() Set searchResult = updateSearcher.Search("IsInstalled=0 and Type='Software'") For I = 0 To searchResult.Updates.Count-1 Set update = searchResult.Updates.Item(I) WScript.Echo "STATUS: " & update.Title & "|n/i|u=n/a" Next End Sub Sub do_kernel() If sh.ExpandEnvironmentStrings("%OS%") = "Windows_NT" Then kernelinfo = sh.regread("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\BuildLab") Else kernelinfo = sh.regread("HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\BuildLab") End If Set updateSession = CreateObject("Microsoft.Update.Session") Set updateSearcher = updateSession.CreateupdateSearcher() Set searchResult = updateSearcher.Search("RebootRequired=1") If searchResult.Updates.Count > 0 then WScript.Echo "KERNELINFO: " & kernelinfo & " 1" Else WScript.Echo "KERNELINFO: " & kernelinfo & " 0" End If End Sub Sub get_installed() Const HKLM = &H80000002 'HKEY_LOCAL_MACHINE strComputer = "." strKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" strEntry1a = "DisplayName" strEntry1b = "QuietDisplayName" strEntry2 = "DisplayVersion" strEntry3 = "VersionMajor" strEntry4 = "VersionMinor" Set objReg = GetObject("winmgmts://" & strComputer & "/root/default:StdRegProv") objReg.EnumKey HKLM, strKey, arrSubkeys For Each strSubkey In arrSubkeys ret = objReg.GetStringValue(HKLM, strKey & strSubkey, strEntry1a, strProgName) If ret <> 0 Then objReg.GetStringValue HKLM, strKey & strSubkey, strEntry1b, strProgName End If If strProgName <> "" Then ret = objReg.GetStringValue(HKLM, strKey & strSubkey, strEntry2, strVersion) if ret <> 0 Then objReg.GetDWORDValue HKLM, strKey & strSubkey, strEntry3, intValue3 objReg.GetDWORDValue HKLM, strKey & strSubkey, strEntry4, intValue4 If intValue3 <> "" Then strVersion = intValue3 & "." & intValue4 Else strVersion = "n/a" End If End If WScript.Echo "STATUS: " & strProgName & "|" & strVersion & "|i" End If Next End Sub apt-dater-host-1.0.1/yum/000077500000000000000000000000001322523035200151545ustar00rootroot00000000000000apt-dater-host-1.0.1/yum/apt-dater-host000077500000000000000000000172001322523035200177360ustar00rootroot00000000000000#!/usr/bin/perl # apt-dater - terminal-based remote package update manager # # Authors: # Andre Ellguth # Thomas Liske # # Copyright Holder: # 2008-2014 (C) IBH IT-Service GmbH [http://www.ibh.de/apt-dater/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # use strict; use warnings; my $CFGFILE = '/etc/apt-dater-host.conf'; my $GETROOT = 'sudo'; my $CLEANUP = 0; my $FORBID_UPGRADE = 0; my $FORBID_INSTALL = 0; my $UUIDFILE = '/etc/apt-dater-host.uuid'; my @CLUSTERS; my $NEEDRESTART; my $RUNNEEDREST; my $YES_OPT = ""; my $ASSUMEYES; my $CMD = shift; my $ADPROTO = '0.7'; $ENV{'LC_ALL'} = 'C'; if (-r $CFGFILE) { eval `cat "$CFGFILE"` ; if($@ ne '') { print "ADPROTO: $ADPROTO\n"; print "ADPERR: Invalid config $CFGFILE: $@\n"; exit; } if($ASSUMEYES) { $YES_OPT = "-y"; # better use -y than --assumeyes since older centos/redhat # version do not know about --assumeyes but do now -y } } $GETROOT = '' if($> == 0); die "Don't call this script directly!\n" unless (defined($CMD)); if($CMD eq 'sshkey') { die "Sorry, no shell access allowed!\n" unless(defined($ENV{'SSH_ORIGINAL_COMMAND'})); @ARGV = split(' ', $ENV{'SSH_ORIGINAL_COMMAND'}); shift; $CMD = shift; } die "Invalid command '$CMD'!\n" unless ($CMD=~/^(refresh|status|upgrade|install|kernel)$/); if ($CMD eq 'refresh') { print "ADPROTO: $ADPROTO\n"; &do_status; &do_kernel; } elsif ($CMD eq 'status') { print "ADPROTO: $ADPROTO\n"; &do_status; &do_kernel; } elsif ($CMD eq 'upgrade') { if ($FORBID_UPGRADE) { print STDERR "\n\n** Sorry, apt-dater based upgrades on this host are disabled! **\n\n" } else { &do_upgrade; &do_cleanup; } } elsif ($CMD eq 'install') { if ($FORBID_INSTALL) { print STDERR "\n\n** Sorry, apt-dater based installations on this host are disabled! **\n\n" } else { &do_install(@ARGV); &do_cleanup; } } elsif ($CMD eq 'kernel') { print "ADPROTO: $ADPROTO\n"; &do_kernel; } else { die "Internal error!\n"; } sub call_yum { my $nofatal = ($_[0] && $_[0] eq "nofatal" && shift @_); open (my $fh, "-|", @_) or do { return if $nofatal; print "\nADPERR: Failed to execute '@_' ($!).\n"; exit(1); }; my $out = do { local $/; # slurp <$fh>; }; close $fh; if($?) { return if $nofatal; print "\nADPERR: Error executing '@_' ($?).\n"; exit(1); } $out =~ s/\n+(\s+)/$1/g; return split(/\n+/, $out); } sub get_virt() { return "Unknown" unless (-x '/usr/bin/imvirt'); my $imvirt; chomp($imvirt = `/usr/bin/imvirt`); return $imvirt; } sub get_uname() { my $kernel; my $machine; chomp($kernel = `uname -s`); chomp($machine = `uname -m`); return "$kernel|$machine"; } sub do_status() { # retrieve lsb informations unless(open(HLSB, "lsb_release -a 2> /dev/null |")) { print "\nADPERR: Failed to execute 'lsb_release -a' ($!).\n"; exit(1); }; my %lsb; while() { chomp; $lsb{$1}=$2 if (/^(Distributor ID|Release|Codename):\s+(\S.*)$/); } close(HLSB); if($?) { print "\nADPERR: Error executing 'lsb_release -a' ($?).\n"; exit(1); }; print "LSBREL: $lsb{'Distributor ID'}|$lsb{'Release'}|$lsb{'Codename'}\n"; # retrieve virtualization informations print "VIRT: ".&get_virt."\n"; # retrieve uname informations print "UNAME: ".&get_uname."\n"; # calculate forbid mask my $mask = 0; # $mask |= 1 if ($FORBID_REFRESH); NOT SUPPORTED $mask |= 2 if ($FORBID_UPGRADE); $mask |= 4 if ($FORBID_INSTALL); print "FORBID: $mask\n"; # add installation UUID if available if(-r $UUIDFILE && -s $UUIDFILE) { print "UUID: ", `head -n 1 "$UUIDFILE"`; } # add cluster name if available foreach my $CLUSTER (@CLUSTERS) { print "CLUSTER: $CLUSTER\n"; } # add needrestart batch output system(($GETROOT ? $GETROOT : ()), $NEEDRESTART, '-b') if($NEEDRESTART); # get packages which might be upgraded my %updates; foreach(call_yum("$GETROOT yum list updates")) { $updates{$1} = $2 if (/^(\S+)\s+(\d\S*)\s+(\S+)/); } # get packages which are obsolete (extra - no downloadable version available) my %extras; foreach(call_yum("$GETROOT yum list extras")) { $extras{$1} = $2 if (/^(\S+)\s+(\d\S*)\s+(\S+)/); } # get version of installed packages my %installed; my %status; foreach(call_yum("$GETROOT yum list installed")) { next unless (/^(\S+)\s+(\d\S*)\s+(\S+)/); $installed{$1} = $2 ; if($updates{$1}) { $status{$1} = 'u'; } elsif($extras{$1}) { $status{$1} = 'x'; } else { $status{$1} = 'i'; } } foreach my $pkg (keys %installed) { print "STATUS: $pkg|$installed{$pkg}|$status{$pkg}"; if (exists($updates{$pkg})) { print "=$updates{$pkg}" ; } print "\n"; } } sub do_upgrade() { system("$GETROOT yum $YES_OPT update"); } sub do_install() { if($GETROOT) { system($GETROOT, 'yum', 'install', @_); } else { system('yum', 'install', @_); } } sub do_kernel() { my $infostr = 'KERNELINFO:'; my $version = `uname -r`; chomp($version); my $add = ''; $add = "-$1" if($version =~ /([a-z]+)$/); my $pos = 0; my $kinstalled; my %distri; my @ret; if (!(@ret = call_yum('nofatal', "$GETROOT yum list 'kernel*'")) || $?) { print "$infostr 9 $version\n"; return; }; foreach(@ret) { if(/^Installed Packages/) { $pos = 1; next; } if(/^Available Packages/) { $pos = 2; next; } if(($pos == 1) && /^(\S+$add\.\S+)\s+(\d\S*)\s/) { my $ver = $2; $distri{$ver.substr($add,1)} = 1; if(!$kinstalled) { $kinstalled = $ver; } else { $kinstalled = $ver if(&versioncmp($kinstalled, $ver) < 0); } } } unless($distri{$version}) { print "$infostr 2 $version\n"; return; } unless($kinstalled.substr($add, 1) cmp $version) { print "$infostr 0 $version\n"; return; } print "$infostr 1 $version\n"; } ## # Taken from Sort::Versions 1.4 # Copyright (c) 1996, Kenneth J. Albanowski. ## sub versioncmp() { my @A = ($_[0] =~ /([-.]|\d+|[^-.\d]+)/g); my @B = ($_[1] =~ /([-.]|\d+|[^-.\d]+)/g); my ($A, $B); while (@A and @B) { $A = shift @A; $B = shift @B; if ($A eq '-' and $B eq '-') { next; } elsif ( $A eq '-' ) { return -1; } elsif ( $B eq '-') { return 1; } elsif ($A eq '.' and $B eq '.') { next; } elsif ( $A eq '.' ) { return -1; } elsif ( $B eq '.' ) { return 1; } elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/) { if ($A =~ /^0/ || $B =~ /^0/) { return $A cmp $B if $A cmp $B; } else { return $A <=> $B if $A <=> $B; } } else { $A = uc $A; $B = uc $B; return $A cmp $B if $A cmp $B; } } @A <=> @B; } sub do_cleanup() { system(($GETROOT ? $GETROOT : ()), $NEEDRESTART) if($RUNNEEDREST); return unless $CLEANUP; system("$GETROOT yum clean packages"); } apt-dater-host-1.0.1/yum/apt-dater-host.conf000066400000000000000000000021031322523035200206530ustar00rootroot00000000000000# use this command to become root $GETROOT="sudo"; # clean package cache after upgrade/install $CLEANUP=0; # the installation UUID $UUIDFILE = '/etc/apt-dater-host.uuid'; # If this host is part of (multiple) cluster(s), you might set a # symbolic name. Hosts with the same cluster name won't be upgraded # simultaneously by apt-dater (requires apt-dater 0.9 or above). #@CLUSTERS = qw(my-db-cluster); # Check if needrestart is available. This requires the needrestart # package to be installed. $NEEDRESTART = (-x '/usr/sbin/needrestart' ? '/usr/sbin/needrestart' : undef); # On apt-based systems needrestart should to be called by apt directly, # no need to run it in an interactive mode from within apt-dater-host. $RUNNEEDREST = $NEEDRESTART; ## ## If this host is a mission critical system and ## needs scheduled downtimes for upgrades, enable ## (some) of the following $FORBID_* lines: ## # prevent apt-dater-host from upgrading packages #$FORBID_UPGRADE=1; # prevent apt-dater-host from installing packages #$FORBID_INSTALL=1; # Acknowledge yes/no questions # $ASSUMEYES=1; apt-dater-host-1.0.1/zypper/000077500000000000000000000000001322523035200156735ustar00rootroot00000000000000apt-dater-host-1.0.1/zypper/apt-dater-host000077500000000000000000000165141322523035200204640ustar00rootroot00000000000000#!/usr/bin/perl # apt-dater - terminal-based remote package update manager # # Authors: # Andre Ellguth # Thomas Liske # # Copyright Holder: # 2008-2014 (C) IBH IT-Service GmbH [http://www.ibh.de/apt-dater/] # # License: # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this package; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # use strict; use warnings; my $CFGFILE = '/etc/apt-dater-host.conf'; my $GETROOT = 'sudo'; my $FORBID_REFRESH = 0; my $FORBID_UPGRADE = 0; my $FORBID_INSTALL = 0; my $UUIDFILE = '/etc/apt-dater-host.uuid'; my @CLUSTERS; my $NEEDRESTART; my $RUNNEEDREST; my $CMD = shift; my $ADPROTO = '0.7'; $ENV{'LC_ALL'} = 'C'; if (-r $CFGFILE) { eval `cat "$CFGFILE"` ; if($@ ne '') { print "ADPROTO: $ADPROTO\n"; print "ADPERR: Invalid config $CFGFILE: $@\n"; exit; } } $GETROOT = '' if($> == 0); die "Don't call this script directly!\n" unless (defined($CMD)); if($CMD eq 'sshkey') { die "Sorry, no shell access allowed!\n" unless(defined($ENV{'SSH_ORIGINAL_COMMAND'})); @ARGV = split(' ', $ENV{'SSH_ORIGINAL_COMMAND'}); shift; $CMD = shift; } die "Invalid command '$CMD'!\n" unless ($CMD=~/^(refresh|status|upgrade|install|kernel)$/); if ($CMD eq 'refresh') { print "ADPROTO: $ADPROTO\n"; if ($FORBID_REFRESH) { print STDERR "\n\n** Sorry, apt-dater based refreshs on this host are disabled! **\n\n" } else { &do_refresh; } &do_status; &do_kernel; } elsif ($CMD eq 'status') { print "ADPROTO: $ADPROTO\n"; &do_status; &do_kernel; } elsif ($CMD eq 'upgrade') { if ($FORBID_UPGRADE) { print STDERR "\n\n** Sorry, apt-dater based upgrades on this host are disabled! **\n\n" } else { &do_upgrade; system(($GETROOT ? $GETROOT : ()), $NEEDRESTART) if($RUNNEEDREST); } } elsif ($CMD eq 'install') { if ($FORBID_INSTALL) { print STDERR "\n\n** Sorry, apt-dater based installations on this host are disabled! **\n\n" } else { &do_install(@ARGV); system(($GETROOT ? $GETROOT : ()), $NEEDRESTART) if($RUNNEEDREST); } } elsif ($CMD eq 'kernel') { print "ADPROTO: $ADPROTO\n"; &do_kernel; } else { die "Internal error!\n"; } sub do_refresh() { if(system("$GETROOT zypper refresh")) { print "\nADPERR: Failed to execute '$GETROOT zypper refresh' ($?).\n"; exit(1); } } sub get_virt() { return "Unknown" unless (-x '/usr/bin/imvirt'); my $imvirt; chomp($imvirt = `/usr/bin/imvirt`); return $imvirt; } sub get_uname() { my $kernel; my $machine; chomp($kernel = `uname -s`); chomp($machine = `uname -m`); return "$kernel|$machine"; } sub do_status() { # retrieve lsb informations unless(open(HLSB, "lsb_release -a 2> /dev/null |")) { print "\nADPERR: Failed to execute 'lsb_release -a' ($!).\n"; exit(1); } my %lsb; while() { chomp; $lsb{$1}=$2 if (/^(Distributor ID|Release|Codename):\s+(\S.*)$/); } close(HLSB); if($?) { print "\nADPERR: Error executing 'lsb_release -a' ($?).\n"; exit(1); } print "LSBREL: $lsb{'Distributor ID'}|$lsb{'Release'}|$lsb{'Codename'}\n"; # retrieve virtualization informations print "VIRT: ".&get_virt."\n"; # retrieve uname informations print "UNAME: ".&get_uname."\n"; # calculate forbid mask my $mask = 0; $mask |= 1 if ($FORBID_REFRESH); $mask |= 2 if ($FORBID_UPGRADE); $mask |= 4 if ($FORBID_INSTALL); print "FORBID: $mask\n"; # add installation UUID if available if(-r $UUIDFILE && -s $UUIDFILE) { print "UUID: ", `head -n 1 "$UUIDFILE"`; } # add cluster name if available foreach my $CLUSTER (@CLUSTERS) { print "CLUSTER: $CLUSTER\n"; } # add needrestart batch output system(($GETROOT ? $GETROOT : ()), $NEEDRESTART, '-b') if($NEEDRESTART); # get packages which might be upgraded my %updates; unless(open(HAPT, "$GETROOT zypper --terse list-updates -a |")) { print "\nADPERR: Failed to execute '$GETROOT zypper --terse list-updates -a' ($!).\n"; exit(1); }; while() { chomp; my @line = split(/\s*\|\s*/); $updates{$line[2]} = $line[4] if($#line >= 4); } close(HAPT); if($?) { print "\nADPERR: Error executing '$GETROOT zypper --terse list-updates -a' ($?).\n"; exit(1); } # get version of installed packages my %installed; my %status; unless(open(HDPKG, "rpm -qa --qf '%{NAME}|%{VERSION}-%{RELEASE}|\n' |")) { print "\nADPERR: Failed to execute \"rpm -qa --qf '%{NAME}|%{VERSION}-%{RELEASE}|\\n'\" ($!).\n"; exit(1); }; while() { chomp; next unless (/^(\S+)\|\S+\|/); print "STATUS: "; print; if($updates{$1}) { print 'u=', $updates{$1}; } else { print 'i'; } print "\n"; } close(HDPKG); if($?) { print "\nADPERR: Error executing \"rpm -qa --qf '%{NAME}|%{VERSION}-%{RELEASE}|\\n'\" ($?).\n"; exit(1); }; } sub do_upgrade() { system("$GETROOT zypper -r update"); } sub do_install() { if($GETROOT) { system($GETROOT, 'zypper', '-r', 'install', @_); } else { system('rug', '-r', 'install', @_); } } sub do_kernel() { my $infostr = 'KERNELINFO:'; my $version = `uname -r`; chomp($version); my $add = ''; $add = $1 if($version =~ /(-[a-z]+)$/); my $pos = 0; my $kinstalled; my %distri; unless(open(HKERNEL, "rpm -q --whatprovides kernel --qf '%{NAME}|%{VERSION}-%{RELEASE}\n' |")) { print "$infostr 9 $version\n"; return; } while() { chomp; if(/^kernel$add\|(.+)/) { my $ver = $1; $distri{$ver.$add} = 1; if(!$kinstalled) { $kinstalled = $ver; } else { $kinstalled = $ver if(&versioncmp($kinstalled, $ver) < 0); } } } close(HKERNEL); if($?) { print "$infostr 9 $version\n"; return; } unless($distri{$version}) { print "$infostr 2 $version\n"; return; } unless($kinstalled.$add cmp $version) { print "$infostr 0 $version\n"; return; } print "$infostr 1 $version\n"; } ## # Taken from Sort::Versions 1.4 # Copyright (c) 1996, Kenneth J. Albanowski. ## sub versioncmp() { my @A = ($_[0] =~ /([-.]|\d+|[^-.\d]+)/g); my @B = ($_[1] =~ /([-.]|\d+|[^-.\d]+)/g); my ($A, $B); while (@A and @B) { $A = shift @A; $B = shift @B; if ($A eq '-' and $B eq '-') { next; } elsif ( $A eq '-' ) { return -1; } elsif ( $B eq '-') { return 1; } elsif ($A eq '.' and $B eq '.') { next; } elsif ( $A eq '.' ) { return -1; } elsif ( $B eq '.' ) { return 1; } elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/) { if ($A =~ /^0/ || $B =~ /^0/) { return $A cmp $B if $A cmp $B; } else { return $A <=> $B if $A <=> $B; } } else { $A = uc $A; $B = uc $B; return $A cmp $B if $A cmp $B; } } @A <=> @B; } apt-dater-host-1.0.1/zypper/apt-dater-host.conf000066400000000000000000000020461322523035200214000ustar00rootroot00000000000000# use this command to become root $GETROOT="sudo"; # the installation UUID $UUIDFILE = '/etc/apt-dater-host.uuid'; # If this host is part of (multiple) cluster(s), you might set a # symbolic name. Hosts with the same cluster name won't be upgraded # simultaneously by apt-dater (requires apt-dater 0.9 or above). #@CLUSTERS = qw(my-db-cluster); # Check if needrestart is available. This requires the needrestart # package to be installed. $NEEDRESTART = (-x '/usr/sbin/needrestart' ? '/usr/sbin/needrestart' : undef); # On apt-based systems needrestart should to be called by apt directly, # no need to run it in an interactive mode from within apt-dater-host. $RUNNEEDREST = $NEEDRESTART; ## ## If this host is a mission critical system and ## needs scheduled downtimes for upgrades, enable ## (some) of the following $FORBID_* lines: ## # prevent apt-dater-host from refreshing package lists #$FORBID_REFRESH=1; # prevent apt-dater-host from upgrading packages #$FORBID_UPGRADE=1; # prevent apt-dater-host from installing packages #$FORBID_INSTALL=1;