123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- #!/usr/bin/env python
- # coding: utf-8
- # Copyright (C) 1994-2018 Altair Engineering, Inc.
- # For more information, contact Altair at www.altair.com.
- #
- # This file is part of the PBS Professional ("PBS Pro") software.
- #
- # Open Source License Information:
- #
- # PBS Pro is free software. You can redistribute it and/or modify it under the
- # terms of the GNU Affero General Public License as published by the Free
- # Software Foundation, either version 3 of the License, or (at your option) any
- # later version.
- #
- # PBS Pro is distributed in the hope that it will be useful, but WITHOUT ANY
- # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- # FOR A PARTICULAR PURPOSE.
- # See the GNU Affero General Public License for more details.
- #
- # You should have received a copy of the GNU Affero General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- #
- # Commercial License Information:
- #
- # For a copy of the commercial license terms and conditions,
- # go to: (http://www.pbspro.com/UserArea/agreement.html)
- # or contact the Altair Legal Department.
- #
- # Altair’s dual-license business model allows companies, individuals, and
- # organizations to create proprietary derivative works of PBS Pro and
- # distribute them - whether embedded or bundled with other software -
- # under a commercial license agreement.
- #
- # Use of Altair’s trademarks, including but not limited to "PBS™",
- # "PBS Professional®", and "PBS Pro™" and Altair’s logos is subject to Altair's
- # trademark licensing policies.
- import os
- import sys
- import socket
- import getopt
- import tempfile
- import logging
- import logging.config
- import errno
- import ptl
- import ptl.lib
- from ptl.utils.pbs_cliutils import CliUtils
- from ptl.utils.pbs_dshutils import DshUtils
- from ptl.lib.pbs_testlib import PtlConfig
- # trap SIGINT and SIGPIPE
- def trap_exceptions(etype, value, tb):
- sys.excepthook = sys.__excepthook__
- if issubclass(etype, KeyboardInterrupt):
- pass
- elif issubclass(etype, IOError) and value.errno == errno.EPIPE:
- pass
- else:
- sys.__excepthook__(etype, value, tb)
- sys.excepthook = trap_exceptions
- # A basic SWIG interface definition to wrap PBS IFL
- swiginter = '''\
- %module pbs_ifl
- %typemap(out) char ** {
- int len,i;
- len = 0;
- while ($1[len]) len++;
- $result = PyList_New(len);
- for (i = 0; i < len; i++) {
- PyList_SetItem($result,i,PyString_FromString($1[i]));
- }
- }
- %typemap(in) char ** {
- /* Check if is a list */
- if (PyList_Check($input)) {
- int size = PyList_Size($input);
- int i = 0;
- $1 = (char **) malloc((size+1)*sizeof(char *));
- for (i = 0; i < size; i++) {
- PyObject *o = PyList_GetItem($input,i);
- if (PyString_Check(o))
- $1[i] = PyString_AsString(PyList_GetItem($input,i));
- else {
- PyErr_SetString(PyExc_TypeError,"list must contain strings");
- free($1);
- return NULL;
- }
- }
- $1[i] = 0;
- } else {
- PyErr_SetString(PyExc_TypeError,"not a list");
- return NULL;
- }
- }
- %typemap(out) struct batch_status * {
- struct batch_status *head_bs, *bs;
- struct attrl *attribs;
- char *resource;
- char *str;
- int i, j;
- int len;
- char buf[4096];
- static char *id = "id";
- head_bs = $1;
- bs = $1;
- for (len=0; bs != NULL; len++)
- bs = bs->next;
- $result = PyList_New(len);
- bs = head_bs;
- for (i=0; i < len; i++) {
- PyObject *dict;
- PyObject *a, *v, *tmpv;
- dict = PyDict_New();
- PyList_SetItem($result, i, dict);
- a = PyString_FromString(id);
- v = PyString_FromString(bs->name);
- PyDict_SetItem(dict, a, v);
- attribs = bs->attribs;
- while (attribs) {
- resource = attribs->resource;
- if (resource != NULL) {
- /* +2 to account for the '.' between name and resource */
- str = malloc(strlen(attribs->name) + strlen(resource) + 2);
- sprintf(str, "%s.%s", attribs->name, attribs->resource);
- a = PyString_FromString(str);
- }
- else {
- a = PyString_FromString(attribs->name);
- }
- tmpv = PyDict_GetItem(dict, a);
- /* if the key already exists, append as comma-separated */
- if (tmpv != NULL) {
- char *s = PyString_AsString(tmpv);
- /* +4 for the quotes, the comma, and a NULL byte */
- str = malloc(strlen(attribs->value) + strlen(s) + 4);
- sprintf(str, "%s,%s", attribs->value, s);
- v = PyString_FromString(str);
- }
- else {
- v = PyString_FromString(attribs->value);
- }
- PyDict_SetItem(dict, a, v);
- attribs = attribs->next;
- }
- bs = bs->next;
- }
- }
- %{
- #include "pbs_ifl.h"
- int pbs_py_spawn(int, char *, char **, char **);
- %}
- %include "pbs_ifl.h"
- int pbs_py_spawn(int, char *, char **, char **);
- '''
- def _remove_file(workdir, filename):
- f = os.path.join(workdir, filename)
- if os.path.isfile(f):
- logging.debug('removing intermediary file ' + filename)
- os.remove(f)
- def usage():
- msg = []
- msg += ['Usage: ' + os.path.basename(sys.argv[0]) + ' [OPTION]\n\n']
- msg += [' Produce Python wrappers for PBS IFL API\n\n']
- msg += ['-c <pbs_conf>: path to pbs.conf\n']
- msg += [
- '-f: force overwrite of _pbs_ifl.so and pbs_ifl.py when present\n']
- msg += ['-h: display usage information\n']
- msg += ['-i <swig.i>: path to swig interface file\n']
- msg += ['-I <python_include>: path to python include directory\n']
- msg += ['-l <level>: logging level\n']
- msg += ['-s <swig>: path to swig binary to use\n']
- msg += ['-t <targethost>: hostname to operate on\n']
- msg += ['-w <workdir>: path to working directory\n']
- msg += ['--log-conf=<file>: logging config file\n']
- msg += ['--version: print version number and exit\n']
- print "".join(msg)
- if __name__ == '__main__':
- workdir = tempfile.gettempdir()
- targethost = socket.gethostname()
- config = None
- interface = None
- pythoninc = None
- level = 'INFO'
- force = False
- swigbin = 'swig'
- logconf = None
- if 'PBS_CONF_FILE' in os.environ:
- config = os.environ['PBS_CONF_FILE']
- else:
- config = '/etc/pbs.conf'
- opts, args = getopt.getopt(sys.argv[1:], "t:i:I:c:w:l:s:hf",
- ["log-conf=", "version"])
- for o, val in opts:
- if o == '-t':
- targethost = val
- elif o == '-w':
- workdir = CliUtils.expand_abs_path(val)
- elif o == '-i':
- interface = val
- elif o == '-l':
- level = val
- elif o == '-c':
- config = val
- elif o == '-I':
- pythoninc = CliUtils.expand_abs_path(val)
- elif o == '-f':
- force = True
- elif o == '-s':
- swigbin = CliUtils.expand_abs_path(val)
- elif o == '--log-conf':
- logconf = val
- elif o == '--version':
- print ptl.__version__
- sys.exit(0)
- elif o == '-h':
- usage()
- sys.exit(0)
- else:
- sys.stderr.write("Unrecognized option\n")
- usage()
- sys.exit(1)
- cu = CliUtils()
- if logconf:
- logging.config.fileConfig(logconf)
- else:
- l = cu.get_logging_level(level)
- logging.basicConfig(level=l)
- b = cu.check_bin(swigbin)
- if not b:
- logging.error("swig is missing, exiting")
- sys.exit(1)
- b = cu.check_bin("gcc")
- if not b:
- logging.error("gcc is missing, exiting")
- sys.exit(1)
- if pythoninc is None:
- logging.error("Path to Python include directory is mandatory")
- usage()
- sys.exit(1)
- if targethost != socket.gethostname():
- logging.error("This command only works on localhost")
- sys.exit(1)
- PtlConfig()
- du = DshUtils()
- pbs_conf = du.parse_pbs_config(targethost, file=config)
- os.chdir(workdir)
- if interface is None:
- interface = os.path.join(workdir, "pbs_ifl.i")
- f = open(interface, 'w')
- f.write(swiginter)
- f.close()
- srcdir = os.getcwd()
- else:
- srcdir = os.path.dirname(interface)
- if 'PBS_EXEC' in pbs_conf:
- pbsinclude = os.path.join(pbs_conf['PBS_EXEC'], 'include')
- cmd = [swigbin, '-python', '-I' + pbsinclude, interface]
- logging.debug(du.run_cmd(targethost, cmd))
- if srcdir != os.getcwd():
- logging.debug(du.run_copy(targethost,
- os.path.join(srcdir, "pbs_ifl_wrap.c"),
- workdir))
- logging.debug(du.run_copy(targethost,
- os.path.join(srcdir, "pbs_ifl.py"),
- workdir))
- cmd = ['gcc', '-Wall', '-Wno-unused-variable', '-fPIC', '-shared',
- '-I' + pbsinclude]
- cmd += ['-I' + pythoninc]
- cmd += ['pbs_ifl_wrap.c']
- cmd += ['-L' + os.path.join(pbs_conf['PBS_EXEC'], 'lib')]
- cmd += ['-lpbs']
- cmd += ['-o', '_pbs_ifl.so']
- cmd += ['-lcrypto', '-lssl']
- logging.debug(du.run_cmd(targethost, cmd))
- libdir = os.path.dirname(ptl.lib.__file__)
- if force or not os.path.isfile(libdir + '/_pbs_ifo.so'):
- du.run_copy(targethost,
- os.path.join(workdir, '_pbs_ifl.so'),
- os.path.join(libdir, '_pbs_ifl.so'), sudo=True)
- if force or not os.path.isfile(os.path.join(libdir, '/pbs_ifl.py')):
- du.run_copy(targethost,
- os.path.join(workdir, 'pbs_ifl.py'),
- os.path.join(libdir, 'pbs_ifl.py'), sudo=True)
- _remove_file(workdir, "pbs_ifl.py")
- _remove_file(workdir, "_pbs_ifl.so")
- _remove_file(workdir, "pbs_ifl_wrap.c")
- _remove_file(workdir, "pbs_ifl.i")
|