def validate_manifest_url(self, attrs, source): try: url = attrs[source] except KeyError: return attrs img = self.img try: req = HttpClient(url) res = req.get(timeout=5, max_size=8192) except RequestException as e: raise s.ValidationError( _('Image manifest URL is unreachable (%s).') % e) try: self.manifest = manifest = res.json() except ValueError: raise s.ValidationError(_('Could not parse image manifest.')) try: self.img_file = manifest['files'][0] img.uuid = manifest['uuid'] img.version = manifest['version'] img.ostype = Image.os_to_ostype(manifest) img.size = int(manifest.get('image_size', Image.DEFAULT_SIZE)) img.desc = manifest.get('description', '')[:128] tags = manifest.pop('tags', {}) img.tags = tags.get(Image.TAGS_KEY, []) img.deploy = tags.get('deploy', False) img.resize = tags.get('resize', img.ostype in img.ZONE) except Exception: raise s.ValidationError(_('Invalid image manifest.')) if len(manifest['files']) > 1: raise s.ValidationError( 'Multiple files inside manifest are not supported.') if img.uuid: try: x = Image.objects.only('name').get(uuid=img.uuid) except Image.DoesNotExist: pass else: raise s.ValidationError( _('Image UUID is already registered by image "%(name)s".') % {'name': x.name}) return attrs
def _update(cls, task_id, repo): err = res = images = None repo_url = repo.get_images_url() logger.info('Downloading images from image repository %s (%s)', repo.name, repo_url) try: curl = HttpClient(repo_url) res = curl.get(timeout=cls.HTTP_TIMEOUT, max_size=cls.HTTP_MAX_SIZE, allow_redirects=True) images = res.json() except RequestException as exc: err = '%s' % exc except ValueError as exc: err = 'Image server response could not be decoded (%s)' % exc else: if not isinstance(images, list): err = 'Unexpected output from image server (%s)' % type(images) if err: status = FAILURE msg = err logger.error(err) repo.error = err repo.save() else: status = SUCCESS img_count = len(images) msg = u'Downloaded metadata for %d images from image repository %s in %d μs' % ( img_count, repo.name, res.elapsed.microseconds) logger.info(msg) repo.image_count = img_count repo.last_update = timezone.now() repo.error = None repo.save(images=images) del images # The list can be big => remove from memory, we don't need it now task_log(task_id, LOG_IMAGE_STORE_UPDATE, obj=repo, task_status=status, detail=msg, update_user_tasks=False) return repo
def validate(self, attrs): self.img_manifest_url = attrs['manifest_url'] file_url = attrs.get('file_url', None) if not file_url: file_url = self.img_manifest_url.strip('/') + '/file' self.img_file_url = file_url try: req_file = HttpClient(file_url) req_file.get(timeout=5, max_size=32) except TooLarge: pass except RequestException as e: self._errors['file_url'] = s.ErrorList([_('Image file URL is unreachable (%s).') % e]) return attrs