Merge "p/Separate-armband-repo no longer needed."
[armband.git] / patches / opnfv-fuel / 0021-common.py-allow-specifying-number-of-attempts-in-exe.patch
1 From: Josep Puigdemont <josep.puigdemont@enea.com>
2 Date: Fri, 6 May 2016 03:28:26 +0200
3 Subject: [PATCH] common.py: allow specifying number of attempts in exec_cmd
4
5 Some commands executed by exec_cmd may fail because of a temporary
6 cause, and it may be desirable to retry the same command several times
7 until it succeeds. One example of this are the ipmitool commands, which
8 may fail temorarily on some targets if they get too many requests
9 simultaneously.
10
11 In this patch two new optional parameters are introduced to the function
12 signature, which do not break backward compatibility:
13   attempts: which indicates how many times the command should be run if
14             it returns a non-zero value*, and defaults to 1 (as today).
15   delay:    which indicates the delay in seconds between attempts, and
16             defaults to 5 seconds.
17   verbose:  It will print the remaining attempts left for the current
18             command if set to True.
19
20 * It may be desirable to add yet another parameter to indicate what
21   return value should be considered an error, but zero for now seems a
22   reasonable default
23
24 Signed-off-by: Josep Puigdemont <josep.puigdemont@enea.com>
25 ---
26  deploy/common.py | 24 +++++++++++++++++-------
27  1 file changed, 17 insertions(+), 7 deletions(-)
28
29 diff --git a/deploy/common.py b/deploy/common.py
30 index 41b4e27..3cd3e0e 100644
31 --- a/deploy/common.py
32 +++ b/deploy/common.py
33 @@ -16,6 +16,7 @@ import argparse
34  import shutil
35  import stat
36  import errno
37 +import time
38  
39  N = {'id': 0, 'status': 1, 'name': 2, 'cluster': 3, 'ip': 4, 'mac': 5,
40       'roles': 6, 'pending_roles': 7, 'online': 8, 'group_id': 9}
41 @@ -37,13 +38,22 @@ out_handler.setFormatter(formatter)
42  LOG.addHandler(out_handler)
43  os.chmod(LOGFILE, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
44  
45 -def exec_cmd(cmd, check=True):
46 -    process = subprocess.Popen(cmd,
47 -                               stdout=subprocess.PIPE,
48 -                               stderr=subprocess.PIPE,
49 -                               shell=True)
50 -    (response, stderr) = process.communicate()
51 -    return_code = process.returncode
52 +def exec_cmd(cmd, check=True, attempts=1, delay=5, verbose=False):
53 +    # a negative value means forever
54 +    while attempts != 0:
55 +        attempts = attempts - 1
56 +        process = subprocess.Popen(cmd,
57 +                                   stdout=subprocess.PIPE,
58 +                                   stderr=subprocess.PIPE,
59 +                                   shell=True)
60 +        (response, stderr) = process.communicate()
61 +        return_code = process.returncode
62 +        if return_code == 0 or attempts == 0:
63 +            break
64 +        time.sleep(delay)
65 +        if verbose:
66 +            log('%d attempts left: %s' % (attempts, cmd))
67 +
68      response = response.strip()
69      if check:
70          if return_code > 0: