2
# vim: tabstop=4 shiftwidth=4 softtabstop=4
4
# Copyright 2010 United States Government as represented by the
5
# Administrator of the National Aeronautics and Space Administration.
8
# Copyright 2010 OpenStack, LLC
10
# Licensed under the Apache License, Version 2.0 (the "License"); you may
11
# not use this file except in compliance with the License. You may obtain
12
# a copy of the License at
14
# http://www.apache.org/licenses/LICENSE-2.0
16
# Unless required by applicable law or agreed to in writing, software
17
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
19
# License for the specific language governing permissions and limitations
22
"""Installation script for Cinder's development virtualenv."""
30
ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
31
VENV = os.path.join(ROOT, '.venv')
32
PIP_REQUIRES = os.path.join(ROOT, 'tools', 'pip-requires')
33
TEST_REQUIRES = os.path.join(ROOT, 'tools', 'test-requires')
34
PY_VERSION = "python%s.%s" % (sys.version_info[0], sys.version_info[1])
37
def die(message, *args):
38
print >> sys.stderr, message % args
42
def check_python_version():
43
if sys.version_info < (2, 6):
44
die("Need Python Version >= 2.6")
47
def run_command_with_code(cmd, redirect_output=True, check_exit_code=True):
48
"""Runs a command in an out-of-process shell.
50
Returns the output of that command. Working directory is ROOT.
53
stdout = subprocess.PIPE
57
proc = subprocess.Popen(cmd, cwd=ROOT, stdout=stdout)
58
output = proc.communicate()[0]
59
if check_exit_code and proc.returncode != 0:
60
die('Command "%s" failed.\n%s', ' '.join(cmd), output)
61
return (output, proc.returncode)
64
def run_command(cmd, redirect_output=True, check_exit_code=True):
65
return run_command_with_code(cmd, redirect_output, check_exit_code)[0]
70
def check_cmd(self, cmd):
71
return bool(run_command(['which', cmd], check_exit_code=False).strip())
73
def install_virtualenv(self):
74
if self.check_cmd('virtualenv'):
77
if self.check_cmd('easy_install'):
78
print 'Installing virtualenv via easy_install...',
79
if run_command(['easy_install', 'virtualenv']):
85
die('ERROR: virtualenv not found.\n\nCinder development'
86
' requires virtualenv, please install it using your'
87
' favorite package management tool')
89
def post_process(self):
90
"""Any distribution-specific post-processing gets done here.
92
In particular, this is useful for applying patches to code inside
99
"""This covers all Fedora-based distributions.
101
Includes: Fedora, RHEL, CentOS, Scientific Linux"""
103
def check_pkg(self, pkg):
104
return run_command_with_code(['rpm', '-q', pkg],
105
check_exit_code=False)[1] == 0
107
def yum_install(self, pkg, **kwargs):
108
print "Attempting to install '%s' via yum" % pkg
109
run_command(['sudo', 'yum', 'install', '-y', pkg], **kwargs)
111
def apply_patch(self, originalfile, patchfile):
112
run_command(['patch', originalfile, patchfile])
114
def install_virtualenv(self):
115
if self.check_cmd('virtualenv'):
118
if not self.check_pkg('python-virtualenv'):
119
self.yum_install('python-virtualenv', check_exit_code=False)
121
super(Fedora, self).install_virtualenv()
123
def post_process(self):
124
"""Workaround for a bug in eventlet.
126
This currently affects RHEL6.1, but the fix can safely be
127
applied to all RHEL and Fedora distributions.
129
This can be removed when the fix is applied upstream.
131
Cinder: https://bugs.launchpad.net/cinder/+bug/884915
132
Upstream: https://bitbucket.org/which_linden/eventlet/issue/89
135
# Install "patch" program if it's not there
136
if not self.check_pkg('patch'):
137
self.yum_install('patch')
139
# Apply the eventlet patch
140
self.apply_patch(os.path.join(VENV, 'lib', PY_VERSION, 'site-packages',
141
'eventlet/green/subprocess.py'),
142
'contrib/redhat-eventlet.patch')
146
if os.path.exists('/etc/fedora-release') or \
147
os.path.exists('/etc/redhat-release'):
153
def check_dependencies():
154
get_distro().install_virtualenv()
157
def create_virtualenv(venv=VENV, no_site_packages=True):
158
"""Creates the virtual environment and installs PIP.
160
Creates the virtual environment and installs PIP only into the
163
print 'Creating venv...',
165
run_command(['virtualenv', '-q', '--no-site-packages', VENV])
167
run_command(['virtualenv', '-q', VENV])
169
print 'Installing pip in virtualenv...',
170
if not run_command(['tools/with_venv.sh', 'easy_install',
172
die("Failed to install pip.")
176
def pip_install(*args):
177
run_command(['tools/with_venv.sh',
178
'pip', 'install', '--upgrade'] + list(args),
179
redirect_output=False)
182
def install_dependencies(venv=VENV):
183
print 'Installing dependencies with pip (this can take a while)...'
185
# First things first, make sure our venv has the latest pip and distribute.
187
pip_install('distribute')
189
# Install greenlet by hand - just listing it in the requires file does not
190
# get it in stalled in the right order
191
pip_install('greenlet')
193
pip_install('-r', PIP_REQUIRES)
194
pip_install('-r', TEST_REQUIRES)
196
# Tell the virtual env how to "import cinder"
197
pthfile = os.path.join(venv, "lib", PY_VERSION, "site-packages",
199
f = open(pthfile, 'w')
200
f.write("%s\n" % ROOT)
204
get_distro().post_process()
209
Cinder development environment setup is complete.
211
Cinder development uses virtualenv to track and manage Python dependencies
212
while in development and testing.
214
To activate the Cinder virtualenv for the extent of your current shell
217
$ source .venv/bin/activate
219
Or, if you prefer, you can run commands in the virtualenv on a case by case
222
$ tools/with_venv.sh <your command>
224
Also, make test will automatically use the virtualenv.
230
"""Parses command-line arguments."""
231
parser = optparse.OptionParser()
232
parser.add_option("-n", "--no-site-packages", dest="no_site_packages",
233
default=False, action="store_true",
234
help="Do not inherit packages from global Python install")
235
return parser.parse_args()
239
(options, args) = parse_args()
240
check_python_version()
242
create_virtualenv(no_site_packages=options.no_site_packages)
243
install_dependencies()
247
if __name__ == '__main__':