diff options
-rw-r--r-- | docker/Dockerfile | 2 | ||||
-rw-r--r-- | docs/release/release-notes/index.rst | 2 | ||||
-rw-r--r-- | qtip/api/__main__.py | 5 | ||||
-rw-r--r-- | qtip/api/controllers/metric.py | 23 | ||||
-rw-r--r-- | qtip/api/controllers/plan.py | 29 | ||||
-rw-r--r-- | qtip/api/controllers/qpi.py | 23 | ||||
-rw-r--r-- | qtip/api/swagger/swagger.yaml | 200 | ||||
-rw-r--r-- | qtip/driver/playbook/bwn_ng.yaml | 2 | ||||
-rw-r--r-- | qtip/driver/playbook/dpi/run.yaml | 14 | ||||
-rw-r--r-- | qtip/driver/playbook/dpi/setup.yaml | 2 | ||||
-rw-r--r-- | qtip/driver/playbook/inxi.yaml | 2 | ||||
-rw-r--r-- | qtip/driver/playbook/openssl/run.yaml | 14 | ||||
-rw-r--r-- | qtip/driver/playbook/openssl/setup.yaml | 2 | ||||
-rw-r--r-- | qtip/driver/playbook/ramspeed/run.yaml | 14 | ||||
-rw-r--r-- | qtip/driver/playbook/ramspeed/setup.yaml | 2 | ||||
-rw-r--r-- | qtip/driver/playbook/top.yaml | 2 | ||||
-rw-r--r-- | qtip/driver/playbook/unixbench/dhrystone.yaml | 22 | ||||
-rw-r--r-- | qtip/driver/playbook/unixbench/run.yaml | 14 | ||||
-rw-r--r-- | qtip/driver/playbook/unixbench/setup.yaml | 13 | ||||
-rw-r--r-- | qtip/driver/playbook/unixbench/whetstone.yaml | 23 | ||||
-rw-r--r-- | setup.cfg | 2 |
21 files changed, 337 insertions, 75 deletions
diff --git a/docker/Dockerfile b/docker/Dockerfile index 13665131..149c1fda 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -35,6 +35,8 @@ RUN apt-get update && apt-get install -y \ curl \ supervisor \ python-setuptools \ + iputils-ping\ + rsync --no-install-recommends \ && rm -rf /var/lib/apt/lists/* diff --git a/docs/release/release-notes/index.rst b/docs/release/release-notes/index.rst index 5d045388..3864c451 100644 --- a/docs/release/release-notes/index.rst +++ b/docs/release/release-notes/index.rst @@ -1,3 +1,5 @@ +.. _qtip-releasenotes: + .. This work is licensed under a Creative Commons Attribution 4.0 International License. .. http://creativecommons.org/licenses/by/4.0 .. (c) 2015 Dell Inc. diff --git a/qtip/api/__main__.py b/qtip/api/__main__.py index aa2941a7..7b9cdaf5 100644 --- a/qtip/api/__main__.py +++ b/qtip/api/__main__.py @@ -8,10 +8,13 @@ ############################################################################## import connexion +import os + +swagger_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'swagger/')) def main(): - app = connexion.App(__name__, specification_dir='swagger/') + app = connexion.App(__name__, specification_dir=swagger_dir) app.add_api('swagger.yaml', base_path='/v1.0') app.run(host='0.0.0.0', port='5000') diff --git a/qtip/api/controllers/metric.py b/qtip/api/controllers/metric.py new file mode 100644 index 00000000..a026b5fc --- /dev/null +++ b/qtip/api/controllers/metric.py @@ -0,0 +1,23 @@ +############################################################################## +# Copyright (c) 2017 akhil.batra@research.iiit.ac.in and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import connexion +import httplib + + +def list_metrics(): + return connexion.problem(httplib.NOT_IMPLEMENTED, + 'List metrics', + 'Metrics listing not implemented') + + +def get_metric(name): + return connexion.problem(httplib.NOT_IMPLEMENTED, + 'Get a metric', + 'metric retrieval not implemented') diff --git a/qtip/api/controllers/plan.py b/qtip/api/controllers/plan.py new file mode 100644 index 00000000..e202b413 --- /dev/null +++ b/qtip/api/controllers/plan.py @@ -0,0 +1,29 @@ +############################################################################## +# Copyright (c) 2017 akhil.batra@research.iiit.ac.in and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import connexion +import httplib + + +def list_plans(): + return connexion.problem(httplib.NOT_IMPLEMENTED, + 'List plans', + 'Plans listing not implemented') + + +def get_plan(name): + return connexion.problem(httplib.NOT_IMPLEMENTED, + 'Get a plan', + 'Plan retrieval not implemented') + + +def run_plan(name, action="run"): + return connexion.problem(httplib.NOT_IMPLEMENTED, + 'Run a plan', + 'Plan runner not implemented') diff --git a/qtip/api/controllers/qpi.py b/qtip/api/controllers/qpi.py new file mode 100644 index 00000000..0b5c5b09 --- /dev/null +++ b/qtip/api/controllers/qpi.py @@ -0,0 +1,23 @@ +############################################################################## +# Copyright (c) 2017 akhil.batra@research.iiit.ac.in and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import connexion +import httplib + + +def list_qpis(): + return connexion.problem(httplib.NOT_IMPLEMENTED, + 'List QPIs', + 'QPIs listing not implemented') + + +def get_qpi(name): + return connexion.problem(httplib.NOT_IMPLEMENTED, + 'Get a QPI', + 'QPI retrieval not implemented') diff --git a/qtip/api/swagger/swagger.yaml b/qtip/api/swagger/swagger.yaml index a5a815f1..96d34681 100644 --- a/qtip/api/swagger/swagger.yaml +++ b/qtip/api/swagger/swagger.yaml @@ -10,9 +10,207 @@ swagger: '2.0' info: title: QTIP-API + version: "1.0" consumes: - application/json produces: - application/json paths: - #TODO (akhil) add paths
\ No newline at end of file + /plans: + get: + summary: List all plans + operationId: qtip.api.controllers.plan.list_plans + tags: + - Plan + - standalone + responses: + 200: + description: A list of plans + #TODO (akhil) add item with properties and parameters + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + /plans/{name}: + get: + summary: Get a plan by plan name + operationId: qtip.api.controllers.plan.get_plan + tags: + - Plan + - standalone + parameters: + - name: name + in: path + description: Plan name + required: true + type: string + responses: + 200: + description: Plan information + #TODO (akhil) define schema + 404: + description: Plan not found + schema: + $ref: '#/definitions/Error' + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + post: + summary: Run a plan and return results + operationId: qtip.api.controllers.plan.run_plan + tags: + - Plan + - Standalone + parameters: + - name: name + in: path + description: Plan name + required: true + type: string + - name: action + in: query + description: action for a plan + required: true + type: string + responses: + 200: + description: Result of the run of the plan + #TODO (akhil) define schema + 404: + description: Plan not found + schema: + $ref: '#/definitions/Error' + 400: + description: Invalid parameters + schema: + $ref: '#/definitions/Error' + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + /qpis: + get: + summary: List all QPIs + operationId: qtip.api.controllers.qpi.list_qpis + tags: + - QPI + - Standalone + - Agent + responses: + 200: + description: A list of QPIs + #TODO (akhil) add item with properties and parameters + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + /qpis/{name}: + get: + summary: Get a QPI + operationId: qtip.api.controllers.qpi.get_qpi + tags: + - QPI + - Standalone + - Agent + parameters: + - name: name + in: path + description: QPI name + required: true + type: string + responses: + 200: + description: QPI information + #TODO (akhil) define schema + 404: + description: QPI not found + schema: + $ref: '#/definitions/Error' + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + /metrics: + get: + summary: List all metrics + operationId: qtip.api.controllers.metric.list_metrics + tags: + - Metric + - Standalone + - Agent + responses: + 200: + description: A list of metrics + #TODO (akhil) add item with properties and parameters + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + /metrics/{name}: + get: + summary: Get a metric + operationId: qtip.api.controllers.metric.get_metric + tags: + - Metric + - Standalone + - Agent + parameters: + - name: name + in: path + description: Metric name + required: true + type: string + responses: + 200: + description: Metric information + #TODO (akhil) define schema + 404: + description: Metric not found + schema: + $ref: '#/definitions/Error' + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' +definitions: + Error: + type: object + properties: + status: + type: integer + format: int32 + title: + type: string + detail: + type: string + type: + type: string
\ No newline at end of file diff --git a/qtip/driver/playbook/bwn_ng.yaml b/qtip/driver/playbook/bwn_ng.yaml index f79bb04e..c52cb14e 100644 --- a/qtip/driver/playbook/bwn_ng.yaml +++ b/qtip/driver/playbook/bwn_ng.yaml @@ -22,4 +22,4 @@ - name: Run bwm-ng shell: bwm-ng -o plain -c 1 > bwm-dump.log args: - chdir: '{{ dest_path }}/'
\ No newline at end of file + chdir: '{{ dest_path }}'
\ No newline at end of file diff --git a/qtip/driver/playbook/dpi/run.yaml b/qtip/driver/playbook/dpi/run.yaml index 58f7eb2f..f4c8c457 100644 --- a/qtip/driver/playbook/dpi/run.yaml +++ b/qtip/driver/playbook/dpi/run.yaml @@ -12,22 +12,18 @@ remote_user: root tasks: - - name: Get current timestamp - set_fact: - timestamp: "{{ lookup('pipe', 'date +%Y-%m-%d-%H-%M') }}" - - name: Make some directories needed file: - path: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}' + path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dpi/' state: directory - include: ../inxi.yaml vars: - dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}' + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dpi/' - include: ../top.yaml vars: - dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}' + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dpi/' - name: Run nDPI benchmark shell: ./dpi_average.sh @@ -37,10 +33,10 @@ - name: Copying result and system info to qtip result directory command: cp $HOME/tempD/nDPI/example/dpi_dump.txt ./ args: - chdir: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}' + chdir: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dpi/' - name: Fetch result files to local manchine synchronize: mode: pull src: '{{ ansible_env.HOME }}/qtip_result/' - dest: '{{ result_dir }}/dpi/logs/' + dest: '{{ result_dir }}/' diff --git a/qtip/driver/playbook/dpi/setup.yaml b/qtip/driver/playbook/dpi/setup.yaml index c1b45450..76e62e6d 100644 --- a/qtip/driver/playbook/dpi/setup.yaml +++ b/qtip/driver/playbook/dpi/setup.yaml @@ -14,7 +14,7 @@ tasks: - name: Making Dpi directory file: - path: '{{ result_dir }}/dpi/logs/' + path: '{{ result_dir }}/' state: directory - hosts: hosts diff --git a/qtip/driver/playbook/inxi.yaml b/qtip/driver/playbook/inxi.yaml index a06da042..2a4d9b3f 100644 --- a/qtip/driver/playbook/inxi.yaml +++ b/qtip/driver/playbook/inxi.yaml @@ -22,4 +22,4 @@ - name: Run inxi shell: inxi -b -c0 -n > inxi.log args: - chdir: '{{ dest_path }}/' + chdir: '{{ dest_path }}' diff --git a/qtip/driver/playbook/openssl/run.yaml b/qtip/driver/playbook/openssl/run.yaml index 241cac61..db923fed 100644 --- a/qtip/driver/playbook/openssl/run.yaml +++ b/qtip/driver/playbook/openssl/run.yaml @@ -12,22 +12,18 @@ remote_user: root tasks: - - name: Get current timestamp - set_fact: - timestamp: "{{ lookup('pipe', 'date +%Y-%m-%d-%H-%M') }}" - - name: Make some directories needed file: - path: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}' + path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ssl/' state: directory - include: ../inxi.yaml vars: - dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}/' + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ssl/' - include: ../top.yaml vars: - dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}/' + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ssl/' - name: Benchmarking RSA signatures and AES-128-cbc cipher encryption throughput shell: '{{ item }}' @@ -40,10 +36,10 @@ - name: Copying result to qtip result directory shell: cp ~/Open_SSL/openssl-1.0.2f/apps/*_dump ./ args: - chdir: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}/' + chdir: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ssl/' - name: Fetch result files to local manchine synchronize: mode: pull src: '{{ ansible_env.HOME }}/qtip_result/' - dest: '{{ result_dir }}/ssl/logs/' + dest: '{{ result_dir }}/' diff --git a/qtip/driver/playbook/openssl/setup.yaml b/qtip/driver/playbook/openssl/setup.yaml index e93bfb8e..3a6f385a 100644 --- a/qtip/driver/playbook/openssl/setup.yaml +++ b/qtip/driver/playbook/openssl/setup.yaml @@ -14,7 +14,7 @@ tasks: - name: Making ssl directory file: - path: '{{ result_dir }}/ssl/logs/' + path: '{{ result_dir }}/' state: directory - hosts: hosts diff --git a/qtip/driver/playbook/ramspeed/run.yaml b/qtip/driver/playbook/ramspeed/run.yaml index 33c9a6ef..94becb55 100644 --- a/qtip/driver/playbook/ramspeed/run.yaml +++ b/qtip/driver/playbook/ramspeed/run.yaml @@ -12,22 +12,18 @@ remote_user: root tasks: - - name: Get current timestamp - set_fact: - timestamp: "{{ lookup('pipe', 'date +%Y-%m-%d-%H-%M') }}" - - name: Make some directories needed file: - path: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}' + path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ramspeed/' state: directory - include: ../inxi.yaml vars: - dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}/' + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ramspeed/' - include: ../top.yaml vars: - dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}/' + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ramspeed/' - name: Benchmarking IntMem Bandwidth and FloatMem Bandwidth shell: '{{ item }}' @@ -35,10 +31,10 @@ - ~/ramspeed/ramsmp-3.5.0/ramsmp -b 3 -l 5 -p 1 >> Intmem - ~/ramspeed/ramsmp-3.5.0/ramsmp -b 6 -l 5 -p 1 >> Floatmem args: - chdir: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}/' + chdir: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/whetstone/' - name: Fetch result files to local manchine synchronize: mode: pull src: '{{ ansible_env.HOME }}/qtip_result/' - dest: '{{ result_dir }}/ramspeed/logs/' + dest: '{{ result_dir }}/' diff --git a/qtip/driver/playbook/ramspeed/setup.yaml b/qtip/driver/playbook/ramspeed/setup.yaml index 60368605..842bbda2 100644 --- a/qtip/driver/playbook/ramspeed/setup.yaml +++ b/qtip/driver/playbook/ramspeed/setup.yaml @@ -14,7 +14,7 @@ tasks: - name: Making ramspeed directory file: - path: '{{ result_dir }}/ramspeed/logs/' + path: '{{ result_dir }}/' state: directory - hosts: hosts diff --git a/qtip/driver/playbook/top.yaml b/qtip/driver/playbook/top.yaml index 64584338..dfa0aff2 100644 --- a/qtip/driver/playbook/top.yaml +++ b/qtip/driver/playbook/top.yaml @@ -9,4 +9,4 @@ - name: Collect cpu usage shell: top -bn1 > top.log args: - chdir: '{{ dest_path }}/' + chdir: '{{ dest_path }}' diff --git a/qtip/driver/playbook/unixbench/dhrystone.yaml b/qtip/driver/playbook/unixbench/dhrystone.yaml index 431814dd..caa97f44 100644 --- a/qtip/driver/playbook/unixbench/dhrystone.yaml +++ b/qtip/driver/playbook/unixbench/dhrystone.yaml @@ -7,21 +7,31 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## +- name: Make dhrystone directories + file: + path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dhrystone/' + state: directory + +- include: ../inxi.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dhrystone/' + +- include: ../top.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dhrystone/' + - name: Run dhrystone shell: ./Run -v dhrystone args: chdir: '{{ ansible_env.HOME }}/tempT/UnixBench/' - name: Copying result and system info to qtip result directory - shell: '{{ item }}' - with_items: - - mv ~/tempT/UnixBench/results/* ./ - - cp ~/qtip_result/inxi.log ~/qtip_result/top.log ./ + shell: mv ~/tempT/UnixBench/results/* ./ args: - chdir: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}' + chdir: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dhrystone/' - name: Fetch dhrystone result files to local manchine synchronize: mode: pull src: '{{ ansible_env.HOME }}/qtip_result/' - dest: '{{ result_dir }}/dhrystone/logs/' + dest: '{{ result_dir }}/' diff --git a/qtip/driver/playbook/unixbench/run.yaml b/qtip/driver/playbook/unixbench/run.yaml index acef36a7..fbe4d4ad 100644 --- a/qtip/driver/playbook/unixbench/run.yaml +++ b/qtip/driver/playbook/unixbench/run.yaml @@ -15,20 +15,6 @@ - set_fact: is_dhrystone: "{{ dhrystone | default(False) }}" is_whetstone: "{{ whetstone | default(False) }}" - timestamp: "{{ lookup('pipe', 'date +%Y-%m-%d-%H-%M') }}" - - - name: Make some directories needed - file: - path: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}' - state: directory - - - include: ../inxi.yaml - vars: - dest_path: '{{ ansible_env.HOME }}/qtip_result/' - - - include: ../top.yaml - vars: - dest_path: '{{ ansible_env.HOME }}/qtip_result/' - include: ./dhrystone.yaml when: "{{ is_dhrystone }}" diff --git a/qtip/driver/playbook/unixbench/setup.yaml b/qtip/driver/playbook/unixbench/setup.yaml index 283884ac..4b9b5240 100644 --- a/qtip/driver/playbook/unixbench/setup.yaml +++ b/qtip/driver/playbook/unixbench/setup.yaml @@ -12,21 +12,10 @@ gather_facts: no tasks: - - set_fact: - is_dhrystone: "{{ dhrystone | default(False) }}" - is_whetstone: "{{ whetstone | default(False) }}" - - name: Making dhrystone directory file: - path: '{{ result_dir }}/dhrystone/logs/' - state: directory - when: '{{ is_dhrystone }}' - - - name: Making whetstone directory - file: - path: '{{ result_dir }}/whetstone/logs/' + path: '{{ result_dir }}/' state: directory - when: '{{ is_whetstone }}' - hosts: hosts become: yes diff --git a/qtip/driver/playbook/unixbench/whetstone.yaml b/qtip/driver/playbook/unixbench/whetstone.yaml index f09e4e53..723fb3a6 100644 --- a/qtip/driver/playbook/unixbench/whetstone.yaml +++ b/qtip/driver/playbook/unixbench/whetstone.yaml @@ -7,22 +7,31 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## +- name: Make whetstone directories + file: + path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/whetstone/' + state: directory + +- include: ../inxi.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/whetstone/' + +- include: ../top.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/whetstone/' + - name: Run whetstone shell: ./Run -v whetstone - when: whetstone args: chdir: '{{ ansible_env.HOME }}/tempT/UnixBench/' - name: Copying result and system info to qtip result directory - shell: '{{ item }}' - with_items: - - mv ~/tempT/UnixBench/results/* ./ - - cp ~/qtip_result/inxi.log ~/qtip_result/top.log ./ + shell: mv ~/tempT/UnixBench/results/* ./ args: - chdir: '{{ ansible_env.HOME }}/qtip_result/{{ timestamp }}/{{ ansible_hostname }}' + chdir: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/whetstone/' - name: Fetch whetstone result files to local manchine synchronize: mode: pull src: '{{ ansible_env.HOME }}/qtip_result/' - dest: '{{ result_dir }}/whetstone/logs/' + dest: '{{ result_dir }}/' @@ -14,7 +14,7 @@ setup-hooks = [entry_points] console_scripts = qtip = qtip.cli.entry:cli - # TODO(akhil) add qtip-api + qtip-api = qtip.api.__main__:main [files] packages = |