pax_global_header00006660000000000000000000000064124106307740014516gustar00rootroot0000000000000052 comment=1d1387ce0afd18d8a9498ed99f58f29b3b7a6652 apt-dater-host-1.0.0/000077500000000000000000000000001241063077400143505ustar00rootroot00000000000000apt-dater-host-1.0.0/ChangeLog000066400000000000000000000057051241063077400161310ustar00rootroot00000000000000apt-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.0/README000066400000000000000000000011261241063077400152300ustar00rootroot00000000000000README for apt-dater-host ========================= Setup hosts managed by apt-dater: You need a SSH server and sudo installed. Create a user which will be used to install updates (using root is NOT recommended). Modify the /etc/sudoers: Defaults env_reset,env_keep=MAINTAINER the-user ALL=NOPASSWD: /usr/bin/apt-get, /usr/bin/aptitude At your management server: Create a user on your management server which perform updates on your hosts. Generate a SSH keypair: ssh-keygen [..] Distribute the public key(s) e.g.: ssh-copy-id -i ~/.ssh/your-public-key managed-host apt-dater-host-1.0.0/doc/000077500000000000000000000000001241063077400151155ustar00rootroot00000000000000apt-dater-host-1.0.0/doc/ADP-0.1000066400000000000000000000060401241063077400157400ustar00rootroot00000000000000apt-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.0/doc/ADP-0.2000066400000000000000000000076421241063077400157520ustar00rootroot00000000000000apt-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.0/doc/ADP-0.3000066400000000000000000000102661241063077400157470ustar00rootroot00000000000000apt-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.0/doc/ADP-0.4000066400000000000000000000107211241063077400157440ustar00rootroot00000000000000apt-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.0/doc/ADP-0.5000066400000000000000000000112721241063077400157470ustar00rootroot00000000000000apt-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.0/doc/ADP-0.6000066400000000000000000000130621241063077400157470ustar00rootroot00000000000000apt-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.0/doc/ADP-0.7000066400000000000000000000154421241063077400157540ustar00rootroot00000000000000apt-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.0/doc/README.sshkey000066400000000000000000000004441241063077400173040ustar00rootroot00000000000000Bind 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.0/dpkg/000077500000000000000000000000001241063077400152755ustar00rootroot00000000000000apt-dater-host-1.0.0/dpkg/Makefile000066400000000000000000000010031241063077400167270ustar00rootroot00000000000000clean: 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.0/dpkg/apt-dater-host000077500000000000000000000227061241063077400200660ustar00rootroot00000000000000#!/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 |")) { 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.0/dpkg/apt-dater-host.conf000066400000000000000000000027521241063077400210060ustar00rootroot00000000000000# 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.0/dpkg/scripts/000077500000000000000000000000001241063077400167645ustar00rootroot00000000000000apt-dater-host-1.0.0/dpkg/scripts/99apt-dater-host_periodic000066400000000000000000000002011241063077400235740ustar00rootroot00000000000000APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Download-Upgradeable-Packages "1"; APT::Periodic::AutocleanInterval "7"; apt-dater-host-1.0.0/dpkg/scripts/apt-dater-host000066400000000000000000000005521241063077400215450ustar00rootroot00000000000000# 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.0/dpkg/scripts/apt-dater-host_reboot000077500000000000000000000000601241063077400231140ustar00rootroot00000000000000#!/bin/sh touch /var/run/apt-dater-host_reboot apt-dater-host-1.0.0/man/000077500000000000000000000000001241063077400151235ustar00rootroot00000000000000apt-dater-host-1.0.0/man/apt-dater-host.1000066400000000000000000000012261241063077400200420ustar00rootroot00000000000000.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.0/rpm/000077500000000000000000000000001241063077400151465ustar00rootroot00000000000000apt-dater-host-1.0.0/rpm/apt-dater-host000077500000000000000000000127171241063077400177400ustar00rootroot00000000000000#!/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.0/rug/000077500000000000000000000000001241063077400151455ustar00rootroot00000000000000apt-dater-host-1.0.0/rug/apt-dater-host000077500000000000000000000157261241063077400177420ustar00rootroot00000000000000#!/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.0/rug/apt-dater-host.conf000066400000000000000000000017321241063077400206530ustar00rootroot00000000000000# 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.0/wua/000077500000000000000000000000001241063077400151445ustar00rootroot00000000000000apt-dater-host-1.0.0/wua/README.wua000066400000000000000000000024171241063077400166230ustar00rootroot00000000000000apt-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.0/wua/apt-dater-host.cmd000077500000000000000000000000711241063077400204660ustar00rootroot00000000000000@echo off cscript cscript-apt-dater-host.vbs //Nologo %*apt-dater-host-1.0.0/wua/cscript-apt-dater-host.vbs000077500000000000000000000112661241063077400221720ustar00rootroot00000000000000'~ 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.0/yum/000077500000000000000000000000001241063077400151625ustar00rootroot00000000000000apt-dater-host-1.0.0/yum/apt-dater-host000077500000000000000000000166631241063077400177600ustar00rootroot00000000000000#!/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 $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; &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 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.0/yum/apt-dater-host.conf000066400000000000000000000020231241063077400206620ustar00rootroot00000000000000# 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; apt-dater-host-1.0.0/zypper/000077500000000000000000000000001241063077400157015ustar00rootroot00000000000000apt-dater-host-1.0.0/zypper/apt-dater-host000077500000000000000000000165141241063077400204720ustar00rootroot00000000000000#!/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.0/zypper/apt-dater-host.conf000066400000000000000000000020461241063077400214060ustar00rootroot00000000000000# 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;