def hosts(request):
    _hosts = _get_data(request, "hosts")
    _result = Hosts()
    for _host in _hosts['HOSTS']:
        instance = Host(len(_result.all()), **_host)
        instance._hostImplementation = instance
        _result.add(instance)
    return _result
class ReclaimHostTest(EpollEventLoopTestCase):
    def setUp(self):
        super(ReclaimHostTest, self).setUp(moduleInWhichToSetupMocks=reclaimhostspooler)
        self._host = FakeHost()
        self._hostStateMachine = FakeHostStateMachine(self._host)
        self._hosts = Hosts()
        self._hosts.add(self._hostStateMachine)
        self._tftpboot = FakeTFTPBoot()
        self._wasThereAnAttemptToCreateFifo = False
        self._fakeSoftReclaimRequestFifoPath = "/fakeNotifyFifoPath"
        self._fakeSoftReclaimFailedFifoPath = "/fakeSoftReclaimFailedFifoPath"
        self._origKillSelf = reclaimhostspooler.suicide.killSelf
        reclaimhostspooler.suicide.killSelf = mock.Mock()

    def tearDown(self):
        reclaimhostspooler.suicide.killSelf = self._origKillSelf
        super(ReclaimHostTest, self).tearDown()

    def _validateSoftReclamationRequestsFifo(self, requests):
        for requestType, host in requests:
            if requestType == "soft":
                expectedRequest = self._getEncodedSoftRequest(host)
            elif requestType == "cold":
                expectedRequest = self._getEncodedColdRequest(host)
            else:
                self.assertTrue(False)
            actual = self._pipeMethodsMock.getFifoContent(self._fakeSoftReclaimRequestFifoPath)
            expected = expectedRequest + ","
            self.assertEquals(actual, expected)

    def _getEncodedColdRequest(self, host):
        requestArgs = [host.id(),
                       host.primaryMacAddress()]
        decodedRequest = ",".join(requestArgs)
        encodedRequest = base64.encodestring(decodedRequest)
        return encodedRequest

    def _getEncodedSoftRequest(self, host):
        credentials = host.rootSSHCredentials()
        requestArgs = [host.id(),
                       credentials["hostname"],
                       credentials["username"],
                       credentials["password"],
                       host.primaryMacAddress()]
        decodedRequest = ",".join(requestArgs)
        encodedRequest = base64.encodestring(decodedRequest)
        return encodedRequest

    def _generateTestedInstance(self):
        instance = reclaimhostspooler.ReclaimHostSpooler(self._hosts,
                                                         self._fakeSoftReclaimRequestFifoPath,
                                                         self._fakeSoftReclaimFailedFifoPath)
        instance._handleColdReclamationRequest = mock.Mock()
        return instance
 def setUp(self):
     super(ReclaimHostTest, self).setUp(moduleInWhichToSetupMocks=reclaimhostspooler)
     self._host = FakeHost()
     self._hostStateMachine = FakeHostStateMachine(self._host)
     self._hosts = Hosts()
     self._hosts.add(self._hostStateMachine)
     self._tftpboot = FakeTFTPBoot()
     self._wasThereAnAttemptToCreateFifo = False
     self._fakeSoftReclaimRequestFifoPath = "/fakeNotifyFifoPath"
     self._fakeSoftReclaimFailedFifoPath = "/fakeSoftReclaimFailedFifoPath"
     self._origKillSelf = reclaimhostspooler.suicide.killSelf
     reclaimhostspooler.suicide.killSelf = mock.Mock()
 def setUp(self):
     super(Test, self).setUp(moduleInWhichToSetupMocks=reclaimhostspooler)
     self._host = FakeHost()
     self._hostStateMachine = FakeHostStateMachine(self._host)
     self._hosts = Hosts()
     self._hosts.add(self._hostStateMachine)
     self._tftpboot = FakeTFTPBoot()
     self._wasThereAnAttemptToCreateFifo = False
     self._fakeSoftReclaimRequestFifoPath = "/fakeNotifyFifoPath"
     self._fakeSoftReclaimFailedFifoPath = "/fakeSoftReclaimFailedFifoPath"
     self._origKillSelf = reclaimhostspooler.suicide.killSelf
     reclaimhostspooler.suicide.killSelf = mock.Mock()
     self._actualColdReclamationRequests = []
     self._tested = self._generateTestedInstanceWithMockedThreading()
     self._expectedRequests = []
     self._coldReclaimCallbackRaisesException = False
class Test(EpollEventLoopTestCase):
    def setUp(self):
        super(Test, self).setUp(moduleInWhichToSetupMocks=reclaimhostspooler)
        self._host = FakeHost()
        self._hostStateMachine = FakeHostStateMachine(self._host)
        self._hosts = Hosts()
        self._hosts.add(self._hostStateMachine)
        self._tftpboot = FakeTFTPBoot()
        self._wasThereAnAttemptToCreateFifo = False
        self._fakeSoftReclaimRequestFifoPath = "/fakeNotifyFifoPath"
        self._fakeSoftReclaimFailedFifoPath = "/fakeSoftReclaimFailedFifoPath"
        self._origKillSelf = reclaimhostspooler.suicide.killSelf
        reclaimhostspooler.suicide.killSelf = mock.Mock()
        self._actualColdReclamationRequests = []
        self._tested = self._generateTestedInstanceWithMockedThreading()
        self._expectedRequests = []
        self._coldReclaimCallbackRaisesException = False

    def tearDown(self):
        reclaimhostspooler.suicide.killSelf = self._origKillSelf
        super(Test, self).tearDown()

    def test_FifosCreatedIfDoNotExist(self):
        self.assertFalse(self._fakeFilesystem.Exists(self._fakeSoftReclaimRequestFifoPath))
        self.assertFalse(self._fakeFilesystem.Exists(self._fakeSoftReclaimFailedFifoPath))
        self._continueWithEventLoop()
        self.assertTrue(self._fakeFilesystem.Exists(self._fakeSoftReclaimRequestFifoPath))
        self.assertTrue(self._fakeFilesystem.Exists(self._fakeSoftReclaimFailedFifoPath))

    def test_FifosStayIfAlreadyExist(self):
        self._pipeMethodsMock.osMkfifo(self._fakeSoftReclaimRequestFifoPath)
        self._pipeMethodsMock.osMkfifo(self._fakeSoftReclaimFailedFifoPath)
        self.assertTrue(self._fakeFilesystem.Exists(self._fakeSoftReclaimRequestFifoPath))
        self.assertTrue(self._fakeFilesystem.Exists(self._fakeSoftReclaimFailedFifoPath))
        self._continueWithEventLoop()
        self.assertTrue(self._fakeFilesystem.Exists(self._fakeSoftReclaimRequestFifoPath))
        self.assertTrue(self._fakeFilesystem.Exists(self._fakeSoftReclaimFailedFifoPath))

    def test_SoftReclaimRequest(self):
        self._validateSoftReclaimFlow()

    def test_SoftReclaimFailed(self):
        self._continueWithEventLoop()
        softReclaimFailedFifoWriteFd = self._pipeMethodsMock.osOpen(self._fakeSoftReclaimFailedFifoPath, os.O_WRONLY)
        self._pipeMethodsMock.osWrite(softReclaimFailedFifoWriteFd, self._host.id())
        self._continueWithEventLoop()
        self._hostStateMachine.softReclaimFailed.assert_called_once_with()

    def test_NoCrashOnSoftReclaimFailedCallbackFaliure(self):
        self._hostStateMachine.softReclaimFailed.side_effect = Exception("don't crash because of me")
        self._continueWithEventLoop()
        softReclaimFailedFifoWriteFd = self._pipeMethodsMock.osOpen(self._fakeSoftReclaimFailedFifoPath, os.O_WRONLY)
        self._pipeMethodsMock.osWrite(softReclaimFailedFifoWriteFd, self._host.id())
        self._continueWithEventLoop()
        self._hostStateMachine.softReclaimFailed.assert_called_once_with()
        self._hostStateMachine.softReclaimFailed.side_effect = None
        self._validateSoftReclaimFlow()

    def test_NoCrashOnSoftReclaimFailedMsgForNonExistentHost(self):
        self._continueWithEventLoop()
        softReclaimFailedFifoWriteFd = self._pipeMethodsMock.osOpen(self._fakeSoftReclaimFailedFifoPath, os.O_WRONLY)
        self._pipeMethodsMock.osWrite(softReclaimFailedFifoWriteFd, "non-existent")
        self._continueWithEventLoop()
        self._validateSoftReclaimFlow()

    def test_NoCrashOnSoftReclaimFailedForEmptyHost(self):
        self._continueWithEventLoop()
        softReclaimFailedFifoWriteFd = self._pipeMethodsMock.osOpen(self._fakeSoftReclaimFailedFifoPath, os.O_WRONLY)
        self._pipeMethodsMock.osWrite(softReclaimFailedFifoWriteFd, "fake id,,")
        self._continueWithEventLoop()
        self._validateSoftReclaimFlow()

    def test_SuicideOnFailure(self):
        self._continueWithEventLoop()
        self._addColdReclamationRequest(self._host)
        self._coldReclaimCallbackRaisesException = True
        self.assertRaises(ValueError, self._continueWithEventLoop)
        reclaimhostspooler.suicide.killSelf.assert_called_once_with()

    def test_NoCrashOnSoftReclaimRequestForHostWithEmptyName(self):
        self._host._id = ""
        self._validateSoftReclaimFlow()

    def test_ColdReclaimRequest(self):
        self._continueWithEventLoop()
        self._addColdReclamationRequest(self._host)
        self._continueWithEventLoop()
        self._validateExpectedRequests()

    def test_ColdReclaimRequestWithHardReset(self):
        self._continueWithEventLoop()
        self._addColdReclamationRequest(self._host, hardReset=True)
        self._continueWithEventLoop()
        self._validateExpectedRequests()

    def _addSoftReclamationRequest(self, host):
        self._expectedRequests.append(["soft", self._host])
        request = greenlet.greenlet(lambda: self._tested.soft(self._host))
        request.switch()

    def _addColdReclamationRequest(self, host, hardReset=False):
        self._expectedRequests.append(["cold", self._host, hardReset])
        request = greenlet.greenlet(lambda: self._tested.cold(self._host, hardReset=hardReset))
        request.switch()

    def _validateExpectedRequests(self):
        self._continueWithEventLoop()
        for request in self._expectedRequests:
            requestType = request[0]
            if requestType == "cold":
                actual = self._actualColdReclamationRequests.pop(0)
                expected = request[1:]
            elif requestType == "soft":
                host = request[1]
                expected = self._getEncodedSoftRequest(host)
                actual = self._pipeMethodsMock.getFifoContent(self._fakeSoftReclaimRequestFifoPath)
                actual = base64.decodestring(actual)
            else:
                self.assertFalse(True)
            self.assertEquals(actual, expected)

    def _validateSoftReclaimFlow(self):
        self._continueWithEventLoop()
        self._addSoftReclamationRequest(self._host)
        self._validateExpectedRequests()

    def _handleColdReclamationRequest(self, host, hardReset):
        if self._coldReclaimCallbackRaisesException:
            raise ValueError("Ignore me")
        self._actualColdReclamationRequests.append([host, hardReset])

    def _getEncodedColdRequest(self, host):
        requestArgs = [host.id(), host.primaryMACAddress()]
        decodedRequest = ",".join(requestArgs)
        encodedRequest = base64.encodestring(decodedRequest)
        return encodedRequest

    def _getEncodedSoftRequest(self, host):
        credentials = host.rootSSHCredentials()
        requestArgs = [
            "soft",
            host.id(),
            credentials["hostname"],
            credentials["username"],
            credentials["password"],
            host.primaryMACAddress(),
            host.targetDevice(),
            "False",
        ]
        return ",".join(requestArgs)

    def _generateTestedInstance(self):
        ReclaimHostSpoolerWithColdReclamation._handleColdReclamationRequest = self._handleColdReclamationRequest
        instance = ReclaimHostSpoolerWithColdReclamation(
            self._hosts, self._fakeSoftReclaimRequestFifoPath, self._fakeSoftReclaimFailedFifoPath
        )
        return instance