3 # Copyright 2016 RIFT.IO Inc
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
31 import tornado
.httputil
32 import tornadostreamform
.multipart_streamer
as multipart_streamer
36 # disable unsigned certificate warning
37 from requests
.packages
.urllib3
.exceptions
import InsecureRequestWarning
38 requests
.packages
.urllib3
.disable_warnings(InsecureRequestWarning
)
41 gi
.require_version('RwLaunchpadYang', '1.0')
42 gi
.require_version('ProjectNsdYang', '1.0')
43 gi
.require_version('ProjectVnfdYang', '1.0')
45 from gi
.repository
import (
46 ProjectNsdYang
as NsdYang
,
47 ProjectVnfdYang
as VnfdYang
,
49 import rift
.mano
.cloud
51 import rift
.package
.checksums
52 import rift
.package
.convert
53 import rift
.package
.handler
as pkg_handler
54 import rift
.package
.icon
55 import rift
.package
.package
56 import rift
.package
.script
57 import rift
.package
.store
59 from gi
.repository
import (
63 import rift
.downloader
as downloader
64 import rift
.mano
.dts
as mano_dts
76 from .message
import (
79 # Onboard Error Messages
80 OnboardChecksumMismatch
,
81 OnboardDescriptorError
,
82 OnboardDescriptorExistsError
,
83 OnboardDescriptorFormatError
,
85 OnboardExtractionError
,
86 OnboardImageUploadError
,
87 OnboardMissingContentBoundary
,
88 OnboardMissingContentType
,
89 OnboardMissingTerminalBoundary
,
90 OnboardUnreadableHeaders
,
91 OnboardUnreadablePackage
,
92 OnboardUnsupportedMediaType
,
94 # Onboard Status Messages
95 OnboardDescriptorOnboard
,
99 OnboardPackageValidation
,
106 # Update Error Messages
107 UpdateChecksumMismatch
,
108 UpdateDescriptorError
,
109 UpdateDescriptorFormatError
,
111 UpdateExtractionError
,
112 UpdateImageUploadError
,
113 UpdateMissingContentBoundary
,
114 UpdateMissingContentType
,
115 UpdatePackageNotFoundError
,
116 UpdateUnreadableHeaders
,
117 UpdateUnreadablePackage
,
118 UpdateUnsupportedMediaType
,
120 # Update Status Messages
121 UpdateDescriptorUpdate
,
122 UpdateDescriptorUpdated
,
129 from .tosca
import ExportTosca
131 from .onboard
import OnboardError
as OnboardException
136 MAX_STREAMED_SIZE
= 5 * GB
139 RPC_PACKAGE_CREATE_ENDPOINT
= RwPkgMgmtYang
.YangOutput_RwPkgMgmt_PackageCreate
140 RPC_PACKAGE_UPDATE_ENDPOINT
= RwPkgMgmtYang
.YangOutput_RwPkgMgmt_PackageUpdate
142 class HttpMessageError(Exception):
143 def __init__(self
, code
, msg
):
148 class UploadRpcHandler(mano_dts
.AbstractRpcHandler
):
149 def __init__(self
, application
):
152 application: UploaderApplication
154 super().__init
__(application
.log
, application
.dts
, application
.loop
)
155 self
.application
= application
159 return "/rw-pkg-mgmt:package-create"
162 def callback(self
, ks_path
, msg
):
163 transaction_id
= str(uuid
.uuid4())
164 log
= self
.application
.get_logger(transaction_id
)
165 log
.message(OnboardStart())
167 self
.log
.debug("Package create RPC: {}".format(msg
))
170 if msg
.username
is not None:
171 auth
= (msg
.username
, msg
.password
)
174 project
= msg
.project_name
175 except AttributeError as e
:
176 self
._log
.warning("Did not get project name in RPC: {}".
177 format(msg
.as_dict()))
178 project
= rift
.mano
.utils
.project
.DEFAULT_PROJECT
180 self
.application
.onboard(
187 rpc_op
= RPC_PACKAGE_CREATE_ENDPOINT
.from_dict({
188 "transaction_id": transaction_id
,
189 "project_name": project
,
195 class UpdateRpcHandler(mano_dts
.AbstractRpcHandler
):
196 def __init__(self
, application
):
199 application: UploaderApplication
201 super().__init
__(application
.log
, application
.dts
, application
.loop
)
202 self
.application
= application
206 return "/rw-pkg-mgmt:package-update"
209 def callback(self
, ks_path
, msg
):
211 transaction_id
= str(uuid
.uuid4())
212 log
= self
.application
.get_logger(transaction_id
)
213 log
.message(UpdateStart())
216 if msg
.username
is not None:
217 auth
= (msg
.username
, msg
.password
)
219 self
.application
.update(
223 project
=msg
.project_name
,
226 rpc_op
= RPC_PACKAGE_UPDATE_ENDPOINT
.from_dict({
227 "transaction_id": transaction_id
,
228 "project_name": msg
.project_name
,
234 class UploadStateHandler(state
.StateHandler
):
235 STARTED
= OnboardStart
236 SUCCESS
= OnboardSuccess
237 FAILURE
= OnboardFailure
240 class UpdateStateHandler(state
.StateHandler
):
241 STARTED
= UpdateStart
242 SUCCESS
= UpdateSuccess
243 FAILURE
= UpdateFailure
246 class UpdatePackage(downloader
.DownloaderProtocol
):
248 def __init__(self
, log
, loop
, project
, url
, auth
,
249 onboarder
, uploader
, package_store_map
, transaction_id
):
253 self
.project
= project
256 self
.onboarder
= onboarder
257 self
.uploader
= uploader
258 self
.package_store_map
= package_store_map
259 self
.transaction_id
= transaction_id
262 def _update_package(self
, packages
):
264 # Extract package could return multiple packages if
265 # the package is converted
267 with pkg
as temp_package
:
268 package_checksums
= self
.validate_package(temp_package
)
269 stored_package
= self
.update_package(temp_package
)
270 self
.validate_descriptor_fields(temp_package
)
273 self
.extract_icons(temp_package
)
274 self
.update_descriptors(temp_package
)
277 self
.delete_stored_package(stored_package
)
281 self
.upload_images(temp_package
, package_checksums
)
283 def extract(self
, packages
):
285 self
._update
_package
(packages
)
286 self
.log
.message(UpdateSuccess())
288 except MessageException
as e
:
289 self
.log
.message(e
.msg
)
290 self
.log
.message(UpdateFailure())
291 raise UpdateFailure(str(e
))
293 except Exception as e
:
294 self
.log
.exception(e
)
296 self
.log
.message(UpdateError(str(e
)))
297 self
.log
.message(UpdateFailure())
299 def on_download_succeeded(self
, job
):
300 self
.log
.message(DownloadSuccess("Package downloaded."))
302 extractor
= extract
.UploadPackageExtractor(self
.log
)
303 file_backed_packages
= extractor
.create_packages_from_upload(
304 job
.filename
, job
.filepath
307 self
.extract(file_backed_packages
)
308 except Exception as e
:
309 raise Exception("Error in Package Update")
311 def on_download_finished(self
, job
):
312 self
.log
.debug("*** Download completed")
313 if hasattr(self
.project
, 'update_status_handler'):
314 self
.project
.update_status_handler
.update_status(job
, self
.transaction_id
)
316 def on_download_progress(self
, job
):
317 self
.log
.debug("*** Download in progress")
318 if hasattr(self
.project
, 'update_status_handler'):
319 self
.project
.update_status_handler
.update_status(job
, self
.transaction_id
)
321 def on_download_failed(self
, job
):
322 self
.log
.error(job
.detail
)
323 self
.log
.message(DownloadError("Package download failed. {}".format(job
.detail
)))
324 self
.log
.message(UpdateFailure())
326 def download_package(self
):
328 _
, filename
= tempfile
.mkstemp()
329 url_downloader
= downloader
.UrlDownloader(
333 decompress_on_fly
=True,
335 url_downloader
.delegate
= self
336 url_downloader
.download()
338 def get_package_store(self
, package
):
339 return self
.package_store_map
[package
.descriptor_type
]
341 def update_package(self
, package
):
342 store
= self
.get_package_store(package
)
345 store
.update_package(package
)
346 except rift
.package
.store
.PackageNotFoundError
as e
:
347 # If the package doesn't exist, then it is possible the descriptor was onboarded
348 # out of band. In that case, just store the package as is
349 self
.log
.warning("Package not found, storing new package instead.")
350 store
.store_package(package
)
352 stored_package
= store
.get_package(package
.descriptor_id
)
354 return stored_package
356 def delete_stored_package(self
, package
):
357 self
.log
.info("Deleting stored package: %s", package
)
358 store
= self
.get_package_store(package
)
360 store
.delete_package(package
.descriptor_id
)
361 except Exception as e
:
362 self
.log
.warning("Failed to delete package from store: %s", str(e
))
364 def upload_images(self
, package
, package_checksums
):
365 image_file_map
= rift
.package
.image
.get_package_image_files(package
)
366 name_hdl_map
= {name
: package
.open(image_file_map
[name
]) for name
in image_file_map
}
367 if not image_file_map
:
371 for image_name
, image_hdl
in name_hdl_map
.items():
372 image_file
= image_file_map
[image_name
]
373 if image_file
in package_checksums
:
374 image_checksum
= package_checksums
[image_file
]
376 self
.log
.warning("checksum not provided for image %s. Calculating checksum",
378 image_checksum
= rift
.package
.checksums
.checksum(
379 package
.open(image_file_map
[image_name
])
382 self
.uploader
.upload_image(image_name
, image_checksum
, image_hdl
)
383 self
.uploader
.upload_image_to_cloud_accounts(image_name
, image_checksum
, self
.project
)
385 except image
.ImageUploadError
as e
:
386 self
.log
.exception("Failed to upload image: %s", image_name
)
387 raise MessageException(OnboardImageUploadError(str(e
))) from e
390 _
= [image_hdl
.close() for image_hdl
in name_hdl_map
.values()]
392 def extract_icons(self
, package
):
394 icon_extractor
= rift
.package
.icon
.PackageIconExtractor(self
.log
)
395 icon_extractor
.extract_icons(package
)
396 except rift
.package
.icon
.IconExtractionError
as e
:
397 raise MessageException(UpdateExtractionError()) from e
399 def validate_descriptor_fields(self
, package
):
400 # We can add more VNFD validations here. Currently we are validating only cloud-init
401 if package
.descriptor_msg
is not None:
402 self
.validate_cloud_init_file(package
)
404 def validate_cloud_init_file(self
, package
):
405 """ This validation is for VNFDs with associated VDUs. """
406 if 'vdu' in package
.descriptor_msg
.as_dict():
407 for vdu
in package
.descriptor_msg
.as_dict()['vdu']:
408 if 'cloud_init_file' in vdu
:
409 cloud_init_file
= vdu
['cloud_init_file']
410 for file in package
.files
:
411 if file.endswith('/' + cloud_init_file
) is True:
413 raise MessageException(
414 OnboardError("Cloud-Init file reference in VNFD does not match with cloud-init file"))
416 def validate_package(self
, package
):
417 checksum_validator
= rift
.package
.package
.PackageChecksumValidator(self
.log
)
420 checksum_validator
.validate(package
)
421 except rift
.package
.package
.PackageFileChecksumError
as e
:
422 raise MessageException(UpdateChecksumMismatch(e
.filename
)) from e
423 except rift
.package
.package
.PackageValidationError
as e
:
424 raise MessageException(UpdateUnreadablePackage()) from e
426 return checksum_validator
.checksums
428 def update_descriptors(self
, package
):
429 descriptor_msg
= package
.descriptor_msg
431 self
.log
.message(UpdateDescriptorUpdate())
434 self
.onboarder
.update(descriptor_msg
, project
=self
.project
.name
)
435 except onboard
.UpdateError
as e
:
436 raise MessageException(UpdateDescriptorError(package
.descriptor_file
)) from e
439 class OnboardPackage(downloader
.DownloaderProtocol
):
441 def __init__(self
, log
, loop
, project
, url
, auth
,
442 onboarder
, uploader
, package_store_map
, transaction_id
):
445 self
.project
= project
448 self
.onboarder
= onboarder
449 self
.uploader
= uploader
450 self
.package_store_map
= package_store_map
451 self
.transaction_id
= transaction_id
453 def _onboard_package(self
, packages
):
454 # Extract package could return multiple packages if
455 # the package is converted
457 with pkg
as temp_package
:
458 package_checksums
= self
.validate_package(temp_package
)
459 stored_package
= self
.store_package(temp_package
)
460 self
.validate_descriptor_fields(temp_package
)
463 self
.extract_icons(temp_package
)
464 self
.onboard_descriptors(temp_package
)
466 except Exception as e
:
467 if "data-exists" not in e
.msg
.text
:
468 self
.delete_stored_package(stored_package
)
471 self
.upload_images(temp_package
, package_checksums
)
473 def extract(self
, packages
):
475 self
._onboard
_package
(packages
)
476 self
.log
.message(OnboardSuccess())
478 except MessageException
as e
:
479 self
.log
.message(e
.msg
)
480 self
.log
.message(OnboardFailure())
481 raise OnboardException(OnboardFailure())
484 except Exception as e
:
485 self
.log
.exception(e
)
487 self
.log
.message(OnboardError(str(e
)))
488 self
.log
.message(OnboardFailure())
490 def on_download_succeeded(self
, job
):
491 self
.log
.message(DownloadSuccess("Package downloaded."))
493 extractor
= extract
.UploadPackageExtractor(self
.log
)
494 file_backed_packages
= extractor
.create_packages_from_upload(
495 job
.filename
, job
.filepath
498 self
.extract(file_backed_packages
)
499 except Exception as e
:
500 raise Exception("Error in Onboarding Package")
502 def on_download_finished(self
, job
):
503 self
.log
.debug("*** Download completed")
504 if hasattr(self
.project
, 'upload_status_handler'):
505 self
.project
.upload_status_handler
.upload_status(job
, self
.transaction_id
)
507 def on_download_progress(self
, job
):
508 self
.log
.debug("*** Download in progress")
509 if hasattr(self
.project
, 'upload_status_handler'):
510 self
.project
.upload_status_handler
.upload_status(job
, self
.transaction_id
)
512 def on_download_failed(self
, job
):
513 self
.log
.error(job
.detail
)
514 self
.log
.message(DownloadError("Package download failed. {}".format(job
.detail
)))
515 self
.log
.message(OnboardFailure())
517 def download_package(self
):
519 self
.log
.debug("Before pkg download, project = {}".format(self
.project
.name
))
520 _
, filename
= tempfile
.mkstemp()
521 url_downloader
= downloader
.UrlDownloader(
525 decompress_on_fly
=True,
527 url_downloader
.delegate
= self
528 url_downloader
.download()
530 def get_package_store(self
, package
):
531 return self
.package_store_map
[package
.descriptor_type
]
533 def store_package(self
, package
):
534 store
= self
.get_package_store(package
)
537 store
.store_package(package
)
538 except rift
.package
.store
.PackageExistsError
as e
:
539 store
.update_package(package
)
541 stored_package
= store
.get_package(package
.descriptor_id
)
543 return stored_package
545 def delete_stored_package(self
, package
):
546 self
.log
.info("Deleting stored package: %s", package
)
547 store
= self
.get_package_store(package
)
549 store
.delete_package(package
.descriptor_id
)
550 except Exception as e
:
551 self
.log
.warning("Failed to delete package from store: %s", str(e
))
553 def upload_images(self
, package
, package_checksums
):
554 image_file_map
= rift
.package
.image
.get_package_image_files(package
)
555 if not image_file_map
:
558 name_hdl_map
= {name
: package
.open(image_file_map
[name
]) for name
in image_file_map
}
560 for image_name
, image_hdl
in name_hdl_map
.items():
561 image_file
= image_file_map
[image_name
]
562 if image_file
in package_checksums
:
563 image_checksum
= package_checksums
[image_file
]
565 self
.log
.warning("checksum not provided for image %s. Calculating checksum",
567 image_checksum
= rift
.package
.checksums
.checksum(
568 package
.open(image_file_map
[image_name
])
571 set_image_property
= {}
572 self
.uploader
.upload_image(image_name
, image_checksum
, image_hdl
, set_image_property
)
573 self
.uploader
.upload_image_to_cloud_accounts(image_name
, image_checksum
, self
.project
.name
)
575 except image
.ImageUploadError
as e
:
576 raise MessageException(OnboardImageUploadError(str(e
))) from e
579 _
= [image_hdl
.close() for image_hdl
in name_hdl_map
.values()]
581 def extract_icons(self
, package
):
583 icon_extractor
= rift
.package
.icon
.PackageIconExtractor(self
.log
)
584 icon_extractor
.extract_icons(package
)
585 except rift
.package
.icon
.IconExtractionError
as e
:
586 raise MessageException(OnboardExtractionError()) from e
588 def validate_descriptor_fields(self
, package
):
589 # We can add more VNFD/NSD validations here.
590 if package
.descriptor_msg
is not None:
591 self
.validate_cloud_init_file(package
)
592 self
.validate_vld_mgmt_network(package
)
594 def validate_vld_mgmt_network(self
, package
):
595 """ This is validation at onboarding of NSD for atleast one of the VL's to have mgmt network true
596 and have minimum one connection point"""
597 if package
.descriptor_type
== 'nsd':
598 for vld
in package
.descriptor_msg
.as_dict().get('vld',[]):
599 if vld
.get('mgmt_network', False) is True and \
600 len(vld
.get('vnfd_connection_point_ref',[])) > 0 :
603 self
.log
.error(("AtLeast One of the VL's should have Management Network as True "
604 "and have minimum one connection point"))
606 def validate_cloud_init_file(self
, package
):
607 """ This validation is for VNFDs with associated VDUs. """
608 if 'vdu' in package
.descriptor_msg
.as_dict():
609 for vdu
in package
.descriptor_msg
.as_dict()['vdu']:
610 if 'cloud_init_file' in vdu
:
611 cloud_init_file
= vdu
['cloud_init_file']
612 for file in package
.files
:
613 if file.endswith('/' + cloud_init_file
) is True:
615 raise MessageException(
616 OnboardError("Cloud-Init file reference in VNFD does not match with cloud-init file"))
618 def validate_package(self
, package
):
620 rift
.package
.package
.PackageChecksumValidator(self
.log
),
621 rift
.package
.package
.PackageConstructValidator(self
.log
),
624 # Run the validators for checksum and package construction for imported pkgs
625 for validator
in validators
:
627 validator
.validate(package
)
629 except rift
.package
.package
.PackageFileChecksumError
as e
:
630 raise MessageException(OnboardChecksumMismatch(e
.filename
)) from e
631 except rift
.package
.package
.PackageValidationError
as e
:
632 raise MessageException(OnboardUnreadablePackage()) from e
634 return validators
[0].checksums
636 def onboard_descriptors(self
, package
):
637 def process_error_messsage(exception
, package
):
639 This method captures error reason. This needs to be enhanced with time.
641 exception_msg
= str(exception
)
642 match_duplicate
= re
.findall('<error-tag>(.*?)</error-tag>', exception_msg
, re
.DOTALL
)
644 if len(match_duplicate
) > 0:
645 error_message
= str(match_duplicate
[0])
648 match
= re
.findall('<tailf:missing-element>(.*?)</tailf:missing-element>', exception_msg
, re
.DOTALL
)
651 for element
in match
:
652 element_message
= "Missing element : {}".format(element
)
653 error_message
+= element_message
655 error_message
= package
.descriptor_file
658 def process_exception(exception
, package
):
659 return OnboardDescriptorError(process_error_messsage(exception
, package
))
661 descriptor_msg
= package
.descriptor_msg
662 self
.log
.message(OnboardDescriptorOnboard())
665 self
.onboarder
.onboard(descriptor_msg
, project
=self
.project
.name
)
666 except onboard
.OnboardError
as e
:
667 raise MessageException(process_exception(e
, package
)) from e
670 class UploaderApplication(tornado
.web
.Application
):
673 def from_tasklet(cls
, tasklet
):
674 manifest
= tasklet
.tasklet_info
.get_pb_manifest()
675 use_ssl
= manifest
.bootstrap_phase
.rwsecurity
.use_ssl
676 ssl_cert
= manifest
.bootstrap_phase
.rwsecurity
.cert
677 ssl_key
= manifest
.bootstrap_phase
.rwsecurity
.key
680 ssl
=(ssl_cert
, ssl_key
))
689 self
.log
= tasklet
.log
690 self
.loop
= tasklet
.loop
691 self
.dts
= tasklet
.dts
694 self
.ro_accounts
= {}
697 self
.ssl_cert
, self
.ssl_key
= None, None
700 self
.ssl_cert
, self
.ssl_key
= ssl
702 self
.messages
= collections
.defaultdict(list)
703 self
.export_dir
= os
.path
.join(os
.environ
['RIFT_VAR_ROOT'], 'launchpad/exports')
705 self
.uploader
= image
.ImageUploader(self
.log
, self
.loop
, self
.dts
)
706 self
.onboarder
= onboard
.DescriptorOnboarder(
707 self
.log
, "127.0.0.1", 8008, self
.use_ssl
, self
.ssl_cert
, self
.ssl_key
710 self
.exporter
= export
.DescriptorPackageArchiveExporter(self
.log
)
711 self
.loop
.create_task(export
.periodic_export_cleanup(self
.log
, self
.loop
, self
.export_dir
))
713 self
.tasklet
= tasklet
714 self
.get_vnfd_catalog
= tasklet
.get_vnfd_catalog
715 self
.get_nsd_catalog
= tasklet
.get_nsd_catalog
717 "vnfd": self
.get_vnfd_catalog
,
718 "nsd": self
.get_nsd_catalog
721 self
.upload_handler
= UploadRpcHandler(self
)
722 self
.update_handler
= UpdateRpcHandler(self
)
723 self
.export_handler
= export
.ExportRpcHandler(self
, catalog_map
)
725 attrs
= dict(log
=self
.log
, loop
=self
.loop
)
727 super(UploaderApplication
, self
).__init
__([
728 (r
"/api/package/vnfd/(.*)", pkg_handler
.FileRestApiHandler
, {
729 'path': rift
.package
.store
.VnfdPackageFilesystemStore
.DEFAULT_ROOT_DIR
}),
730 (r
"/api/package/nsd/(.*)", pkg_handler
.FileRestApiHandler
, {
731 'path': rift
.package
.store
.NsdPackageFilesystemStore
.DEFAULT_ROOT_DIR
}),
733 (r
"/api/upload/([^/]+)/state", UploadStateHandler
, attrs
),
734 (r
"/api/update/([^/]+)/state", UpdateStateHandler
, attrs
),
735 (r
"/api/export/([^/]+)/state", export
.ExportStateHandler
, attrs
),
737 (r
"/api/export/([^/]+.tar.gz)", tornado
.web
.StaticFileHandler
, {
738 "path": self
.export_dir
,
740 (r
"/api/export/([^/]+.zip)", tornado
.web
.StaticFileHandler
, {
741 "path": self
.export_dir
,
747 yield from self
.upload_handler
.register()
748 yield from self
.update_handler
.register()
749 yield from self
.export_handler
.register()
751 def get_logger(self
, transaction_id
):
752 return message
.Logger(self
.log
, self
.messages
[transaction_id
])
754 def build_store_map(self
, project
=None):
755 ''' Use project information to build vnfd/nsd filesystem stores with appropriate
756 package directory root.
758 vnfd_store
= rift
.package
.store
.VnfdPackageFilesystemStore(self
.log
) if not \
759 project
else rift
.package
.store
.VnfdPackageFilesystemStore(self
.log
, project
=project
)
760 nsd_store
= rift
.package
.store
.NsdPackageFilesystemStore(self
.log
) if not \
761 project
else rift
.package
.store
.NsdPackageFilesystemStore(self
.log
, project
=project
)
763 return dict(vnfd
= vnfd_store
, nsd
= nsd_store
)
765 def onboard(self
, url
, transaction_id
, auth
=None, project
=None):
766 log
= message
.Logger(self
.log
, self
.messages
[transaction_id
])
769 self
.project
= self
.tasklet
._get
_project
(project
)
770 except Exception as e
:
771 self
.log
.error("Exception raised ...%s" % (str(e
)))
772 self
.log
.exception(e
)
774 self
.package_store_map
= self
.build_store_map(project
)
775 onboard_package
= OnboardPackage(
783 self
.package_store_map
,
787 self
.loop
.run_in_executor(None, onboard_package
.download_package
)
789 def update(self
, url
, transaction_id
, auth
=None, project
=None):
790 log
= message
.Logger(self
.log
, self
.messages
[transaction_id
])
793 self
.project
= self
.tasklet
._get
_project
(project
)
794 except Exception as e
:
795 self
.log
.error("Exception raised ...%s" % (str(e
)))
796 self
.log
.exception(e
)
798 self
.package_store_map
= self
.build_store_map(project
)
799 update_package
= UpdatePackage(
807 self
.package_store_map
,
811 self
.loop
.run_in_executor(None, update_package
.download_package
)