Hello community, here is the log from the commit of package google-daemon for openSUSE:Factory checked in at 2015-08-03 17:22:39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/google-daemon (Old) and /work/SRC/openSUSE:Factory/.google-daemon.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "google-daemon" Changes: -------- --- /work/SRC/openSUSE:Factory/google-daemon/google-daemon.changes 2015-03-19 21:16:32.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.google-daemon.new/google-daemon.changes 2015-08-03 17:22:40.000000000 +0200 @@ -1,0 +2,15 @@ +Mon Aug 3 08:26:42 UTC 2015 - [email protected] + +- Update to version 1.2.7 (bnc#940190) + + Fix check for gcua + + Preventing the accounts manager from starting if GCUA is + installed. + + Remove temp files when move operation fails + + Fix string formatting. + + Documentation should point to gcloud compute instead of the + deprecated gcutil. + + Use /bin/ip instead of /sbin/ip + + Google clock sync manager to sync the system clock when a migration + occurs. Fix white space in existing daemons to be consistent. + +------------------------------------------------------------------- Old: ---- google-daemon-1.2.4.tar.bz2 New: ---- google-daemon-1.2.7.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ google-daemon.spec ++++++ --- /var/tmp/diff_new_pack.UMoZtQ/_old 2015-08-03 17:22:41.000000000 +0200 +++ /var/tmp/diff_new_pack.UMoZtQ/_new 2015-08-03 17:22:41.000000000 +0200 @@ -17,7 +17,7 @@ Name: google-daemon -Version: 1.2.4 +Version: 1.2.7 Release: 0 Summary: VM management inside GCE License: Apache-2.0 @@ -100,7 +100,7 @@ %files %defattr(-,root,root,-) -%doc LICENSE +%doc LICENSE README.md %{_datadir}/google/google_daemon/* %{_sbindir}/rcgoogle-address-manager %{_sbindir}/rcgoogle-accounts-manager ++++++ google-daemon-1.2.4.tar.bz2 -> google-daemon-1.2.7.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-daemon-1.2.4/README.md new/google-daemon-1.2.7/README.md --- old/google-daemon-1.2.4/README.md 2015-03-10 02:28:44.000000000 +0100 +++ new/google-daemon-1.2.7/README.md 2015-07-11 02:13:30.000000000 +0200 @@ -8,7 +8,7 @@ /usr/share/google/google_daemon/manage_accounts.py -Your users can create ssh keys for accounts on a virtual machine using [gcutil](http://developers.google.com/compute/docs/gcutil "gcutil") or manually using these steps: +Your users can create ssh keys for accounts on a virtual machine using [gcloud compute](https://cloud.google.com/compute/docs/gcloud-compute/) or manually using these steps: # Generate the ssh keys $ ssh-keygen -t rsa -f ~/.ssh/google_compute_engine diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-daemon-1.2.4/etc/init/google-clock-sync-manager.conf new/google-daemon-1.2.7/etc/init/google-clock-sync-manager.conf --- old/google-daemon-1.2.4/etc/init/google-clock-sync-manager.conf 1970-01-01 01:00:00.000000000 +0100 +++ new/google-daemon-1.2.7/etc/init/google-clock-sync-manager.conf 2015-07-11 02:13:30.000000000 +0200 @@ -0,0 +1,5 @@ +# This service syncs the clock after migration in a Google Compute Engine instance. +start on google-rc-local-has-run + +respawn +exec /usr/share/google/google_daemon/manage_clock_sync.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-daemon-1.2.4/etc/init.d/google-clock-sync-manager new/google-daemon-1.2.7/etc/init.d/google-clock-sync-manager --- old/google-daemon-1.2.4/etc/init.d/google-clock-sync-manager 1970-01-01 01:00:00.000000000 +0100 +++ new/google-daemon-1.2.7/etc/init.d/google-clock-sync-manager 2015-07-11 02:13:30.000000000 +0200 @@ -0,0 +1,153 @@ +#! /bin/sh +# Copyright 2015 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +### BEGIN INIT INFO +# Provides: google-clock-manager +# Required-Start: $network $syslog +# Required-Stop: $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Example initscript +# Description: This file should be used to construct scripts to be +# placed in /etc/init.d. +### END INIT INFO + +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="Google clock sync manager" +NAME=google-clock-sync-manager +DAEMON=/usr/share/google/google_daemon/manage_clock_sync.py +DAEMON_ARGS="" +PIDFILE=/var/run/$NAME.pid +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 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# 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 + +# If we're running under upstart, let the upstart config file handle things. +# Debian 7 and newer have a near-one-liner function to detect this... +if type init_is_upstart >/dev/null 2>&1; then + # ... which we can use if present. + init_is_upstart && exit 0 +else + # Otherwise, directly include the core line of Debian 7's version. + # Authorship credit: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=661109 + if [ -x /sbin/initctl ] && /sbin/initctl version | /bin/grep -q upstart; then + exit 0 + fi +fi + +# +# Function that starts the daemon/service +# +do_start() +{ + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + start-stop-daemon --start --quiet --make-pidfile --background \ + --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ + || return 1 + start-stop-daemon --start --quiet --make-pidfile --background \ + --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS || return 2 +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + # Wait for children to finish too if this is a daemon that forks + # and if the daemon is only ever run from this initscript. + # If the above conditions are not satisfied then add some other code + # that waits for the process to drop all resources that could be + # needed by services started subsequently. A last resort is to + # sleep for some time. + start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 \ + --pidfile $PIDFILE + [ "$?" = 2 ] && return 2 + # Many daemons don't delete their pidfiles when they exit. + rm -f $PIDFILE + return "$RETVAL" +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc -p "$PIDFILE" "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + restart|force-reload) + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-daemon-1.2.4/usr/lib/systemd/system/google-clock-sync-manager.service new/google-daemon-1.2.7/usr/lib/systemd/system/google-clock-sync-manager.service --- old/google-daemon-1.2.4/usr/lib/systemd/system/google-clock-sync-manager.service 1970-01-01 01:00:00.000000000 +0100 +++ new/google-daemon-1.2.7/usr/lib/systemd/system/google-clock-sync-manager.service 2015-07-11 02:13:30.000000000 +0200 @@ -0,0 +1,11 @@ +[Unit] +Description=Google Compute Engine Clock Sync Daemon +After=network.target +Requires=network.target + +[Service] +Type=simple +ExecStart=/usr/share/google/google_daemon/manage_clock_sync.py + +[Install] +WantedBy=multi-user.target diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-daemon-1.2.4/usr/share/google/google_daemon/accounts.py new/google-daemon-1.2.7/usr/share/google/google_daemon/accounts.py --- old/google-daemon-1.2.4/usr/share/google/google_daemon/accounts.py 2015-03-10 02:28:44.000000000 +0100 +++ new/google-daemon-1.2.7/usr/share/google/google_daemon/accounts.py 2015-07-11 02:13:30.000000000 +0200 @@ -414,8 +414,14 @@ if available_space < required_space: raise IOError('Disk is too full') - # Override the old authorized keys file with the new one. - self.system.MoveFile(new_keys_path, authorized_keys_file) + try: + # Override the old authorized keys file with the new one. + self.system.MoveFile(new_keys_path, authorized_keys_file) + finally: + try: + self.system.DeleteFile(new_keys_path) + except: + pass # Make sure the authorized_keys_file has the right perms (u+rw). self.os.chmod(authorized_keys_file, 0600) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-daemon-1.2.4/usr/share/google/google_daemon/accounts_manager.py new/google-daemon-1.2.7/usr/share/google/google_daemon/accounts_manager.py --- old/google-daemon-1.2.4/usr/share/google/google_daemon/accounts_manager.py 2015-03-10 02:28:44.000000000 +0100 +++ new/google-daemon-1.2.7/usr/share/google/google_daemon/accounts_manager.py 2015-07-11 02:13:30.000000000 +0200 @@ -50,9 +50,9 @@ while True: # Fork and run the key regeneration and account update while the # parent waits for the subprocess to finish before continuing. - + # Create a pipe used to get the new etag value from child - reader, writer = os.pipe() # these are file descriptors, not file objects + reader, writer = os.pipe() # these are file descriptors, not file objects pid = os.fork() if pid: # we are the parent @@ -117,7 +117,7 @@ for entry in all_accounts if os.path.isfile(os.path.join(entry.pw_dir, keyfile_suffix))] extra_usernames = set(sshable_usernames) - set(desired_accounts.keys()) - + if desired_accounts: for username, ssh_keys in desired_accounts.iteritems(): if not username: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-daemon-1.2.4/usr/share/google/google_daemon/address_manager.py new/google-daemon-1.2.7/usr/share/google/google_daemon/address_manager.py --- old/google-daemon-1.2.4/usr/share/google/google_daemon/address_manager.py 2015-03-10 02:28:44.000000000 +0100 +++ new/google-daemon-1.2.7/usr/share/google/google_daemon/address_manager.py 2015-07-11 02:13:30.000000000 +0200 @@ -49,6 +49,9 @@ self.system = system_module self.urllib2 = urllib2_module self.time = time_module + self.ip_path = '/sbin/ip' + if not os.path.exists(self.ip_path): + self.ip_path = '/bin/ip' # etag header value is hex, so this is guaranteed to not match. self.default_last_etag = 'NONE' @@ -104,8 +107,8 @@ def ReadLocalConfiguredAddrs(self): """Fetch list of addresses we've configured on eth0 already.""" - cmd = ('/sbin/ip route ls table local type local dev eth0 scope host ' + - 'proto %d' % GOOGLE_PROTO_ID) + cmd = ('{0} route ls table local type local dev eth0 scope host ' + + 'proto {1:d}').format(self.ip_path, GOOGLE_PROTO_ID) result = self.system.RunCommand(cmd.split()) if self.IPCommandFailed(result, cmd): raise InputError('Can''t check local addresses') @@ -138,8 +141,8 @@ def AddOneAddress(self, addr): """Configure one address on eth0.""" - cmd = '/sbin/ip route add to local %s/32 dev eth0 proto %d' % ( - addr, GOOGLE_PROTO_ID) + cmd = '%s route add to local %s/32 dev eth0 proto %d' % ( + self.ip_path, addr, GOOGLE_PROTO_ID) result = self.system.RunCommand(cmd.split()) self.IPCommandFailed(result, cmd) # Ignore return code @@ -152,8 +155,8 @@ """Delete one address from eth0.""" # This will fail if it doesn't match exactly the specs listed. # That'll help ensure we don't remove one added by someone else. - cmd = '/sbin/ip route delete to local %s/32 dev eth0 proto %d' % ( - addr, GOOGLE_PROTO_ID) + cmd = '%s route delete to local %s/32 dev eth0 proto %d' % ( + self.ip_path, addr, GOOGLE_PROTO_ID) result = self.system.RunCommand(cmd.split()) self.IPCommandFailed(result, cmd) # Ignore return code diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-daemon-1.2.4/usr/share/google/google_daemon/desired_accounts.py new/google-daemon-1.2.7/usr/share/google/google_daemon/desired_accounts.py --- old/google-daemon-1.2.4/usr/share/google/google_daemon/desired_accounts.py 2015-03-10 02:28:44.000000000 +0100 +++ new/google-daemon-1.2.7/usr/share/google/google_daemon/desired_accounts.py 2015-07-11 02:13:30.000000000 +0200 @@ -87,7 +87,7 @@ expire_str) logging.error('Not expiring key.') return False - + # Expire the key if and only if we have exceeded the expiration timestamp. return (datetime.datetime.utcnow() > expire_time) @@ -170,7 +170,7 @@ return (attribute_value, etag) except urllib2.HTTPError as e: if e.code == 404: - # The attribute doesn't exist. Return None. + # The attribute doesn't exist. Return None. # No need to log a warning. return None # rethrow the exception since we don't know what it is. Let the @@ -231,6 +231,6 @@ logging.debug('Project sshKeys attribute not found.') # sshKeys doesn't exist for either project or instance. account_data = None - + self.attributes_etag = attributes_etag_cache return AccountDataToDictionary(account_data) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-daemon-1.2.4/usr/share/google/google_daemon/manage_accounts.py new/google-daemon-1.2.7/usr/share/google/google_daemon/manage_accounts.py --- old/google-daemon-1.2.4/usr/share/google/google_daemon/manage_accounts.py 2015-03-10 02:28:44.000000000 +0100 +++ new/google-daemon-1.2.7/usr/share/google/google_daemon/manage_accounts.py 2015-07-11 02:13:30.000000000 +0200 @@ -18,6 +18,7 @@ import logging import optparse import os +import os.path import sys @@ -40,21 +41,25 @@ def Main(accounts, desired_accounts, system, logger, log_handler, lock_file, lock_fname=None, single_pass=True, - daemon_mode=False, debug_mode=False): - + daemon_mode=False, force_mode=False, debug_mode=False): + if not log_handler: log_handler = system.MakeLoggingHandler( 'accounts-from-metadata', logging.handlers.SysLogHandler.LOG_AUTH) system.SetLoggingHandler(logger, log_handler) - + if debug_mode: system.EnableDebugLogging(logger) logging.debug('Running in Debug Mode') + if not force_mode and os.path.isfile('/usr/share/google/gcua'): + logging.error('Google Compute User Accounts is installed.') + sys.exit(1) + accounts_manager = AccountsManager( accounts, desired_accounts, system, lock_file, lock_fname, single_pass) - + if daemon_mode: manager_daemon = AccountsManagerDaemon(None, accounts_manager) manager_daemon.StartDaemon() @@ -71,10 +76,12 @@ parser.add_option('--interval', type='int', dest='interval') parser.add_option('--single-pass', dest='single_pass', action='store_true') parser.add_option('--no-single-pass', dest='single_pass', action='store_false') + parser.add_option('--force', dest='force', action='store_true') parser.add_option('--debug', dest='debug', action='store_true') parser.set_defaults(interval=60) parser.set_defaults(single_pass=False) parser.set_defaults(daemon=False) + parser.set_defaults(force=False) parser.set_defaults(debug=False) (options, args) = parser.parse_args() @@ -84,4 +91,4 @@ Main(Accounts(system_module=System()), DesiredAccounts(), System(), logging.getLogger(), None, LockFile(), None, options.single_pass, - options.daemon, options.debug) + options.daemon, options.force, options.debug) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-daemon-1.2.4/usr/share/google/google_daemon/manage_clock_sync.py new/google-daemon-1.2.7/usr/share/google/google_daemon/manage_clock_sync.py --- old/google-daemon-1.2.4/usr/share/google/google_daemon/manage_clock_sync.py 1970-01-01 01:00:00.000000000 +0100 +++ new/google-daemon-1.2.7/usr/share/google/google_daemon/manage_clock_sync.py 2015-07-11 02:13:30.000000000 +0200 @@ -0,0 +1,85 @@ +#!/usr/bin/python +# Copyright 2015 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Manages clock syncing after migration on GCE instances.""" + +import logging +import os +import sys + +def FixPath(): + parent_dir = os.path.dirname(os.path.realpath(sys.argv[0])) + if os.path.isdir(parent_dir): + sys.path.append(parent_dir) + + +FixPath() + +from utils import LockFile +from utils import System +from metadata_watcher import MetadataWatcher + + +LOCKFILE = '/var/lock/google-clock-sync.lock' + + +def HandleClockDriftToken(metadata_watcher, on_change): + """Watches for and responds to drift-token changes. + + Args: + metadata_watcher: a MetadataWatcher object. + on_change: a callable to call for any change. + """ + clock_drift_token_key = 'instance/virtual-clock/drift-token' + + def Handler(event): + on_change(event) + + metadata_watcher.WatchMetadataForever(clock_drift_token_key, + Handler, initial_value='') + + +def OnChange(event): + """Called when clock drift token changes. + + Args: + event: the new value of the drift token. + """ + system = System() + logging.info('Clock drift token has changed: %s', event) + logging.info('Syncing system time with hardware clock...') + result = system.RunCommand(['/sbin/hwclock', '--hctosys']) + if system.RunCommandFailed(result): + logging.error('Syncing system time failed.') + else: + logging.info('Synced system time with hardware clock.') + + +def Main(system=System(), logger=logging.getLogger(), log_handler=None, + lock_file=LockFile(), lock_fname=None): + if not log_handler: + log_handler = system.MakeLoggingHandler( + 'google-clock-sync', logging.handlers.SysLogHandler.LOG_SYSLOG) + system.SetLoggingHandler(logger, log_handler) + logging.info('Starting GCE clock sync') + + if not lock_fname: + lock_fname = LOCKFILE + watcher = MetadataWatcher() + lock_file.RunExclusively(lock_fname, HandleClockDriftToken(watcher, OnChange)) + + +if __name__ == '__main__': + Main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-daemon-1.2.4/usr/share/google/google_daemon/metadata_watcher.py new/google-daemon-1.2.7/usr/share/google/google_daemon/metadata_watcher.py --- old/google-daemon-1.2.4/usr/share/google/google_daemon/metadata_watcher.py 1970-01-01 01:00:00.000000000 +0100 +++ new/google-daemon-1.2.7/usr/share/google/google_daemon/metadata_watcher.py 2015-07-11 02:13:30.000000000 +0200 @@ -0,0 +1,97 @@ +#!/usr/bin/python +# Copyright 2015 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import httplib +import time +import urllib +import urllib2 + + +METADATA_URL = 'http://metadata.google.internal/computeMetadata/v1/' + + +class Error(Exception): + pass + + +class UnexpectedStatusException(Error): + pass + + +class MetadataWatcher(object): + """Watches for changing metadata.""" + + def __init__(self, httplib_module=httplib, time_module=time, + urllib_module=urllib, urllib2_module=urllib2): + self.httplib = httplib_module + self.time = time_module + self.urllib = urllib_module + self.urllib2 = urllib2_module + + def WatchMetadataForever(self, metadata_key, handler, initial_value=None): + """Watches for a change in the value of metadata. + + Args: + metadata_key: The key identifying which metadata to watch for changes. + handler: A callable to call when the metadata value changes. Will be passed + a single parameter, the new value of the metadata. + initial_value: The expected initial value for the metadata. The handler will + not be called on the initial metadata request unless the value differs + from this. + + Raises: + UnexpectedStatusException: If the http request is unsuccessful for an + unexpected reason. + """ + params = { + 'wait_for_change': 'true', + 'last_etag': 0, + } + + value = initial_value + while True: + # start a hanging-GET request for metadata key. + url = '{base_url}{key}?{params}'.format( + base_url=METADATA_URL, + key=metadata_key, + params=self.urllib.urlencode(params) + ) + req = self.urllib2.Request(url, headers={'Metadata-Flavor': 'Google'}) + + try: + response = self.urllib2.urlopen(req) + content = response.read() + status = response.getcode() + except self.urllib2.HTTPError as e: + content = None + status = e.code + + if status == self.httplib.SERVICE_UNAVAILABLE: + self.time.sleep(1) + continue + elif status == self.httplib.OK: + # Extract new metadata value and latest etag. + new_value = content + headers = response.info() + params['last_etag'] = headers['ETag'] + else: + raise UnexpectedStatusException(status) + + # If the metadata value changed, call the appropriate handler. + if value == initial_value: + value = new_value + elif value != new_value: + value = new_value + handler(value) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-daemon-1.2.4/usr/share/google/google_daemon/utils.py new/google-daemon-1.2.7/usr/share/google/google_daemon/utils.py --- old/google-daemon-1.2.4/usr/share/google/google_daemon/utils.py 2015-03-10 02:28:44.000000000 +0100 +++ new/google-daemon-1.2.7/usr/share/google/google_daemon/utils.py 2015-07-11 02:13:30.000000000 +0200 @@ -66,6 +66,9 @@ def CreateTempFile(self, delete=True): return tempfile.NamedTemporaryFile(delete=delete) + def DeleteFile(self, name): + return os.remove(name) + def UserAdd(self, user, groups): logging.info('Creating account %s', user)
