From beb7cfbba437440811adb1b40a7882b15888b341 Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Tue, 16 Jul 2013 09:54:32 +0200 Subject: Add SysV init scripts for Debian --- sysvinit/debian/cloud-config | 52 ++++++++++++++++++++++++++++++++++++++ sysvinit/debian/cloud-final | 54 ++++++++++++++++++++++++++++++++++++++++ sysvinit/debian/cloud-init | 52 ++++++++++++++++++++++++++++++++++++++ sysvinit/debian/cloud-init-local | 52 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 210 insertions(+) create mode 100755 sysvinit/debian/cloud-config create mode 100755 sysvinit/debian/cloud-final create mode 100755 sysvinit/debian/cloud-init create mode 100755 sysvinit/debian/cloud-init-local diff --git a/sysvinit/debian/cloud-config b/sysvinit/debian/cloud-config new file mode 100755 index 00000000..57888653 --- /dev/null +++ b/sysvinit/debian/cloud-config @@ -0,0 +1,52 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: cloud-config +# Required-Start: cloud-init cloud-init-local +# Required-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Cloud init modules --mode config +# Description: Cloud configuration initialization +### END INIT INFO + +# Authors: Julien Danjou +# Juerg Haefliger + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="Cloud service" +NAME=cloud-init +DAEMON=/usr/bin/$NAME +DAEMON_ARGS="modules --mode config" +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +case "$1" in +start) + log_daemon_msg "Starting $DESC" "$NAME" + $DAEMON ${DAEMON_ARGS} + case "$?" in + 0|1) log_end_msg 0 ;; + 2) log_end_msg 1 ;; + esac +;; +stop|restart|force-reload) + echo "Error: argument '$1' not supported" >&2 + exit 3 +;; +*) + echo "Usage: $SCRIPTNAME {start}" >&2 + exit 3 +;; +esac + +: diff --git a/sysvinit/debian/cloud-final b/sysvinit/debian/cloud-final new file mode 100755 index 00000000..46e9b454 --- /dev/null +++ b/sysvinit/debian/cloud-final @@ -0,0 +1,54 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: cloud-final +# Required-Start: $all cloud-config +# Required-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Cloud init modules final jobs +# Description: This runs the cloud configuration initialization "final" jobs +# and can be seen as the traditional "rc.local" time for the cloud. +# It runs after all cloud-config jobs are run +### END INIT INFO + +# Authors: Julien Danjou +# Juerg Haefliger + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="Cloud service" +NAME=cloud-init +DAEMON=/usr/bin/$NAME +DAEMON_ARGS="modules --mode final" +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +case "$1" in +start) + log_daemon_msg "Starting $DESC" "$NAME" + $DAEMON ${DAEMON_ARGS} + case "$?" in + 0|1) log_end_msg 0 ;; + 2) log_end_msg 1 ;; + esac +;; +stop|restart|force-reload) + echo "Error: argument '$1' not supported" >&2 + exit 3 +;; +*) + echo "Usage: $SCRIPTNAME {start}" >&2 + exit 3 +;; +esac + +: diff --git a/sysvinit/debian/cloud-init b/sysvinit/debian/cloud-init new file mode 100755 index 00000000..15ffeb2e --- /dev/null +++ b/sysvinit/debian/cloud-init @@ -0,0 +1,52 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: cloud-init +# Required-Start: $local_fs $remote_fs $syslog $network cloud-init-local +# Required-Stop: $remote_fs +# X-Start-Before: sshd +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Cloud init +# Description: Cloud configuration initialization +### END INIT INFO + +# Author: Julien Danjou + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="Cloud service" +NAME=cloud-init +DAEMON=/usr/bin/$NAME +DAEMON_ARGS="init" +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +case "$1" in + start) + log_daemon_msg "Starting $DESC" "$NAME" + $DAEMON ${DAEMON_ARGS} + case "$?" in + 0|1) log_end_msg 0 ;; + 2) log_end_msg 1 ;; + esac + ;; + stop|restart|force-reload) + echo "Error: argument '$1' not supported" >&2 + exit 3 + ;; + *) + echo "Usage: $SCRIPTNAME {start}" >&2 + exit 3 + ;; +esac + +: diff --git a/sysvinit/debian/cloud-init-local b/sysvinit/debian/cloud-init-local new file mode 100755 index 00000000..a1685c1e --- /dev/null +++ b/sysvinit/debian/cloud-init-local @@ -0,0 +1,52 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: cloud-init-local +# Required-Start: $local_fs $remote_fs +# Required-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Cloud init local +# Description: Cloud configuration initialization +### END INIT INFO + +# Authors: Julien Danjou +# Juerg Haefliger + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="Cloud service" +NAME=cloud-init +DAEMON=/usr/bin/$NAME +DAEMON_ARGS="init --local" +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +case "$1" in +start) + log_daemon_msg "Starting $DESC" "$NAME" + $DAEMON ${DAEMON_ARGS} + case "$?" in + 0|1) log_end_msg 0 ;; + 2) log_end_msg 1 ;; + esac +;; +stop|restart|force-reload) + echo "Error: argument '$1' not supported" >&2 + exit 3 +;; +*) + echo "Usage: $SCRIPTNAME {start}" >&2 + exit 3 +;; +esac + +: -- cgit v1.2.3 From 198206b67f18f0f51bf057d76cee8b3a3526c8eb Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Fri, 19 Jul 2013 09:23:53 +0200 Subject: move redhat sysvinit scripts --- setup.py | 4 +- sysvinit/cloud-config | 121 --------------------------------------- sysvinit/cloud-final | 121 --------------------------------------- sysvinit/cloud-init | 121 --------------------------------------- sysvinit/cloud-init-local | 121 --------------------------------------- sysvinit/redhat/cloud-config | 121 +++++++++++++++++++++++++++++++++++++++ sysvinit/redhat/cloud-final | 121 +++++++++++++++++++++++++++++++++++++++ sysvinit/redhat/cloud-init | 121 +++++++++++++++++++++++++++++++++++++++ sysvinit/redhat/cloud-init-local | 121 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 486 insertions(+), 486 deletions(-) delete mode 100755 sysvinit/cloud-config delete mode 100755 sysvinit/cloud-final delete mode 100755 sysvinit/cloud-init delete mode 100755 sysvinit/cloud-init-local create mode 100755 sysvinit/redhat/cloud-config create mode 100755 sysvinit/redhat/cloud-final create mode 100755 sysvinit/redhat/cloud-init create mode 100755 sysvinit/redhat/cloud-init-local diff --git a/setup.py b/setup.py index 4aa1a47c..8d18b97e 100755 --- a/setup.py +++ b/setup.py @@ -37,8 +37,8 @@ def is_f(p): INITSYS_FILES = { - 'sysvinit': [f for f in glob('sysvinit/*') if is_f(f)], - 'sysvinit_deb': [f for f in glob('sysvinit/*') if is_f(f)], + 'sysvinit': [f for f in glob('sysvinit/redhat/*') if is_f(f)], + 'sysvinit_deb': [f for f in glob('sysvinit/debian/*') if is_f(f)], 'systemd': [f for f in glob('systemd/*') if is_f(f)], 'upstart': [f for f in glob('upstart/*') if is_f(f)], } diff --git a/sysvinit/cloud-config b/sysvinit/cloud-config deleted file mode 100755 index ad8ed831..00000000 --- a/sysvinit/cloud-config +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/sh - -# -# Copyright (C) 2012 Yahoo! Inc. -# -# Author: Joshua Harlow -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# 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 program. If not, see . -# - -# See: http://wiki.debian.org/LSBInitScripts -# See: http://tiny.cc/czvbgw -# See: http://www.novell.com/coolsolutions/feature/15380.html -# Also based on dhcpd in RHEL (for comparison) - -### BEGIN INIT INFO -# Provides: cloud-config -# Required-Start: cloud-init cloud-init-local -# Should-Start: $time -# Required-Stop: -# Should-Stop: -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: The config cloud-init job -# Description: Start cloud-init and runs the config phase -# and any associated config modules as desired. -### END INIT INFO - -# Return values acc. to LSB for all commands but status: -# 0 - success -# 1 - generic or unspecified error -# 2 - invalid or excess argument(s) -# 3 - unimplemented feature (e.g. "reload") -# 4 - user had insufficient privileges -# 5 - program is not installed -# 6 - program is not configured -# 7 - program is not running -# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) -# -# Note that starting an already running service, stopping -# or restarting a not-running service as well as the restart -# with force-reload (in case signaling is not supported) are -# considered a success. - -RETVAL=0 - -prog="cloud-init" -cloud_init="/usr/bin/cloud-init" -conf="/etc/cloud/cloud.cfg" - -# If there exist sysconfig/default variable override files use it... -[ -f /etc/sysconfig/cloud-init ] && . /etc/sysconfig/cloud-init -[ -f /etc/default/cloud-init ] && . /etc/default/cloud-init - -start() { - [ -x $cloud_init ] || return 5 - [ -f $conf ] || return 6 - - echo -n $"Starting $prog: " - $cloud_init $CLOUDINITARGS modules --mode config - RETVAL=$? - return $RETVAL -} - -stop() { - echo -n $"Shutting down $prog: " - # No-op - RETVAL=7 - return $RETVAL -} - -case "$1" in - start) - start - RETVAL=$? - ;; - stop) - stop - RETVAL=$? - ;; - restart|try-restart|condrestart) - ## Stop the service and regardless of whether it was - ## running or not, start it again. - # - ## Note: try-restart is now part of LSB (as of 1.9). - ## RH has a similar command named condrestart. - start - RETVAL=$? - ;; - reload|force-reload) - # It does not support reload - RETVAL=3 - ;; - status) - echo -n $"Checking for service $prog:" - # Return value is slightly different for the status command: - # 0 - service up and running - # 1 - service dead, but /var/run/ pid file exists - # 2 - service dead, but /var/lock/ lock file exists - # 3 - service not running (unused) - # 4 - service status unknown :-( - # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) - RETVAL=3 - ;; - *) - echo "Usage: $0 {start|stop|status|try-restart|condrestart|restart|force-reload|reload}" - RETVAL=3 - ;; -esac - -exit $RETVAL diff --git a/sysvinit/cloud-final b/sysvinit/cloud-final deleted file mode 100755 index aeae8903..00000000 --- a/sysvinit/cloud-final +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/sh - -# -# Copyright (C) 2012 Yahoo! Inc. -# -# Author: Joshua Harlow -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# 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 program. If not, see . -# - -# See: http://wiki.debian.org/LSBInitScripts -# See: http://tiny.cc/czvbgw -# See: http://www.novell.com/coolsolutions/feature/15380.html -# Also based on dhcpd in RHEL (for comparison) - -### BEGIN INIT INFO -# Provides: cloud-final -# Required-Start: $all cloud-config -# Should-Start: $time -# Required-Stop: -# Should-Stop: -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: The final cloud-init job -# Description: Start cloud-init and runs the final phase -# and any associated final modules as desired. -### END INIT INFO - -# Return values acc. to LSB for all commands but status: -# 0 - success -# 1 - generic or unspecified error -# 2 - invalid or excess argument(s) -# 3 - unimplemented feature (e.g. "reload") -# 4 - user had insufficient privileges -# 5 - program is not installed -# 6 - program is not configured -# 7 - program is not running -# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) -# -# Note that starting an already running service, stopping -# or restarting a not-running service as well as the restart -# with force-reload (in case signaling is not supported) are -# considered a success. - -RETVAL=0 - -prog="cloud-init" -cloud_init="/usr/bin/cloud-init" -conf="/etc/cloud/cloud.cfg" - -# If there exist sysconfig/default variable override files use it... -[ -f /etc/sysconfig/cloud-init ] && . /etc/sysconfig/cloud-init -[ -f /etc/default/cloud-init ] && . /etc/default/cloud-init - -start() { - [ -x $cloud_init ] || return 5 - [ -f $conf ] || return 6 - - echo -n $"Starting $prog: " - $cloud_init $CLOUDINITARGS modules --mode final - RETVAL=$? - return $RETVAL -} - -stop() { - echo -n $"Shutting down $prog: " - # No-op - RETVAL=7 - return $RETVAL -} - -case "$1" in - start) - start - RETVAL=$? - ;; - stop) - stop - RETVAL=$? - ;; - restart|try-restart|condrestart) - ## Stop the service and regardless of whether it was - ## running or not, start it again. - # - ## Note: try-restart is now part of LSB (as of 1.9). - ## RH has a similar command named condrestart. - start - RETVAL=$? - ;; - reload|force-reload) - # It does not support reload - RETVAL=3 - ;; - status) - echo -n $"Checking for service $prog:" - # Return value is slightly different for the status command: - # 0 - service up and running - # 1 - service dead, but /var/run/ pid file exists - # 2 - service dead, but /var/lock/ lock file exists - # 3 - service not running (unused) - # 4 - service status unknown :-( - # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) - RETVAL=3 - ;; - *) - echo "Usage: $0 {start|stop|status|try-restart|condrestart|restart|force-reload|reload}" - RETVAL=3 - ;; -esac - -exit $RETVAL diff --git a/sysvinit/cloud-init b/sysvinit/cloud-init deleted file mode 100755 index c1c92ad0..00000000 --- a/sysvinit/cloud-init +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/sh - -# -# Copyright (C) 2012 Yahoo! Inc. -# -# Author: Joshua Harlow -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# 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 program. If not, see . -# - -# See: http://wiki.debian.org/LSBInitScripts -# See: http://tiny.cc/czvbgw -# See: http://www.novell.com/coolsolutions/feature/15380.html -# Also based on dhcpd in RHEL (for comparison) - -### BEGIN INIT INFO -# Provides: cloud-init -# Required-Start: $local_fs $network $named $remote_fs cloud-init-local -# Should-Start: $time -# Required-Stop: -# Should-Stop: -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: The initial cloud-init job (net and fs contingent) -# Description: Start cloud-init and runs the initialization phase -# and any associated initial modules as desired. -### END INIT INFO - -# Return values acc. to LSB for all commands but status: -# 0 - success -# 1 - generic or unspecified error -# 2 - invalid or excess argument(s) -# 3 - unimplemented feature (e.g. "reload") -# 4 - user had insufficient privileges -# 5 - program is not installed -# 6 - program is not configured -# 7 - program is not running -# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) -# -# Note that starting an already running service, stopping -# or restarting a not-running service as well as the restart -# with force-reload (in case signaling is not supported) are -# considered a success. - -RETVAL=0 - -prog="cloud-init" -cloud_init="/usr/bin/cloud-init" -conf="/etc/cloud/cloud.cfg" - -# If there exist sysconfig/default variable override files use it... -[ -f /etc/sysconfig/cloud-init ] && . /etc/sysconfig/cloud-init -[ -f /etc/default/cloud-init ] && . /etc/default/cloud-init - -start() { - [ -x $cloud_init ] || return 5 - [ -f $conf ] || return 6 - - echo -n $"Starting $prog: " - $cloud_init $CLOUDINITARGS init - RETVAL=$? - return $RETVAL -} - -stop() { - echo -n $"Shutting down $prog: " - # No-op - RETVAL=7 - return $RETVAL -} - -case "$1" in - start) - start - RETVAL=$? - ;; - stop) - stop - RETVAL=$? - ;; - restart|try-restart|condrestart) - ## Stop the service and regardless of whether it was - ## running or not, start it again. - # - ## Note: try-restart is now part of LSB (as of 1.9). - ## RH has a similar command named condrestart. - start - RETVAL=$? - ;; - reload|force-reload) - # It does not support reload - RETVAL=3 - ;; - status) - echo -n $"Checking for service $prog:" - # Return value is slightly different for the status command: - # 0 - service up and running - # 1 - service dead, but /var/run/ pid file exists - # 2 - service dead, but /var/lock/ lock file exists - # 3 - service not running (unused) - # 4 - service status unknown :-( - # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) - RETVAL=3 - ;; - *) - echo "Usage: $0 {start|stop|status|try-restart|condrestart|restart|force-reload|reload}" - RETVAL=3 - ;; -esac - -exit $RETVAL diff --git a/sysvinit/cloud-init-local b/sysvinit/cloud-init-local deleted file mode 100755 index b53e0db2..00000000 --- a/sysvinit/cloud-init-local +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/sh - -# -# Copyright (C) 2012 Yahoo! Inc. -# -# Author: Joshua Harlow -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# 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 program. If not, see . -# - -# See: http://wiki.debian.org/LSBInitScripts -# See: http://tiny.cc/czvbgw -# See: http://www.novell.com/coolsolutions/feature/15380.html -# Also based on dhcpd in RHEL (for comparison) - -### BEGIN INIT INFO -# Provides: cloud-init-local -# Required-Start: $local_fs $remote_fs -# Should-Start: $time -# Required-Stop: -# Should-Stop: -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: The initial cloud-init job (local fs contingent) -# Description: Start cloud-init and runs the initialization phases -# and any associated initial modules as desired. -### END INIT INFO - -# Return values acc. to LSB for all commands but status: -# 0 - success -# 1 - generic or unspecified error -# 2 - invalid or excess argument(s) -# 3 - unimplemented feature (e.g. "reload") -# 4 - user had insufficient privileges -# 5 - program is not installed -# 6 - program is not configured -# 7 - program is not running -# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) -# -# Note that starting an already running service, stopping -# or restarting a not-running service as well as the restart -# with force-reload (in case signaling is not supported) are -# considered a success. - -RETVAL=0 - -prog="cloud-init" -cloud_init="/usr/bin/cloud-init" -conf="/etc/cloud/cloud.cfg" - -# If there exist sysconfig/default variable override files use it... -[ -f /etc/sysconfig/cloud-init ] && . /etc/sysconfig/cloud-init -[ -f /etc/default/cloud-init ] && . /etc/default/cloud-init - -start() { - [ -x $cloud_init ] || return 5 - [ -f $conf ] || return 6 - - echo -n $"Starting $prog: " - $cloud_init $CLOUDINITARGS init --local - RETVAL=$? - return $RETVAL -} - -stop() { - echo -n $"Shutting down $prog: " - # No-op - RETVAL=7 - return $RETVAL -} - -case "$1" in - start) - start - RETVAL=$? - ;; - stop) - stop - RETVAL=$? - ;; - restart|try-restart|condrestart) - ## Stop the service and regardless of whether it was - ## running or not, start it again. - # - ## Note: try-restart is now part of LSB (as of 1.9). - ## RH has a similar command named condrestart. - start - RETVAL=$? - ;; - reload|force-reload) - # It does not support reload - RETVAL=3 - ;; - status) - echo -n $"Checking for service $prog:" - # Return value is slightly different for the status command: - # 0 - service up and running - # 1 - service dead, but /var/run/ pid file exists - # 2 - service dead, but /var/lock/ lock file exists - # 3 - service not running (unused) - # 4 - service status unknown :-( - # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) - RETVAL=3 - ;; - *) - echo "Usage: $0 {start|stop|status|try-restart|condrestart|restart|force-reload|reload}" - RETVAL=3 - ;; -esac - -exit $RETVAL diff --git a/sysvinit/redhat/cloud-config b/sysvinit/redhat/cloud-config new file mode 100755 index 00000000..ad8ed831 --- /dev/null +++ b/sysvinit/redhat/cloud-config @@ -0,0 +1,121 @@ +#!/bin/sh + +# +# Copyright (C) 2012 Yahoo! Inc. +# +# Author: Joshua Harlow +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, as +# published by the Free Software Foundation. +# +# 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 program. If not, see . +# + +# See: http://wiki.debian.org/LSBInitScripts +# See: http://tiny.cc/czvbgw +# See: http://www.novell.com/coolsolutions/feature/15380.html +# Also based on dhcpd in RHEL (for comparison) + +### BEGIN INIT INFO +# Provides: cloud-config +# Required-Start: cloud-init cloud-init-local +# Should-Start: $time +# Required-Stop: +# Should-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: The config cloud-init job +# Description: Start cloud-init and runs the config phase +# and any associated config modules as desired. +### END INIT INFO + +# Return values acc. to LSB for all commands but status: +# 0 - success +# 1 - generic or unspecified error +# 2 - invalid or excess argument(s) +# 3 - unimplemented feature (e.g. "reload") +# 4 - user had insufficient privileges +# 5 - program is not installed +# 6 - program is not configured +# 7 - program is not running +# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) +# +# Note that starting an already running service, stopping +# or restarting a not-running service as well as the restart +# with force-reload (in case signaling is not supported) are +# considered a success. + +RETVAL=0 + +prog="cloud-init" +cloud_init="/usr/bin/cloud-init" +conf="/etc/cloud/cloud.cfg" + +# If there exist sysconfig/default variable override files use it... +[ -f /etc/sysconfig/cloud-init ] && . /etc/sysconfig/cloud-init +[ -f /etc/default/cloud-init ] && . /etc/default/cloud-init + +start() { + [ -x $cloud_init ] || return 5 + [ -f $conf ] || return 6 + + echo -n $"Starting $prog: " + $cloud_init $CLOUDINITARGS modules --mode config + RETVAL=$? + return $RETVAL +} + +stop() { + echo -n $"Shutting down $prog: " + # No-op + RETVAL=7 + return $RETVAL +} + +case "$1" in + start) + start + RETVAL=$? + ;; + stop) + stop + RETVAL=$? + ;; + restart|try-restart|condrestart) + ## Stop the service and regardless of whether it was + ## running or not, start it again. + # + ## Note: try-restart is now part of LSB (as of 1.9). + ## RH has a similar command named condrestart. + start + RETVAL=$? + ;; + reload|force-reload) + # It does not support reload + RETVAL=3 + ;; + status) + echo -n $"Checking for service $prog:" + # Return value is slightly different for the status command: + # 0 - service up and running + # 1 - service dead, but /var/run/ pid file exists + # 2 - service dead, but /var/lock/ lock file exists + # 3 - service not running (unused) + # 4 - service status unknown :-( + # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) + RETVAL=3 + ;; + *) + echo "Usage: $0 {start|stop|status|try-restart|condrestart|restart|force-reload|reload}" + RETVAL=3 + ;; +esac + +exit $RETVAL diff --git a/sysvinit/redhat/cloud-final b/sysvinit/redhat/cloud-final new file mode 100755 index 00000000..aeae8903 --- /dev/null +++ b/sysvinit/redhat/cloud-final @@ -0,0 +1,121 @@ +#!/bin/sh + +# +# Copyright (C) 2012 Yahoo! Inc. +# +# Author: Joshua Harlow +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, as +# published by the Free Software Foundation. +# +# 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 program. If not, see . +# + +# See: http://wiki.debian.org/LSBInitScripts +# See: http://tiny.cc/czvbgw +# See: http://www.novell.com/coolsolutions/feature/15380.html +# Also based on dhcpd in RHEL (for comparison) + +### BEGIN INIT INFO +# Provides: cloud-final +# Required-Start: $all cloud-config +# Should-Start: $time +# Required-Stop: +# Should-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: The final cloud-init job +# Description: Start cloud-init and runs the final phase +# and any associated final modules as desired. +### END INIT INFO + +# Return values acc. to LSB for all commands but status: +# 0 - success +# 1 - generic or unspecified error +# 2 - invalid or excess argument(s) +# 3 - unimplemented feature (e.g. "reload") +# 4 - user had insufficient privileges +# 5 - program is not installed +# 6 - program is not configured +# 7 - program is not running +# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) +# +# Note that starting an already running service, stopping +# or restarting a not-running service as well as the restart +# with force-reload (in case signaling is not supported) are +# considered a success. + +RETVAL=0 + +prog="cloud-init" +cloud_init="/usr/bin/cloud-init" +conf="/etc/cloud/cloud.cfg" + +# If there exist sysconfig/default variable override files use it... +[ -f /etc/sysconfig/cloud-init ] && . /etc/sysconfig/cloud-init +[ -f /etc/default/cloud-init ] && . /etc/default/cloud-init + +start() { + [ -x $cloud_init ] || return 5 + [ -f $conf ] || return 6 + + echo -n $"Starting $prog: " + $cloud_init $CLOUDINITARGS modules --mode final + RETVAL=$? + return $RETVAL +} + +stop() { + echo -n $"Shutting down $prog: " + # No-op + RETVAL=7 + return $RETVAL +} + +case "$1" in + start) + start + RETVAL=$? + ;; + stop) + stop + RETVAL=$? + ;; + restart|try-restart|condrestart) + ## Stop the service and regardless of whether it was + ## running or not, start it again. + # + ## Note: try-restart is now part of LSB (as of 1.9). + ## RH has a similar command named condrestart. + start + RETVAL=$? + ;; + reload|force-reload) + # It does not support reload + RETVAL=3 + ;; + status) + echo -n $"Checking for service $prog:" + # Return value is slightly different for the status command: + # 0 - service up and running + # 1 - service dead, but /var/run/ pid file exists + # 2 - service dead, but /var/lock/ lock file exists + # 3 - service not running (unused) + # 4 - service status unknown :-( + # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) + RETVAL=3 + ;; + *) + echo "Usage: $0 {start|stop|status|try-restart|condrestart|restart|force-reload|reload}" + RETVAL=3 + ;; +esac + +exit $RETVAL diff --git a/sysvinit/redhat/cloud-init b/sysvinit/redhat/cloud-init new file mode 100755 index 00000000..c1c92ad0 --- /dev/null +++ b/sysvinit/redhat/cloud-init @@ -0,0 +1,121 @@ +#!/bin/sh + +# +# Copyright (C) 2012 Yahoo! Inc. +# +# Author: Joshua Harlow +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, as +# published by the Free Software Foundation. +# +# 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 program. If not, see . +# + +# See: http://wiki.debian.org/LSBInitScripts +# See: http://tiny.cc/czvbgw +# See: http://www.novell.com/coolsolutions/feature/15380.html +# Also based on dhcpd in RHEL (for comparison) + +### BEGIN INIT INFO +# Provides: cloud-init +# Required-Start: $local_fs $network $named $remote_fs cloud-init-local +# Should-Start: $time +# Required-Stop: +# Should-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: The initial cloud-init job (net and fs contingent) +# Description: Start cloud-init and runs the initialization phase +# and any associated initial modules as desired. +### END INIT INFO + +# Return values acc. to LSB for all commands but status: +# 0 - success +# 1 - generic or unspecified error +# 2 - invalid or excess argument(s) +# 3 - unimplemented feature (e.g. "reload") +# 4 - user had insufficient privileges +# 5 - program is not installed +# 6 - program is not configured +# 7 - program is not running +# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) +# +# Note that starting an already running service, stopping +# or restarting a not-running service as well as the restart +# with force-reload (in case signaling is not supported) are +# considered a success. + +RETVAL=0 + +prog="cloud-init" +cloud_init="/usr/bin/cloud-init" +conf="/etc/cloud/cloud.cfg" + +# If there exist sysconfig/default variable override files use it... +[ -f /etc/sysconfig/cloud-init ] && . /etc/sysconfig/cloud-init +[ -f /etc/default/cloud-init ] && . /etc/default/cloud-init + +start() { + [ -x $cloud_init ] || return 5 + [ -f $conf ] || return 6 + + echo -n $"Starting $prog: " + $cloud_init $CLOUDINITARGS init + RETVAL=$? + return $RETVAL +} + +stop() { + echo -n $"Shutting down $prog: " + # No-op + RETVAL=7 + return $RETVAL +} + +case "$1" in + start) + start + RETVAL=$? + ;; + stop) + stop + RETVAL=$? + ;; + restart|try-restart|condrestart) + ## Stop the service and regardless of whether it was + ## running or not, start it again. + # + ## Note: try-restart is now part of LSB (as of 1.9). + ## RH has a similar command named condrestart. + start + RETVAL=$? + ;; + reload|force-reload) + # It does not support reload + RETVAL=3 + ;; + status) + echo -n $"Checking for service $prog:" + # Return value is slightly different for the status command: + # 0 - service up and running + # 1 - service dead, but /var/run/ pid file exists + # 2 - service dead, but /var/lock/ lock file exists + # 3 - service not running (unused) + # 4 - service status unknown :-( + # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) + RETVAL=3 + ;; + *) + echo "Usage: $0 {start|stop|status|try-restart|condrestart|restart|force-reload|reload}" + RETVAL=3 + ;; +esac + +exit $RETVAL diff --git a/sysvinit/redhat/cloud-init-local b/sysvinit/redhat/cloud-init-local new file mode 100755 index 00000000..b53e0db2 --- /dev/null +++ b/sysvinit/redhat/cloud-init-local @@ -0,0 +1,121 @@ +#!/bin/sh + +# +# Copyright (C) 2012 Yahoo! Inc. +# +# Author: Joshua Harlow +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, as +# published by the Free Software Foundation. +# +# 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 program. If not, see . +# + +# See: http://wiki.debian.org/LSBInitScripts +# See: http://tiny.cc/czvbgw +# See: http://www.novell.com/coolsolutions/feature/15380.html +# Also based on dhcpd in RHEL (for comparison) + +### BEGIN INIT INFO +# Provides: cloud-init-local +# Required-Start: $local_fs $remote_fs +# Should-Start: $time +# Required-Stop: +# Should-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: The initial cloud-init job (local fs contingent) +# Description: Start cloud-init and runs the initialization phases +# and any associated initial modules as desired. +### END INIT INFO + +# Return values acc. to LSB for all commands but status: +# 0 - success +# 1 - generic or unspecified error +# 2 - invalid or excess argument(s) +# 3 - unimplemented feature (e.g. "reload") +# 4 - user had insufficient privileges +# 5 - program is not installed +# 6 - program is not configured +# 7 - program is not running +# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) +# +# Note that starting an already running service, stopping +# or restarting a not-running service as well as the restart +# with force-reload (in case signaling is not supported) are +# considered a success. + +RETVAL=0 + +prog="cloud-init" +cloud_init="/usr/bin/cloud-init" +conf="/etc/cloud/cloud.cfg" + +# If there exist sysconfig/default variable override files use it... +[ -f /etc/sysconfig/cloud-init ] && . /etc/sysconfig/cloud-init +[ -f /etc/default/cloud-init ] && . /etc/default/cloud-init + +start() { + [ -x $cloud_init ] || return 5 + [ -f $conf ] || return 6 + + echo -n $"Starting $prog: " + $cloud_init $CLOUDINITARGS init --local + RETVAL=$? + return $RETVAL +} + +stop() { + echo -n $"Shutting down $prog: " + # No-op + RETVAL=7 + return $RETVAL +} + +case "$1" in + start) + start + RETVAL=$? + ;; + stop) + stop + RETVAL=$? + ;; + restart|try-restart|condrestart) + ## Stop the service and regardless of whether it was + ## running or not, start it again. + # + ## Note: try-restart is now part of LSB (as of 1.9). + ## RH has a similar command named condrestart. + start + RETVAL=$? + ;; + reload|force-reload) + # It does not support reload + RETVAL=3 + ;; + status) + echo -n $"Checking for service $prog:" + # Return value is slightly different for the status command: + # 0 - service up and running + # 1 - service dead, but /var/run/ pid file exists + # 2 - service dead, but /var/lock/ lock file exists + # 3 - service not running (unused) + # 4 - service status unknown :-( + # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) + RETVAL=3 + ;; + *) + echo "Usage: $0 {start|stop|status|try-restart|condrestart|restart|force-reload|reload}" + RETVAL=3 + ;; +esac + +exit $RETVAL -- cgit v1.2.3 From 3d10b8d080a874be022f9e25063ba77f0293c5e8 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Thu, 25 Jul 2013 14:37:10 -0400 Subject: azure: support bouncing interfaces to publish new hostname See the added doc/sources/azure/README.rst for why this is necessary. Essentially, we now are doing the following in the get_data() method of azure datasource to publish this NewHostname: hostname NewHostName ifdown eth0; ifup eth0 LP: #1202758 --- cloudinit/sources/DataSourceAzure.py | 114 +++++++++++++++++----- doc/examples/cloud-config-datasources.txt | 5 + doc/sources/azure/README.rst | 134 ++++++++++++++++++++++++++ tests/unittests/test_datasource/test_azure.py | 77 ++++++++++++++- 4 files changed, 300 insertions(+), 30 deletions(-) create mode 100644 doc/sources/azure/README.rst diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index 0a5caebe..30b06fef 100644 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -31,9 +31,20 @@ LOG = logging.getLogger(__name__) DS_NAME = 'Azure' DEFAULT_METADATA = {"instance-id": "iid-AZURE-NODE"} AGENT_START = ['service', 'walinuxagent', 'start'] -BUILTIN_DS_CONFIG = {'datasource': {DS_NAME: { - 'agent_command': AGENT_START, - 'data_dir': "/var/lib/waagent"}}} +BOUNCE_COMMAND = ("i=$interface; x=0; ifdown $i || x=$?; " + "ifup $i || x=$?; exit $x") +BUILTIN_DS_CONFIG = { + 'agent_command': AGENT_START, + 'data_dir': "/var/lib/waagent", + 'set_hostname': True, + 'hostname_bounce': { + 'interface': 'eth0', + 'policy': True, + 'command': BOUNCE_COMMAND, + 'hostname_command': 'hostname', + } +} +DS_CFG_PATH = ['datasource', DS_NAME] class DataSourceAzureNet(sources.DataSource): @@ -42,19 +53,19 @@ class DataSourceAzureNet(sources.DataSource): self.seed_dir = os.path.join(paths.seed_dir, 'azure') self.cfg = {} self.seed = None + self.ds_cfg = util.mergemanydict([ + util.get_cfg_by_path(sys_cfg, DS_CFG_PATH), + BUILTIN_DS_CONFIG]) def __str__(self): root = sources.DataSource.__str__(self) return "%s [seed=%s]" % (root, self.seed) def get_data(self): - ddir_cfgpath = ['datasource', DS_NAME, 'data_dir'] # azure removes/ejects the cdrom containing the ovf-env.xml # file on reboot. So, in order to successfully reboot we # need to look in the datadir and consider that valid - ddir = util.get_cfg_by_path(self.sys_cfg, ddir_cfgpath) - if ddir is None: - ddir = util.get_cfg_by_path(BUILTIN_DS_CONFIG, ddir_cfgpath) + ddir = self.ds_cfg['data_dir'] candidates = [self.seed_dir] candidates.extend(list_possible_azure_ds_devs()) @@ -91,36 +102,40 @@ class DataSourceAzureNet(sources.DataSource): return False if found == ddir: - LOG.debug("using cached datasource in %s", ddir) - - fields = [('cmd', ['datasource', DS_NAME, 'agent_command']), - ('datadir', ddir_cfgpath)] - mycfg = {} - for cfg in (self.cfg, self.sys_cfg, BUILTIN_DS_CONFIG): - for name, path in fields: - if name in mycfg: - continue - value = util.get_cfg_by_path(cfg, keyp=path) - if value is not None: - mycfg[name] = value + LOG.debug("using files cached in %s", ddir) + + # now update ds_cfg to reflect contents pass in config + usercfg = util.get_cfg_by_path(self.cfg, DS_CFG_PATH, {}) + self.ds_cfg = util.mergemanydict([usercfg, self.ds_cfg]) + mycfg = self.ds_cfg # walinux agent writes files world readable, but expects # the directory to be protected. - write_files(mycfg['datadir'], files, dirmode=0700) + write_files(mycfg['data_dir'], files, dirmode=0700) + + # handle the hostname 'publishing' + try: + handle_set_hostname(mycfg.get('set_hostname'), + self.metadata.get('local-hostname'), + mycfg['hostname_bounce']) + except Exception as e: + LOG.warn("Failed publishing hostname: %s" % e) + util.logexc(LOG, "handling set_hostname failed") try: - invoke_agent(mycfg['cmd']) + invoke_agent(mycfg['agent_command']) except util.ProcessExecutionError: # claim the datasource even if the command failed - util.logexc(LOG, "agent command '%s' failed.", mycfg['cmd']) + util.logexc(LOG, "agent command '%s' failed.", + mycfg['agent_command']) - shcfgxml = os.path.join(mycfg['datadir'], "SharedConfig.xml") + shcfgxml = os.path.join(mycfg['data_dir'], "SharedConfig.xml") wait_for = [shcfgxml] fp_files = [] for pk in self.cfg.get('_pubkeys', []): bname = pk['fingerprint'] + ".crt" - fp_files += [os.path.join(mycfg['datadir'], bname)] + fp_files += [os.path.join(mycfg['data_dir'], bname)] start = time.time() missing = wait_for_files(wait_for + fp_files) @@ -148,6 +163,43 @@ class DataSourceAzureNet(sources.DataSource): return self.cfg +def handle_set_hostname(enabled, hostname, cfg): + if not util.is_true(enabled): + return + + if not hostname: + LOG.warn("set_hostname was true but no local-hostname") + return + + apply_hostname_bounce(hostname=hostname, policy=cfg['policy'], + interface=cfg['interface'], + command=cfg['command'], + hostname_command=cfg['hostname_command']) + + +def apply_hostname_bounce(hostname, policy, interface, command, + hostname_command="hostname"): + # set the hostname to 'hostname' if it is not already set to that. + # then, if policy is not off, bounce the interface using command + prev_hostname = util.subp(hostname_command, capture=True)[0].strip() + + util.subp([hostname_command, hostname]) + + if util.is_false(policy): + return + + if prev_hostname == hostname and policy != "force": + return + + env = os.environ.copy() + env['interface'] = interface + + if command == "builtin": + command = BOUNCE_COMMAND + + util.subp(command, shell=(not isinstance(command, list)), capture=True) + + def crtfile_to_pubkey(fname): pipeline = ('openssl x509 -noout -pubkey < "$0" |' 'ssh-keygen -i -m PKCS8 -f /dev/stdin') @@ -319,15 +371,21 @@ def read_azure_ovf(contents): name = child.localName.lower() simple = False + value = "" if (len(child.childNodes) == 1 and child.childNodes[0].nodeType == dom.TEXT_NODE): simple = True value = child.childNodes[0].wholeText + attrs = {k: v for k, v in child.attributes.items()} + # we accept either UserData or CustomData. If both are present # then behavior is undefined. if (name == "userdata" or name == "customdata"): - ud = base64.b64decode(''.join(value.split())) + if attrs.get('encoding') in (None, "base64"): + ud = base64.b64decode(''.join(value.split())) + else: + ud = value elif name == "username": username = value elif name == "userpassword": @@ -335,7 +393,11 @@ def read_azure_ovf(contents): elif name == "hostname": md['local-hostname'] = value elif name == "dscfg": - cfg['datasource'] = {DS_NAME: util.load_yaml(value, default={})} + if attrs.get('encoding') in (None, "base64"): + dscfg = base64.b64decode(''.join(value.split())) + else: + dscfg = value + cfg['datasource'] = {DS_NAME: util.load_yaml(dscfg, default={})} elif name == "ssh": cfg['_pubkeys'] = load_azure_ovf_pubkeys(child) elif name == "disablesshpasswordauthentication": diff --git a/doc/examples/cloud-config-datasources.txt b/doc/examples/cloud-config-datasources.txt index a19353fc..6544448e 100644 --- a/doc/examples/cloud-config-datasources.txt +++ b/doc/examples/cloud-config-datasources.txt @@ -45,6 +45,11 @@ datasource: Azure: agent_command: [service, walinuxagent, start] + set_hostname: True + hostname_bounce: + interface: eth0 + policy: on # [can be 'on', 'off' or 'force'] + } SmartOS: # Smart OS datasource works over a serial console interacting with diff --git a/doc/sources/azure/README.rst b/doc/sources/azure/README.rst new file mode 100644 index 00000000..8239d1fa --- /dev/null +++ b/doc/sources/azure/README.rst @@ -0,0 +1,134 @@ +================ +Azure Datasource +================ + +This datasource finds metadata and user-data from the Azure cloud platform. + +Azure Platform +-------------- +The azure cloud-platform provides initial data to an instance via an attached +CD formated in UDF. That CD contains a 'ovf-env.xml' file that provides some +information. Additional information is obtained via interaction with the +"endpoint". The ip address of the endpoint is advertised to the instance +inside of dhcp option 245. On ubuntu, that can be seen in +/var/lib/dhcp/dhclient.eth0.leases as a colon delimited hex value (example: +``option unknown-245 64:41:60:82;`` is 100.65.96.130) + +walinuxagent +------------ +In order to operate correctly, cloud-init needs walinuxagent to provide much +of the interaction with azure. In addition to "provisioning" code, walinux +does the following on the agent is a long running daemon that handles the +following things: +- generate a x509 certificate and send that to the endpoint + +waagent.conf config +~~~~~~~~~~~~~~~~~~~ +in order to use waagent.conf with cloud-init, the following settings are recommended. Other values can be changed or set to the defaults. + + :: + + # disabling provisioning turns off all 'Provisioning.*' function + Provisioning.Enabled=n + # this is currently not handled by cloud-init, so let walinuxagent do it. + ResourceDisk.Format=y + ResourceDisk.MountPoint=/mnt + + +Userdata +-------- +Userdata is provided to cloud-init inside the ovf-env.xml file. Cloud-init +expects that user-data will be provided as base64 encoded value inside the +text child of a element named ``UserData`` or ``CustomData`` which is a direct +child of the ``LinuxProvisioningConfigurationSet`` (a sibling to ``UserName``) +If both ``UserData`` and ``CustomData`` are provided behavior is undefined on +which will be selected. + +In the example below, user-data provided is 'this is my userdata', and the +datasource config provided is ``{"agent_command": ["start", "walinuxagent"]}``. +That agent command will take affect as if it were specified in system config. + +Example: + +.. code:: + + + 1.0 + + LinuxProvisioningConfiguration + myHost + myuser + + dGhpcyBpcyBteSB1c2VyZGF0YQ=== + eyJhZ2VudF9jb21tYW5kIjogWyJzdGFydCIsICJ3YWxpbnV4YWdlbnQiXX0= + true + + + + 6BE7A7C3C8A8F4B123CCA5D0C2F1BE4CA7B63ED7 + this-value-unused + + + + + + +Configuration +------------- +Configuration for the datasource can be read from the system config's or set +via the `dscfg` entry in the `LinuxProvisioningConfigurationSet`. Content in +dscfg node is expected to be base64 encoded yaml content, and it will be +merged into the 'datasource: Azure' entry. + +The '``hostname_bounce: command``' entry can be either the literal string +'builtin' or a command to execute. The command will be invoked after the +hostname is set, and will have the 'interface' in its environment. If +``set_hostname`` is not true, then ``hostname_bounce`` will be ignored. + +An example might be: + command: ["sh", "-c", "killall dhclient; dhclient $interface"] + +.. code:: + + datasource: + agent_command + Azure: + agent_command: [service, walinuxagent, start] + set_hostname: True + hostname_bounce: + # the name of the interface to bounce + interface: eth0 + # policy can be 'on', 'off' or 'force' + policy: on + # the method 'bounce' command. + command: "builtin" + hostname_command: "hostname" + } + +hostname +-------- +When the user launches an instance, they provide a hostname for that instance. +The hostname is provided to the instance in the ovf-env.xml file as +``HostName``. + +Whatever value the instance provides in its dhcp request will resolve in the +domain returned in the 'search' request. + +The interesting issue is that a generic image will already have a hostname +configured. The ubuntu cloud images have 'ubuntu' as the hostname of the +system, and the initial dhcp request on eth0 is not guaranteed to occur after +the datasource code has been run. So, on first boot, that initial value will +be sent in the dhcp request and *that* value will resolve. + +In order to make the ``HostName`` provided in the ovf-env.xml resolve, a +dhcp request must be made with the new value. Walinuxagent (in its current +version) handles this by polling the state of hostname and bouncing ('``ifdown +eth0; ifup eth0``' the network interface if it sees that a change has been +made. + +cloud-init handles this by setting the hostname in the DataSource's 'get_data' +method via '``hostname $HostName``', and then bouncing the interface. This +behavior can be configured or disabled in the datasource config. See +'Configuration' above. diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py index 2e8583f9..c944cb13 100644 --- a/tests/unittests/test_datasource/test_azure.py +++ b/tests/unittests/test_datasource/test_azure.py @@ -26,8 +26,15 @@ def construct_valid_ovf_env(data=None, pubkeys=None, userdata=None): xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> LinuxProvisioningConfiguration """ - for key, val in data.items(): - content += "<%s>%s\n" % (key, val, key) + for key, dval in data.items(): + if isinstance(dval, dict): + val = dval.get('text') + attrs = ' ' + ' '.join(["%s='%s'" % (k, v) for k, v in dval.items() + if k != 'text']) + else: + val = dval + attrs = "" + content += "<%s%s>%s\n" % (key, attrs, val, key) if userdata: content += "%s\n" % (base64.b64encode(userdata)) @@ -103,6 +110,9 @@ class TestAzureDataSource(MockerTestCase): data['iid_from_shared_cfg'] = path return 'i-my-azure-id' + def _apply_hostname_bounce(**kwargs): + data['apply_hostname_bounce'] = kwargs + if data.get('ovfcontent') is not None: populate_dir(os.path.join(self.paths.seed_dir, "azure"), {'ovf-env.xml': data['ovfcontent']}) @@ -118,7 +128,9 @@ class TestAzureDataSource(MockerTestCase): (mod, 'pubkeys_from_crt_files', _pubkeys_from_crt_files), (mod, 'iid_from_shared_config', - _iid_from_shared_config), ]) + _iid_from_shared_config), + (mod, 'apply_hostname_bounce', + _apply_hostname_bounce), ]) dsrc = mod.DataSourceAzureNet( data.get('sys_cfg', {}), distro=None, paths=self.paths) @@ -139,11 +151,26 @@ class TestAzureDataSource(MockerTestCase): self.assertEqual(0700, data['datadir_mode']) self.assertEqual(dsrc.metadata['instance-id'], 'i-my-azure-id') + def test_user_cfg_set_agent_command_plain(self): + # set dscfg in via plaintext + cfg = {'agent_command': "my_command"} + odata = {'HostName': "myhost", 'UserName': "myuser", + 'dscfg': {'text': yaml.dump(cfg), 'encoding': 'plain'}} + data = {'ovfcontent': construct_valid_ovf_env(data=odata)} + + dsrc = self._get_ds(data) + ret = dsrc.get_data() + self.assertTrue(ret) + self.assertEqual(data['agent_invoked'], cfg['agent_command']) + def test_user_cfg_set_agent_command(self): + # set dscfg in via base64 encoded yaml cfg = {'agent_command': "my_command"} odata = {'HostName': "myhost", 'UserName': "myuser", - 'dscfg': yaml.dump(cfg)} + 'dscfg': {'text': base64.b64encode(yaml.dump(cfg)), + 'encoding': 'base64'}} data = {'ovfcontent': construct_valid_ovf_env(data=odata)} + print data dsrc = self._get_ds(data) ret = dsrc.get_data() @@ -218,6 +245,48 @@ class TestAzureDataSource(MockerTestCase): for mypk in mypklist: self.assertIn(mypk, dsrc.cfg['_pubkeys']) + def test_disabled_bounce(self): + pass + + def test_apply_bounce_call_1(self): + # hostname needs to get through to apply_hostname_bounce + mydata = "FOOBAR" + odata = {'HostName': 'my-random-hostname'} + data = {'ovfcontent': construct_valid_ovf_env(data=odata)} + + self._get_ds(data).get_data() + self.assertIn('hostname', data['apply_hostname_bounce']) + self.assertEqual(data['apply_hostname_bounce']['hostname'], + odata['HostName']) + + def test_apply_bounce_call_configurable(self): + # hostname_bounce should be configurable in datasource cfg + cfg = {'hostname_bounce': {'interface': 'eth1', 'policy': 'off', + 'command': 'my-bounce-command', + 'hostname_command': 'my-hostname-command'}} + odata = {'HostName': "xhost", + 'dscfg': {'text': base64.b64encode(yaml.dump(cfg)), + 'encoding': 'base64'}} + data = {'ovfcontent': construct_valid_ovf_env(data=odata)} + self._get_ds(data).get_data() + + for k in cfg['hostname_bounce']: + self.assertIn(k, data['apply_hostname_bounce']) + + for k, v in cfg['hostname_bounce'].items(): + self.assertEqual(data['apply_hostname_bounce'][k], v) + + def test_set_hostname_disabled(self): + # config specifying set_hostname off should not bounce + cfg = {'set_hostname': False} + odata = {'HostName': "xhost", + 'dscfg': {'text': base64.b64encode(yaml.dump(cfg)), + 'encoding': 'base64'}} + data = {'ovfcontent': construct_valid_ovf_env(data=odata)} + self._get_ds(data).get_data() + + self.assertEqual(data.get('apply_hostname_bounce', "N/A"), "N/A") + class TestReadAzureOvf(MockerTestCase): def test_invalid_xml_raises_non_azure_ds(self): -- cgit v1.2.3 From 4d9668dac5fed8f713f3b4300fdb574f399c14ee Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Thu, 25 Jul 2013 15:27:44 -0400 Subject: minor azure cleanup --- cloudinit/sources/DataSourceAzure.py | 2 +- tests/unittests/test_datasource/test_azure.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index 30b06fef..d4863429 100644 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -54,7 +54,7 @@ class DataSourceAzureNet(sources.DataSource): self.cfg = {} self.seed = None self.ds_cfg = util.mergemanydict([ - util.get_cfg_by_path(sys_cfg, DS_CFG_PATH), + util.get_cfg_by_path(sys_cfg, DS_CFG_PATH, {}), BUILTIN_DS_CONFIG]) def __str__(self): diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py index c944cb13..4cd3f213 100644 --- a/tests/unittests/test_datasource/test_azure.py +++ b/tests/unittests/test_datasource/test_azure.py @@ -170,7 +170,6 @@ class TestAzureDataSource(MockerTestCase): 'dscfg': {'text': base64.b64encode(yaml.dump(cfg)), 'encoding': 'base64'}} data = {'ovfcontent': construct_valid_ovf_env(data=odata)} - print data dsrc = self._get_ds(data) ret = dsrc.get_data() -- cgit v1.2.3 From 068009432909ae54b42e2cb56ec6557b04c677b0 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Thu, 25 Jul 2013 16:34:19 -0400 Subject: pull in fixes for debian bug 712985 --- sysvinit/debian/cloud-config | 12 ++++++++++++ sysvinit/debian/cloud-final | 12 ++++++++++++ sysvinit/debian/cloud-init | 14 +++++++++++++- sysvinit/debian/cloud-init-local | 11 +++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) mode change 100755 => 100644 sysvinit/debian/cloud-config mode change 100755 => 100644 sysvinit/debian/cloud-final mode change 100755 => 100644 sysvinit/debian/cloud-init-local diff --git a/sysvinit/debian/cloud-config b/sysvinit/debian/cloud-config old mode 100755 new mode 100644 index 57888653..53322748 --- a/sysvinit/debian/cloud-config +++ b/sysvinit/debian/cloud-config @@ -11,6 +11,7 @@ # Authors: Julien Danjou # Juerg Haefliger +# Thomas Goirand PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="Cloud service" @@ -30,6 +31,17 @@ SCRIPTNAME=/etc/init.d/$NAME # and status_of_proc is working. . /lib/lsb/init-functions +if init_is_upstart; then + case "$1" in + stop) + exit 0 + ;; + *) + exit 1 + ;; + esac +fi + case "$1" in start) log_daemon_msg "Starting $DESC" "$NAME" diff --git a/sysvinit/debian/cloud-final b/sysvinit/debian/cloud-final old mode 100755 new mode 100644 index 46e9b454..55afc8b0 --- a/sysvinit/debian/cloud-final +++ b/sysvinit/debian/cloud-final @@ -13,6 +13,7 @@ # Authors: Julien Danjou # Juerg Haefliger +# Thomas Goirand PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="Cloud service" @@ -32,6 +33,17 @@ SCRIPTNAME=/etc/init.d/$NAME # and status_of_proc is working. . /lib/lsb/init-functions +if init_is_upstart; then + case "$1" in + stop) + exit 0 + ;; + *) + exit 1 + ;; + esac +fi + case "$1" in start) log_daemon_msg "Starting $DESC" "$NAME" diff --git a/sysvinit/debian/cloud-init b/sysvinit/debian/cloud-init index 15ffeb2e..48fa0423 100755 --- a/sysvinit/debian/cloud-init +++ b/sysvinit/debian/cloud-init @@ -10,7 +10,8 @@ # Description: Cloud configuration initialization ### END INIT INFO -# Author: Julien Danjou +# Authors: Julien Danjou +# Thomas Goirand PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="Cloud service" @@ -30,6 +31,17 @@ SCRIPTNAME=/etc/init.d/$NAME # and status_of_proc is working. . /lib/lsb/init-functions +if init_is_upstart; then + case "$1" in + stop) + exit 0 + ;; + *) + exit 1 + ;; + esac +fi + case "$1" in start) log_daemon_msg "Starting $DESC" "$NAME" diff --git a/sysvinit/debian/cloud-init-local b/sysvinit/debian/cloud-init-local old mode 100755 new mode 100644 index a1685c1e..802ee8e9 --- a/sysvinit/debian/cloud-init-local +++ b/sysvinit/debian/cloud-init-local @@ -30,6 +30,17 @@ SCRIPTNAME=/etc/init.d/$NAME # and status_of_proc is working. . /lib/lsb/init-functions +if init_is_upstart; then + case "$1" in + stop) + exit 0 + ;; + *) + exit 1 + ;; + esac +fi + case "$1" in start) log_daemon_msg "Starting $DESC" "$NAME" -- cgit v1.2.3 From 60dfcb852c3dafdcf3563cc3e6c631dfbc2bafd8 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Thu, 25 Jul 2013 17:01:57 -0400 Subject: add --init-sytem to ./packages/bddeb this way you can now do ./package/bddeb --init-system=sysvinit_deb --- packages/bddeb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/bddeb b/packages/bddeb index 00bc717e..7bf59fcd 100755 --- a/packages/bddeb +++ b/packages/bddeb @@ -94,12 +94,20 @@ def main(): default=False, action='store_true') + parser.add_argument("--init-system", dest="init_system", + help=("build deb with INIT_SYSTEM=xxx" + " (default: %(default)s"), + default=os.environ.get("INIT_SYSTEM", "upstart")) + + for ent in DEBUILD_ARGS: parser.add_argument(ent, dest="debuild_args", action='append_const', const=ent, help=("pass through '%s' to debuild" % ent)) args = parser.parse_args() + os.environ['INIT_SYSTEM'] = args.init_system + capture = True if args.verbose: capture = False -- cgit v1.2.3 From 9da084bda820d0ab8500ea6ee13a014f46d3bfab Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Fri, 26 Jul 2013 14:05:52 -0400 Subject: azure: fix bouncing of interface the environment that was set up to include 'interface' was not actually being passed on to 'subp', so when the command ran it wasn't available. --- cloudinit/sources/DataSourceAzure.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index d4863429..9503b045 100644 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -31,8 +31,9 @@ LOG = logging.getLogger(__name__) DS_NAME = 'Azure' DEFAULT_METADATA = {"instance-id": "iid-AZURE-NODE"} AGENT_START = ['service', 'walinuxagent', 'start'] -BOUNCE_COMMAND = ("i=$interface; x=0; ifdown $i || x=$?; " - "ifup $i || x=$?; exit $x") +BOUNCE_COMMAND = ['sh', '-xc', + "i=$interface; x=0; ifdown $i || x=$?; ifup $i || x=$?; exit $x"] + BUILTIN_DS_CONFIG = { 'agent_command': AGENT_START, 'data_dir': "/var/lib/waagent", @@ -185,19 +186,29 @@ def apply_hostname_bounce(hostname, policy, interface, command, util.subp([hostname_command, hostname]) + msg = ("phostname=%s hostname=%s policy=%s interface=%s" % + (prev_hostname, hostname, policy, interface)) + if util.is_false(policy): + LOG.debug("pubhname: policy false, skipping [%s]", msg) return if prev_hostname == hostname and policy != "force": + LOG.debug("pubhname: no change, policy != force. skipping. [%s]", msg) return env = os.environ.copy() env['interface'] = interface + env['hostname'] = hostname + env['old_hostname'] = prev_hostname if command == "builtin": command = BOUNCE_COMMAND - util.subp(command, shell=(not isinstance(command, list)), capture=True) + LOG.debug("pubhname: publishing hostname [%s]", msg) + shell = not isinstance(command, (list, tuple)) + (output, err) = util.subp(command, shell=shell, capture=True, env=env) + LOG.debug("output: %s. err: %s", output, err) def crtfile_to_pubkey(fname): -- cgit v1.2.3 From de1e9a7e8e23d4b986c85365a79b9cf026a85ed1 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Sat, 27 Jul 2013 14:20:12 -0700 Subject: Add the pyserial dependency. LP: #1205720 --- Requires | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Requires b/Requires index 5086230d..f19c9691 100644 --- a/Requires +++ b/Requires @@ -10,6 +10,10 @@ PrettyTable # datasource is removed, this is no longer needed oauth +# This one is currently used only by the SmartOS datasource. If that +# datasource is removed, this is no longer needed +pyserial + # This is only needed for places where we need to support configs in a manner # that the built-in config parser is not sufficent (ie # when we need to preserve comments, or do not have a top-level -- cgit v1.2.3 From e9f1190993fc5e66cd7bcc47016a5d7335fe8763 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Mon, 29 Jul 2013 12:02:03 -0400 Subject: DataSourceAzure: do not capture output of bounce command As shown in comments of bug 1202758 and filing of ntp bug 1206164, waiting for the output of this command causes us to wait for ntpdate to fully finish. Ideally I think we'd disable ntpdate running on this run, but that is not trivially possible. --- cloudinit/sources/DataSourceAzure.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index 9503b045..2f28702e 100644 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -206,9 +206,11 @@ def apply_hostname_bounce(hostname, policy, interface, command, command = BOUNCE_COMMAND LOG.debug("pubhname: publishing hostname [%s]", msg) + start = time.time() shell = not isinstance(command, (list, tuple)) - (output, err) = util.subp(command, shell=shell, capture=True, env=env) - LOG.debug("output: %s. err: %s", output, err) + # capture=False, see comments in bug 1202758 and bug 1206164. + (output, err) = util.subp(command, shell=shell, capture=False, env=env) + LOG.debug("publishing hostname took %.3f seconds", time.time() - start) def crtfile_to_pubkey(fname): -- cgit v1.2.3 From 88b2a8ef062398499a2c14d309c132a081cac26b Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Mon, 29 Jul 2013 13:21:57 -0400 Subject: add 'pyserial' to bddeb and bdrpm --- packages/bddeb | 3 ++- packages/brpm | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/bddeb b/packages/bddeb index 15d424f2..30559870 100755 --- a/packages/bddeb +++ b/packages/bddeb @@ -32,11 +32,12 @@ PKG_MP = { 'boto': 'python-boto', 'cheetah': 'python-cheetah', 'configobj': 'python-configobj', + 'jsonpatch': 'python-json-patch', 'oauth': 'python-oauth', 'prettytable': 'python-prettytable', + 'pyserial': 'python-serial', 'pyyaml': 'python-yaml', 'requests': 'python-requests', - 'jsonpatch': 'python-json-patch', } DEBUILD_ARGS = ["-us", "-S", "-uc", "-d"] diff --git a/packages/brpm b/packages/brpm index 91a0a0ec..8c90a0ab 100755 --- a/packages/brpm +++ b/packages/brpm @@ -42,6 +42,7 @@ PKG_MP = { 'jsonpatch': 'python-jsonpatch', 'oauth': 'python-oauth', 'prettytable': 'python-prettytable', + 'pyserial': 'pyserial', 'pyyaml': 'PyYAML', 'requests': 'python-requests', }, @@ -53,6 +54,7 @@ PKG_MP = { 'jsonpatch': 'python-jsonpatch', 'oauth': 'python-oauth', 'prettytable': 'python-prettytable', + 'pyserial': 'python-pyserial', 'pyyaml': 'python-yaml', 'requests': 'python-requests', } -- cgit v1.2.3 From 66490ebb92af59d148f79aae42a2eddc1ecedb7e Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Tue, 30 Jul 2013 14:23:10 -0400 Subject: add util.log_time helper The reason for this is that more and more things I was wanting to be able to see how long they took. This puts that time logic into a single place. It also supports (by default) reading from /proc/uptime as the timing mechanism. While that is almost certainly slower than time.time(), it does give millisecond granularity and is not affected by 'ntpdate' having run in between the two events. --- ChangeLog | 3 +++ bin/cloud-init | 5 ++++- cloudinit/config/cc_growpart.py | 3 ++- cloudinit/config/cc_resizefs.py | 11 +++++------ cloudinit/sources/DataSourceAzure.py | 14 ++++++-------- cloudinit/util.py | 35 +++++++++++++++++++++++++++++++++++ 6 files changed, 55 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index a255d24a..68d03376 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,9 @@ - always finalize handlers even if processing failed (LP: #1203368) - support merging into cloud-config via jsonp. (LP: #1200476) - add datasource 'SmartOS' for Joyent Cloud. Adds a dependency on serial. + - add 'log_time' helper to util for timing how long things take + which also reads from uptime. uptime is useful as clock may change during + boot due to ntp. 0.7.2: - add a debian watch file - add 'sudo' entry to ubuntu's default user (LP: #1080717) diff --git a/bin/cloud-init b/bin/cloud-init index c5a5b949..bd9ddc04 100755 --- a/bin/cloud-init +++ b/bin/cloud-init @@ -502,7 +502,10 @@ def main(): signal_handler.attach_handlers() (name, functor) = args.action - return functor(name, args) + + return util.log_time(logfunc=LOG.debug, + msg="cloud-init mode '%s'" % name, uptime=True, + func=functor, args=(name, args)) if __name__ == '__main__': diff --git a/cloudinit/config/cc_growpart.py b/cloudinit/config/cc_growpart.py index 4f8c8f80..ba6c58af 100644 --- a/cloudinit/config/cc_growpart.py +++ b/cloudinit/config/cc_growpart.py @@ -264,7 +264,8 @@ def handle(_name, cfg, _cloud, log, _args): raise e return - resized = resize_devices(resizer, devices) + resized = util.log_time(logfunc=log.debug, msg="resize_devices", + func=resize_devices, args=(resizer, devices)) for (entry, action, msg) in resized: if action == RESIZE.CHANGED: log.info("'%s' resized: %s" % (entry, msg)) diff --git a/cloudinit/config/cc_resizefs.py b/cloudinit/config/cc_resizefs.py index b4ee16b2..56040fdd 100644 --- a/cloudinit/config/cc_resizefs.py +++ b/cloudinit/config/cc_resizefs.py @@ -21,7 +21,6 @@ import errno import os import stat -import time from cloudinit.settings import PER_ALWAYS from cloudinit import util @@ -120,9 +119,12 @@ def handle(name, cfg, _cloud, log, args): if resize_root == NOBLOCK: # Fork to a child that will run # the resize command - util.fork_cb(do_resize, resize_cmd, log) + util.fork_cb( + util.log_time(logfunc=log.debug, msg="backgrounded Resizing", + func=do_resize, args=(resize_cmd, log))) else: - do_resize(resize_cmd, log) + util.log_time(logfunc=log.debug, msg="Resizing", + func=do_resize, args=(resize_cmd, log)) action = 'Resized' if resize_root == NOBLOCK: @@ -132,13 +134,10 @@ def handle(name, cfg, _cloud, log, args): def do_resize(resize_cmd, log): - start = time.time() try: util.subp(resize_cmd) except util.ProcessExecutionError: util.logexc(log, "Failed to resize filesystem (cmd=%s)", resize_cmd) raise - tot_time = time.time() - start - log.debug("Resizing took %.3f seconds", tot_time) # TODO(harlowja): Should we add a fsck check after this to make # sure we didn't corrupt anything? diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index 2f28702e..f906b8fa 100644 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -138,13 +138,11 @@ class DataSourceAzureNet(sources.DataSource): bname = pk['fingerprint'] + ".crt" fp_files += [os.path.join(mycfg['data_dir'], bname)] - start = time.time() - missing = wait_for_files(wait_for + fp_files) + missing = util.log_time(logfunc=LOG.debug, msg="waiting for files", + func=wait_for_files, + args=(wait_for + fp_files,)) if len(missing): LOG.warn("Did not find files, but going on: %s", missing) - else: - LOG.debug("waited %.3f seconds for %d files to appear", - time.time() - start, len(wait_for)) if shcfgxml in missing: LOG.warn("SharedConfig.xml missing, using static instance-id") @@ -206,11 +204,11 @@ def apply_hostname_bounce(hostname, policy, interface, command, command = BOUNCE_COMMAND LOG.debug("pubhname: publishing hostname [%s]", msg) - start = time.time() shell = not isinstance(command, (list, tuple)) # capture=False, see comments in bug 1202758 and bug 1206164. - (output, err) = util.subp(command, shell=shell, capture=False, env=env) - LOG.debug("publishing hostname took %.3f seconds", time.time() - start) + util.log_time(logfunc=LOG.debug, msg="publishing hostname", + func=util.subp, kwargs={'command': command, 'shell': shell, + 'capture': False, 'env': env}) def crtfile_to_pubkey(fname): diff --git a/cloudinit/util.py b/cloudinit/util.py index 8542fe27..b0eb56e6 100644 --- a/cloudinit/util.py +++ b/cloudinit/util.py @@ -1770,3 +1770,38 @@ def which(program): return exe_file return None + + +def log_time(logfunc, msg, func, args=None, kwargs=None, get_uptime=True): + if args is None: + args = [] + if kwargs is None: + kwargs = {} + + start = time.time() + + ustart = None + if get_uptime: + try: + ustart = float(uptime()) + except ValueError: + pass + + try: + ret = func(*args, **kwargs) + finally: + delta = time.time() - start + if ustart is not None: + try: + udelta = float(uptime()) - ustart + except ValueError: + udelta = "N/A" + + tmsg = " took %0.3f seconds" % delta + if get_uptime: + tmsg += "(%0.2f)" % udelta + try: + logfunc(msg + tmsg) + except: + pass + return ret -- cgit v1.2.3 From 0ca150b08433fbc57e10d599a46e300142c955c5 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Tue, 30 Jul 2013 14:28:09 -0400 Subject: set reading /proc/uptime to false by default. reading /proc/uptime is going to be slower, and no reason to do it on most things. Better to only do it when you suspect maybe a need for it. --- bin/cloud-init | 5 ++--- cloudinit/sources/DataSourceAzure.py | 5 +++-- cloudinit/util.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bin/cloud-init b/bin/cloud-init index bd9ddc04..b4f9fd07 100755 --- a/bin/cloud-init +++ b/bin/cloud-init @@ -503,9 +503,8 @@ def main(): (name, functor) = args.action - return util.log_time(logfunc=LOG.debug, - msg="cloud-init mode '%s'" % name, uptime=True, - func=functor, args=(name, args)) + return util.log_time(logfunc=LOG.debug, msg="cloud-init mode '%s'" % name, + get_uptime=True, func=functor, args=(name, args)) if __name__ == '__main__': diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index f906b8fa..1a74de21 100644 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -207,8 +207,9 @@ def apply_hostname_bounce(hostname, policy, interface, command, shell = not isinstance(command, (list, tuple)) # capture=False, see comments in bug 1202758 and bug 1206164. util.log_time(logfunc=LOG.debug, msg="publishing hostname", - func=util.subp, kwargs={'command': command, 'shell': shell, - 'capture': False, 'env': env}) + get_uptime=True, func=util.subp, + kwargs={'command': command, 'shell': shell, 'capture': False, + 'env': env}) def crtfile_to_pubkey(fname): diff --git a/cloudinit/util.py b/cloudinit/util.py index b0eb56e6..4a74ba57 100644 --- a/cloudinit/util.py +++ b/cloudinit/util.py @@ -1772,7 +1772,7 @@ def which(program): return None -def log_time(logfunc, msg, func, args=None, kwargs=None, get_uptime=True): +def log_time(logfunc, msg, func, args=None, kwargs=None, get_uptime=False): if args is None: args = [] if kwargs is None: -- cgit v1.2.3