Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / pybind / rbd / setup.py
1 from __future__ import print_function
2
3 import os
4 import pkgutil
5 import shutil
6 import subprocess
7 import sys
8 import tempfile
9 import textwrap
10 from distutils.ccompiler import new_compiler
11 from distutils.errors import CompileError, LinkError
12 from distutils.sysconfig import customize_compiler
13
14 if not pkgutil.find_loader('setuptools'):
15     from distutils.core import setup
16     from distutils.extension import Extension
17 else:
18     from setuptools import setup
19     from setuptools.extension import Extension
20
21 # PEP 440 versioning of the RBD package on PyPI
22 # Bump this version, after every changeset
23
24 __version__ = '2.0.0'
25
26
27 def get_python_flags():
28     cflags = {'I': [], 'extras': []}
29     ldflags = {'l': [], 'L': [], 'extras': []}
30
31     if os.environ.get('VIRTUAL_ENV', None):
32         python = "python"
33     else:
34         python = 'python' + str(sys.version_info.major) + '.' + str(sys.version_info.minor)
35
36     python_config = python + '-config'
37
38     for cflag in subprocess.check_output(
39             [python_config, "--cflags"]
40     ).strip().decode('utf-8').split():
41         if cflag.startswith('-I'):
42             cflags['I'].append(cflag.replace('-I', ''))
43         else:
44             cflags['extras'].append(cflag)
45
46     for ldflag in subprocess.check_output(
47             [python_config, "--ldflags"]
48     ).strip().decode('utf-8').split():
49         if ldflag.startswith('-l'):
50             ldflags['l'].append(ldflag.replace('-l', ''))
51         if ldflag.startswith('-L'):
52             ldflags['L'].append(ldflag.replace('-L', ''))
53         else:
54             ldflags['extras'].append(ldflag)
55
56     return {
57         'cflags': cflags,
58         'ldflags': ldflags
59     }
60
61
62 def check_sanity():
63     """
64     Test if development headers and library for rbd is available by compiling a dummy C program.
65     """
66     CEPH_SRC_DIR = os.path.join(
67         os.path.dirname(os.path.abspath(__file__)),
68         '..',
69         '..'
70     )
71
72     tmp_dir = tempfile.mkdtemp(dir=os.environ.get('TMPDIR', os.path.dirname(__file__)))
73     tmp_file = os.path.join(tmp_dir, 'rbd_dummy.c')
74
75     with open(tmp_file, 'w') as fp:
76         dummy_prog = textwrap.dedent("""
77         #include <stddef.h>
78         #include <rbd/librbd.h>
79         int main(void) {
80             rados_t cluster;
81             rados_create(&cluster, NULL);
82             return 0;
83         }
84         """)
85         fp.write(dummy_prog)
86
87     compiler = new_compiler()
88     customize_compiler(compiler)
89
90     if {'MAKEFLAGS', 'MFLAGS', 'MAKELEVEL'}.issubset(set(os.environ.keys())):
91         # The setup.py has been invoked by a top-level Ceph make.
92         # Set the appropriate CFLAGS and LDFLAGS
93
94         compiler.set_include_dirs([os.path.join(CEPH_SRC_DIR, 'include')])
95         compiler.set_library_dirs([os.environ.get('CEPH_LIBDIR')])
96
97     try:
98         compiler.define_macro('_FILE_OFFSET_BITS', '64')
99
100         link_objects = compiler.compile(
101             sources=[tmp_file],
102             output_dir=tmp_dir
103         )
104
105         compiler.link_executable(
106             objects=link_objects,
107             output_progname=os.path.join(tmp_dir, 'rbd_dummy'),
108             libraries=['rbd', 'rados'],
109             output_dir=tmp_dir,
110         )
111
112     except CompileError:
113         print('\nCompile Error: RBD development headers not found', file=sys.stderr)
114         return False
115     except LinkError:
116         print('\nLink Error: RBD library not found', file=sys.stderr)
117         return False
118     else:
119         return True
120     finally:
121         shutil.rmtree(tmp_dir)
122
123
124 if 'BUILD_DOC' in os.environ.keys():
125     pass
126 elif check_sanity():
127     pass
128 else:
129     sys.exit(1)
130
131 cmdclass = {}
132 try:
133     from Cython.Build import cythonize
134     from Cython.Distutils import build_ext
135
136     cmdclass = {'build_ext': build_ext}
137 except ImportError:
138     print("WARNING: Cython is not installed.")
139
140     if not os.path.isfile('rbd.c'):
141         print('ERROR: Cannot find Cythonized file rbd.c', file=sys.stderr)
142         sys.exit(1)
143     else:
144         def cythonize(x, **kwargs):
145             return x
146
147         source = "rbd.c"
148 else:
149     source = "rbd.pyx"
150
151 # Disable cythonification if we're not really building anything
152 if (len(sys.argv) >= 2 and
153         any(i in sys.argv[1:] for i in ('--help', 'clean', 'egg_info', '--version')
154             )):
155     def cythonize(x, **kwargs):
156         return x
157
158 flags = get_python_flags()
159
160 setup(
161     name='rbd',
162     version=__version__,
163     description="Python bindings for the RBD library",
164     long_description=(
165         "This package contains Python bindings for interacting with the "
166         "RADOS Block Device (RBD) library. rbd is a utility for manipulating "
167         "rados block device images, used by the Linux rbd driver and the rbd "
168         "storage driver for QEMU/KVM. RBD images are simple block devices that "
169         "are striped over objects and stored in a RADOS object store. The size "
170         "of the objects the image is striped over must be a power of two."
171     ),
172     url='https://github.com/ceph/ceph/tree/master/src/pybind/rbd',
173     license='LGPLv2+',
174     platforms='Linux',
175     ext_modules=cythonize(
176         [
177             Extension(
178                 "rbd",
179                 [source],
180                 include_dirs=flags['cflags']['I'],
181                 library_dirs=flags['ldflags']['L'],
182                 libraries=['rbd', 'rados'] + flags['ldflags']['l'],
183                 extra_compile_args=flags['cflags']['extras'] + flags['ldflags']['extras'],
184             )
185         ],
186         build_dir=os.environ.get("CYTHON_BUILD_DIR", None),
187         include_path=[
188             os.path.join(os.path.dirname(__file__), "..", "rados")
189         ]
190     ),
191     classifiers=[
192         'Intended Audience :: Developers',
193         'Intended Audience :: System Administrators',
194         'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)',
195         'Operating System :: POSIX :: Linux',
196         'Programming Language :: Cython',
197         'Programming Language :: Python :: 2.7',
198         'Programming Language :: Python :: 3.4',
199         'Programming Language :: Python :: 3.5'
200     ],
201     cmdclass=cmdclass,
202 )