1#!/usr/bin/python
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 argparse
7import logging
8import sys
9import xmlrpclib
10
11import common
12
13from config import rpm_config
14from autotest_lib.client.common_lib import global_config
15from autotest_lib.client.common_lib.cros import retry
16
17
18RPM_FRONTEND_URI = global_config.global_config.get_config_value('CROS',
19        'rpm_frontend_uri', type=str, default='')
20RPM_CALL_TIMEOUT_MINS = rpm_config.getint('RPM_INFRASTRUCTURE',
21                                          'call_timeout_mins')
22
23
24class RemotePowerException(Exception):
25    """This is raised when we fail to set the state of the device's outlet."""
26    pass
27
28
29def set_power(hostname, new_state, timeout_mins=RPM_CALL_TIMEOUT_MINS):
30    """Sends the power state change request to the RPM Infrastructure.
31
32    @param hostname: host who's power outlet we want to change.
33    @param new_state: State we want to set the power outlet to.
34    """
35    client = xmlrpclib.ServerProxy(RPM_FRONTEND_URI, verbose=False)
36    timeout = None
37    result = None
38    try:
39        timeout, result = retry.timeout(client.queue_request,
40                                        args=(hostname, new_state),
41                                        timeout_sec=timeout_mins * 60,
42                                        default_result=False)
43    except Exception as e:
44        logging.exception(e)
45        raise RemotePowerException(
46                'Client call exception: ' + str(e))
47    if timeout:
48        raise RemotePowerException(
49                'Call to RPM Infrastructure timed out.')
50    if not result:
51        error_msg = ('Failed to change outlet status for host: %s to '
52                     'state: %s.' % (hostname, new_state))
53        logging.error(error_msg)
54        raise RemotePowerException(error_msg)
55
56
57def parse_options():
58    """Parse the user supplied options."""
59    parser = argparse.ArgumentParser()
60    parser.add_argument('-m', '--machine', dest='machine',
61                        help='Machine hostname to change outlet state.')
62    parser.add_argument('-s', '--state', dest='state',
63                        help='Power state to set outlet: ON, OFF, CYCLE')
64    parser.add_argument('-d', '--disable_emails', dest='disable_emails',
65                        help='Hours to suspend RPM email notifications.')
66    parser.add_argument('-e', '--enable_emails', dest='enable_emails',
67                        action='store_true',
68                        help='Resume RPM email notifications.')
69    return parser.parse_args()
70
71
72def main():
73    """Entry point for rpm_client script."""
74    options = parse_options()
75    if options.machine is not None and options.state is None:
76        print 'Need --state to change outlet state.'
77    elif options.machine is not None and options.state is not None:
78        set_power(options.machine, options.state)
79
80    if options.disable_emails is not None:
81        client = xmlrpclib.ServerProxy(RPM_FRONTEND_URI, verbose=False)
82        client.suspend_emails(options.disable_emails)
83    if options.enable_emails:
84        client = xmlrpclib.ServerProxy(RPM_FRONTEND_URI, verbose=False)
85        client.resume_emails()
86
87
88if __name__ == "__main__":
89    sys.exit(main())
90