def _process_command(self): """ Build the process command line using the driver_config dict @return a list containing spawn args for the _spawn method 1. check cache (CACHE_DIR = '/tmp') 2. download to cache if not present. 3. construct call command """ log.debug("cwd: %s", os.getcwd()) driver_package = self.config.get('dvr_egg') ppid = os.getpid() if self.test_mode else None python = PYTHON_PATH if not driver_package: raise DriverLaunchException( "missing driver config: driver_package") if not os.path.exists(python): raise DriverLaunchException( "could not find python executable: %s" % python) path = self._get_egg(self.config.get('dvr_egg')) log.debug("_process_command: %s", path) cmd_port_fname = self._driver_command_port_file() evt_port_fname = self._driver_event_port_file() cmd_str = "import sys; sys.path.insert(0, '%s/%s'); from mi.main import run; sys.exit(run(command_port_file='%s', event_port_file='%s', ppid=%s))" % \ (CACHE_DIR, get_filename_from_uri(driver_package), cmd_port_fname, evt_port_fname, str(ppid)) return [python, '-c', cmd_str]
def get_process(cls, driver_config, test_mode=False): """ Factory method to get the correct driver process object based on the type in driver_config @param driver_config a dict containing configuration information for the driver process. This will be different for each driver process type, but each should minimally have 'process_type' which defines which object to use for launching. @param test_mode tell the driver you are running in test mode. Some drivers use this to add a poison pill to the driver process. """ type = driver_config.get("process_type")[0] driver_module = driver_config.get('dvr_mod') if not type: raise DriverLaunchException("missing driver config: process_type") # For some reason the enum wasn't working with the instrument agent. I would see [emum] when called from # the IA, but (enum,) when called from this module. # # elif type == DriverProcessType.PYTHON_MODULE: log.debug("DriverProcessType.PYTHON_MODULE") return ZMQPyClassDriverProcess(driver_config, test_mode) elif type == DriverProcessType.EGG: log.debug("DriverProcessType.EGG") return ZMQEggDriverProcess(driver_config, test_mode) else: raise DriverLaunchException("unknown driver process type: %s" % type)
def _process_command(self): """ Build the process command line using the driver_config dict @return a list containing spawn args for the _spawn method """ log.debug("cwd: %s", os.getcwd()) mi_repo = self.config.get('mi_repo', None) driver_module = self.config.get('dvr_mod') driver_class = self.config.get('dvr_cls') ppid = os.getpid() if self.test_mode else None python = PYTHON_PATH if not driver_module: raise DriverLaunchException("missing driver config: driver_module") if not driver_class: raise DriverLaunchException("missing driver config: driver_class") if not os.path.exists(python): raise DriverLaunchException( "could not find python executable: %s" % python) cmd_port_fname = self._driver_command_port_file() evt_port_fname = self._driver_event_port_file() cmd_str = '' if mi_repo: cmd_str += 'import sys; sys.path.insert(0,"%s");' % mi_repo cmd_str += 'from %s import %s; dp = %s("%s", "%s", "%s", "%s", %s);dp.run()'\ % ('mi.core.instrument.zmq_driver_process', 'ZmqDriverProcess', 'ZmqDriverProcess', driver_module, driver_class, cmd_port_fname, evt_port_fname, str(ppid)) return [python, '-c', cmd_str]
def get_client(self): """ Get a python client for the driver process. @return an client object for the driver process """ # Start client messaging and verify messaging. if not self._driver_client: try: driver_client = ZmqDriverClient('localhost', self._command_port, self._event_port) self._driver_client = driver_client except Exception, e: self.stop() log.error('Error starting driver client: %s' % e) raise DriverLaunchException('Error starting driver client.')
def _get_remote_egg(self, egg_name): """ pull the egg from a remote server if present to the local cache dir. @return: returns the path, throws exception if not found. """ log.debug("_get_remote_egg %s", egg_name) try: if egg_name.startswith("http://"): response = urlopen(egg_name) else: response = urlopen(self._egg_remotepath(egg_name)) egg_yolk = response.read() log.debug("_fetch_egg GOT YOLK") except HTTPError, e: raise DriverLaunchException('failed to download egg: ' + str(e))
def launch(self): """ Launch the driver process. Once the process is launched read the two status files that contain the event port and command port for the driver. @raises DriverLaunchException """ log.info("Launch driver process") cmd = self._process_command() self._driver_process = self._spawn(cmd) if not self._driver_process and not self.poll(): log.error("Failed to launch driver: %s" % cmd) raise DriverLaunchException('Error starting driver process') log.debug("driver process started, pid: %s" % self.getpid()) self._command_port = self._get_port_from_file(self._driver_command_port_file()) self._event_port = self._get_port_from_file(self._driver_event_port_file()) log.debug("-- command port: %s, event port: %s" % (self._command_port, self._event_port))
class ZMQEggDriverProcess(DriverProcess): ''' Object to facilitate ZMQ driver processes using a python egg Driver config requirements: dvr_egg :: the filename of the egg Example: driver_config = { dvr_egg: seabird_sbe37smb_ooicore-0.0.1-py2.7.egg process_type: DriverProcessType.EGG } @param driver_config configuration parameters for the driver process @param test_mode should the driver be run in test mode ''' def __init__(self, driver_config, test_mode=False): self.config = driver_config self.test_mode = test_mode def _egg_path(self, egg_name): log.debug("_egg_path") if not CACHE_DIR: raise ServerError("CACHE_DIR is %s'%s'" % (type(CACHE_DIR), CACHE_DIR)) elif not egg_name: raise ServerError("egg_name for path is %s'%s'" % (type(egg_name), egg_name)) return CACHE_DIR + "/" + egg_name def _egg_remotepath(self, egg_name): log.debug("_egg_remotepath: %s", egg_name) if not REPO_BASE: raise ServerError("REPO_BASE is %s'%s'" % (type(REPO_BASE), REPO_BASE)) elif not egg_name: raise ServerError("egg_name for remotepath is %s'%s'" % (type(egg_name), egg_name)) return REPO_BASE + "/" + egg_name def _check_cache_for_egg(self, egg_name): """ Check if the egg is already cached, if so, return the path. @return: egg path if cached, else None """ log.debug("_check_cache_for_egg: %s", egg_name) path = self._egg_path(egg_name) if os.path.exists(path): log.debug("_check_cache_for_egg cache hit PATH = " + str(path)) return path else: log.debug("_check_cache_for_egg cache miss" + str(path)) return None def _get_remote_egg(self, egg_name): """ pull the egg from a remote server if present to the local cache dir. @return: returns the path, throws exception if not found. """ log.debug("_get_remote_egg %s", egg_name) try: if egg_name.startswith("http://"): response = urlopen(egg_name) else: response = urlopen(self._egg_remotepath(egg_name)) egg_yolk = response.read() log.debug("_fetch_egg GOT YOLK") except HTTPError, e: raise DriverLaunchException('failed to download egg: ' + str(e)) except URLError, e: raise DriverLaunchException('bad egg URL ' + egg_name + ': ' + e.reason)
def _process_command(self): """ Define the command that is sent to _spawn. This will be specific to each driver process type """ raise DriverLaunchException("_process_command must be overloaded")
egg_yolk = response.read() log.debug("_fetch_egg GOT YOLK") except HTTPError, e: raise DriverLaunchException('failed to download egg: ' + str(e)) except URLError, e: raise DriverLaunchException('bad egg URL ' + egg_name + ': ' + e.reason) filename = get_filename_from_uri(egg_name) path = self._egg_path(filename) log.debug("PATH = %s", path) try: egg_file = open(path, "wb") egg_file.write(egg_yolk) except IOError: raise DriverLaunchException("IOError writing egg file to cache") else: egg_file.close() return path def _get_egg(self, egg_uri): filename = get_filename_from_uri(egg_uri) log.debug("_get_egg: %s", filename) path = self._check_cache_for_egg(filename) if None == path: path = self._get_remote_egg( filename) # Will exception out if problem. return path