0b4eac3a468bf128d86947e87f083115e7eae56e
[tools/litmus.git] / litmus / helper / helper.py
1 #!/usr/bin/env python3
2 # Copyright 2015-2016 Samsung Electronics Co., Ltd.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 import re
17 import sys
18 import time
19 import logging
20 import requests
21 import urllib.parse
22 from bs4 import BeautifulSoup
23 from litmus.core.util import find_pattern, find_all_pattern
24 from litmus.core.util import call
25
26
27 def tizen_snapshot_downloader(url, pattern_bin='tar.gz$',
28                               username='', password='',
29                               pattern_version='tizen[a-zA-Z0-9-_.^/]*[0-9]{8}.[0-9]{1,2}',
30                               version=None,
31                               timeout=10,
32                               maxretry=20,
33                               waiting_for_retry=10):
34     """
35     Download snapshot images from web server.
36
37     :param str url: url for downloading binaries. This has to include 'latest' string
38     :param str pattern_bin: filename pattern to find correct binary under the url
39     :param str username: username to access http server
40     :param str password: password to access http server
41     :param str pattern_version: pattern of tizen snapshot version string
42     :param str version: specific version string of tizen snapshot what you want to download
43     :param float timeout: timeout
44     :param int maxretry: max retry count to attempt the url for downloading
45     :param float waiting_for_retry: delay for each retry
46
47     Example:
48         >>> from litmus.helper.helper import tizen_snapshot_downloader
49         >>> tizen_snapshot_downloader(url=\'http://download.tizen.org/snapshots/tizen/tv/latest/images/arm-wayland/tv-wayland-armv7l-odroidu3/\')
50         [\'tizen-tv_20160516.2_tv-wayland-armv7l-odroidu3.tar.gz\']
51
52     :returns list: filenames of downloaded binaries
53
54     """
55     logging.debug('============Download binaries from server===========')
56     # convert latest url to actual url
57     url_to_find_latest_version_number = url.split('latest')[0]
58
59     for loop in range(maxretry):
60         try:
61             f = requests.get(url_to_find_latest_version_number,
62                              auth=(username, password), timeout=timeout)
63             if f.status_code == 200:
64                 break
65             time.sleep(waiting_for_retry)
66         except requests.exceptions.Timeout as e:
67             logging.debug(e)
68             continue
69         except requests.exceptions.ConnectionError as e:
70             logging.debug(e)
71             continue
72         except Exception as e:
73             logging.debug(e)
74             raise Exception('Can\'t open url {0}'.format(url))
75     else:
76         raise Exception('Can\'t open url {0}'.format(url))
77
78     latest_version = find_all_pattern(pattern_version, f.text)[-1]
79     url = url.replace('latest', latest_version)
80
81     if version:
82         pattern_version_number = '[0-9]{8}.[0-9]{1,2}'
83         found = find_pattern(pattern_version_number, url)
84         url = url.replace(found, version)
85
86     # get data from actual url and download binaries
87     for loop in range(maxretry):
88         try:
89             f = requests.get(url, auth=(username, password), timeout=timeout)
90             if f.status_code != 200:
91                 continue
92             soup = BeautifulSoup(f.text, 'html.parser')
93             filenames = []
94
95             for l in soup.findAll('a', attrs={'href': re.compile(pattern_bin)}):
96                 filename = l['href']
97                 fileurl = urllib.parse.urljoin(url, filename)
98                 logging.debug(fileurl)
99
100                 with open(filename, 'wb') as f:
101                     logging.debug('Downloading {}'.format(filename))
102                     resp = requests.get(fileurl,
103                                         auth=(username, password),
104                                         stream=True)
105
106                     total_length = resp.headers.get('Content-Length')
107
108                     if total_length is None:
109                         f.write(resp.content)
110                     else:
111                         downloaded_data = 0
112                         total_length = int(total_length)
113                         for download_data in resp.iter_content(chunk_size=1024 * 1024):
114                             downloaded_data += len(download_data)
115                             f.write(download_data)
116                             done = int(50 * downloaded_data / total_length)
117                             sys.stdout.write('\r[{0}{1}]'.format('#'*done,
118                                                                  ' '*(50-done)))
119                             sys.stdout.flush()
120                 logging.debug('')
121                 filenames.append(filename)
122
123             if filenames:
124                 break
125             else:
126                 logging.debug('There\'s no binary for downloading. Retry.')
127                 time.sleep(waiting_for_retry)
128
129         except requests.exceptions.Timeout as e:
130             logging.debug(e)
131             continue
132         except requests.exceptions.ConnectionError as e:
133             logging.debug(e)
134             continue
135         except Exception as e:
136             logging.debug(e)
137             raise Exception('Can\'t open url {0}'.format(url))
138     else:
139         raise Exception('Can\'t open url {0}'.format(url))
140
141     return filenames
142
143
144 def install_plugin(dut, script, waiting=5, timeout=180):
145     """
146     Install tizen plugins on device.
147     This helper function turn on device and turn off device automatically.
148
149     :param device dut: device instance
150     :param str script: script path to install plugins on device
151     :param float waiting: wait time before installing plugins
152     :param float timeout: timeout
153
154     Example:
155         >>> from litmus.helper.helper import install_plugin
156         >>> install_plugin(dut,
157                            script='install-set/setup')
158     """
159     logging.debug('================Install plugins=================')
160     dut.on()
161
162     script_path = '/'.join(script.split('/')[:-1])
163     script_name = script.split('/')[-1]
164
165     call('cp -R {0}/* .'.format(script_path), shell=True)
166
167     time.sleep(waiting)
168
169     call('sh {0} {1}'.format(script_name, dut.get_id()).split(),
170          timeout=timeout)
171
172     dut.off()
173
174
175 import tempfile
176 import shutil
177 from subprocess import DEVNULL
178
179 def install_plugin_from_git(dut, url, branch, script,
180                             waiting=5, timeout=180, commitid=None):
181     """
182     Clone a git project which include tizen plugins and install the plugins on device.
183     This helper function turn on device and turn off device automatically.
184
185     :param device dut: device instance
186     :param str url: url for git project
187     :param str branch: branch name of the git project
188     :param str script: script path to install plugins on device
189     :param float waiting: wait time before installing plugins
190     :param float timeout: timeout
191     :param str commitid: commitid which you want to clone
192
193     .. note:: You have to configure your open-ssh key if you want to use ssh protocol to clone the git project.
194
195     Example:
196         >>> from litmus.helper.helper import install_plugin_from_git
197         >>> install_plugin_from_git(dut,
198                                     url='ssh://{username}@localhost:29418/platform/adaptation/opengl-es-mali-t628'
199                                     branch='tizen_3.0'
200                                     script='install-set/setup')
201
202
203     """
204     logging.debug('=============Install plugins from git===============')
205     logging.debug('plugin git path : {}'.format(url))
206     logging.debug('plugin git branch : {}'.format(branch))
207     logging.debug('plugin git commitid : {}'
208                   .format(commitid if commitid else 'latest'))
209     logging.debug('plugin install script : {}'.format(script))
210     dut.on()
211
212     tmpdir = next(tempfile._get_candidate_names())
213
214     call('git clone {0} {1} --branch {2}'.format(url, tmpdir, branch),
215          shell=True)
216
217     if commitid:
218         call('git --git-dir={0}/.git checkout {1}'.format(tmpdir, commitid),
219              shell=True)
220
221     call('find ./{0} -exec perl -pi -e "s/sdb\s+(-d\s+)*(root|shell|push|pull)/sdb -s {1} \\2/g" {{}} \;'.format(tmpdir, dut.get_id()), stderr=DEVNULL, shell=True)
222     call('find ./{0} -exec perl -pi -e "s/sdb\s+.*reboot.*//g" {{}} \;'.format(tmpdir), stderr=DEVNULL, shell=True)
223
224     script_path = '/'.join(script.split('/')[:-1])
225     script_name = script.split('/')[-1]
226
227     time.sleep(waiting)
228
229     call('cd {0}/{1} && sh {2}'.format(tmpdir, script_path, script_name),
230          shell=True, timeout=timeout)
231     shutil.rmtree(tmpdir)
232
233     dut.off()