[autotest] rpm dispatcher/controller get power info from frontend server

This is the 3rd CL for making the rpm infra read rpm/outlet/hydra
info from AFE.

Previously, rpm dispatcher/controler uses regular expression pattern
to determine the hydra hostname. And outlet(ports) must be labeled
with hostname beforehand.

This cl makes rpm dispatcher/controler receive a PowerUnitInfo instance
from frontend server, which includes the rpm(poe)/outlet(port)/hydra
information for the device.

CQ-DEPEND=CL:212346
BUG=chromium:392548
TEST=unittest; Integration tests with other cls in this series, set
up a local rpm server and power cycle devices.

Change-Id: I492531c8dc3f134d32f73d0a0560bf54f8a28b70
Reviewed-on: https://chromium-review.googlesource.com/212357
Tested-by: Fang Deng <fdeng@chromium.org>
Reviewed-by: Simran Basi <sbasi@chromium.org>
Commit-Queue: Fang Deng <fdeng@chromium.org>
diff --git a/site_utils/rpm_control_system/rpm_controller_unittest.py b/site_utils/rpm_control_system/rpm_controller_unittest.py
index f88f1c1..dd6bb2f 100755
--- a/site_utils/rpm_control_system/rpm_controller_unittest.py
+++ b/site_utils/rpm_control_system/rpm_controller_unittest.py
@@ -11,6 +11,9 @@
 
 import rpm_controller
 
+import common
+from autotest_lib.site_utils.rpm_control_system import utils
+
 
 class TestRPMControllerQueue(mox.MoxTestBase):
     """Test request can be queued and processed in controller.
@@ -19,11 +22,16 @@
     def setUp(self):
         super(TestRPMControllerQueue, self).setUp()
         self.rpm = rpm_controller.SentryRPMController('chromeos-rack1-host8')
+        self.powerunit_info = utils.PowerUnitInfo(
+                device_hostname='chromos-rack1-host8',
+                powerunit_hostname='chromeos-rack1-rpm1',
+                powerunit_type=utils.PowerUnitInfo.POWERUNIT_TYPES.RPM,
+                outlet='.A100',
+                hydra_hostname=None)
 
 
     def testQueueRequest(self):
         """Should create a new process to handle request."""
-        dut_hostname = 'chromos-rack1-host8'
         new_state = 'ON'
         process = self.mox.CreateMockAnything()
         rpm_controller.multiprocessing.Process = self.mox.CreateMockAnything()
@@ -32,7 +40,7 @@
         process.start()
         process.join()
         self.mox.ReplayAll()
-        self.assertFalse(self.rpm.queue_request(dut_hostname, new_state))
+        self.assertFalse(self.rpm.queue_request(self.powerunit_info, new_state))
         self.mox.VerifyAll()
 
 
@@ -46,23 +54,29 @@
         rpm_controller.pexpect.spawn = self.mox.CreateMockAnything()
         rpm_controller.pexpect.spawn(mox.IgnoreArg()).AndReturn(self.ssh)
         self.rpm = rpm_controller.SentryRPMController('chromeos-rack1-host8')
+        self.powerunit_info = utils.PowerUnitInfo(
+                device_hostname='chromos-rack1-host8',
+                powerunit_hostname='chromeos-rack1-rpm1',
+                powerunit_type=utils.PowerUnitInfo.POWERUNIT_TYPES.RPM,
+                outlet='.A100',
+                hydra_hostname=None)
 
 
     def testSuccessfullyChangeOutlet(self):
         """Should return True if change was successful."""
         prompt = 'Switched CDU:'
         password = 'admn'
-        dut_hostname = 'chromos-rack1-host8'
         new_state = 'ON'
         self.ssh.expect('Password:', timeout=60)
         self.ssh.sendline(password)
         self.ssh.expect(prompt, timeout=60)
-        self.ssh.sendline('%s %s' % (new_state, dut_hostname))
+        self.ssh.sendline('%s %s' % (new_state, self.powerunit_info.outlet))
         self.ssh.expect('Command successful', timeout=60)
         self.ssh.sendline('logout')
         self.ssh.close(force=True)
         self.mox.ReplayAll()
-        self.assertTrue(self.rpm.set_power_state(dut_hostname, new_state))
+        self.assertTrue(self.rpm.set_power_state(
+                self.powerunit_info, new_state))
         self.mox.VerifyAll()
 
 
@@ -70,18 +84,17 @@
         """Should return False if change was unsuccessful."""
         prompt = 'Switched CDU:'
         password = 'admn'
-        dut_hostname = 'chromos-rack1-host8'
         new_state = 'ON'
         self.ssh.expect('Password:', timeout=60)
         self.ssh.sendline(password)
         self.ssh.expect(prompt, timeout=60)
-        self.ssh.sendline('%s %s' % (new_state, dut_hostname))
+        self.ssh.sendline('%s %s' % (new_state, self.powerunit_info.outlet))
         self.ssh.expect('Command successful',
                         timeout=60).AndRaise(pexpect.TIMEOUT('Timed Out'))
         self.ssh.sendline('logout')
         self.ssh.close(force=True)
         self.mox.ReplayAll()
-        self.assertFalse(self.rpm.set_power_state(dut_hostname, new_state))
+        self.assertFalse(self.rpm.set_power_state(self.powerunit_info, new_state))
         self.mox.VerifyAll()
 
 
@@ -100,6 +113,12 @@
         # Outlet statuses are in the format "u'ON'"
         initial_state = 'u\'ON\''
         self.test_status_list_initial = [[outlet, dut, initial_state]]
+        self.powerunit_info = utils.PowerUnitInfo(
+                device_hostname=dut,
+                powerunit_hostname=hostname,
+                powerunit_type=utils.PowerUnitInfo.POWERUNIT_TYPES.RPM,
+                outlet=outlet,
+                hydra_hostname=None)
 
 
     def testSuccessfullyChangeOutlet(self):
@@ -109,8 +128,8 @@
         self.dli_ps.off(8)
         self.dli_ps.statuslist().AndReturn(test_status_list_final)
         self.mox.ReplayAll()
-        self.assertTrue(self.web_rpm.set_power_state('chromeos-rack8a-host8',
-                                                   'OFF'))
+        self.assertTrue(self.web_rpm.set_power_state(
+                self.powerunit_info, 'OFF'))
         self.mox.VerifyAll()
 
 
@@ -121,18 +140,16 @@
         self.dli_ps.off(8)
         self.dli_ps.statuslist().AndReturn(test_status_list_final)
         self.mox.ReplayAll()
-        self.assertFalse(self.web_rpm.set_power_state('chromeos-rack8a-host8',
-                                                    'OFF'))
+        self.assertFalse(self.web_rpm.set_power_state(
+                self.powerunit_info, 'OFF'))
         self.mox.VerifyAll()
 
 
-    def testDutNotOnRPM(self):
+    def testNoOutlet(self):
         """Should return False if DUT hostname is not on the RPM device."""
-        self.dli_ps.statuslist().AndReturn(self.test_status_list_initial)
-        self.mox.ReplayAll()
-        self.assertFalse(self.web_rpm.set_power_state('chromeos-rack8a-host1',
-                                                    'OFF'))
-        self.mox.VerifyAll()
+        self.powerunit_info.outlet=None
+        self.assertFalse(self.web_rpm.set_power_state(
+                self.powerunit_info, 'OFF'))
 
 
 class TestCiscoPOEController(mox.MoxTestBase):
@@ -155,6 +172,12 @@
     SERVO = 'chromeos1-rack3-host12-servo'
     SWITCH = 'chromeos2-poe-switch8'
     PORT = 'fa32'
+    POWERUNIT_INFO = utils.PowerUnitInfo(
+            device_hostname=PORT,
+            powerunit_hostname=SERVO,
+            powerunit_type=utils.PowerUnitInfo.POWERUNIT_TYPES.POE,
+            outlet=PORT,
+            hydra_hostname=None)
 
 
     def setUp(self):
@@ -162,9 +185,7 @@
         self.mox.StubOutWithMock(pexpect.spawn, '_spawn')
         self.mox.StubOutWithMock(pexpect.spawn, 'read_nonblocking')
         self.mox.StubOutWithMock(pexpect.spawn, 'sendline')
-        servo_interface = {self.SERVO:(self.SWITCH, self.PORT)}
-        self.poe = rpm_controller.CiscoPOEController(
-                self.SWITCH, servo_interface)
+        self.poe = rpm_controller.CiscoPOEController(self.SWITCH)
         pexpect.spawn._spawn(mox.IgnoreArg(), mox.IgnoreArg())
         pexpect.spawn.read_nonblocking(
                 mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(self.STREAM_WELCOME)
@@ -222,7 +243,7 @@
                 mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(self.STREAM_DEVICE)
         pexpect.spawn.sendline('exit')
         self.mox.ReplayAll()
-        self.assertTrue(self.poe.set_power_state(self.SERVO, 'ON'))
+        self.assertTrue(self.poe.set_power_state(self.POWERUNIT_INFO, 'ON'))
         self.mox.VerifyAll()
 
 
@@ -231,7 +252,7 @@
         self._EnterConfigurationHelper(success=False)
         pexpect.spawn.sendline('exit')
         self.mox.ReplayAll()
-        self.assertFalse(self.poe.set_power_state(self.SERVO, 'ON'))
+        self.assertFalse(self.poe.set_power_state(self.POWERUNIT_INFO, 'ON'))
         self.mox.VerifyAll()
 
 
@@ -251,7 +272,7 @@
         pexpect.spawn.__str__().AndReturn('A pexpect.spawn object.')
         pexpect.spawn.sendline('exit')
         self.mox.ReplayAll()
-        self.assertFalse(self.poe.set_power_state(self.SERVO, 'ON'))
+        self.assertFalse(self.poe.set_power_state(self.POWERUNIT_INFO, 'ON'))
         self.mox.VerifyAll()
 
 
@@ -274,7 +295,7 @@
         pexpect.spawn.__str__().AndReturn('A pexpect.spawn object.')
         pexpect.spawn.sendline('exit')
         self.mox.ReplayAll()
-        self.assertFalse(self.poe.set_power_state(self.SERVO, 'ON'))
+        self.assertFalse(self.poe.set_power_state(self.POWERUNIT_INFO, 'ON'))
         self.mox.VerifyAll()