from testrunner import VdsmTestCase as TestCaseBase
import supervdsm
import testValidation
import tempfile
from vdsm import utils
import os
import uuid
from vdsm import constants
from storage import misc
from monkeypatch import MonkeyPatch
from time import sleep
from vdsm.constants import DISKIMAGE_GROUP, METADATA_GROUP,\
    QEMU_PROCESS_USER, EXT_PS


@utils.memoized
def getNeededPythonPath():
    testDir = os.path.dirname(__file__)
    base = os.path.dirname(testDir)
    vdsmPath = os.path.join(base, 'vdsm')
    cliPath = os.path.join(base, 'vdsm_cli')
    pyPath = "PYTHONPATH=" + ':'.join([base, vdsmPath, cliPath])
    return pyPath


def monkeyStart(self):
    self._authkey = str(uuid.uuid4())
    self._log.debug("Launching Super Vdsm")

    superVdsmCmd = [getNeededPythonPath(), constants.EXT_PYTHON,
                    supervdsm.SUPERVDSM,
                    self._authkey, str(os.getpid()),
                    self.pidfile, self.timestamp, self.address,
                    str(os.getuid())]
    misc.execCmd(superVdsmCmd, sync=False, sudo=True)
    sleep(2)


class TestSuperVdsm(TestCaseBase):
    def setUp(self):
        testValidation.checkSudo(['python', supervdsm.SUPERVDSM])
        self._proxy = supervdsm.getProxy()

        # temporary values to run temporary svdsm
        self.pidfd, pidfile = tempfile.mkstemp()
        self.timefd, timestamp = tempfile.mkstemp()
        self.addfd, address = tempfile.mkstemp()

        self._proxy.setIPCPaths(pidfile, timestamp, address)

    def tearDown(self):
        supervdsm.extraPythonPathList = []
        for fd in (self.pidfd, self.timefd, self.addfd):
            try:
                os.close(fd)
            except OSError:
                pass
        self._proxy.kill()  # cleanning old temp files

    @MonkeyPatch(supervdsm.SuperVdsmProxy, '_start', monkeyStart)
    def testIsSuperUp(self):
        self._proxy.ping()  # this call initiate svdsm
        self.assertTrue(self._proxy.isRunning())

    @MonkeyPatch(supervdsm.SuperVdsmProxy, '_start', monkeyStart)
    def testKillSuper(self):
        self._proxy.ping()
        self._proxy.kill()
        self.assertFalse(self._proxy.isRunning())
        self._proxy.ping()  # Launching vdsm after kill
        self.assertTrue(self._proxy.isRunning())

    @MonkeyPatch(supervdsm.SuperVdsmProxy, '_start', monkeyStart)
    def testNoPidFile(self):
        self._proxy.ping()  # svdsm is up
        self.assertTrue(self._proxy.isRunning())
        utils.rmFile(self._proxy.timestamp)
        self.assertRaises(IOError, self._proxy.isRunning)

    @MonkeyPatch(supervdsm.SuperVdsmProxy, '_start', monkeyStart)
    def testZombieReaper(self):
        REPO_PATH = '/rhev/data-center'
        self._proxy.ping()
        self.assertTrue(self._proxy.isRunning())
        self._proxy.validateAccess(
                QEMU_PROCESS_USER,
                (DISKIMAGE_GROUP, METADATA_GROUP), REPO_PATH,
                (os.R_OK | os.X_OK))
        sleep(4)
        self._proxy.validateAccess(
                QEMU_PROCESS_USER,
                (DISKIMAGE_GROUP, METADATA_GROUP), REPO_PATH,
                (os.R_OK | os.X_OK))

        with os.fdopen(self.pidfd, "r") as f:
            svdsmPid = f.read().strip()

        reapPid = utils.execCmd(
                         [EXT_PS, '--ppid', svdsmPid, '-o', 'pid='])[1]
        if reapPid:
            sleep(6)  # supervdsmServer checks SIGCHLD every 5 secs
            self.assertRaises(OSError, os.waitpid, int(reapPid[0]), os.WNOHANG)
