summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Izotov <enykeev@stackstorm.com>2014-06-10 18:41:02 +0700
committerKirill Izotov <enykeev@stackstorm.com>2014-06-17 13:53:16 +0700
commit28bde7a23059e0426e1d7e6855375345299c1f3f (patch)
tree852267a50cf950bd05116c407293166930c2f3fe
parent551d292cdaedf2cb4d7ac062e074cec3d1718e56 (diff)
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
Notes
Notes (review): Verified+2: Jenkins Code-Review+2: Renat Akhmerov <rakhmerov@mirantis.com> Workflow+1: Renat Akhmerov <rakhmerov@mirantis.com> Code-Review+2: Dmitri Zimine <dz@stackstorm.com> Submitted-by: Jenkins Submitted-at: Wed, 18 Jun 2014 04:39:36 +0000 Reviewed-on: https://review.openstack.org/99014 Project: stackforge/mistral-dashboard Branch: refs/heads/master
-rw-r--r--.gitignore42
-rw-r--r--LICENSE175
-rw-r--r--README.md4
-rw-r--r--README.rst33
-rw-r--r--doc/source/conf.py62
-rw-r--r--doc/source/index.rst1
-rwxr-xr-xmanage.py23
-rw-r--r--mistraldashboard/__init__.py0
-rw-r--r--mistraldashboard/dashboards/__init__.py0
-rw-r--r--mistraldashboard/dashboards/mistral/__init__.py0
-rw-r--r--mistraldashboard/dashboards/mistral/api.py37
-rw-r--r--mistraldashboard/dashboards/mistral/dashboard.py38
-rw-r--r--mistraldashboard/dashboards/mistral/executions/__init__.py0
-rw-r--r--mistraldashboard/dashboards/mistral/executions/panel.py28
-rw-r--r--mistraldashboard/dashboards/mistral/executions/tables.py42
-rw-r--r--mistraldashboard/dashboards/mistral/executions/templates/executions/index.html11
-rw-r--r--mistraldashboard/dashboards/mistral/executions/urls.py29
-rw-r--r--mistraldashboard/dashboards/mistral/executions/views.py43
-rw-r--r--mistraldashboard/dashboards/mistral/workbooks/__init__.py0
-rw-r--r--mistraldashboard/dashboards/mistral/workbooks/forms.py63
-rw-r--r--mistraldashboard/dashboards/mistral/workbooks/panel.py29
-rw-r--r--mistraldashboard/dashboards/mistral/workbooks/tables.py44
-rw-r--r--mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/_execute.html25
-rw-r--r--mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/execute.html11
-rw-r--r--mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/index.html11
-rw-r--r--mistraldashboard/dashboards/mistral/workbooks/urls.py29
-rw-r--r--mistraldashboard/dashboards/mistral/workbooks/views.py48
-rw-r--r--mistraldashboard/local/__init__.py0
-rw-r--r--mistraldashboard/local/local_settings.py.example488
-rw-r--r--mistraldashboard/models.py3
-rw-r--r--mistraldashboard/settings.py263
-rw-r--r--requirements.txt3
-rw-r--r--setup.cfg29
-rw-r--r--setup.py30
-rw-r--r--test-requirements.txt4
-rw-r--r--tox.ini26
36 files changed, 1670 insertions, 4 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..10e4d87
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,42 @@
1*.py[cod]
2*.sqlite
3
4# C extensions
5*.so
6
7# Packages
8*.egg
9*.egg-info
10dist
11build
12.venv
13eggs
14parts
15bin
16var
17sdist
18develop-eggs
19.installed.cfg
20lib
21lib64
22
23# Installer logs
24pip-log.txt
25
26# Unit test / coverage reports
27.coverage
28.tox
29nosetests.xml
30
31# Translations
32*.mo
33
34# Mr Developer
35.mr.developer.cfg
36.project
37.pydevproject
38.idea
39.DS_Store
40mistraldashboard/local/local_settings.py
41mistraldashboard/local/.secret_key_store
42static
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..67db858
--- /dev/null
+++ b/LICENSE
@@ -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.
diff --git a/README.md b/README.md
deleted file mode 100644
index 48dcf68..0000000
--- a/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
1mistral-dashboard
2=================
3
4OpenStack dashboard for Mistral project
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..b3abb0b
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,33 @@
1=================
2Mistral Dashboard
3=================
4
5Horizon plugin for Mistral.
6
7Setup Instructions
8==================
9
10The 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
17Edit the ``local_settings.py`` file as needed. Make sure you have changed
18OPENSTACK_HOST to point to your keystone server and also check all endpoints
19are accessible. You may want to change OPENSTACK_ENDPOINT_TYPE to "publicURL"
20if some of your endpoints are inaccessible.
21
22You 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
29When you're ready to run the development server::
30
31 $ tox -evenv -- python manage.py runserver
32
33
diff --git a/doc/source/conf.py b/doc/source/conf.py
new file mode 100644
index 0000000..59ec8bd
--- /dev/null
+++ b/doc/source/conf.py
@@ -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
15import os
16import sys
17
18sys.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.
23extensions = [
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.
34source_suffix = '.rst'
35
36# The master toctree document.
37master_doc = 'index'
38
39# General information about the project.
40project = u'mistral-dashboard'
41copyright = u'2014, OpenStack Foundation'
42
43# If true, '()' will be appended to :func: etc. cross-reference text.
44add_function_parentheses = True
45
46# If true, the current module name will be prepended to all description
47# unit titles (such as .. function::).
48add_module_names = True
49
50# The name of the Pygments (syntax highlighting) style to use.
51pygments_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.
62htmlhelp_basename = '%sdoc' % project
diff --git a/doc/source/index.rst b/doc/source/index.rst
new file mode 100644
index 0000000..38ba804
--- /dev/null
+++ b/doc/source/index.rst
@@ -0,0 +1 @@
.. include:: ../../README.rst \ No newline at end of file
diff --git a/manage.py b/manage.py
new file mode 100755
index 0000000..4ce8bb5
--- /dev/null
+++ b/manage.py
@@ -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
15import os
16import sys
17
18from django.core.management import execute_from_command_line # noqa
19
20if __name__ == "__main__":
21 os.environ.setdefault("DJANGO_SETTINGS_MODULE",
22 "mistraldashboard.settings")
23 execute_from_command_line(sys.argv)
diff --git a/mistraldashboard/__init__.py b/mistraldashboard/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mistraldashboard/__init__.py
diff --git a/mistraldashboard/dashboards/__init__.py b/mistraldashboard/dashboards/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mistraldashboard/dashboards/__init__.py
diff --git a/mistraldashboard/dashboards/mistral/__init__.py b/mistraldashboard/dashboards/mistral/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/__init__.py
diff --git a/mistraldashboard/dashboards/mistral/api.py b/mistraldashboard/dashboards/mistral/api.py
new file mode 100644
index 0000000..32b80ff
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/api.py
@@ -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
17from django.conf import settings
18
19from mistralclient.api import client as mistral_client
20
21SERVICE_TYPE = 'workflow'
22
23
24def 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)
diff --git a/mistraldashboard/dashboards/mistral/dashboard.py b/mistraldashboard/dashboards/mistral/dashboard.py
new file mode 100644
index 0000000..b0e34d2
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/dashboard.py
@@ -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
17from django.utils.translation import ugettext_lazy as _
18
19import horizon
20
21
22class Default(horizon.Panel):
23 name = _("Default")
24 slug = 'default'
25 urls = 'mistraldashboard.dashboards.mistral.workbooks.urls'
26 nav = False
27
28
29class MistralDashboard(horizon.Dashboard):
30 name = _("Mistral")
31 slug = "mistral"
32 panels = ('default', 'workbooks', 'executions',)
33 default_panel = 'default'
34 roles = ('admin',)
35
36
37horizon.register(MistralDashboard)
38MistralDashboard.register(Default)
diff --git a/mistraldashboard/dashboards/mistral/executions/__init__.py b/mistraldashboard/dashboards/mistral/executions/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/executions/__init__.py
diff --git a/mistraldashboard/dashboards/mistral/executions/panel.py b/mistraldashboard/dashboards/mistral/executions/panel.py
new file mode 100644
index 0000000..e42a595
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/executions/panel.py
@@ -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
17from django.utils.translation import ugettext_lazy as _
18
19import horizon
20from mistraldashboard.dashboards.mistral import dashboard
21
22
23class Executions(horizon.Panel):
24 name = _("Executions")
25 slug = 'executions'
26
27
28dashboard.MistralDashboard.register(Executions)
diff --git a/mistraldashboard/dashboards/mistral/executions/tables.py b/mistraldashboard/dashboards/mistral/executions/tables.py
new file mode 100644
index 0000000..4549331
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/executions/tables.py
@@ -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
17from django.utils.translation import ugettext_lazy as _
18
19from horizon import tables
20
21
22class 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
34class 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")
diff --git a/mistraldashboard/dashboards/mistral/executions/templates/executions/index.html b/mistraldashboard/dashboards/mistral/executions/templates/executions/index.html
new file mode 100644
index 0000000..864a4d4
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/executions/templates/executions/index.html
@@ -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 %}
diff --git a/mistraldashboard/dashboards/mistral/executions/urls.py b/mistraldashboard/dashboards/mistral/executions/urls.py
new file mode 100644
index 0000000..8d9b875
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/executions/urls.py
@@ -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
17from django.conf.urls import patterns # noqa
18from django.conf.urls import url # noqa
19
20from mistraldashboard.dashboards.mistral.executions.views import IndexView
21from mistraldashboard.dashboards.mistral.executions.views import TaskView
22
23EXECUTIONS = r'^(?P<execution_id>[^/]+)/%s$'
24
25urlpatterns = patterns(
26 '',
27 url(r'^$', IndexView.as_view(), name='index'),
28 url(EXECUTIONS % 'tasks', TaskView.as_view(), name='tasks'),
29)
diff --git a/mistraldashboard/dashboards/mistral/executions/views.py b/mistraldashboard/dashboards/mistral/executions/views.py
new file mode 100644
index 0000000..f8ecc5f
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/executions/views.py
@@ -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
17from horizon import tables
18
19from mistraldashboard.dashboards.mistral import api
20from mistraldashboard.dashboards.mistral.executions.tables \
21 import ExecutionsTable
22from mistraldashboard.dashboards.mistral.executions.tables import TaskTable
23
24
25class 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
35class 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'])]
diff --git a/mistraldashboard/dashboards/mistral/workbooks/__init__.py b/mistraldashboard/dashboards/mistral/workbooks/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/workbooks/__init__.py
diff --git a/mistraldashboard/dashboards/mistral/workbooks/forms.py b/mistraldashboard/dashboards/mistral/workbooks/forms.py
new file mode 100644
index 0000000..5e4a261
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/workbooks/forms.py
@@ -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
17from django.utils.translation import ugettext_lazy as _
18from django.core.urlresolvers import reverse
19import yaml
20
21from horizon import exceptions
22from horizon import forms
23from horizon import messages
24
25from mistraldashboard.dashboards.mistral import api
26
27
28class 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)
diff --git a/mistraldashboard/dashboards/mistral/workbooks/panel.py b/mistraldashboard/dashboards/mistral/workbooks/panel.py
new file mode 100644
index 0000000..9065a57
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/workbooks/panel.py
@@ -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
17from django.utils.translation import ugettext_lazy as _
18
19import horizon
20
21from mistraldashboard.dashboards.mistral import dashboard
22
23
24class Workbooks(horizon.Panel):
25 name = _("Workbooks")
26 slug = 'workbooks'
27
28
29dashboard.MistralDashboard.register(Workbooks)
diff --git a/mistraldashboard/dashboards/mistral/workbooks/tables.py b/mistraldashboard/dashboards/mistral/workbooks/tables.py
new file mode 100644
index 0000000..25b3319
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/workbooks/tables.py
@@ -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
17from django.utils.translation import ugettext_lazy as _
18
19from horizon import tables
20
21
22class ExecuteWorkflow(tables.LinkAction):
23 name = "execute"
24 verbose_name = _("Execute")
25 url = "horizon:mistral:workbooks:execute"
26 classes = ("ajax-modal", "btn-edit")
27
28
29def tags_to_string(workbook):
30 return ', '.join(workbook.tags)
31
32
33class 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,)
diff --git a/mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/_execute.html b/mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/_execute.html
new file mode 100644
index 0000000..94d3267
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/_execute.html
@@ -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 %}
diff --git a/mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/execute.html b/mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/execute.html
new file mode 100644
index 0000000..848d6c9
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/execute.html
@@ -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 %}
diff --git a/mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/index.html b/mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/index.html
new file mode 100644
index 0000000..a7094d5
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/workbooks/templates/workbooks/index.html
@@ -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 %}
diff --git a/mistraldashboard/dashboards/mistral/workbooks/urls.py b/mistraldashboard/dashboards/mistral/workbooks/urls.py
new file mode 100644
index 0000000..a262a40
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/workbooks/urls.py
@@ -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
17from django.conf.urls import patterns # noqa
18from django.conf.urls import url # noqa
19
20from mistraldashboard.dashboards.mistral.workbooks.views import IndexView
21from mistraldashboard.dashboards.mistral.workbooks.views import ExecuteView
22
23WORKBOOKS = r'^(?P<workbook_name>[^/]+)/%s$'
24
25urlpatterns = patterns(
26 '',
27 url(r'^$', IndexView.as_view(), name='index'),
28 url(WORKBOOKS % 'execute', ExecuteView.as_view(), name='execute'),
29)
diff --git a/mistraldashboard/dashboards/mistral/workbooks/views.py b/mistraldashboard/dashboards/mistral/workbooks/views.py
new file mode 100644
index 0000000..71f1840
--- /dev/null
+++ b/mistraldashboard/dashboards/mistral/workbooks/views.py
@@ -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
17from django.core.urlresolvers import reverse_lazy
18
19from horizon import tables
20from horizon import forms
21
22from mistraldashboard.dashboards.mistral import api
23from mistraldashboard.dashboards.mistral.workbooks.tables import WorkbooksTable
24from mistraldashboard.dashboards.mistral.workbooks.forms import ExecuteForm
25
26
27class 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
35class 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 }
diff --git a/mistraldashboard/local/__init__.py b/mistraldashboard/local/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mistraldashboard/local/__init__.py
diff --git a/mistraldashboard/local/local_settings.py.example b/mistraldashboard/local/local_settings.py.example
new file mode 100644
index 0000000..d9960d0
--- /dev/null
+++ b/mistraldashboard/local/local_settings.py.example
@@ -0,0 +1,488 @@
1import os
2
3from django.utils.translation import ugettext_lazy as _
4
5from openstack_dashboard import exceptions
6
7DEBUG = True
8TEMPLATE_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.
52HORIZON_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
81LOCAL_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.
92from horizon.utils import secret_key
93SECRET_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
106CACHES = {
107 'default': {
108 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'
109 }
110}
111
112# Send email to the console by default
113EMAIL_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
129OPENSTACK_HOST = "172.16.80.200"
130OPENSTACK_KEYSTONE_URL = "http://%s:5000/v2.0" % OPENSTACK_HOST
131OPENSTACK_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.
145OPENSTACK_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.
162OPENSTACK_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.
170OPENSTACK_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.
202IMAGE_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.
226API_RESULT_LIMIT = 1000
227API_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.
231TIME_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
266LOGGING = {
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.
374SECURITY_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
479FLAVOR_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}
diff --git a/mistraldashboard/models.py b/mistraldashboard/models.py
new file mode 100644
index 0000000..1b3d5f9
--- /dev/null
+++ b/mistraldashboard/models.py
@@ -0,0 +1,3 @@
1"""
2Stub file to work around django bug: https://code.djangoproject.com/ticket/7198
3"""
diff --git a/mistraldashboard/settings.py b/mistraldashboard/settings.py
new file mode 100644
index 0000000..aeadbac
--- /dev/null
+++ b/mistraldashboard/settings.py
@@ -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
19import logging
20import os
21import sys
22import warnings
23
24from django.utils.translation import ugettext_lazy as _
25
26from openstack_dashboard import exceptions
27
28warnings.formatwarning = lambda message, category, *args, **kwargs: \
29 '%s: %s' % (category.__name__, message)
30
31ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
32BIN_DIR = os.path.abspath(os.path.join(ROOT_PATH, '..', 'bin'))
33
34if ROOT_PATH not in sys.path:
35 sys.path.append(ROOT_PATH)
36
37DEBUG = False
38TEMPLATE_DEBUG = DEBUG
39
40SITE_BRANDING = 'OpenStack Dashboard'
41
42LOGIN_URL = '/auth/login/'
43LOGOUT_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
47LOGIN_REDIRECT_URL = '/'
48
49MEDIA_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'media'))
50MEDIA_URL = '/media/'
51STATIC_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'static'))
52STATIC_URL = '/static/'
53
54ROOT_URLCONF = 'openstack_dashboard.urls'
55
56HORIZON_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.
76HORIZON_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.
81OPENSTACK_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
96MIDDLEWARE_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
108TEMPLATE_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
119TEMPLATE_LOADERS = (
120 'django.template.loaders.filesystem.Loader',
121 'django.template.loaders.app_directories.Loader',
122 'horizon.loaders.TemplateLoader'
123)
124
125TEMPLATE_DIRS = (
126 os.path.join(ROOT_PATH, 'templates'),
127)
128
129STATICFILES_FINDERS = (
130 'compressor.finders.CompressorFinder',
131 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
132)
133
134COMPRESS_PRECOMPILERS = (
135 ('text/less', ('lesscpy {infile}')),
136)
137
138COMPRESS_CSS_FILTERS = (
139 'compressor.filters.css_default.CssAbsoluteFilter',
140)
141
142COMPRESS_ENABLED = True
143COMPRESS_OUTPUT_DIR = 'dashboard'
144COMPRESS_CSS_HASHING_METHOD = 'hash'
145COMPRESS_PARSER = 'compressor.parser.HtmlParser'
146
147INSTALLED_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
161TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
162AUTHENTICATION_BACKENDS = ('openstack_auth.backend.KeystoneBackend',)
163MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
164
165SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
166SESSION_COOKIE_HTTPONLY = True
167SESSION_EXPIRE_AT_BROWSER_CLOSE = True
168SESSION_COOKIE_SECURE = False
169SESSION_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):
173SESSION_COOKIE_MAX_SIZE = 4093
174
175# when doing upgrades, it may be wise to stick to PickleSerializer
176# TODO(mrunge): remove after Icehouse
177SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
178
179LANGUAGES = (
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)
196LANGUAGE_CODE = 'en'
197LANGUAGE_COOKIE_NAME = 'horizon_language'
198USE_I18N = True
199USE_L10N = True
200USE_TZ = True
201
202OPENSTACK_KEYSTONE_DEFAULT_ROLE = '_member_'
203
204DEFAULT_EXCEPTION_REPORTER_FILTER = 'horizon.exceptions.HorizonReporterFilter'
205
206POLICY_FILES_PATH = os.path.join(ROOT_PATH, "conf")
207# Map of local copy of service policy files
208POLICY_FILES = {
209 'identity': 'keystone_policy.json',
210 'compute': 'nova_policy.json',
211 'volume': 'cinder_policy.json',
212 'image': 'glance_policy.json',
213}
214
215SECRET_KEY = None
216LOCAL_PATH = None
217
218try:
219 from local.local_settings import * # noqa
220except ImportError:
221 logging.warning("No local_settings file found.")
222
223# Load the pluggable dashboard settings
224import openstack_dashboard.enabled
225import openstack_dashboard.local.enabled
226from openstack_dashboard.utils import settings
227
228INSTALLED_APPS = list(INSTALLED_APPS) # Make sure it's mutable
229settings.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.
237if 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
246from openstack_dashboard import policy
247POLICY_CHECK_FUNCTION = policy.check
248
249# Add HORIZON_CONFIG to the context information for offline compression
250COMPRESS_OFFLINE_CONTEXT = {
251 'STATIC_URL': STATIC_URL,
252 'HORIZON_CONFIG': HORIZON_CONFIG
253}
254
255if 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
262from openstack_auth import utils as auth_utils
263auth_utils.patch_middleware_get_user()
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..16f9b48
--- /dev/null
+++ b/requirements.txt
@@ -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
3PyYAML>=3.1.0 \ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..a4206e9
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,29 @@
1[metadata]
2name = mistral-dashboard
3summary = Mistral dashboard
4description-file = README.rst
5license = Apache License, Version 2.0
6classifiers =
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
15author = Openstack Mistral Team
16author-email = openstack-dev@lists.openstack.org
17
18[global]
19setup-hooks =
20 pbr.hooks.setup_hook
21
22[files]
23packages =
24 mistraldashboard
25
26[build_sphinx]
27source-dir = doc/source
28build-dir = doc/build
29all_files = 1
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..10ec121
--- /dev/null
+++ b/setup.py
@@ -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
18import 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
23try:
24 import multiprocessing # noqa
25except ImportError:
26 pass
27
28setuptools.setup(
29 setup_requires=['pbr'],
30 pbr=True)
diff --git a/test-requirements.txt b/test-requirements.txt
new file mode 100644
index 0000000..2fa2aa7
--- /dev/null
+++ b/test-requirements.txt
@@ -0,0 +1,4 @@
1pep8==1.4.5
2flake8==2.0
3sphinx>=1.1.2
4oslosphinx
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..94a3f58
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,26 @@
1[tox]
2envlist = pep8
3minversion = 1.6
4skipsdist = True
5
6[testenv]
7usedevelop = True
8setenv = VIRTUAL_ENV={envdir}
9 DJANGO_SETTINGS_MODULE=mistraldashboard.settings
10deps = -r{toxinidir}/requirements.txt
11 -r{toxinidir}/test-requirements.txt
12
13[testenv:pep8]
14commands = flake8 {posargs}
15
16[testenv:venv]
17commands = {posargs}
18
19[testenv:docs]
20commands = python setup.py build_sphinx
21
22[flake8]
23show-source = true
24ignore = H101,H302,H306,H803
25builtins = _
26exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,tools,local_settings.py