blob: acebacaf95cb333b3b49bc6d7be7dbec07979911 [file] [log] [blame]
Mahir Gunyelfa6ea272020-06-10 17:03:51 -07001/*
2 * Copyright 2018-present Open Networking Foundation
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
17package device
18
19import (
20 "context"
Andrea Campanella025667e2021-01-14 11:50:07 +010021 "github.com/opencord/voltha-protos/v4/go/common"
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070022
23 "github.com/gogo/protobuf/proto"
24 "github.com/golang/protobuf/ptypes"
Maninderdfadc982020-10-28 14:04:33 +053025 "github.com/opencord/voltha-lib-go/v4/pkg/log"
26 "github.com/opencord/voltha-protos/v4/go/voltha"
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070027 "google.golang.org/grpc/codes"
28 "google.golang.org/grpc/status"
29)
30
Andrea Campanella025667e2021-01-14 11:50:07 +010031func (agent *Agent) downloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070032 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
33 return nil, err
34 }
Rohan Agrawal31f21802020-06-12 05:38:46 +000035 logger.Debugw(ctx, "downloadImage", log.Fields{"device-id": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070036
Andrea Campanella025667e2021-01-14 11:50:07 +010037 if agent.device.Root {
38 return nil, status.Errorf(codes.FailedPrecondition, "device-id:%s, is an OLT. Image update "+
39 "not supported by VOLTHA. Use Device Manager or other means", agent.deviceID)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070040 }
Andrea Campanella025667e2021-01-14 11:50:07 +010041
42 device := agent.cloneDeviceWithoutLock()
43 if device.ImageDownloads != nil {
44 for _, image := range device.ImageDownloads {
45 if image.DownloadState == voltha.ImageDownload_DOWNLOAD_REQUESTED {
46 return nil, status.Errorf(codes.FailedPrecondition, "device-id:%s, already downloading image:%s",
47 agent.deviceID, image.Name)
48 }
49 }
Kent Hagermanf6db9f12020-07-22 17:16:19 -040050 }
51
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070052 // Save the image
53 clonedImg := proto.Clone(img).(*voltha.ImageDownload)
54 clonedImg.DownloadState = voltha.ImageDownload_DOWNLOAD_REQUESTED
Kent Hagermanf6db9f12020-07-22 17:16:19 -040055 cloned := agent.cloneDeviceWithoutLock()
56 cloned.ImageDownloads = append(device.ImageDownloads, clonedImg)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070057
Kent Hagermanf6db9f12020-07-22 17:16:19 -040058 cloned.AdminState = voltha.AdminState_DOWNLOADING_IMAGE
59 if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
60 return nil, err
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070061 }
Kent Hagermanf6db9f12020-07-22 17:16:19 -040062
63 // Send the request to the adapter
Rohan Agrawalcf12f202020-08-03 04:42:01 +000064 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
Andrea Campanella025667e2021-01-14 11:50:07 +010065 ch, err := agent.adapterProxy.DownloadImage(subCtx, cloned, clonedImg)
Kent Hagermanf6db9f12020-07-22 17:16:19 -040066 if err != nil {
67 cancel()
68 return nil, err
69 }
Andrea Campanella025667e2021-01-14 11:50:07 +010070 go agent.waitForAdapterResponse(subCtx, cancel, "downloadImage", ch, agent.onImageSuccess, agent.onImageFailure)
Kent Hagermanf6db9f12020-07-22 17:16:19 -040071
Andrea Campanella025667e2021-01-14 11:50:07 +010072 return &common.OperationResp{Code: voltha.OperationResp_OPERATION_SUCCESS}, nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070073}
74
Andrea Campanella025667e2021-01-14 11:50:07 +010075// getImage is a helper method to figure out if an image is already registered
76func getImage(img *voltha.ImageDownload, device *voltha.Device) (*voltha.ImageDownload, int, error) {
77 for pos, image := range device.ImageDownloads {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070078 if image.Id == img.Id && image.Name == img.Name {
Andrea Campanella025667e2021-01-14 11:50:07 +010079 return image, pos, nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070080 }
81 }
Andrea Campanella025667e2021-01-14 11:50:07 +010082 return nil, -1, status.Errorf(codes.FailedPrecondition, "device-id:%s, image-not-registered:%s",
83 device.Id, img.Name)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070084}
85
Andrea Campanella025667e2021-01-14 11:50:07 +010086func (agent *Agent) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070087 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
88 return nil, err
89 }
Rohan Agrawal31f21802020-06-12 05:38:46 +000090 logger.Debugw(ctx, "cancelImageDownload", log.Fields{"device-id": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070091
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070092 // Update image download state
Kent Hagermanf6db9f12020-07-22 17:16:19 -040093 cloned := agent.cloneDeviceWithoutLock()
Andrea Campanella025667e2021-01-14 11:50:07 +010094 _, index, err := getImage(img, cloned)
95 if err != nil {
96 agent.requestQueue.RequestComplete()
97 return nil, err
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070098 }
99
Andrea Campanella025667e2021-01-14 11:50:07 +0100100 cloned.ImageDownloads[index].DownloadState = voltha.ImageDownload_DOWNLOAD_CANCELLED
101
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400102 if cloned.AdminState != voltha.AdminState_DOWNLOADING_IMAGE {
103 agent.requestQueue.RequestComplete()
104 } else {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700105 // Set the device to Enabled
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400106 cloned.AdminState = voltha.AdminState_ENABLED
107 if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700108 return nil, err
109 }
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000110 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400111 ch, err := agent.adapterProxy.CancelImageDownload(subCtx, cloned, img)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700112 if err != nil {
113 cancel()
114 return nil, err
115 }
Andrea Campanella025667e2021-01-14 11:50:07 +0100116 go agent.waitForAdapterResponse(subCtx, cancel, "cancelImageDownload", ch, agent.onImageSuccess,
117 agent.onImageFailure)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700118 }
119 return &voltha.OperationResp{Code: voltha.OperationResp_OPERATION_SUCCESS}, nil
120}
121
122func (agent *Agent) activateImage(ctx context.Context, img *voltha.ImageDownload) (*voltha.OperationResp, error) {
123 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
124 return nil, err
125 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000126 logger.Debugw(ctx, "activateImage", log.Fields{"device-id": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700127
Andrea Campanella025667e2021-01-14 11:50:07 +0100128 // Update image download state
129 cloned := agent.cloneDeviceWithoutLock()
130 image, index, err := getImage(img, cloned)
131 if err != nil {
132 agent.requestQueue.RequestComplete()
133 return nil, err
134 }
135
136 if err != nil {
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400137 agent.requestQueue.RequestComplete()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700138 return nil, status.Errorf(codes.FailedPrecondition, "device-id:%s, image-not-registered:%s", agent.deviceID, img.Name)
139 }
Andrea Campanella025667e2021-01-14 11:50:07 +0100140
141 if image.DownloadState != voltha.ImageDownload_DOWNLOAD_SUCCEEDED {
142 agent.requestQueue.RequestComplete()
143 return nil, status.Errorf(codes.FailedPrecondition, "device-id:%s, device-has-not-downloaded-image:%s", agent.deviceID, img.Name)
144 }
145
146 //TODO does this need to be removed ?
147 if cloned.AdminState == voltha.AdminState_DOWNLOADING_IMAGE {
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400148 agent.requestQueue.RequestComplete()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700149 return nil, status.Errorf(codes.FailedPrecondition, "device-id:%s, device-in-downloading-state:%s", agent.deviceID, img.Name)
150 }
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400151
Andrea Campanella025667e2021-01-14 11:50:07 +0100152 // Save the image
153 cloned.ImageDownloads[index].ImageState = voltha.ImageDownload_IMAGE_ACTIVATING
154
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400155 cloned.AdminState = voltha.AdminState_DOWNLOADING_IMAGE
156 if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700157 return nil, err
158 }
159
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000160 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400161 ch, err := agent.adapterProxy.ActivateImageUpdate(subCtx, cloned, img)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700162 if err != nil {
163 cancel()
164 return nil, err
165 }
Andrea Campanella025667e2021-01-14 11:50:07 +0100166 go agent.waitForAdapterResponse(subCtx, cancel, "activateImageUpdate", ch, agent.onImageSuccess, agent.onFailure)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700167
168 // The status of the AdminState will be changed following the update_download_status response from the adapter
169 // The image name will also be removed from the device list
170 return &voltha.OperationResp{Code: voltha.OperationResp_OPERATION_SUCCESS}, nil
171}
172
173func (agent *Agent) revertImage(ctx context.Context, img *voltha.ImageDownload) (*voltha.OperationResp, error) {
174 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
175 return nil, err
176 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000177 logger.Debugw(ctx, "revertImage", log.Fields{"device-id": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700178
Andrea Campanella025667e2021-01-14 11:50:07 +0100179 // Update image download state
180 cloned := agent.cloneDeviceWithoutLock()
181 _, index, err := getImage(img, cloned)
182 if err != nil {
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400183 agent.requestQueue.RequestComplete()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700184 return nil, status.Errorf(codes.FailedPrecondition, "deviceId:%s, image-not-registered:%s", agent.deviceID, img.Name)
185 }
Andrea Campanella025667e2021-01-14 11:50:07 +0100186 if cloned.AdminState != voltha.AdminState_ENABLED {
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400187 agent.requestQueue.RequestComplete()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700188 return nil, status.Errorf(codes.FailedPrecondition, "deviceId:%s, device-not-enabled-state:%s", agent.deviceID, img.Name)
189 }
Andrea Campanella025667e2021-01-14 11:50:07 +0100190
191 cloned.ImageDownloads[index].ImageState = voltha.ImageDownload_IMAGE_REVERTING
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700192
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400193 if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700194 return nil, err
195 }
196
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000197 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400198 ch, err := agent.adapterProxy.RevertImageUpdate(subCtx, cloned, img)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700199 if err != nil {
200 cancel()
201 return nil, err
202 }
203 go agent.waitForAdapterResponse(subCtx, cancel, "revertImageUpdate", ch, agent.onSuccess, agent.onFailure)
204
205 return &voltha.OperationResp{Code: voltha.OperationResp_OPERATION_SUCCESS}, nil
206}
207
208func (agent *Agent) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000209 logger.Debugw(ctx, "getImageDownloadStatus", log.Fields{"device-id": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700210
211 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
212 return nil, err
213 }
Kent Hagermancba2f302020-07-28 13:37:36 -0400214 device := agent.getDeviceReadOnlyWithoutLock()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700215 ch, err := agent.adapterProxy.GetImageDownloadStatus(ctx, device, img)
216 agent.requestQueue.RequestComplete()
217 if err != nil {
218 return nil, err
219 }
220 // Wait for the adapter response
221 rpcResponse, ok := <-ch
222 if !ok {
223 return nil, status.Errorf(codes.Aborted, "channel-closed-device-id-%s", agent.deviceID)
224 }
225 if rpcResponse.Err != nil {
226 return nil, rpcResponse.Err
227 }
228 // Successful response
229 imgDownload := &voltha.ImageDownload{}
230 if err := ptypes.UnmarshalAny(rpcResponse.Reply, imgDownload); err != nil {
231 return nil, status.Errorf(codes.InvalidArgument, "%s", err.Error())
232 }
233 return imgDownload, nil
234}
235
236func (agent *Agent) updateImageDownload(ctx context.Context, img *voltha.ImageDownload) error {
237 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
238 return err
239 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000240 logger.Debugw(ctx, "updating-image-download", log.Fields{"device-id": agent.deviceID, "img": img})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700241
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700242 // Update the image as well as remove it if the download was cancelled
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400243 cloned := agent.cloneDeviceWithoutLock()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700244 clonedImages := make([]*voltha.ImageDownload, len(cloned.ImageDownloads))
245 for _, image := range cloned.ImageDownloads {
246 if image.Id == img.Id && image.Name == img.Name {
247 if image.DownloadState != voltha.ImageDownload_DOWNLOAD_CANCELLED {
248 clonedImages = append(clonedImages, img)
249 }
250 }
251 }
252 cloned.ImageDownloads = clonedImages
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400253
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700254 // Set the Admin state to enabled if required
255 if (img.DownloadState != voltha.ImageDownload_DOWNLOAD_REQUESTED &&
256 img.DownloadState != voltha.ImageDownload_DOWNLOAD_STARTED) ||
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400257 img.ImageState != voltha.ImageDownload_IMAGE_ACTIVATING {
258 cloned.AdminState = voltha.AdminState_ENABLED
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700259 }
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400260 return agent.updateDeviceAndReleaseLock(ctx, cloned)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700261}
262
263func (agent *Agent) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000264 logger.Debugw(ctx, "getImageDownload", log.Fields{"device-id": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700265
Kent Hagermancba2f302020-07-28 13:37:36 -0400266 device, err := agent.getDeviceReadOnly(ctx)
267 if err != nil {
268 return nil, status.Errorf(codes.Aborted, "%s", err)
269 }
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400270 for _, image := range device.ImageDownloads {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700271 if image.Id == img.Id && image.Name == img.Name {
272 return image, nil
273 }
274 }
275 return nil, status.Errorf(codes.NotFound, "image-not-found:%s", img.Name)
276}
277
278func (agent *Agent) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000279 logger.Debugw(ctx, "listImageDownloads", log.Fields{"device-id": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700280
Kent Hagermancba2f302020-07-28 13:37:36 -0400281 device, err := agent.getDeviceReadOnly(ctx)
282 if err != nil {
283 return nil, status.Errorf(codes.Aborted, "%s", err)
284 }
285 return &voltha.ImageDownloads{Items: device.ImageDownloads}, nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700286}
Andrea Campanella025667e2021-01-14 11:50:07 +0100287
288// onImageFailure brings back the device to Enabled state and sets the image to image download_failed.
289func (agent *Agent) onImageFailure(ctx context.Context, rpc string, response interface{}, reqArgs ...interface{}) {
290 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
291 logger.Errorw(ctx, "can't obtain lock", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "error": err, "args": reqArgs})
292 return
293 }
294 if res, ok := response.(error); ok {
295 logger.Errorw(ctx, "rpc-failed", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "error": res, "args": reqArgs})
296 device := agent.cloneDeviceWithoutLock()
297 //TODO base this on IMAGE ID when created
298 var imageFailed *voltha.ImageDownload
299 var index int
300 if device.ImageDownloads != nil {
301 for pos, image := range device.ImageDownloads {
302 if image.DownloadState == voltha.ImageDownload_DOWNLOAD_REQUESTED ||
303 image.ImageState == voltha.ImageDownload_IMAGE_ACTIVATING {
304 imageFailed = image
305 index = pos
306 }
307 }
308 }
309
310 if imageFailed == nil {
311 logger.Errorw(ctx, "can't find image", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "args": reqArgs})
312 return
313 }
314
315 updatedImages := removeImage(device.ImageDownloads, index)
316
317 // Save the image
318 clonedImg := proto.Clone(imageFailed).(*voltha.ImageDownload)
319 if imageFailed.DownloadState == voltha.ImageDownload_DOWNLOAD_REQUESTED {
320 clonedImg.DownloadState = voltha.ImageDownload_DOWNLOAD_FAILED
321 } else if imageFailed.ImageState == voltha.ImageDownload_IMAGE_ACTIVATING {
322 clonedImg.ImageState = voltha.ImageDownload_IMAGE_INACTIVE
323 }
324 cloned := agent.cloneDeviceWithoutLock()
325 cloned.ImageDownloads = append(updatedImages, clonedImg)
326 //Enabled is the only state we can go back to.
327 cloned.AdminState = voltha.AdminState_ENABLED
328 if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
329 logger.Errorw(ctx, "failed-enable-device-after-image-failure",
330 log.Fields{"rpc": rpc, "device-id": agent.deviceID, "error": res, "args": reqArgs})
331 }
332 } else {
333 logger.Errorw(ctx, "rpc-failed-invalid-error", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "args": reqArgs})
334 }
335 // TODO: Post failure message onto kafka
336}
337
338// onImageSuccess brings back the device to Enabled state and sets the image to image download_failed.
339func (agent *Agent) onImageSuccess(ctx context.Context, rpc string, response interface{}, reqArgs ...interface{}) {
340 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
341 logger.Errorw(ctx, "can't obtain lock", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "error": err, "args": reqArgs})
342 return
343 }
344 logger.Errorw(ctx, "rpc-successful", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "response": response, "args": reqArgs})
345 device := agent.cloneDeviceWithoutLock()
346 //TODO base this on IMAGE ID when created
347 var imageSucceeded *voltha.ImageDownload
348 var index int
349 if device.ImageDownloads != nil {
350 for pos, image := range device.ImageDownloads {
351 if image.DownloadState == voltha.ImageDownload_DOWNLOAD_REQUESTED ||
352 image.ImageState == voltha.ImageDownload_IMAGE_ACTIVATING {
353 imageSucceeded = image
354 index = pos
355 }
356 }
357 }
358
359 if imageSucceeded == nil {
360 logger.Errorw(ctx, "can't find image", log.Fields{"rpc": rpc, "device-id": agent.deviceID, "args": reqArgs})
361 return
362 }
363
364 updatedImages := removeImage(device.ImageDownloads, index)
365
366 // Save the image
367 clonedImg := proto.Clone(imageSucceeded).(*voltha.ImageDownload)
368 if imageSucceeded.DownloadState == voltha.ImageDownload_DOWNLOAD_REQUESTED {
369 clonedImg.DownloadState = voltha.ImageDownload_DOWNLOAD_SUCCEEDED
370 } else if imageSucceeded.ImageState == voltha.ImageDownload_IMAGE_ACTIVATING {
371 clonedImg.ImageState = voltha.ImageDownload_IMAGE_ACTIVE
372
373 }
374 cloned := agent.cloneDeviceWithoutLock()
375 cloned.ImageDownloads = append(updatedImages, clonedImg)
376
377 //Enabled is the only state we can go back to.
378 cloned.AdminState = voltha.AdminState_ENABLED
379 if err := agent.updateDeviceAndReleaseLock(ctx, cloned); err != nil {
380 logger.Errorw(ctx, "failed-enable-device-after-image-download-success",
381 log.Fields{"rpc": rpc, "device-id": agent.deviceID, "response": response, "args": reqArgs})
382 }
383
384}
385
386func removeImage(s []*voltha.ImageDownload, i int) []*voltha.ImageDownload {
387 s[i] = s[len(s)-1]
388 // We do not need to put s[i] at the end, as it will be discarded anyway
389 return s[:len(s)-1]
390}