We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Recipe validation fails
When trying to submit a recipe over turbiniactl, the recipe validation fails:

turbiniactl -P ./temp/recipe.yaml googleclouddisk -d disk-name

2021-11-19 09:48:04 [INFO] Turbinia version: 20211018
2021-11-19 09:48:16 [INFO] Disabling non-allowlisted jobs configured to be disabled in the config file: binaryextractorjob, bulkextractorjob, dfdeweyjob, hindsightjob, photorecjob, jenkinsanalysisjob, volatilityjob
2021-11-19 09:48:16 [INFO] Loading recipe file from ./temp/recipe.yaml
Traceback (most recent call last):
  File "/usr/local/bin/turbiniactl", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.9/site-packages/turbinia/turbiniactl.py", line 824, in main
    recipe_dict = recipe_helpers.load_recipe_from_file(
  File "/usr/local/lib/python3.9/site-packages/turbinia/lib/recipe_helpers.py", line 60, in load_recipe_from_file
    success, _ = validate_recipe(recipe_dict)
  File "/usr/local/lib/python3.9/site-packages/turbinia/lib/recipe_helpers.py", line 161, in validate_recipe
    if not task_loader.check_task_name(proposed_task):
  File "/usr/local/lib/python3.9/site-packages/turbinia/task_utils.py", line 82, in check_task_name
    for task in TASK_LIST:
NameError: name 'TASK_LIST' is not defined

Bug is also present in master branch, this should be "self.TASK_LIST":

https://github.com/google/turbinia/blob/54c2a03566422efffcc93197661d6e5da319e591/turbinia/task_utils.py#L82

Would send a PR myself, but still getting approvals to contribute :) 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `turbinia/task_utils.py`
Content:
```
1 #-*- coding: utf-8 -*-
2 # Copyright 2021 Google Inc.
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 """Task runner for Turbinia."""
16 
17 from datetime import datetime
18 import logging
19 import os
20 import sys
21 
22 import filelock
23 
24 import turbinia
25 from turbinia import config
26 from turbinia.config import DATETIME_FORMAT
27 from turbinia import TurbiniaException
28 
29 log = logging.getLogger('turbinia')
30 
31 config.LoadConfig()
32 
33 
34 class TaskLoader():
35   """Utility class for handling Task loading/checking/deserialization.
36 
37   Attributes:
38     TASK_LIST(list): A list of all valid Tasks.
39   """
40 
41   TASK_LIST = [
42       'FileArtifactExtractionTask',
43       'WordpressAccessLogAnalysisTask',
44       'WordpressCredsAnalysisTask',
45       'FinalizeRequestTask',
46       'JenkinsAnalysisTask',
47       'JupyterAnalysisTask',
48       'GrepTask',
49       'FsstatTask',
50       'HadoopAnalysisTask',
51       'HindsightTask',
52       'LinuxAccountAnalysisTask',
53       'WindowsAccountAnalysisTask',
54       'LokiAnalysisTask',
55       'PartitionEnumerationTask',
56       'PlasoTask',
57       'PsortTask',
58       'RedisAnalysisTask',
59       'SSHDAnalysisTask',
60       'StringsAsciiTask',
61       'StringsUnicodeTask',
62       'TomcatAnalysisTask',
63       'VolatilityTask',
64       'StatTask',
65       'BinaryExtractorTask',
66       'BulkExtractorTask',
67       'DockerContainersEnumerationTask',
68       'PhotorecTask',
69       'AbortTask',
70       'CronAnalysisTask',
71   ]
72 
73   def check_task_name(self, task_name):
74     """Checks whether a given task name is a valid task
75     
76     Args:
77       task_name(str): Name of the Task to check.
78       
79     Returns:
80       bool: True if task with the given name exists, else False
81     """
82     for task in TASK_LIST:
83       if task.lower() == task_name.lower():
84         return True
85     return False
86 
87   def get_task(self, task_name):
88     """Gets an instantiated Task object for the given name.
89     
90     Args:
91       task_name(str): Name of the Task to return.
92       
93     Returns:
94       TurbiniaTask: An instantiated Task object.
95     """
96     # TODO(aarontp): Remove this list after
97     # https://github.com/google/turbinia/issues/278 is fixed.
98     #
99     # Late imports to minimize what loads all Tasks
100     from turbinia.workers.artifact import FileArtifactExtractionTask
101     from turbinia.workers.analysis.wordpress_access import WordpressAccessLogAnalysisTask
102     from turbinia.workers.analysis.wordpress_creds import WordpressCredsAnalysisTask
103     from turbinia.workers.analysis.jenkins import JenkinsAnalysisTask
104     from turbinia.workers.analysis.jupyter import JupyterAnalysisTask
105     from turbinia.workers.analysis.linux_acct import LinuxAccountAnalysisTask
106     from turbinia.workers.analysis.loki import LokiAnalysisTask
107     from turbinia.workers.analysis.windows_acct import WindowsAccountAnalysisTask
108     from turbinia.workers.finalize_request import FinalizeRequestTask
109     from turbinia.workers.cron import CronAnalysisTask
110     from turbinia.workers.docker import DockerContainersEnumerationTask
111     from turbinia.workers.grep import GrepTask
112     from turbinia.workers.fsstat import FsstatTask
113     from turbinia.workers.hadoop import HadoopAnalysisTask
114     from turbinia.workers.hindsight import HindsightTask
115     from turbinia.workers.partitions import PartitionEnumerationTask
116     from turbinia.workers.plaso import PlasoTask
117     from turbinia.workers.psort import PsortTask
118     from turbinia.workers.redis import RedisAnalysisTask
119     from turbinia.workers.sshd import SSHDAnalysisTask
120     from turbinia.workers.strings import StringsAsciiTask
121     from turbinia.workers.strings import StringsUnicodeTask
122     from turbinia.workers.tomcat import TomcatAnalysisTask
123     from turbinia.workers.volatility import VolatilityTask
124     from turbinia.workers.worker_stat import StatTask
125     from turbinia.workers.binary_extractor import BinaryExtractorTask
126     from turbinia.workers.bulk_extractor import BulkExtractorTask
127     from turbinia.workers.photorec import PhotorecTask
128     from turbinia.workers.abort import AbortTask
129 
130     for task in self.TASK_LIST:
131       if task.lower() == task_name.lower():
132         try:
133           task_obj = locals()[task]
134           return task_obj()
135         except (AttributeError, KeyError):
136           message = (
137               "Could not import {0:s} object! Make sure it is imported where "
138               "this method is defined.".format(task_name))
139           log.error(message)
140           raise TurbiniaException(message)
141 
142     return
143 
144   def get_task_names(self):
145     """Returns a list of Task names.
146     
147     Returns:
148       (list) All Task names.
149     """
150     return self.TASK_LIST
151 
152 
153 def task_deserialize(input_dict):
154   """Converts an input dictionary back into a TurbiniaTask object.
155 
156   Args:
157     input_dict (dict): TurbiniaTask object dictionary.
158 
159   Returns:
160     TurbiniaTask: Deserialized object.
161   """
162 
163   type_ = input_dict['name']
164   task_loader = TaskLoader()
165   task = task_loader.get_task(type_)
166   if not task:
167     raise TurbiniaException('Could not load Task module {0:s}'.format(type_))
168   # Remove serialized output manager because this gets reinstantiated when the
169   # empty Task is instantiated and we don't want to overwrite it.
170   input_dict.pop('output_manager')
171   task.__dict__.update(input_dict)
172   task.last_update = datetime.strptime(
173       input_dict['last_update'], DATETIME_FORMAT)
174   return task
175 
176 
177 def task_runner(obj, *args, **kwargs):
178   """Wrapper function to run specified TurbiniaTask object.
179 
180   Args:
181     obj: An instantiated TurbiniaTask object.
182     *args: Any Args to pass to obj.
183     **kwargs: Any keyword args to pass to obj.
184 
185   Returns:
186     Output from TurbiniaTask (should be TurbiniaTaskResult).
187   """
188 
189   # GKE Specific - do not queue more work if pod places this file
190   if config.TASK_MANAGER.lower() == 'psq':
191     if os.path.exists(config.SCALEDOWN_WORKER_FILE):
192       # Late import because this is only needed for PSQ
193       import psq
194       raise psq.Retry()
195 
196   # Try to acquire lock, timeout and requeue task if the worker
197   # is already processing a task.
198   try:
199     lock = filelock.FileLock(config.LOCK_FILE)
200     with lock.acquire(timeout=0.001):
201       obj = task_deserialize(obj)
202       run = obj.run_wrapper(*args, **kwargs)
203   except filelock.Timeout:
204     if config.TASK_MANAGER.lower() == 'psq':
205       # Late import because this is only needed for PSQ
206       import psq
207       raise psq.Retry()
208   # *Always* make sure we release the lock
209   finally:
210     lock.release()
211 
212   return run
213
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/turbinia/task_utils.py b/turbinia/task_utils.py
--- a/turbinia/task_utils.py
+++ b/turbinia/task_utils.py
@@ -79,7 +79,7 @@
     Returns:
       bool: True if task with the given name exists, else False
     """
-    for task in TASK_LIST:
+    for task in self.TASK_LIST:
       if task.lower() == task_name.lower():
         return True
     return False

{"golden_diff": "diff --git a/turbinia/task_utils.py b/turbinia/task_utils.py\n--- a/turbinia/task_utils.py\n+++ b/turbinia/task_utils.py\n@@ -79,7 +79,7 @@\n     Returns:\n       bool: True if task with the given name exists, else False\n     \"\"\"\n-    for task in TASK_LIST:\n+    for task in self.TASK_LIST:\n       if task.lower() == task_name.lower():\n         return True\n     return False\n", "issue": "Recipe validation fails\nWhen trying to submit a recipe over turbiniactl, the recipe validation fails:\r\n\r\nturbiniactl -P ./temp/recipe.yaml googleclouddisk -d disk-name\r\n\r\n2021-11-19 09:48:04 [INFO] Turbinia version: 20211018\r\n2021-11-19 09:48:16 [INFO] Disabling non-allowlisted jobs configured to be disabled in the config file: binaryextractorjob, bulkextractorjob, dfdeweyjob, hindsightjob, photorecjob, jenkinsanalysisjob, volatilityjob\r\n2021-11-19 09:48:16 [INFO] Loading recipe file from ./temp/recipe.yaml\r\nTraceback (most recent call last):\r\n  File \"/usr/local/bin/turbiniactl\", line 8, in <module>\r\n    sys.exit(main())\r\n  File \"/usr/local/lib/python3.9/site-packages/turbinia/turbiniactl.py\", line 824, in main\r\n    recipe_dict = recipe_helpers.load_recipe_from_file(\r\n  File \"/usr/local/lib/python3.9/site-packages/turbinia/lib/recipe_helpers.py\", line 60, in load_recipe_from_file\r\n    success, _ = validate_recipe(recipe_dict)\r\n  File \"/usr/local/lib/python3.9/site-packages/turbinia/lib/recipe_helpers.py\", line 161, in validate_recipe\r\n    if not task_loader.check_task_name(proposed_task):\r\n  File \"/usr/local/lib/python3.9/site-packages/turbinia/task_utils.py\", line 82, in check_task_name\r\n    for task in TASK_LIST:\r\nNameError: name 'TASK_LIST' is not defined\r\n\r\nBug is also present in master branch, this should be \"self.TASK_LIST\":\r\n\r\nhttps://github.com/google/turbinia/blob/54c2a03566422efffcc93197661d6e5da319e591/turbinia/task_utils.py#L82\r\n\r\nWould send a PR myself, but still getting approvals to contribute :) \n", "before_files": [{"content": "#-*- coding: utf-8 -*-\n# Copyright 2021 Google Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Task runner for Turbinia.\"\"\"\n\nfrom datetime import datetime\nimport logging\nimport os\nimport sys\n\nimport filelock\n\nimport turbinia\nfrom turbinia import config\nfrom turbinia.config import DATETIME_FORMAT\nfrom turbinia import TurbiniaException\n\nlog = logging.getLogger('turbinia')\n\nconfig.LoadConfig()\n\n\nclass TaskLoader():\n  \"\"\"Utility class for handling Task loading/checking/deserialization.\n\n  Attributes:\n    TASK_LIST(list): A list of all valid Tasks.\n  \"\"\"\n\n  TASK_LIST = [\n      'FileArtifactExtractionTask',\n      'WordpressAccessLogAnalysisTask',\n      'WordpressCredsAnalysisTask',\n      'FinalizeRequestTask',\n      'JenkinsAnalysisTask',\n      'JupyterAnalysisTask',\n      'GrepTask',\n      'FsstatTask',\n      'HadoopAnalysisTask',\n      'HindsightTask',\n      'LinuxAccountAnalysisTask',\n      'WindowsAccountAnalysisTask',\n      'LokiAnalysisTask',\n      'PartitionEnumerationTask',\n      'PlasoTask',\n      'PsortTask',\n      'RedisAnalysisTask',\n      'SSHDAnalysisTask',\n      'StringsAsciiTask',\n      'StringsUnicodeTask',\n      'TomcatAnalysisTask',\n      'VolatilityTask',\n      'StatTask',\n      'BinaryExtractorTask',\n      'BulkExtractorTask',\n      'DockerContainersEnumerationTask',\n      'PhotorecTask',\n      'AbortTask',\n      'CronAnalysisTask',\n  ]\n\n  def check_task_name(self, task_name):\n    \"\"\"Checks whether a given task name is a valid task\n    \n    Args:\n      task_name(str): Name of the Task to check.\n      \n    Returns:\n      bool: True if task with the given name exists, else False\n    \"\"\"\n    for task in TASK_LIST:\n      if task.lower() == task_name.lower():\n        return True\n    return False\n\n  def get_task(self, task_name):\n    \"\"\"Gets an instantiated Task object for the given name.\n    \n    Args:\n      task_name(str): Name of the Task to return.\n      \n    Returns:\n      TurbiniaTask: An instantiated Task object.\n    \"\"\"\n    # TODO(aarontp): Remove this list after\n    # https://github.com/google/turbinia/issues/278 is fixed.\n    #\n    # Late imports to minimize what loads all Tasks\n    from turbinia.workers.artifact import FileArtifactExtractionTask\n    from turbinia.workers.analysis.wordpress_access import WordpressAccessLogAnalysisTask\n    from turbinia.workers.analysis.wordpress_creds import WordpressCredsAnalysisTask\n    from turbinia.workers.analysis.jenkins import JenkinsAnalysisTask\n    from turbinia.workers.analysis.jupyter import JupyterAnalysisTask\n    from turbinia.workers.analysis.linux_acct import LinuxAccountAnalysisTask\n    from turbinia.workers.analysis.loki import LokiAnalysisTask\n    from turbinia.workers.analysis.windows_acct import WindowsAccountAnalysisTask\n    from turbinia.workers.finalize_request import FinalizeRequestTask\n    from turbinia.workers.cron import CronAnalysisTask\n    from turbinia.workers.docker import DockerContainersEnumerationTask\n    from turbinia.workers.grep import GrepTask\n    from turbinia.workers.fsstat import FsstatTask\n    from turbinia.workers.hadoop import HadoopAnalysisTask\n    from turbinia.workers.hindsight import HindsightTask\n    from turbinia.workers.partitions import PartitionEnumerationTask\n    from turbinia.workers.plaso import PlasoTask\n    from turbinia.workers.psort import PsortTask\n    from turbinia.workers.redis import RedisAnalysisTask\n    from turbinia.workers.sshd import SSHDAnalysisTask\n    from turbinia.workers.strings import StringsAsciiTask\n    from turbinia.workers.strings import StringsUnicodeTask\n    from turbinia.workers.tomcat import TomcatAnalysisTask\n    from turbinia.workers.volatility import VolatilityTask\n    from turbinia.workers.worker_stat import StatTask\n    from turbinia.workers.binary_extractor import BinaryExtractorTask\n    from turbinia.workers.bulk_extractor import BulkExtractorTask\n    from turbinia.workers.photorec import PhotorecTask\n    from turbinia.workers.abort import AbortTask\n\n    for task in self.TASK_LIST:\n      if task.lower() == task_name.lower():\n        try:\n          task_obj = locals()[task]\n          return task_obj()\n        except (AttributeError, KeyError):\n          message = (\n              \"Could not import {0:s} object! Make sure it is imported where \"\n              \"this method is defined.\".format(task_name))\n          log.error(message)\n          raise TurbiniaException(message)\n\n    return\n\n  def get_task_names(self):\n    \"\"\"Returns a list of Task names.\n    \n    Returns:\n      (list) All Task names.\n    \"\"\"\n    return self.TASK_LIST\n\n\ndef task_deserialize(input_dict):\n  \"\"\"Converts an input dictionary back into a TurbiniaTask object.\n\n  Args:\n    input_dict (dict): TurbiniaTask object dictionary.\n\n  Returns:\n    TurbiniaTask: Deserialized object.\n  \"\"\"\n\n  type_ = input_dict['name']\n  task_loader = TaskLoader()\n  task = task_loader.get_task(type_)\n  if not task:\n    raise TurbiniaException('Could not load Task module {0:s}'.format(type_))\n  # Remove serialized output manager because this gets reinstantiated when the\n  # empty Task is instantiated and we don't want to overwrite it.\n  input_dict.pop('output_manager')\n  task.__dict__.update(input_dict)\n  task.last_update = datetime.strptime(\n      input_dict['last_update'], DATETIME_FORMAT)\n  return task\n\n\ndef task_runner(obj, *args, **kwargs):\n  \"\"\"Wrapper function to run specified TurbiniaTask object.\n\n  Args:\n    obj: An instantiated TurbiniaTask object.\n    *args: Any Args to pass to obj.\n    **kwargs: Any keyword args to pass to obj.\n\n  Returns:\n    Output from TurbiniaTask (should be TurbiniaTaskResult).\n  \"\"\"\n\n  # GKE Specific - do not queue more work if pod places this file\n  if config.TASK_MANAGER.lower() == 'psq':\n    if os.path.exists(config.SCALEDOWN_WORKER_FILE):\n      # Late import because this is only needed for PSQ\n      import psq\n      raise psq.Retry()\n\n  # Try to acquire lock, timeout and requeue task if the worker\n  # is already processing a task.\n  try:\n    lock = filelock.FileLock(config.LOCK_FILE)\n    with lock.acquire(timeout=0.001):\n      obj = task_deserialize(obj)\n      run = obj.run_wrapper(*args, **kwargs)\n  except filelock.Timeout:\n    if config.TASK_MANAGER.lower() == 'psq':\n      # Late import because this is only needed for PSQ\n      import psq\n      raise psq.Retry()\n  # *Always* make sure we release the lock\n  finally:\n    lock.release()\n\n  return run\n", "path": "turbinia/task_utils.py"}], "after_files": [{"content": "#-*- coding: utf-8 -*-\n# Copyright 2021 Google Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Task runner for Turbinia.\"\"\"\n\nfrom datetime import datetime\nimport logging\nimport os\nimport sys\n\nimport filelock\n\nimport turbinia\nfrom turbinia import config\nfrom turbinia.config import DATETIME_FORMAT\nfrom turbinia import TurbiniaException\n\nlog = logging.getLogger('turbinia')\n\nconfig.LoadConfig()\n\n\nclass TaskLoader():\n  \"\"\"Utility class for handling Task loading/checking/deserialization.\n\n  Attributes:\n    TASK_LIST(list): A list of all valid Tasks.\n  \"\"\"\n\n  TASK_LIST = [\n      'FileArtifactExtractionTask',\n      'WordpressAccessLogAnalysisTask',\n      'WordpressCredsAnalysisTask',\n      'FinalizeRequestTask',\n      'JenkinsAnalysisTask',\n      'JupyterAnalysisTask',\n      'GrepTask',\n      'FsstatTask',\n      'HadoopAnalysisTask',\n      'HindsightTask',\n      'LinuxAccountAnalysisTask',\n      'WindowsAccountAnalysisTask',\n      'LokiAnalysisTask',\n      'PartitionEnumerationTask',\n      'PlasoTask',\n      'PsortTask',\n      'RedisAnalysisTask',\n      'SSHDAnalysisTask',\n      'StringsAsciiTask',\n      'StringsUnicodeTask',\n      'TomcatAnalysisTask',\n      'VolatilityTask',\n      'StatTask',\n      'BinaryExtractorTask',\n      'BulkExtractorTask',\n      'DockerContainersEnumerationTask',\n      'PhotorecTask',\n      'AbortTask',\n      'CronAnalysisTask',\n  ]\n\n  def check_task_name(self, task_name):\n    \"\"\"Checks whether a given task name is a valid task\n    \n    Args:\n      task_name(str): Name of the Task to check.\n      \n    Returns:\n      bool: True if task with the given name exists, else False\n    \"\"\"\n    for task in self.TASK_LIST:\n      if task.lower() == task_name.lower():\n        return True\n    return False\n\n  def get_task(self, task_name):\n    \"\"\"Gets an instantiated Task object for the given name.\n    \n    Args:\n      task_name(str): Name of the Task to return.\n      \n    Returns:\n      TurbiniaTask: An instantiated Task object.\n    \"\"\"\n    # TODO(aarontp): Remove this list after\n    # https://github.com/google/turbinia/issues/278 is fixed.\n    #\n    # Late imports to minimize what loads all Tasks\n    from turbinia.workers.artifact import FileArtifactExtractionTask\n    from turbinia.workers.analysis.wordpress_access import WordpressAccessLogAnalysisTask\n    from turbinia.workers.analysis.wordpress_creds import WordpressCredsAnalysisTask\n    from turbinia.workers.analysis.jenkins import JenkinsAnalysisTask\n    from turbinia.workers.analysis.jupyter import JupyterAnalysisTask\n    from turbinia.workers.analysis.linux_acct import LinuxAccountAnalysisTask\n    from turbinia.workers.analysis.loki import LokiAnalysisTask\n    from turbinia.workers.analysis.windows_acct import WindowsAccountAnalysisTask\n    from turbinia.workers.finalize_request import FinalizeRequestTask\n    from turbinia.workers.cron import CronAnalysisTask\n    from turbinia.workers.docker import DockerContainersEnumerationTask\n    from turbinia.workers.grep import GrepTask\n    from turbinia.workers.fsstat import FsstatTask\n    from turbinia.workers.hadoop import HadoopAnalysisTask\n    from turbinia.workers.hindsight import HindsightTask\n    from turbinia.workers.partitions import PartitionEnumerationTask\n    from turbinia.workers.plaso import PlasoTask\n    from turbinia.workers.psort import PsortTask\n    from turbinia.workers.redis import RedisAnalysisTask\n    from turbinia.workers.sshd import SSHDAnalysisTask\n    from turbinia.workers.strings import StringsAsciiTask\n    from turbinia.workers.strings import StringsUnicodeTask\n    from turbinia.workers.tomcat import TomcatAnalysisTask\n    from turbinia.workers.volatility import VolatilityTask\n    from turbinia.workers.worker_stat import StatTask\n    from turbinia.workers.binary_extractor import BinaryExtractorTask\n    from turbinia.workers.bulk_extractor import BulkExtractorTask\n    from turbinia.workers.photorec import PhotorecTask\n    from turbinia.workers.abort import AbortTask\n\n    for task in self.TASK_LIST:\n      if task.lower() == task_name.lower():\n        try:\n          task_obj = locals()[task]\n          return task_obj()\n        except (AttributeError, KeyError):\n          message = (\n              \"Could not import {0:s} object! Make sure it is imported where \"\n              \"this method is defined.\".format(task_name))\n          log.error(message)\n          raise TurbiniaException(message)\n\n    return\n\n  def get_task_names(self):\n    \"\"\"Returns a list of Task names.\n    \n    Returns:\n      (list) All Task names.\n    \"\"\"\n    return self.TASK_LIST\n\n\ndef task_deserialize(input_dict):\n  \"\"\"Converts an input dictionary back into a TurbiniaTask object.\n\n  Args:\n    input_dict (dict): TurbiniaTask object dictionary.\n\n  Returns:\n    TurbiniaTask: Deserialized object.\n  \"\"\"\n\n  type_ = input_dict['name']\n  task_loader = TaskLoader()\n  task = task_loader.get_task(type_)\n  if not task:\n    raise TurbiniaException('Could not load Task module {0:s}'.format(type_))\n  # Remove serialized output manager because this gets reinstantiated when the\n  # empty Task is instantiated and we don't want to overwrite it.\n  input_dict.pop('output_manager')\n  task.__dict__.update(input_dict)\n  task.last_update = datetime.strptime(\n      input_dict['last_update'], DATETIME_FORMAT)\n  return task\n\n\ndef task_runner(obj, *args, **kwargs):\n  \"\"\"Wrapper function to run specified TurbiniaTask object.\n\n  Args:\n    obj: An instantiated TurbiniaTask object.\n    *args: Any Args to pass to obj.\n    **kwargs: Any keyword args to pass to obj.\n\n  Returns:\n    Output from TurbiniaTask (should be TurbiniaTaskResult).\n  \"\"\"\n\n  # GKE Specific - do not queue more work if pod places this file\n  if config.TASK_MANAGER.lower() == 'psq':\n    if os.path.exists(config.SCALEDOWN_WORKER_FILE):\n      # Late import because this is only needed for PSQ\n      import psq\n      raise psq.Retry()\n\n  # Try to acquire lock, timeout and requeue task if the worker\n  # is already processing a task.\n  try:\n    lock = filelock.FileLock(config.LOCK_FILE)\n    with lock.acquire(timeout=0.001):\n      obj = task_deserialize(obj)\n      run = obj.run_wrapper(*args, **kwargs)\n  except filelock.Timeout:\n    if config.TASK_MANAGER.lower() == 'psq':\n      # Late import because this is only needed for PSQ\n      import psq\n      raise psq.Retry()\n  # *Always* make sure we release the lock\n  finally:\n    lock.release()\n\n  return run\n", "path": "turbinia/task_utils.py"}]}