Merge lp:~wingc/cloud-init/fix-chef-omnibus-install into lp:~cloud-init-dev/cloud-init/trunk

Proposed by Christopher Allen Wing on 2013-05-20
Status: Merged
Merged at revision: 819
Proposed branch: lp:~wingc/cloud-init/fix-chef-omnibus-install
Merge into: lp:~cloud-init-dev/cloud-init/trunk
Diff against target: 12 lines (+1/-1)
1 file modified
cloudinit/config/cc_chef.py (+1/-1)
To merge this branch: bzr merge lp:~wingc/cloud-init/fix-chef-omnibus-install
Reviewer Review Type Date Requested Status
Scott Moser 2013-05-20 Pending
Review via email: mp+164810@code.launchpad.net

Description of the change

cloud-init fails to install the Chef client via 'omnibus' installer, support for which was added in the following change:

http://bazaar.launchpad.net/~cloud-init-dev/cloud-init/trunk/revision/749

--- cloudinit/config/cc_chef.py ---
...
        elif install_type == 'omnibus':
            url = util.get_cfg_option_str(chef_cfg, "omnibus_url", OMNIBUS_URL)
            content = url_helper.readurl(url=url, retries=5)
            with util.tempdir() as tmpd:
                # use tmpd over tmpfile to avoid 'Text file busy' on execute
                tmpf = "%s/chef-omnibus-install" % tmpd
                util.write_file(tmpf, content, mode=0700)
                util.subp([tmpf], capture=False)
...

Here 'content' is a UrlRequest object, but util.write_file() dies with an exception due to a debug statement:

--- cloudinit/util.py ---
...
def write_file(filename, content, mode=0644, omode="wb"):
    """
    Writes a file with the given content and sets the file mode as specified.
    Resotres the SELinux context if possible.

    @param filename: The full path of the file to write.
    @param content: The content to write to the file.
    @param mode: The filesystem mode to set on the file.
    @param omode: The open mode used when opening the file (r, rb, a, etc.)
    """
    ensure_dir(os.path.dirname(filename))
    LOG.debug("Writing to %s - %s: [%s] %s bytes",
               filename, omode, mode, len(content))
...

The UrlResponse class does not expose a method for len():

#
# example failure log from a CentOS 6.x host, with cloud-init 0.7.2 installed from RPM
#
2013-05-20 21:35:21,247 - util.py[WARNING]: Running chef (<module 'cloudinit.config.cc_chef' from '/usr/lib/python2.6/site-packages/cloudinit/config/cc_chef.pyc'>) failed
2013-05-20 21:35:21,247 - util.py[DEBUG]: Running chef (<module 'cloudinit.config.cc_chef' from '/usr/lib/python2.6/site-packages/cloudinit/config/cc_chef.pyc'>) failed
Traceback (most recent call last):
  File "/usr/lib/python2.6/site-packages/cloudinit/stages.py", line 547, in _run_modules
    cc.run(run_name, mod.handle, func_args, freq=freq)
  File "/usr/lib/python2.6/site-packages/cloudinit/cloud.py", line 63, in run
    return self._runners.run(name, functor, args, freq, clear_on_fail)
  File "/usr/lib/python2.6/site-packages/cloudinit/helpers.py", line 196, in run
    results = functor(*args)
  File "/usr/lib/python2.6/site-packages/cloudinit/config/cc_chef.py", line 114, in handle
    util.subp([tmpf], capture=False)
  File "/usr/lib64/python2.6/contextlib.py", line 34, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/lib/python2.6/site-packages/cloudinit/util.py", line 576, in tempdir
    yield tdir
  File "/usr/lib/python2.6/site-packages/cloudinit/config/cc_chef.py", line 113, in handle
    util.write_file(tmpf, content, mode=0700)
  File "/usr/lib/python2.6/site-packages/cloudinit/util.py", line 1380, in write_file
    filename, omode, mode, len(content))
TypeError: object of type 'UrlResponse' has no len()

My proposed fix is to convert the UrlReponse into a plain string and pass that to util.write_file(), which makes things work as expected.

To post a comment you must log in.
Scott Moser (smoser) wrote :

Christopher,
  Thanks for catching the bug, debugging and submitting a fix.

  I've opened bug 1182265. Bugs are required to get anything SRU'd into Ubuntu and this would be good to SRU into 13.04.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cloudinit/config/cc_chef.py'
2--- cloudinit/config/cc_chef.py 2012-12-12 15:39:43 +0000
3+++ cloudinit/config/cc_chef.py 2013-05-20 21:44:25 +0000
4@@ -110,7 +110,7 @@
5 with util.tempdir() as tmpd:
6 # use tmpd over tmpfile to avoid 'Text file busy' on execute
7 tmpf = "%s/chef-omnibus-install" % tmpd
8- util.write_file(tmpf, content, mode=0700)
9+ util.write_file(tmpf, str(content), mode=0700)
10 util.subp([tmpf], capture=False)
11 else:
12 log.warn("Unknown chef install type %s", install_type)