Browse Source

Move dashboard from python-mistralclient

Also:
- add license headers
- set up tox for flake8 checks and venv
- remove run_tests.sh, tools/ and other stuff we don't need at the moment
- add basic sphinx setup for later use

Change-Id: I0d34fb9fd0bfd351d20474da88715b30ff3c3d61
tags/0.0.3
Kirill Izotov 5 years ago
parent
commit
28bde7a230
36 changed files with 1670 additions and 4 deletions
  1. 42
    0
      .gitignore
  2. 175
    0
      LICENSE
  3. 0
    4
      README.md
  4. 33
    0
      README.rst
  5. 62
    0
      doc/source/conf.py
  6. 1
    0
      doc/source/index.rst
  7. 23
    0
      manage.py
  8. 0
    0
      mistraldashboard/__init__.py
  9. 0
    0
      mistraldashboard/dashboards/__init__.py
  10. 0
    0
      mistraldashboard/dashboards/mistral/__init__.py
  11. 37
    0
      mistraldashboard/dashboards/mistral/api.py
  12. 38
    0
      mistraldashboard/dashboards/mistral/dashboard.py
  13. 0
    0
      mistraldashboard/dashboards/mistral/executions/__init__.py
  14. 28
    0
      mistraldashboard/dashboards/mistral/executions/panel.py
  15. 42
    0
      mistraldashboard/dashboards/mistral/executions/tables.py
  16. 11
    0
      mistraldashboard/dashboards/mistral/executions/templates/executions/index.html
  17. 29
    0
      mistraldashboard/dashboards/mistral/executions/urls.py
  18. 43
    0
      mistraldashboard/dashboards/mistral/executions/views.py
  19. 0
    0
      mistraldashboard/dashboards/mistral/workbooks/__init__.py
  20. 63
    0
      mistraldashboard/dashboards/mistral/workbooks/forms.py
  21. 29
    0
      mistraldashboard/dashboards/mistral/workbooks/panel.py
  22. 44
    0
      mistraldashboard/dashboards/mistral/workbooks/tables.py
  23. 25
    0
      mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/_execute.html
  24. 11
    0
      mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/execute.html
  25. 11
    0
      mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/index.html
  26. 29
    0
      mistraldashboard/dashboards/mistral/workbooks/urls.py
  27. 48
    0
      mistraldashboard/dashboards/mistral/workbooks/views.py
  28. 0
    0
      mistraldashboard/local/__init__.py
  29. 488
    0
      mistraldashboard/local/local_settings.py.example
  30. 3
    0
      mistraldashboard/models.py
  31. 263
    0
      mistraldashboard/settings.py
  32. 3
    0
      requirements.txt
  33. 29
    0
      setup.cfg
  34. 30
    0
      setup.py
  35. 4
    0
      test-requirements.txt
  36. 26
    0
      tox.ini

+ 42
- 0
.gitignore View File

@@ -0,0 +1,42 @@
1
+*.py[cod]
2
+*.sqlite
3
+
4
+# C extensions
5
+*.so
6
+
7
+# Packages
8
+*.egg
9
+*.egg-info
10
+dist
11
+build
12
+.venv
13
+eggs
14
+parts
15
+bin
16
+var
17
+sdist
18
+develop-eggs
19
+.installed.cfg
20
+lib
21
+lib64
22
+
23
+# Installer logs
24
+pip-log.txt
25
+
26
+# Unit test / coverage reports
27
+.coverage
28
+.tox
29
+nosetests.xml
30
+
31
+# Translations
32
+*.mo
33
+
34
+# Mr Developer
35
+.mr.developer.cfg
36
+.project
37
+.pydevproject
38
+.idea
39
+.DS_Store
40
+mistraldashboard/local/local_settings.py
41
+mistraldashboard/local/.secret_key_store
42
+static

+ 175
- 0
LICENSE View File

@@ -0,0 +1,175 @@
1
+
2
+                                 Apache License
3
+                           Version 2.0, January 2004
4
+                        http://www.apache.org/licenses/
5
+
6
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+   1. Definitions.
9
+
10
+      "License" shall mean the terms and conditions for use, reproduction,
11
+      and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+      "Licensor" shall mean the copyright owner or entity authorized by
14
+      the copyright owner that is granting the License.
15
+
16
+      "Legal Entity" shall mean the union of the acting entity and all
17
+      other entities that control, are controlled by, or are under common
18
+      control with that entity. For the purposes of this definition,
19
+      "control" means (i) the power, direct or indirect, to cause the
20
+      direction or management of such entity, whether by contract or
21
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+      outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+      "You" (or "Your") shall mean an individual or Legal Entity
25
+      exercising permissions granted by this License.
26
+
27
+      "Source" form shall mean the preferred form for making modifications,
28
+      including but not limited to software source code, documentation
29
+      source, and configuration files.
30
+
31
+      "Object" form shall mean any form resulting from mechanical
32
+      transformation or translation of a Source form, including but
33
+      not limited to compiled object code, generated documentation,
34
+      and conversions to other media types.
35
+
36
+      "Work" shall mean the work of authorship, whether in Source or
37
+      Object form, made available under the License, as indicated by a
38
+      copyright notice that is included in or attached to the work
39
+      (an example is provided in the Appendix below).
40
+
41
+      "Derivative Works" shall mean any work, whether in Source or Object
42
+      form, that is based on (or derived from) the Work and for which the
43
+      editorial revisions, annotations, elaborations, or other modifications
44
+      represent, as a whole, an original work of authorship. For the purposes
45
+      of this License, Derivative Works shall not include works that remain
46
+      separable from, or merely link (or bind by name) to the interfaces of,
47
+      the Work and Derivative Works thereof.
48
+
49
+      "Contribution" shall mean any work of authorship, including
50
+      the original version of the Work and any modifications or additions
51
+      to that Work or Derivative Works thereof, that is intentionally
52
+      submitted to Licensor for inclusion in the Work by the copyright owner
53
+      or by an individual or Legal Entity authorized to submit on behalf of
54
+      the copyright owner. For the purposes of this definition, "submitted"
55
+      means any form of electronic, verbal, or written communication sent
56
+      to the Licensor or its representatives, including but not limited to
57
+      communication on electronic mailing lists, source code control systems,
58
+      and issue tracking systems that are managed by, or on behalf of, the
59
+      Licensor for the purpose of discussing and improving the Work, but
60
+      excluding communication that is conspicuously marked or otherwise
61
+      designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+      "Contributor" shall mean Licensor and any individual or Legal Entity
64
+      on behalf of whom a Contribution has been received by Licensor and
65
+      subsequently incorporated within the Work.
66
+
67
+   2. Grant of Copyright License. Subject to the terms and conditions of
68
+      this License, each Contributor hereby grants to You a perpetual,
69
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+      copyright license to reproduce, prepare Derivative Works of,
71
+      publicly display, publicly perform, sublicense, and distribute the
72
+      Work and such Derivative Works in Source or Object form.
73
+
74
+   3. Grant of Patent License. Subject to the terms and conditions of
75
+      this License, each Contributor hereby grants to You a perpetual,
76
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+      (except as stated in this section) patent license to make, have made,
78
+      use, offer to sell, sell, import, and otherwise transfer the Work,
79
+      where such license applies only to those patent claims licensable
80
+      by such Contributor that are necessarily infringed by their
81
+      Contribution(s) alone or by combination of their Contribution(s)
82
+      with the Work to which such Contribution(s) was submitted. If You
83
+      institute patent litigation against any entity (including a
84
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+      or a Contribution incorporated within the Work constitutes direct
86
+      or contributory patent infringement, then any patent licenses
87
+      granted to You under this License for that Work shall terminate
88
+      as of the date such litigation is filed.
89
+
90
+   4. Redistribution. You may reproduce and distribute copies of the
91
+      Work or Derivative Works thereof in any medium, with or without
92
+      modifications, and in Source or Object form, provided that You
93
+      meet the following conditions:
94
+
95
+      (a) You must give any other recipients of the Work or
96
+          Derivative Works a copy of this License; and
97
+
98
+      (b) You must cause any modified files to carry prominent notices
99
+          stating that You changed the files; and
100
+
101
+      (c) You must retain, in the Source form of any Derivative Works
102
+          that You distribute, all copyright, patent, trademark, and
103
+          attribution notices from the Source form of the Work,
104
+          excluding those notices that do not pertain to any part of
105
+          the Derivative Works; and
106
+
107
+      (d) If the Work includes a "NOTICE" text file as part of its
108
+          distribution, then any Derivative Works that You distribute must
109
+          include a readable copy of the attribution notices contained
110
+          within such NOTICE file, excluding those notices that do not
111
+          pertain to any part of the Derivative Works, in at least one
112
+          of the following places: within a NOTICE text file distributed
113
+          as part of the Derivative Works; within the Source form or
114
+          documentation, if provided along with the Derivative Works; or,
115
+          within a display generated by the Derivative Works, if and
116
+          wherever such third-party notices normally appear. The contents
117
+          of the NOTICE file are for informational purposes only and
118
+          do not modify the License. You may add Your own attribution
119
+          notices within Derivative Works that You distribute, alongside
120
+          or as an addendum to the NOTICE text from the Work, provided
121
+          that such additional attribution notices cannot be construed
122
+          as modifying the License.
123
+
124
+      You may add Your own copyright statement to Your modifications and
125
+      may provide additional or different license terms and conditions
126
+      for use, reproduction, or distribution of Your modifications, or
127
+      for any such Derivative Works as a whole, provided Your use,
128
+      reproduction, and distribution of the Work otherwise complies with
129
+      the conditions stated in this License.
130
+
131
+   5. Submission of Contributions. Unless You explicitly state otherwise,
132
+      any Contribution intentionally submitted for inclusion in the Work
133
+      by You to the Licensor shall be under the terms and conditions of
134
+      this License, without any additional terms or conditions.
135
+      Notwithstanding the above, nothing herein shall supersede or modify
136
+      the terms of any separate license agreement you may have executed
137
+      with Licensor regarding such Contributions.
138
+
139
+   6. Trademarks. This License does not grant permission to use the trade
140
+      names, trademarks, service marks, or product names of the Licensor,
141
+      except as required for reasonable and customary use in describing the
142
+      origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+   7. Disclaimer of Warranty. Unless required by applicable law or
145
+      agreed to in writing, Licensor provides the Work (and each
146
+      Contributor provides its Contributions) on an "AS IS" BASIS,
147
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+      implied, including, without limitation, any warranties or conditions
149
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+      PARTICULAR PURPOSE. You are solely responsible for determining the
151
+      appropriateness of using or redistributing the Work and assume any
152
+      risks associated with Your exercise of permissions under this License.
153
+
154
+   8. Limitation of Liability. In no event and under no legal theory,
155
+      whether in tort (including negligence), contract, or otherwise,
156
+      unless required by applicable law (such as deliberate and grossly
157
+      negligent acts) or agreed to in writing, shall any Contributor be
158
+      liable to You for damages, including any direct, indirect, special,
159
+      incidental, or consequential damages of any character arising as a
160
+      result of this License or out of the use or inability to use the
161
+      Work (including but not limited to damages for loss of goodwill,
162
+      work stoppage, computer failure or malfunction, or any and all
163
+      other commercial damages or losses), even if such Contributor
164
+      has been advised of the possibility of such damages.
165
+
166
+   9. Accepting Warranty or Additional Liability. While redistributing
167
+      the Work or Derivative Works thereof, You may choose to offer,
168
+      and charge a fee for, acceptance of support, warranty, indemnity,
169
+      or other liability obligations and/or rights consistent with this
170
+      License. However, in accepting such obligations, You may act only
171
+      on Your own behalf and on Your sole responsibility, not on behalf
172
+      of any other Contributor, and only if You agree to indemnify,
173
+      defend, and hold each Contributor harmless for any liability
174
+      incurred by, or claims asserted against, such Contributor by reason
175
+      of your accepting any such warranty or additional liability.

+ 0
- 4
README.md View File

@@ -1,4 +0,0 @@
1
-mistral-dashboard
2
-=================
3
-
4
-OpenStack dashboard for Mistral project

+ 33
- 0
README.rst View File

@@ -0,0 +1,33 @@
1
+=================
2
+Mistral Dashboard
3
+=================
4
+
5
+Horizon plugin for Mistral.
6
+
7
+Setup Instructions
8
+==================
9
+
10
+The following should get you started::
11
+
12
+    $ git clone https://github.com/stackforge/mistral-dashboard.git
13
+    $ cd mistral-dashboard
14
+    $ cp mistraldashboard/local/local_settings.py.example \
15
+      mistraldashboard/local/local_settings.py
16
+
17
+Edit the ``local_settings.py`` file as needed. Make sure you have changed
18
+OPENSTACK_HOST to point to your keystone server and also check all endpoints
19
+are accessible. You may want to change OPENSTACK_ENDPOINT_TYPE to "publicURL"
20
+if some of your endpoints are inaccessible.
21
+
22
+You may also need to add a service and endpoints to keystone::
23
+
24
+    $ MISTRAL_URL="http://[host]:[port]/v1"
25
+    $ keystone service-create --name mistral --type workflow
26
+    $ keystone endpoint-create --service_id mistral --publicurl $MISTRAL_URL \
27
+      --adminurl $MISTRAL_URL --internalurl $MISTRAL_URL
28
+
29
+When you're ready to run the development server::
30
+
31
+    $ tox -evenv -- python manage.py runserver
32
+
33
+

+ 62
- 0
doc/source/conf.py View File

@@ -0,0 +1,62 @@
1
+# -*- coding: utf-8 -*-
2
+# Licensed under the Apache License, Version 2.0 (the "License");
3
+# you may not use this file except in compliance with the License.
4
+# You may obtain a copy of the License at
5
+#
6
+# http://www.apache.org/licenses/LICENSE-2.0
7
+#
8
+# Unless required by applicable law or agreed to in writing, software
9
+# distributed under the License is distributed on an "AS IS" BASIS,
10
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
11
+# implied.
12
+# See the License for the specific language governing permissions and
13
+# limitations under the License.
14
+
15
+import os
16
+import sys
17
+
18
+sys.path.insert(0, os.path.abspath('../..'))
19
+# -- General configuration ----------------------------------------------------
20
+
21
+# Add any Sphinx extension module names here, as strings. They can be
22
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
23
+extensions = [
24
+    'sphinx.ext.autodoc',
25
+    'sphinx.ext.intersphinx',
26
+    'oslosphinx',
27
+]
28
+
29
+# autodoc generation is a bit aggressive and a nuisance when doing heavy
30
+# text edit cycles.
31
+# execute "export SPHINX_DEBUG=1" in your terminal to disable
32
+
33
+# The suffix of source filenames.
34
+source_suffix = '.rst'
35
+
36
+# The master toctree document.
37
+master_doc = 'index'
38
+
39
+# General information about the project.
40
+project = u'mistral-dashboard'
41
+copyright = u'2014, OpenStack Foundation'
42
+
43
+# If true, '()' will be appended to :func: etc. cross-reference text.
44
+add_function_parentheses = True
45
+
46
+# If true, the current module name will be prepended to all description
47
+# unit titles (such as .. function::).
48
+add_module_names = True
49
+
50
+# The name of the Pygments (syntax highlighting) style to use.
51
+pygments_style = 'sphinx'
52
+
53
+# -- Options for HTML output --------------------------------------------------
54
+
55
+# The theme to use for HTML and HTML Help pages. Major themes that come with
56
+# Sphinx are currently 'default' and 'sphinxdoc'.
57
+# html_theme_path = ["."]
58
+# html_theme = '_theme'
59
+# html_static_path = []
60
+
61
+# Output file base name for HTML help builder.
62
+htmlhelp_basename = '%sdoc' % project

+ 1
- 0
doc/source/index.rst View File

@@ -0,0 +1 @@
1
+.. include:: ../../README.rst

+ 23
- 0
manage.py View File

@@ -0,0 +1,23 @@
1
+#!/usr/bin/env python
2
+
3
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+# not use this file except in compliance with the License. You may obtain
5
+# a copy of the License at
6
+#
7
+#      http://www.apache.org/licenses/LICENSE-2.0
8
+#
9
+# Unless required by applicable law or agreed to in writing, software
10
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+# License for the specific language governing permissions and limitations
13
+# under the License.
14
+
15
+import os
16
+import sys
17
+
18
+from django.core.management import execute_from_command_line  # noqa
19
+
20
+if __name__ == "__main__":
21
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE",
22
+                          "mistraldashboard.settings")
23
+    execute_from_command_line(sys.argv)

+ 0
- 0
mistraldashboard/__init__.py View File


+ 0
- 0
mistraldashboard/dashboards/__init__.py View File


+ 0
- 0
mistraldashboard/dashboards/mistral/__init__.py View File


+ 37
- 0
mistraldashboard/dashboards/mistral/api.py View File

@@ -0,0 +1,37 @@
1
+# -*- coding: utf-8 -*-
2
+#
3
+# Copyright 2014 - StackStorm, Inc.
4
+#
5
+# Licensed under the Apache License, Version 2.0 (the "License");
6
+# you may not use this file except in compliance with the License.
7
+# You may obtain a copy of the License at
8
+#
9
+# http://www.apache.org/licenses/LICENSE-2.0
10
+#
11
+# Unless required by applicable law or agreed to in writing, software
12
+# distributed under the License is distributed on an "AS IS" BASIS,
13
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+from django.conf import settings
18
+
19
+from mistralclient.api import client as mistral_client
20
+
21
+SERVICE_TYPE = 'workflow'
22
+
23
+
24
+def mistralclient(request):
25
+    return mistral_client.Client(
26
+        username=request.user.username,
27
+        auth_token=request.user.token.id,
28
+        project_id=request.user.tenant_id,
29
+        # Ideally, we should get it from identity endpoint, but since
30
+        # python-mistralclient is not supporting v2.0 API it might create
31
+        # additional troubles for those who still rely on v2.0 stack-wise.
32
+        auth_url=getattr(settings, 'OPENSTACK_KEYSTONE_URL'),
33
+        # Todo: add SECONDARY_ENDPOINT_TYPE support
34
+        endpoint_type=getattr(settings,
35
+                              'OPENSTACK_ENDPOINT_TYPE',
36
+                              'internalURL'),
37
+        service_type=SERVICE_TYPE)

+ 38
- 0
mistraldashboard/dashboards/mistral/dashboard.py View File

@@ -0,0 +1,38 @@
1
+# -*- coding: utf-8 -*-
2
+#
3
+# Copyright 2014 - StackStorm, Inc.
4
+#
5
+# Licensed under the Apache License, Version 2.0 (the "License");
6
+# you may not use this file except in compliance with the License.
7
+# You may obtain a copy of the License at
8
+#
9
+# http://www.apache.org/licenses/LICENSE-2.0
10
+#
11
+# Unless required by applicable law or agreed to in writing, software
12
+# distributed under the License is distributed on an "AS IS" BASIS,
13
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+from django.utils.translation import ugettext_lazy as _
18
+
19
+import horizon
20
+
21
+
22
+class Default(horizon.Panel):
23
+    name = _("Default")
24
+    slug = 'default'
25
+    urls = 'mistraldashboard.dashboards.mistral.workbooks.urls'
26
+    nav = False
27
+
28
+
29
+class MistralDashboard(horizon.Dashboard):
30
+    name = _("Mistral")
31
+    slug = "mistral"
32
+    panels = ('default', 'workbooks', 'executions',)
33
+    default_panel = 'default'
34
+    roles = ('admin',)
35
+
36
+
37
+horizon.register(MistralDashboard)
38
+MistralDashboard.register(Default)

+ 0
- 0
mistraldashboard/dashboards/mistral/executions/__init__.py View File


+ 28
- 0
mistraldashboard/dashboards/mistral/executions/panel.py View File

@@ -0,0 +1,28 @@
1
+# -*- coding: utf-8 -*-
2
+#
3
+# Copyright 2014 - StackStorm, Inc.
4
+#
5
+# Licensed under the Apache License, Version 2.0 (the "License");
6
+# you may not use this file except in compliance with the License.
7
+# You may obtain a copy of the License at
8
+#
9
+# http://www.apache.org/licenses/LICENSE-2.0
10
+#
11
+# Unless required by applicable law or agreed to in writing, software
12
+# distributed under the License is distributed on an "AS IS" BASIS,
13
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+from django.utils.translation import ugettext_lazy as _
18
+
19
+import horizon
20
+from mistraldashboard.dashboards.mistral import dashboard
21
+
22
+
23
+class Executions(horizon.Panel):
24
+    name = _("Executions")
25
+    slug = 'executions'
26
+
27
+
28
+dashboard.MistralDashboard.register(Executions)

+ 42
- 0
mistraldashboard/dashboards/mistral/executions/tables.py View File

@@ -0,0 +1,42 @@
1
+# -*- coding: utf-8 -*-
2
+#
3
+# Copyright 2014 - StackStorm, Inc.
4
+#
5
+# Licensed under the Apache License, Version 2.0 (the "License");
6
+# you may not use this file except in compliance with the License.
7
+# You may obtain a copy of the License at
8
+#
9
+# http://www.apache.org/licenses/LICENSE-2.0
10
+#
11
+# Unless required by applicable law or agreed to in writing, software
12
+# distributed under the License is distributed on an "AS IS" BASIS,
13
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+from django.utils.translation import ugettext_lazy as _
18
+
19
+from horizon import tables
20
+
21
+
22
+class ExecutionsTable(tables.DataTable):
23
+    id = tables.Column("id",
24
+                       verbose_name=_("ID"),
25
+                       link=("horizon:mistral:executions:tasks"))
26
+    wb_name = tables.Column("workbook_name", verbose_name=_("Workbook"))
27
+    state = tables.Column("state", verbose_name=_("State"))
28
+
29
+    class Meta:
30
+        name = "executions"
31
+        verbose_name = _("Executions")
32
+
33
+
34
+class TaskTable(tables.DataTable):
35
+    id = tables.Column("id", verbose_name=_("ID"))
36
+    name = tables.Column("name", verbose_name=_("Name"))
37
+    action = tables.Column("action", verbose_name=_("Action"))
38
+    state = tables.Column("state", verbose_name=_("State"))
39
+
40
+    class Meta:
41
+        name = "tasks"
42
+        verbose_name = _("Tasks")

+ 11
- 0
mistraldashboard/dashboards/mistral/executions/templates/executions/index.html View File

@@ -0,0 +1,11 @@
1
+{% extends 'base.html' %}
2
+{% load i18n %}
3
+{% block title %}{% trans "Executions" %}{% endblock %}
4
+
5
+{% block page_header %}
6
+  {% include "horizon/common/_page_header.html" with title=_("Executions") %}
7
+{% endblock page_header %}
8
+
9
+{% block main %}
10
+  {{ table.render }}
11
+{% endblock %}

+ 29
- 0
mistraldashboard/dashboards/mistral/executions/urls.py View File

@@ -0,0 +1,29 @@
1
+# -*- coding: utf-8 -*-
2
+#
3
+# Copyright 2014 - StackStorm, Inc.
4
+#
5
+# Licensed under the Apache License, Version 2.0 (the "License");
6
+# you may not use this file except in compliance with the License.
7
+# You may obtain a copy of the License at
8
+#
9
+# http://www.apache.org/licenses/LICENSE-2.0
10
+#
11
+# Unless required by applicable law or agreed to in writing, software
12
+# distributed under the License is distributed on an "AS IS" BASIS,
13
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+from django.conf.urls import patterns  # noqa
18
+from django.conf.urls import url  # noqa
19
+
20
+from mistraldashboard.dashboards.mistral.executions.views import IndexView
21
+from mistraldashboard.dashboards.mistral.executions.views import TaskView
22
+
23
+EXECUTIONS = r'^(?P<execution_id>[^/]+)/%s$'
24
+
25
+urlpatterns = patterns(
26
+    '',
27
+    url(r'^$', IndexView.as_view(), name='index'),
28
+    url(EXECUTIONS % 'tasks', TaskView.as_view(), name='tasks'),
29
+)

+ 43
- 0
mistraldashboard/dashboards/mistral/executions/views.py View File

@@ -0,0 +1,43 @@
1
+# -*- coding: utf-8 -*-
2
+#
3
+# Copyright 2014 - StackStorm, Inc.
4
+#
5
+# Licensed under the Apache License, Version 2.0 (the "License");
6
+# you may not use this file except in compliance with the License.
7
+# You may obtain a copy of the License at
8
+#
9
+# http://www.apache.org/licenses/LICENSE-2.0
10
+#
11
+# Unless required by applicable law or agreed to in writing, software
12
+# distributed under the License is distributed on an "AS IS" BASIS,
13
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+from horizon import tables
18
+
19
+from mistraldashboard.dashboards.mistral import api
20
+from mistraldashboard.dashboards.mistral.executions.tables \
21
+    import ExecutionsTable
22
+from mistraldashboard.dashboards.mistral.executions.tables import TaskTable
23
+
24
+
25
+class IndexView(tables.DataTableView):
26
+    table_class = ExecutionsTable
27
+    template_name = 'mistral/executions/index.html'
28
+
29
+    def get_data(self):
30
+        client = api.mistralclient(self.request)
31
+        return [item for wb in client.workbooks.list()
32
+                for item in client.executions.list(wb.name)]
33
+
34
+
35
+class TaskView(tables.DataTableView):
36
+    table_class = TaskTable
37
+    template_name = 'mistral/executions/index.html'
38
+
39
+    def get_data(self):
40
+        client = api.mistralclient(self.request)
41
+        return [item for wb in client.workbooks.list()
42
+                for item in client.tasks.list(wb.name,
43
+                                              self.kwargs['execution_id'])]

+ 0
- 0
mistraldashboard/dashboards/mistral/workbooks/__init__.py View File


+ 63
- 0
mistraldashboard/dashboards/mistral/workbooks/forms.py View File

@@ -0,0 +1,63 @@
1
+# -*- coding: utf-8 -*-
2
+#
3
+# Copyright 2014 - StackStorm, Inc.
4
+#
5
+# Licensed under the Apache License, Version 2.0 (the "License");
6
+# you may not use this file except in compliance with the License.
7
+# You may obtain a copy of the License at
8
+#
9
+# http://www.apache.org/licenses/LICENSE-2.0
10
+#
11
+# Unless required by applicable law or agreed to in writing, software
12
+# distributed under the License is distributed on an "AS IS" BASIS,
13
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+from django.utils.translation import ugettext_lazy as _
18
+from django.core.urlresolvers import reverse
19
+import yaml
20
+
21
+from horizon import exceptions
22
+from horizon import forms
23
+from horizon import messages
24
+
25
+from mistraldashboard.dashboards.mistral import api
26
+
27
+
28
+class ExecuteForm(forms.SelfHandlingForm):
29
+    workbook_name = forms.CharField(label=_("Workbook"),
30
+                                    required=True,
31
+                                    widget=forms.TextInput(
32
+                                        attrs={'readonly': 'readonly'}))
33
+    task = forms.ChoiceField(label=_("Task"),
34
+                             required=True,
35
+                             help_text=_("Task to start the execution"))
36
+    context = forms.CharField(label=_("Context"),
37
+                              required=False,
38
+                              initial="{}",
39
+                              widget=forms.widgets.Textarea())
40
+
41
+    def __init__(self, request, *args, **kwargs):
42
+        super(ExecuteForm, self).__init__(request, *args, **kwargs)
43
+        client = api.mistralclient(request)
44
+        workbook_definition = client.workbooks.get_definition(
45
+            kwargs['initial']['workbook_name'])
46
+        workbook = yaml.safe_load(workbook_definition)
47
+
48
+        task_choices = [('', _("Select a task"))]
49
+        for task in workbook['Workflow']['tasks']:
50
+            task_choices.append((task, task))
51
+        self.fields['task'].choices = task_choices
52
+
53
+    def handle(self, request, data):
54
+        try:
55
+            ex = api.mistralclient(request).executions.create(**data)
56
+
57
+            msg = _('Execution has been created with id "%s".') % ex.id
58
+            messages.success(request, msg)
59
+            return True
60
+        except Exception:
61
+            msg = _('Failed to execute workbook "%s".') % data['workbook_name']
62
+            redirect = reverse('horizon:mistral:workbooks:index')
63
+            exceptions.handle(request, msg, redirect=redirect)

+ 29
- 0
mistraldashboard/dashboards/mistral/workbooks/panel.py View File

@@ -0,0 +1,29 @@
1
+# -*- coding: utf-8 -*-
2
+#
3
+# Copyright 2014 - StackStorm, Inc.
4
+#
5
+# Licensed under the Apache License, Version 2.0 (the "License");
6
+# you may not use this file except in compliance with the License.
7
+# You may obtain a copy of the License at
8
+#
9
+# http://www.apache.org/licenses/LICENSE-2.0
10
+#
11
+# Unless required by applicable law or agreed to in writing, software
12
+# distributed under the License is distributed on an "AS IS" BASIS,
13
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+from django.utils.translation import ugettext_lazy as _
18
+
19
+import horizon
20
+
21
+from mistraldashboard.dashboards.mistral import dashboard
22
+
23
+
24
+class Workbooks(horizon.Panel):
25
+    name = _("Workbooks")
26
+    slug = 'workbooks'
27
+
28
+
29
+dashboard.MistralDashboard.register(Workbooks)

+ 44
- 0
mistraldashboard/dashboards/mistral/workbooks/tables.py View File

@@ -0,0 +1,44 @@
1
+# -*- coding: utf-8 -*-
2
+#
3
+# Copyright 2014 - StackStorm, Inc.
4
+#
5
+# Licensed under the Apache License, Version 2.0 (the "License");
6
+# you may not use this file except in compliance with the License.
7
+# You may obtain a copy of the License at
8
+#
9
+# http://www.apache.org/licenses/LICENSE-2.0
10
+#
11
+# Unless required by applicable law or agreed to in writing, software
12
+# distributed under the License is distributed on an "AS IS" BASIS,
13
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+from django.utils.translation import ugettext_lazy as _
18
+
19
+from horizon import tables
20
+
21
+
22
+class ExecuteWorkflow(tables.LinkAction):
23
+    name = "execute"
24
+    verbose_name = _("Execute")
25
+    url = "horizon:mistral:workbooks:execute"
26
+    classes = ("ajax-modal", "btn-edit")
27
+
28
+
29
+def tags_to_string(workbook):
30
+    return ', '.join(workbook.tags)
31
+
32
+
33
+class WorkbooksTable(tables.DataTable):
34
+    name = tables.Column("name", verbose_name=_("Name"))
35
+    description = tables.Column("description", verbose_name=_("Description"))
36
+    tags = tables.Column(tags_to_string, verbose_name=_("Tags"))
37
+
38
+    def get_object_id(self, datum):
39
+        return datum.name
40
+
41
+    class Meta:
42
+        name = "workbooks"
43
+        verbose_name = _("Workbooks")
44
+        row_actions = (ExecuteWorkflow,)

+ 25
- 0
mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/_execute.html View File

@@ -0,0 +1,25 @@
1
+{% extends "horizon/common/_modal_form.html" %}
2
+{% load i18n %}
3
+{% load url from future %}
4
+
5
+{% block form_id %}execute_form{% endblock %}
6
+{% block form_action %}{% url 'horizon:mistral:workbooks:execute' workbook_name %}{% endblock %}
7
+
8
+{% block modal-header %}{% trans "Execute" %}{% endblock %}
9
+
10
+{% block modal-body %}
11
+<div class="left">
12
+    <fieldset>
13
+    {% include "horizon/common/_form_fields.html" %}
14
+    </fieldset>
15
+</div>
16
+<div class="right">
17
+    <h3>{% trans "Description:" %}</h3>
18
+    <p>{% trans "From here you can execute a workbook." %}</p>
19
+</div>
20
+{% endblock %}
21
+
22
+{% block modal-footer %}
23
+  <input class="btn btn-primary pull-right" type="submit" value="{% trans "Execute" %}" />
24
+  <a href="{% url 'horizon:mistral:workbooks:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
25
+{% endblock %}

+ 11
- 0
mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/execute.html View File

@@ -0,0 +1,11 @@
1
+{% extends 'base.html' %}
2
+{% load i18n %}
3
+{% block title %}{% trans "Execute workbook" %}{% endblock %}
4
+
5
+{% block page_header %}
6
+  {% include "horizon/common/_page_header.html" with title=_("Execute workbook") %}
7
+{% endblock page_header %}
8
+
9
+{% block main %}
10
+  {% include 'mistral/workbooks/_execute.html' %}
11
+{% endblock %}

+ 11
- 0
mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/index.html View File

@@ -0,0 +1,11 @@
1
+{% extends 'base.html' %}
2
+{% load i18n %}
3
+{% block title %}{% trans "Workbooks" %}{% endblock %}
4
+
5
+{% block page_header %}
6
+  {% include "horizon/common/_page_header.html" with title=_("Workbooks") %}
7
+{% endblock page_header %}
8
+
9
+{% block main %}
10
+  {{ table.render }}
11
+{% endblock %}

+ 29
- 0
mistraldashboard/dashboards/mistral/workbooks/urls.py View File

@@ -0,0 +1,29 @@
1
+# -*- coding: utf-8 -*-
2
+#
3
+# Copyright 2014 - StackStorm, Inc.
4
+#
5
+# Licensed under the Apache License, Version 2.0 (the "License");
6
+# you may not use this file except in compliance with the License.
7
+# You may obtain a copy of the License at
8
+#
9
+# http://www.apache.org/licenses/LICENSE-2.0
10
+#
11
+# Unless required by applicable law or agreed to in writing, software
12
+# distributed under the License is distributed on an "AS IS" BASIS,
13
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+from django.conf.urls import patterns  # noqa
18
+from django.conf.urls import url  # noqa
19
+
20
+from mistraldashboard.dashboards.mistral.workbooks.views import IndexView
21
+from mistraldashboard.dashboards.mistral.workbooks.views import ExecuteView
22
+
23
+WORKBOOKS = r'^(?P<workbook_name>[^/]+)/%s$'
24
+
25
+urlpatterns = patterns(
26
+    '',
27
+    url(r'^$', IndexView.as_view(), name='index'),
28
+    url(WORKBOOKS % 'execute', ExecuteView.as_view(), name='execute'),
29
+)

+ 48
- 0
mistraldashboard/dashboards/mistral/workbooks/views.py View File

@@ -0,0 +1,48 @@
1
+# -*- coding: utf-8 -*-
2
+#
3
+# Copyright 2014 - StackStorm, Inc.
4
+#
5
+# Licensed under the Apache License, Version 2.0 (the "License");
6
+# you may not use this file except in compliance with the License.
7
+# You may obtain a copy of the License at
8
+#
9
+# http://www.apache.org/licenses/LICENSE-2.0
10
+#
11
+# Unless required by applicable law or agreed to in writing, software
12
+# distributed under the License is distributed on an "AS IS" BASIS,
13
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+from django.core.urlresolvers import reverse_lazy
18
+
19
+from horizon import tables
20
+from horizon import forms
21
+
22
+from mistraldashboard.dashboards.mistral import api
23
+from mistraldashboard.dashboards.mistral.workbooks.tables import WorkbooksTable
24
+from mistraldashboard.dashboards.mistral.workbooks.forms import ExecuteForm
25
+
26
+
27
+class IndexView(tables.DataTableView):
28
+    table_class = WorkbooksTable
29
+    template_name = 'mistral/workbooks/index.html'
30
+
31
+    def get_data(self):
32
+        return api.mistralclient(self.request).workbooks.list()
33
+
34
+
35
+class ExecuteView(forms.ModalFormView):
36
+    form_class = ExecuteForm
37
+    template_name = 'mistral/workbooks/execute.html'
38
+    success_url = reverse_lazy("horizon:mistral:executions:index")
39
+
40
+    def get_context_data(self, **kwargs):
41
+        context = super(ExecuteView, self).get_context_data(**kwargs)
42
+        context["workbook_name"] = self.kwargs['workbook_name']
43
+        return context
44
+
45
+    def get_initial(self, **kwargs):
46
+        return {
47
+            'workbook_name': self.kwargs['workbook_name']
48
+        }

+ 0
- 0
mistraldashboard/local/__init__.py View File


+ 488
- 0
mistraldashboard/local/local_settings.py.example View File

@@ -0,0 +1,488 @@
1
+import os
2
+
3
+from django.utils.translation import ugettext_lazy as _
4
+
5
+from openstack_dashboard import exceptions
6
+
7
+DEBUG = True
8
+TEMPLATE_DEBUG = DEBUG
9
+
10
+# Required for Django 1.5.
11
+# If horizon is running in production (DEBUG is False), set this
12
+# with the list of host/domain names that the application can serve.
13
+# For more information see:
14
+# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
15
+#ALLOWED_HOSTS = ['horizon.example.com', ]
16
+
17
+# Set SSL proxy settings:
18
+# For Django 1.4+ pass this header from the proxy after terminating the SSL,
19
+# and don't forget to strip it from the client's request.
20
+# For more information see:
21
+# https://docs.djangoproject.com/en/1.4/ref/settings/#secure-proxy-ssl-header
22
+# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
23
+
24
+# If Horizon is being served through SSL, then uncomment the following two
25
+# settings to better secure the cookies from security exploits
26
+#CSRF_COOKIE_SECURE = True
27
+#SESSION_COOKIE_SECURE = True
28
+
29
+# Overrides for OpenStack API versions. Use this setting to force the
30
+# OpenStack dashboard to use a specific API version for a given service API.
31
+# NOTE: The version should be formatted as it appears in the URL for the
32
+# service API. For example, The identity service APIs have inconsistent
33
+# use of the decimal point, so valid options would be "2.0" or "3".
34
+# OPENSTACK_API_VERSIONS = {
35
+#     "identity": 3,
36
+#     "volume": 2
37
+# }
38
+
39
+# Set this to True if running on multi-domain model. When this is enabled, it
40
+# will require user to enter the Domain name in addition to username for login.
41
+# OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = False
42
+
43
+# Overrides the default domain used when running on single-domain model
44
+# with Keystone V3. All entities will be created in the default domain.
45
+# OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'Default'
46
+
47
+# Set Console type:
48
+# valid options would be "AUTO", "VNC", "SPICE" or "RDP"
49
+# CONSOLE_TYPE = "AUTO"
50
+
51
+# Default OpenStack Dashboard configuration.
52
+HORIZON_CONFIG = {
53
+    'dashboards': ('project', 'admin', 'settings',),
54
+    'default_dashboard': 'project',
55
+    'user_home': 'openstack_dashboard.views.get_user_home',
56
+    'ajax_queue_limit': 10,
57
+    'auto_fade_alerts': {
58
+        'delay': 3000,
59
+        'fade_duration': 1500,
60
+        'types': ['alert-success', 'alert-info']
61
+    },
62
+    'help_url': "http://docs.openstack.org",
63
+    'exceptions': {'recoverable': exceptions.RECOVERABLE,
64
+                   'not_found': exceptions.NOT_FOUND,
65
+                   'unauthorized': exceptions.UNAUTHORIZED},
66
+}
67
+
68
+# Specify a regular expression to validate user passwords.
69
+# HORIZON_CONFIG["password_validator"] = {
70
+#     "regex": '.*',
71
+#     "help_text": _("Your password does not meet the requirements.")
72
+# }
73
+
74
+# Disable simplified floating IP address management for deployments with
75
+# multiple floating IP pools or complex network requirements.
76
+# HORIZON_CONFIG["simple_ip_management"] = False
77
+
78
+# Turn off browser autocompletion for the login form if so desired.
79
+# HORIZON_CONFIG["password_autocomplete"] = "off"
80
+
81
+LOCAL_PATH = os.path.dirname(os.path.abspath(__file__))
82
+
83
+# Set custom secret key:
84
+# You can either set it to a specific value or you can let horizion generate a
85
+# default secret key that is unique on this machine, e.i. regardless of the
86
+# amount of Python WSGI workers (if used behind Apache+mod_wsgi): However,
87
+# there may be situations where you would want to set this explicitly, e.g.
88
+# when multiple dashboard instances are distributed on different machines
89
+# (usually behind a load-balancer). Either you have to make sure that a session
90
+# gets all requests routed to the same dashboard instance or you set the same
91
+# SECRET_KEY for all of them.
92
+from horizon.utils import secret_key
93
+SECRET_KEY = secret_key.generate_or_read_from_file(
94
+    os.path.join(LOCAL_PATH, '.secret_key_store'))
95
+
96
+# We recommend you use memcached for development; otherwise after every reload
97
+# of the django development server, you will have to login again. To use
98
+# memcached set CACHES to something like
99
+# CACHES = {
100
+#    'default': {
101
+#        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
102
+#        'LOCATION': '127.0.0.1:11211',
103
+#    }
104
+#}
105
+
106
+CACHES = {
107
+    'default': {
108
+        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'
109
+    }
110
+}
111
+
112
+# Send email to the console by default
113
+EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
114
+# Or send them to /dev/null
115
+#EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'
116
+
117
+# Configure these for your outgoing email host
118
+# EMAIL_HOST = 'smtp.my-company.com'
119
+# EMAIL_PORT = 25
120
+# EMAIL_HOST_USER = 'djangomail'
121
+# EMAIL_HOST_PASSWORD = 'top-secret!'
122
+
123
+# For multiple regions uncomment this configuration, and add (endpoint, title).
124
+# AVAILABLE_REGIONS = [
125
+#     ('http://cluster1.example.com:5000/v2.0', 'cluster1'),
126
+#     ('http://cluster2.example.com:5000/v2.0', 'cluster2'),
127
+# ]
128
+
129
+OPENSTACK_HOST = "172.16.80.200"
130
+OPENSTACK_KEYSTONE_URL = "http://%s:5000/v2.0" % OPENSTACK_HOST
131
+OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_"
132
+
133
+# Disable SSL certificate checks (useful for self-signed certificates):
134
+# OPENSTACK_SSL_NO_VERIFY = True
135
+
136
+# The CA certificate to use to verify SSL connections
137
+# OPENSTACK_SSL_CACERT = '/path/to/cacert.pem'
138
+
139
+# The OPENSTACK_KEYSTONE_BACKEND settings can be used to identify the
140
+# capabilities of the auth backend for Keystone.
141
+# If Keystone has been configured to use LDAP as the auth backend then set
142
+# can_edit_user to False and name to 'ldap'.
143
+#
144
+# TODO(tres): Remove these once Keystone has an API to identify auth backend.
145
+OPENSTACK_KEYSTONE_BACKEND = {
146
+    'name': 'native',
147
+    'can_edit_user': True,
148
+    'can_edit_group': True,
149
+    'can_edit_project': True,
150
+    'can_edit_domain': True,
151
+    'can_edit_role': True
152
+}
153
+
154
+#Setting this to True, will add a new "Retrieve Password" action on instance,
155
+#allowing Admin session password retrieval/decryption.
156
+#OPENSTACK_ENABLE_PASSWORD_RETRIEVE = False
157
+
158
+# The Xen Hypervisor has the ability to set the mount point for volumes
159
+# attached to instances (other Hypervisors currently do not). Setting
160
+# can_set_mount_point to True will add the option to set the mount point
161
+# from the UI.
162
+OPENSTACK_HYPERVISOR_FEATURES = {
163
+    'can_set_mount_point': False,
164
+    'can_set_password': False,
165
+}
166
+
167
+# The OPENSTACK_NEUTRON_NETWORK settings can be used to enable optional
168
+# services provided by neutron. Options currently available are load
169
+# balancer service, security groups, quotas, VPN service.
170
+OPENSTACK_NEUTRON_NETWORK = {
171
+    'enable_lb': False,
172
+    'enable_firewall': False,
173
+    'enable_quotas': True,
174
+    'enable_vpn': False,
175
+    # The profile_support option is used to detect if an external router can be
176
+    # configured via the dashboard. When using specific plugins the
177
+    # profile_support can be turned on if needed.
178
+    'profile_support': None,
179
+    #'profile_support': 'cisco',
180
+}
181
+
182
+# The OPENSTACK_IMAGE_BACKEND settings can be used to customize features
183
+# in the OpenStack Dashboard related to the Image service, such as the list
184
+# of supported image formats.
185
+# OPENSTACK_IMAGE_BACKEND = {
186
+#     'image_formats': [
187
+#         ('', ''),
188
+#         ('aki', _('AKI - Amazon Kernel Image')),
189
+#         ('ami', _('AMI - Amazon Machine Image')),
190
+#         ('ari', _('ARI - Amazon Ramdisk Image')),
191
+#         ('iso', _('ISO - Optical Disk Image')),
192
+#         ('qcow2', _('QCOW2 - QEMU Emulator')),
193
+#         ('raw', _('Raw')),
194
+#         ('vdi', _('VDI')),
195
+#         ('vhd', _('VHD')),
196
+#         ('vmdk', _('VMDK'))
197
+#     ]
198
+# }
199
+
200
+# The IMAGE_CUSTOM_PROPERTY_TITLES settings is used to customize the titles for
201
+# image custom property attributes that appear on image detail pages.
202
+IMAGE_CUSTOM_PROPERTY_TITLES = {
203
+    "architecture": _("Architecture"),
204
+    "kernel_id": _("Kernel ID"),
205
+    "ramdisk_id": _("Ramdisk ID"),
206
+    "image_state": _("Euca2ools state"),
207
+    "project_id": _("Project ID"),
208
+    "image_type": _("Image Type")
209
+}
210
+
211
+# OPENSTACK_ENDPOINT_TYPE specifies the endpoint type to use for the endpoints
212
+# in the Keystone service catalog. Use this setting when Horizon is running
213
+# external to the OpenStack environment. The default is 'publicURL'.
214
+#OPENSTACK_ENDPOINT_TYPE = "publicURL"
215
+
216
+# SECONDARY_ENDPOINT_TYPE specifies the fallback endpoint type to use in the
217
+# case that OPENSTACK_ENDPOINT_TYPE is not present in the endpoints
218
+# in the Keystone service catalog. Use this setting when Horizon is running
219
+# external to the OpenStack environment. The default is None.  This
220
+# value should differ from OPENSTACK_ENDPOINT_TYPE if used.
221
+#SECONDARY_ENDPOINT_TYPE = "publicURL"
222
+
223
+# The number of objects (Swift containers/objects or images) to display
224
+# on a single page before providing a paging element (a "more" link)
225
+# to paginate results.
226
+API_RESULT_LIMIT = 1000
227
+API_RESULT_PAGE_SIZE = 20
228
+
229
+# The timezone of the server. This should correspond with the timezone
230
+# of your entire OpenStack installation, and hopefully be in UTC.
231
+TIME_ZONE = "UTC"
232
+
233
+# When launching an instance, the menu of available flavors is
234
+# sorted by RAM usage, ascending. If you would like a different sort order,
235
+# you can provide another flavor attribute as sorting key. Alternatively, you
236
+# can provide a custom callback method to use for sorting. You can also provide
237
+# a flag for reverse sort. For more info, see
238
+# http://docs.python.org/2/library/functions.html#sorted
239
+# CREATE_INSTANCE_FLAVOR_SORT = {
240
+#     'key': 'name',
241
+#      # or
242
+#     'key': my_awesome_callback_method,
243
+#     'reverse': False,
244
+# }
245
+
246
+# The Horizon Policy Enforcement engine uses these values to load per service
247
+# policy rule files. The content of these files should match the files the
248
+# OpenStack services are using to determine role based access control in the
249
+# target installation.
250
+
251
+# Path to directory containing policy.json files
252
+#POLICY_FILES_PATH = os.path.join(ROOT_PATH, "conf")
253
+# Map of local copy of service policy files
254
+#POLICY_FILES = {
255
+#    'identity': 'keystone_policy.json',
256
+#    'compute': 'nova_policy.json'
257
+#}
258
+
259
+# Trove user and database extension support. By default support for
260
+# creating users and databases on database instances is turned on.
261
+# To disable these extensions set the permission here to something
262
+# unusable such as ["!"].
263
+# TROVE_ADD_USER_PERMS = []
264
+# TROVE_ADD_DATABASE_PERMS = []
265
+
266
+LOGGING = {
267
+    'version': 1,
268
+    # When set to True this will disable all logging except
269
+    # for loggers specified in this configuration dictionary. Note that
270
+    # if nothing is specified here and disable_existing_loggers is True,
271
+    # django.db.backends will still log unless it is disabled explicitly.
272
+    'disable_existing_loggers': False,
273
+    'handlers': {
274
+        'null': {
275
+            'level': 'DEBUG',
276
+            'class': 'django.utils.log.NullHandler',
277
+        },
278
+        'console': {
279
+            # Set the level to "DEBUG" for verbose output logging.
280
+            'level': 'INFO',
281
+            'class': 'logging.StreamHandler',
282
+        },
283
+    },
284
+    'loggers': {
285
+        # Logging from django.db.backends is VERY verbose, send to null
286
+        # by default.
287
+        'django.db.backends': {
288
+            'handlers': ['null'],
289
+            'propagate': False,
290
+        },
291
+        'requests': {
292
+            'handlers': ['null'],
293
+            'propagate': False,
294
+        },
295
+        'horizon': {
296
+            'handlers': ['console'],
297
+            'level': 'DEBUG',
298
+            'propagate': False,
299
+        },
300
+        'openstack_dashboard': {
301
+            'handlers': ['console'],
302
+            'level': 'DEBUG',
303
+            'propagate': False,
304
+        },
305
+        'novaclient': {
306
+            'handlers': ['console'],
307
+            'level': 'DEBUG',
308
+            'propagate': False,
309
+        },
310
+        'cinderclient': {
311
+            'handlers': ['console'],
312
+            'level': 'DEBUG',
313
+            'propagate': False,
314
+        },
315
+        'keystoneclient': {
316
+            'handlers': ['console'],
317
+            'level': 'DEBUG',
318
+            'propagate': False,
319
+        },
320
+        'glanceclient': {
321
+            'handlers': ['console'],
322
+            'level': 'DEBUG',
323
+            'propagate': False,
324
+        },
325
+        'neutronclient': {
326
+            'handlers': ['console'],
327
+            'level': 'DEBUG',
328
+            'propagate': False,
329
+        },
330
+        'heatclient': {
331
+            'handlers': ['console'],
332
+            'level': 'DEBUG',
333
+            'propagate': False,
334
+        },
335
+        'ceilometerclient': {
336
+            'handlers': ['console'],
337
+            'level': 'DEBUG',
338
+            'propagate': False,
339
+        },
340
+        'troveclient': {
341
+            'handlers': ['console'],
342
+            'level': 'DEBUG',
343
+            'propagate': False,
344
+        },
345
+        'swiftclient': {
346
+            'handlers': ['console'],
347
+            'level': 'DEBUG',
348
+            'propagate': False,
349
+        },
350
+        'openstack_auth': {
351
+            'handlers': ['console'],
352
+            'level': 'DEBUG',
353
+            'propagate': False,
354
+        },
355
+        'nose.plugins.manager': {
356
+            'handlers': ['console'],
357
+            'level': 'DEBUG',
358
+            'propagate': False,
359
+        },
360
+        'django': {
361
+            'handlers': ['console'],
362
+            'level': 'DEBUG',
363
+            'propagate': False,
364
+        },
365
+        'iso8601': {
366
+            'handlers': ['null'],
367
+            'propagate': False,
368
+        },
369
+    }
370
+}
371
+
372
+# 'direction' should not be specified for all_tcp/udp/icmp.
373
+# It is specified in the form.
374
+SECURITY_GROUP_RULES = {
375
+    'all_tcp': {
376
+        'name': 'ALL TCP',
377
+        'ip_protocol': 'tcp',
378
+        'from_port': '1',
379
+        'to_port': '65535',
380
+    },
381
+    'all_udp': {
382
+        'name': 'ALL UDP',
383
+        'ip_protocol': 'udp',
384
+        'from_port': '1',
385
+        'to_port': '65535',
386
+    },
387
+    'all_icmp': {
388
+        'name': 'ALL ICMP',
389
+        'ip_protocol': 'icmp',
390
+        'from_port': '-1',
391
+        'to_port': '-1',
392
+    },
393
+    'ssh': {
394
+        'name': 'SSH',
395
+        'ip_protocol': 'tcp',
396
+        'from_port': '22',
397
+        'to_port': '22',
398
+    },
399
+    'smtp': {
400
+        'name': 'SMTP',
401
+        'ip_protocol': 'tcp',
402
+        'from_port': '25',
403
+        'to_port': '25',
404
+    },
405
+    'dns': {
406
+        'name': 'DNS',
407
+        'ip_protocol': 'tcp',
408
+        'from_port': '53',
409
+        'to_port': '53',
410
+    },
411
+    'http': {
412
+        'name': 'HTTP',
413
+        'ip_protocol': 'tcp',
414
+        'from_port': '80',
415
+        'to_port': '80',
416
+    },
417
+    'pop3': {
418
+        'name': 'POP3',
419
+        'ip_protocol': 'tcp',
420
+        'from_port': '110',
421
+        'to_port': '110',
422
+    },
423
+    'imap': {
424
+        'name': 'IMAP',
425
+        'ip_protocol': 'tcp',
426
+        'from_port': '143',
427
+        'to_port': '143',
428
+    },
429
+    'ldap': {
430
+        'name': 'LDAP',
431
+        'ip_protocol': 'tcp',
432
+        'from_port': '389',
433
+        'to_port': '389',
434
+    },
435
+    'https': {
436
+        'name': 'HTTPS',
437
+        'ip_protocol': 'tcp',
438
+        'from_port': '443',
439
+        'to_port': '443',
440
+    },
441
+    'smtps': {
442
+        'name': 'SMTPS',
443
+        'ip_protocol': 'tcp',
444
+        'from_port': '465',
445
+        'to_port': '465',
446
+    },
447
+    'imaps': {
448
+        'name': 'IMAPS',
449
+        'ip_protocol': 'tcp',
450
+        'from_port': '993',
451
+        'to_port': '993',
452
+    },
453
+    'pop3s': {
454
+        'name': 'POP3S',
455
+        'ip_protocol': 'tcp',
456
+        'from_port': '995',
457
+        'to_port': '995',
458
+    },
459
+    'ms_sql': {
460
+        'name': 'MS SQL',
461
+        'ip_protocol': 'tcp',
462
+        'from_port': '1433',
463
+        'to_port': '1433',
464
+    },
465
+    'mysql': {
466
+        'name': 'MYSQL',
467
+        'ip_protocol': 'tcp',
468
+        'from_port': '3306',
469
+        'to_port': '3306',
470
+    },
471
+    'rdp': {
472
+        'name': 'RDP',
473
+        'ip_protocol': 'tcp',
474
+        'from_port': '3389',
475
+        'to_port': '3389',
476
+    },
477
+}
478
+
479
+FLAVOR_EXTRA_KEYS = {
480
+    'flavor_keys': [
481
+        ('quota:read_bytes_sec', _('Quota: Read bytes')),
482
+        ('quota:write_bytes_sec', _('Quota: Write bytes')),
483
+        ('quota:cpu_quota', _('Quota: CPU')),
484
+        ('quota:cpu_period', _('Quota: CPU period')),
485
+        ('quota:inbound_average', _('Quota: Inbound average')),
486
+        ('quota:outbound_average', _('Quota: Outbound average')),
487
+    ]
488
+}

+ 3
- 0
mistraldashboard/models.py View File

@@ -0,0 +1,3 @@
1
+"""
2
+Stub file to work around django bug: https://code.djangoproject.com/ticket/7198
3
+"""

+ 263
- 0
mistraldashboard/settings.py View File

@@ -0,0 +1,263 @@
1
+# Copyright 2012 United States Government as represented by the
2
+# Administrator of the National Aeronautics and Space Administration.
3
+# All Rights Reserved.
4
+#
5
+# Copyright 2012 Nebula, Inc.
6
+#
7
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
8
+#    not use this file except in compliance with the License. You may obtain
9
+#    a copy of the License at
10
+#
11
+#         http://www.apache.org/licenses/LICENSE-2.0
12
+#
13
+#    Unless required by applicable law or agreed to in writing, software
14
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
+#    License for the specific language governing permissions and limitations
17
+#    under the License.
18
+
19
+import logging
20
+import os
21
+import sys
22
+import warnings
23
+
24
+from django.utils.translation import ugettext_lazy as _
25
+
26
+from openstack_dashboard import exceptions
27
+
28
+warnings.formatwarning = lambda message, category, *args, **kwargs: \
29
+    '%s: %s' % (category.__name__, message)
30
+
31
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
32
+BIN_DIR = os.path.abspath(os.path.join(ROOT_PATH, '..', 'bin'))
33
+
34
+if ROOT_PATH not in sys.path:
35
+    sys.path.append(ROOT_PATH)
36
+
37
+DEBUG = False
38
+TEMPLATE_DEBUG = DEBUG
39
+
40
+SITE_BRANDING = 'OpenStack Dashboard'
41
+
42
+LOGIN_URL = '/auth/login/'
43
+LOGOUT_URL = '/auth/logout/'
44
+# LOGIN_REDIRECT_URL can be used as an alternative for
45
+# HORIZON_CONFIG.user_home, if user_home is not set.
46
+# Do not set it to '/home/', as this will cause circular redirect loop
47
+LOGIN_REDIRECT_URL = '/'
48
+
49
+MEDIA_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'media'))
50
+MEDIA_URL = '/media/'
51
+STATIC_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'static'))
52
+STATIC_URL = '/static/'
53
+
54
+ROOT_URLCONF = 'openstack_dashboard.urls'
55
+
56
+HORIZON_CONFIG = {
57
+    'dashboards': ('project', 'admin', 'mistral',
58
+                   'settings', 'router',),
59
+    'default_dashboard': 'project',
60
+    'user_home': 'openstack_dashboard.views.get_user_home',
61
+    'ajax_queue_limit': 10,
62
+    'auto_fade_alerts': {
63
+        'delay': 3000,
64
+        'fade_duration': 1500,
65
+        'types': ['alert-success', 'alert-info']
66
+    },
67
+    'help_url': "http://docs.openstack.org",
68
+    'exceptions': {'recoverable': exceptions.RECOVERABLE,
69
+                   'not_found': exceptions.NOT_FOUND,
70
+                   'unauthorized': exceptions.UNAUTHORIZED},
71
+}
72
+
73
+# Set to True to allow users to upload images to glance via Horizon server.
74
+# When enabled, a file form field will appear on the create image form.
75
+# See documentation for deployment considerations.
76
+HORIZON_IMAGES_ALLOW_UPLOAD = True
77
+
78
+# The OPENSTACK_IMAGE_BACKEND settings can be used to customize features
79
+# in the OpenStack Dashboard related to the Image service, such as the list
80
+# of supported image formats.
81
+OPENSTACK_IMAGE_BACKEND = {
82
+    'image_formats': [
83
+        ('', ''),
84
+        ('aki', _('AKI - Amazon Kernel Image')),
85
+        ('ami', _('AMI - Amazon Machine Image')),
86
+        ('ari', _('ARI - Amazon Ramdisk Image')),
87
+        ('iso', _('ISO - Optical Disk Image')),
88
+        ('qcow2', _('QCOW2 - QEMU Emulator')),
89
+        ('raw', _('Raw')),
90
+        ('vdi', _('VDI')),
91
+        ('vhd', _('VHD')),
92
+        ('vmdk', _('VMDK'))
93
+    ]
94
+}
95
+
96
+MIDDLEWARE_CLASSES = (
97
+    'django.middleware.common.CommonMiddleware',
98
+    'django.middleware.csrf.CsrfViewMiddleware',
99
+    'django.contrib.sessions.middleware.SessionMiddleware',
100
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
101
+    'django.contrib.messages.middleware.MessageMiddleware',
102
+    'horizon.middleware.HorizonMiddleware',
103
+    'django.middleware.doc.XViewMiddleware',
104
+    'django.middleware.locale.LocaleMiddleware',
105
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
106
+)
107
+
108
+TEMPLATE_CONTEXT_PROCESSORS = (
109
+    'django.core.context_processors.debug',
110
+    'django.core.context_processors.i18n',
111
+    'django.core.context_processors.request',
112
+    'django.core.context_processors.media',
113
+    'django.core.context_processors.static',
114
+    'django.contrib.messages.context_processors.messages',
115
+    'horizon.context_processors.horizon',
116
+    'openstack_dashboard.context_processors.openstack',
117
+)
118
+
119
+TEMPLATE_LOADERS = (
120
+    'django.template.loaders.filesystem.Loader',
121
+    'django.template.loaders.app_directories.Loader',
122
+    'horizon.loaders.TemplateLoader'
123
+)
124
+
125
+TEMPLATE_DIRS = (
126
+    os.path.join(ROOT_PATH, 'templates'),
127
+)
128
+
129
+STATICFILES_FINDERS = (
130
+    'compressor.finders.CompressorFinder',
131
+    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
132
+)
133
+
134
+COMPRESS_PRECOMPILERS = (
135
+    ('text/less', ('lesscpy {infile}')),
136
+)
137
+
138
+COMPRESS_CSS_FILTERS = (
139
+    'compressor.filters.css_default.CssAbsoluteFilter',
140
+)
141
+
142
+COMPRESS_ENABLED = True
143
+COMPRESS_OUTPUT_DIR = 'dashboard'
144
+COMPRESS_CSS_HASHING_METHOD = 'hash'
145
+COMPRESS_PARSER = 'compressor.parser.HtmlParser'
146
+
147
+INSTALLED_APPS = [
148
+    'openstack_dashboard',
149
+    'django.contrib.contenttypes',
150
+    'django.contrib.auth',
151
+    'django.contrib.sessions',
152
+    'django.contrib.messages',
153
+    'django.contrib.staticfiles',
154
+    'django.contrib.humanize',
155
+    'compressor',
156
+    'horizon',
157
+    'openstack_auth',
158
+    'mistraldashboard.dashboards.mistral'
159
+]
160
+
161
+TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
162
+AUTHENTICATION_BACKENDS = ('openstack_auth.backend.KeystoneBackend',)
163
+MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
164
+
165
+SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
166
+SESSION_COOKIE_HTTPONLY = True
167
+SESSION_EXPIRE_AT_BROWSER_CLOSE = True
168
+SESSION_COOKIE_SECURE = False
169
+SESSION_TIMEOUT = 1800
170
+
171
+# When using cookie-based sessions, log error when the session cookie exceeds
172
+# the following size (common browsers drop cookies above a certain size):
173
+SESSION_COOKIE_MAX_SIZE = 4093
174
+
175
+# when doing upgrades, it may be wise to stick to PickleSerializer
176
+# TODO(mrunge): remove after Icehouse
177
+SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
178
+
179
+LANGUAGES = (
180
+    ('de', 'German'),
181
+    ('en', 'English'),
182
+    ('en-au', 'Australian English'),
183
+    ('en-gb', 'British English'),
184
+    ('es', 'Spanish'),
185
+    ('fr', 'French'),
186
+    ('hi', 'Hindi'),
187
+    ('ja', 'Japanese'),
188
+    ('ko', 'Korean (Korea)'),
189
+    ('nl', 'Dutch (Netherlands)'),
190
+    ('pl', 'Polish'),
191
+    ('pt-br', 'Portuguese (Brazil)'),
192
+    ('sr', 'Serbian'),
193
+    ('zh-cn', 'Simplified Chinese'),
194
+    ('zh-tw', 'Chinese (Taiwan)'),
195
+)
196
+LANGUAGE_CODE = 'en'
197
+LANGUAGE_COOKIE_NAME = 'horizon_language'
198
+USE_I18N = True
199
+USE_L10N = True
200
+USE_TZ = True
201
+
202
+OPENSTACK_KEYSTONE_DEFAULT_ROLE = '_member_'
203
+
204
+DEFAULT_EXCEPTION_REPORTER_FILTER = 'horizon.exceptions.HorizonReporterFilter'
205
+
206
+POLICY_FILES_PATH = os.path.join(ROOT_PATH, "conf")
207
+# Map of local copy of service policy files
208
+POLICY_FILES = {
209
+    'identity': 'keystone_policy.json',
210
+    'compute': 'nova_policy.json',
211
+    'volume': 'cinder_policy.json',
212
+    'image': 'glance_policy.json',
213
+}
214
+
215
+SECRET_KEY = None
216
+LOCAL_PATH = None
217
+
218
+try:
219
+    from local.local_settings import *  # noqa
220
+except ImportError:
221
+    logging.warning("No local_settings file found.")
222
+
223
+# Load the pluggable dashboard settings
224
+import openstack_dashboard.enabled
225
+import openstack_dashboard.local.enabled
226
+from openstack_dashboard.utils import settings
227
+
228
+INSTALLED_APPS = list(INSTALLED_APPS)  # Make sure it's mutable
229
+settings.update_dashboards([
230
+    openstack_dashboard.enabled,
231
+    openstack_dashboard.local.enabled,
232
+], HORIZON_CONFIG, INSTALLED_APPS)
233
+
234
+# Ensure that we always have a SECRET_KEY set, even when no local_settings.py
235
+# file is present. See local_settings.py.example for full documentation on the
236
+# horizon.utils.secret_key module and its use.
237
+if not SECRET_KEY:
238
+    if not LOCAL_PATH:
239
+        LOCAL_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)),
240
+                                  'local')
241
+
242
+    from horizon.utils import secret_key
243
+    SECRET_KEY = secret_key.generate_or_read_from_file(os.path.join(LOCAL_PATH,
244
+                                                       '.secret_key_store'))
245
+
246
+from openstack_dashboard import policy
247
+POLICY_CHECK_FUNCTION = policy.check
248
+
249
+# Add HORIZON_CONFIG to the context information for offline compression
250
+COMPRESS_OFFLINE_CONTEXT = {
251
+    'STATIC_URL': STATIC_URL,
252
+    'HORIZON_CONFIG': HORIZON_CONFIG
253
+}
254
+
255
+if DEBUG:
256
+    logging.basicConfig(level=logging.DEBUG)
257
+
258
+# during django reloads and an active user is logged in, the monkey
259
+# patch below will not otherwise be applied in time - resulting in developers
260
+# appearing to be logged out.  In typical production deployments this section
261
+# below may be ommited, though it should not be harmful
262
+from openstack_auth import utils as auth_utils
263
+auth_utils.patch_middleware_get_user()

+ 3
- 0
requirements.txt View File

@@ -0,0 +1,3 @@
1
+-e git+https://github.com/openstack/horizon.git#egg=horizon
2
+-e git+https://github.com/stackforge/python-mistralclient.git#egg=python-mistralclient
3
+PyYAML>=3.1.0

+ 29
- 0
setup.cfg View File

@@ -0,0 +1,29 @@
1
+[metadata]
2
+name = mistral-dashboard
3
+summary = Mistral dashboard
4
+description-file = README.rst
5
+license = Apache License, Version 2.0
6
+classifiers =
7
+    Programming Language :: Python
8
+    Programming Language :: Python :: 2
9
+    Programming Language :: Python :: 2.7
10
+    Environment :: OpenStack
11
+    Intended Audience :: Information Technology
12
+    Intended Audience :: System Administrators
13
+    License :: OSI Approved :: Apache Software License
14
+    Operating System :: POSIX :: Linux
15
+author = Openstack Mistral Team
16
+author-email = openstack-dev@lists.openstack.org
17
+
18
+[global]
19
+setup-hooks =
20
+    pbr.hooks.setup_hook
21
+
22
+[files]
23
+packages =
24
+    mistraldashboard
25
+
26
+[build_sphinx]
27
+source-dir = doc/source
28
+build-dir = doc/build
29
+all_files = 1

+ 30
- 0
setup.py View File

@@ -0,0 +1,30 @@
1
+#!/usr/bin/env python
2
+# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
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
13
+# implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
18
+import setuptools
19
+
20
+# In python < 2.7.4, a lazy loading of package `pbr` will break
21
+# setuptools if some other modules registered functions in `atexit`.
22
+# solution from: http://bugs.python.org/issue15881#msg170215
23
+try:
24
+    import multiprocessing  # noqa
25
+except ImportError:
26
+    pass
27
+
28
+setuptools.setup(
29
+    setup_requires=['pbr'],
30
+    pbr=True)

+ 4
- 0
test-requirements.txt View File

@@ -0,0 +1,4 @@
1
+pep8==1.4.5
2
+flake8==2.0
3
+sphinx>=1.1.2
4
+oslosphinx

+ 26
- 0
tox.ini View File

@@ -0,0 +1,26 @@
1
+[tox]
2
+envlist = pep8
3
+minversion = 1.6
4
+skipsdist = True
5
+
6
+[testenv]
7
+usedevelop = True
8
+setenv = VIRTUAL_ENV={envdir}
9
+         DJANGO_SETTINGS_MODULE=mistraldashboard.settings
10
+deps = -r{toxinidir}/requirements.txt
11
+       -r{toxinidir}/test-requirements.txt
12
+
13
+[testenv:pep8]
14
+commands = flake8 {posargs}
15
+
16
+[testenv:venv]
17
+commands = {posargs}
18
+
19
+[testenv:docs]
20
+commands = python setup.py build_sphinx
21
+
22
+[flake8]
23
+show-source = true
24
+ignore = H101,H302,H306,H803
25
+builtins = _
26
+exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,tools,local_settings.py

Loading…
Cancel
Save