2012-07-01 01:54:25 +00:00
|
|
|
#!/usr/bin/env python
|
2014-01-13 07:35:18 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2011-02-27 22:17:45 +00:00
|
|
|
'''
|
|
|
|
The setup script for salt
|
|
|
|
'''
|
2011-11-14 15:49:06 +00:00
|
|
|
|
2017-03-09 13:49:08 +00:00
|
|
|
# pylint: disable=file-perms,ungrouped-imports,wrong-import-order,wrong-import-position,repr-flag-used-in-string
|
2017-04-05 22:18:00 +00:00
|
|
|
# pylint: disable=3rd-party-local-module-not-gated,resource-leakage
|
2014-10-05 19:05:26 +00:00
|
|
|
# pylint: disable=C0111,E1101,E1103,F0401,W0611,W0201,W0232,R0201,R0902,R0903
|
2013-11-14 18:49:26 +00:00
|
|
|
|
2012-05-07 03:25:14 +00:00
|
|
|
# For Python 2.5. A no-op on 2.6 and above.
|
2017-03-09 13:49:08 +00:00
|
|
|
from __future__ import absolute_import, print_function, with_statement
|
2012-05-07 03:25:14 +00:00
|
|
|
|
2011-12-10 20:12:16 +00:00
|
|
|
import os
|
|
|
|
import sys
|
2013-11-12 05:10:41 +00:00
|
|
|
import glob
|
2015-01-09 16:41:50 +00:00
|
|
|
import time
|
2014-11-07 16:50:11 +00:00
|
|
|
try:
|
|
|
|
from urllib2 import urlopen
|
|
|
|
except ImportError:
|
2015-08-14 14:39:58 +00:00
|
|
|
from urllib.request import urlopen # pylint: disable=no-name-in-module
|
2013-02-06 04:23:56 +00:00
|
|
|
from datetime import datetime
|
2013-11-14 18:49:26 +00:00
|
|
|
# pylint: disable=E0611
|
2014-10-05 19:05:26 +00:00
|
|
|
import distutils.dist
|
2013-11-14 18:18:51 +00:00
|
|
|
from distutils import log
|
2011-07-22 17:47:34 +00:00
|
|
|
from distutils.cmd import Command
|
2014-06-17 23:34:04 +00:00
|
|
|
from distutils.errors import DistutilsArgError
|
2013-02-06 04:23:56 +00:00
|
|
|
from distutils.command.build import build
|
2012-10-12 14:51:28 +00:00
|
|
|
from distutils.command.clean import clean
|
2013-11-14 18:06:12 +00:00
|
|
|
from distutils.command.sdist import sdist
|
2014-03-17 16:56:31 +00:00
|
|
|
from distutils.command.install_lib import install_lib
|
2016-09-20 15:31:13 +00:00
|
|
|
from ctypes.util import find_library
|
2013-11-14 18:49:26 +00:00
|
|
|
# pylint: enable=E0611
|
2011-12-22 22:56:33 +00:00
|
|
|
|
2014-02-25 22:52:02 +00:00
|
|
|
try:
|
|
|
|
import zmq
|
|
|
|
HAS_ZMQ = True
|
|
|
|
except ImportError:
|
|
|
|
HAS_ZMQ = False
|
|
|
|
|
2016-02-04 09:29:53 +00:00
|
|
|
try:
|
|
|
|
DATE = datetime.utcfromtimestamp(int(os.environ['SOURCE_DATE_EPOCH']))
|
|
|
|
except (KeyError, ValueError):
|
|
|
|
DATE = datetime.utcnow()
|
|
|
|
|
2012-12-30 17:55:23 +00:00
|
|
|
# Change to salt source's directory prior to running any command
|
2013-05-22 01:00:44 +00:00
|
|
|
try:
|
2013-08-23 22:17:13 +00:00
|
|
|
SETUP_DIRNAME = os.path.dirname(__file__)
|
2013-05-22 01:00:44 +00:00
|
|
|
except NameError:
|
|
|
|
# We're most likely being frozen and __file__ triggered this NameError
|
|
|
|
# Let's work around that
|
2013-08-23 22:17:13 +00:00
|
|
|
SETUP_DIRNAME = os.path.dirname(sys.argv[0])
|
2013-05-22 01:00:44 +00:00
|
|
|
|
2013-08-23 22:17:13 +00:00
|
|
|
if SETUP_DIRNAME != '':
|
|
|
|
os.chdir(SETUP_DIRNAME)
|
2012-12-30 17:55:23 +00:00
|
|
|
|
2013-11-14 23:01:30 +00:00
|
|
|
SETUP_DIRNAME = os.path.abspath(SETUP_DIRNAME)
|
|
|
|
|
2013-11-14 18:18:51 +00:00
|
|
|
BOOTSTRAP_SCRIPT_DISTRIBUTED_VERSION = os.environ.get(
|
|
|
|
# The user can provide a different bootstrap-script version.
|
|
|
|
# ATTENTION: A tag for that version MUST exist
|
|
|
|
'BOOTSTRAP_SCRIPT_VERSION',
|
|
|
|
# If no bootstrap-script version was provided from the environment, let's
|
|
|
|
# provide the one we define.
|
2014-06-21 13:46:08 +00:00
|
|
|
'v2014.06.21'
|
2013-11-14 18:18:51 +00:00
|
|
|
)
|
|
|
|
|
2013-08-23 22:58:26 +00:00
|
|
|
# Store a reference to the executing platform
|
|
|
|
IS_WINDOWS_PLATFORM = sys.platform.startswith('win')
|
2016-02-05 20:41:36 +00:00
|
|
|
if IS_WINDOWS_PLATFORM:
|
|
|
|
IS_SMARTOS_PLATFORM = False
|
|
|
|
else:
|
|
|
|
# os.uname() not available on Windows.
|
|
|
|
IS_SMARTOS_PLATFORM = os.uname()[0] == 'SunOS' and os.uname()[3].startswith('joyent_')
|
2013-08-23 22:58:26 +00:00
|
|
|
|
2015-10-18 08:44:54 +00:00
|
|
|
# Store a reference wether if we're running under Python 3 and above
|
|
|
|
IS_PY3 = sys.version_info > (3,)
|
|
|
|
|
2012-07-01 02:00:22 +00:00
|
|
|
# Use setuptools only if the user opts-in by setting the USE_SETUPTOOLS env var
|
2013-05-21 23:36:31 +00:00
|
|
|
# Or if setuptools was previously imported (which is the case when using
|
|
|
|
# 'distribute')
|
2012-07-01 02:00:22 +00:00
|
|
|
# This ensures consistent behavior but allows for advanced usage with
|
|
|
|
# virtualenv, buildout, and others.
|
2013-08-23 22:17:13 +00:00
|
|
|
WITH_SETUPTOOLS = False
|
2013-03-20 21:05:20 +00:00
|
|
|
if 'USE_SETUPTOOLS' in os.environ or 'setuptools' in sys.modules:
|
2012-06-30 20:01:57 +00:00
|
|
|
try:
|
|
|
|
from setuptools import setup
|
2015-08-14 14:27:03 +00:00
|
|
|
from setuptools.command.develop import develop
|
2013-02-13 10:53:33 +00:00
|
|
|
from setuptools.command.install import install
|
2013-11-14 18:06:12 +00:00
|
|
|
from setuptools.command.sdist import sdist
|
2014-10-01 20:39:37 +00:00
|
|
|
from setuptools.command.egg_info import egg_info
|
2013-08-23 22:17:13 +00:00
|
|
|
WITH_SETUPTOOLS = True
|
|
|
|
except ImportError:
|
|
|
|
WITH_SETUPTOOLS = False
|
2012-06-30 20:01:57 +00:00
|
|
|
|
2013-08-23 22:17:13 +00:00
|
|
|
if WITH_SETUPTOOLS is False:
|
2013-01-14 13:41:42 +00:00
|
|
|
import warnings
|
2013-11-14 18:49:26 +00:00
|
|
|
# pylint: disable=E0611
|
2013-02-13 10:53:33 +00:00
|
|
|
from distutils.command.install import install
|
2012-06-05 10:00:20 +00:00
|
|
|
from distutils.core import setup
|
2013-11-14 18:49:26 +00:00
|
|
|
# pylint: enable=E0611
|
2013-01-14 13:41:42 +00:00
|
|
|
warnings.filterwarnings(
|
|
|
|
'ignore',
|
2014-06-20 11:10:34 +00:00
|
|
|
'Unknown distribution option: \'(extras_require|tests_require|install_requires|zip_safe)\'',
|
2013-01-14 13:41:42 +00:00
|
|
|
UserWarning,
|
|
|
|
'distutils.dist'
|
|
|
|
)
|
2012-06-05 10:00:20 +00:00
|
|
|
|
2013-01-01 22:49:26 +00:00
|
|
|
try:
|
|
|
|
# Add the esky bdist target if the module is available
|
|
|
|
# may require additional modules depending on platform
|
|
|
|
from esky import bdist_esky
|
|
|
|
# bbfreeze chosen for its tight integration with distutils
|
|
|
|
import bbfreeze
|
|
|
|
HAS_ESKY = True
|
|
|
|
except ImportError:
|
|
|
|
HAS_ESKY = False
|
|
|
|
|
2014-06-17 14:19:03 +00:00
|
|
|
SALT_VERSION = os.path.join(os.path.abspath(SETUP_DIRNAME), 'salt', 'version.py')
|
2014-08-01 18:10:49 +00:00
|
|
|
SALT_VERSION_HARDCODED = os.path.join(os.path.abspath(SETUP_DIRNAME), 'salt', '_version.py')
|
2015-08-14 17:32:30 +00:00
|
|
|
SALT_SYSPATHS_HARDCODED = os.path.join(os.path.abspath(SETUP_DIRNAME), 'salt', '_syspaths.py')
|
2015-01-12 19:58:09 +00:00
|
|
|
SALT_REQS = os.path.join(os.path.abspath(SETUP_DIRNAME), 'requirements', 'base.txt')
|
|
|
|
SALT_ZEROMQ_REQS = os.path.join(os.path.abspath(SETUP_DIRNAME), 'requirements', 'zeromq.txt')
|
|
|
|
SALT_RAET_REQS = os.path.join(os.path.abspath(SETUP_DIRNAME), 'requirements', 'raet.txt')
|
2017-04-27 15:47:46 +00:00
|
|
|
if IS_PY3:
|
|
|
|
SALT_WINDOWS_REQS = os.path.join(
|
|
|
|
os.path.abspath(SETUP_DIRNAME), 'pkg', 'windows', 'req_3.txt')
|
|
|
|
else:
|
|
|
|
SALT_WINDOWS_REQS = os.path.join(
|
2017-04-27 15:51:32 +00:00
|
|
|
os.path.abspath(SETUP_DIRNAME), 'pkg', 'windows', 'req_2.txt')
|
2013-08-23 22:58:26 +00:00
|
|
|
|
2014-10-01 19:47:03 +00:00
|
|
|
# Salt SSH Packaging Detection
|
|
|
|
PACKAGED_FOR_SALT_SSH_FILE = os.path.join(os.path.abspath(SETUP_DIRNAME), '.salt-ssh-package')
|
|
|
|
PACKAGED_FOR_SALT_SSH = os.path.isfile(PACKAGED_FOR_SALT_SSH_FILE)
|
|
|
|
|
2014-10-05 19:05:26 +00:00
|
|
|
|
2013-11-14 18:49:26 +00:00
|
|
|
# pylint: disable=W0122
|
2013-08-23 22:17:13 +00:00
|
|
|
exec(compile(open(SALT_VERSION).read(), SALT_VERSION, 'exec'))
|
2013-11-14 18:49:26 +00:00
|
|
|
# pylint: enable=W0122
|
2011-09-25 06:30:36 +00:00
|
|
|
|
2012-06-30 20:35:31 +00:00
|
|
|
|
2014-06-17 14:19:03 +00:00
|
|
|
# ----- Helper Functions -------------------------------------------------------------------------------------------->
|
|
|
|
def _parse_requirements_file(requirements_file):
|
|
|
|
parsed_requirements = []
|
|
|
|
with open(requirements_file) as rfh:
|
|
|
|
for line in rfh.readlines():
|
|
|
|
line = line.strip()
|
|
|
|
if not line or line.startswith(('#', '-r')):
|
|
|
|
continue
|
2015-08-14 15:27:31 +00:00
|
|
|
if IS_WINDOWS_PLATFORM:
|
|
|
|
if 'libcloud' in line:
|
|
|
|
continue
|
2017-03-10 21:52:38 +00:00
|
|
|
if 'pycrypto' in line.lower() and not IS_PY3:
|
|
|
|
# On Python 2 in Windows we install PyCrypto using python wheels
|
2015-08-14 15:27:31 +00:00
|
|
|
continue
|
|
|
|
if 'm2crypto' in line.lower() and __saltstack_version__.info < (2015, 8): # pylint: disable=undefined-variable
|
|
|
|
# In Windows, we're installing M2CryptoWin{32,64} which comes
|
|
|
|
# compiled
|
|
|
|
continue
|
2015-10-18 08:44:54 +00:00
|
|
|
if IS_PY3 and 'futures' in line.lower():
|
|
|
|
# Python 3 already has futures, installing it will only break
|
|
|
|
# the current python installation whenever futures is imported
|
|
|
|
continue
|
2014-06-17 14:19:03 +00:00
|
|
|
parsed_requirements.append(line)
|
|
|
|
return parsed_requirements
|
|
|
|
# <---- Helper Functions ---------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
# ----- Custom Distutils/Setuptools Commands ------------------------------------------------------------------------>
|
2014-08-01 18:10:49 +00:00
|
|
|
class WriteSaltVersion(Command):
|
|
|
|
|
|
|
|
description = 'Write salt\'s hardcoded version file'
|
2015-03-09 06:03:38 +00:00
|
|
|
user_options = []
|
2014-08-01 18:10:49 +00:00
|
|
|
|
|
|
|
def initialize_options(self):
|
2015-08-16 04:04:51 +00:00
|
|
|
'''
|
|
|
|
Abstract method that is required to be overwritten
|
|
|
|
'''
|
2014-08-01 18:10:49 +00:00
|
|
|
|
|
|
|
def finalize_options(self):
|
2015-08-16 04:04:51 +00:00
|
|
|
'''
|
|
|
|
Abstract method that is required to be overwritten
|
|
|
|
'''
|
2014-08-01 18:10:49 +00:00
|
|
|
|
|
|
|
def run(self):
|
|
|
|
if not os.path.exists(SALT_VERSION_HARDCODED):
|
|
|
|
# Write the version file
|
|
|
|
if getattr(self.distribution, 'salt_version_hardcoded_path', None) is None:
|
2014-10-05 19:05:26 +00:00
|
|
|
print('This command is not meant to be called on it\'s own')
|
2014-08-01 18:10:49 +00:00
|
|
|
exit(1)
|
|
|
|
|
|
|
|
# pylint: disable=E0602
|
|
|
|
open(self.distribution.salt_version_hardcoded_path, 'w').write(
|
|
|
|
INSTALL_VERSION_TEMPLATE.format(
|
2016-02-04 09:29:53 +00:00
|
|
|
date=DATE,
|
2014-08-01 18:10:49 +00:00
|
|
|
full_version_info=__saltstack_version__.full_info
|
|
|
|
)
|
|
|
|
)
|
|
|
|
# pylint: enable=E0602
|
|
|
|
|
|
|
|
|
2015-08-14 17:32:30 +00:00
|
|
|
class GenerateSaltSyspaths(Command):
|
|
|
|
|
|
|
|
description = 'Generate salt\'s hardcoded syspaths file'
|
|
|
|
|
|
|
|
def initialize_options(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def finalize_options(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
# Write the syspaths file
|
|
|
|
if getattr(self.distribution, 'salt_syspaths_hardcoded_path', None) is None:
|
|
|
|
print('This command is not meant to be called on it\'s own')
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
# Write the system paths file
|
|
|
|
open(self.distribution.salt_syspaths_hardcoded_path, 'w').write(
|
|
|
|
INSTALL_SYSPATHS_TEMPLATE.format(
|
2016-02-04 09:29:53 +00:00
|
|
|
date=DATE,
|
2015-08-14 17:32:30 +00:00
|
|
|
root_dir=self.distribution.salt_root_dir,
|
2017-03-02 12:17:42 +00:00
|
|
|
share_dir=self.distribution.salt_share_dir,
|
2015-08-14 17:32:30 +00:00
|
|
|
config_dir=self.distribution.salt_config_dir,
|
|
|
|
cache_dir=self.distribution.salt_cache_dir,
|
|
|
|
sock_dir=self.distribution.salt_sock_dir,
|
|
|
|
srv_root_dir=self.distribution.salt_srv_root_dir,
|
|
|
|
base_file_roots_dir=self.distribution.salt_base_file_roots_dir,
|
|
|
|
base_pillar_roots_dir=self.distribution.salt_base_pillar_roots_dir,
|
|
|
|
base_master_roots_dir=self.distribution.salt_base_master_roots_dir,
|
2016-02-02 17:49:23 +00:00
|
|
|
base_thorium_roots_dir=self.distribution.salt_base_thorium_roots_dir,
|
2015-08-14 17:32:30 +00:00
|
|
|
logs_dir=self.distribution.salt_logs_dir,
|
|
|
|
pidfile_dir=self.distribution.salt_pidfile_dir,
|
2015-08-28 00:25:48 +00:00
|
|
|
spm_formula_path=self.distribution.salt_spm_formula_dir,
|
|
|
|
spm_pillar_path=self.distribution.salt_spm_pillar_dir,
|
|
|
|
spm_reactor_path=self.distribution.salt_spm_reactor_dir,
|
2015-08-14 17:32:30 +00:00
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2015-08-16 04:04:51 +00:00
|
|
|
class WriteSaltSshPackagingFile(Command):
|
2014-10-01 19:47:03 +00:00
|
|
|
|
|
|
|
description = 'Write salt\'s ssh packaging file'
|
2015-03-09 06:03:38 +00:00
|
|
|
user_options = []
|
2014-10-01 19:47:03 +00:00
|
|
|
|
|
|
|
def initialize_options(self):
|
2015-08-16 04:04:51 +00:00
|
|
|
'''
|
|
|
|
Abstract method that is required to be overwritten
|
|
|
|
'''
|
2014-10-01 19:47:03 +00:00
|
|
|
|
|
|
|
def finalize_options(self):
|
2015-08-16 04:04:51 +00:00
|
|
|
'''
|
|
|
|
Abstract method that is required to be overwritten
|
|
|
|
'''
|
2014-10-01 19:47:03 +00:00
|
|
|
|
|
|
|
def run(self):
|
|
|
|
if not os.path.exists(PACKAGED_FOR_SALT_SSH_FILE):
|
|
|
|
# Write the salt-ssh packaging file
|
|
|
|
if getattr(self.distribution, 'salt_ssh_packaging_file', None) is None:
|
2014-10-05 19:05:26 +00:00
|
|
|
print('This command is not meant to be called on it\'s own')
|
2014-10-01 19:47:03 +00:00
|
|
|
exit(1)
|
|
|
|
|
|
|
|
# pylint: disable=E0602
|
|
|
|
open(self.distribution.salt_ssh_packaging_file, 'w').write('Packaged for Salt-SSH\n')
|
|
|
|
# pylint: enable=E0602
|
|
|
|
|
|
|
|
|
2015-08-14 14:27:03 +00:00
|
|
|
if WITH_SETUPTOOLS:
|
|
|
|
class Develop(develop):
|
2015-08-14 16:59:40 +00:00
|
|
|
user_options = develop.user_options + [
|
2015-08-18 22:18:09 +00:00
|
|
|
('write-salt-version', None,
|
2015-08-14 16:59:40 +00:00
|
|
|
'Generate Salt\'s _version.py file which allows proper version '
|
2015-08-14 17:32:30 +00:00
|
|
|
'reporting. This defaults to False on develop/editable setups. '
|
|
|
|
'If WRITE_SALT_VERSION is found in the environment this flag is '
|
|
|
|
'switched to True.'),
|
2015-08-18 22:18:09 +00:00
|
|
|
('generate-salt-syspaths', None,
|
2015-08-14 17:32:30 +00:00
|
|
|
'Generate Salt\'s _syspaths.py file which allows tweaking some '
|
|
|
|
'common paths that salt uses. This defaults to False on '
|
|
|
|
'develop/editable setups. If GENERATE_SALT_SYSPATHS is found in '
|
|
|
|
'the environment this flag is switched to True.'),
|
2015-08-18 22:18:09 +00:00
|
|
|
('mimic-salt-install', None,
|
2015-08-14 17:32:30 +00:00
|
|
|
'Mimmic the install command when running the develop command. '
|
|
|
|
'This will generate salt\'s _version.py and _syspaths.py files. '
|
|
|
|
'Generate Salt\'s _syspaths.py file which allows tweaking some '
|
|
|
|
'This defaults to False on develop/editable setups. '
|
|
|
|
'If MIMIC_INSTALL is found in the environment this flag is '
|
|
|
|
'switched to True.')
|
2015-08-14 16:59:40 +00:00
|
|
|
]
|
|
|
|
boolean_options = develop.boolean_options + [
|
2015-08-18 22:18:09 +00:00
|
|
|
'write-salt-version',
|
|
|
|
'generate-salt-syspaths',
|
|
|
|
'mimic-salt-install'
|
2015-08-14 16:59:40 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
def initialize_options(self):
|
|
|
|
develop.initialize_options(self)
|
|
|
|
self.write_salt_version = False
|
2015-08-14 17:32:30 +00:00
|
|
|
self.generate_salt_syspaths = False
|
|
|
|
self.mimic_salt_install = False
|
2015-08-14 16:59:40 +00:00
|
|
|
|
|
|
|
def finalize_options(self):
|
|
|
|
develop.finalize_options(self)
|
|
|
|
if 'WRITE_SALT_VERSION' in os.environ:
|
|
|
|
self.write_salt_version = True
|
2015-08-14 17:32:30 +00:00
|
|
|
if 'GENERATE_SALT_SYSPATHS' in os.environ:
|
|
|
|
self.generate_salt_syspaths = True
|
|
|
|
if 'MIMIC_SALT_INSTALL' in os.environ:
|
|
|
|
self.mimic_salt_install = True
|
|
|
|
|
|
|
|
if self.mimic_salt_install:
|
|
|
|
self.write_salt_version = True
|
|
|
|
self.generate_salt_syspaths = True
|
2015-08-14 16:59:40 +00:00
|
|
|
|
2015-08-14 14:27:03 +00:00
|
|
|
def run(self):
|
2015-08-14 15:27:31 +00:00
|
|
|
if IS_WINDOWS_PLATFORM:
|
|
|
|
if __saltstack_version__.info < (2015, 8): # pylint: disable=undefined-variable
|
|
|
|
# Install M2Crypto first
|
|
|
|
self.distribution.salt_installing_m2crypto_windows = True
|
|
|
|
self.run_command('install-m2crypto-windows')
|
|
|
|
self.distribution.salt_installing_m2crypto_windows = None
|
2015-08-14 16:20:12 +00:00
|
|
|
|
2017-03-10 21:52:38 +00:00
|
|
|
if not IS_PY3:
|
2015-08-14 15:27:31 +00:00
|
|
|
|
2017-03-10 21:52:38 +00:00
|
|
|
# Install PyCrypto
|
|
|
|
self.distribution.salt_installing_pycrypto_windows = True
|
|
|
|
self.run_command('install-pycrypto-windows')
|
|
|
|
self.distribution.salt_installing_pycrypto_windows = None
|
|
|
|
|
|
|
|
# Install PyYAML
|
|
|
|
self.distribution.salt_installing_pyyaml_windows = True
|
|
|
|
self.run_command('install-pyyaml-windows')
|
|
|
|
self.distribution.salt_installing_pyyaml_windows = None
|
2016-09-06 23:36:38 +00:00
|
|
|
|
2015-08-14 16:20:12 +00:00
|
|
|
# Download the required DLLs
|
|
|
|
self.distribution.salt_download_windows_dlls = True
|
|
|
|
self.run_command('download-windows-dlls')
|
|
|
|
self.distribution.salt_download_windows_dlls = None
|
2015-08-14 16:59:40 +00:00
|
|
|
|
|
|
|
if self.write_salt_version is True:
|
2015-08-14 17:32:30 +00:00
|
|
|
self.distribution.running_salt_install = True
|
2015-08-14 16:59:40 +00:00
|
|
|
self.distribution.salt_version_hardcoded_path = SALT_VERSION_HARDCODED
|
2015-08-17 22:54:16 +00:00
|
|
|
self.run_command('write_salt_version')
|
2015-08-14 17:32:30 +00:00
|
|
|
|
|
|
|
if self.generate_salt_syspaths:
|
|
|
|
self.distribution.salt_syspaths_hardcoded_path = SALT_SYSPATHS_HARDCODED
|
2015-08-17 22:54:16 +00:00
|
|
|
self.run_command('generate_salt_syspaths')
|
2015-08-14 17:32:30 +00:00
|
|
|
|
|
|
|
# Resume normal execution
|
2015-08-14 14:27:03 +00:00
|
|
|
develop.run(self)
|
|
|
|
|
|
|
|
|
2015-08-14 13:51:32 +00:00
|
|
|
class InstallM2CryptoWindows(Command):
|
|
|
|
|
|
|
|
description = 'Install M2CryptoWindows'
|
|
|
|
|
|
|
|
def initialize_options(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def finalize_options(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
if getattr(self.distribution, 'salt_installing_m2crypto_windows', None) is None:
|
|
|
|
print('This command is not meant to be called on it\'s own')
|
|
|
|
exit(1)
|
|
|
|
import platform
|
|
|
|
from pip.utils import call_subprocess
|
|
|
|
from pip.utils.logging import indent_log
|
|
|
|
platform_bits, _ = platform.architecture()
|
|
|
|
with indent_log():
|
|
|
|
call_subprocess(
|
|
|
|
['pip', 'install', '--egg', 'M2CryptoWin{0}'.format(platform_bits[:2])]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2015-08-14 15:27:31 +00:00
|
|
|
class InstallPyCryptoWindowsWheel(Command):
|
|
|
|
|
|
|
|
description = 'Install PyCrypto on Windows'
|
|
|
|
|
|
|
|
def initialize_options(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def finalize_options(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
if getattr(self.distribution, 'salt_installing_pycrypto_windows', None) is None:
|
|
|
|
print('This command is not meant to be called on it\'s own')
|
|
|
|
exit(1)
|
|
|
|
import platform
|
|
|
|
from pip.utils import call_subprocess
|
|
|
|
from pip.utils.logging import indent_log
|
|
|
|
platform_bits, _ = platform.architecture()
|
|
|
|
call_arguments = ['pip', 'install', 'wheel']
|
|
|
|
if platform_bits == '64bit':
|
|
|
|
call_arguments.append(
|
2016-09-16 21:43:36 +00:00
|
|
|
'https://repo.saltstack.com/windows/dependencies/64/pycrypto-2.6.1-cp27-none-win_amd64.whl'
|
2015-08-14 15:27:31 +00:00
|
|
|
)
|
|
|
|
else:
|
|
|
|
call_arguments.append(
|
2016-09-16 21:43:36 +00:00
|
|
|
'https://repo.saltstack.com/windows/dependencies/32/pycrypto-2.6.1-cp27-none-win32.whl'
|
2015-08-14 15:27:31 +00:00
|
|
|
)
|
|
|
|
with indent_log():
|
|
|
|
call_subprocess(call_arguments)
|
|
|
|
|
2017-03-09 13:49:08 +00:00
|
|
|
|
2017-01-27 21:52:21 +00:00
|
|
|
def uri_to_resource(resource_file):
|
2017-03-09 13:49:08 +00:00
|
|
|
# ## Returns the URI for a resource
|
2017-01-27 21:52:21 +00:00
|
|
|
# The basic case is that the resource is on saltstack.com
|
|
|
|
# It could be the case that the resource is cached.
|
2017-03-09 13:49:08 +00:00
|
|
|
salt_uri = 'https://repo.saltstack.com/windows/dependencies/' + resource_file
|
|
|
|
if os.getenv('SALTREPO_LOCAL_CACHE') is None:
|
2017-01-27 21:52:21 +00:00
|
|
|
# if environment variable not set, return the basic case
|
|
|
|
return salt_uri
|
|
|
|
if not os.path.isdir(os.getenv('SALTREPO_LOCAL_CACHE')):
|
|
|
|
# if environment variable is not a directory, return the basic case
|
|
|
|
return salt_uri
|
|
|
|
cached_resource = os.path.join(os.getenv('SALTREPO_LOCAL_CACHE'), resource_file)
|
|
|
|
cached_resource = cached_resource.replace('/', '\\')
|
|
|
|
if not os.path.isfile(cached_resource):
|
2017-03-09 13:49:08 +00:00
|
|
|
# if file does not exist, return the basic case
|
2017-01-27 21:52:21 +00:00
|
|
|
return salt_uri
|
|
|
|
if os.path.getsize(cached_resource) == 0:
|
2017-03-09 13:49:08 +00:00
|
|
|
# if file has zero size, return the basic case
|
|
|
|
return salt_uri
|
2017-01-27 21:52:21 +00:00
|
|
|
return cached_resource
|
|
|
|
|
2017-03-09 13:49:08 +00:00
|
|
|
|
2016-09-06 23:36:38 +00:00
|
|
|
class InstallCompiledPyYaml(Command):
|
|
|
|
|
|
|
|
description = 'Install PyYAML on Windows'
|
|
|
|
|
|
|
|
def initialize_options(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def finalize_options(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
if getattr(self.distribution, 'salt_installing_pyyaml_windows', None) is None:
|
|
|
|
print('This command is not meant to be called on it\'s own')
|
|
|
|
exit(1)
|
|
|
|
import platform
|
|
|
|
from pip.utils import call_subprocess
|
|
|
|
from pip.utils.logging import indent_log
|
|
|
|
platform_bits, _ = platform.architecture()
|
|
|
|
call_arguments = ['easy_install', '-Z']
|
|
|
|
if platform_bits == '64bit':
|
|
|
|
call_arguments.append(
|
2017-01-27 21:52:21 +00:00
|
|
|
uri_to_resource('64/PyYAML-3.11.win-amd64-py2.7.exe')
|
2016-09-06 23:36:38 +00:00
|
|
|
)
|
|
|
|
else:
|
|
|
|
call_arguments.append(
|
2017-01-27 21:52:21 +00:00
|
|
|
uri_to_resource('32/PyYAML-3.11.win32-py2.7.exe')
|
2016-09-06 23:36:38 +00:00
|
|
|
)
|
|
|
|
with indent_log():
|
|
|
|
call_subprocess(call_arguments)
|
|
|
|
|
|
|
|
|
2015-08-14 16:20:12 +00:00
|
|
|
class DownloadWindowsDlls(Command):
|
|
|
|
|
|
|
|
description = 'Download required DLL\'s for windows'
|
|
|
|
|
|
|
|
def initialize_options(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def finalize_options(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
if getattr(self.distribution, 'salt_download_windows_dlls', None) is None:
|
|
|
|
print('This command is not meant to be called on it\'s own')
|
|
|
|
exit(1)
|
|
|
|
import platform
|
|
|
|
from pip.utils.logging import indent_log
|
|
|
|
platform_bits, _ = platform.architecture()
|
2016-09-16 21:43:36 +00:00
|
|
|
url = 'https://repo.saltstack.com/windows/dependencies/{bits}/{fname}.dll'
|
2016-09-06 23:36:38 +00:00
|
|
|
dest = os.path.join(os.path.dirname(sys.executable), '{fname}.dll')
|
2015-08-14 16:20:12 +00:00
|
|
|
with indent_log():
|
2016-09-06 23:36:38 +00:00
|
|
|
for fname in ('libeay32', 'ssleay32', 'libsodium', 'msvcr120'):
|
2016-09-20 15:31:13 +00:00
|
|
|
# See if the library is already on the system
|
|
|
|
if find_library(fname):
|
|
|
|
continue
|
2015-08-14 16:20:12 +00:00
|
|
|
furl = url.format(bits=platform_bits[:2], fname=fname)
|
|
|
|
fdest = dest.format(fname=fname)
|
|
|
|
if not os.path.exists(fdest):
|
2016-09-06 23:36:38 +00:00
|
|
|
log.info('Downloading {0}.dll to {1} from {2}'.format(fname, fdest, furl))
|
2015-08-14 16:20:12 +00:00
|
|
|
try:
|
|
|
|
import requests
|
|
|
|
from contextlib import closing
|
2015-08-14 16:35:38 +00:00
|
|
|
with closing(requests.get(furl, stream=True)) as req:
|
2015-08-14 16:20:12 +00:00
|
|
|
if req.status_code == 200:
|
2015-09-28 16:51:53 +00:00
|
|
|
with open(fdest, 'wb') as wfh:
|
2015-08-14 16:20:12 +00:00
|
|
|
for chunk in req.iter_content(chunk_size=4096):
|
|
|
|
if chunk: # filter out keep-alive new chunks
|
|
|
|
wfh.write(chunk)
|
|
|
|
wfh.flush()
|
|
|
|
else:
|
|
|
|
log.error(
|
2016-09-06 23:36:38 +00:00
|
|
|
'Failed to download {0}.dll to {1} from {2}'.format(
|
2015-08-14 16:20:12 +00:00
|
|
|
fname, fdest, furl
|
|
|
|
)
|
|
|
|
)
|
|
|
|
except ImportError:
|
2015-08-14 16:35:38 +00:00
|
|
|
req = urlopen(furl)
|
2015-08-14 16:20:12 +00:00
|
|
|
|
|
|
|
if req.getcode() == 200:
|
2015-09-28 16:51:53 +00:00
|
|
|
with open(fdest, 'wb') as wfh:
|
PY3 support for Windows master/minion using TCP transport
This allows masters and minions to run on Windows using Python 3. Tested
with Python 3.5.1 64-bit on Windows 7. Only the TCP transport has been
ported. It will likely not work with other transports such as ZeroMQ or
RAET without further work.
Since there were many changes necessary to make this work, here is a list
of common changes:
- Python 3 distinguishes `bytes` from `str`. In some cases `bytes` must be
used (eg read/write to binary file). In other cases `str` must be used
(eg general Salt dictionary look-ups, read/write to text file). Due to
this, there are a lot of extra uses of `salt.utils.to_bytes` in necessary
locations.
- Use `six.itervalues(varname)` instead of `varname.itervalues()`.
- In Python 2.6 and 2.7, the 'b' prefix is ignored. So instead of
```
if six.PY2:
some_var = 'some_value'
else:
some_var = b'some_value'
```
we choose to simply use:
```
some_var = b'some_value'
```
`salt/engine/__init__.py`:
- In Python 3, `engine.items()` will return an iterator instead of
a list. Due to this, needed to change `engine.items()[0]` to
`list(engine.items())[0]`.
`salt/minion.py`:
- `contextlib.nested` no longer supported in Python 3. Use
`contextlib.ExitStack` in this case.
- In `Minion.handle_event`, in PY3, `package` is of type `bytes` and `tag`
is of type `str`. Due to this, do all string searches via `tag` instead
of `package` since you can't search for a `str` in a `bytes` object.
`salt/payload.py`:
- Added `encoding` parameter to `Serial.loads`. See description in comments
for details.
- Added `use_bin_type` parameter to `Serial.dumps`. See description in
comments for details.
- When reading / writing local files, encode using `use_bin_type=True` and
decode using `encoding='utf-8'` to distinguish `bytes` and `str` types.
`salt/transport/frame.py`:
- Added `frame_msg_ipc`. This is used for IPC communications where it is
safe to break the wire protocol and so we encode using `use_bin_type=True`.
- Added `decode_embedded_strs`. This is used when it is not safe to break
the wire protocol (eg external communications). This will convert `bytes`
objects to `str` objects if possible. This will search for such objects
within dicts and lists.
`salt/transport/ipc.py`:
- Use `salt.transport.frame.frame_msg_ipc` to encode using
`use_bin_type=True`.
- Use `encoding='utf-8'` to decode such messages and ensure proper
distinction of `bytes` and `str` types.
`salt/transport/tpc.py`:
- Since we need to preserve the wire protocol, we don't use
`use_bin_type=True`. When decoding, we use `decode_embedded_strs` to
convert the embedded `bytes` objects that can be converted to `str`.
- `urlparse` doesn't exist in PY3. Use `urllib.parse` instead.
- `sys.maxint` not supported in PY3. Use `int((1 << 31) - 1)` instead.
Hence `sys.maxint - 1` becomes `int((1 << 31) - 2)`.
`salt/utils/__init__.py`:
- `libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c"))` returns
`TypeError` in PY3. This is because `ctypes.util.find_library("c")`
returns `None` and in PY3 `ctypes.cdll.LoadLibrary(None)` is a
`TypeError`.
- On Windows, `salt.utils.fopen` would always read and write files in
binary mode. This has been changed for Python 3 since `bytes` must be
used for binary mode and `str` must be used for text mode and forcing
binary mode would screw things up if you want to read/write to `str`
objects. Preserved original behavior on PY2.
- For `salt.utils.fopen`, when reading and writing text files in PY3, if
an encoding is not specified, it will choose 'utf-8'.
`salt/utils/args.py`:
- In Python 3.5, every time `inspect.getargsspec` is used, a warning would
appear announcing its deprecation (it will be removed entirely in Python
3.6). Due to this, implemented our own version using
`inspect.getfullargspec`.
`salt/utils/event.py`:
- Since all functionality here is used only in IPC (the mechanism for
firing an event from minion to master is outside this file), we can break
the wire protocol and hence encode using `use_bin_type=True` and decode
using `encoding='utf-8'`.
`salt/utils/vt.py`:
- `_subprocess` is not available in PY3 under Windows, so we use an
alternate method to invoke `TerminateProcess` and `GetExitCodeProcess`.
`setup.py`:
- In PY3, `req.read(4096)` returns a `bytes` object. If you try to for
loop through it, each element is an `int` which represents an individual
byte. Trying to write an `int` to `wfh.write` raises an exception. Due to
this, use an alternate approach when writing from a
`http.client.HTTPResponse` object to file in PY3.
Signed-off-by: Sergey Kizunov <sergey.kizunov@ni.com>
2016-03-18 18:51:12 +00:00
|
|
|
if IS_PY3:
|
|
|
|
while True:
|
|
|
|
chunk = req.read(4096)
|
|
|
|
if len(chunk) == 0:
|
2017-03-09 13:49:08 +00:00
|
|
|
break
|
2015-08-14 16:20:12 +00:00
|
|
|
wfh.write(chunk)
|
|
|
|
wfh.flush()
|
PY3 support for Windows master/minion using TCP transport
This allows masters and minions to run on Windows using Python 3. Tested
with Python 3.5.1 64-bit on Windows 7. Only the TCP transport has been
ported. It will likely not work with other transports such as ZeroMQ or
RAET without further work.
Since there were many changes necessary to make this work, here is a list
of common changes:
- Python 3 distinguishes `bytes` from `str`. In some cases `bytes` must be
used (eg read/write to binary file). In other cases `str` must be used
(eg general Salt dictionary look-ups, read/write to text file). Due to
this, there are a lot of extra uses of `salt.utils.to_bytes` in necessary
locations.
- Use `six.itervalues(varname)` instead of `varname.itervalues()`.
- In Python 2.6 and 2.7, the 'b' prefix is ignored. So instead of
```
if six.PY2:
some_var = 'some_value'
else:
some_var = b'some_value'
```
we choose to simply use:
```
some_var = b'some_value'
```
`salt/engine/__init__.py`:
- In Python 3, `engine.items()` will return an iterator instead of
a list. Due to this, needed to change `engine.items()[0]` to
`list(engine.items())[0]`.
`salt/minion.py`:
- `contextlib.nested` no longer supported in Python 3. Use
`contextlib.ExitStack` in this case.
- In `Minion.handle_event`, in PY3, `package` is of type `bytes` and `tag`
is of type `str`. Due to this, do all string searches via `tag` instead
of `package` since you can't search for a `str` in a `bytes` object.
`salt/payload.py`:
- Added `encoding` parameter to `Serial.loads`. See description in comments
for details.
- Added `use_bin_type` parameter to `Serial.dumps`. See description in
comments for details.
- When reading / writing local files, encode using `use_bin_type=True` and
decode using `encoding='utf-8'` to distinguish `bytes` and `str` types.
`salt/transport/frame.py`:
- Added `frame_msg_ipc`. This is used for IPC communications where it is
safe to break the wire protocol and so we encode using `use_bin_type=True`.
- Added `decode_embedded_strs`. This is used when it is not safe to break
the wire protocol (eg external communications). This will convert `bytes`
objects to `str` objects if possible. This will search for such objects
within dicts and lists.
`salt/transport/ipc.py`:
- Use `salt.transport.frame.frame_msg_ipc` to encode using
`use_bin_type=True`.
- Use `encoding='utf-8'` to decode such messages and ensure proper
distinction of `bytes` and `str` types.
`salt/transport/tpc.py`:
- Since we need to preserve the wire protocol, we don't use
`use_bin_type=True`. When decoding, we use `decode_embedded_strs` to
convert the embedded `bytes` objects that can be converted to `str`.
- `urlparse` doesn't exist in PY3. Use `urllib.parse` instead.
- `sys.maxint` not supported in PY3. Use `int((1 << 31) - 1)` instead.
Hence `sys.maxint - 1` becomes `int((1 << 31) - 2)`.
`salt/utils/__init__.py`:
- `libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c"))` returns
`TypeError` in PY3. This is because `ctypes.util.find_library("c")`
returns `None` and in PY3 `ctypes.cdll.LoadLibrary(None)` is a
`TypeError`.
- On Windows, `salt.utils.fopen` would always read and write files in
binary mode. This has been changed for Python 3 since `bytes` must be
used for binary mode and `str` must be used for text mode and forcing
binary mode would screw things up if you want to read/write to `str`
objects. Preserved original behavior on PY2.
- For `salt.utils.fopen`, when reading and writing text files in PY3, if
an encoding is not specified, it will choose 'utf-8'.
`salt/utils/args.py`:
- In Python 3.5, every time `inspect.getargsspec` is used, a warning would
appear announcing its deprecation (it will be removed entirely in Python
3.6). Due to this, implemented our own version using
`inspect.getfullargspec`.
`salt/utils/event.py`:
- Since all functionality here is used only in IPC (the mechanism for
firing an event from minion to master is outside this file), we can break
the wire protocol and hence encode using `use_bin_type=True` and decode
using `encoding='utf-8'`.
`salt/utils/vt.py`:
- `_subprocess` is not available in PY3 under Windows, so we use an
alternate method to invoke `TerminateProcess` and `GetExitCodeProcess`.
`setup.py`:
- In PY3, `req.read(4096)` returns a `bytes` object. If you try to for
loop through it, each element is an `int` which represents an individual
byte. Trying to write an `int` to `wfh.write` raises an exception. Due to
this, use an alternate approach when writing from a
`http.client.HTTPResponse` object to file in PY3.
Signed-off-by: Sergey Kizunov <sergey.kizunov@ni.com>
2016-03-18 18:51:12 +00:00
|
|
|
else:
|
|
|
|
while True:
|
|
|
|
for chunk in req.read(4096):
|
|
|
|
if not chunk:
|
|
|
|
break
|
|
|
|
wfh.write(chunk)
|
|
|
|
wfh.flush()
|
2015-08-14 16:20:12 +00:00
|
|
|
else:
|
|
|
|
log.error(
|
2016-09-06 23:36:38 +00:00
|
|
|
'Failed to download {0}.dll to {1} from {2}'.format(
|
2015-08-14 16:20:12 +00:00
|
|
|
fname, fdest, furl
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2014-08-01 18:10:49 +00:00
|
|
|
class Sdist(sdist):
|
2014-10-01 19:47:03 +00:00
|
|
|
|
2014-08-01 18:10:49 +00:00
|
|
|
def make_release_tree(self, base_dir, files):
|
2014-10-05 19:05:26 +00:00
|
|
|
if self.distribution.ssh_packaging:
|
2014-10-01 19:47:03 +00:00
|
|
|
self.distribution.salt_ssh_packaging_file = PACKAGED_FOR_SALT_SSH_FILE
|
2015-03-09 06:03:38 +00:00
|
|
|
self.run_command('write_salt_ssh_packaging_file')
|
2014-10-01 20:39:37 +00:00
|
|
|
self.filelist.files.append(os.path.basename(PACKAGED_FOR_SALT_SSH_FILE))
|
|
|
|
|
2014-08-01 18:10:49 +00:00
|
|
|
sdist.make_release_tree(self, base_dir, files)
|
|
|
|
|
|
|
|
# Let's generate salt/_version.py to include in the sdist tarball
|
|
|
|
self.distribution.running_salt_sdist = True
|
|
|
|
self.distribution.salt_version_hardcoded_path = os.path.join(
|
|
|
|
base_dir, 'salt', '_version.py'
|
|
|
|
)
|
2015-03-09 06:03:38 +00:00
|
|
|
self.run_command('write_salt_version')
|
2014-08-01 18:10:49 +00:00
|
|
|
|
2014-10-01 19:47:03 +00:00
|
|
|
def make_distribution(self):
|
|
|
|
sdist.make_distribution(self)
|
2014-10-05 19:05:26 +00:00
|
|
|
if self.distribution.ssh_packaging:
|
2014-10-01 19:47:03 +00:00
|
|
|
os.unlink(PACKAGED_FOR_SALT_SSH_FILE)
|
|
|
|
|
2014-08-01 18:10:49 +00:00
|
|
|
|
2017-03-09 13:49:08 +00:00
|
|
|
class CloudSdist(Sdist): # pylint: disable=too-many-ancestors
|
2014-10-01 19:47:03 +00:00
|
|
|
user_options = Sdist.user_options + [
|
2014-01-03 01:24:17 +00:00
|
|
|
('download-bootstrap-script', None,
|
|
|
|
'Download the latest stable bootstrap-salt.sh script. This '
|
|
|
|
'can also be triggered by having `DOWNLOAD_BOOTSTRAP_SCRIPT=1` as an '
|
|
|
|
'environment variable.')
|
|
|
|
|
2013-11-14 18:06:12 +00:00
|
|
|
]
|
2014-10-01 19:47:03 +00:00
|
|
|
boolean_options = Sdist.boolean_options + [
|
2014-01-03 01:24:17 +00:00
|
|
|
'download-bootstrap-script'
|
2013-11-14 18:06:12 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
def initialize_options(self):
|
2014-08-01 18:10:49 +00:00
|
|
|
Sdist.initialize_options(self)
|
|
|
|
self.skip_bootstrap_download = True
|
2014-01-03 01:24:17 +00:00
|
|
|
self.download_bootstrap_script = False
|
2013-11-14 18:06:12 +00:00
|
|
|
|
|
|
|
def finalize_options(self):
|
2014-08-01 18:10:49 +00:00
|
|
|
Sdist.finalize_options(self)
|
|
|
|
if 'SKIP_BOOTSTRAP_DOWNLOAD' in os.environ:
|
2017-03-09 13:49:08 +00:00
|
|
|
log('Please stop using \'SKIP_BOOTSTRAP_DOWNLOAD\' and use ' # pylint: disable=not-callable
|
2014-08-01 18:10:49 +00:00
|
|
|
'\'DOWNLOAD_BOOTSTRAP_SCRIPT\' instead')
|
|
|
|
|
2014-01-03 01:24:17 +00:00
|
|
|
if 'DOWNLOAD_BOOTSTRAP_SCRIPT' in os.environ:
|
|
|
|
download_bootstrap_script = os.environ.get(
|
|
|
|
'DOWNLOAD_BOOTSTRAP_SCRIPT', '0'
|
2013-11-14 18:06:12 +00:00
|
|
|
)
|
2014-01-03 01:24:17 +00:00
|
|
|
self.download_bootstrap_script = download_bootstrap_script == '1'
|
2013-11-14 18:06:12 +00:00
|
|
|
|
|
|
|
def run(self):
|
2014-01-03 01:24:17 +00:00
|
|
|
if self.download_bootstrap_script is True:
|
2013-11-14 18:06:12 +00:00
|
|
|
# Let's update the bootstrap-script to the version defined to be
|
|
|
|
# distributed. See BOOTSTRAP_SCRIPT_DISTRIBUTED_VERSION above.
|
|
|
|
url = (
|
|
|
|
'https://github.com/saltstack/salt-bootstrap/raw/{0}'
|
|
|
|
'/bootstrap-salt.sh'.format(
|
|
|
|
BOOTSTRAP_SCRIPT_DISTRIBUTED_VERSION
|
|
|
|
)
|
|
|
|
)
|
|
|
|
deploy_path = os.path.join(
|
2013-11-14 18:18:51 +00:00
|
|
|
SETUP_DIRNAME,
|
|
|
|
'salt',
|
|
|
|
'cloud',
|
2013-11-14 18:06:12 +00:00
|
|
|
'deploy',
|
|
|
|
'bootstrap-salt.sh'
|
|
|
|
)
|
2014-06-17 14:19:03 +00:00
|
|
|
log.info(
|
|
|
|
'Updating bootstrap-salt.sh.'
|
|
|
|
'\n\tSource: {0}'
|
|
|
|
'\n\tDestination: {1}'.format(
|
|
|
|
url,
|
|
|
|
deploy_path
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
try:
|
|
|
|
import requests
|
|
|
|
req = requests.get(url)
|
|
|
|
if req.status_code == 200:
|
|
|
|
script_contents = req.text.encode(req.encoding)
|
|
|
|
else:
|
|
|
|
log.error(
|
|
|
|
'Failed to update the bootstrap-salt.sh script. HTTP '
|
|
|
|
'Error code: {0}'.format(
|
|
|
|
req.status_code
|
2013-11-14 18:06:12 +00:00
|
|
|
)
|
|
|
|
)
|
2014-06-17 14:19:03 +00:00
|
|
|
except ImportError:
|
2014-11-07 16:50:11 +00:00
|
|
|
req = urlopen(url)
|
2014-06-17 14:19:03 +00:00
|
|
|
|
|
|
|
if req.getcode() == 200:
|
|
|
|
script_contents = req.read()
|
|
|
|
else:
|
2013-11-14 18:06:12 +00:00
|
|
|
log.error(
|
2014-06-17 14:19:03 +00:00
|
|
|
'Failed to update the bootstrap-salt.sh script. HTTP '
|
|
|
|
'Error code: {0}'.format(
|
|
|
|
req.getcode()
|
|
|
|
)
|
2013-11-14 18:06:12 +00:00
|
|
|
)
|
2014-06-17 14:19:03 +00:00
|
|
|
try:
|
|
|
|
with open(deploy_path, 'w') as fp_:
|
|
|
|
fp_.write(script_contents)
|
|
|
|
except (OSError, IOError) as err:
|
2013-11-14 18:06:12 +00:00
|
|
|
log.error(
|
2014-06-17 14:19:03 +00:00
|
|
|
'Failed to write the updated script: {0}'.format(err)
|
2013-11-14 18:06:12 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
# Let's the rest of the build command
|
2014-08-01 18:10:49 +00:00
|
|
|
Sdist.run(self)
|
2013-11-14 18:06:12 +00:00
|
|
|
|
2013-11-14 08:22:17 +00:00
|
|
|
def write_manifest(self):
|
2014-10-05 19:05:26 +00:00
|
|
|
# We only need to ship the scripts which are supposed to be installed
|
|
|
|
dist_scripts = self.distribution.scripts
|
|
|
|
for script in self.filelist.files[:]:
|
|
|
|
if not script.startswith('scripts/'):
|
|
|
|
continue
|
|
|
|
if script not in dist_scripts:
|
|
|
|
self.filelist.files.remove(script)
|
2014-08-01 18:10:49 +00:00
|
|
|
return Sdist.write_manifest(self)
|
2013-11-14 08:22:17 +00:00
|
|
|
|
2013-11-14 18:06:12 +00:00
|
|
|
|
2011-12-22 01:36:26 +00:00
|
|
|
class TestCommand(Command):
|
|
|
|
description = 'Run tests'
|
2012-09-29 18:41:21 +00:00
|
|
|
user_options = [
|
|
|
|
('runtests-opts=', 'R', 'Command line options to pass to runtests.py')
|
|
|
|
]
|
2012-06-30 20:35:31 +00:00
|
|
|
|
|
|
|
def initialize_options(self):
|
2012-09-29 18:41:21 +00:00
|
|
|
self.runtests_opts = None
|
2012-06-30 20:35:31 +00:00
|
|
|
|
|
|
|
def finalize_options(self):
|
2015-08-16 04:04:51 +00:00
|
|
|
'''
|
|
|
|
Abstract method that is required to be overwritten
|
|
|
|
'''
|
2012-06-30 20:35:31 +00:00
|
|
|
|
2011-12-22 01:36:26 +00:00
|
|
|
def run(self):
|
|
|
|
from subprocess import Popen
|
|
|
|
self.run_command('build')
|
|
|
|
build_cmd = self.get_finalized_command('build_ext')
|
|
|
|
runner = os.path.abspath('tests/runtests.py')
|
2013-01-18 01:05:45 +00:00
|
|
|
test_cmd = sys.executable + ' {0}'.format(runner)
|
2012-09-29 18:41:21 +00:00
|
|
|
if self.runtests_opts:
|
|
|
|
test_cmd += ' {0}'.format(self.runtests_opts)
|
|
|
|
|
2013-05-21 23:36:31 +00:00
|
|
|
print('running test')
|
2011-12-22 01:36:26 +00:00
|
|
|
test_process = Popen(
|
|
|
|
test_cmd, shell=True,
|
|
|
|
stdout=sys.stdout, stderr=sys.stderr,
|
|
|
|
cwd=build_cmd.build_lib
|
|
|
|
)
|
|
|
|
test_process.communicate()
|
2012-05-05 11:53:39 +00:00
|
|
|
sys.exit(test_process.returncode)
|
2011-12-22 01:36:26 +00:00
|
|
|
|
2012-10-12 14:51:28 +00:00
|
|
|
|
|
|
|
class Clean(clean):
|
|
|
|
def run(self):
|
|
|
|
clean.run(self)
|
|
|
|
# Let's clean compiled *.py[c,o]
|
2013-09-26 16:44:14 +00:00
|
|
|
for subdir in ('salt', 'tests', 'doc'):
|
2012-10-12 14:51:28 +00:00
|
|
|
root = os.path.join(os.path.dirname(__file__), subdir)
|
2014-10-05 19:05:26 +00:00
|
|
|
for dirname, _, _ in os.walk(root):
|
2014-08-01 18:10:49 +00:00
|
|
|
for to_remove_filename in glob.glob('{0}/*.py[oc]'.format(dirname)):
|
2013-11-12 05:10:41 +00:00
|
|
|
os.remove(to_remove_filename)
|
2012-10-12 14:51:28 +00:00
|
|
|
|
|
|
|
|
2013-08-23 22:17:13 +00:00
|
|
|
INSTALL_VERSION_TEMPLATE = '''\
|
2013-02-06 04:23:56 +00:00
|
|
|
# This file was auto-generated by salt's setup on \
|
2013-03-14 03:36:50 +00:00
|
|
|
{date:%A, %d %B %Y @ %H:%m:%S UTC}.
|
2013-02-06 04:23:56 +00:00
|
|
|
|
2014-05-06 04:43:22 +00:00
|
|
|
from salt.version import SaltStackVersion
|
|
|
|
|
2015-08-31 11:12:43 +00:00
|
|
|
__saltstack_version__ = SaltStackVersion{full_version_info!r}
|
2013-05-21 23:36:31 +00:00
|
|
|
'''
|
2013-02-06 04:23:56 +00:00
|
|
|
|
|
|
|
|
2013-09-19 10:42:09 +00:00
|
|
|
INSTALL_SYSPATHS_TEMPLATE = '''\
|
2013-08-23 22:58:26 +00:00
|
|
|
# This file was auto-generated by salt's setup on \
|
|
|
|
{date:%A, %d %B %Y @ %H:%m:%S UTC}.
|
|
|
|
|
2015-08-31 11:12:43 +00:00
|
|
|
ROOT_DIR = {root_dir!r}
|
2017-03-02 12:17:42 +00:00
|
|
|
SHARE_DIR = {share_dir!r}
|
2015-08-31 11:12:43 +00:00
|
|
|
CONFIG_DIR = {config_dir!r}
|
|
|
|
CACHE_DIR = {cache_dir!r}
|
|
|
|
SOCK_DIR = {sock_dir!r}
|
|
|
|
SRV_ROOT_DIR= {srv_root_dir!r}
|
|
|
|
BASE_FILE_ROOTS_DIR = {base_file_roots_dir!r}
|
|
|
|
BASE_PILLAR_ROOTS_DIR = {base_pillar_roots_dir!r}
|
|
|
|
BASE_MASTER_ROOTS_DIR = {base_master_roots_dir!r}
|
2016-02-02 17:49:23 +00:00
|
|
|
BASE_THORIUM_ROOTS_DIR = {base_thorium_roots_dir!r}
|
2015-08-31 11:12:43 +00:00
|
|
|
LOGS_DIR = {logs_dir!r}
|
|
|
|
PIDFILE_DIR = {pidfile_dir!r}
|
|
|
|
SPM_FORMULA_PATH = {spm_formula_path!r}
|
|
|
|
SPM_PILLAR_PATH = {spm_pillar_path!r}
|
|
|
|
SPM_REACTOR_PATH = {spm_reactor_path!r}
|
2013-08-23 22:58:26 +00:00
|
|
|
'''
|
|
|
|
|
|
|
|
|
2013-02-06 04:23:56 +00:00
|
|
|
class Build(build):
|
|
|
|
def run(self):
|
|
|
|
# Run build.run function
|
|
|
|
build.run(self)
|
|
|
|
if getattr(self.distribution, 'running_salt_install', False):
|
2013-08-23 22:58:26 +00:00
|
|
|
# If our install attribute is present and set to True, we'll go
|
|
|
|
# ahead and write our install time python modules.
|
|
|
|
|
2014-08-01 18:10:49 +00:00
|
|
|
# Write the hardcoded salt version module salt/_version.py
|
2015-03-09 06:03:38 +00:00
|
|
|
self.run_command('write_salt_version')
|
2013-02-06 04:23:56 +00:00
|
|
|
|
2013-08-23 22:58:26 +00:00
|
|
|
# Write the system paths file
|
2015-08-14 17:32:30 +00:00
|
|
|
self.distribution.salt_syspaths_hardcoded_path = os.path.join(
|
2013-08-23 22:58:26 +00:00
|
|
|
self.build_lib, 'salt', '_syspaths.py'
|
|
|
|
)
|
2015-08-17 22:54:16 +00:00
|
|
|
self.run_command('generate_salt_syspaths')
|
2013-08-23 22:58:26 +00:00
|
|
|
|
2013-02-06 04:23:56 +00:00
|
|
|
|
|
|
|
class Install(install):
|
2013-08-23 22:58:26 +00:00
|
|
|
def initialize_options(self):
|
|
|
|
install.initialize_options(self)
|
|
|
|
|
|
|
|
def finalize_options(self):
|
|
|
|
install.finalize_options(self)
|
2014-10-01 19:47:03 +00:00
|
|
|
|
2013-02-06 04:23:56 +00:00
|
|
|
def run(self):
|
|
|
|
# Let's set the running_salt_install attribute so we can add
|
|
|
|
# _version.py in the build command
|
|
|
|
self.distribution.running_salt_install = True
|
2014-08-01 18:10:49 +00:00
|
|
|
self.distribution.salt_version_hardcoded_path = os.path.join(
|
|
|
|
self.build_lib, 'salt', '_version.py'
|
|
|
|
)
|
2015-08-14 15:27:31 +00:00
|
|
|
if IS_WINDOWS_PLATFORM:
|
|
|
|
if __saltstack_version__.info < (2015, 8): # pylint: disable=undefined-variable
|
|
|
|
# Install M2Crypto first
|
|
|
|
self.distribution.salt_installing_m2crypto_windows = True
|
|
|
|
self.run_command('install-m2crypto-windows')
|
|
|
|
self.distribution.salt_installing_m2crypto_windows = None
|
2017-03-10 21:52:38 +00:00
|
|
|
|
|
|
|
if not IS_PY3:
|
|
|
|
# Install PyCrypto
|
|
|
|
self.distribution.salt_installing_pycrypto_windows = True
|
|
|
|
self.run_command('install-pycrypto-windows')
|
|
|
|
self.distribution.salt_installing_pycrypto_windows = None
|
|
|
|
|
|
|
|
# Install PyYAML
|
|
|
|
self.distribution.salt_installing_pyyaml_windows = True
|
|
|
|
self.run_command('install-pyyaml-windows')
|
|
|
|
self.distribution.salt_installing_pyyaml_windows = None
|
|
|
|
|
2015-08-14 16:20:12 +00:00
|
|
|
# Download the required DLLs
|
|
|
|
self.distribution.salt_download_windows_dlls = True
|
|
|
|
self.run_command('download-windows-dlls')
|
|
|
|
self.distribution.salt_download_windows_dlls = None
|
2013-02-06 04:23:56 +00:00
|
|
|
# Run install.run
|
|
|
|
install.run(self)
|
|
|
|
|
|
|
|
|
2014-03-17 16:56:31 +00:00
|
|
|
class InstallLib(install_lib):
|
|
|
|
def run(self):
|
2014-04-08 05:29:29 +00:00
|
|
|
executables = [
|
|
|
|
'salt/templates/git/ssh-id-wrapper',
|
|
|
|
'salt/templates/lxc/salt_tarball',
|
|
|
|
]
|
2014-03-17 16:56:31 +00:00
|
|
|
install_lib.run(self)
|
|
|
|
|
|
|
|
# input and outputs match 1-1
|
|
|
|
inp = self.get_inputs()
|
|
|
|
out = self.get_outputs()
|
2014-04-08 05:29:29 +00:00
|
|
|
chmod = []
|
2014-03-17 16:56:31 +00:00
|
|
|
|
2014-04-08 07:30:47 +00:00
|
|
|
for idx, inputfile in enumerate(inp):
|
2014-04-08 05:29:29 +00:00
|
|
|
for executeable in executables:
|
2014-04-08 07:30:47 +00:00
|
|
|
if inputfile.endswith(executeable):
|
|
|
|
chmod.append(idx)
|
2014-04-08 05:29:29 +00:00
|
|
|
for idx in chmod:
|
|
|
|
filename = out[idx]
|
2014-11-07 16:50:11 +00:00
|
|
|
os.chmod(filename, 0o755)
|
2014-06-17 14:19:03 +00:00
|
|
|
# <---- Custom Distutils/Setuptools Commands -------------------------------------------------------------------------
|
|
|
|
|
2014-11-04 17:42:03 +00:00
|
|
|
|
|
|
|
# ----- Custom Distribution Class ----------------------------------------------------------------------------------->
|
|
|
|
# We use this to override the package name in case --ssh-packaging is passed to
|
|
|
|
# setup.py or the special .salt-ssh-package is found
|
|
|
|
class SaltDistribution(distutils.dist.Distribution):
|
|
|
|
'''
|
|
|
|
Just so it's completely clear
|
|
|
|
|
|
|
|
Under windows, the following scripts should be installed:
|
|
|
|
|
|
|
|
* salt-call
|
|
|
|
* salt-cp
|
|
|
|
* salt-minion
|
|
|
|
* salt-unity
|
2015-09-04 18:05:14 +00:00
|
|
|
* salt-proxy
|
2014-11-04 17:42:03 +00:00
|
|
|
|
|
|
|
When packaged for salt-ssh, the following scripts should be installed:
|
|
|
|
* salt-call
|
|
|
|
* salt-run
|
|
|
|
* salt-ssh
|
|
|
|
* salt-cloud
|
|
|
|
|
|
|
|
Under windows, the following scripts should be omitted from the salt-ssh package:
|
|
|
|
* salt-cloud
|
|
|
|
* salt-run
|
|
|
|
|
|
|
|
Under *nix, all scripts should be installed
|
|
|
|
'''
|
|
|
|
global_options = distutils.dist.Distribution.global_options + [
|
|
|
|
('ssh-packaging', None, 'Run in SSH packaging mode'),
|
|
|
|
('salt-transport=', None, 'The transport to prepare salt for. Choices are \'zeromq\' '
|
2015-01-09 16:41:50 +00:00
|
|
|
'\'raet\' or \'both\'. Defaults to \'zeromq\'', 'zeromq')] + [
|
|
|
|
# Salt's Paths Configuration Settings
|
|
|
|
('salt-root-dir=', None,
|
|
|
|
'Salt\'s pre-configured root directory'),
|
2017-03-02 12:27:20 +00:00
|
|
|
('salt-share-dir=', None,
|
|
|
|
'Salt\'s pre-configured share directory'),
|
2015-01-09 16:41:50 +00:00
|
|
|
('salt-config-dir=', None,
|
|
|
|
'Salt\'s pre-configured configuration directory'),
|
|
|
|
('salt-cache-dir=', None,
|
|
|
|
'Salt\'s pre-configured cache directory'),
|
|
|
|
('salt-sock-dir=', None,
|
|
|
|
'Salt\'s pre-configured socket directory'),
|
|
|
|
('salt-srv-root-dir=', None,
|
|
|
|
'Salt\'s pre-configured service directory'),
|
|
|
|
('salt-base-file-roots-dir=', None,
|
|
|
|
'Salt\'s pre-configured file roots directory'),
|
|
|
|
('salt-base-pillar-roots-dir=', None,
|
|
|
|
'Salt\'s pre-configured pillar roots directory'),
|
|
|
|
('salt-base-master-roots-dir=', None,
|
|
|
|
'Salt\'s pre-configured master roots directory'),
|
|
|
|
('salt-logs-dir=', None,
|
|
|
|
'Salt\'s pre-configured logs directory'),
|
|
|
|
('salt-pidfile-dir=', None,
|
|
|
|
'Salt\'s pre-configured pidfiles directory'),
|
2015-08-28 00:22:14 +00:00
|
|
|
('salt-spm-formula-dir=', None,
|
|
|
|
'Salt\'s pre-configured SPM formulas directory'),
|
|
|
|
('salt-spm-pillar-dir=', None,
|
|
|
|
'Salt\'s pre-configured SPM pillar directory'),
|
|
|
|
('salt-spm-reactor-dir=', None,
|
|
|
|
'Salt\'s pre-configured SPM reactor directory'),
|
2014-11-04 17:42:03 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
def __init__(self, attrs=None):
|
|
|
|
distutils.dist.Distribution.__init__(self, attrs)
|
|
|
|
|
|
|
|
self.ssh_packaging = PACKAGED_FOR_SALT_SSH
|
|
|
|
self.salt_transport = None
|
|
|
|
|
2015-01-09 16:41:50 +00:00
|
|
|
# Salt Paths Configuration Settings
|
|
|
|
self.salt_root_dir = None
|
2017-03-02 12:17:42 +00:00
|
|
|
self.salt_share_dir = None
|
2015-01-09 16:41:50 +00:00
|
|
|
self.salt_config_dir = None
|
|
|
|
self.salt_cache_dir = None
|
|
|
|
self.salt_sock_dir = None
|
|
|
|
self.salt_srv_root_dir = None
|
|
|
|
self.salt_base_file_roots_dir = None
|
2016-02-02 17:49:23 +00:00
|
|
|
self.salt_base_thorium_roots_dir = None
|
2015-01-09 16:41:50 +00:00
|
|
|
self.salt_base_pillar_roots_dir = None
|
|
|
|
self.salt_base_master_roots_dir = None
|
|
|
|
self.salt_logs_dir = None
|
|
|
|
self.salt_pidfile_dir = None
|
2015-08-28 00:22:14 +00:00
|
|
|
self.salt_spm_formula_dir = None
|
|
|
|
self.salt_spm_pillar_dir = None
|
|
|
|
self.salt_spm_reactor_dir = None
|
2015-01-09 16:41:50 +00:00
|
|
|
|
2014-11-04 17:42:03 +00:00
|
|
|
self.name = 'salt-ssh' if PACKAGED_FOR_SALT_SSH else 'salt'
|
2015-03-11 19:21:26 +00:00
|
|
|
self.salt_version = __version__ # pylint: disable=undefined-variable
|
2014-11-04 17:42:03 +00:00
|
|
|
self.description = 'Portable, distributed, remote execution and configuration management system'
|
|
|
|
self.author = 'Thomas S Hatch'
|
|
|
|
self.author_email = 'thatch45@gmail.com'
|
|
|
|
self.url = 'http://saltstack.org'
|
|
|
|
self.cmdclass.update({'test': TestCommand,
|
|
|
|
'clean': Clean,
|
|
|
|
'build': Build,
|
|
|
|
'sdist': Sdist,
|
|
|
|
'install': Install,
|
2015-03-09 06:03:38 +00:00
|
|
|
'write_salt_version': WriteSaltVersion,
|
2015-08-17 22:54:16 +00:00
|
|
|
'generate_salt_syspaths': GenerateSaltSyspaths,
|
2015-08-16 04:04:51 +00:00
|
|
|
'write_salt_ssh_packaging_file': WriteSaltSshPackagingFile})
|
2014-11-04 17:42:03 +00:00
|
|
|
if not IS_WINDOWS_PLATFORM:
|
|
|
|
self.cmdclass.update({'sdist': CloudSdist,
|
|
|
|
'install_lib': InstallLib})
|
2015-08-14 15:27:31 +00:00
|
|
|
if IS_WINDOWS_PLATFORM:
|
2017-03-10 21:52:38 +00:00
|
|
|
if IS_PY3:
|
|
|
|
self.cmdclass.update({'download-windows-dlls': DownloadWindowsDlls})
|
|
|
|
else:
|
|
|
|
self.cmdclass.update({'install-pycrypto-windows': InstallPyCryptoWindowsWheel,
|
|
|
|
'install-pyyaml-windows': InstallCompiledPyYaml,
|
|
|
|
'download-windows-dlls': DownloadWindowsDlls})
|
2015-08-14 15:27:31 +00:00
|
|
|
if __saltstack_version__.info < (2015, 8): # pylint: disable=undefined-variable
|
|
|
|
self.cmdclass.update({'install-m2crypto-windows': InstallM2CryptoWindows})
|
2014-11-04 17:42:03 +00:00
|
|
|
|
2015-08-14 14:32:33 +00:00
|
|
|
if WITH_SETUPTOOLS:
|
|
|
|
self.cmdclass.update({'develop': Develop})
|
2014-11-04 17:42:03 +00:00
|
|
|
|
|
|
|
self.license = 'Apache Software License 2.0'
|
|
|
|
self.packages = self.discover_packages()
|
|
|
|
self.zip_safe = False
|
|
|
|
|
|
|
|
if HAS_ESKY:
|
|
|
|
self.setup_esky()
|
|
|
|
|
|
|
|
self.update_metadata()
|
|
|
|
|
|
|
|
def update_metadata(self):
|
|
|
|
for attrname in dir(self):
|
2014-11-08 00:44:40 +00:00
|
|
|
if attrname.startswith('__'):
|
|
|
|
continue
|
2014-11-04 17:42:03 +00:00
|
|
|
attrvalue = getattr(self, attrname, None)
|
|
|
|
if attrvalue == 0:
|
|
|
|
continue
|
2015-03-11 19:21:26 +00:00
|
|
|
if attrname == 'salt_version':
|
|
|
|
attrname = 'version'
|
2014-11-04 17:42:03 +00:00
|
|
|
if hasattr(self.metadata, 'set_{0}'.format(attrname)):
|
|
|
|
getattr(self.metadata, 'set_{0}'.format(attrname))(attrvalue)
|
|
|
|
elif hasattr(self.metadata, attrname):
|
2014-11-07 23:48:30 +00:00
|
|
|
try:
|
|
|
|
setattr(self.metadata, attrname, attrvalue)
|
|
|
|
except AttributeError:
|
|
|
|
pass
|
2014-11-04 17:42:03 +00:00
|
|
|
|
|
|
|
def discover_packages(self):
|
|
|
|
modules = []
|
|
|
|
for root, _, files in os.walk(os.path.join(SETUP_DIRNAME, 'salt')):
|
|
|
|
if '__init__.py' not in files:
|
|
|
|
continue
|
|
|
|
modules.append(os.path.relpath(root, SETUP_DIRNAME).replace(os.sep, '.'))
|
|
|
|
return modules
|
|
|
|
|
2015-01-27 07:12:35 +00:00
|
|
|
# ----- Static Data -------------------------------------------------------------------------------------------->
|
2014-11-04 17:42:03 +00:00
|
|
|
@property
|
|
|
|
def _property_classifiers(self):
|
|
|
|
return ['Programming Language :: Python',
|
|
|
|
'Programming Language :: Cython',
|
|
|
|
'Programming Language :: Python :: 2.6',
|
|
|
|
'Programming Language :: Python :: 2.7',
|
|
|
|
'Development Status :: 5 - Production/Stable',
|
|
|
|
'Environment :: Console',
|
|
|
|
'Intended Audience :: Developers',
|
|
|
|
'Intended Audience :: Information Technology',
|
|
|
|
'Intended Audience :: System Administrators',
|
|
|
|
'License :: OSI Approved :: Apache Software License',
|
|
|
|
'Operating System :: POSIX :: Linux',
|
|
|
|
'Topic :: System :: Clustering',
|
|
|
|
'Topic :: System :: Distributed Computing']
|
|
|
|
|
|
|
|
@property
|
|
|
|
def _property_dependency_links(self):
|
|
|
|
return ['https://github.com/saltstack/salt-testing/tarball/develop#egg=SaltTesting']
|
|
|
|
|
|
|
|
@property
|
|
|
|
def _property_tests_require(self):
|
|
|
|
return ['SaltTesting']
|
|
|
|
# <---- Static Data ----------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
# ----- Dynamic Data -------------------------------------------------------------------------------------------->
|
|
|
|
@property
|
|
|
|
def _property_package_data(self):
|
|
|
|
package_data = {'salt.templates': ['rh_ip/*.jinja',
|
|
|
|
'debian_ip/*.jinja',
|
|
|
|
'virt/*.jinja',
|
|
|
|
'git/*',
|
|
|
|
'lxc/*',
|
2017-03-09 13:49:08 +00:00
|
|
|
]}
|
2014-11-04 17:42:03 +00:00
|
|
|
if not IS_WINDOWS_PLATFORM:
|
|
|
|
package_data['salt.cloud'] = ['deploy/*.sh']
|
|
|
|
|
|
|
|
if not self.ssh_packaging and not PACKAGED_FOR_SALT_SSH:
|
|
|
|
package_data['salt.daemons.flo'] = ['*.flo']
|
|
|
|
return package_data
|
|
|
|
|
|
|
|
@property
|
|
|
|
def _property_data_files(self):
|
|
|
|
# Data files common to all scenarios
|
|
|
|
data_files = [
|
2016-02-04 21:14:55 +00:00
|
|
|
('share/man/man1', ['doc/man/salt-call.1', 'doc/man/salt-run.1']),
|
2014-11-04 17:42:03 +00:00
|
|
|
('share/man/man7', ['doc/man/salt.7'])
|
|
|
|
]
|
|
|
|
if self.ssh_packaging or PACKAGED_FOR_SALT_SSH:
|
|
|
|
data_files[0][1].append('doc/man/salt-ssh.1')
|
|
|
|
if IS_WINDOWS_PLATFORM:
|
|
|
|
return data_files
|
2016-02-04 21:14:55 +00:00
|
|
|
data_files[0][1].append('doc/man/salt-cloud.1')
|
|
|
|
|
2014-11-04 17:42:03 +00:00
|
|
|
return data_files
|
|
|
|
|
|
|
|
if IS_WINDOWS_PLATFORM:
|
|
|
|
data_files[0][1].extend(['doc/man/salt-cp.1',
|
2016-02-04 21:14:55 +00:00
|
|
|
'doc/man/salt-key.1',
|
|
|
|
'doc/man/salt-master.1',
|
2014-11-04 17:42:03 +00:00
|
|
|
'doc/man/salt-minion.1',
|
2015-09-01 23:09:35 +00:00
|
|
|
'doc/man/salt-proxy.1',
|
2014-11-04 17:42:03 +00:00
|
|
|
'doc/man/salt-unity.1'])
|
|
|
|
return data_files
|
|
|
|
|
|
|
|
# *nix, so, we need all man pages
|
|
|
|
data_files[0][1].extend(['doc/man/salt-api.1',
|
|
|
|
'doc/man/salt-cloud.1',
|
|
|
|
'doc/man/salt-cp.1',
|
|
|
|
'doc/man/salt-key.1',
|
|
|
|
'doc/man/salt-master.1',
|
2012-06-05 10:00:20 +00:00
|
|
|
'doc/man/salt-minion.1',
|
2015-09-01 23:09:35 +00:00
|
|
|
'doc/man/salt-proxy.1',
|
2015-07-09 01:25:09 +00:00
|
|
|
'doc/man/spm.1',
|
2016-02-05 21:23:30 +00:00
|
|
|
'doc/man/salt.1',
|
2014-10-05 19:05:26 +00:00
|
|
|
'doc/man/salt-ssh.1',
|
|
|
|
'doc/man/salt-syndic.1',
|
|
|
|
'doc/man/salt-unity.1'])
|
|
|
|
return data_files
|
2012-06-05 10:00:20 +00:00
|
|
|
|
2014-10-05 19:05:26 +00:00
|
|
|
@property
|
|
|
|
def _property_install_requires(self):
|
|
|
|
install_requires = _parse_requirements_file(SALT_REQS)
|
|
|
|
|
|
|
|
if IS_WINDOWS_PLATFORM:
|
2016-09-16 21:43:36 +00:00
|
|
|
install_requires += _parse_requirements_file(SALT_WINDOWS_REQS)
|
2014-10-05 19:05:26 +00:00
|
|
|
|
|
|
|
if self.salt_transport == 'zeromq':
|
|
|
|
install_requires += _parse_requirements_file(SALT_ZEROMQ_REQS)
|
|
|
|
elif self.salt_transport == 'raet':
|
|
|
|
install_requires += _parse_requirements_file(SALT_RAET_REQS)
|
|
|
|
return install_requires
|
|
|
|
|
|
|
|
@property
|
|
|
|
def _property_extras_require(self):
|
|
|
|
if self.ssh_packaging:
|
|
|
|
return {}
|
2015-06-17 16:00:17 +00:00
|
|
|
return {'RAET': _parse_requirements_file(SALT_RAET_REQS)}
|
2014-10-05 19:05:26 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def _property_scripts(self):
|
|
|
|
# Scripts common to all scenarios
|
2016-02-04 21:14:55 +00:00
|
|
|
scripts = ['scripts/salt-call', 'scripts/salt-run']
|
2014-10-05 19:05:26 +00:00
|
|
|
if self.ssh_packaging or PACKAGED_FOR_SALT_SSH:
|
|
|
|
scripts.append('scripts/salt-ssh')
|
|
|
|
if IS_WINDOWS_PLATFORM:
|
|
|
|
return scripts
|
2016-02-04 21:14:55 +00:00
|
|
|
scripts.extend(['scripts/salt-cloud', 'scripts/spm'])
|
2014-10-05 19:05:26 +00:00
|
|
|
return scripts
|
|
|
|
|
|
|
|
if IS_WINDOWS_PLATFORM:
|
2016-02-04 21:14:55 +00:00
|
|
|
scripts.extend(['scripts/salt',
|
|
|
|
'scripts/salt-cp',
|
|
|
|
'scripts/salt-key',
|
|
|
|
'scripts/salt-master',
|
2014-10-05 19:05:26 +00:00
|
|
|
'scripts/salt-minion',
|
2015-09-04 18:05:14 +00:00
|
|
|
'scripts/salt-proxy',
|
2014-10-05 19:05:26 +00:00
|
|
|
'scripts/salt-unity'])
|
|
|
|
return scripts
|
|
|
|
|
|
|
|
# *nix, so, we need all scripts
|
|
|
|
scripts.extend(['scripts/salt',
|
|
|
|
'scripts/salt-api',
|
|
|
|
'scripts/salt-cloud',
|
|
|
|
'scripts/salt-cp',
|
|
|
|
'scripts/salt-key',
|
|
|
|
'scripts/salt-master',
|
|
|
|
'scripts/salt-minion',
|
|
|
|
'scripts/salt-ssh',
|
|
|
|
'scripts/salt-syndic',
|
2015-06-29 14:49:48 +00:00
|
|
|
'scripts/salt-unity',
|
2015-09-04 18:05:14 +00:00
|
|
|
'scripts/salt-proxy',
|
2015-06-29 14:49:48 +00:00
|
|
|
'scripts/spm'])
|
2014-10-05 19:05:26 +00:00
|
|
|
return scripts
|
|
|
|
|
2014-11-11 16:19:18 +00:00
|
|
|
@property
|
|
|
|
def _property_entry_points(self):
|
|
|
|
# console scripts common to all scenarios
|
2016-02-04 21:14:55 +00:00
|
|
|
scripts = ['salt-call = salt.scripts:salt_call',
|
|
|
|
'salt-run = salt.scripts:salt_run']
|
2014-11-11 16:19:18 +00:00
|
|
|
if self.ssh_packaging or PACKAGED_FOR_SALT_SSH:
|
|
|
|
scripts.append('salt-ssh = salt.scripts:salt_ssh')
|
|
|
|
if IS_WINDOWS_PLATFORM:
|
|
|
|
return {'console_scripts': scripts}
|
2016-02-04 21:14:55 +00:00
|
|
|
scripts.append('salt-cloud = salt.scripts:salt_cloud')
|
2014-11-11 16:19:18 +00:00
|
|
|
return {'console_scripts': scripts}
|
|
|
|
|
|
|
|
if IS_WINDOWS_PLATFORM:
|
2016-02-04 21:14:55 +00:00
|
|
|
scripts.extend(['salt = salt.scripts:salt_main',
|
|
|
|
'salt-cp = salt.scripts:salt_cp',
|
|
|
|
'salt-key = salt.scripts:salt_key',
|
|
|
|
'salt-master = salt.scripts:salt_master',
|
2014-11-11 16:19:18 +00:00
|
|
|
'salt-minion = salt.scripts:salt_minion',
|
2015-06-29 14:51:12 +00:00
|
|
|
'salt-unity = salt.scripts:salt_unity',
|
|
|
|
'spm = salt.scripts:salt_spm'])
|
2014-11-11 16:19:18 +00:00
|
|
|
return {'console_scripts': scripts}
|
|
|
|
|
|
|
|
# *nix, so, we need all scripts
|
|
|
|
scripts.extend(['salt = salt.scripts:salt_main',
|
|
|
|
'salt-api = salt.scripts:salt_api',
|
|
|
|
'salt-cloud = salt.scripts:salt_cloud',
|
|
|
|
'salt-cp = salt.scripts:salt_cp',
|
|
|
|
'salt-key = salt.scripts:salt_key',
|
|
|
|
'salt-master = salt.scripts:salt_master',
|
|
|
|
'salt-minion = salt.scripts:salt_minion',
|
|
|
|
'salt-ssh = salt.scripts:salt_ssh',
|
|
|
|
'salt-syndic = salt.scripts:salt_syndic',
|
2015-06-29 14:49:48 +00:00
|
|
|
'salt-unity = salt.scripts:salt_unity',
|
|
|
|
'spm = salt.scripts:salt_spm'])
|
2014-11-11 16:19:18 +00:00
|
|
|
return {'console_scripts': scripts}
|
2014-10-05 19:05:26 +00:00
|
|
|
# <---- Dynamic Data ---------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
# ----- Esky Setup ---------------------------------------------------------------------------------------------->
|
|
|
|
def setup_esky(self):
|
|
|
|
opt_dict = self.get_option_dict('bdist_esky')
|
|
|
|
opt_dict['freezer_module'] = ('setup script', 'bbfreeze')
|
|
|
|
opt_dict['freezer_options'] = ('setup script', {'includes': self.get_esky_freezer_includes()})
|
|
|
|
|
|
|
|
@property
|
|
|
|
def _property_freezer_options(self):
|
|
|
|
return {'includes': self.get_esky_freezer_includes()}
|
|
|
|
|
|
|
|
def get_esky_freezer_includes(self):
|
|
|
|
# Sometimes the auto module traversal doesn't find everything, so we
|
|
|
|
# explicitly add it. The auto dependency tracking especially does not work for
|
|
|
|
# imports occurring in salt.modules, as they are loaded at salt runtime.
|
|
|
|
# Specifying includes that don't exist doesn't appear to cause a freezing
|
|
|
|
# error.
|
|
|
|
freezer_includes = [
|
|
|
|
'zmq.core.*',
|
|
|
|
'zmq.utils.*',
|
|
|
|
'ast',
|
2014-12-04 09:34:37 +00:00
|
|
|
'csv',
|
2014-10-05 19:05:26 +00:00
|
|
|
'difflib',
|
|
|
|
'distutils',
|
|
|
|
'distutils.version',
|
|
|
|
'numbers',
|
|
|
|
'json',
|
|
|
|
'M2Crypto',
|
|
|
|
'Cookie',
|
|
|
|
'asyncore',
|
|
|
|
'fileinput',
|
|
|
|
'sqlite3',
|
|
|
|
'email',
|
|
|
|
'email.mime.*',
|
|
|
|
'requests',
|
|
|
|
'sqlite3',
|
|
|
|
]
|
|
|
|
if HAS_ZMQ and hasattr(zmq, 'pyzmq_version_info'):
|
|
|
|
if HAS_ZMQ and zmq.pyzmq_version_info() >= (0, 14):
|
|
|
|
# We're freezing, and when freezing ZMQ needs to be installed, so this
|
|
|
|
# works fine
|
|
|
|
if 'zmq.core.*' in freezer_includes:
|
|
|
|
# For PyZMQ >= 0.14, freezing does not need 'zmq.core.*'
|
|
|
|
freezer_includes.remove('zmq.core.*')
|
|
|
|
|
|
|
|
if IS_WINDOWS_PLATFORM:
|
|
|
|
freezer_includes.extend([
|
2015-02-26 06:23:26 +00:00
|
|
|
'imp',
|
2014-10-05 19:05:26 +00:00
|
|
|
'win32api',
|
|
|
|
'win32file',
|
|
|
|
'win32con',
|
|
|
|
'win32com',
|
|
|
|
'win32net',
|
|
|
|
'win32netcon',
|
|
|
|
'win32gui',
|
|
|
|
'win32security',
|
|
|
|
'ntsecuritycon',
|
|
|
|
'pywintypes',
|
|
|
|
'pythoncom',
|
|
|
|
'_winreg',
|
|
|
|
'wmi',
|
|
|
|
'site',
|
|
|
|
'psutil',
|
2014-10-01 21:57:39 +00:00
|
|
|
])
|
2016-01-25 23:37:06 +00:00
|
|
|
elif IS_SMARTOS_PLATFORM:
|
2016-01-23 13:32:18 +00:00
|
|
|
# we have them as requirements in pkg/smartos/esky/requirements.txt
|
|
|
|
# all these should be safe to force include
|
|
|
|
freezer_includes.extend([
|
|
|
|
'cherrypy',
|
2016-01-23 14:04:13 +00:00
|
|
|
'dateutils',
|
|
|
|
'pyghmi',
|
|
|
|
'croniter',
|
|
|
|
'mako',
|
|
|
|
'gnupg',
|
2016-01-23 13:32:18 +00:00
|
|
|
])
|
2014-10-05 19:05:26 +00:00
|
|
|
elif sys.platform.startswith('linux'):
|
|
|
|
freezer_includes.append('spwd')
|
|
|
|
try:
|
|
|
|
import yum # pylint: disable=unused-variable
|
|
|
|
freezer_includes.append('yum')
|
|
|
|
except ImportError:
|
|
|
|
pass
|
|
|
|
elif sys.platform.startswith('sunos'):
|
|
|
|
# (The sledgehammer approach)
|
|
|
|
# Just try to include everything
|
|
|
|
# (This may be a better way to generate freezer_includes generally)
|
|
|
|
try:
|
|
|
|
from bbfreeze.modulegraph.modulegraph import ModuleGraph
|
|
|
|
mgraph = ModuleGraph(sys.path[:])
|
|
|
|
for arg in glob.glob('salt/modules/*.py'):
|
|
|
|
mgraph.run_script(arg)
|
|
|
|
for mod in mgraph.flatten():
|
|
|
|
if type(mod).__name__ != 'Script' and mod.filename:
|
|
|
|
freezer_includes.append(str(os.path.basename(mod.identifier)))
|
|
|
|
except ImportError:
|
|
|
|
pass
|
|
|
|
# Include C extension that convinces esky to package up the libsodium C library
|
|
|
|
# This is needed for ctypes to find it in libnacl which is in turn needed for raet
|
|
|
|
# see pkg/smartos/esky/sodium_grabber{.c,_installer.py}
|
|
|
|
freezer_includes.extend([
|
|
|
|
'sodium_grabber',
|
|
|
|
'ioflo',
|
|
|
|
'raet',
|
|
|
|
'libnacl',
|
2014-10-01 19:47:03 +00:00
|
|
|
])
|
2014-10-05 19:05:26 +00:00
|
|
|
return freezer_includes
|
|
|
|
# <---- Esky Setup -----------------------------------------------------------------------------------------------
|
2014-06-17 22:56:05 +00:00
|
|
|
|
2014-10-05 19:05:26 +00:00
|
|
|
# ----- Overridden Methods -------------------------------------------------------------------------------------->
|
|
|
|
def parse_command_line(self):
|
|
|
|
args = distutils.dist.Distribution.parse_command_line(self)
|
|
|
|
|
|
|
|
if not self.ssh_packaging and PACKAGED_FOR_SALT_SSH:
|
|
|
|
self.ssh_packaging = 1
|
2014-10-01 19:47:03 +00:00
|
|
|
|
2014-10-05 19:05:26 +00:00
|
|
|
if self.ssh_packaging:
|
|
|
|
self.metadata.name = 'salt-ssh'
|
|
|
|
self.salt_transport = 'ssh'
|
|
|
|
elif self.salt_transport is None:
|
|
|
|
self.salt_transport = 'zeromq'
|
|
|
|
|
|
|
|
if self.salt_transport not in ('zeromq', 'raet', 'both', 'ssh', 'none'):
|
|
|
|
raise DistutilsArgError(
|
|
|
|
'The value of --salt-transport needs be \'zeromq\', '
|
2015-08-27 04:26:07 +00:00
|
|
|
'\'raet\', \'both\', \'ssh\' or \'none\' not \'{0}\''.format(
|
2014-10-05 19:05:26 +00:00
|
|
|
self.salt_transport
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2015-08-14 13:02:26 +00:00
|
|
|
# Setup our property functions after class initialization and
|
|
|
|
# after parsing the command line since most are set to None
|
|
|
|
# ATTENTION: This should be the last step before returning the args or
|
|
|
|
# some of the requirements won't be correctly set
|
|
|
|
for funcname in dir(self):
|
|
|
|
if not funcname.startswith('_property_'):
|
|
|
|
continue
|
|
|
|
property_name = funcname.split('_property_', 1)[-1]
|
|
|
|
setattr(self, property_name, getattr(self, funcname))
|
|
|
|
|
2014-10-05 19:05:26 +00:00
|
|
|
return args
|
|
|
|
# <---- Overridden Methods ---------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
# <---- Custom Distribution Class ------------------------------------------------------------------------------------
|
2014-10-01 19:47:03 +00:00
|
|
|
|
2013-11-14 07:20:01 +00:00
|
|
|
|
2012-09-23 05:19:39 +00:00
|
|
|
if __name__ == '__main__':
|
2014-10-05 19:05:26 +00:00
|
|
|
setup(distclass=SaltDistribution)
|