Lydia Fang | 01f2e85 | 2017-06-28 17:24:58 -0700 | [diff] [blame] | 1 | from unittest import main |
| 2 | from time import time, sleep |
| 3 | import simplejson, jsonschema |
| 4 | from google.protobuf.json_format import MessageToDict, \ |
| 5 | MessageToJson |
| 6 | from tests.itests.voltha.rest_base import RestBase |
| 7 | from common.utils.consulhelpers import get_endpoint_from_consul |
| 8 | from voltha.protos.device_pb2 import Device, ImageDownload |
| 9 | from voltha.protos.common_pb2 import AdminState |
| 10 | from google.protobuf.empty_pb2 import Empty |
| 11 | |
| 12 | LOCAL_CONSUL = "localhost:8500" |
| 13 | |
| 14 | class VolthaImageDownloadUpdate(RestBase): |
| 15 | # Retrieve details on the REST entry point |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame^] | 16 | rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'envoy-8443') |
Lydia Fang | 01f2e85 | 2017-06-28 17:24:58 -0700 | [diff] [blame] | 17 | |
| 18 | # Construct the base_url |
| 19 | base_url = 'https://' + rest_endpoint |
| 20 | |
| 21 | def wait_till(self, msg, predicate, interval=0.1, timeout=5.0): |
| 22 | deadline = time() + timeout |
| 23 | while time() < deadline: |
| 24 | if predicate(): |
| 25 | return |
| 26 | sleep(interval) |
| 27 | self.fail('Timed out while waiting for condition: {}'.format(msg)) |
| 28 | |
| 29 | def setUp(self): |
| 30 | # Make sure the Voltha REST interface is available |
| 31 | self.verify_rest() |
| 32 | # Create a new device |
| 33 | device = self.add_device() |
| 34 | # Activate the new device |
| 35 | self.activate_device(device['id']) |
| 36 | self.device_id = device['id'] |
| 37 | print("self.device_id {}".format(self.device_id)) |
| 38 | assert(self.device_id) |
| 39 | |
| 40 | # wait untill device moves to ACTIVE state |
| 41 | self.wait_till( |
| 42 | 'admin state moves from ACTIVATING to ACTIVE', |
| 43 | lambda: self.get('/api/v1/devices/{}'.format(self.device_id))\ |
| 44 | ['oper_status'] in ('ACTIVE'), |
| 45 | timeout=5.0) |
| 46 | # wait until ONUs are detected |
| 47 | sleep(2.0) |
| 48 | |
| 49 | def tearDown(self): |
| 50 | # Disable device |
| 51 | #self.disable_device(self.device_id) |
| 52 | # Delete device |
| 53 | #self.delete_device(self.device_id) |
| 54 | pass |
| 55 | |
| 56 | # test cases |
| 57 | |
| 58 | def test_voltha_global_download_image(self): |
| 59 | name = 'image-1' |
| 60 | self.request_download_image(name) |
| 61 | self.verify_request_download_image(name) |
| 62 | self.cancel_download_image(name) |
| 63 | self.verify_list_download_images(0) |
| 64 | |
| 65 | name = 'image-2' |
| 66 | self.request_download_image(name) |
| 67 | self.verify_request_download_image(name) |
| 68 | self.get_download_image_status(name) |
| 69 | self.verify_successful_download_image(name) |
| 70 | self.activate_image(name) |
| 71 | self.verify_activate_image(name) |
| 72 | self.revert_image(name) |
| 73 | self.verify_revert_image(name) |
| 74 | |
| 75 | name = 'image-3' |
| 76 | self.request_download_image(name) |
| 77 | self.verify_request_download_image(name) |
| 78 | self.verify_list_download_images(2) |
| 79 | |
| 80 | def verify_list_download_images(self, num_of_images): |
| 81 | path = '/api/v1/devices/{}/image_downloads' \ |
| 82 | .format(self.device_id) |
| 83 | res = self.get(path) |
| 84 | print(res['items']) |
| 85 | self.assertEqual(len(res['items']), num_of_images) |
| 86 | |
| 87 | def get_download_image(self, name): |
| 88 | path = '/api/v1/devices/{}/image_downloads/{}' \ |
| 89 | .format(self.device_id, name) |
| 90 | response = self.get(path) |
| 91 | print(response) |
| 92 | return response |
| 93 | |
| 94 | def request_download_image(self, name): |
| 95 | path = '/api/v1/devices/{}/image_downloads/{}' \ |
| 96 | .format(self.device_id, name) |
| 97 | url='http://[user@](hostname)[:port]/(dir)/(filename)' |
| 98 | request = ImageDownload(id=self.device_id, |
| 99 | name=name, |
| 100 | image_version="1.1.2", |
| 101 | url=url) |
| 102 | self.post(path, MessageToDict(request), |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame^] | 103 | expected_http_code=200) |
Lydia Fang | 01f2e85 | 2017-06-28 17:24:58 -0700 | [diff] [blame] | 104 | |
| 105 | def verify_request_download_image(self, name): |
| 106 | res = self.get_download_image(name) |
| 107 | self.assertEqual(res['state'], 'DOWNLOAD_REQUESTED') |
| 108 | self.assertEqual(res['image_state'], 'IMAGE_UNKNOWN') |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame^] | 109 | path = '/api/v1/devices/{}'.format(self.device_id) |
Lydia Fang | 01f2e85 | 2017-06-28 17:24:58 -0700 | [diff] [blame] | 110 | device = self.get(path) |
| 111 | self.assertEqual(device['admin_state'], 'DOWNLOADING_IMAGE') |
| 112 | |
| 113 | def cancel_download_image(self, name): |
| 114 | path = '/api/v1/devices/{}/image_downloads/{}' \ |
| 115 | .format(self.device_id, name) |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame^] | 116 | self.delete(path, expected_http_code=200) |
Lydia Fang | 01f2e85 | 2017-06-28 17:24:58 -0700 | [diff] [blame] | 117 | |
| 118 | def get_download_image_status(self, name): |
| 119 | path = '/api/v1/devices/{}/image_downloads/{}/status' \ |
| 120 | .format(self.device_id, name) |
| 121 | response = self.get(path) |
| 122 | while (response['state'] != 'DOWNLOAD_SUCCEEDED'): |
| 123 | response = self.get(path) |
| 124 | |
| 125 | def verify_successful_download_image(self, name): |
| 126 | res = self.get_download_image(name) |
| 127 | self.assertEqual(res['state'], 'DOWNLOAD_SUCCEEDED') |
| 128 | self.assertEqual(res['image_state'], 'IMAGE_UNKNOWN') |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame^] | 129 | path = '/api/v1/devices/{}'.format(self.device_id) |
Lydia Fang | 01f2e85 | 2017-06-28 17:24:58 -0700 | [diff] [blame] | 130 | device = self.get(path) |
| 131 | self.assertEqual(device['admin_state'], 'ENABLED') |
| 132 | |
| 133 | def activate_image(self, name): |
| 134 | path = '/api/v1/devices/{}/image_downloads/{}/image_update' \ |
| 135 | .format(self.device_id, name) |
| 136 | request = ImageDownload(id=self.device_id, |
| 137 | name=name, |
| 138 | save_config=True, |
| 139 | local_dir='/local/images/v.1.1.run') |
| 140 | self.post(path, MessageToDict(request), |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame^] | 141 | expected_http_code=200) |
Lydia Fang | 01f2e85 | 2017-06-28 17:24:58 -0700 | [diff] [blame] | 142 | |
| 143 | def verify_activate_image(self, name): |
| 144 | res = self.get_download_image(name) |
| 145 | self.assertEqual(res['image_state'], 'IMAGE_ACTIVE') |
| 146 | |
| 147 | def revert_image(self, name): |
| 148 | path = '/api/v1/devices/{}/image_downloads/{}/image_revert' \ |
| 149 | .format(self.device_id, name) |
| 150 | request = ImageDownload(id=self.device_id, |
| 151 | name=name, |
| 152 | save_config=True, |
| 153 | local_dir='/local/images/v.1.1.run') |
| 154 | self.post(path, MessageToDict(request), |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame^] | 155 | expected_http_code=200) |
Lydia Fang | 01f2e85 | 2017-06-28 17:24:58 -0700 | [diff] [blame] | 156 | |
| 157 | def verify_revert_image(self, name): |
| 158 | res = self.get_download_image(name) |
| 159 | self.assertEqual(res['image_state'], 'IMAGE_INACTIVE') |
| 160 | |
| 161 | |
| 162 | # test helpers |
| 163 | |
| 164 | def verify_rest(self): |
| 165 | self.get('/api/v1') |
| 166 | |
| 167 | # Create a new simulated device |
| 168 | def add_device(self): |
| 169 | device = Device( |
| 170 | type='simulated_olt', |
| 171 | ) |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame^] | 172 | device = self.post('/api/v1/devices', MessageToDict(device), |
| 173 | expected_http_code=200) |
Lydia Fang | 01f2e85 | 2017-06-28 17:24:58 -0700 | [diff] [blame] | 174 | return device |
| 175 | |
| 176 | # Active the simulated device. |
| 177 | def activate_device(self, device_id): |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame^] | 178 | path = '/api/v1/devices/{}'.format(device_id) |
| 179 | self.post(path + '/enable', expected_http_code=200) |
Lydia Fang | 01f2e85 | 2017-06-28 17:24:58 -0700 | [diff] [blame] | 180 | device = self.get(path) |
| 181 | self.assertEqual(device['admin_state'], 'ENABLED') |
| 182 | |
| 183 | # Disable the simulated device. |
| 184 | def disable_device(self, device_id): |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame^] | 185 | path = '/api/v1/devices/{}'.format(device_id) |
| 186 | self.post(path + '/disable', expected_http_code=200) |
Lydia Fang | 01f2e85 | 2017-06-28 17:24:58 -0700 | [diff] [blame] | 187 | device = self.get(path) |
| 188 | self.assertEqual(device['admin_state'], 'DISABLED') |
| 189 | |
| 190 | # Delete the simulated device |
| 191 | def delete_device(self, device_id): |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame^] | 192 | path = '/api/v1/devices/{}'.format(device_id) |
| 193 | self.delete(path + '/delete', expected_http_code=200) |
Lydia Fang | 01f2e85 | 2017-06-28 17:24:58 -0700 | [diff] [blame] | 194 | |
| 195 | if __name__ == '__main__': |
| 196 | main() |