Plan for saltstack, having issues

“Hey, I’m having some issues with saltstack packages from the distribution, an excuse to learn habitat, and it feels cleaner than running from virtualenv!”

Several hours later, I have following plan:

    pkg_name=salt
    pkg_version=2017.7.4
    pkg_origin=viq
    pkg_license=('Apache License, Version 2.0')
    pkg_description="Software to automate the management and configuration of any infrastructure or application at scale."
    pkg_upstream_url=https://saltstack.com/
    pkg_source=https://github.com/saltstack/salt/releases/download/v${pkg_version}/salt-${pkg_version}.tar.gz
    pkg_filename=salt-${pkg_version}.tar.gz
    pkg_dirname=salt-${pkg_version}
    pkg_shasum=1d573095776ba052eec7d7cae1472f4b1d4c15f16e1d79c2dc48db3129dbae97
    pkg_build_deps=(
      core/gcc
      core/make
    )
    pkg_deps=(
      core/gnupg
      core/openssl
      core/python2
      core/zeromq
    )
    pkg_bin_dirs=(bin)
    pkg_lib_dirs=(lib)
    pkg_exports=(
      [port]=serverport
    )
    pkg_svc_run="salt-master -c ${pkg_svc_config_path}"
    #pkg_svc_user="salt"
    
    do_build() {
      pip install --upgrade pip
      pip install --prefix="$pkg_prefix" -r requirements/base.txt
      pip install --prefix="$pkg_prefix" -r requirements/zeromq.txt
      pip install --prefix="$pkg_prefix" timelib python-gnupg cherrypy libnacl
      pip install --prefix="$pkg_prefix" .
    }

    do_install() {
      python setup.py install \
        --prefix="$pkg_prefix"
    }

    do_setup_environment() {
      push_runtime_env PYTHONPATH "$(pkg_path_for python2)/lib/python2.7/site-packages"
      push_runtime_env PYTHONPATH "${pkg_prefix}/lib/python2.7/site-packages"
      push_runtime_env LD_LIBRARY_PATH "$(pkg_path_for openssl)/lib"
    }

Unfortunately, trying to run it fails, strangely enough on finding openssl libraries:

hab start viq/salt
sl
    hab-launch(SV): Child for service 'salt.default' with PID 28016 exited with code exit code: 1
    salt.default(SV): Starting service as user=hab, group=hab
    salt.default(O): Traceback (most recent call last):
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/bin/salt-master", line 22, in <module>
    salt.default(O):     salt_master()
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/scripts.py", line 90, in salt_master
    salt.default(O):     import salt.cli.daemons
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/cli/daemons.py", line 47, in <module>
    salt.default(O):     from salt.utils import parsers, ip_bracket
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/utils/parsers.py", line 28, in <module>
    salt.default(O):     import salt.config as config
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/config/__init__.py", line 100, in <module>
    salt.default(O):     _DFLT_IPC_WBUFFER = _gather_buffer_space() * .5
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/config/__init__.py", line 90, in _gather_buffer_space
    salt.default(O):     import salt.grains.core
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/grains/core.py", line 47, in <module>
    salt.default(O):     import salt.utils.dns
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/utils/dns.py", line 28, in <module>
    salt.default(O):     import salt.modules.cmdmod
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/modules/cmdmod.py", line 34, in <module>
    salt.default(O):     import salt.utils.templates
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/utils/templates.py", line 31, in <module>
    salt.default(O):     import salt.utils.http
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/utils/http.py", line 41, in <module>
    salt.default(O):     import salt.loader
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/loader.py", line 26, in <module>
    salt.default(O):     import salt.utils.event
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/utils/event.py", line 74, in <module>
    salt.default(O):     import salt.payload
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/payload.py", line 17, in <module>
    salt.default(O):     import salt.crypt
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/crypt.py", line 54, in <module>
    salt.default(O):     import salt.utils.rsax931
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/utils/rsax931.py", line 85, in <module>
    salt.default(O):     libcrypto = _init_libcrypto()
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/utils/rsax931.py", line 56, in _init_libcrypto
    salt.default(O):     libcrypto = _load_libcrypto()
    salt.default(O):   File "/hab/pkgs/viq/salt/2017.7.4/20180324155051/lib/python2.7/site-packages/salt/utils/rsax931.py", line 49, in _load_libcrypto
    salt.default(O):     raise OSError('Cannot locate OpenSSL libcrypto')
    salt.default(O): OSError: Cannot locate OpenSSL libcrypto
    hab-launch(SV): Child for service 'salt.default' with PID 28028 exited with code exit code: 1

Where do I go from there?

@viq sorry you haven’t gotten a response to this yet. Give me a few minutes to get some tea and food in me and I’ll take a look and see if we can’t figure this one out!

Ok so here’s what’s up. It looks like you’re using the load_library ctypes module to find the crypto libraries. In this function:

def _load_libcrypto():
    ' ' '
    Load OpenSSL libcrypto
    ' ' '
    if sys.platform.startswith('win'):
        return cdll.LoadLibrary('libeay32')
    elif getattr(sys, 'frozen', False) and salt.utils.is_smartos():
        return cdll.LoadLibrary(glob.glob(os.path.join(
            os.path.dirname(sys.executable),
            'libcrypto.so*'))[0])
    else:
        lib = find_library('crypto')
        if not lib and salt.utils.is_sunos():
            # Solaris-like distribution that use pkgsrc have
            # libraries in a non standard location.
            # (SmartOS, OmniOS, OpenIndiana, ...)
            # This could be /opt/tools/lib (Global Zone)
            # or /opt/local/lib (non-Global Zone), thus the
            # two checks below
            lib = glob.glob('/opt/local/lib/libcrypto.so*') + glob.glob('/opt/tools/lib/libcrypto.so*')
            lib = lib[0] if len(lib) > 0 else None
        if lib:
            return cdll.LoadLibrary(lib)
        raise OSError('Cannot locate OpenSSL libcrypto')

The problem appears to be that the ctypes module. Im looking now to figure out why. After some looking it sounds like the ctypes module is just using gcc + ldconfig + objdump to return the library location so I don’t know why it’s not getting linked appropriately. Going to do some more digging.

Thank you very much for looking!

Ok so I’ve looked at this a bit more today and the findings are tough. I’m hoping to see if we can get @bixu to add some thoughts here.

Basically what i’m seeing is that no matter if I modify $LD_LIBRARY_PATH in any of 5 different ways, no matter if I modify $PATH to the depped core/openssl, no matter if I bypass stripping at the end of the build, I cannot get the ctype module for find_lib() to pick up the library. The code for that check is happening in here I believe: https://github.com/python/cpython/blob/30e507dff465a31901d87df791a2bac40dc88530/Lib/ctypes/util.py#L92

Of further interest, It looks like you need objdump and gcc to make those find_library calls which seems to mean taking a runtime dep on gcc & binutils? I’m not totally certain if that’s the case because I’m absolutely not a pythonista. That being said I’ve also attempted to take runtime deps on binutils and gcc as well as reconfigure the build to happen inside virtualenv and nothing seems to make a difference. Perhaps theres something simple we’re overlooking like a hardcoded library path somewhere?

@eeyun, are how are you installing the module? Could this be a case where the install needs to avoid using a pre-compiled module, so that the module picks up lib paths?

If using pip, we’d do something like install —no-binary <module>

The pattern I’m using is pretty closely mirrored to the plan above. I’ve just also gone the path of building inside virtualenv. The more I look at this, the more I think the util script for the application is busted. The only way I’ve been able to get past this issue is to use sed to modify the util script at build time to pull the appropriate library location.

pkg_name=salt
pkg_version=2017.7.4
pkg_origin=core
pkg_license=('Apache License, Version 2.0')
pkg_description="Software to automate the management and configuration of any infrastructure or application at scale."
pkg_upstream_url=https://saltstack.com/
pkg_source=https://github.com/saltstack/salt/releases/download/v${pkg_version}/salt-${pkg_version}.tar.gz
pkg_filename=salt-${pkg_version}.tar.gz
pkg_dirname=salt-${pkg_version}
pkg_shasum=1d573095776ba052eec7d7cae1472f4b1d4c15f16e1d79c2dc48db3129dbae97
pkg_build_deps=(
  core/make
  core/virtualenv
  core/cacerts
  core/git
  core/gcc
)
pkg_deps=(
  core/gnupg
  core/openssl
  core/python2
  core/zeromq
  core/binutils
  core/libsodium
)
pkg_bin_dirs=(bin)
pkg_lib_dirs=(lib)
pkg_exports=(
  [port]=serverport
)
pkg_svc_run="salt-master -c ${pkg_svc_config_path}"

do_prepare() {
  localedef -i en_US -f UTF-8 en_US.UTF-8
  export LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
  virtualenv "${pkg_prefix}"
  source "${pkg_prefix}/bin/activate"
}

do_build() {
  pip install --upgrade pip
  pip install --prefix="$pkg_prefix" -r requirements/base.txt
  pip install --prefix="$pkg_prefix" -r requirements/zeromq.txt
  pip install --prefix="$pkg_prefix" timelib python-gnupg cherrypy libnacl
  pip install --prefix="$pkg_prefix" --no-binary .

  python setup.py build
}

do_install() {
  
  python setup.py install \
    --prefix="${pkg_prefix}" 


  lib="$(hab pkg path core/openssl)/lib/libcrypto.so"
  cd "${pkg_prefix}/lib/python2.7/site-packages/salt/utils"
  sed -i.bak "s@find_library('crypto')@"\""$lib"\""@" "rsax931.py"
}

do_setup_environment() {
  push_runtime_env PYTHONPATH "$(pkg_path_for core/python2)"
}

This at least gets past the issue of the library not getting linked, but it’s also still not functional.

You can ignore the unnecessary duplication - hackety hack and never cleaned up after myself.

Actually this looks like it causes a segfault. So I’m totally at a loss.