def plugin_upload(self, request, *args, **kwargs): file = request.FILES.get('file') if file is not None: # Save to tmp dir tmp_zip_path = tempfile.mktemp('plugin.zip', dir=settings.MEDIA_TMP) tmp_extract_path = tempfile.mkdtemp('plugin', dir=settings.MEDIA_TMP) try: with open(tmp_zip_path, 'wb+') as fd: if isinstance(file, InMemoryUploadedFile): for chunk in file.chunks(): fd.write(chunk) else: with open(file.temporary_file_path(), 'rb') as f: shutil.copyfileobj(f, fd) # Extract with zipfile.ZipFile(tmp_zip_path, "r") as zip_h: zip_h.extractall(tmp_extract_path) # Validate folders = os.listdir(tmp_extract_path) if len(folders) != 1: raise ValueError( "The plugin has more than 1 root directory (it should have only one)" ) plugin_name = folders[0] plugin_path = os.path.join(tmp_extract_path, plugin_name) if not valid_plugin(plugin_path): raise ValueError( "This doesn't look like a plugin. Are plugin.py and manifest.json in the proper place?" ) if os.path.exists(get_plugins_persistent_path(plugin_name)): raise ValueError( "A plugin with the name {} already exist. Please remove it before uploading one with the same name." .format(plugin_name)) # Move shutil.move(plugin_path, get_plugins_persistent_path()) # Initialize clear_plugins_cache() init_plugins() messages.info(request, "Plugin added successfully") except Exception as e: messages.warning(request, "Cannot load plugin: {}".format(str(e))) if os.path.exists(tmp_zip_path): os.remove(tmp_zip_path) if os.path.exists(tmp_extract_path): shutil.rmtree(tmp_extract_path) else: messages.error(request, "You need to upload a zip file") return HttpResponseRedirect(reverse('admin:app_plugin_changelist'))
def boot(): # booted is a shared memory variable to keep track of boot status # as multiple gunicorn workers could trigger the boot sequence twice if (not settings.DEBUG and booted.value) or settings.MIGRATING: return booted.value = True logger = logging.getLogger('app.logger') logger.info("Booting WebODM {}".format(settings.VERSION)) if settings.DEBUG: logger.warning("Debug mode is ON (for development this is OK)") # Make sure our app/media/tmp folder exists if not os.path.exists(settings.MEDIA_TMP): os.makedirs(settings.MEDIA_TMP) # Check default group try: default_group, created = Group.objects.get_or_create(name='Default') if created: logger.info("Created default group") # Assign viewprocessing node object permission to default processing node (if present) # Otherwise non-root users will not be able to process try: pnode = ProcessingNode.objects.get(hostname="node-odm-1") assign_perm('view_processingnode', default_group, pnode) logger.info( "Added view_processingnode permissions to default group") except ObjectDoesNotExist: pass # Add default permissions (view_project, change_project, delete_project, etc.) for permission in ('_project', '_task', '_preset'): default_group.permissions.add( *list(Permission.objects.filter( codename__endswith=permission))) # Add permission to view processing nodes default_group.permissions.add( Permission.objects.get(codename="view_processingnode")) add_default_presets() # Add settings default_theme, created = Theme.objects.get_or_create(name='Default') if created: logger.info("Created default theme") if Setting.objects.all().count() == 0: default_logo = os.path.join('app', 'static', 'app', 'img', 'logo512.png') s = Setting.objects.create(app_name='WebODM', theme=default_theme) s.app_logo.save(os.path.basename(default_logo), File(open(default_logo, 'rb'))) logger.info("Created settings") init_plugins() if not settings.TESTING: try: worker_tasks.update_nodes_info.delay() except kombu.exceptions.OperationalError as e: logger.error( "Cannot connect to celery broker at {}. Make sure that your redis-server is running at that address: {}" .format(settings.CELERY_BROKER_URL, str(e))) except ProgrammingError: logger.warning( "Could not touch the database. If running a migration, this is expected." )