~ubuntu-branches/ubuntu/trusty/cinder/trusty

« back to all changes in this revision

Viewing changes to tools/install_venv.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-05-22 09:57:46 UTC
  • Revision ID: package-import@ubuntu.com-20120522095746-9lm71yvzltjybk4b
Tags: upstream-2012.2~f1~20120503.2
ImportĀ upstreamĀ versionĀ 2012.2~f1~20120503.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
3
 
 
4
# Copyright 2010 United States Government as represented by the
 
5
# Administrator of the National Aeronautics and Space Administration.
 
6
# All Rights Reserved.
 
7
#
 
8
# Copyright 2010 OpenStack, LLC
 
9
#
 
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
 
13
#
 
14
#         http://www.apache.org/licenses/LICENSE-2.0
 
15
#
 
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
 
20
#    under the License.
 
21
 
 
22
"""Installation script for Cinder's development virtualenv."""
 
23
 
 
24
import optparse
 
25
import os
 
26
import subprocess
 
27
import sys
 
28
 
 
29
 
 
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])
 
35
 
 
36
 
 
37
def die(message, *args):
 
38
    print >> sys.stderr, message % args
 
39
    sys.exit(1)
 
40
 
 
41
 
 
42
def check_python_version():
 
43
    if sys.version_info < (2, 6):
 
44
        die("Need Python Version >= 2.6")
 
45
 
 
46
 
 
47
def run_command_with_code(cmd, redirect_output=True, check_exit_code=True):
 
48
    """Runs a command in an out-of-process shell.
 
49
 
 
50
    Returns the output of that command.  Working directory is ROOT.
 
51
    """
 
52
    if redirect_output:
 
53
        stdout = subprocess.PIPE
 
54
    else:
 
55
        stdout = None
 
56
 
 
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)
 
62
 
 
63
 
 
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]
 
66
 
 
67
 
 
68
class Distro(object):
 
69
 
 
70
    def check_cmd(self, cmd):
 
71
        return bool(run_command(['which', cmd], check_exit_code=False).strip())
 
72
 
 
73
    def install_virtualenv(self):
 
74
        if self.check_cmd('virtualenv'):
 
75
            return
 
76
 
 
77
        if self.check_cmd('easy_install'):
 
78
            print 'Installing virtualenv via easy_install...',
 
79
            if run_command(['easy_install', 'virtualenv']):
 
80
                print 'Succeeded'
 
81
                return
 
82
            else:
 
83
                print 'Failed'
 
84
 
 
85
        die('ERROR: virtualenv not found.\n\nCinder development'
 
86
            ' requires virtualenv, please install it using your'
 
87
            ' favorite package management tool')
 
88
 
 
89
    def post_process(self):
 
90
        """Any distribution-specific post-processing gets done here.
 
91
 
 
92
        In particular, this is useful for applying patches to code inside
 
93
        the venv.
 
94
        """
 
95
        pass
 
96
 
 
97
 
 
98
class Fedora(Distro):
 
99
    """This covers all Fedora-based distributions.
 
100
 
 
101
    Includes: Fedora, RHEL, CentOS, Scientific Linux"""
 
102
 
 
103
    def check_pkg(self, pkg):
 
104
        return run_command_with_code(['rpm', '-q', pkg],
 
105
                                     check_exit_code=False)[1] == 0
 
106
 
 
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)
 
110
 
 
111
    def apply_patch(self, originalfile, patchfile):
 
112
        run_command(['patch', originalfile, patchfile])
 
113
 
 
114
    def install_virtualenv(self):
 
115
        if self.check_cmd('virtualenv'):
 
116
            return
 
117
 
 
118
        if not self.check_pkg('python-virtualenv'):
 
119
            self.yum_install('python-virtualenv', check_exit_code=False)
 
120
 
 
121
        super(Fedora, self).install_virtualenv()
 
122
 
 
123
    def post_process(self):
 
124
        """Workaround for a bug in eventlet.
 
125
 
 
126
        This currently affects RHEL6.1, but the fix can safely be
 
127
        applied to all RHEL and Fedora distributions.
 
128
 
 
129
        This can be removed when the fix is applied upstream.
 
130
 
 
131
        Cinder: https://bugs.launchpad.net/cinder/+bug/884915
 
132
        Upstream: https://bitbucket.org/which_linden/eventlet/issue/89
 
133
        """
 
134
 
 
135
        # Install "patch" program if it's not there
 
136
        if not self.check_pkg('patch'):
 
137
            self.yum_install('patch')
 
138
 
 
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')
 
143
 
 
144
 
 
145
def get_distro():
 
146
    if os.path.exists('/etc/fedora-release') or \
 
147
       os.path.exists('/etc/redhat-release'):
 
148
        return Fedora()
 
149
    else:
 
150
        return Distro()
 
151
 
 
152
 
 
153
def check_dependencies():
 
154
    get_distro().install_virtualenv()
 
155
 
 
156
 
 
157
def create_virtualenv(venv=VENV, no_site_packages=True):
 
158
    """Creates the virtual environment and installs PIP.
 
159
 
 
160
    Creates the virtual environment and installs PIP only into the
 
161
    virtual environment.
 
162
    """
 
163
    print 'Creating venv...',
 
164
    if no_site_packages:
 
165
        run_command(['virtualenv', '-q', '--no-site-packages', VENV])
 
166
    else:
 
167
        run_command(['virtualenv', '-q', VENV])
 
168
    print 'done.'
 
169
    print 'Installing pip in virtualenv...',
 
170
    if not run_command(['tools/with_venv.sh', 'easy_install',
 
171
                        'pip>1.0']).strip():
 
172
        die("Failed to install pip.")
 
173
    print 'done.'
 
174
 
 
175
 
 
176
def pip_install(*args):
 
177
    run_command(['tools/with_venv.sh',
 
178
                 'pip', 'install', '--upgrade'] + list(args),
 
179
                redirect_output=False)
 
180
 
 
181
 
 
182
def install_dependencies(venv=VENV):
 
183
    print 'Installing dependencies with pip (this can take a while)...'
 
184
 
 
185
    # First things first, make sure our venv has the latest pip and distribute.
 
186
    pip_install('pip')
 
187
    pip_install('distribute')
 
188
 
 
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')
 
192
 
 
193
    pip_install('-r', PIP_REQUIRES)
 
194
    pip_install('-r', TEST_REQUIRES)
 
195
 
 
196
    # Tell the virtual env how to "import cinder"
 
197
    pthfile = os.path.join(venv, "lib", PY_VERSION, "site-packages",
 
198
                        "cinder.pth")
 
199
    f = open(pthfile, 'w')
 
200
    f.write("%s\n" % ROOT)
 
201
 
 
202
 
 
203
def post_process():
 
204
    get_distro().post_process()
 
205
 
 
206
 
 
207
def print_help():
 
208
    help = """
 
209
    Cinder development environment setup is complete.
 
210
 
 
211
    Cinder development uses virtualenv to track and manage Python dependencies
 
212
    while in development and testing.
 
213
 
 
214
    To activate the Cinder virtualenv for the extent of your current shell
 
215
    session you can run:
 
216
 
 
217
    $ source .venv/bin/activate
 
218
 
 
219
    Or, if you prefer, you can run commands in the virtualenv on a case by case
 
220
    basis by running:
 
221
 
 
222
    $ tools/with_venv.sh <your command>
 
223
 
 
224
    Also, make test will automatically use the virtualenv.
 
225
    """
 
226
    print help
 
227
 
 
228
 
 
229
def parse_args():
 
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()
 
236
 
 
237
 
 
238
def main(argv):
 
239
    (options, args) = parse_args()
 
240
    check_python_version()
 
241
    check_dependencies()
 
242
    create_virtualenv(no_site_packages=options.no_site_packages)
 
243
    install_dependencies()
 
244
    post_process()
 
245
    print_help()
 
246
 
 
247
if __name__ == '__main__':
 
248
    main(sys.argv)