blob: 35fc7442bb83e64eef9e7a9ae5aa465f0e3d64ec [file] [log] [blame]
Keun Soo Yimb293fdb2016-09-21 16:03:44 -07001#!/usr/bin/env python
2#
3# Copyright 2016 - The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070016"""Kernel Swapper.
17
18This class manages swapping kernel images for a Cloud Android instance.
19"""
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070020import subprocess
21
22from acloud.public import errors
23from acloud.public import report
24from acloud.internal.lib import android_build_client
25from acloud.internal.lib import android_compute_client
26from acloud.internal.lib import auth
27from acloud.internal.lib import gstorage_client
28from acloud.internal.lib import utils
29
cylan0d77ae12018-05-18 08:36:48 +000030ALL_SCOPES = ' '.join([
31 android_build_client.AndroidBuildClient.SCOPE,
32 gstorage_client.StorageClient.SCOPE,
33 android_compute_client.AndroidComputeClient.SCOPE
34])
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070035
36# ssh flags used to communicate with the Cloud Android instance.
37SSH_FLAGS = [
38 '-q', '-o UserKnownHostsFile=/dev/null', '-o "StrictHostKeyChecking no"',
39 '-o ServerAliveInterval=10'
40]
41
42# Shell commands run on target.
43MOUNT_CMD = ('if mountpoint -q /boot ; then umount /boot ; fi ; '
44 'mount -t ext4 /dev/block/sda1 /boot')
45REBOOT_CMD = 'nohup reboot > /dev/null 2>&1 &'
46
47
48class KernelSwapper(object):
49 """A class that manages swapping a kernel image on a Cloud Android instance.
50
51 Attributes:
52 _compute_client: AndroidCopmuteClient object, manages AVD.
cylan0d77ae12018-05-18 08:36:48 +000053 _instance_name: tring, name of Cloud Android Instance.
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070054 _target_ip: string, IP address of Cloud Android instance.
55 _ssh_flags: string list, flags to be used with ssh and scp.
56 """
57
58 def __init__(self, cfg, instance_name):
59 """Initialize.
60
61 Args:
62 cfg: AcloudConfig object, used to create credentials.
63 instance_name: string, instance name.
64 """
65 credentials = auth.CreateCredentials(cfg, ALL_SCOPES)
66 self._compute_client = android_compute_client.AndroidComputeClient(
67 cfg, credentials)
68 # Name of the Cloud Android instance.
69 self._instance_name = instance_name
70 # IP of the Cloud Android instance.
71 self._target_ip = self._compute_client.GetInstanceIP(instance_name)
72
73 def SwapKernel(self, local_kernel_image):
74 """Swaps the kernel image on target AVD with given kernel.
75
76 Mounts boot image containing the kernel image to the filesystem, then
77 overwrites that kernel image with a new kernel image, then reboots the
78 Cloud Android instance.
79
80 Args:
81 local_kernel_image: string, local path to a kernel image.
82
83 Returns:
84 A Report instance.
85 """
cylan0d77ae12018-05-18 08:36:48 +000086 reboot_image = report.Report(command='swap_kernel')
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070087 try:
88 self._ShellCmdOnTarget(MOUNT_CMD)
89 self.PushFile(local_kernel_image, '/boot')
90 self.RebootTarget()
91 except subprocess.CalledProcessError as e:
cylan0d77ae12018-05-18 08:36:48 +000092 reboot_image.AddError(str(e))
93 reboot_image.SetStatus(report.Status.FAIL)
94 return reboot_image
Kevin Chengb5963882018-05-09 00:06:27 -070095 except errors.DeviceBootError as e:
cylan0d77ae12018-05-18 08:36:48 +000096 reboot_image.AddError(str(e))
97 reboot_image.SetStatus(report.Status.BOOT_FAIL)
98 return reboot_image
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070099
cylan0d77ae12018-05-18 08:36:48 +0000100 reboot_image.SetStatus(report.Status.SUCCESS)
101 return reboot_image
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700102
103 def PushFile(self, src_path, dest_path):
104 """Pushes local file to target Cloud Android instance.
105
106 Args:
107 src_path: string, local path to file to be pushed.
108 dest_path: string, path on target where to push the file to.
109
110 Raises:
111 subprocess.CalledProcessError: see _ShellCmd.
112 """
113 cmd = 'scp %s %s root@%s:%s' % (' '.join(SSH_FLAGS), src_path,
114 self._target_ip, dest_path)
115 self._ShellCmd(cmd)
116
117 def RebootTarget(self):
118 """Reboots the target Cloud Android instance and waits for boot.
119
120 Raises:
121 subprocess.CalledProcessError: see _ShellCmd.
Kevin Chengb5963882018-05-09 00:06:27 -0700122 errors.DeviceBootError: if target fails to boot.
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700123 """
124 self._ShellCmdOnTarget(REBOOT_CMD)
125 self._compute_client.WaitForBoot(self._instance_name)
126
127 def _ShellCmdOnTarget(self, target_cmd):
128 """Runs a shell command on target Cloud Android instance.
129
130 Args:
131 target_cmd: string, shell command to be run on target.
132
133 Raises:
134 subprocess.CalledProcessError: see _ShellCmd.
135 """
136 ssh_cmd = 'ssh %s root@%s' % (' '.join(SSH_FLAGS), self._target_ip)
137 host_cmd = ' '.join([ssh_cmd, '"%s"' % target_cmd])
138 self._ShellCmd(host_cmd)
139
cylan0d77ae12018-05-18 08:36:48 +0000140 @staticmethod
141 def _ShellCmd(host_cmd):
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700142 """Runs a shell command on host device.
143
144 Args:
145 host_cmd: string, shell command to be run on host.
146
147 Raises:
148 subprocess.CalledProcessError: For any non-zero return code of
149 host_cmd.
150 """
Fang Dengf24be082018-02-10 10:09:55 -0800151 utils.Retry(
cylan0d77ae12018-05-18 08:36:48 +0000152 retry_checker=
153 lambda e: isinstance(e, subprocess.CalledProcessError),
Fang Dengf24be082018-02-10 10:09:55 -0800154 max_retries=2,
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700155 functor=lambda cmd: subprocess.check_call(cmd, shell=True),
cylan0d77ae12018-05-18 08:36:48 +0000156 sleep_multiplier=0,
157 retry_backoff_factor=1,
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700158 cmd=host_cmd)