blob: 46822e32933e88c9eafa5d5880f038df5286dd40 [file] [log] [blame]
Dirk Mueller74af42c2013-06-23 20:50:22 +02001# Copyright 2013 OpenStack Foundation
Matthew Treinish51dfee72013-01-28 15:50:29 -05002# Copyright 2013 IBM Corp.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""Provides methods needed by installation script for OpenStack development
17virtual environments.
18
Dirk Mueller74af42c2013-06-23 20:50:22 +020019Since this script is used to bootstrap a virtualenv from the system's Python
20environment, it should be kept strictly compatible with Python 2.6.
21
Matthew Treinish51dfee72013-01-28 15:50:29 -050022Synced in from openstack-common
23"""
24
Dirk Mueller74af42c2013-06-23 20:50:22 +020025from __future__ import print_function
26
27import optparse
Matthew Treinish51dfee72013-01-28 15:50:29 -050028import os
29import subprocess
30import sys
31
Matthew Treinish7682cde2013-02-06 16:34:40 -050032
Matthew Treinish51dfee72013-01-28 15:50:29 -050033class InstallVenv(object):
34
Monty Taylor7a3c3792013-07-05 22:15:06 -040035 def __init__(self, root, venv, requirements,
36 test_requirements, py_version,
Matthew Treinish51dfee72013-01-28 15:50:29 -050037 project):
38 self.root = root
39 self.venv = venv
Monty Taylor7a3c3792013-07-05 22:15:06 -040040 self.requirements = requirements
41 self.test_requirements = test_requirements
Matthew Treinish51dfee72013-01-28 15:50:29 -050042 self.py_version = py_version
43 self.project = project
44
45 def die(self, message, *args):
Dirk Mueller74af42c2013-06-23 20:50:22 +020046 print(message % args, file=sys.stderr)
Matthew Treinish51dfee72013-01-28 15:50:29 -050047 sys.exit(1)
48
49 def check_python_version(self):
50 if sys.version_info < (2, 6):
51 self.die("Need Python Version >= 2.6")
52
53 def run_command_with_code(self, cmd, redirect_output=True,
54 check_exit_code=True):
55 """Runs a command in an out-of-process shell.
56
Joe Gordon2b0591d2013-02-14 23:18:39 +000057 Returns the output of that command. Working directory is self.root.
Matthew Treinish51dfee72013-01-28 15:50:29 -050058 """
59 if redirect_output:
60 stdout = subprocess.PIPE
61 else:
62 stdout = None
63
64 proc = subprocess.Popen(cmd, cwd=self.root, stdout=stdout)
65 output = proc.communicate()[0]
66 if check_exit_code and proc.returncode != 0:
67 self.die('Command "%s" failed.\n%s', ' '.join(cmd), output)
68 return (output, proc.returncode)
69
70 def run_command(self, cmd, redirect_output=True, check_exit_code=True):
71 return self.run_command_with_code(cmd, redirect_output,
72 check_exit_code)[0]
73
74 def get_distro(self):
75 if (os.path.exists('/etc/fedora-release') or
76 os.path.exists('/etc/redhat-release')):
Monty Taylor7a3c3792013-07-05 22:15:06 -040077 return Fedora(
78 self.root, self.venv, self.requirements,
79 self.test_requirements, self.py_version, self.project)
Matthew Treinish51dfee72013-01-28 15:50:29 -050080 else:
Monty Taylor7a3c3792013-07-05 22:15:06 -040081 return Distro(
82 self.root, self.venv, self.requirements,
83 self.test_requirements, self.py_version, self.project)
Matthew Treinish51dfee72013-01-28 15:50:29 -050084
85 def check_dependencies(self):
86 self.get_distro().install_virtualenv()
87
88 def create_virtualenv(self, no_site_packages=True):
89 """Creates the virtual environment and installs PIP.
90
91 Creates the virtual environment and installs PIP only into the
92 virtual environment.
93 """
94 if not os.path.isdir(self.venv):
Dirk Mueller74af42c2013-06-23 20:50:22 +020095 print('Creating venv...', end=' ')
Matthew Treinish51dfee72013-01-28 15:50:29 -050096 if no_site_packages:
97 self.run_command(['virtualenv', '-q', '--no-site-packages',
98 self.venv])
99 else:
100 self.run_command(['virtualenv', '-q', self.venv])
Dirk Mueller74af42c2013-06-23 20:50:22 +0200101 print('done.')
Matthew Treinish51dfee72013-01-28 15:50:29 -0500102 else:
Dirk Mueller74af42c2013-06-23 20:50:22 +0200103 print("venv already exists...")
Matthew Treinish51dfee72013-01-28 15:50:29 -0500104 pass
105
106 def pip_install(self, *args):
107 self.run_command(['tools/with_venv.sh',
108 'pip', 'install', '--upgrade'] + list(args),
109 redirect_output=False)
110
111 def install_dependencies(self):
Dirk Mueller74af42c2013-06-23 20:50:22 +0200112 print('Installing dependencies with pip (this can take a while)...')
Matthew Treinish51dfee72013-01-28 15:50:29 -0500113
114 # First things first, make sure our venv has the latest pip and
Matthew Treinishffa94d62013-09-11 18:09:17 +0000115 # setuptools and pbr
116 self.pip_install('pip>=1.4')
Monty Taylor7a3c3792013-07-05 22:15:06 -0400117 self.pip_install('setuptools')
Matthew Treinishffa94d62013-09-11 18:09:17 +0000118 self.pip_install('pbr')
Matthew Treinish51dfee72013-01-28 15:50:29 -0500119
Matthew Treinish50bf2d22013-09-20 11:54:32 -0400120 self.pip_install('-r', self.requirements, '-r', self.test_requirements)
Matthew Treinish51dfee72013-01-28 15:50:29 -0500121
Matthew Treinish51dfee72013-01-28 15:50:29 -0500122 def parse_args(self, argv):
123 """Parses command-line arguments."""
Dirk Mueller74af42c2013-06-23 20:50:22 +0200124 parser = optparse.OptionParser()
125 parser.add_option('-n', '--no-site-packages',
126 action='store_true',
127 help="Do not inherit packages from global Python "
128 "install")
129 return parser.parse_args(argv[1:])[0]
Matthew Treinish51dfee72013-01-28 15:50:29 -0500130
131
132class Distro(InstallVenv):
133
134 def check_cmd(self, cmd):
135 return bool(self.run_command(['which', cmd],
136 check_exit_code=False).strip())
137
138 def install_virtualenv(self):
139 if self.check_cmd('virtualenv'):
140 return
141
142 if self.check_cmd('easy_install'):
Dirk Mueller74af42c2013-06-23 20:50:22 +0200143 print('Installing virtualenv via easy_install...', end=' ')
Matthew Treinish51dfee72013-01-28 15:50:29 -0500144 if self.run_command(['easy_install', 'virtualenv']):
Dirk Mueller74af42c2013-06-23 20:50:22 +0200145 print('Succeeded')
Matthew Treinish51dfee72013-01-28 15:50:29 -0500146 return
147 else:
Dirk Mueller74af42c2013-06-23 20:50:22 +0200148 print('Failed')
Matthew Treinish51dfee72013-01-28 15:50:29 -0500149
150 self.die('ERROR: virtualenv not found.\n\n%s development'
151 ' requires virtualenv, please install it using your'
152 ' favorite package management tool' % self.project)
153
Matthew Treinish51dfee72013-01-28 15:50:29 -0500154
155class Fedora(Distro):
156 """This covers all Fedora-based distributions.
157
158 Includes: Fedora, RHEL, CentOS, Scientific Linux
159 """
160
161 def check_pkg(self, pkg):
162 return self.run_command_with_code(['rpm', '-q', pkg],
163 check_exit_code=False)[1] == 0
164
Matthew Treinish51dfee72013-01-28 15:50:29 -0500165 def install_virtualenv(self):
166 if self.check_cmd('virtualenv'):
167 return
168
169 if not self.check_pkg('python-virtualenv'):
Dirk Mueller74af42c2013-06-23 20:50:22 +0200170 self.die("Please install 'python-virtualenv'.")
Matthew Treinish51dfee72013-01-28 15:50:29 -0500171
172 super(Fedora, self).install_virtualenv()