summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorScott Moser <smoser@ubuntu.com>2012-07-06 17:19:37 -0400
committerScott Moser <smoser@ubuntu.com>2012-07-06 17:19:37 -0400
commitb2a21ed1dc682a262d55a4202c6b9606496d211f (patch)
tree37f1c4acd3ea891c1e7a60bcd9dd8aa8c7ca1e0c /packages
parent646384ccd6f1707b2712d9bcd683ae877f1903bd (diff)
parente7095a1b19e849c530650d2d71edf8b28d30f1d1 (diff)
downloadvyos-cloud-init-b2a21ed1dc682a262d55a4202c6b9606496d211f.tar.gz
vyos-cloud-init-b2a21ed1dc682a262d55a4202c6b9606496d211f.zip
Merge rework branch in [Joshua Harlow]
- unified binary that activates the various stages - Now using argparse + subcommands to specify the various CLI options - a stage module that clearly separates the stages of the different components (also described how they are used and in what order in the new unified binary) - user_data is now a module that just does user data processing while the actual activation and 'handling' of the processed user data is done via a separate set of files (and modules) with the main 'init' stage being the controller of this - creation of boot_hook, cloud_config, shell_script, upstart_job version 2 modules (with classes that perform there functionality) instead of those having functionality that is attached to the cloudinit object (which reduces reuse and limits future functionality, and makes testing harder) - removal of global config that defined paths, shared config, now this is via objects making unit testing testing and global side-effects a non issue - creation of a 'helpers.py' - this contains an abstraction for the 'lock' like objects that the various module/handler running stages use to avoid re-running a given module/handler for a given frequency. this makes it separated from the actual usage of that object (thus helpful for testing and clear lines usage and how the actual job is accomplished) - a common 'runner' class is the main entrypoint using these locks to run function objects passed in (along with there arguments) and there frequency - add in a 'paths' object that provides access to the previously global and/or config based paths (thus providing a single entrypoint object/type that provides path information) - this also adds in the ability to change the path when constructing that path 'object' and adding in additional config that can be used to alter the root paths of 'joins' (useful for testing or possibly useful in chroots?) - config options now avaiable that can alter the 'write_root' and the 'read_root' when backing code uses the paths join() function - add a config parser subclass that will automatically add unknown sections and return default values (instead of throwing exceptions for these cases) - a new config merging class that will be the central object that knows how to do the common configuration merging from the various configuration sources. The order is the following: - cli config files override environment config files which override instance configs which override datasource configs which override base configuration which overrides default configuration. - remove the passing around of the 'cloudinit' object as a 'cloud' variable and instead pass around an 'interface' object that can be given to modules and handlers as there cloud access layer while the backing of that object can be varied (good for abstraction and testing) - use a single set of functions to do importing of modules - add a function in which will search for a given set of module names with a given set of attributes and return those which are found - refactor logging so that instead of using a single top level 'log' that instead each component/module can use its own logger (if desired), this should be backwards compatible with handlers and config modules that used the passed in logger (its still passed in) - ensure that all places where exception are caught and where applicable that the util logexc() is called, so that no exceptions that may occur are dropped without first being logged (where it makes sense for this to happen) - add a 'requires' file that lists cloud-init dependencies - applying it in package creation (bdeb and brpm) as well as using it in the modified setup.py to ensure dependencies are installed when using that method of packaging - add a 'version.py' that lists the active version (in code) so that code inside cloud-init can report the version in messaging and other config files - cleanup of subprocess usage so that all subprocess calls go through the subp() utility method, which now has an exception type that will provide detailed information on python 2.6 and 2.7 - forced all code loading, moving, chmod, writing files and other system level actions to go through standard set of util functions, this greatly helps in debugging and determining exactly which system actions cloud-init is performing - switching out the templating engine cheetah for tempita since tempita has no external dependencies (minus python) while cheetah has many dependencies which makes it more difficult to adopt cloud-init in distros that may not have those dependencies - adjust url fetching and url trying to go through a single function that reads urls in the new 'url helper' file, this helps in tracing, debugging and knowing which urls are being called and/or posted to from with-in cloud-init code - add in the sending of a 'User-Agent' header for all urls fetched that do not provide there own header mapping, derive this user-agent from the following template, 'Cloud-Init/{version}' where the version is the cloud-init version number - using prettytable for netinfo 'debug' printing since it provides a standard and defined output that should be easier to parse than a custom format - add a set of distro specific classes, that handle distro specific actions that modules and or handler code can use as needed, this is organized into a base abstract class with child classes that implement the shared functionality. config determines exactly which subclass to load, so it can be easily extended as needed. - current functionality - network interface config file writing - hostname setting/updating - locale/timezone/ setting - updating of /etc/hosts (with templates or generically) - package commands (ie installing, removing)/mirror finding - interface up/down activating - implemented a debian + ubuntu subclass - implemented a redhat + fedora subclass - adjust the root 'cloud.cfg' file to now have distrobution/path specific configuration values in it. these special configs are merged as the normal config is, but the system level config is not passed into modules/handlers - modules/handlers must go through the path and distro object instead - have the cloudstack datasource test the url before calling into boto to avoid the long wait for boto to finish retrying and finally fail when the gateway meta-data address is unavailable - add a simple mock ec2 meta-data python based http server that can serve a very simple set of ec2 meta-data back to callers - useful for testing or for understanding what the ec2 meta-data service can provide in terms of data or functionality - for ssh key and authorized key file parsing add in classes and util functions that maintain the state of individual lines, allowing for a clearer separation of parsing and modification (useful for testing and tracing) - add a set of 'base' init.d scripts that can be used on systems that do not have full upstart or systemd support (or support that does not match the standard fedora/ubuntu implementation) - currently these are being tested on RHEL 6.2 - separate the datasources into there own subdirectory (instead of being a top-level item), this matches how config 'modules' and user-data 'handlers' are also in there own subdirectory (thus helping new developers and others understand the code layout in a quicker manner) - add the building of rpms based off a new cli tool and template 'spec' file that will templatize and perform the necessary commands to create a source and binary package to be used with a cloud-init install on a 'rpm' supporting system - uses the new standard set of requires and converts those pypi requirements into a local set of package requirments (that are known to exist on RHEL systems but should also exist on fedora systems) - adjust the bdeb builder to be a python script (instead of a shell script) and make its 'control' file a template that takes in the standard set of pypi dependencies and uses a local mapping (known to work on ubuntu) to create the packages set of dependencies (that should also work on ubuntu-like systems) - pythonify a large set of various pieces of code - remove wrapping return statements with () when it has no effect - upper case all constants used - correctly 'case' class and method names (where applicable) - use os.path.join (and similar commands) instead of custom path creation - use 'is None' instead of the frowned upon '== None' which picks up a large set of 'true' cases than is typically desired (ie for objects that have there own equality) - use context managers on locks, tempdir, chdir, file, selinux, umask, unmounting commands so that these actions do not have to be closed and/or cleaned up manually in finally blocks, which is typically not done and will eventually be a bug in the future - use the 'abc' module for abstract classes base where possible - applied in the datasource root class, the distro root class, and the user-data v2 root class - when loading yaml, check that the 'root' type matches a predefined set of valid types (typically just 'dict') and throw a type error if a mismatch occurs, this seems to be a good idea to do when loading user config files - when forking a long running task (ie resizing a filesytem) use a new util function that will fork and then call a callback, instead of having to implement all that code in a non-shared location (thus allowing it to be used by others in the future) - when writing out filenames, go through a util function that will attempt to ensure that the given filename is 'filesystem' safe by replacing '/' with '_' and removing characters which do not match a given whitelist of allowed filename characters - for the varying usages of the 'blkid' command make a function in the util module that can be used as the single point of entry for interaction with that command (and its results) instead of having X separate implementations - place the rfc 8222 time formatting and uptime repeated pieces of code in the util module as a set of function with the name 'time_rfc2822'/'uptime' - separate the pylint+pep8 calling from one tool into two indivudal tools so that they can be called independently, add make file sections that can be used to call these independently - remove the support for the old style config that was previously located in '/etc/ec2-init/ec2-config.cfg', no longer supported! - instead of using a altered config parser that added its own 'dummy' section on in the 'mcollective' module, use configobj which handles the parsing of config without sections better (and it also maintains comments instead of removing them) - use the new defaulting config parser (that will not raise errors on sections that do not exist or return errors when values are fetched that do not exist) in the 'puppet' module - for config 'modules' add in the ability for the module to provide a list of distro names which it is known to work with, if when ran and the distro being used name does not match one of those in this list, a warning will be written out saying that this module may not work correctly on this distrobution - for all dynamically imported modules ensure that they are fixed up before they are used by ensuring that they have certain attributes, if they do not have those attributes they will be set to a sensible set of defaults instead - adjust all 'config' modules and handlers to use the adjusted util functions and the new distro objects where applicable so that those pieces of code can benefit from the unified and enhanced functionality being provided in that util module - fix a potential bug whereby when a #includeonce was encountered it would enable checking of urls against a cache, if later a #include was encountered it would continue checking against that cache, instead of refetching (which would likely be the expected case) - add a openstack/nova based pep8 extension utility ('hacking.py') that allows for custom checks (along with the standard pep8 checks) to occur when running 'make pep8' and its derivatives
Diffstat (limited to 'packages')
-rwxr-xr-xpackages/bddeb172
-rwxr-xr-xpackages/brpm216
-rw-r--r--packages/debian/changelog5
-rw-r--r--packages/debian/compat1
-rw-r--r--packages/debian/control29
-rw-r--r--packages/debian/copyright51
-rw-r--r--packages/debian/dirs5
-rw-r--r--packages/debian/pycompat1
-rwxr-xr-xpackages/debian/rules17
-rwxr-xr-xpackages/make-dist-tarball25
-rwxr-xr-xpackages/make-tarball89
-rw-r--r--packages/redhat/cloud-init.spec183
12 files changed, 794 insertions, 0 deletions
diff --git a/packages/bddeb b/packages/bddeb
new file mode 100755
index 00000000..10ad08b3
--- /dev/null
+++ b/packages/bddeb
@@ -0,0 +1,172 @@
+#!/usr/bin/python
+
+import os
+import shutil
+import sys
+import glob
+
+# Use the util functions from cloudinit
+possible_topdir = os.path.normpath(os.path.join(os.path.abspath(
+ sys.argv[0]), os.pardir, os.pardir))
+if os.path.exists(os.path.join(possible_topdir, "cloudinit", "__init__.py")):
+ sys.path.insert(0, possible_topdir)
+
+from cloudinit import templater
+from cloudinit import util
+
+import argparse
+
+# Package names that will showup in requires to what we can actually
+# use in our debian 'control' file
+PKG_MP = {
+ 'tempita': 'python-tempita',
+ 'boto': 'python-boto',
+ 'configobj': 'python-configobj',
+ 'oauth': 'python-oauth',
+ 'yaml': 'python-yaml',
+ 'prettytable': 'python-prettytable',
+ 'argparse': 'python-argparse',
+}
+
+
+def write_debian_folder(root, version, revno, init_sys):
+ deb_dir = util.abs_join(root, 'debian')
+ os.makedirs(deb_dir)
+
+ # Fill in the change log template
+ templater.render_to_file(util.abs_join('debian', 'changelog'),
+ util.abs_join(deb_dir, 'changelog'),
+ params={
+ 'version': version,
+ 'revision': revno,
+ })
+
+ # Write out the control file template
+ cmd = [sys.executable,
+ util.abs_join(os.pardir, 'tools', 'read-dependencies')]
+ (stdout, _stderr) = util.subp(cmd)
+
+ # Map to known packages
+ pkgs = [p.lower().strip() for p in stdout.splitlines()]
+ requires = []
+ for p in pkgs:
+ tgt_pkg = None
+ for name in PKG_MP.keys():
+ if p.find(name) != -1:
+ tgt_pkg = PKG_MP.get(name)
+ break
+ if not tgt_pkg:
+ raise RuntimeError(("Do not know how to translate %s to "
+ " a known package") % (p))
+ else:
+ requires.append(tgt_pkg)
+
+ templater.render_to_file(util.abs_join('debian', 'control'),
+ util.abs_join(deb_dir, 'control'),
+ params={'requires': requires})
+
+ templater.render_to_file(util.abs_join('debian', 'rules'),
+ util.abs_join(deb_dir, 'rules'),
+ params={'init_sys': init_sys})
+
+ # Just copy the following directly
+ for base_fn in ['dirs', 'copyright', 'compat', 'pycompat']:
+ shutil.copy(util.abs_join('debian', base_fn),
+ util.abs_join(deb_dir, base_fn))
+
+
+def main():
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-n", "--no-sign", dest="sign",
+ help=("attempt to sign "
+ "the package (default: %(default)s)"),
+ default=True,
+ action='store_false')
+ parser.add_argument("-v", "--verbose", dest="verbose",
+ help=("run verbosely"
+ " (default: %(default)s)"),
+ default=False,
+ action='store_true')
+ parser.add_argument("-b", "--boot", dest="boot",
+ help="select boot type (default: %(default)s)",
+ metavar="TYPE", default='upstart',
+ choices=('upstart', 'upstart-local'))
+ args = parser.parse_args()
+
+ capture = True
+ if args.verbose:
+ capture = False
+
+ with util.tempdir() as tdir:
+
+ cmd = [sys.executable,
+ util.abs_join(os.pardir, 'tools', 'read-version')]
+ (sysout, _stderr) = util.subp(cmd)
+ version = sysout.strip()
+
+ cmd = ['bzr', 'revno']
+ (sysout, _stderr) = util.subp(cmd)
+ revno = sysout.strip()
+
+ # This is really only a temporary archive
+ # since we will extract it then add in the debian
+ # folder, then re-archive it for debian happiness
+ print("Creating a temporary tarball using the 'make-tarball' helper")
+ cmd = [sys.executable,
+ util.abs_join(os.getcwd(), 'make-tarball')]
+ (sysout, _stderr) = util.subp(cmd)
+ arch_fn = sysout.strip()
+ tmp_arch_fn = util.abs_join(tdir, os.path.basename(arch_fn))
+ shutil.move(arch_fn, tmp_arch_fn)
+
+ print("Extracting temporary tarball %r" % (tmp_arch_fn))
+ cmd = ['tar', '-xvzf', tmp_arch_fn, '-C', tdir]
+ util.subp(cmd, capture=capture)
+ base_name = os.path.basename(arch_fn)[:-len(".tar.gz")]
+ shutil.move(util.abs_join(tdir, base_name),
+ util.abs_join(tdir, 'cloud-init'))
+
+ print("Creating a debian/ folder in %r" %
+ (util.abs_join(tdir, 'cloud-init')))
+ write_debian_folder(util.abs_join(tdir, 'cloud-init'),
+ version, revno, args.boot)
+
+ # The naming here seems to follow some debian standard
+ # so it will whine if it is changed...
+ tar_fn = "cloud-init_%s~%s.orig.tar.gz" % (version, revno)
+ print("Archiving that new folder into %r" % (tar_fn))
+ cmd = ['tar', '-czvf',
+ util.abs_join(tdir, tar_fn),
+ '-C', util.abs_join(tdir, 'cloud-init')]
+ cmd.extend(os.listdir(util.abs_join(tdir, 'cloud-init')))
+ util.subp(cmd, capture=capture)
+ shutil.copy(util.abs_join(tdir, tar_fn), tar_fn)
+ print("Wrote out archive %r" % (util.abs_join(tar_fn)))
+
+ print("Running 'debuild' in %r" % (util.abs_join(tdir, 'cloud-init')))
+ with util.chdir(util.abs_join(tdir, 'cloud-init')):
+ cmd = ['debuild']
+ if not args.sign:
+ cmd.extend(['-us', '-uc'])
+ util.subp(cmd, capture=capture)
+
+ globs = []
+ globs.extend(glob.glob("%s/*.deb" %
+ (os.path.join(tdir))))
+ link_fn = os.path.join(os.getcwd(), 'cloud-init_all.deb')
+ for fn in globs:
+ base_fn = os.path.basename(fn)
+ shutil.move(fn, base_fn)
+ print("Wrote out debian package %r" % (base_fn))
+ if fn.endswith('_all.deb'):
+ # Add in the local link
+ util.del_file(link_fn)
+ os.symlink(base_fn, link_fn)
+ print("Linked %r to %r" % (base_fn, link_fn))
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/packages/brpm b/packages/brpm
new file mode 100755
index 00000000..1d05bd2a
--- /dev/null
+++ b/packages/brpm
@@ -0,0 +1,216 @@
+#!/usr/bin/python
+
+import contextlib
+import glob
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+import re
+
+import argparse
+
+# Use the util functions from cloudinit
+possible_topdir = os.path.normpath(os.path.join(os.path.abspath(
+ sys.argv[0]), os.pardir, os.pardir))
+if os.path.exists(os.path.join(possible_topdir, "cloudinit", "__init__.py")):
+ sys.path.insert(0, possible_topdir)
+
+from cloudinit import templater
+from cloudinit import util
+
+from datetime import datetime
+
+
+# Mapping of expected packages to there full name...
+PKG_MP = {
+ 'boto': 'python-boto',
+ 'tempita': 'python-tempita',
+ 'prettytable': 'python-prettytable',
+ 'oauth': 'python-oauth',
+ 'configobj': 'python-configobj',
+ 'yaml': 'PyYAML',
+ 'argparse': 'python-argparse'
+}
+
+
+def get_log_header(version):
+ # Try to find the version in the tags output
+ cmd = ['bzr', 'tags']
+ (stdout, _stderr) = util.subp(cmd)
+ a_rev = None
+ for t in stdout.splitlines():
+ ver, rev = t.split(None)
+ if ver == version:
+ a_rev = rev
+ break
+ if not a_rev:
+ return format_change_line(datetime.now(),
+ '??', version)
+
+ # Extract who made that tag as the header
+ cmd = ['bzr', 'log', '-r%s' % (a_rev), '--timezone=utc']
+ (stdout, _stderr) = util.subp(cmd)
+ kvs = {
+ 'comment': version,
+ }
+
+ for line in stdout.splitlines():
+ if line.startswith('committer:'):
+ kvs['who'] = line[len('committer:'):].strip()
+ if line.startswith('timestamp:'):
+ ts = line[len('timestamp:'):]
+ ts = ts.strip()
+ # http://bugs.python.org/issue6641
+ ts = ts.replace("+0000", '').strip()
+ ds = datetime.strptime(ts, '%a %Y-%m-%d %H:%M:%S')
+ kvs['ds'] = ds
+
+ return format_change_line(**kvs)
+
+
+def format_change_line(ds, who, comment=None):
+ # Rpmbuild seems to be pretty strict about the date format
+ d = ds.strftime("%a %b %d %Y")
+ d += " - %s" % (who)
+ if comment:
+ d += " - %s" % (comment)
+ return "* %s" % (d)
+
+
+def generate_spec_contents(args, tmpl_fn):
+
+ # Figure out the version and revno
+ cmd = [sys.executable,
+ util.abs_join(os.pardir, 'tools', 'read-version')]
+ (stdout, _stderr) = util.subp(cmd)
+ version = stdout.strip()
+
+ cmd = ['bzr', 'revno']
+ (stdout, _stderr) = util.subp(cmd)
+ revno = stdout.strip()
+
+ # Tmpl params
+ subs = {}
+ subs['version'] = version
+ subs['revno'] = revno
+ subs['release'] = revno
+ subs['archive_name'] = '%{name}-%{version}-' + revno + '.tar.gz'
+ subs['bd_requires'] = ['python-devel', 'python-setuptools']
+
+ cmd = [sys.executable,
+ util.abs_join(os.pardir, 'tools', 'read-dependencies')]
+ (stdout, _stderr) = util.subp(cmd)
+
+ # Map to known packages
+ pkgs = [p.lower().strip() for p in stdout.splitlines()]
+
+ # Map to known packages
+ requires = []
+ for p in pkgs:
+ tgt_pkg = None
+ for name in PKG_MP.keys():
+ if p.find(name) != -1:
+ tgt_pkg = PKG_MP.get(name)
+ break
+ if not tgt_pkg:
+ raise RuntimeError(("Do not know how to translate %s to "
+ " a known package") % (p))
+ else:
+ requires.append(tgt_pkg)
+ subs['requires'] = requires
+
+ # Format a nice changelog (as best as we can)
+ changelog = util.load_file(util.abs_join(os.pardir, 'ChangeLog'))
+ changelog_lines = []
+ for line in changelog.splitlines():
+ if not line.strip():
+ continue
+ if re.match(r"^\s*[\d][.][\d][.][\d]:\s*", line):
+ line = line.strip(":")
+ header = get_log_header(line)
+ changelog_lines.append(header)
+ else:
+ changelog_lines.append(line)
+ subs['changelog'] = "\n".join(changelog_lines)
+
+ if args.boot == 'initd':
+ subs['init_d'] = True
+ subs['init_d_local'] = False
+ elif args.boot == 'initd-local':
+ subs['init_d'] = True
+ subs['init_d_local'] = True
+ else:
+ subs['init_d'] = False
+ subs['init_d_local'] = False
+
+ if args.boot == 'systemd':
+ subs['systemd'] = True
+ else:
+ subs['systemd'] = False
+
+ subs['init_sys'] = args.boot
+ return templater.render_from_file(tmpl_fn, params=subs)
+
+
+def main():
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-b", "--boot", dest="boot",
+ help="select boot type (default: %(default)s)",
+ metavar="TYPE", default='initd',
+ choices=('initd', 'systemd', 'initd-local'))
+ parser.add_argument("-v", "--verbose", dest="verbose",
+ help=("run verbosely"
+ " (default: %(default)s)"),
+ default=False,
+ action='store_true')
+ args = parser.parse_args()
+ capture = True
+ if args.verbose:
+ capture = False
+
+ # Clean out the root dir and make sure the dirs we want are in place
+ root_dir = os.path.expanduser("~/rpmbuild")
+ if os.path.isdir(root_dir):
+ shutil.rmtree(root_dir)
+ arc_dir = util.abs_join(root_dir, 'SOURCES')
+ util.ensure_dirs([root_dir, arc_dir])
+
+ # Archive the code
+ cmd = [sys.executable,
+ util.abs_join(os.getcwd(), 'make-tarball')]
+ (stdout, _stderr) = util.subp(cmd)
+ archive_fn = stdout.strip()
+ real_archive_fn = os.path.join(arc_dir, os.path.basename(archive_fn))
+ shutil.move(archive_fn, real_archive_fn)
+
+ # Form the spec file to be used
+ tmpl_fn = util.abs_join(os.getcwd(), 'redhat', 'cloud-init.spec')
+ contents = generate_spec_contents(args, tmpl_fn)
+ spec_fn = os.path.join(root_dir, 'cloud-init.spec')
+ util.write_file(spec_fn, contents)
+
+ # Now build it!
+ cmd = ['rpmbuild', '-ba', spec_fn]
+ util.subp(cmd, capture=capture)
+
+ # Copy the items built to our local dir
+ globs = []
+ globs.extend(glob.glob("%s/*.rpm" %
+ (os.path.join(root_dir, 'RPMS', 'noarch'))))
+ globs.extend(glob.glob("%s/*.rpm" %
+ (os.path.join(root_dir, 'RPMS'))))
+ globs.extend(glob.glob("%s/*.rpm" %
+ (os.path.join(root_dir, 'SRPMS'))))
+ for rpm_fn in globs:
+ tgt_fn = util.abs_join(os.getcwd(), os.path.basename(rpm_fn))
+ shutil.move(rpm_fn, tgt_fn)
+ print(tgt_fn)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/packages/debian/changelog b/packages/debian/changelog
new file mode 100644
index 00000000..ac5bcf98
--- /dev/null
+++ b/packages/debian/changelog
@@ -0,0 +1,5 @@
+cloud-init ({{version}}~{{revision}}-1) UNRELEASED; urgency=low
+
+ * build
+
+ -- Scott Moser <smoser@ubuntu.com> Fri, 16 Dec 2011 11:50:25 -0500
diff --git a/packages/debian/compat b/packages/debian/compat
new file mode 100644
index 00000000..7ed6ff82
--- /dev/null
+++ b/packages/debian/compat
@@ -0,0 +1 @@
+5
diff --git a/packages/debian/control b/packages/debian/control
new file mode 100644
index 00000000..e00901af
--- /dev/null
+++ b/packages/debian/control
@@ -0,0 +1,29 @@
+Source: cloud-init
+Section: admin
+Priority: extra
+Maintainer: Scott Moser <smoser@ubuntu.com>
+Build-Depends: cdbs,
+ debhelper (>= 5.0.38),
+ python (>= 2.6.6-3~),
+ python-nose,
+ pyflakes,
+ pylint,
+ python-mocker,
+XS-Python-Version: all
+Standards-Version: 3.9.3
+
+Package: cloud-init
+Architecture: all
+Depends: cloud-utils,
+ procps,
+ python,
+{{for r in requires}}
+ {{r}},
+{{endfor}}
+ python-software-properties,
+ ${misc:Depends},
+ ${python:Depends}
+XB-Python-Version: ${python:Versions}
+Description: Init scripts for cloud instances
+ Cloud instances need special scripts to run during initialisation
+ to retrieve and install ssh keys and to let the user run various scripts.
diff --git a/packages/debian/copyright b/packages/debian/copyright
new file mode 100644
index 00000000..dc993525
--- /dev/null
+++ b/packages/debian/copyright
@@ -0,0 +1,51 @@
+Format-Specification: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=135
+Name: cloud-init
+Maintainer: Scott Moser <scott.moser@canonical.com>
+Source: https://launchpad.net/cloud-init
+
+This package was debianized by Soren Hansen <soren@ubuntu.com> on
+Thu, 04 Sep 2008 12:49:15 +0200 as ec2-init. It was later renamed to
+cloud-utils by Scott Moser <scott.moser@canonical.com>
+
+Upstream Author: Scott Moser <smoser@canonical.com>
+ Soren Hansen <soren@canonical.com>
+ Chuck Short <chuck.short@canonical.com>
+
+Copyright: 2010, Canonical Ltd.
+License: GPL-3
+ 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 <http://www.gnu.org/licenses/>.
+
+ The complete text of the GPL version 3 can be seen in
+ /usr/share/common-licenses/GPL-3.
+
+Files: cloudinit/boto_utils.py
+Copyright: 2006,2007, Mitch Garnaat http://garnaat.org/
+License: MIT
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish, dis-
+ tribute, sublicense, and/or sell copies of the Software, and to permit
+ persons to whom the Software is furnished to do so, subject to the fol-
+ lowing conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+ SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
diff --git a/packages/debian/dirs b/packages/debian/dirs
new file mode 100644
index 00000000..f3de468d
--- /dev/null
+++ b/packages/debian/dirs
@@ -0,0 +1,5 @@
+var/lib/cloud
+usr/bin
+etc/init
+usr/share/doc/cloud
+etc/cloud
diff --git a/packages/debian/pycompat b/packages/debian/pycompat
new file mode 100644
index 00000000..0cfbf088
--- /dev/null
+++ b/packages/debian/pycompat
@@ -0,0 +1 @@
+2
diff --git a/packages/debian/rules b/packages/debian/rules
new file mode 100755
index 00000000..87cd6538
--- /dev/null
+++ b/packages/debian/rules
@@ -0,0 +1,17 @@
+#!/usr/bin/make -f
+
+DEB_PYTHON2_MODULE_PACKAGES = cloud-init
+
+binary-install/cloud-init::cloud-init-fixups
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/python-distutils.mk
+
+DEB_PYTHON_INSTALL_ARGS_ALL += --init-system={{init_sys}}
+
+DEB_DH_INSTALL_SOURCEDIR := debian/tmp
+
+cloud-init-fixups:
+ install -d $(DEB_DESTDIR)/etc/rsyslog.d
+ cp tools/21-cloudinit.conf $(DEB_DESTDIR)/etc/rsyslog.d/21-cloudinit.conf
+
diff --git a/packages/make-dist-tarball b/packages/make-dist-tarball
new file mode 100755
index 00000000..622283bd
--- /dev/null
+++ b/packages/make-dist-tarball
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+Usage() {
+ cat <<EOF
+Usage: ${0##*/} version
+ make a tarball of 'version'
+ must be in a bzr directory, and 'version' must be a tag
+
+EOF
+}
+
+topdir="../$PWD"
+tag=${1}
+
+[ -n "$tag" ] || { Usage 1>&2 ; exit 1; }
+
+tmpd=$(mktemp -d );
+trap "rm -Rf '${tmpd}'" 0
+
+out=${topdir}/cloud-init-${tag}.tar.gz
+
+cd ${tmpd} &&
+ bzr branch -r "tag:${tag}" "${topdir}" ./cloud-init-${tag} &&
+ tar czf "${out}" cloud-init-${tag}/ --exclude cloud-init-${tag}/.bzr &&
+ echo "Wrote ${out}"
diff --git a/packages/make-tarball b/packages/make-tarball
new file mode 100755
index 00000000..43a6fc33
--- /dev/null
+++ b/packages/make-tarball
@@ -0,0 +1,89 @@
+#!/usr/bin/python
+
+import contextlib
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+
+import optparse
+
+
+# Use the util functions from cloudinit
+possible_topdir = os.path.normpath(os.path.join(os.path.abspath(
+ sys.argv[0]), os.pardir, os.pardir))
+if os.path.exists(os.path.join(possible_topdir, "cloudinit", "__init__.py")):
+ sys.path.insert(0, possible_topdir)
+
+from cloudinit import util
+
+
+def find_versioned_files():
+ (stdout, _stderr) = util.subp(['bzr', 'ls', '--versioned', '--recursive'])
+ fns = [fn for fn in stdout.splitlines()
+ if fn and not fn.startswith('.')]
+ fns.sort()
+ return fns
+
+
+def copy(fn, where_to, verbose):
+ if verbose:
+ print("Copying %r --> %r" % (fn, where_to))
+ if os.path.isfile(fn):
+ shutil.copy(fn, where_to)
+ elif os.path.isdir(fn) and not os.path.isdir(where_to):
+ os.makedirs(where_to)
+ else:
+ raise RuntimeError("Do not know how to copy %s" % (fn))
+
+
+def main():
+
+ parser = optparse.OptionParser()
+ parser.add_option("-f", "--file", dest="filename",
+ help="write archive to FILE", metavar="FILE")
+ parser.add_option("-v", "--verbose",
+ action="store_true", dest="verbose", default=False,
+ help="show verbose messaging")
+
+ (options, args) = parser.parse_args()
+
+ base_fn = options.filename
+ if not base_fn:
+ (stdout, _stderr) = util.subp(['bzr', 'revno'])
+ revno = stdout.strip()
+ cmd = [sys.executable,
+ util.abs_join(os.pardir, 'tools', 'read-version')]
+ (stdout, _stderr) = util.subp(cmd)
+ version = stdout.strip()
+ base_fn = 'cloud-init-%s-%s' % (version, revno)
+
+ with util.tempdir() as tdir:
+ util.ensure_dir(util.abs_join(tdir, base_fn))
+ arch_fn = '%s.tar.gz' % (base_fn)
+
+ with util.chdir(os.pardir):
+ fns = find_versioned_files()
+ for fn in fns:
+ copy(fn, util.abs_join(tdir, base_fn, fn),
+ verbose=options.verbose)
+
+ arch_full_fn = util.abs_join(tdir, arch_fn)
+ cmd = ['tar', '-czvf', arch_full_fn, '-C', tdir, base_fn]
+ if options.verbose:
+ print("Creating an archive from directory %r to %r" %
+ (util.abs_join(tdir, base_fn), arch_full_fn))
+
+ util.subp(cmd, capture=(not options.verbose))
+ shutil.move(util.abs_join(tdir, arch_fn),
+ util.abs_join(os.getcwd(), arch_fn))
+
+ print(os.path.abspath(arch_fn))
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
+
diff --git a/packages/redhat/cloud-init.spec b/packages/redhat/cloud-init.spec
new file mode 100644
index 00000000..d0f83a4b
--- /dev/null
+++ b/packages/redhat/cloud-init.spec
@@ -0,0 +1,183 @@
+%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
+
+# See: http://www.zarb.org/~jasonc/macros.php
+# Or: http://fedoraproject.org/wiki/Packaging:ScriptletSnippets
+# Or: http://www.rpm.org/max-rpm/ch-rpm-inside.html
+
+Name: cloud-init
+Version: {{version}}
+Release: {{release}}%{?dist}
+Summary: Cloud instance init scripts
+
+Group: System Environment/Base
+License: GPLv3
+URL: http://launchpad.net/cloud-init
+
+Source0: {{archive_name}}
+BuildArch: noarch
+BuildRoot: %{_tmppath}
+
+BuildRequires: python-devel
+BuildRequires: python-setuptools
+
+# System util packages needed
+Requires: shadow-utils
+Requires: rsyslog
+Requires: iproute
+Requires: e2fsprogs
+Requires: net-tools
+Requires: procps
+Requires: shadow-utils
+
+# Install pypi 'dynamic' requirements
+{{for r in requires}}
+Requires: {{r}}
+{{endfor}}
+
+{{if init_d}}
+Requires(post): chkconfig
+Requires(postun): initscripts
+Requires(preun): chkconfig
+Requires(preun): initscripts
+{{endif}}
+
+{{if systemd}}
+BuildRequires: systemd-units
+Requires(post): systemd-units
+Requires(postun): systemd-units
+Requires(preun): systemd-units
+{{endif}}
+
+%description
+Cloud-init is a set of init scripts for cloud instances. Cloud instances
+need special scripts to run during initialization to retrieve and install
+ssh keys and to let the user run various scripts.
+
+%prep
+%setup -q -n %{name}-%{version}-{{revno}}
+
+%build
+%{__python} setup.py build
+
+%install
+rm -rf $RPM_BUILD_ROOT
+%{__python} setup.py install -O1 \
+ --skip-build --root $RPM_BUILD_ROOT \
+ --init-system={{init_sys}}
+
+# Note that /etc/rsyslog.d didn't exist by default until F15.
+# el6 request: https://bugzilla.redhat.com/show_bug.cgi?id=740420
+mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/rsyslog.d
+cp -p tools/21-cloudinit.conf \
+ $RPM_BUILD_ROOT/%{_sysconfdir}/rsyslog.d/21-cloudinit.conf
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+
+{{if systemd}}
+if [ $1 -eq 1 ]
+then
+ /bin/systemctl enable cloud-config.service >/dev/null 2>&1 || :
+ /bin/systemctl enable cloud-final.service >/dev/null 2>&1 || :
+ /bin/systemctl enable cloud-init.service >/dev/null 2>&1 || :
+ /bin/systemctl enable cloud-init-local.service >/dev/null 2>&1 || :
+fi
+{{endif}}
+
+{{if init_d_local}}
+/sbin/chkconfig --add %{_initrddir}/cloud-init-local
+{{elif init_d}}
+/sbin/chkconfig --add %{_initrddir}/cloud-init
+{{endif}}
+{{if init_d}}
+/sbin/chkconfig --add %{_initrddir}/cloud-config
+/sbin/chkconfig --add %{_initrddir}/cloud-final
+{{endif}}
+
+%preun
+
+{{if init_d_local}}
+if [ $1 -eq 0 ]
+then
+ /sbin/service cloud-init-local stop >/dev/null 2>&1
+ /sbin/chkconfig --del cloud-init-local
+fi
+{{elif init_d}}
+if [ $1 -eq 0 ]
+then
+ /sbin/service cloud-init stop >/dev/null 2>&1
+ /sbin/chkconfig --del cloud-init
+fi
+{{endif}}
+{{if init_d}}
+if [ $1 -eq 0 ]
+then
+ /sbin/service cloud-config stop >/dev/null 2>&1
+ /sbin/chkconfig --del cloud-config
+ /sbin/service cloud-final stop >/dev/null 2>&1
+ /sbin/chkconfig --del cloud-final
+fi
+{{endif}}
+
+{{if systemd}}
+if [ $1 -eq 0 ]
+then
+ /bin/systemctl --no-reload disable cloud-config.service >/dev/null 2>&1 || :
+ /bin/systemctl --no-reload disable cloud-final.service >/dev/null 2>&1 || :
+ /bin/systemctl --no-reload disable cloud-init.service >/dev/null 2>&1 || :
+ /bin/systemctl --no-reload disable cloud-init-local.service >/dev/null 2>&1 || :
+fi
+{{endif}}
+
+%postun
+
+{{if systemd}}
+/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+{{endif}}
+
+%files
+
+{{if init_d}}
+%attr(0755, root, root) %{_initddir}/cloud-config
+%attr(0755, root, root) %{_initddir}/cloud-final
+{{endif}}
+{{if init_d_local}}
+%attr(0755, root, root) %{_initddir}/cloud-init-local
+{{elif init_d}}
+%attr(0755, root, root) %{_initddir}/cloud-init
+{{endif}}
+
+{{if systemd}}
+%{_unitdir}/cloud-*
+{{endif}}
+
+# Program binaries
+%{_bindir}/cloud-init*
+
+# There doesn't seem to be an agreed upon place for these
+# although it appears the standard says /usr/lib but rpmbuild
+# will try /usr/lib64 ??
+/usr/lib/%{name}/uncloud-init
+/usr/lib/%{name}/write-ssh-key-fingerprints
+
+# Docs
+%doc TODO LICENSE ChangeLog Requires
+%doc %{_defaultdocdir}/cloud-init/*
+
+# Configs
+%config(noreplace) %{_sysconfdir}/cloud/cloud.cfg
+%dir %{_sysconfdir}/cloud/cloud.cfg.d
+%config(noreplace) %{_sysconfdir}/cloud/cloud.cfg.d/*.cfg
+%config(noreplace) %{_sysconfdir}/cloud/cloud.cfg.d/README
+%dir %{_sysconfdir}/cloud/templates
+%config(noreplace) %{_sysconfdir}/cloud/templates/*
+%config(noreplace) %{_sysconfdir}/rsyslog.d/21-cloudinit.conf
+
+# Python code is here...
+%{python_sitelib}/*
+
+%changelog
+
+{{changelog}}