From a7dad278bc8c5f19362f674922194f1c335a5d17 Mon Sep 17 00:00:00 2001
From: Megan Henning <meganhenning@flywheel.io>
Date: Wed, 26 Apr 2017 10:41:50 -0500
Subject: [PATCH] Move reaper upload, change uid upload logic

---
 api/api.py    |  8 ++++----
 api/placer.py | 19 +++++++++++++++++--
 api/upload.py |  3 +++
 3 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/api/api.py b/api/api.py
index c2ff13c2..227914dd 100644
--- a/api/api.py
+++ b/api/api.py
@@ -84,10 +84,10 @@ endpoints = [
 
         # General-purpose upload & download
 
-        route('/download',                              Download, h='download',              m=['GET', 'POST']),
-        route('/upload/<strategy:label|uid|uid-match>', Upload,   h='upload',                m=['POST']),
-        route('/clean-packfiles',                       Upload,   h='clean_packfile_tokens', m=['POST']),
-        route('/engine',                                Upload,   h='engine',                m=['POST']),
+        route('/download',                                      Download, h='download',              m=['GET', 'POST']),
+        route('/upload/<strategy:label|uid|uid-match|reaper>',  Upload,   h='upload',                m=['POST']),
+        route('/clean-packfiles',                               Upload,   h='clean_packfile_tokens', m=['POST']),
+        route('/engine',                                        Upload,   h='engine',                m=['POST']),
 
 
         # Top-level endpoints
diff --git a/api/placer.py b/api/placer.py
index 7b3bd666..8427fcc7 100644
--- a/api/placer.py
+++ b/api/placer.py
@@ -135,7 +135,8 @@ class UIDPlacer(Placer):
     Sessions and acquisitions are identified by UID.
     """
     metadata_schema = 'uidupload.json'
-    create_hierarchy = staticmethod(hierarchy.upsert_bottom_up_hierarchy)
+    create_hierarchy = staticmethod(hierarchy.upsert_top_down_hierarchy)
+    match_type = 'uid'
 
     def __init__(self, container_type, container, id_, metadata, timestamp, origin, context):
         super(UIDPlacer, self).__init__(container_type, container, id_, metadata, timestamp, origin, context)
@@ -151,7 +152,7 @@ class UIDPlacer(Placer):
         metadata_validator(self.metadata, 'POST')
 
         # If not a superuser request, pass uid of user making the upload request
-        targets = self.create_hierarchy(self.metadata, user=self.context.get('uid'), site=self.context.get('site'))
+        targets = self.create_hierarchy(self.metadata, type_=self.match_type, user=self.context.get('uid'), site=self.context.get('site'))
 
         self.metadata_for_file = {}
 
@@ -201,6 +202,18 @@ class UIDPlacer(Placer):
             self.recalc_session_compliance()
         return self.saved
 
+class ReaperUIDPlacer(UIDPlacer):
+    """
+    A placer that creates or matches based on UID.
+
+    Ignores project and group information if it finds session with matching UID.
+    Allows users to move sessions during scans without causing new data to be
+    created in referenced project/group.
+    """
+
+    metadata_schema = 'uidmatchupload.json'
+    create_hierarchy = staticmethod(hierarchy.hierarchy.upsert_bottom_up_hierarchy)
+    match_type = 'uid'
 
 class LabelPlacer(UIDPlacer):
     """
@@ -212,6 +225,7 @@ class LabelPlacer(UIDPlacer):
 
     metadata_schema = 'labelupload.json'
     create_hierarchy = staticmethod(hierarchy.upsert_top_down_hierarchy)
+    match_type = 'label'
 
 
 class UIDMatchPlacer(UIDPlacer):
@@ -221,6 +235,7 @@ class UIDMatchPlacer(UIDPlacer):
 
     metadata_schema = 'uidmatchupload.json'
     create_hierarchy = staticmethod(hierarchy.find_existing_hierarchy)
+    match_type = 'uid'
 
 
 class EnginePlacer(Placer):
diff --git a/api/upload.py b/api/upload.py
index 31370c3b..e05d4bee 100644
--- a/api/upload.py
+++ b/api/upload.py
@@ -21,6 +21,7 @@ Strategy = util.Enum('Strategy', {
     'labelupload' : pl.LabelPlacer,
     'uidupload'   : pl.UIDPlacer,
     'uidmatch'    : pl.UIDMatchPlacer,
+    'reaper'      : pl.UIDReaperPlacer,
     'analysis'    : pl.AnalysisPlacer,      # Upload N files to an analysis as input and output (no db updates)
     'analysis_job': pl.AnalysisJobPlacer   # Upload N files to an analysis as output from job results
 })
@@ -165,6 +166,8 @@ class Upload(base.RequestHandler):
             strategy = Strategy.uidupload
         elif strategy == 'uid-match':
             strategy = Strategy.uidmatch
+        elif strategy == 'reaper':
+            strategy = Strategy.reaper
         else:
             self.abort(500, 'stragegy {} not implemented'.format(strategy))
         return process_upload(self.request, strategy, origin=self.origin, context=context)
-- 
GitLab