We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
log2timeline not scanning volumes
log2timeline (PlasoHasher/Parser task) is not scanning volumes like the image_export (FileExtractor task) job does. Log2timeline is missing the ```--volumes all``` option.

https://github.com/google/turbinia/blob/7dfde64b24f0e13d1da771e60a00d244d7e2571b/turbinia/workers/binary_extractor.py#L103

https://github.com/google/turbinia/blob/749a25a065e89994d8fb324ebc31530c1b5efa57/turbinia/workers/plaso.py#L150

--- 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/workers/plaso.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # Copyright 2015 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 for running Plaso."""
16 
17 from __future__ import unicode_literals
18 
19 import os
20 import logging
21 
22 from turbinia import config
23 from turbinia.evidence import EvidenceState as state
24 from turbinia.evidence import PlasoFile
25 from turbinia.workers import TurbiniaTask
26 from turbinia.lib import file_helpers
27 
28 
29 class PlasoTask(TurbiniaTask):
30   """Parent task for PlasoJob sub-tasks."""
31 
32   # Plaso requires the Disk to be attached, but doesn't require it be mounted.
33   REQUIRED_STATES = [
34       state.ATTACHED, state.DECOMPRESSED, state.CONTAINER_MOUNTED
35   ]
36 
37   def test_yara_rules(self, file_path, result):
38     """Test the given Yara rules for syntactical validity before processing.
39 
40     Args:
41       file_path (str): Location on disk of the Yara rules to be tested.
42       result (TurbiniaTaskResult): The object to place task results into.
43     
44     Returns:
45       True if rules are good, else False
46     """
47     cmd = ['/opt/fraken/fraken', '-rules', file_path, '-testrules']
48     (ret, _) = self.execute(cmd, result)
49     if ret == 0:
50       return True
51     return False
52 
53   def build_plaso_command(self, base_command, conf):
54     """Builds a typical plaso command, contains logic specific to log2timeline.
55 
56     Args:
57       base_command (str): Command to invoke log2timeline (e.g. log2timeline.py)
58       conf (dict): Dynamic config containing the parameters for the command.
59 
60     Returns:
61       String for valid Log2timeline command.
62     """
63     self.result.log(
64         'Generating Plaso command line from arguments: {0!s}'.format(conf),
65         level=logging.DEBUG)
66     cmd = [base_command]
67     for k, v in conf.items():
68       cli_args = [
69           'status_view', 'hashers', 'hasher_file_size_limit', 'partitions',
70           'vss_stores', 'custom_artifact_definitions', 'parsers',
71           'artifact_filters', 'file_filter', 'yara_rules'
72       ]
73       if (k not in cli_args or not v):
74         continue
75       prepend = '-'
76       if len(k) > 1:
77         prepend = '--'
78       if k == 'file_filter':
79         file_path = file_helpers.write_list_to_temp_file(
80             v, preferred_dir=self.tmp_dir)
81         cmd.extend(['-f', file_path])
82       elif k == 'yara_rules':
83         file_path = file_helpers.write_str_to_temp_file(
84             v, preferred_dir=self.tmp_dir)
85         rules_check = self.test_yara_rules(file_path, self.result)
86         if rules_check:
87           cmd.extend(['--yara_rules', file_path])
88       elif isinstance(v, list):
89         cmd.extend([prepend + k, ','.join(v)])
90       elif isinstance(v, bool):
91         cmd.append(prepend + k)
92       elif isinstance(v, str):
93         cmd.extend([prepend + k, v])
94     return cmd
95 
96   def run(self, evidence, result):
97     """Task that process data with Plaso.
98 
99     Args:
100         evidence (Evidence object):  The evidence we will process.
101         result (TurbiniaTaskResult): The object to place task results into.
102 
103     Returns:
104         TurbiniaTaskResult object.
105     """
106 
107     config.LoadConfig()
108 
109     # Write plaso file into tmp_dir because sqlite has issues with some shared
110     # filesystems (e.g NFS).
111     plaso_file = os.path.join(self.tmp_dir, '{0:s}.plaso'.format(self.id))
112     plaso_evidence = PlasoFile(source_path=plaso_file)
113     plaso_log = os.path.join(self.output_dir, '{0:s}.log'.format(self.id))
114 
115     cmd = self.build_plaso_command('log2timeline.py', self.task_config)
116 
117     if config.DEBUG_TASKS or self.task_config.get('debug_tasks'):
118       cmd.append('-d')
119 
120     if evidence.credentials:
121       for credential_type, credential_data in evidence.credentials:
122         cmd.extend([
123             '--credential', '{0:s}:{1:s}'.format(
124                 credential_type, credential_data)
125         ])
126 
127     cmd.extend(['--temporary_directory', self.tmp_dir])
128     cmd.extend(['--logfile', plaso_log])
129     cmd.extend(['--unattended'])
130     cmd.extend(['--storage_file', plaso_file])
131     cmd.extend([evidence.local_path])
132 
133     result.log('Running {0:s} as [{1:s}]'.format(self.name, ' '.join(cmd)))
134     self.execute(
135         cmd, result, log_files=[plaso_log], new_evidence=[plaso_evidence],
136         close=True)
137 
138     return result
139 
140 
141 class PlasoParserTask(PlasoTask):
142   """Task to run Plaso parsers (log2timeline)."""
143 
144   TASK_CONFIG = {
145       # 'none' as indicated in the options for status_view within
146       # the Plaso documentation
147       'status_view': 'none',
148       'hashers': 'none',
149       'hasher_file_size_limit': None,
150       'partitions': 'all',
151       'vss_stores': 'none',
152       # artifact_filters and file_filter are mutually exclusive
153       # parameters and Plaso will error out if both parameters are used.
154       'artifact_filters': None,
155       'file_filter': None,
156       'custom_artifact_definitions': None,
157       # Disable filestat parser. PlasoHasherTask will run it separately.
158       'parsers': '!filestat',
159       'yara_rules': None
160   }
161 
162 
163 class PlasoHasherTask(PlasoTask):
164   """Task to run Plaso hashers. This task only runs the filestat parser."""
165 
166   TASK_CONFIG = {
167       # 'none' as indicated in the options for status_view within
168       # the Plaso documentation
169       'status_view': 'none',
170       'hashers': 'all',
171       'hasher_file_size_limit': '1073741824',
172       'partitions': 'all',
173       'vss_stores': 'none',
174       # artifact_filters and file_filter are mutually exclusive
175       # parameters and Plaso will error out if both parameters are used.
176       'artifact_filters': None,
177       'file_filter': None,
178       'custom_artifact_definitions': None,
179       'parsers': 'filestat',
180       'yara_rules': None
181   }
182
```
--- 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/workers/plaso.py b/turbinia/workers/plaso.py
--- a/turbinia/workers/plaso.py
+++ b/turbinia/workers/plaso.py
@@ -68,7 +68,7 @@
       cli_args = [
           'status_view', 'hashers', 'hasher_file_size_limit', 'partitions',
           'vss_stores', 'custom_artifact_definitions', 'parsers',
-          'artifact_filters', 'file_filter', 'yara_rules'
+          'artifact_filters', 'file_filter', 'yara_rules', 'volumes'
       ]
       if (k not in cli_args or not v):
         continue
@@ -148,6 +148,7 @@
       'hashers': 'none',
       'hasher_file_size_limit': None,
       'partitions': 'all',
+      'volumes': 'all',
       'vss_stores': 'none',
       # artifact_filters and file_filter are mutually exclusive
       # parameters and Plaso will error out if both parameters are used.
@@ -170,6 +171,7 @@
       'hashers': 'all',
       'hasher_file_size_limit': '1073741824',
       'partitions': 'all',
+      'volumes': 'all',
       'vss_stores': 'none',
       # artifact_filters and file_filter are mutually exclusive
       # parameters and Plaso will error out if both parameters are used.

{"golden_diff": "diff --git a/turbinia/workers/plaso.py b/turbinia/workers/plaso.py\n--- a/turbinia/workers/plaso.py\n+++ b/turbinia/workers/plaso.py\n@@ -68,7 +68,7 @@\n       cli_args = [\n           'status_view', 'hashers', 'hasher_file_size_limit', 'partitions',\n           'vss_stores', 'custom_artifact_definitions', 'parsers',\n-          'artifact_filters', 'file_filter', 'yara_rules'\n+          'artifact_filters', 'file_filter', 'yara_rules', 'volumes'\n       ]\n       if (k not in cli_args or not v):\n         continue\n@@ -148,6 +148,7 @@\n       'hashers': 'none',\n       'hasher_file_size_limit': None,\n       'partitions': 'all',\n+      'volumes': 'all',\n       'vss_stores': 'none',\n       # artifact_filters and file_filter are mutually exclusive\n       # parameters and Plaso will error out if both parameters are used.\n@@ -170,6 +171,7 @@\n       'hashers': 'all',\n       'hasher_file_size_limit': '1073741824',\n       'partitions': 'all',\n+      'volumes': 'all',\n       'vss_stores': 'none',\n       # artifact_filters and file_filter are mutually exclusive\n       # parameters and Plaso will error out if both parameters are used.\n", "issue": "log2timeline not scanning volumes\nlog2timeline (PlasoHasher/Parser task) is not scanning volumes like the image_export (FileExtractor task) job does. Log2timeline is missing the ```--volumes all``` option.\r\n\r\nhttps://github.com/google/turbinia/blob/7dfde64b24f0e13d1da771e60a00d244d7e2571b/turbinia/workers/binary_extractor.py#L103\r\n\r\nhttps://github.com/google/turbinia/blob/749a25a065e89994d8fb324ebc31530c1b5efa57/turbinia/workers/plaso.py#L150\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 2015 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 for running Plaso.\"\"\"\n\nfrom __future__ import unicode_literals\n\nimport os\nimport logging\n\nfrom turbinia import config\nfrom turbinia.evidence import EvidenceState as state\nfrom turbinia.evidence import PlasoFile\nfrom turbinia.workers import TurbiniaTask\nfrom turbinia.lib import file_helpers\n\n\nclass PlasoTask(TurbiniaTask):\n  \"\"\"Parent task for PlasoJob sub-tasks.\"\"\"\n\n  # Plaso requires the Disk to be attached, but doesn't require it be mounted.\n  REQUIRED_STATES = [\n      state.ATTACHED, state.DECOMPRESSED, state.CONTAINER_MOUNTED\n  ]\n\n  def test_yara_rules(self, file_path, result):\n    \"\"\"Test the given Yara rules for syntactical validity before processing.\n\n    Args:\n      file_path (str): Location on disk of the Yara rules to be tested.\n      result (TurbiniaTaskResult): The object to place task results into.\n    \n    Returns:\n      True if rules are good, else False\n    \"\"\"\n    cmd = ['/opt/fraken/fraken', '-rules', file_path, '-testrules']\n    (ret, _) = self.execute(cmd, result)\n    if ret == 0:\n      return True\n    return False\n\n  def build_plaso_command(self, base_command, conf):\n    \"\"\"Builds a typical plaso command, contains logic specific to log2timeline.\n\n    Args:\n      base_command (str): Command to invoke log2timeline (e.g. log2timeline.py)\n      conf (dict): Dynamic config containing the parameters for the command.\n\n    Returns:\n      String for valid Log2timeline command.\n    \"\"\"\n    self.result.log(\n        'Generating Plaso command line from arguments: {0!s}'.format(conf),\n        level=logging.DEBUG)\n    cmd = [base_command]\n    for k, v in conf.items():\n      cli_args = [\n          'status_view', 'hashers', 'hasher_file_size_limit', 'partitions',\n          'vss_stores', 'custom_artifact_definitions', 'parsers',\n          'artifact_filters', 'file_filter', 'yara_rules'\n      ]\n      if (k not in cli_args or not v):\n        continue\n      prepend = '-'\n      if len(k) > 1:\n        prepend = '--'\n      if k == 'file_filter':\n        file_path = file_helpers.write_list_to_temp_file(\n            v, preferred_dir=self.tmp_dir)\n        cmd.extend(['-f', file_path])\n      elif k == 'yara_rules':\n        file_path = file_helpers.write_str_to_temp_file(\n            v, preferred_dir=self.tmp_dir)\n        rules_check = self.test_yara_rules(file_path, self.result)\n        if rules_check:\n          cmd.extend(['--yara_rules', file_path])\n      elif isinstance(v, list):\n        cmd.extend([prepend + k, ','.join(v)])\n      elif isinstance(v, bool):\n        cmd.append(prepend + k)\n      elif isinstance(v, str):\n        cmd.extend([prepend + k, v])\n    return cmd\n\n  def run(self, evidence, result):\n    \"\"\"Task that process data with Plaso.\n\n    Args:\n        evidence (Evidence object):  The evidence we will process.\n        result (TurbiniaTaskResult): The object to place task results into.\n\n    Returns:\n        TurbiniaTaskResult object.\n    \"\"\"\n\n    config.LoadConfig()\n\n    # Write plaso file into tmp_dir because sqlite has issues with some shared\n    # filesystems (e.g NFS).\n    plaso_file = os.path.join(self.tmp_dir, '{0:s}.plaso'.format(self.id))\n    plaso_evidence = PlasoFile(source_path=plaso_file)\n    plaso_log = os.path.join(self.output_dir, '{0:s}.log'.format(self.id))\n\n    cmd = self.build_plaso_command('log2timeline.py', self.task_config)\n\n    if config.DEBUG_TASKS or self.task_config.get('debug_tasks'):\n      cmd.append('-d')\n\n    if evidence.credentials:\n      for credential_type, credential_data in evidence.credentials:\n        cmd.extend([\n            '--credential', '{0:s}:{1:s}'.format(\n                credential_type, credential_data)\n        ])\n\n    cmd.extend(['--temporary_directory', self.tmp_dir])\n    cmd.extend(['--logfile', plaso_log])\n    cmd.extend(['--unattended'])\n    cmd.extend(['--storage_file', plaso_file])\n    cmd.extend([evidence.local_path])\n\n    result.log('Running {0:s} as [{1:s}]'.format(self.name, ' '.join(cmd)))\n    self.execute(\n        cmd, result, log_files=[plaso_log], new_evidence=[plaso_evidence],\n        close=True)\n\n    return result\n\n\nclass PlasoParserTask(PlasoTask):\n  \"\"\"Task to run Plaso parsers (log2timeline).\"\"\"\n\n  TASK_CONFIG = {\n      # 'none' as indicated in the options for status_view within\n      # the Plaso documentation\n      'status_view': 'none',\n      'hashers': 'none',\n      'hasher_file_size_limit': None,\n      'partitions': 'all',\n      'vss_stores': 'none',\n      # artifact_filters and file_filter are mutually exclusive\n      # parameters and Plaso will error out if both parameters are used.\n      'artifact_filters': None,\n      'file_filter': None,\n      'custom_artifact_definitions': None,\n      # Disable filestat parser. PlasoHasherTask will run it separately.\n      'parsers': '!filestat',\n      'yara_rules': None\n  }\n\n\nclass PlasoHasherTask(PlasoTask):\n  \"\"\"Task to run Plaso hashers. This task only runs the filestat parser.\"\"\"\n\n  TASK_CONFIG = {\n      # 'none' as indicated in the options for status_view within\n      # the Plaso documentation\n      'status_view': 'none',\n      'hashers': 'all',\n      'hasher_file_size_limit': '1073741824',\n      'partitions': 'all',\n      'vss_stores': 'none',\n      # artifact_filters and file_filter are mutually exclusive\n      # parameters and Plaso will error out if both parameters are used.\n      'artifact_filters': None,\n      'file_filter': None,\n      'custom_artifact_definitions': None,\n      'parsers': 'filestat',\n      'yara_rules': None\n  }\n", "path": "turbinia/workers/plaso.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 2015 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 for running Plaso.\"\"\"\n\nfrom __future__ import unicode_literals\n\nimport os\nimport logging\n\nfrom turbinia import config\nfrom turbinia.evidence import EvidenceState as state\nfrom turbinia.evidence import PlasoFile\nfrom turbinia.workers import TurbiniaTask\nfrom turbinia.lib import file_helpers\n\n\nclass PlasoTask(TurbiniaTask):\n  \"\"\"Parent task for PlasoJob sub-tasks.\"\"\"\n\n  # Plaso requires the Disk to be attached, but doesn't require it be mounted.\n  REQUIRED_STATES = [\n      state.ATTACHED, state.DECOMPRESSED, state.CONTAINER_MOUNTED\n  ]\n\n  def test_yara_rules(self, file_path, result):\n    \"\"\"Test the given Yara rules for syntactical validity before processing.\n\n    Args:\n      file_path (str): Location on disk of the Yara rules to be tested.\n      result (TurbiniaTaskResult): The object to place task results into.\n    \n    Returns:\n      True if rules are good, else False\n    \"\"\"\n    cmd = ['/opt/fraken/fraken', '-rules', file_path, '-testrules']\n    (ret, _) = self.execute(cmd, result)\n    if ret == 0:\n      return True\n    return False\n\n  def build_plaso_command(self, base_command, conf):\n    \"\"\"Builds a typical plaso command, contains logic specific to log2timeline.\n\n    Args:\n      base_command (str): Command to invoke log2timeline (e.g. log2timeline.py)\n      conf (dict): Dynamic config containing the parameters for the command.\n\n    Returns:\n      String for valid Log2timeline command.\n    \"\"\"\n    self.result.log(\n        'Generating Plaso command line from arguments: {0!s}'.format(conf),\n        level=logging.DEBUG)\n    cmd = [base_command]\n    for k, v in conf.items():\n      cli_args = [\n          'status_view', 'hashers', 'hasher_file_size_limit', 'partitions',\n          'vss_stores', 'custom_artifact_definitions', 'parsers',\n          'artifact_filters', 'file_filter', 'yara_rules', 'volumes'\n      ]\n      if (k not in cli_args or not v):\n        continue\n      prepend = '-'\n      if len(k) > 1:\n        prepend = '--'\n      if k == 'file_filter':\n        file_path = file_helpers.write_list_to_temp_file(\n            v, preferred_dir=self.tmp_dir)\n        cmd.extend(['-f', file_path])\n      elif k == 'yara_rules':\n        file_path = file_helpers.write_str_to_temp_file(\n            v, preferred_dir=self.tmp_dir)\n        rules_check = self.test_yara_rules(file_path, self.result)\n        if rules_check:\n          cmd.extend(['--yara_rules', file_path])\n      elif isinstance(v, list):\n        cmd.extend([prepend + k, ','.join(v)])\n      elif isinstance(v, bool):\n        cmd.append(prepend + k)\n      elif isinstance(v, str):\n        cmd.extend([prepend + k, v])\n    return cmd\n\n  def run(self, evidence, result):\n    \"\"\"Task that process data with Plaso.\n\n    Args:\n        evidence (Evidence object):  The evidence we will process.\n        result (TurbiniaTaskResult): The object to place task results into.\n\n    Returns:\n        TurbiniaTaskResult object.\n    \"\"\"\n\n    config.LoadConfig()\n\n    # Write plaso file into tmp_dir because sqlite has issues with some shared\n    # filesystems (e.g NFS).\n    plaso_file = os.path.join(self.tmp_dir, '{0:s}.plaso'.format(self.id))\n    plaso_evidence = PlasoFile(source_path=plaso_file)\n    plaso_log = os.path.join(self.output_dir, '{0:s}.log'.format(self.id))\n\n    cmd = self.build_plaso_command('log2timeline.py', self.task_config)\n\n    if config.DEBUG_TASKS or self.task_config.get('debug_tasks'):\n      cmd.append('-d')\n\n    if evidence.credentials:\n      for credential_type, credential_data in evidence.credentials:\n        cmd.extend([\n            '--credential', '{0:s}:{1:s}'.format(\n                credential_type, credential_data)\n        ])\n\n    cmd.extend(['--temporary_directory', self.tmp_dir])\n    cmd.extend(['--logfile', plaso_log])\n    cmd.extend(['--unattended'])\n    cmd.extend(['--storage_file', plaso_file])\n    cmd.extend([evidence.local_path])\n\n    result.log('Running {0:s} as [{1:s}]'.format(self.name, ' '.join(cmd)))\n    self.execute(\n        cmd, result, log_files=[plaso_log], new_evidence=[plaso_evidence],\n        close=True)\n\n    return result\n\n\nclass PlasoParserTask(PlasoTask):\n  \"\"\"Task to run Plaso parsers (log2timeline).\"\"\"\n\n  TASK_CONFIG = {\n      # 'none' as indicated in the options for status_view within\n      # the Plaso documentation\n      'status_view': 'none',\n      'hashers': 'none',\n      'hasher_file_size_limit': None,\n      'partitions': 'all',\n      'volumes': 'all',\n      'vss_stores': 'none',\n      # artifact_filters and file_filter are mutually exclusive\n      # parameters and Plaso will error out if both parameters are used.\n      'artifact_filters': None,\n      'file_filter': None,\n      'custom_artifact_definitions': None,\n      # Disable filestat parser. PlasoHasherTask will run it separately.\n      'parsers': '!filestat',\n      'yara_rules': None\n  }\n\n\nclass PlasoHasherTask(PlasoTask):\n  \"\"\"Task to run Plaso hashers. This task only runs the filestat parser.\"\"\"\n\n  TASK_CONFIG = {\n      # 'none' as indicated in the options for status_view within\n      # the Plaso documentation\n      'status_view': 'none',\n      'hashers': 'all',\n      'hasher_file_size_limit': '1073741824',\n      'partitions': 'all',\n      'volumes': 'all',\n      'vss_stores': 'none',\n      # artifact_filters and file_filter are mutually exclusive\n      # parameters and Plaso will error out if both parameters are used.\n      'artifact_filters': None,\n      'file_filter': None,\n      'custom_artifact_definitions': None,\n      'parsers': 'filestat',\n      'yara_rules': None\n  }\n", "path": "turbinia/workers/plaso.py"}]}