Merge lp:~javier.collado/utah/bug1037056 into lp:utah

Proposed by Javier Collado
Status: Merged
Merged at revision: 639
Proposed branch: lp:~javier.collado/utah/bug1037056
Merge into: lp:utah
Diff against target: 112 lines (+26/-15)
3 files modified
utah/provisioning/baremetal/cobbler.py (+3/-3)
utah/provisioning/provisioning.py (+21/-10)
utah/run.py (+2/-2)
To merge this branch: bzr merge lp:~javier.collado/utah/bug1037056
Reviewer Review Type Date Requested Status
Max Brustkern (community) Approve
Review via email: mp+119861@code.launchpad.net

Description of the change

- Updated Machine.run and SSHMixin.run to return (returncode, stdout, stderr) instead of just returncode.
- Added parsing of stderr output from gdebi to be able to detect a postinstall script failure
- Code will exit if that happens

After testing the code the output when a postinstall script error happens is:
INFO: Uploading /usr/share/utah/utah-client_0.4ubuntu46-rev644~precise1_all.deb from the host to /tmp on the machine
INFO: Running command through SSH: DEBIAN_FRONTEND=noninteractive gdebi -n -q /tmp/utah-client_0.4ubuntu46-rev644~precise1_all.deb
Exception: Failed to install client

The only thing that I don't really like yet is that the exception text is not written to the log file. I think that aside from the logger object in the machine we should have another logger object for the cases in which the machine might not exist so that every error message is written to the logs. Let me know if you agree and I'll open a bug for that.

To post a comment you must log in.
Revision history for this message
Max Brustkern (nuclearbob) wrote :

I think that's a good idea. More logging at this point is almost always going to be helpful.

Revision history for this message
Max Brustkern (nuclearbob) wrote :

Also, this looks to me like it covers what we need. I'm a little surprised we have that few things that call the run() method of a machine, but I guess that's the idea. I think I'll need to update my bootspeed stuff as well, but that's in a separate branch.

review: Approve
Revision history for this message
Javier Collado (javier.collado) wrote :

Thanks Max.

I'll create a bug to review the print statements and see where using a logger outside from the machine object makes sense.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'utah/provisioning/baremetal/cobbler.py'
2--- utah/provisioning/baremetal/cobbler.py 2012-08-03 21:44:39 +0000
3+++ utah/provisioning/baremetal/cobbler.py 2012-08-16 08:40:40 +0000
4@@ -144,9 +144,9 @@
5 retry(self.sshcheck, checktimeout, logmethod=self.logger.info)
6 self.provisioned = True
7 self.active = True
8- if (self.run([('[ "{uuid}" == '
9- + '"$(cat /etc/utah/uuid)" ]').format(uuid=self.uuid)])
10- != 0):
11+ uuid_check_command = ('[ "{uuid}" == "$(cat /etc/utah/uuid)" ]'
12+ .format(uuid=self.uuid))
13+ if self.run(uuid_check_command)[0] != 0:
14 self.provisioned = False
15 raise UTAHProvisioningException(
16 'Installed UUID differs from CobblerMachine UUID; '
17
18=== modified file 'utah/provisioning/provisioning.py'
19--- utah/provisioning/provisioning.py 2012-08-15 09:35:14 +0000
20+++ utah/provisioning/provisioning.py 2012-08-16 08:40:40 +0000
21@@ -16,6 +16,7 @@
22 import urllib
23 import uuid
24 import paramiko
25+import re
26
27
28 import apt.cache
29@@ -272,9 +273,11 @@
30
31 remote_clientdeb = os.path.join(tmppath, os.path.basename(clientdeb))
32 install_command = ('DEBIAN_FRONTEND=noninteractive '
33- 'gdebi -n {}'
34+ 'gdebi -n -q {}'
35 .format(remote_clientdeb))
36- if self.run(install_command, root=True) != 0:
37+ returncode, stdout, stderr = self.run(install_command, root=True)
38+ if (returncode != 0
39+ or re.search(r'script returned error exit status \d+', stderr)):
40 raise UTAHProvisioningException('Failed to install client\n')
41
42 def _provision(self):
43@@ -364,8 +367,8 @@
44
45 def run(self, command, quiet=None, root=False, timeout=None):
46 """
47- Run a command on the machine and return the output status of that
48- command.
49+ Run a command on the machine and return a three element tuple:
50+ (returncode, stdout, stder)
51 If quiet is True, all output other than the output of the command
52 should be suppressed (i.e., no output from helper programs such as
53 ssh.)
54@@ -463,8 +466,8 @@
55
56 self.logger.debug('Opening SSH session')
57 channel = self.ssh_client.get_transport().open_session()
58+
59 self.logger.info('Running command through SSH: ' + commandstring)
60- channel.makefile('wb')
61 stdout = channel.makefile('rb')
62 stderr = channel.makefile_stderr('rb')
63 if timeout is None:
64@@ -472,19 +475,27 @@
65 else:
66 utah.timeout.timeout(timeout, channel.exec_command, commandstring)
67 retval = channel.recv_exit_status()
68+
69 self.logger.debug('Closing SSH connection')
70 self.ssh_client.close()
71+
72+ log_message = 'Return code: {}'.format(retval)
73 if retval == 0:
74- self.logger.debug('Return code: {}'.format(retval))
75+ self.logger.debug(log_message)
76 else:
77- self.logger.warning('Return code: {}'.format(retval))
78+ self.logger.warning(log_message)
79+
80 self.logger.debug('Standard output follows:')
81- for line in stdout:
82+ stdout_lines = stdout.readlines()
83+ for line in stdout_lines:
84 self.logger.debug(line.strip())
85+
86 self.logger.debug('Standard error follows:')
87- for line in stderr:
88+ stderr_lines = stderr.readlines()
89+ for line in stderr_lines:
90 self.logger.debug(line.strip())
91- return retval
92+
93+ return retval, ''.join(stdout_lines), ''.join(stderr_lines)
94
95 def uploadfiles(self, files, target=os.path.normpath('/tmp/')):
96 """
97
98=== modified file 'utah/run.py'
99--- utah/run.py 2012-08-14 21:10:29 +0000
100+++ utah/run.py 2012-08-16 08:40:40 +0000
101@@ -42,9 +42,9 @@
102 machine.uploadfiles([locallist], os.path.normpath('/tmp'))
103 options = (' -r /tmp/' + os.path.basename(locallist)
104 + ' -o ' + remotelog)
105+ utah_command = 'utah' + extraopts + options
106 try:
107- returncode = machine.run('utah' + extraopts + options,
108- root=True)
109+ returncode = machine.run(utah_command, root=True)[0]
110 if returncode != 0:
111 machine.logger.error('utah failed with return code: {}\n'
112 .format(returncode))

Subscribers

People subscribed via source and target branches