def test_logging_no_hang(self):
        '''Try to ensure Popen.check_call doesn't hang when trying to do
        logging'''

        # To ensure the logger keyword arg is implemented in a way that
        # doesn't cause hangs, and since the use of logger causes blocking
        # behavior, spawn a non-blocking subprocess that spawns a blocking
        # subprocess. If the non-blocking subprocess doesn't complete
        # in a reasonable amount of time, kill both and fail
        cmd = [
            sys.executable, "-c",
            "from solaris_install import Popen; import logging; "
            "Popen.check_call(['/usr/bin/pkg', 'foo'], "
            "logger=logging.getLogger())"
        ]

        popen = Popen(cmd, stdout=Popen.DEVNULL, stderr=Popen.DEVNULL)
        for wait_count in xrange(15):
            # If it's not done nearly instantly, something is wrong.
            # However, give the benefit of the doubt by waiting up to
            # 5 seconds for completion
            if popen.poll() is not None:
                break
            else:
                time.sleep(0.5)
        else:
            popen.kill()
            self.fail("subprocess hung while attempting logging")
    def test_logging_no_hang(self):
        '''Try to ensure Popen.check_call doesn't hang when trying to do
        logging'''

        # To ensure the logger keyword arg is implemented in a way that
        # doesn't cause hangs, and since the use of logger causes blocking
        # behavior, spawn a non-blocking subprocess that spawns a blocking
        # subprocess. If the non-blocking subprocess doesn't complete
        # in a reasonable amount of time, kill both and fail
        cmd = [sys.executable, "-c",
               "from solaris_install import Popen; import logging; "
               "Popen.check_call(['/usr/bin/pkg', 'foo'], "
               "logger=logging.getLogger())"]

        popen = Popen(cmd, stdout=Popen.DEVNULL, stderr=Popen.DEVNULL)
        for wait_count in xrange(15):
            # If it's not done nearly instantly, something is wrong.
            # However, give the benefit of the doubt by waiting up to
            # 5 seconds for completion
            if popen.poll() is not None:
                break
            else:
                time.sleep(0.5)
        else:
            popen.kill()
            self.fail("subprocess hung while attempting logging")
Пример #3
0
def _fork_proc(cmd, timeout=15):
    '''Run a command in a forked process, with a timeout.

    Kills the process on timeout.
    Logs errors.
    Handles processes with large amounts of data so check_call() is not used.

    Args:
      - cmd: a list of commandline arguments
      - timeout: timeout in seconds
    Returns:
      - Return status:
        - return status of the command run, if command completes.
        - SupportInfo.PH_TIMEOUT if timeout occurs.
      - stdout and stderr of the run process.
    '''
    timeout_tenths = timeout * 10

    def read_subproc(subproc, outbuf, errbuf):
        intoutbuf = interrbuf = ""
        try:
            intoutbuf = subproc.stdout.read()
            outbuf = "".join([outbuf, intoutbuf])
        except IOError as err:
            if err.errno != errno.EAGAIN:
                raise
        try:
            interrbuf = subproc.stderr.read()
            errbuf = "".join([errbuf, interrbuf])
        except IOError as err:
            if err.errno != errno.EAGAIN:
                raise
        return (outbuf, errbuf)

    # Can throw an child_exception if command cannot be started.
    subproc = Popen(cmd, stdout=Popen.PIPE, stderr=Popen.PIPE)

    flags = fcntl.fcntl(subproc.stdout.fileno(), fcntl.F_GETFL)
    fcntl.fcntl(subproc.stdout.fileno(), fcntl.F_SETFL, flags | os.O_NONBLOCK)
    flags = fcntl.fcntl(subproc.stderr.fileno(), fcntl.F_GETFL)
    fcntl.fcntl(subproc.stderr.fileno(), fcntl.F_SETFL, flags | os.O_NONBLOCK)

    (outbuf, errbuf) = read_subproc(subproc, "", "")
    while subproc.poll() is None and timeout_tenths > 0:
        timeout_tenths -= 1
        time.sleep(0.1)
        (outbuf, errbuf) = read_subproc(subproc, outbuf, errbuf)
    if subproc.returncode is None:
        subproc.terminate()
        return (SupportInfo.PH_TIMEOUT, outbuf, errbuf)
    else:
        (outbuf, errbuf) = read_subproc(subproc, outbuf, errbuf)
    return (subproc.returncode, outbuf, errbuf)
    def test_devnull(self):
        '''Test using Popen.DEVNULL for stdin'''
        popen = Popen(["/usr/bin/cat"], stdin=Popen.DEVNULL, stdout=Popen.PIPE)
        # Use PIPE for stdout as, for a failure case, the subprocess call
        # could hang indefinitely, so we can't block on it

        for wait_count in xrange(10):
            # If it's not done nearly instantly, something is wrong.
            # However, give the benefit of the doubt by waiting up to
            # 5 seconds for completion
            if popen.poll() is not None:
                break
            else:
                time.sleep(0.5)
        else:
            popen.kill()
            self.fail("stdin=Popen.DEVNULL did not work")

        stdout = popen.communicate()[0]
        self.assertEqual("", stdout)
    def test_devnull(self):
        '''Test using Popen.DEVNULL for stdin'''
        popen = Popen(["/usr/bin/cat"], stdin=Popen.DEVNULL, stdout=Popen.PIPE)
        # Use PIPE for stdout as, for a failure case, the subprocess call
        # could hang indefinitely, so we can't block on it

        for wait_count in xrange(10):
            # If it's not done nearly instantly, something is wrong.
            # However, give the benefit of the doubt by waiting up to
            # 5 seconds for completion
            if popen.poll() is not None:
                break
            else:
                time.sleep(0.5)
        else:
            popen.kill()
            self.fail("stdin=Popen.DEVNULL did not work")

        stdout = popen.communicate()[0]
        self.assertEqual("", stdout)
Пример #6
0
    def _transfer(self):
        '''Method to transfer from the source to the destination'''
        if self.give_progress:
            # Start up the ProgressMon to report progress
            # while the actual transfer is taking place.
            self.pmon = ProgressMon(logger=self.logger)
            # Note: startmonitor assumes there is another thread creating a
            # file system.  If this is not the case (as may be when testing
            # this module in abnormal conditions), startmonitor will hang.
            # Just create the self.dst as a directory in this case.
            self.pmon.startmonitor(self.dst, self.total_size, 0, 100)

        # Perform the transfer specific operations.

        try:
            for trans_val in self._transfer_list:

                # Get the arguments for the transfer process
                arglist = trans_val.get(SVR4_ARGS).split(' ')

                # Parse the components to determine the transfer action
                if trans_val.get(ACTION) == 'install':
                    self.check_cancel_event()
                    self.logger.info("Installing SVR4 packages")
                    cmd = [AbstractSVR4.PKGADD] + arglist + \
                        trans_val.get(CONTENTS)

                elif trans_val.get(ACTION) == 'uninstall':
                    self.check_cancel_event()
                    self.logger.info("Uninstalling SVR4 packages")
                    cmd = [AbstractSVR4.PKGRM] + arglist + \
                        trans_val.get(CONTENTS)

                else:
                    self.logger.warning("Transfer action, %s, is not valid" %
                                     trans_val.get(ACTION))
                    self.check_cancel_event()
                    continue

                if self.dry_run:
                    self.logger.debug("Would execute the following transfer "
                                     "command: %s" % cmd)
                else:
                    self.logger.debug("Executing the following transfer "
                                     "command: %s" % cmd)
                    self.check_cancel_event()
                    pkg_proc = Popen(cmd, shell=False,
                                     stdout=Popen.PIPE,
                                     stderr=Popen.STDOUT)
                    while 1:
                        self.check_cancel_event()
                        pkgoutput = pkg_proc.stdout.readline()
                        if not pkgoutput:
                            retcode = pkg_proc.poll()
                            if retcode != 0:
                                self.svr4_process = None
                                raise OSError(retcode,
                                              "SVR4 transfer error while "
                                              "adding packages")
                            break
                        pkgoutput = pkgoutput[:-1]
                        if not pkgoutput.strip():
                            continue
                        self.logger.debug("%s", pkgoutput)
                    self.svr4_process = None

        finally:
            if self.pmon:
                self.pmon.done = True
                self.pmon.wait()
                self.pmon = None
Пример #7
0
    def _transfer(self):
        '''Method to transfer from the source to the destination'''
        if self.give_progress:
            # Start up the ProgressMon to report progress
            # while the actual transfer is taking place.
            self.pmon = ProgressMon(logger=self.logger)
            # Note: startmonitor assumes there is another thread creating a
            # file system.  If this is not the case (as may be when testing
            # this module in abnormal conditions), startmonitor will hang.
            # Just create the self.dst as a directory in this case.
            self.pmon.startmonitor(self.dst, self.total_size, 0, 100)

        # Perform the transfer specific operations.

        try:
            for trans_val in self._transfer_list:

                # Get the arguments for the transfer process
                arglist = trans_val.get(SVR4_ARGS).split(' ')

                # Parse the components to determine the transfer action
                if trans_val.get(ACTION) == 'install':
                    self.check_cancel_event()
                    self.logger.info("Installing SVR4 packages")
                    cmd = [AbstractSVR4.PKGADD] + arglist + \
                        trans_val.get(CONTENTS)

                elif trans_val.get(ACTION) == 'uninstall':
                    self.check_cancel_event()
                    self.logger.info("Uninstalling SVR4 packages")
                    cmd = [AbstractSVR4.PKGRM] + arglist + \
                        trans_val.get(CONTENTS)

                else:
                    self.logger.warning("Transfer action, %s, is not valid" %
                                        trans_val.get(ACTION))
                    self.check_cancel_event()
                    continue

                if self.dry_run:
                    self.logger.debug("Would execute the following transfer "
                                      "command: %s" % cmd)
                else:
                    self.logger.debug("Executing the following transfer "
                                      "command: %s" % cmd)
                    self.check_cancel_event()
                    pkg_proc = Popen(cmd,
                                     shell=False,
                                     stdout=Popen.PIPE,
                                     stderr=Popen.STDOUT)
                    while 1:
                        self.check_cancel_event()
                        pkgoutput = pkg_proc.stdout.readline()
                        if not pkgoutput:
                            retcode = pkg_proc.poll()
                            if retcode != 0:
                                self.svr4_process = None
                                raise OSError(
                                    retcode, "SVR4 transfer error while "
                                    "adding packages")
                            break
                        pkgoutput = pkgoutput[:-1]
                        if not pkgoutput.strip():
                            continue
                        self.logger.debug("%s", pkgoutput)
                    self.svr4_process = None

        finally:
            if self.pmon:
                self.pmon.done = True
                self.pmon.wait()
                self.pmon = None