1#!/usr/bin/python2
2# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import mox
7import pexpect
8import unittest
9
10import dli
11
12import rpm_controller
13
14import common
15from autotest_lib.site_utils.rpm_control_system import utils
16
17
18class TestRPMControllerQueue(mox.MoxTestBase):
19    """Test request can be queued and processed in controller."""
20
21    def setUp(self):
22        super(TestRPMControllerQueue, self).setUp()
23        self.rpm = rpm_controller.SentryRPMController('chromeos-rack1-host8')
24        self.powerunit_info = utils.PowerUnitInfo(
25                device_hostname='chromos-rack1-host8',
26                powerunit_hostname='chromeos-rack1-rpm1',
27                powerunit_type=utils.PowerUnitInfo.POWERUNIT_TYPES.RPM,
28                outlet='.A100',
29                hydra_hostname=None)
30
31
32    def testQueueRequest(self):
33        """Should create a new process to handle request."""
34        new_state = 'ON'
35        process = self.mox.CreateMockAnything()
36        rpm_controller.multiprocessing.Process = self.mox.CreateMockAnything()
37        rpm_controller.multiprocessing.Process(target=mox.IgnoreArg(),
38                args=mox.IgnoreArg()).AndReturn(process)
39        process.start()
40        process.join()
41        self.mox.ReplayAll()
42        self.assertFalse(self.rpm.queue_request(self.powerunit_info, new_state))
43        self.mox.VerifyAll()
44
45
46class TestSentryRPMController(mox.MoxTestBase):
47    """Test SentryRPMController."""
48
49
50    def setUp(self):
51        super(TestSentryRPMController, self).setUp()
52        self.ssh = self.mox.CreateMockAnything()
53        rpm_controller.pexpect.spawn = self.mox.CreateMockAnything()
54        rpm_controller.pexpect.spawn(mox.IgnoreArg()).AndReturn(self.ssh)
55        self.rpm = rpm_controller.SentryRPMController('chromeos-rack1-host8')
56        self.powerunit_info = utils.PowerUnitInfo(
57                device_hostname='chromos-rack1-host8',
58                powerunit_hostname='chromeos-rack1-rpm1',
59                powerunit_type=utils.PowerUnitInfo.POWERUNIT_TYPES.RPM,
60                outlet='.A100',
61                hydra_hostname=None)
62
63
64    def testSuccessfullyChangeOutlet(self):
65        """Should return True if change was successful."""
66        prompt = ['Switched CDU:', 'Switched PDU:']
67        password = 'admn'
68        new_state = 'ON'
69        self.ssh.expect('Password:', timeout=60)
70        self.ssh.sendline(password)
71        self.ssh.expect(prompt, timeout=60)
72        self.ssh.sendline('%s %s' % (new_state, self.powerunit_info.outlet))
73        self.ssh.expect('Command successful', timeout=60)
74        self.ssh.sendline('logout')
75        self.ssh.close(force=True)
76        self.mox.ReplayAll()
77        self.assertTrue(self.rpm.set_power_state(
78                self.powerunit_info, new_state))
79        self.mox.VerifyAll()
80
81
82    def testUnsuccessfullyChangeOutlet(self):
83        """Should return False if change was unsuccessful."""
84        prompt = ['Switched CDU:', 'Switched PDU:']
85        password = 'admn'
86        new_state = 'ON'
87        self.ssh.expect('Password:', timeout=60)
88        self.ssh.sendline(password)
89        self.ssh.expect(prompt, timeout=60)
90        self.ssh.sendline('%s %s' % (new_state, self.powerunit_info.outlet))
91        self.ssh.expect('Command successful',
92                        timeout=60).AndRaise(pexpect.TIMEOUT('Timed Out'))
93        self.ssh.sendline('logout')
94        self.ssh.close(force=True)
95        self.mox.ReplayAll()
96        self.assertFalse(
97            self.rpm.set_power_state(self.powerunit_info, new_state))
98        self.mox.VerifyAll()
99
100
101class TestWebPoweredRPMController(mox.MoxTestBase):
102    """Test WebPoweredRPMController."""
103
104
105    def setUp(self):
106        super(TestWebPoweredRPMController, self).setUp()
107        self.dli_ps = self.mox.CreateMock(dli.powerswitch)
108        hostname = 'chromeos-rack8a-rpm1'
109        self.web_rpm = rpm_controller.WebPoweredRPMController(hostname,
110                                                              self.dli_ps)
111        outlet = 8
112        dut = 'chromeos-rack8a-host8'
113        # Outlet statuses are in the format "u'ON'"
114        initial_state = 'u\'ON\''
115        self.test_status_list_initial = [[outlet, dut, initial_state]]
116        self.powerunit_info = utils.PowerUnitInfo(
117                device_hostname=dut,
118                powerunit_hostname=hostname,
119                powerunit_type=utils.PowerUnitInfo.POWERUNIT_TYPES.RPM,
120                outlet=outlet,
121                hydra_hostname=None)
122
123
124    def testSuccessfullyChangeOutlet(self):
125        """Should return True if change was successful."""
126        test_status_list_final = [[8, 'chromeos-rack8a-host8', 'u\'OFF\'']]
127        self.dli_ps.off(8)
128        self.dli_ps.statuslist().AndReturn(test_status_list_final)
129        self.mox.ReplayAll()
130        self.assertTrue(self.web_rpm.set_power_state(
131                self.powerunit_info, 'OFF'))
132        self.mox.VerifyAll()
133
134
135    def testUnsuccessfullyChangeOutlet(self):
136        """Should return False if Outlet State does not change."""
137        test_status_list_final = [[8, 'chromeos-rack8a-host8', 'u\'ON\'']]
138        self.dli_ps.off(8)
139        self.dli_ps.statuslist().AndReturn(test_status_list_final)
140        self.mox.ReplayAll()
141        self.assertFalse(self.web_rpm.set_power_state(
142                self.powerunit_info, 'OFF'))
143        self.mox.VerifyAll()
144
145
146    def testNoOutlet(self):
147        """Should return False if DUT hostname is not on the RPM device."""
148        self.powerunit_info.outlet=None
149        self.assertFalse(self.web_rpm.set_power_state(
150                self.powerunit_info, 'OFF'))
151
152
153class TestCiscoPOEController(mox.MoxTestBase):
154    """Test CiscoPOEController."""
155
156    DEVICE = 'chromeos2-poe-sw8#'
157    MATCHER = 'Port\\s+.*%s(\\s+(\\S+)){6,6}.*%s'
158    PORT = 'fa32'
159    PWD = 'Password:'
160    SERVO = 'chromeos1-rack3-host12-servo'
161    SWITCH = 'chromeos2-poe-switch8'
162    POWERUNIT_INFO = utils.PowerUnitInfo(
163            device_hostname=PORT,
164            powerunit_hostname=SERVO,
165            powerunit_type=utils.PowerUnitInfo.POWERUNIT_TYPES.POE,
166            outlet=PORT,
167            hydra_hostname=None)
168
169    def testLogin(self):
170        """Test we can log into the switch."""
171        rpm_controller.pexpect.spawn = self.mox.CreateMockAnything()
172        mock_ssh = self.mox.CreateMockAnything()
173        rpm_controller.pexpect.spawn(mox.IgnoreArg()).AndReturn(mock_ssh)
174        sut = rpm_controller.CiscoPOEController(self.SWITCH)
175        mock_ssh.expect(sut.POE_USERNAME_PROMPT, timeout=sut.LOGIN_TIMEOUT)
176        mock_ssh.sendline(mox.IgnoreArg())
177        mock_ssh.expect(self.PWD, timeout=sut.LOGIN_TIMEOUT)
178        mock_ssh.sendline(mox.IgnoreArg())
179        mock_ssh.expect(self.DEVICE, timeout=sut.LOGIN_TIMEOUT)
180        self.mox.ReplayAll()
181        self.assertIsNotNone(sut._login())
182        self.mox.VerifyAll()
183
184    def testSuccessfullyChangePowerState(self):
185        """Should return True if change was successful."""
186        sut = rpm_controller.CiscoPOEController(self.SWITCH)
187        mock_ssh = self.mox.CreateMockAnything()
188        self.mox.StubOutWithMock(sut, '_login')
189        sut._login().AndReturn(mock_ssh)
190        self.mox.StubOutWithMock(sut, '_verify_state')
191        sut._verify_state(self.PORT, 'ON', mock_ssh).AndReturn(True)
192        # _enter_configuration_terminal
193        mock_ssh.sendline(sut.CONFIG)
194        mock_ssh.expect(sut.config_prompt, timeout=sut.CMD_TIMEOUT)
195        mock_ssh.sendline(sut.CONFIG_IF % self.PORT)
196        mock_ssh.expect(sut.config_if_prompt, timeout=sut.CMD_TIMEOUT)
197        # _change_state
198        mock_ssh.sendline(sut.SET_STATE_ON)
199        # _exit_configuration_terminal
200        mock_ssh.sendline(sut.END_CMD)
201        mock_ssh.expect(sut.poe_prompt, timeout=sut.CMD_TIMEOUT)
202        # exit
203        mock_ssh.sendline(sut.EXIT_CMD)
204        mock_ssh.close(force=True)
205        self.mox.ReplayAll()
206        self.assertTrue(sut.set_power_state(self.POWERUNIT_INFO, 'ON'))
207        self.mox.VerifyAll()
208
209    def testUnableToEnterConfigurationTerminal(self):
210        """Should return False if unable to enter configuration terminal."""
211        exception = pexpect.TIMEOUT('Could not enter configuration terminal.')
212        sut = rpm_controller.CiscoPOEController(self.SWITCH)
213        timeout = sut.CMD_TIMEOUT
214        mock_ssh = self.mox.CreateMockAnything()
215        self.mox.StubOutWithMock(sut, '_login')
216        sut._login().AndReturn(mock_ssh)
217        mock_ssh.sendline(sut.CONFIG)
218        mock_ssh.expect(sut.config_prompt, timeout=timeout)
219        mock_ssh.sendline(sut.CONFIG_IF % self.PORT)
220        config_if_prompt = sut.config_if_prompt
221        mock_ssh.expect(config_if_prompt, timeout=timeout).AndRaise(exception)
222        mock_ssh.sendline(sut.END_CMD)
223        mock_ssh.sendline(sut.EXIT_CMD)
224        mock_ssh.close(force=True)
225        self.mox.ReplayAll()
226        self.assertFalse(sut.set_power_state(self.POWERUNIT_INFO, mock_ssh))
227        self.mox.VerifyAll()
228
229    def testUnableToExitConfigurationTerminal(self):
230        """Should return False if unable to exit configuration terminal."""
231        exception = pexpect.TIMEOUT('Could not exit configuration terminal.')
232        sut = rpm_controller.CiscoPOEController(self.SWITCH)
233        mock_ssh = self.mox.CreateMockAnything()
234        self.mox.StubOutWithMock(sut, '_login')
235        self.mox.StubOutWithMock(sut, '_enter_configuration_terminal')
236        sut._login().AndReturn(mock_ssh)
237        sut._enter_configuration_terminal(self.PORT, mock_ssh).AndReturn(True)
238        mock_ssh.sendline(sut.SET_STATE_ON)
239        mock_ssh.sendline(sut.END_CMD)
240        mock_ssh.expect(
241                self.DEVICE, timeout=sut.CMD_TIMEOUT).AndRaise(exception)
242        mock_ssh.sendline(sut.EXIT_CMD)
243        mock_ssh.close(force=True)
244        self.mox.ReplayAll()
245        self.assertFalse(sut.set_power_state(self.POWERUNIT_INFO, 'ON'))
246        self.mox.VerifyAll()
247
248    def testUnableToVerifyState(self):
249        """Should return False if unable to verify current state."""
250        sut = rpm_controller.CiscoPOEController(self.SWITCH)
251        mock_ssh = self.mox.CreateMockAnything()
252        self.mox.StubOutWithMock(sut, '_login')
253        self.mox.StubOutWithMock(sut, '_enter_configuration_terminal')
254        self.mox.StubOutWithMock(sut, '_exit_configuration_terminal')
255        sut._login().AndReturn(mock_ssh)
256        sut._enter_configuration_terminal(self.PORT, mock_ssh).AndReturn(True)
257        sut._exit_configuration_terminal(mock_ssh).AndReturn(True)
258        mock_ssh.sendline(sut.SET_STATE_ON)
259        mock_ssh.sendline(sut.CHECK_INTERFACE_STATE % self.PORT)
260        exception = pexpect.TIMEOUT('Could not verify state.')
261        matcher = self.MATCHER % (self.PORT, self.DEVICE)
262        mock_ssh.expect(matcher, timeout=sut.CMD_TIMEOUT).AndRaise(exception)
263        mock_ssh.sendline(sut.EXIT_CMD)
264        mock_ssh.close(force=True)
265        self.mox.ReplayAll()
266        self.assertFalse(sut.set_power_state(self.POWERUNIT_INFO, 'ON'))
267        self.mox.VerifyAll()
268
269
270if __name__ == "__main__":
271    unittest.main()
272