#!/build/toolchain/lin64/python-2.7.12-openssl1.0.2h/bin/python ######################################################################## # Copyright (C) 2013-2017 VMWare, Inc. All Rights Reserved. ######################################################################## # import os import sys import glob BUILD_ADVICE = "Make sure you are using a complete vibsuite build/RPM or " \ "'scons PRODUCT=vibsuite' has been executed in your local " \ "#bora tree." VIB_ERRORCODE_EXCEPTION = 2 def getBuildDir(baseDir): ''' Return the base of the build directory. Use the envar BUILDROOT if we have it. Otherwise, generate it from baseDir, which is the .../bora/apps directory. ''' buildDir = os.environ.get('BUILDROOT', os.path.join(os.path.dirname(baseDir), 'build')) return buildDir def getBaseDir(): ''' Return the fqpn to the most-specific common directory that VIB-related python files can be found under. ''' thisFile = os.path.abspath(__file__) if os.path.islink(__file__): thisFile = os.path.abspath(os.readlink(__file__)) # In a workspace, thisFile would be .../bora/apps/vibtool/ and # in an rpm, it would be /opt/vmware/vibtools.../bin/. # # If we have .../bora/apps/pythonroot/vmware, then we're in a # workspace and in an rpm, it's /opt/vmware/vibtools/lib/vmware. # # The net result is that we want to return .../apps or # .../vibtools. return os.path.dirname(os.path.dirname(thisFile)) def getVibsuitePubDir(baseDir): ''' Return publish directory of locally built vibsuite, inside bora/build folder. We use whatever we find first in obj, beta and release build types. ''' buildDir = getBuildDir(baseDir) for buildType in ['obj', 'beta', 'release']: candidate = os.path.join(buildDir, 'vibsuite', buildType, 'publish') if os.path.isdir(candidate): return candidate # vibsuite local build is required sys.stderr.write('Could not find valid vibsuite directory. %s\n' % BUILD_ADVICE) sys.exit(VIB_ERRORCODE_EXCEPTION) def _rpmBasedPaths(baseDir): ''' Locate the directories of interest (schemas, certs, shared objects) that are delivered as part of the vib-suite rpm. Add the ones that Python needs to know about to sys.path[] and return the others as a 2-tuple of (schemaDirectory, certsDirectory). ''' foundPythonRoot = False # Non-binary things like .py files are likely to be under lib, # even when we're on a 64-bit host, so include both options. for subDir in ['lib64', 'lib']: libDir = os.path.join(baseDir, subDir) if os.path.isdir(libDir): sys.path.append(libDir) foundPythonRoot = True if not foundPythonRoot: sys.stderr.write('Could not find VIB libraries under %s.' % (baseDir)) sys.exit(VIB_ERRORCODE_EXCEPTION) schemaDir = os.path.join(os.sep, 'opt', 'vmware', baseDir, 'schemas') if not os.path.exists(schemaDir): sys.stderr.write('Could not find the esximage schemas in %s' % (baseDir)) sys.exit(VIB_ERRORCODE_EXCEPTION) defaultCertsDir = os.path.join(os.sep, 'opt', 'vmware', baseDir, 'certs') return (schemaDir, defaultCertsDir) def _standalonePaths(baseDir): ''' Standalone vibsuite build, edit sys.path to be able to import esximage, and return 2-tuple of (schemaDirectory, certsDirectory). This also get called when running vibtool under bora/vibtool with vibsuite built in bora/build. ''' # Add esximage.zip and lib64 directories to path requiredPaths = [os.path.join(baseDir, 'site-packages', 'esximage.zip'), os.path.join(baseDir, 'lib64')] for path in requiredPaths: if not os.path.exists(path): sys.stderr.write('Could not find library %s.' % path) sys.exit(VIB_ERRORCODE_EXCEPTION) sys.path.insert(0, path) # Schema and cert directories schemaDir = os.path.join(baseDir, 'schemas') certDir = os.path.join(baseDir, 'testcerts') if not os.path.exists(schemaDir): sys.stderr.write('Could not find esximage schemas in %s. %s\n' % (schemaDir, BUILD_ADVICE)) sys.exit(VIB_ERRORCODE_EXCEPTION) if not os.path.exists(certDir): sys.stderr.write('Could not find VIB signing certificates in %s. %s\n' % (certDir, BUILD_ADVICE)) sys.exit(VIB_ERRORCODE_EXCEPTION) return (schemaDir, certDir) def getVariantPaths(packages): ''' Make imports work correctly whether we're running in a perforce client or from an RPM installation. Return (schemaDir, certsDir), where schemaDir the directory containing schema files, and certsDir is the directory containing certificate files. ''' archDirs = ['noarch', 'lin64', 'lin32'] libDirs = ['lib64', 'lib'] prefixDir = os.path.join(os.sep, 'build', 'toolchain') for pkg in packages: for arch in archDirs: for lib in libDirs: pkgDir = os.path.join(prefixDir, arch, pkg, lib, 'python2.7', 'site-packages') if os.path.exists(pkgDir): sys.path.append(pkgDir) def getCertDirs(): ''' Gets the cert and schema directories Return (schemaDir, certsDir), where schemaDir the directory containing schema files, and certsDir is the directory containing certificate files. ''' # Determine if we are in vibsuite build/RPM or #bora tree baseDir = getBaseDir() sitePackagesPath = os.path.join(baseDir, 'site-packages') workspacePath = os.path.join(baseDir, 'pythonroot') if os.path.exists(sitePackagesPath): # With site-packages in parent folder, we are in vibsuite build (schemaDir, certsDir) = _standalonePaths(baseDir) elif os.path.exists(workspacePath): # With pythonroot in parent folder, we are in bora tree vibsuitePubDir = getVibsuitePubDir(baseDir) (schemaDir, certsDir) = _standalonePaths(vibsuitePubDir) else: (schemaDir, certsDir) = _rpmBasedPaths(baseDir) return (schemaDir, certsDir) def setupPy3LibPaths(): '''Sets up python 3 library paths ''' baseDir = getBaseDir() sitePackagesPath = os.path.join(baseDir, 'site-packages') sys.path.append(sitePackagesPath) def _maybeAddCertDir(dirs, dirName, haveCRL): '''Add a unique certificate directory if it meets criteria. Arguments: dirs - The dictionary of directories that have been added. dirName - The path name of the directory under consideration. haveCRL - Indicates whether or not we have already added a directory with a CRL file. Returns: True if a CRL file has been added to the dictionary, either previously or as a result of this invocation. False if no CRL files have yet been encountered. This is the equivalent of updating haveCRL to reflect we have added a new CRL-containing directory. Side effects: If dirName meets the addition criteria, the dictionary dirs is updated in place to include it. The addition criteria are: - dirName names an existing directory. - dirName is not a path to an already-added directory, as determined by comparing the device and inode of the named directory with those already added. - If haveCRL is True, then the directory dirName does not contain any CRL files. ''' if os.path.isdir(dirName): statInfo = os.stat(dirName) trueID = 'dev=%s, ino=%s' % (statInfo.st_dev, statInfo.st_ino) if trueID not in dirs: if glob.glob(os.path.join(dirName, '*.crl')): if not haveCRL: dirs[trueID] = dirName haveCRL = True else: dirs[trueID] = dirName return haveCRL def findAllCertDirs(candidates): ''' Goes through a list of path names. Any that are directories are considered potential certificate-related file containers. For files, their containing directory is considered a potential certificate-related file container. For all potential containers, if they exist they will be returned in a list. Additionally, any that have a sibling named "testcerts" will have that sibling included in the returned list, even if the potential container directory itself does not exist. This supports the long-standing implicit semantic of test certificates possibly being located adjacent to real certificates. The list is deduplicated to avoid trying to load the same certificate files multiple times. Doing so causes problems when loading a certificate revocation list, as the esximage class (more precisely, the SSL library) does consider duplicate CRL entries to be a fatal error. Actually, if a CRL file appears in more than one directory, we have to either reject all but the first of those directories or we have to parse each of the CRL files to reject those that overlap to completely avoid the problem. The expected scenario is that we are pointed at several directories that are all copies of each other, so the former heuristic is adequate for our needs and much faster to process than the parsing solution would involve. ''' haveCRL = False dirs = dict() for pathName in candidates: # May get empty entries due to OptionParser quirks. if not pathName: continue abspath = os.path.abspath(pathName) if os.path.isfile(abspath): dirName = os.path.dirname(abspath) else: dirName = abspath haveCRL = _maybeAddCertDir(dirs, dirName, haveCRL) dirName = os.path.join(os.path.dirname(dirName), 'testcerts') haveCRL = _maybeAddCertDir(dirs, dirName, haveCRL) return dirs.values()