~nuclearbob/ubuntu-test-cases/touch-trace-export-dev

« back to all changes in this revision

Viewing changes to scripts/recover.py

  • Committer: Max Brustkern
  • Date: 2014-10-06 21:01:14 UTC
  • mfrom: (187.1.126 touch)
  • Revision ID: max@canonical.com-20141006210114-dxf7s210oyokzwl4
Merged latest changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
 
 
3
import device_info
 
4
import logging
 
5
import subprocess
 
6
import sys
 
7
import time
 
8
from ncd_usb import set_relay
 
9
 
 
10
log = logging.getLogger()
 
11
logging.basicConfig(level=logging.INFO)
 
12
 
 
13
 
 
14
class DeviceError(Exception):
 
15
    pass
 
16
 
 
17
 
 
18
def _reimage_from_fastboot(serial):
 
19
    #Starting from fastboot mode, put a known-good image on the device
 
20
    log.info("Flashing the last stable image")
 
21
    subprocess.check_output(['ubuntu-device-flash', '--serial', serial,
 
22
                             '--channel', 'ubuntu-touch/stable',
 
23
                             '--bootstrap', '--password', 'ubuntuci'])
 
24
    return _wait_for_device(serial, 600)
 
25
 
 
26
 
 
27
def _wait_for_device(serial, timeout=120):
 
28
    # Wait for the device to come up to a good/booted state
 
29
    log.info("Waiting for the device to become available")
 
30
    try:
 
31
        subprocess.check_call(['timeout', str(timeout), 'adb', '-s',
 
32
                               serial, 'wait-for-device'])
 
33
    except:
 
34
        log.error("Timed out waiting for reboot. Recover device manually")
 
35
        raise
 
36
    dev_state = device_info.get_state(serial)
 
37
    if dev_state != 'device':
 
38
        raise DeviceError("Device in state: {0}, still not available after "
 
39
                          "{1} seconds".format(dev_state, timeout))
 
40
    else:
 
41
        log.info("Device is now available")
 
42
        return 0
 
43
 
 
44
 
 
45
def _wait_for_fastboot(serial, timeout=120):
 
46
    if timeout > 10:
 
47
        wait = 10
 
48
    else:
 
49
        wait = timeout
 
50
    waited = 0
 
51
    while waited < timeout:
 
52
        state = device_info.get_state(serial)
 
53
        if state == 'fastboot':
 
54
            return 0
 
55
        time.sleep(wait)
 
56
        waited += wait
 
57
    else:
 
58
        state = device_info.get_state(serial)
 
59
        if state == 'fastboot':
 
60
            return 0
 
61
        log.error("Timed out waiting for fastboot. Recover device manually")
 
62
        raise DeviceError("Device in state: {0}, still not available after "
 
63
                          "{1} seconds".format(state, timeout))
 
64
 
 
65
 
 
66
def _mako_to_bootloader(urlbase, bank, power=1, volume=2):
 
67
    """
 
68
    This just works on mako for certain, but that's all we have connected
 
69
    right now. After this runs, the device should be in the bootloader
 
70
    """
 
71
    log.info("Forcing the device to enter the bootloader")
 
72
    #Power off the device from any state
 
73
    set_relay(urlbase, bank, power, 1)
 
74
    time.sleep(10)
 
75
    set_relay(urlbase, bank, power, 0)
 
76
    time.sleep(10)
 
77
    #Enter the bootloader
 
78
    set_relay(urlbase, bank, volume, 1)
 
79
    set_relay(urlbase, bank, power, 1)
 
80
    time.sleep(5)
 
81
    set_relay(urlbase, bank, volume, 0)
 
82
    set_relay(urlbase, bank, power, 0)
 
83
 
 
84
 
 
85
def _full_recovery(device_name):
 
86
    #we only support mako at the moment
 
87
    (url, bank, power, volume) = device_info.get_power(device_name)
 
88
    if None in (url, bank, power, volume):
 
89
        #This device does not have information about relays
 
90
        raise DeviceError("Full recovery not possible with this device")
 
91
    _mako_to_bootloader(url, bank, power, volume)
 
92
    serial = device_info.get_serial(device_name)
 
93
    _wait_for_fastboot(serial)
 
94
    _reimage_from_fastboot(serial)
 
95
    try:
 
96
        _check_adb_shell(serial)
 
97
    except:
 
98
        # The device looks like it's available, but not responding
 
99
        raise DeviceError("Could not fully recover {}".format(device_name))
 
100
    return 0
 
101
 
 
102
 
 
103
def _check_adb_shell(serial):
 
104
    # Run a quick command in adb to see if the device is responding
 
105
    subprocess.check_call(['timeout', '10', 'adb', '-s',
 
106
                           serial, 'shell', 'pwd'])
 
107
 
 
108
 
 
109
def recover(device):
 
110
    try:
 
111
        serial = device_info.get_serial(device)
 
112
    except AttributeError:
 
113
        log.error("No device found for '{}'".format(device))
 
114
        raise
 
115
    state = device_info.get_state(serial)
 
116
    if state in ('device', 'recovery'):
 
117
        try:
 
118
            _check_adb_shell(serial)
 
119
        except:
 
120
            # The device looks like it's available, but not responding
 
121
            return _full_recovery(device)
 
122
        #The device can proceed with testing
 
123
        return 0
 
124
    if state == 'fastboot':
 
125
        #The device is in fastboot right now, we need it booted first
 
126
        _reimage_from_fastboot(serial)
 
127
        try:
 
128
            _check_adb_shell(serial)
 
129
        except:
 
130
            # The device looks like it's available, but not responding
 
131
            return _full_recovery(device)
 
132
    if state in ('unknown', 'disconnected'):
 
133
        #The device is in an unknown state, we need full recovery
 
134
        return _full_recovery(device)
 
135
    #In theory, we should never get here, but....
 
136
    raise DeviceError("Device '{}' is in an unknown state!".format(device))
 
137
 
 
138
 
 
139
if __name__ == '__main__':
 
140
    name = sys.argv[1]
 
141
    try:
 
142
        print(recover(name))
 
143
    except AttributeError:
 
144
        #This is what we'll get if it's an unknown device, raise for
 
145
        #everything else so we get better debugging information
 
146
        sys.exit(-1)