cloud-init/setup.py
Joshua Harlow 8034c6cf4f Only use datafiles and initsys addon outside virtualenvs
To make it so that cloud-init is installable in a virtualenv
where it can be tested in an isolated scenario we need to avoid
using and including datafiles (which won't be written into the
virtualenv) and also avoid using our initsys helper class which
also adds on its own files when we are being ran from a virtualenv.
2014-10-29 17:12:31 -07:00

188 lines
5.7 KiB
Python
Executable File

# vi: ts=4 expandtab
#
# Distutils magic for ec2-init
#
# Copyright (C) 2009 Canonical Ltd.
# Copyright (C) 2012 Yahoo! Inc.
#
# Author: Soren Hansen <soren@canonical.com>
# Author: Joshua Harlow <harlowja@yahoo-inc.com>
#
# 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/>.
from glob import glob
import os
import sys
import setuptools
from setuptools.command.install import install
from distutils.errors import DistutilsArgError
import subprocess
def is_f(p):
return os.path.isfile(p)
def tiny_p(cmd, capture=True):
# Darn python 2.6 doesn't have check_output (argggg)
stdout = subprocess.PIPE
stderr = subprocess.PIPE
if not capture:
stdout = None
stderr = None
sp = subprocess.Popen(cmd, stdout=stdout,
stderr=stderr, stdin=None)
(out, err) = sp.communicate()
ret = sp.returncode
if ret not in [0]:
raise RuntimeError("Failed running %s [rc=%s] (%s, %s)"
% (cmd, ret, out, err))
return (out, err)
def systemd_unitdir():
cmd = ['pkg-config', '--variable=systemdsystemunitdir', 'systemd']
try:
(path, err) = tiny_p(cmd)
except:
return '/lib/systemd/system'
return str(path).strip()
INITSYS_FILES = {
'sysvinit': [f for f in glob('sysvinit/redhat/*') if is_f(f)],
'sysvinit_freebsd': [f for f in glob('sysvinit/freebsd/*') if is_f(f)],
'sysvinit_deb': [f for f in glob('sysvinit/debian/*') if is_f(f)],
'systemd': [f for f in glob('systemd/*') if is_f(f)],
'upstart': [f for f in glob('upstart/*') if is_f(f)],
}
INITSYS_ROOTS = {
'sysvinit': '/etc/rc.d/init.d',
'sysvinit_freebsd': '/usr/local/etc/rc.d',
'sysvinit_deb': '/etc/init.d',
'systemd': systemd_unitdir(),
'upstart': '/etc/init/',
}
INITSYS_TYPES = sorted(list(INITSYS_ROOTS.keys()))
# Install everything in the right location and take care of Linux (default) and
# FreeBSD systems.
USR = "/usr"
ETC = "/etc"
if os.uname()[0] == 'FreeBSD':
USR = "/usr/local"
ETC = "/usr/local/etc"
# Avoid having datafiles installed in a virtualenv...
def in_virtualenv():
try:
if sys.real_prefix == sys.prefix:
return False
else:
return True
except AttributeError:
return False
def get_version():
cmd = ['tools/read-version']
(ver, _e) = tiny_p(cmd)
return str(ver).strip()
def read_requires():
cmd = ['tools/read-dependencies']
(deps, _e) = tiny_p(cmd)
return str(deps).splitlines()
# TODO: Is there a better way to do this??
class InitsysInstallData(install):
init_system = None
user_options = install.user_options + [
# This will magically show up in member variable 'init_sys'
('init-system=', None,
('init system(s) to configure (%s) [default: None]') %
(", ".join(INITSYS_TYPES))
),
]
def initialize_options(self):
install.initialize_options(self)
self.init_system = ""
def finalize_options(self):
install.finalize_options(self)
if self.init_system and isinstance(self.init_system, str):
self.init_system = self.init_system.split(",")
if len(self.init_system) == 0:
raise DistutilsArgError(("You must specify one of (%s) when"
" specifying init system(s)!") % (", ".join(INITSYS_TYPES)))
bad = [f for f in self.init_system if f not in INITSYS_TYPES]
if len(bad) != 0:
raise DistutilsArgError(
"Invalid --init-system: %s" % (','.join(bad)))
for sys in self.init_system:
self.distribution.data_files.append(
(INITSYS_ROOTS[sys], INITSYS_FILES[sys]))
# Force that command to reinitalize (with new file list)
self.distribution.reinitialize_command('install_data', True)
if in_virtualenv():
data_files = []
cmdclass = {}
else:
data_files = [
(ETC + '/cloud', glob('config/*.cfg')),
(ETC + '/cloud/cloud.cfg.d', glob('config/cloud.cfg.d/*')),
(ETC + '/cloud/templates', glob('templates/*')),
(USR + '/lib/cloud-init', ['tools/uncloud-init',
'tools/write-ssh-key-fingerprints']),
(USR + '/share/doc/cloud-init', [f for f in glob('doc/*') if is_f(f)]),
(USR + '/share/doc/cloud-init/examples',
[f for f in glob('doc/examples/*') if is_f(f)]),
(USR + '/share/doc/cloud-init/examples/seed',
[f for f in glob('doc/examples/seed/*') if is_f(f)]),
]
# Use a subclass for install that handles
# adding on the right init system configuration files
cmdclass = {
'install': InitsysInstallData,
}
setuptools.setup(name='cloud-init',
version=get_version(),
description='EC2 initialisation magic',
author='Scott Moser',
author_email='scott.moser@canonical.com',
url='http://launchpad.net/cloud-init/',
packages=setuptools.find_packages(exclude=['tests']),
scripts=['bin/cloud-init',
'tools/cloud-init-per',
],
license='GPLv3',
data_files=data_files,
install_requires=read_requires(),
cmdclass=cmdclass,
)