Merge lp:~devcamcar/django-nova/move-django-nova into lp:django-nova

Proposed by Devin Carlen
Status: Merged
Approved by: Devin Carlen
Approved revision: 20
Merged at revision: 20
Proposed branch: lp:~devcamcar/django-nova/move-django-nova
Merge into: lp:django-nova
Diff against target: 7292 lines (+5/-6810)
88 files modified
LICENSE (+0/-176)
README (+5/-41)
bootstrap.py (+0/-260)
buildout.cfg (+0/-19)
setup.py (+0/-29)
src/django_nova/adminclient.py (+0/-498)
src/django_nova/connection.py (+0/-38)
src/django_nova/exceptions.py (+0/-95)
src/django_nova/forms.py (+0/-262)
src/django_nova/management/commands/createnovausers.py (+0/-37)
src/django_nova/manager.py (+0/-340)
src/django_nova/models.py (+0/-121)
src/django_nova/shortcuts.py (+0/-131)
src/django_nova/templates/admin/django_nova/project/add_project.html (+0/-45)
src/django_nova/templates/admin/django_nova/project/add_project_user.html (+0/-69)
src/django_nova/templates/admin/django_nova/project/base_projects.html (+0/-16)
src/django_nova/templates/admin/django_nova/project/change_list.html (+0/-3)
src/django_nova/templates/admin/django_nova/project/delete_project.html (+0/-25)
src/django_nova/templates/admin/django_nova/project/delete_project_user.html (+0/-25)
src/django_nova/templates/admin/django_nova/project/edit_project.html (+0/-95)
src/django_nova/templates/admin/django_nova/project/global_edit_user.html (+0/-71)
src/django_nova/templates/admin/django_nova/project/project_list.html (+0/-42)
src/django_nova/templates/admin/django_nova/project/project_user.html (+0/-76)
src/django_nova/templates/admin/django_nova/project/send_credentials.html (+0/-87)
src/django_nova/templates/admin/django_nova/project/user_list.html (+0/-39)
src/django_nova/templates/django_nova/_messages.html (+0/-41)
src/django_nova/templates/django_nova/base.html (+0/-85)
src/django_nova/templates/django_nova/credentials/expired.html (+0/-17)
src/django_nova/templates/django_nova/images/_launch_form.html (+0/-7)
src/django_nova/templates/django_nova/images/_list.html (+0/-112)
src/django_nova/templates/django_nova/images/base.html (+0/-7)
src/django_nova/templates/django_nova/images/detail_list.html (+0/-207)
src/django_nova/templates/django_nova/images/edit.html (+0/-35)
src/django_nova/templates/django_nova/images/index.html (+0/-70)
src/django_nova/templates/django_nova/images/launch.html (+0/-32)
src/django_nova/templates/django_nova/instances/_instances_list.html (+0/-104)
src/django_nova/templates/django_nova/instances/base.html (+0/-7)
src/django_nova/templates/django_nova/instances/detail_list.html (+0/-33)
src/django_nova/templates/django_nova/instances/edit.html (+0/-34)
src/django_nova/templates/django_nova/instances/index.html (+0/-98)
src/django_nova/templates/django_nova/instances/performance.html (+0/-58)
src/django_nova/templates/django_nova/keypairs/_create_form.html (+0/-5)
src/django_nova/templates/django_nova/keypairs/_list.html (+0/-31)
src/django_nova/templates/django_nova/keypairs/base.html (+0/-7)
src/django_nova/templates/django_nova/keypairs/index.html (+0/-77)
src/django_nova/templates/django_nova/projects/edit_user.html (+0/-72)
src/django_nova/templates/django_nova/projects/index.html (+0/-26)
src/django_nova/templates/django_nova/projects/manage.html (+0/-45)
src/django_nova/templates/django_nova/securitygroups/_authorize_form.html (+0/-5)
src/django_nova/templates/django_nova/securitygroups/_create_form.html (+0/-5)
src/django_nova/templates/django_nova/securitygroups/_revoke_form.html (+0/-3)
src/django_nova/templates/django_nova/securitygroups/base.html (+0/-7)
src/django_nova/templates/django_nova/securitygroups/detail.html (+0/-62)
src/django_nova/templates/django_nova/securitygroups/index.html (+0/-59)
src/django_nova/templates/django_nova/volumes/_attach_form.html (+0/-5)
src/django_nova/templates/django_nova/volumes/_create_form.html (+0/-5)
src/django_nova/templates/django_nova/volumes/base.html (+0/-7)
src/django_nova/templates/django_nova/volumes/index.html (+0/-84)
src/django_nova/templatetags/admin_extras.py (+0/-50)
src/django_nova/templatetags/django_nova_tags.py (+0/-37)
src/django_nova/templatetags/project_tags.py (+0/-39)
src/django_nova/templatetags/region_tags.py (+0/-40)
src/django_nova/templatetags/sidebar_tags.py (+0/-46)
src/django_nova/templatetags/truncate_filter.py (+0/-31)
src/django_nova/tests/__init__.py (+0/-1)
src/django_nova/tests/urls.py (+0/-36)
src/django_nova/tests/view_tests/__init__.py (+0/-7)
src/django_nova/tests/view_tests/base.py (+0/-90)
src/django_nova/tests/view_tests/credential_tests.py (+0/-70)
src/django_nova/tests/view_tests/image_tests.py (+0/-232)
src/django_nova/tests/view_tests/instance_tests.py (+0/-67)
src/django_nova/tests/view_tests/keypair_tests.py (+0/-93)
src/django_nova/tests/view_tests/region_tests.py (+0/-43)
src/django_nova/tests/view_tests/volume_tests.py (+0/-170)
src/django_nova/testsettings.py (+0/-21)
src/django_nova/urls/admin_project.py (+0/-55)
src/django_nova/urls/admin_roles.py (+0/-32)
src/django_nova/urls/project.py (+0/-129)
src/django_nova/urls/region.py (+0/-29)
src/django_nova/views/admin.py (+0/-326)
src/django_nova/views/credentials.py (+0/-46)
src/django_nova/views/images.py (+0/-229)
src/django_nova/views/instances.py (+0/-203)
src/django_nova/views/keypairs.py (+0/-122)
src/django_nova/views/projects.py (+0/-107)
src/django_nova/views/regions.py (+0/-36)
src/django_nova/views/securitygroups.py (+0/-180)
src/django_nova/views/volumes.py (+0/-151)
To merge this branch: bzr merge lp:~devcamcar/django-nova/move-django-nova
Reviewer Review Type Date Requested Status
Devin Carlen Pending
Review via email: mp+52312@code.launchpad.net

Description of the change

The Django-Nova repository is decommissioned. It is now part of the OpenStack Dashboard repository located at:

http://launchpad.net/openstack-dashboard

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed file 'LICENSE'
2--- LICENSE 2011-01-12 20:02:06 +0000
3+++ LICENSE 1970-01-01 00:00:00 +0000
4@@ -1,176 +0,0 @@
5-
6- Apache License
7- Version 2.0, January 2004
8- http://www.apache.org/licenses/
9-
10- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
11-
12- 1. Definitions.
13-
14- "License" shall mean the terms and conditions for use, reproduction,
15- and distribution as defined by Sections 1 through 9 of this document.
16-
17- "Licensor" shall mean the copyright owner or entity authorized by
18- the copyright owner that is granting the License.
19-
20- "Legal Entity" shall mean the union of the acting entity and all
21- other entities that control, are controlled by, or are under common
22- control with that entity. For the purposes of this definition,
23- "control" means (i) the power, direct or indirect, to cause the
24- direction or management of such entity, whether by contract or
25- otherwise, or (ii) ownership of fifty percent (50%) or more of the
26- outstanding shares, or (iii) beneficial ownership of such entity.
27-
28- "You" (or "Your") shall mean an individual or Legal Entity
29- exercising permissions granted by this License.
30-
31- "Source" form shall mean the preferred form for making modifications,
32- including but not limited to software source code, documentation
33- source, and configuration files.
34-
35- "Object" form shall mean any form resulting from mechanical
36- transformation or translation of a Source form, including but
37- not limited to compiled object code, generated documentation,
38- and conversions to other media types.
39-
40- "Work" shall mean the work of authorship, whether in Source or
41- Object form, made available under the License, as indicated by a
42- copyright notice that is included in or attached to the work
43- (an example is provided in the Appendix below).
44-
45- "Derivative Works" shall mean any work, whether in Source or Object
46- form, that is based on (or derived from) the Work and for which the
47- editorial revisions, annotations, elaborations, or other modifications
48- represent, as a whole, an original work of authorship. For the purposes
49- of this License, Derivative Works shall not include works that remain
50- separable from, or merely link (or bind by name) to the interfaces of,
51- the Work and Derivative Works thereof.
52-
53- "Contribution" shall mean any work of authorship, including
54- the original version of the Work and any modifications or additions
55- to that Work or Derivative Works thereof, that is intentionally
56- submitted to Licensor for inclusion in the Work by the copyright owner
57- or by an individual or Legal Entity authorized to submit on behalf of
58- the copyright owner. For the purposes of this definition, "submitted"
59- means any form of electronic, verbal, or written communication sent
60- to the Licensor or its representatives, including but not limited to
61- communication on electronic mailing lists, source code control systems,
62- and issue tracking systems that are managed by, or on behalf of, the
63- Licensor for the purpose of discussing and improving the Work, but
64- excluding communication that is conspicuously marked or otherwise
65- designated in writing by the copyright owner as "Not a Contribution."
66-
67- "Contributor" shall mean Licensor and any individual or Legal Entity
68- on behalf of whom a Contribution has been received by Licensor and
69- subsequently incorporated within the Work.
70-
71- 2. Grant of Copyright License. Subject to the terms and conditions of
72- this License, each Contributor hereby grants to You a perpetual,
73- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
74- copyright license to reproduce, prepare Derivative Works of,
75- publicly display, publicly perform, sublicense, and distribute the
76- Work and such Derivative Works in Source or Object form.
77-
78- 3. Grant of Patent License. Subject to the terms and conditions of
79- this License, each Contributor hereby grants to You a perpetual,
80- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
81- (except as stated in this section) patent license to make, have made,
82- use, offer to sell, sell, import, and otherwise transfer the Work,
83- where such license applies only to those patent claims licensable
84- by such Contributor that are necessarily infringed by their
85- Contribution(s) alone or by combination of their Contribution(s)
86- with the Work to which such Contribution(s) was submitted. If You
87- institute patent litigation against any entity (including a
88- cross-claim or counterclaim in a lawsuit) alleging that the Work
89- or a Contribution incorporated within the Work constitutes direct
90- or contributory patent infringement, then any patent licenses
91- granted to You under this License for that Work shall terminate
92- as of the date such litigation is filed.
93-
94- 4. Redistribution. You may reproduce and distribute copies of the
95- Work or Derivative Works thereof in any medium, with or without
96- modifications, and in Source or Object form, provided that You
97- meet the following conditions:
98-
99- (a) You must give any other recipients of the Work or
100- Derivative Works a copy of this License; and
101-
102- (b) You must cause any modified files to carry prominent notices
103- stating that You changed the files; and
104-
105- (c) You must retain, in the Source form of any Derivative Works
106- that You distribute, all copyright, patent, trademark, and
107- attribution notices from the Source form of the Work,
108- excluding those notices that do not pertain to any part of
109- the Derivative Works; and
110-
111- (d) If the Work includes a "NOTICE" text file as part of its
112- distribution, then any Derivative Works that You distribute must
113- include a readable copy of the attribution notices contained
114- within such NOTICE file, excluding those notices that do not
115- pertain to any part of the Derivative Works, in at least one
116- of the following places: within a NOTICE text file distributed
117- as part of the Derivative Works; within the Source form or
118- documentation, if provided along with the Derivative Works; or,
119- within a display generated by the Derivative Works, if and
120- wherever such third-party notices normally appear. The contents
121- of the NOTICE file are for informational purposes only and
122- do not modify the License. You may add Your own attribution
123- notices within Derivative Works that You distribute, alongside
124- or as an addendum to the NOTICE text from the Work, provided
125- that such additional attribution notices cannot be construed
126- as modifying the License.
127-
128- You may add Your own copyright statement to Your modifications and
129- may provide additional or different license terms and conditions
130- for use, reproduction, or distribution of Your modifications, or
131- for any such Derivative Works as a whole, provided Your use,
132- reproduction, and distribution of the Work otherwise complies with
133- the conditions stated in this License.
134-
135- 5. Submission of Contributions. Unless You explicitly state otherwise,
136- any Contribution intentionally submitted for inclusion in the Work
137- by You to the Licensor shall be under the terms and conditions of
138- this License, without any additional terms or conditions.
139- Notwithstanding the above, nothing herein shall supersede or modify
140- the terms of any separate license agreement you may have executed
141- with Licensor regarding such Contributions.
142-
143- 6. Trademarks. This License does not grant permission to use the trade
144- names, trademarks, service marks, or product names of the Licensor,
145- except as required for reasonable and customary use in describing the
146- origin of the Work and reproducing the content of the NOTICE file.
147-
148- 7. Disclaimer of Warranty. Unless required by applicable law or
149- agreed to in writing, Licensor provides the Work (and each
150- Contributor provides its Contributions) on an "AS IS" BASIS,
151- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
152- implied, including, without limitation, any warranties or conditions
153- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
154- PARTICULAR PURPOSE. You are solely responsible for determining the
155- appropriateness of using or redistributing the Work and assume any
156- risks associated with Your exercise of permissions under this License.
157-
158- 8. Limitation of Liability. In no event and under no legal theory,
159- whether in tort (including negligence), contract, or otherwise,
160- unless required by applicable law (such as deliberate and grossly
161- negligent acts) or agreed to in writing, shall any Contributor be
162- liable to You for damages, including any direct, indirect, special,
163- incidental, or consequential damages of any character arising as a
164- result of this License or out of the use or inability to use the
165- Work (including but not limited to damages for loss of goodwill,
166- work stoppage, computer failure or malfunction, or any and all
167- other commercial damages or losses), even if such Contributor
168- has been advised of the possibility of such damages.
169-
170- 9. Accepting Warranty or Additional Liability. While redistributing
171- the Work or Derivative Works thereof, You may choose to offer,
172- and charge a fee for, acceptance of support, warranty, indemnity,
173- or other liability obligations and/or rights consistent with this
174- License. However, in accepting such obligations, You may act only
175- on Your own behalf and on Your sole responsibility, not on behalf
176- of any other Contributor, and only if You agree to indemnify,
177- defend, and hold each Contributor harmless for any liability
178- incurred by, or claims asserted against, such Contributor by reason
179- of your accepting any such warranty or additional liability.
180-
181
182=== modified file 'README'
183--- README 2011-01-12 22:23:24 +0000
184+++ README 2011-03-05 22:32:56 +0000
185@@ -1,42 +1,6 @@
186-OpenStack Django-Nova
187----------------------
188-
189-The Django-Nova project is a Django module that is used to provide web based
190-interactions with the OpenStack Nova cloud controller.
191-
192-There is a reference implementation that uses this module located at:
193-
194- http://launchpad.net/openstack-dashboard
195-
196-It is highly recommended that you make use of this reference implementation
197-so that changes you make can be visualized effectively and are consistent.
198-Using this reference implementation as a development environment will greatly
199-simplify development of the django-nova module.
200-
201-Of course, if you are developing your own Django site using django-nova, then
202-you can disregard this advice.
203-
204-
205-
206-Getting Started
207----------------
208-
209-Django-Nova uses Buildout (http://www.buildout.org/) to manage local
210-development. To configure your local Buildout environment:
211-
212- $ python bootstrap.py
213- $ bin/buildout
214-
215-This will install all the dependencies of django-nova and provide some useful
216-scripts in the bin/ directory:
217-
218- bin/python provides a python shell for the current buildout.
219- bin/django provides django functions for the current buildout.
220-
221-
222-You should now be able to run unit tests as follows:
223-
224- $ bin/django test
225-
226-
227+Django-Nova has been moved into the OpenStack Dashboard repository.
228+
229+It's new home is at:
230+
231+ http://launchpad.net/openstack-dashboard
232
233
234=== removed file 'bootstrap.py'
235--- bootstrap.py 2011-01-12 20:02:06 +0000
236+++ bootstrap.py 1970-01-01 00:00:00 +0000
237@@ -1,260 +0,0 @@
238-##############################################################################
239-#
240-# Copyright (c) 2006 Zope Foundation and Contributors.
241-# All Rights Reserved.
242-#
243-# This software is subject to the provisions of the Zope Public License,
244-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
245-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
246-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
247-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
248-# FOR A PARTICULAR PURPOSE.
249-#
250-##############################################################################
251-"""Bootstrap a buildout-based project
252-
253-Simply run this script in a directory containing a buildout.cfg.
254-The script accepts buildout command-line options, so you can
255-use the -c option to specify an alternate configuration file.
256-"""
257-
258-import os, shutil, sys, tempfile, textwrap, urllib, urllib2, subprocess
259-from optparse import OptionParser
260-
261-if sys.platform == 'win32':
262- def quote(c):
263- if ' ' in c:
264- return '"%s"' % c # work around spawn lamosity on windows
265- else:
266- return c
267-else:
268- quote = str
269-
270-# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments.
271-stdout, stderr = subprocess.Popen(
272- [sys.executable, '-Sc',
273- 'try:\n'
274- ' import ConfigParser\n'
275- 'except ImportError:\n'
276- ' print 1\n'
277- 'else:\n'
278- ' print 0\n'],
279- stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
280-has_broken_dash_S = bool(int(stdout.strip()))
281-
282-# In order to be more robust in the face of system Pythons, we want to
283-# run without site-packages loaded. This is somewhat tricky, in
284-# particular because Python 2.6's distutils imports site, so starting
285-# with the -S flag is not sufficient. However, we'll start with that:
286-if not has_broken_dash_S and 'site' in sys.modules:
287- # We will restart with python -S.
288- args = sys.argv[:]
289- args[0:0] = [sys.executable, '-S']
290- args = map(quote, args)
291- os.execv(sys.executable, args)
292-# Now we are running with -S. We'll get the clean sys.path, import site
293-# because distutils will do it later, and then reset the path and clean
294-# out any namespace packages from site-packages that might have been
295-# loaded by .pth files.
296-clean_path = sys.path[:]
297-import site
298-sys.path[:] = clean_path
299-for k, v in sys.modules.items():
300- if k in ('setuptools', 'pkg_resources') or (
301- hasattr(v, '__path__') and
302- len(v.__path__)==1 and
303- not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))):
304- # This is a namespace package. Remove it.
305- sys.modules.pop(k)
306-
307-is_jython = sys.platform.startswith('java')
308-
309-setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
310-distribute_source = 'http://python-distribute.org/distribute_setup.py'
311-
312-# parsing arguments
313-def normalize_to_url(option, opt_str, value, parser):
314- if value:
315- if '://' not in value: # It doesn't smell like a URL.
316- value = 'file://%s' % (
317- urllib.pathname2url(
318- os.path.abspath(os.path.expanduser(value))),)
319- if opt_str == '--download-base' and not value.endswith('/'):
320- # Download base needs a trailing slash to make the world happy.
321- value += '/'
322- else:
323- value = None
324- name = opt_str[2:].replace('-', '_')
325- setattr(parser.values, name, value)
326-
327-usage = '''\
328-[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
329-
330-Bootstraps a buildout-based project.
331-
332-Simply run this script in a directory containing a buildout.cfg, using the
333-Python that you want bin/buildout to use.
334-
335-Note that by using --setup-source and --download-base to point to
336-local resources, you can keep this script from going over the network.
337-'''
338-
339-parser = OptionParser(usage=usage)
340-parser.add_option("-v", "--version", dest="version",
341- help="use a specific zc.buildout version")
342-parser.add_option("-d", "--distribute",
343- action="store_true", dest="use_distribute", default=False,
344- help="Use Distribute rather than Setuptools.")
345-parser.add_option("--setup-source", action="callback", dest="setup_source",
346- callback=normalize_to_url, nargs=1, type="string",
347- help=("Specify a URL or file location for the setup file. "
348- "If you use Setuptools, this will default to " +
349- setuptools_source + "; if you use Distribute, this "
350- "will default to " + distribute_source +"."))
351-parser.add_option("--download-base", action="callback", dest="download_base",
352- callback=normalize_to_url, nargs=1, type="string",
353- help=("Specify a URL or directory for downloading "
354- "zc.buildout and either Setuptools or Distribute. "
355- "Defaults to PyPI."))
356-parser.add_option("--eggs",
357- help=("Specify a directory for storing eggs. Defaults to "
358- "a temporary directory that is deleted when the "
359- "bootstrap script completes."))
360-parser.add_option("-t", "--accept-buildout-test-releases",
361- dest='accept_buildout_test_releases',
362- action="store_true", default=False,
363- help=("Normally, if you do not specify a --version, the "
364- "bootstrap script and buildout gets the newest "
365- "*final* versions of zc.buildout and its recipes and "
366- "extensions for you. If you use this flag, "
367- "bootstrap and buildout will get the newest releases "
368- "even if they are alphas or betas."))
369-parser.add_option("-c", None, action="store", dest="config_file",
370- help=("Specify the path to the buildout configuration "
371- "file to be used."))
372-
373-options, args = parser.parse_args()
374-
375-# if -c was provided, we push it back into args for buildout's main function
376-if options.config_file is not None:
377- args += ['-c', options.config_file]
378-
379-if options.eggs:
380- eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
381-else:
382- eggs_dir = tempfile.mkdtemp()
383-
384-if options.setup_source is None:
385- if options.use_distribute:
386- options.setup_source = distribute_source
387- else:
388- options.setup_source = setuptools_source
389-
390-if options.accept_buildout_test_releases:
391- args.append('buildout:accept-buildout-test-releases=true')
392-args.append('bootstrap')
393-
394-try:
395- import pkg_resources
396- import setuptools # A flag. Sometimes pkg_resources is installed alone.
397- if not hasattr(pkg_resources, '_distribute'):
398- raise ImportError
399-except ImportError:
400- ez_code = urllib2.urlopen(
401- options.setup_source).read().replace('\r\n', '\n')
402- ez = {}
403- exec ez_code in ez
404- setup_args = dict(to_dir=eggs_dir, download_delay=0)
405- if options.download_base:
406- setup_args['download_base'] = options.download_base
407- if options.use_distribute:
408- setup_args['no_fake'] = True
409- ez['use_setuptools'](**setup_args)
410- if 'pkg_resources' in sys.modules:
411- reload(sys.modules['pkg_resources'])
412- import pkg_resources
413- # This does not (always?) update the default working set. We will
414- # do it.
415- for path in sys.path:
416- if path not in pkg_resources.working_set.entries:
417- pkg_resources.working_set.add_entry(path)
418-
419-cmd = [quote(sys.executable),
420- '-c',
421- quote('from setuptools.command.easy_install import main; main()'),
422- '-mqNxd',
423- quote(eggs_dir)]
424-
425-if not has_broken_dash_S:
426- cmd.insert(1, '-S')
427-
428-find_links = options.download_base
429-if not find_links:
430- find_links = os.environ.get('bootstrap-testing-find-links')
431-if find_links:
432- cmd.extend(['-f', quote(find_links)])
433-
434-if options.use_distribute:
435- setup_requirement = 'distribute'
436-else:
437- setup_requirement = 'setuptools'
438-ws = pkg_resources.working_set
439-setup_requirement_path = ws.find(
440- pkg_resources.Requirement.parse(setup_requirement)).location
441-env = dict(
442- os.environ,
443- PYTHONPATH=setup_requirement_path)
444-
445-requirement = 'zc.buildout'
446-version = options.version
447-if version is None and not options.accept_buildout_test_releases:
448- # Figure out the most recent final version of zc.buildout.
449- import setuptools.package_index
450- _final_parts = '*final-', '*final'
451- def _final_version(parsed_version):
452- for part in parsed_version:
453- if (part[:1] == '*') and (part not in _final_parts):
454- return False
455- return True
456- index = setuptools.package_index.PackageIndex(
457- search_path=[setup_requirement_path])
458- if find_links:
459- index.add_find_links((find_links,))
460- req = pkg_resources.Requirement.parse(requirement)
461- if index.obtain(req) is not None:
462- best = []
463- bestv = None
464- for dist in index[req.project_name]:
465- distv = dist.parsed_version
466- if _final_version(distv):
467- if bestv is None or distv > bestv:
468- best = [dist]
469- bestv = distv
470- elif distv == bestv:
471- best.append(dist)
472- if best:
473- best.sort()
474- version = best[-1].version
475-if version:
476- requirement = '=='.join((requirement, version))
477-cmd.append(requirement)
478-
479-if is_jython:
480- import subprocess
481- exitcode = subprocess.Popen(cmd, env=env).wait()
482-else: # Windows prefers this, apparently; otherwise we would prefer subprocess
483- exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
484-if exitcode != 0:
485- sys.stdout.flush()
486- sys.stderr.flush()
487- print ("An error occurred when trying to install zc.buildout. "
488- "Look above this message for any errors that "
489- "were output by easy_install.")
490- sys.exit(exitcode)
491-
492-ws.add_entry(eggs_dir)
493-ws.require(requirement)
494-import zc.buildout.buildout
495-zc.buildout.buildout.main(args)
496-if not options.eggs: # clean up temporary egg directory
497- shutil.rmtree(eggs_dir)
498
499=== removed file 'buildout.cfg'
500--- buildout.cfg 2011-01-18 06:02:42 +0000
501+++ buildout.cfg 1970-01-01 00:00:00 +0000
502@@ -1,19 +0,0 @@
503-[buildout]
504-parts = python django
505-develop = .
506-eggs = django-nova
507-
508-[python]
509-recipe = zc.recipe.egg
510-interpreter = python
511-eggs = ${buildout:eggs}
512-
513-[django]
514-recipe = djangorecipe
515-version = 1.2.4
516-project = django_nova
517-projectegg = django_nova
518-settings = testsettings
519-test = django_nova
520-eggs = ${buildout:eggs}
521-
522
523=== removed file 'setup.py'
524--- setup.py 2011-01-21 22:38:42 +0000
525+++ setup.py 1970-01-01 00:00:00 +0000
526@@ -1,29 +0,0 @@
527-import os
528-from setuptools import setup, find_packages
529-
530-def read(fname):
531- return open(os.path.join(os.path.dirname(__file__), fname)).read()
532-
533-setup(
534- name = "django-nova",
535- version = "0.1",
536- url = 'https://launchpad.net/django-nova/',
537- license = 'Apache 2.0',
538- description = "A Django interface for OpenStack Nova.",
539- long_description = read('README'),
540- author = 'Devin Carlen',
541- author_email = 'devin.carlen@gmail.com',
542- packages = find_packages('src'),
543- package_dir = {'': 'src'},
544- install_requires = ['setuptools', 'boto==1.9b', 'mox>=0.5.0'],
545- classifiers = [
546- 'Development Status :: 4 - Beta',
547- 'Framework :: Django',
548- 'Intended Audience :: Developers',
549- 'License :: OSI Approved :: Apache License',
550- 'Operating System :: OS Independent',
551- 'Programming Language :: Python',
552- 'Topic :: Internet :: WWW/HTTP',
553- ]
554-)
555-
556
557=== removed directory 'src'
558=== removed directory 'src/django_nova'
559=== removed file 'src/django_nova/__init__.py'
560=== removed file 'src/django_nova/adminclient.py'
561--- src/django_nova/adminclient.py 2011-01-28 20:35:31 +0000
562+++ src/django_nova/adminclient.py 1970-01-01 00:00:00 +0000
563@@ -1,498 +0,0 @@
564-# vim: tabstop=4 shiftwidth=4 softtabstop=4
565-
566-# Copyright 2010 United States Government as represented by the
567-# Administrator of the National Aeronautics and Space Administration.
568-# All Rights Reserved.
569-#
570-# Licensed under the Apache License, Version 2.0 (the "License"); you may
571-# not use this file except in compliance with the License. You may obtain
572-# a copy of the License at
573-#
574-# http://www.apache.org/licenses/LICENSE-2.0
575-#
576-# Unless required by applicable law or agreed to in writing, software
577-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
578-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
579-# License for the specific language governing permissions and limitations
580-# under the License.
581-"""
582-Nova User API client library.
583-"""
584-
585-import base64
586-import boto
587-import boto.exception
588-import httplib
589-import re
590-import string
591-from boto.ec2.regioninfo import RegionInfo
592-
593-
594-DEFAULT_CLC_URL='http://127.0.0.1:8773'
595-DEFAULT_REGION='nova'
596-DEFAULT_ACCESS_KEY='admin'
597-DEFAULT_SECRET_KEY='admin'
598-
599-
600-class UserInfo(object):
601- """
602- Information about a Nova user, as parsed through SAX
603- fields include:
604- username
605- accesskey
606- secretkey
607-
608- and an optional field containing a zip with X509 cert & rc
609- file
610- """
611-
612- def __init__(self, connection=None, username=None, endpoint=None):
613- self.connection = connection
614- self.username = username
615- self.endpoint = endpoint
616-
617- def __repr__(self):
618- return 'UserInfo:%s' % self.username
619-
620- def startElement(self, name, attrs, connection):
621- return None
622-
623- def endElement(self, name, value, connection):
624- if name == 'username':
625- self.username = str(value)
626- elif name == 'file':
627- self.file = base64.b64decode(str(value))
628- elif name == 'accesskey':
629- self.accesskey = str(value)
630- elif name == 'secretkey':
631- self.secretkey = str(value)
632-
633-
634-class UserRole(object):
635- """
636- Information about a Nova user's role, as parsed through SAX.
637- Fields include:
638- role
639- """
640- def __init__(self, connection=None):
641- self.connection = connection
642- self.role = None
643-
644- def __repr__(self):
645- return 'UserRole:%s' % self.role
646-
647- def startElement(self, name, attrs, connection):
648- return None
649-
650- def endElement(self, name, value, connection):
651- if name == 'role':
652- self.role = value
653- else:
654- setattr(self, name, str(value))
655-
656-
657-class ProjectInfo(object):
658- """
659- Information about a Nova project, as parsed through SAX
660- Fields include:
661- projectname
662- description
663- projectManagerId
664- memberIds
665- """
666-
667- def __init__(self, connection=None):
668- self.connection = connection
669- self.projectname = None
670- self.description = None
671- self.projectManagerId = None
672- self.memberIds = []
673-
674- def __repr__(self):
675- return 'ProjectInfo:%s' % self.projectname
676-
677- def startElement(self, name, attrs, connection):
678- return None
679-
680- def endElement(self, name, value, connection):
681- if name == 'projectname':
682- self.projectname = value
683- elif name == 'description':
684- self.description = value
685- elif name == 'projectManagerId':
686- self.projectManagerId = value
687- elif name == 'memberId':
688- self.memberIds.append(value)
689- else:
690- setattr(self, name, str(value))
691-
692-
693-class ProjectMember(object):
694- """
695- Information about a Nova project member, as parsed through SAX.
696- Fields include:
697- memberId
698- """
699-
700- def __init__(self, connection=None):
701- self.connection = connection
702- self.memberId = None
703-
704- def __repr__(self):
705- return 'ProjectMember:%s' % self.memberId
706-
707- def startElement(self, name, attrs, connection):
708- return None
709-
710- def endElement(self, name, value, connection):
711- if name == 'member':
712- self.memberId = value
713- else:
714- setattr(self, name, str(value))
715-
716-
717-class HostInfo(object):
718- """
719- Information about a Nova Host, as parsed through SAX:
720- Hostname
721- Compute Service Status
722- Volume Service Status
723- """
724-
725- def __init__(self, connection=None):
726- self.connection = connection
727- self.hostname = None
728- self.compute = None
729- self.volume = None
730- self.instance_count = 0
731- self.volume_count = 0
732-
733- def __repr__(self):
734- return 'Host:%s' % self.hostname
735-
736- # this is needed by the sax parser, so ignore the ugly name
737- def startElement(self, name, attrs, connection):
738- return None
739-
740- # this is needed by the sax parser, so ignore the ugly name
741- def endElement(self, name, value, connection):
742- fixed_name = string.lower(re.sub(r'([A-Z])', r'_\1', name))
743- setattr(self, fixed_name, value)
744-
745-
746-class Vpn(object):
747- """
748- Information about a Vpn, as parsed through SAX
749- fields include:
750- instance_id
751- project_id
752- public_ip
753- public_port
754- created_at
755- internal_ip
756- state
757- """
758-
759- def __init__(self, connection=None):
760- self.connection = connection
761- self.instance_id = None
762- self.project_id = None
763-
764- def __repr__(self):
765- return 'Vpn:%s:%s' % (self.project_id, self.instance_id)
766-
767- def startElement(self, name, attrs, connection):
768- return None
769-
770- def endElement(self, name, value, connection):
771- if name == 'instanceId':
772- self.instance_id = str(value)
773- elif name == 'projectId':
774- self.project_id = str(value)
775- elif name == 'publicIp':
776- self.public_ip = str(value)
777- elif name == 'publicPort':
778- self.public_port = str(value)
779- elif name == 'createdAt':
780- self.created_at = str(value)
781- elif name == 'internalIp':
782- self.internal_ip = str(value)
783- else:
784- setattr(self, name, str(value))
785-
786-
787-class InstanceType(object):
788- """
789- Information about a Nova instance type, as parsed through SAX.
790-
791- **Fields include**
792-
793- * name
794- * vcpus
795- * disk_gb
796- * memory_mb
797- * flavor_id
798-
799- """
800-
801- def __init__(self, connection=None):
802- self.connection = connection
803- self.name = None
804- self.vcpus = None
805- self.disk_gb = None
806- self.memory_mb = None
807- self.flavor_id = None
808-
809- def __repr__(self):
810- return 'InstanceType:%s' % self.name
811-
812- def startElement(self, name, attrs, connection):
813- return None
814-
815- def endElement(self, name, value, connection):
816- if name == "memoryMb":
817- self.memory_mb = str(value)
818- elif name == "flavorId":
819- self.flavor_id = str(value)
820- elif name == "diskGb":
821- self.disk_gb = str(value)
822- else:
823- setattr(self, name, str(value))
824-
825-
826-class StatusResponse(object):
827- def __init__(self, connection=None):
828- self.connection = connection
829- self.status = None
830-
831- def __repr__(self):
832- return 'Status:%s' % self.status
833-
834- def startElement(self, name, attrs, connection):
835- return None
836-
837- def endElement(self, name, value, connection):
838- setattr(self, name, str(value))
839-
840-
841-class NovaAdminClient(object):
842- def __init__(self, clc_url=DEFAULT_CLC_URL, region=DEFAULT_REGION,
843- access_key=DEFAULT_ACCESS_KEY, secret_key=DEFAULT_SECRET_KEY,
844- **kwargs):
845- parts = self.split_clc_url(clc_url)
846-
847- self.clc_url = clc_url
848- self.region = region
849- self.access = access_key
850- self.secret = secret_key
851- self.apiconn = boto.connect_ec2(aws_access_key_id=access_key,
852- aws_secret_access_key=secret_key,
853- is_secure=parts['is_secure'],
854- region=RegionInfo(None,
855- region,
856- parts['ip']),
857- port=parts['port'],
858- path='/services/Admin',
859- **kwargs)
860- self.apiconn.APIVersion = 'nova'
861-
862- def connection_for(self, username, project, clc_url=None, region=None,
863- **kwargs):
864- """
865- Returns a boto ec2 connection for the given username.
866- """
867- if not clc_url:
868- clc_url = self.clc_url
869- if not region:
870- region = self.region
871- parts = self.split_clc_url(clc_url)
872- user = self.get_user(username)
873- access_key = '%s:%s' % (user.accesskey, project)
874- return boto.connect_ec2(aws_access_key_id=access_key,
875- aws_secret_access_key=user.secretkey,
876- is_secure=parts['is_secure'],
877- region=RegionInfo(None,
878- self.region,
879- parts['ip']),
880- port=parts['port'],
881- path='/services/Cloud',
882- **kwargs)
883-
884- def split_clc_url(self, clc_url):
885- """
886- Splits a cloud controller endpoint url.
887- """
888- parts = httplib.urlsplit(clc_url)
889- is_secure = parts.scheme == 'https'
890- ip, port = parts.netloc.split(':')
891- return {'ip': ip, 'port': int(port), 'is_secure': is_secure}
892-
893- def get_users(self):
894- """ grabs the list of all users """
895- return self.apiconn.get_list('DescribeUsers', {}, [('item', UserInfo)])
896-
897- def get_user(self, name):
898- """ grab a single user by name """
899- try:
900- return self.apiconn.get_object('DescribeUser', {'Name': name}, UserInfo)
901- except boto.exception.BotoServerError, e:
902- if e.status == 400 and e.error_code == 'NotFound':
903- return None
904- raise
905-
906- def has_user(self, username):
907- """ determine if user exists """
908- return self.get_user(username) != None
909-
910- def create_user(self, username):
911- """ creates a new user, returning the userinfo object with access/secret """
912- return self.apiconn.get_object('RegisterUser', {'Name': username}, UserInfo)
913-
914- def delete_user(self, username):
915- """ deletes a user """
916- return self.apiconn.get_object('DeregisterUser', {'Name': username}, UserInfo)
917-
918- def get_roles(self, project_roles=True):
919- """Returns a list of available roles."""
920- return self.apiconn.get_list('DescribeRoles',
921- {'ProjectRoles': project_roles},
922- [('item', UserRole)])
923-
924- def get_user_roles(self, user, project=None):
925- """Returns a list of roles for the given user.
926- Omitting project will return any global roles that the user has.
927- Specifying project will return only project specific roles.
928- """
929- params = {'User':user}
930- if project:
931- params['Project'] = project
932- return self.apiconn.get_list('DescribeUserRoles',
933- params,
934- [('item', UserRole)])
935-
936- def add_user_role(self, user, role, project=None):
937- """
938- Add a role to a user either globally or for a specific project.
939- """
940- return self.modify_user_role(user, role, project=project,
941- operation='add')
942-
943- def remove_user_role(self, user, role, project=None):
944- """
945- Remove a role from a user either globally or for a specific project.
946- """
947- return self.modify_user_role(user, role, project=project,
948- operation='remove')
949-
950- def modify_user_role(self, user, role, project=None, operation='add',
951- **kwargs):
952- """
953- Add or remove a role for a user and project.
954- """
955- params = {'User': user,
956- 'Role': role,
957- 'Project': project,
958- 'Operation': operation}
959- return self.apiconn.get_status('ModifyUserRole', params)
960-
961- def get_projects(self, user=None):
962- """
963- Returns a list of all projects.
964- """
965- if user:
966- params = {'User': user}
967- else:
968- params = {}
969- return self.apiconn.get_list('DescribeProjects',
970- params,
971- [('item', ProjectInfo)])
972-
973- def get_project(self, name):
974- """
975- Returns a single project with the specified name.
976- """
977- project = self.apiconn.get_object('DescribeProject',
978- {'Name': name},
979- ProjectInfo)
980-
981- if project.projectname != None:
982- return project
983-
984- def create_project(self, projectname, manager_user, description=None,
985- member_users=None):
986- """
987- Creates a new project.
988- """
989- params = {'Name': projectname,
990- 'ManagerUser': manager_user,
991- 'Description': description,
992- 'MemberUsers': member_users}
993- return self.apiconn.get_object('RegisterProject', params, ProjectInfo)
994-
995- def delete_project(self, projectname):
996- """
997- Permanently deletes the specified project.
998- """
999- return self.apiconn.get_object('DeregisterProject',
1000- {'Name': projectname},
1001- ProjectInfo)
1002-
1003- def get_project_members(self, name):
1004- """
1005- Returns a list of members of a project.
1006- """
1007- return self.apiconn.get_list('DescribeProjectMembers',
1008- {'Name': name},
1009- [('item', ProjectMember)])
1010-
1011- def add_project_member(self, user, project):
1012- """
1013- Adds a user to a project.
1014- """
1015- return self.modify_project_member(user, project, operation='add')
1016-
1017- def remove_project_member(self, user, project):
1018- """
1019- Removes a user from a project.
1020- """
1021- return self.modify_project_member(user, project, operation='remove')
1022-
1023- def modify_project_member(self, user, project, operation='add'):
1024- """
1025- Adds or removes a user from a project.
1026- """
1027- params = {'User': user,
1028- 'Project': project,
1029- 'Operation': operation}
1030- return self.apiconn.get_status('ModifyProjectMember', params)
1031-
1032- def get_zip(self, user, project):
1033- """
1034- Returns the content of a zip file containing novarc and access credentials.
1035- """
1036- params = {'Name': user, 'Project': project}
1037- zip = self.apiconn.get_object('GenerateX509ForUser', params, UserInfo)
1038- return zip.file
1039-
1040- def start_vpn(self, project):
1041- """
1042- Starts the vpn for a user
1043- """
1044- return self.apiconn.get_object('StartVpn', {'Project': project}, Vpn)
1045-
1046- def get_vpns(self):
1047- """Return a list of vpn with project name"""
1048- return self.apiconn.get_list('DescribeVpns', {}, [('item', Vpn)])
1049-
1050- def get_hosts(self):
1051- return self.apiconn.get_list('DescribeHosts', {}, [('item', HostInfo)])
1052-
1053- def get_instance_types(self):
1054- """Grabs the list of all users."""
1055- return self.apiconn.get_list('DescribeInstanceTypes', {},
1056- [('item', InstanceType)])
1057-
1058- def disable_project_credentials(self, project):
1059- """Revoke project credentials and kill the cloudpipe/vpn instance"""
1060- return self.apiconn.get_object('DisableProjectCredentials',
1061- {'Project': project}, StatusResponse)
1062
1063=== removed file 'src/django_nova/connection.py'
1064--- src/django_nova/connection.py 2011-01-12 20:02:06 +0000
1065+++ src/django_nova/connection.py 1970-01-01 00:00:00 +0000
1066@@ -1,38 +0,0 @@
1067-# vim: tabstop=4 shiftwidth=4 softtabstop=4
1068-
1069-# Copyright 2010 United States Government as represented by the
1070-# Administrator of the National Aeronautics and Space Administration.
1071-# All Rights Reserved.
1072-#
1073-# Licensed under the Apache License, Version 2.0 (the "License"); you may
1074-# not use this file except in compliance with the License. You may obtain
1075-# a copy of the License at
1076-#
1077-# http://www.apache.org/licenses/LICENSE-2.0
1078-#
1079-# Unless required by applicable law or agreed to in writing, software
1080-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1081-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1082-# License for the specific language governing permissions and limitations
1083-# under the License.
1084-"""
1085-Manage connections to Nova's admin API.
1086-"""
1087-
1088-from django.conf import settings
1089-from django_nova import adminclient
1090-
1091-
1092-def get_nova_admin_connection():
1093- """
1094- Returns a Nova administration connection.
1095- """
1096- return adminclient.NovaAdminClient (
1097- clc_url=settings.NOVA_DEFAULT_ENDPOINT,
1098- region=settings.NOVA_DEFAULT_REGION,
1099- access_key=settings.NOVA_ACCESS_KEY,
1100- secret_key=settings.NOVA_SECRET_KEY
1101- )
1102-
1103-
1104-
1105
1106=== removed file 'src/django_nova/exceptions.py'
1107--- src/django_nova/exceptions.py 2011-01-18 23:07:26 +0000
1108+++ src/django_nova/exceptions.py 1970-01-01 00:00:00 +0000
1109@@ -1,95 +0,0 @@
1110-# vim: tabstop=4 shiftwidth=4 softtabstop=4
1111-
1112-# Copyright 2010 United States Government as represented by the
1113-# Administrator of the National Aeronautics and Space Administration.
1114-# All Rights Reserved.
1115-#
1116-# Licensed under the Apache License, Version 2.0 (the "License"); you may
1117-# not use this file except in compliance with the License. You may obtain
1118-# a copy of the License at
1119-#
1120-# http://www.apache.org/licenses/LICENSE-2.0
1121-#
1122-# Unless required by applicable law or agreed to in writing, software
1123-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1124-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1125-# License for the specific language governing permissions and limitations
1126-# under the License.
1127-
1128-"""
1129-Better wrappers for errors from Nova's admin api.
1130-"""
1131-
1132-import boto.exception
1133-from django.shortcuts import redirect
1134-from django.core import exceptions as core_exceptions
1135-
1136-
1137-class NovaServerError(Exception):
1138- """
1139- Consumes a BotoServerError and gives more meaningful errors.
1140- """
1141- def __init__(self, ec2error):
1142- self.status = ec2error.status
1143- self.message = ec2error.reason
1144-
1145- def __str__(self):
1146- return self.message
1147-
1148-
1149-class NovaApiError(Exception):
1150- """
1151- Used when Nova returns a 400 Bad Request status.
1152- """
1153- def __init__(self, ec2error):
1154- self.message = ec2error.error_message
1155-
1156- def __str__(self):
1157- return self.message
1158-
1159-
1160-class NovaUnavailableError(NovaServerError):
1161- """
1162- Used when Nova returns a 503 Service Unavailable status.
1163- """
1164- pass
1165-
1166-
1167-class NovaUnauthorizedError(core_exceptions.PermissionDenied):
1168- """
1169- Used when Nova returns a 401 Not Authorized status.
1170- """
1171- pass
1172-
1173-
1174-def wrap_nova_error(func):
1175- """
1176- Used to decorate a function that interacts with boto. It will catch
1177- and convert boto server errors and reraise as a more specific nova error.
1178- """
1179- def decorator(*args, **kwargs):
1180- try:
1181- return func(*args, **kwargs)
1182- except boto.exception.BotoServerError, e:
1183- if e.status == 400 and e.error_code == 'ApiError':
1184- raise NovaApiError(e)
1185- elif e.status == 401:
1186- raise NovaUnauthorizedError()
1187- elif e.status == 503:
1188- raise NovaUnavailableError(e)
1189- raise NovaServerError(e)
1190- return decorator
1191-
1192-
1193-def handle_nova_error(func):
1194- """
1195- Decorator for handling nova errors in a generalized way.
1196- """
1197- def decorator(*args, **kwargs):
1198- try:
1199- return func(*args, **kwargs)
1200- except NovaUnavailableError:
1201- return redirect('nova_unavailable')
1202- return decorator
1203-
1204-
1205
1206=== removed file 'src/django_nova/forms.py'
1207--- src/django_nova/forms.py 2011-01-21 22:38:42 +0000
1208+++ src/django_nova/forms.py 1970-01-01 00:00:00 +0000
1209@@ -1,262 +0,0 @@
1210-# vim: tabstop=4 shiftwidth=4 softtabstop=4
1211-
1212-# Copyright 2010 United States Government as represented by the
1213-# Administrator of the National Aeronautics and Space Administration.
1214-# All Rights Reserved.
1215-#
1216-# Licensed under the Apache License, Version 2.0 (the "License"); you may
1217-# not use this file except in compliance with the License. You may obtain
1218-# a copy of the License at
1219-#
1220-# http://www.apache.org/licenses/LICENSE-2.0
1221-#
1222-# Unless required by applicable law or agreed to in writing, software
1223-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1224-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1225-# License for the specific language governing permissions and limitations
1226-# under the License.
1227-
1228-"""
1229-Forms used by various views.
1230-"""
1231-
1232-import re
1233-
1234-from django import forms
1235-from django.contrib.auth import models as auth_models
1236-from django_nova.connection import get_nova_admin_connection
1237-from django_nova.exceptions import wrap_nova_error
1238-
1239-
1240-# TODO: Store this in settings.
1241-MAX_VOLUME_SIZE = 100
1242-
1243-alphanumeric_re = re.compile(r'^\w+$')
1244-
1245-
1246-@wrap_nova_error
1247-def get_instance_type_choices():
1248- """
1249- Returns list of instance types from nova admin api
1250- """
1251- nova = get_nova_admin_connection()
1252- instance_types = nova.get_instance_types()
1253- rv = []
1254- for t in instance_types:
1255- rv.append((t.name, "%s (%sMB memory, %s cpu, %sGB space)" % \
1256- (t.name, t.memory_mb, t.vcpus, t.disk_gb)))
1257- return rv
1258-
1259-def get_instance_choices(project):
1260- choices = [(i.id, i.id) for i in project.get_instances()]
1261- if not len(choices):
1262- choices = [('', 'none available')]
1263- return choices
1264-
1265-def get_key_pair_choices(project):
1266- choices = [(k.name, k.name) for k in project.get_key_pairs()]
1267- if not len(choices):
1268- choices = [('', 'none available')]
1269- return choices
1270-
1271-#def get_security_group_choices(project):
1272-# choices = [(g.name, g.description) for g in project.get_security_groups()]
1273-# if len(choices) == 0:
1274-# choices = [('', 'none available')]
1275-# return choices
1276-
1277-def get_available_volume_choices(project):
1278- choices = [(v.id, '%s %s - %dGB' % (v.id, v.displayName, v.size)) for v in \
1279- project.get_volumes() if v.status != "in-use"]
1280- if not len(choices):
1281- choices = [('', 'none available')]
1282- return choices
1283-
1284-def get_protocols():
1285- return (
1286- ('tcp', 'tcp'),
1287- ('udp', 'udp'),
1288- )
1289-
1290-@wrap_nova_error
1291-def get_roles(project_roles=True):
1292- nova = get_nova_admin_connection()
1293- roles = nova.get_roles(project_roles=project_roles)
1294- return [(role.role, role.role) for role in roles]
1295-
1296-@wrap_nova_error
1297-def get_members(project):
1298- nova = get_nova_admin_connection()
1299- members = nova.get_project_members(project)
1300- return [str(user.memberId) for user in members]
1301-
1302-@wrap_nova_error
1303-def set_project_roles(projectname, username, roles):
1304- nova = get_nova_admin_connection()
1305- # hacky work around to interface correctly with multiple select form
1306- _remove_roles(projectname, username)
1307-
1308- for role in roles:
1309- nova.add_user_role(username, str(role), projectname)
1310-
1311-def _remove_roles(project, username):
1312- nova = get_nova_admin_connection()
1313- userroles = nova.get_user_roles(username, project)
1314- roles = [str(role.role) for role in userroles]
1315-
1316- for role in roles:
1317- if role == "developer":
1318- nova.remove_user_role(username, "developer", project)
1319- if role == "sysadmin":
1320- nova.remove_user_role(username, "sysadmin", project)
1321- if role == "netadmin":
1322- nova.remove_user_role(username, "netadmin", project)
1323-
1324-
1325-class ProjectFormBase(forms.Form):
1326- def __init__(self, project, *args, **kwargs):
1327- self.project = project
1328- super(ProjectFormBase, self).__init__(*args, **kwargs)
1329-
1330-
1331-class LaunchInstanceForm(forms.Form):
1332- # nickname = forms.CharField()
1333- # description = forms.CharField()
1334-
1335- count = forms.ChoiceField(choices=[(x, x) for x in range(1, 6)])
1336- size = forms.ChoiceField()
1337- key_name = forms.ChoiceField()
1338- #security_group = forms.ChoiceField()
1339- user_data = forms.CharField(required=False, widget=forms.widgets.Textarea(attrs={'rows': 4}))
1340-
1341- def __init__(self, project, *args, **kwargs):
1342- forms.Form.__init__(self, *args, **kwargs)
1343- #self.fields['security_group'].choices = get_security_group_choices(project)
1344- self.fields['key_name'].choices = get_key_pair_choices(project)
1345- self.fields['size'].choices = get_instance_type_choices()
1346-
1347-
1348-class UpdateInstanceForm(forms.Form):
1349- nickname = forms.CharField(required=False, label="Name")
1350- description = forms.CharField(required=False, widget=forms.Textarea, max_length=70)
1351-
1352- def __init__(self, instance, *args, **kwargs):
1353- forms.Form.__init__(self, *args, **kwargs)
1354- self.fields['nickname'].initial = instance.displayName
1355- self.fields['description'].initial = instance.displayDescription
1356-
1357-
1358-class UpdateImageForm(forms.Form):
1359- nickname = forms.CharField(required=False, label="Name")
1360- description = forms.CharField(required=False, widget=forms.Textarea, max_length=70)
1361-
1362- def __init__(self, image, *args, **kwargs):
1363- forms.Form.__init__(self, *args, **kwargs)
1364- self.fields['nickname'].initial = image.displayName
1365- self.fields['description'].initial = image.description
1366-
1367-
1368-class CreateKeyPairForm(ProjectFormBase):
1369- name = forms.RegexField(regex=alphanumeric_re)
1370-
1371- def clean_name(self):
1372- name = self.cleaned_data['name']
1373-
1374- if self.project.has_key_pair(name):
1375- raise forms.ValidationError('A key named %s already exists.' % name)
1376-
1377- return name
1378-
1379-
1380-class CreateSecurityGroupForm(ProjectFormBase):
1381- name = forms.RegexField(regex=alphanumeric_re)
1382- description = forms.CharField()
1383-
1384- def clean_name(self):
1385- name = self.cleaned_data['name']
1386-
1387- if self.project.has_security_group(name):
1388- raise forms.ValidationError('A security group named %s already exists.' % name)
1389-
1390- return name
1391-
1392-
1393-class AuthorizeSecurityGroupRuleForm(forms.Form):
1394- protocol = forms.ChoiceField(choices=get_protocols())
1395- from_port = forms.IntegerField(min_value=1, max_value=65535)
1396- to_port = forms.IntegerField(min_value=1, max_value=65535)
1397-
1398-
1399-class CreateVolumeForm(forms.Form):
1400- size = forms.IntegerField(label='Size (in GB)', min_value=1, max_value=MAX_VOLUME_SIZE)
1401- nickname = forms.CharField()
1402- description = forms.CharField()
1403-
1404-
1405-class AttachVolumeForm(ProjectFormBase):
1406- volume = forms.ChoiceField()
1407- instance = forms.ChoiceField()
1408- device = forms.CharField(initial='/dev/vdb')
1409-
1410- def __init__(self, project, *args, **kwargs):
1411- super(AttachVolumeForm, self).__init__(project, *args, **kwargs)
1412- self.fields['volume'].choices = get_available_volume_choices(project)
1413- self.fields['instance'].choices = get_instance_choices(project)
1414-
1415-
1416-class ProjectForm(forms.Form):
1417- projectname = forms.CharField(label="Project Name", max_length=20)
1418- description = forms.CharField(label="Description",
1419- widget=forms.widgets.Textarea())
1420- manager = forms.ModelChoiceField(queryset=auth_models.User.objects.all(),
1421- label="Project Manager")
1422-
1423-
1424-class GlobalRolesForm(forms.Form):
1425- role = forms.MultipleChoiceField(label='Roles', required=False)
1426-
1427- def __init__(self, *args, **kwargs):
1428- super(GlobalRolesForm, self).__init__(*args, **kwargs)
1429- self.fields['role'].choices = get_roles(project_roles=False)
1430-
1431-
1432-class ProjectUserForm(forms.Form):
1433- role = forms.MultipleChoiceField(label='Roles', required=False)
1434-
1435- def __init__(self, project, user, *args, **kwargs):
1436- super(ProjectUserForm, self).__init__(*args, **kwargs)
1437- self.project = project
1438- self.user = user
1439- self.fields['role'].choices = get_roles()
1440-
1441- def save(self):
1442- set_project_roles(self.project.projectname,
1443- self.user.username,
1444- self.cleaned_data['role'])
1445-
1446-
1447-class AddProjectUserForm(forms.Form):
1448- username = forms.ModelChoiceField(queryset='',
1449- label='Username',
1450- empty_label='Select a Username')
1451- role = forms.MultipleChoiceField(label='Roles')
1452-
1453- def __init__(self, *args, **kwargs):
1454- project = kwargs.pop('project')
1455- super(AddProjectUserForm, self).__init__(*args, **kwargs)
1456- members = get_members(project)
1457-
1458- self.fields['username'].queryset = \
1459- auth_models.User.objects.exclude(username__in=members)
1460- self.fields['role'].choices = get_roles()
1461-
1462-
1463-class SendCredentialsForm(forms.Form):
1464- users = forms.MultipleChoiceField(label='Users', required=True)
1465-
1466- def __init__(self, *args, **kwargs):
1467- query_list = kwargs.pop('query_list')
1468- super(SendCredentialsForm, self).__init__(*args, **kwargs)
1469-
1470- self.fields['users'].choices = [(choices, choices) for choices in query_list]
1471-
1472
1473=== removed directory 'src/django_nova/management'
1474=== removed file 'src/django_nova/management/__init__.py'
1475=== removed directory 'src/django_nova/management/commands'
1476=== removed file 'src/django_nova/management/commands/__init__.py'
1477=== removed file 'src/django_nova/management/commands/createnovausers.py'
1478--- src/django_nova/management/commands/createnovausers.py 2011-01-12 20:02:06 +0000
1479+++ src/django_nova/management/commands/createnovausers.py 1970-01-01 00:00:00 +0000
1480@@ -1,37 +0,0 @@
1481-# vim: tabstop=4 shiftwidth=4 softtabstop=4
1482-
1483-# Copyright 2010 United States Government as represented by the
1484-# Administrator of the National Aeronautics and Space Administration.
1485-# All Rights Reserved.
1486-#
1487-# Licensed under the Apache License, Version 2.0 (the "License"); you may
1488-# not use this file except in compliance with the License. You may obtain
1489-# a copy of the License at
1490-#
1491-# http://www.apache.org/licenses/LICENSE-2.0
1492-#
1493-# Unless required by applicable law or agreed to in writing, software
1494-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1495-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1496-# License for the specific language governing permissions and limitations
1497-# under the License.
1498-"""
1499-Management commands for synchronizing the Django auth database and Nova
1500-users database.
1501-"""
1502-
1503-from django.core.management.base import NoArgsCommand
1504-from django.contrib.auth.models import User
1505-from django_nova.connection import get_nova_admin_connection
1506-
1507-class Command(NoArgsCommand):
1508- help = 'Creates nova users for all users in the django auth database.'
1509-
1510- def handle_noargs(self, **options):
1511- nova = get_nova_admin_connection()
1512- users = User.objects.all()
1513- for user in users:
1514- if not nova.has_user(user.username):
1515- self.stdout.write('creating user %s... ' % user.username)
1516- nova.create_user(user.username)
1517- self.stdout.write('ok\n')
1518
1519=== removed file 'src/django_nova/manager.py'
1520--- src/django_nova/manager.py 2011-01-24 00:02:34 +0000
1521+++ src/django_nova/manager.py 1970-01-01 00:00:00 +0000
1522@@ -1,340 +0,0 @@
1523-# vim: tabstop=4 shiftwidth=4 softtabstop=4
1524-
1525-# Copyright 2010 United States Government as represented by the
1526-# Administrator of the National Aeronautics and Space Administration.
1527-# All Rights Reserved.
1528-#
1529-# Licensed under the Apache License, Version 2.0 (the "License"); you may
1530-# not use this file except in compliance with the License. You may obtain
1531-# a copy of the License at
1532-#
1533-# http://www.apache.org/licenses/LICENSE-2.0
1534-#
1535-# Unless required by applicable law or agreed to in writing, software
1536-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1537-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1538-# License for the specific language governing permissions and limitations
1539-# under the License.
1540-"""
1541-Simple API for interacting with Nova projects.
1542-"""
1543-
1544-import boto
1545-import boto.ec2.volume
1546-import boto.exception
1547-import boto.s3
1548-from django.conf import settings
1549-from django_nova.connection import get_nova_admin_connection
1550-from django_nova.exceptions import wrap_nova_error
1551-
1552-
1553-class ProjectManager(object):
1554- def __init__(self, username, project, region):
1555- self.username = username
1556- self.projectname = project.projectname
1557- self.projectManagerId = project.projectManagerId
1558- self.region = region
1559-
1560- def get_nova_connection(self):
1561- """
1562- Returns a boto connection for a user's project.
1563- """
1564- nova = get_nova_admin_connection()
1565- return nova.connection_for(self.username,
1566- self.projectname,
1567- clc_url=self.region['endpoint'],
1568- region=self.region['name'])
1569-
1570- def get_zip(self):
1571- """
1572- Returns a buffer of a zip file containing signed credentials
1573- for the project's Nova user.
1574- """
1575- nova = get_nova_admin_connection()
1576- return nova.get_zip(self.username, self.projectname)
1577-
1578- def get_images(self, image_ids=None):
1579- conn = self.get_nova_connection()
1580- images = conn.get_all_images(image_ids=image_ids)
1581- sorted_images = [i for i in images if i.ownerId == self.username] + \
1582- [i for i in images if i.ownerId != self.username]
1583-
1584- return [i for i in sorted_images if i.type == 'machine' and i.location.split('/')[0] != 'nova']
1585-
1586- def get_image(self, image_id):
1587- try:
1588- return self.get_images(image_ids=[image_id,])[0]
1589- except IndexError:
1590- return None
1591-
1592- @wrap_nova_error
1593- def deregister_image(self, image_id):
1594- """
1595- Removes the image's listing but leaves the image
1596- and manifest in the object store in tact.
1597- """
1598- conn = self.get_nova_connection()
1599- return conn.deregister_image(image_id)
1600-
1601- @wrap_nova_error
1602- def update_image(self, image_id, display_name=None, description=None):
1603- conn = self.get_nova_connection()
1604- params = {
1605- 'ImageId': image_id,
1606- 'DisplayName': display_name,
1607- 'Description': description
1608- }
1609- return conn.get_object('UpdateImage', params, boto.ec2.image.Image)
1610-
1611- @wrap_nova_error
1612- def modify_image_attribute(self, image_id, attribute=None, operation=None,
1613- groups='all'):
1614- conn = self.get_nova_connection()
1615- return conn.modify_image_attribute(image_id,
1616- attribute='launchPermission',
1617- operation='remove',
1618- groups='all',)
1619-
1620-
1621- @wrap_nova_error
1622- def run_instances(self, image_id, **kwargs):
1623- """
1624- Runs instances of the specified image id.
1625- """
1626- conn = self.get_nova_connection()
1627- return conn.run_instances(image_id, **kwargs)
1628-
1629- def get_instance_count(self):
1630- """
1631- Returns the number of active instances in this project or None if unknown.
1632- """
1633- try:
1634- return len(self.get_instances())
1635- except:
1636- return None
1637-
1638- @wrap_nova_error
1639- def get_instances(self):
1640- """
1641- Returns all instances in this project.
1642- """
1643- conn = self.get_nova_connection()
1644- reservations = conn.get_all_instances()
1645- instances = []
1646- for reservation in reservations:
1647- for instance in reservation.instances:
1648- instances.append(instance)
1649- return instances
1650-
1651- @wrap_nova_error
1652- def get_instance(self, instance_id):
1653- """
1654- Returns detail about the specified instance.
1655- """
1656- conn = self.get_nova_connection()
1657- # TODO: Refactor this once nova's describe_instances filters by instance_id.
1658- reservations = conn.get_all_instances()
1659- for reservation in reservations:
1660- for instance in reservation.instances:
1661- if instance.id == instance_id:
1662- return instance
1663- return None
1664-
1665- @wrap_nova_error
1666- def update_instance(self, instance_id, updates):
1667- conn = self.get_nova_connection()
1668- params = {'InstanceId': instance_id, 'DisplayName': updates['nickname'],
1669- 'DisplayDescription': updates['description']}
1670- return conn.get_object('UpdateInstance', params,
1671- boto.ec2.instance.Instance)
1672-
1673- def get_instance_graph(self, region, instance_id, graph_name):
1674- # TODO(devcamcar): Need better support for multiple regions.
1675- # Need a way to get object store by region.
1676- s3 = boto.s3.connection.S3Connection (
1677- aws_access_key_id=settings.NOVA_ACCESS_KEY,
1678- aws_secret_access_key=settings.NOVA_SECRET_KEY,
1679- is_secure=False,
1680- calling_format=boto.s3.connection.OrdinaryCallingFormat(),
1681- port=3333,
1682- host=settings.NOVA_CLC_IP
1683- )
1684- key = '_%s.monitor' % instance_id
1685-
1686- try:
1687- bucket = s3.get_bucket(key, validate=False)
1688- except boto.exception.S3ResponseError, e:
1689- if e.code == "NoSuchBucket":
1690- return None
1691- else:
1692- raise e
1693-
1694- key = bucket.get_key(graph_name)
1695-
1696- return key.read()
1697-
1698- @wrap_nova_error
1699- def terminate_instance(self, instance_id):
1700- """ Terminates the specified instance within this project. """
1701- conn = self.get_nova_connection()
1702- conn.terminate_instances([instance_id])
1703-
1704- @wrap_nova_error
1705- def get_security_groups(self):
1706- """
1707- Returns all security groups associated with this project.
1708- """
1709- conn = self.get_nova_connection()
1710- groups = []
1711-
1712- for g in conn.get_all_security_groups():
1713- # Do not show vpn group.
1714- #if g.name != 'vpn-secgroup':
1715- groups.append(g)
1716-
1717- return groups
1718-
1719- @wrap_nova_error
1720- def get_security_group(self, name):
1721- """
1722- Returns the specified security group for this project.
1723- """
1724- conn = self.get_nova_connection()
1725-
1726- try:
1727- return conn.get_all_security_groups(groupnames=name.encode('ASCII'))[0]
1728- except IndexError:
1729- return None
1730-
1731- @wrap_nova_error
1732- def has_security_group(self, name):
1733- """
1734- Indicates whether a security group with the specified name exists in this project.
1735- """
1736- return self.get_security_group(name) is not None
1737-
1738- @wrap_nova_error
1739- def create_security_group(self, name, description):
1740- """
1741- Creates a new security group in this project.
1742- """
1743- conn = self.get_nova_connection()
1744- return conn.create_security_group(name, description)
1745-
1746- @wrap_nova_error
1747- def delete_security_group(self, name):
1748- """
1749- Deletes a security group from the project.
1750- """
1751- conn = self.get_nova_connection()
1752- return conn.delete_security_group(name = name)
1753-
1754- @wrap_nova_error
1755- def authorize_security_group(self, group_name, ip_protocol, from_port, to_port):
1756- """
1757- Authorizes a rule for the specified security group.
1758- """
1759- conn = self.get_nova_connection()
1760- return conn.authorize_security_group (
1761- group_name = group_name,
1762- ip_protocol = ip_protocol,
1763- from_port = from_port,
1764- to_port = to_port,
1765- cidr_ip = '0.0.0.0/0'
1766- )
1767-
1768- @wrap_nova_error
1769- def revoke_security_group(self, group_name, ip_protocol, from_port, to_port):
1770- """
1771- Revokes a rule for the specified security group.
1772- """
1773- conn = self.get_nova_connection()
1774- return conn.revoke_security_group (
1775- group_name = group_name,
1776- ip_protocol = ip_protocol,
1777- from_port = from_port,
1778- to_port = to_port,
1779- cidr_ip = '0.0.0.0/0'
1780- )
1781-
1782- @wrap_nova_error
1783- def get_key_pairs(self):
1784- """
1785- Returns all key pairs associated with this project.
1786- """
1787- conn = self.get_nova_connection()
1788- keys = []
1789-
1790- for k in conn.get_all_key_pairs():
1791- # Do not show vpn key.
1792- if k.name != 'vpn-key':
1793- keys.append(k)
1794-
1795- return keys
1796-
1797- @wrap_nova_error
1798- def get_key_pair(self, name):
1799- """
1800- Returns the specified security group for this project.
1801- """
1802- conn = self.get_nova_connection()
1803-
1804- try:
1805- return conn.get_all_key_pairs(keynames=name.encode('ASCII'))[0]
1806- except IndexError:
1807- return None
1808-
1809- @wrap_nova_error
1810- def has_key_pair(self, name):
1811- """
1812- Indicates whether a key pair with the specified name exists in this project.
1813- """
1814- return self.get_key_pair(name) != None
1815-
1816- @wrap_nova_error
1817- def create_key_pair(self, name):
1818- """
1819- Creates a new key pair for this project.
1820- """
1821- conn = self.get_nova_connection()
1822- return conn.create_key_pair(name)
1823-
1824- @wrap_nova_error
1825- def delete_key_pair(self, name):
1826- """
1827- Deletes a new key pair from this project.
1828- """
1829- conn = self.get_nova_connection()
1830- conn.delete_key_pair(name)
1831-
1832- @wrap_nova_error
1833- def get_volumes(self):
1834- """
1835- Returns all volumes in this project.
1836- """
1837- conn = self.get_nova_connection()
1838- return conn.get_all_volumes()
1839-
1840- @wrap_nova_error
1841- def create_volume(self, size, display_name=None, display_description=None,
1842- snapshot=None):
1843- conn = self.get_nova_connection()
1844- params = {'Size': size, 'DisplayName': display_name,
1845- 'DisplayDescription': display_description}
1846- return conn.get_object('CreateVolume', params, boto.ec2.volume.Volume)
1847-
1848- @wrap_nova_error
1849- def delete_volume(self, volume_id):
1850- conn = self.get_nova_connection()
1851- return conn.delete_volume(volume_id)
1852-
1853- @wrap_nova_error
1854- def attach_volume(self, volume_id, instance_id, device):
1855- conn = self.get_nova_connection()
1856- return conn.attach_volume(volume_id, instance_id, device)
1857-
1858- @wrap_nova_error
1859- def detach_volume(self, volume_id):
1860- conn = self.get_nova_connection()
1861- return conn.detach_volume(volume_id)
1862-
1863
1864=== removed file 'src/django_nova/models.py'
1865--- src/django_nova/models.py 2011-01-15 11:26:01 +0000
1866+++ src/django_nova/models.py 1970-01-01 00:00:00 +0000
1867@@ -1,121 +0,0 @@
1868-# vim: tabstop=4 shiftwidth=4 softtabstop=4
1869-
1870-# Copyright 2010 United States Government as represented by the
1871-# Administrator of the National Aeronautics and Space Administration.
1872-# All Rights Reserved.
1873-#
1874-# Licensed under the Apache License, Version 2.0 (the "License"); you may
1875-# not use this file except in compliance with the License. You may obtain
1876-# a copy of the License at
1877-#
1878-# http://www.apache.org/licenses/LICENSE-2.0
1879-#
1880-# Unless required by applicable law or agreed to in writing, software
1881-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1882-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1883-# License for the specific language governing permissions and limitations
1884-# under the License.
1885-"""
1886-Database models for authorization credentials and synchronizing Nova users.
1887-"""
1888-
1889-import datetime
1890-import random
1891-import re
1892-import sha
1893-from django.conf import settings
1894-from django.contrib.auth import models as auth_models
1895-from django.contrib.sites import models as site_models
1896-from django.core import mail
1897-from django.db import models
1898-from django.db.models.signals import post_save
1899-from django.template.loader import render_to_string
1900-from django_nova.connection import get_nova_admin_connection
1901-
1902-
1903-SHA1_RE=re.compile('^[a-f0-9]{40}$')
1904-
1905-
1906-class CredentialsAuthorization(models.Model):
1907- username = models.CharField(max_length=128)
1908- project = models.CharField(max_length=128)
1909- auth_token = models.CharField(max_length=40)
1910- auth_date = models.DateTimeField(auto_now_add=True)
1911-
1912- def __str__(self):
1913- return '%s/%s:%s' % (self.username, self.project, self.auth_token)
1914-
1915- @classmethod
1916- def get_by_token(cls, token):
1917- if SHA1_RE.search(token):
1918- try:
1919- credentials = cls.objects.get(auth_token=token)
1920- except cls.DoesNotExist:
1921- return None
1922- if not credentials.auth_token_expired():
1923- return credentials
1924- return None
1925-
1926- @classmethod
1927- def authorize(cls, username, project):
1928- return cls.objects.create(username=username,
1929- project=project,
1930- auth_token=cls.create_auth_token(username))
1931-
1932- @staticmethod
1933- def create_auth_token(username):
1934- salt = sha.new(str(random.random())).hexdigest()[:5]
1935- return sha.new(salt+username).hexdigest()
1936-
1937- def auth_token_expired(self):
1938- expiration_date = datetime.timedelta(days=int(settings.CREDENTIAL_AUTHORIZATION_DAYS))
1939-
1940- return self.auth_date + expiration_date <= datetime.datetime.now()
1941-
1942- def get_download_url(self):
1943- return settings.CREDENTIAL_DOWNLOAD_URL + self.auth_token
1944-
1945- def get_zip(self):
1946- nova = get_nova_admin_connection()
1947- self.delete()
1948- return nova.get_zip(self.username, self.project)
1949-
1950-
1951-def credentials_post_save(sender, instance, created, *args, **kwargs):
1952- """
1953- Creates a Nova User when a new Django User is created.
1954- """
1955- if created:
1956- site = site_models.Site.objects.get_current()
1957- user = auth_models.User.objects.get(username=instance.username)
1958- context = {
1959- 'user': user,
1960- 'download_url': instance.get_download_url(),
1961- 'dashboard_url': 'http://%s/' % site.domain
1962- }
1963- subject = render_to_string('credentials/credentials_email_subject.txt')
1964- body = render_to_string('credentials/credentials_email.txt', context)
1965-
1966- message = mail.EmailMessage(subject=subject, body=body, to=[user.email])
1967- message.send(fail_silently=False)
1968-post_save.connect(credentials_post_save,
1969- CredentialsAuthorization,
1970- dispatch_uid='django_nova.CredentialsAuthorization.post_save')
1971-
1972-
1973-def user_post_save(sender, instance, created, *args, **kwargs):
1974- """
1975- Creates a Nova User when a new Django User is created.
1976- """
1977-
1978- # NOTE(devcamcar): If running unit tests, don't use a real endpoint.
1979- if settings.NOVA_DEFAULT_ENDPOINT == 'none':
1980- return
1981-
1982- if created:
1983- nova = get_nova_admin_connection()
1984- if not nova.has_user(instance.username):
1985- nova.create_user(instance.username)
1986-post_save.connect(user_post_save,
1987- auth_models.User,
1988- dispatch_uid='django_nova.User.post_save')
1989
1990=== removed file 'src/django_nova/shortcuts.py'
1991--- src/django_nova/shortcuts.py 2011-01-31 20:24:02 +0000
1992+++ src/django_nova/shortcuts.py 1970-01-01 00:00:00 +0000
1993@@ -1,131 +0,0 @@
1994-# vim: tabstop=4 shiftwidth=4 softtabstop=4
1995-
1996-# Copyright 2010 United States Government as represented by the
1997-# Administrator of the National Aeronautics and Space Administration.
1998-# All Rights Reserved.
1999-#
2000-# Licensed under the Apache License, Version 2.0 (the "License"); you may
2001-# not use this file except in compliance with the License. You may obtain
2002-# a copy of the License at
2003-#
2004-# http://www.apache.org/licenses/LICENSE-2.0
2005-#
2006-# Unless required by applicable law or agreed to in writing, software
2007-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
2008-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
2009-# License for the specific language governing permissions and limitations
2010-# under the License.
2011-
2012-"""
2013-Helper methods for commonly used operations.
2014-"""
2015-
2016-from django.conf import settings
2017-from django.core.cache import cache
2018-from django.core.exceptions import PermissionDenied
2019-from django.http import Http404
2020-from django_nova import manager
2021-from django_nova.connection import get_nova_admin_connection
2022-from django_nova.exceptions import wrap_nova_error
2023-
2024-
2025-@wrap_nova_error
2026-def get_project_or_404(request, project_id):
2027- """
2028- Returns a project or 404s if it doesn't exist.
2029- """
2030-
2031- # Ensure that a connection is never attempted for a user that is unauthenticated.
2032- if not request.user.is_authenticated:
2033- raise PermissionDenied('User not authenticated')
2034-
2035- nova = get_nova_admin_connection()
2036- project = nova.get_project(project_id)
2037- region = get_current_region(request)
2038-
2039- if not project:
2040- raise Http404('Project %s does not exist.' % project_id)
2041-
2042- return manager.ProjectManager(request.user, project, region)
2043-
2044-
2045-@wrap_nova_error
2046-def get_projects(user):
2047- """
2048- Returns a list of projects for a user.
2049- """
2050- #key = 'projects.%s' % user
2051- #projects = cache.get(key)
2052-
2053- #if not projects:
2054- # nova = get_nova_admin_connection()
2055- # projects = nova.get_projects(user=user)
2056- # cache.set(key, projects, 30)
2057-
2058- #return projects
2059- nova = get_nova_admin_connection()
2060- return nova.get_projects(user=user)
2061-
2062-
2063-@wrap_nova_error
2064-def get_all_regions():
2065- """
2066- Returns a list of all regions.
2067- """
2068- regions = cache.get('regions')
2069-
2070- if not regions:
2071- nova = get_nova_admin_connection()
2072- conn = nova.connection_for(settings.NOVA_ADMIN_USER, settings.NOVA_PROJECT)
2073- results = conn.get_all_regions()
2074- regions = [{'name': r.name, 'endpoint': r.endpoint} for r in results]
2075- cache.set('regions', regions, 60 * 60 * 24)
2076-
2077- return regions
2078-
2079-
2080-def get_region(region_name):
2081- regions = get_all_regions()
2082- try:
2083- return [r for r in regions if r['name'] == region_name][0]
2084- except IndexError:
2085- return None
2086-
2087-
2088-def get_current_region(request):
2089- """
2090- Returns the currently selected region for a user.
2091- """
2092- region_name = request.session.get('region', settings.NOVA_DEFAULT_REGION)
2093- return get_region(region_name)
2094-
2095-
2096-def set_current_region(request, region_name):
2097- """
2098- Sets the current region selection for a user.
2099- """
2100- request.session['region'] = region_name
2101-
2102-
2103-@wrap_nova_error
2104-def get_user_image_permissions(username, project_name):
2105- """
2106- Returns true if user is a sysadmin and can modify image attributes.
2107- """
2108- nova = get_nova_admin_connection()
2109- user_has_modify_permissions = False
2110-
2111- # checks global roles, if user is a sysadmin they can modify image attribtues.
2112- if not user_has_modify_permissions:
2113- for role in nova.get_user_roles(username):
2114- if role.role == "sysadmin":
2115- user_has_modify_permissions = True
2116-
2117- # checks project roles, if user is a sysadmin they can modify image attribtues.
2118- if not user_has_modify_permissions:
2119- for role in nova.get_user_roles(username, project_name):
2120- if role.role == "sysadmin":
2121- user_has_modify_permissions = True
2122-
2123- return user_has_modify_permissions
2124-
2125
2126=== removed directory 'src/django_nova/templates'
2127=== removed directory 'src/django_nova/templates/admin'
2128=== removed directory 'src/django_nova/templates/admin/django_nova'
2129=== removed directory 'src/django_nova/templates/admin/django_nova/project'
2130=== removed file 'src/django_nova/templates/admin/django_nova/project/add_project.html'
2131--- src/django_nova/templates/admin/django_nova/project/add_project.html 2011-01-12 20:02:06 +0000
2132+++ src/django_nova/templates/admin/django_nova/project/add_project.html 1970-01-01 00:00:00 +0000
2133@@ -1,45 +0,0 @@
2134-{% extends "admin/django_nova/project/base_projects.html" %}
2135-{% load admin_modify adminmedia %}
2136-
2137-{% block extrahead %}
2138-{{ block.super }}
2139-{{ media }}
2140-{% endblock %}
2141-
2142-{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/forms.css" />{% endblock %}
2143-
2144-{% block coltype %}colMS{% endblock %}
2145-
2146-{% block bodyclass %} change-form{% endblock %}
2147-
2148-{% block breadcrumbs %}
2149-<div class="breadcrumbs">
2150- <a href="/admin">Home</a> &rsaquo;
2151- <a href="../../projects">Projects</a> &rsaquo;
2152- Add Project
2153-</div>
2154-{% endblock %}
2155-
2156-{% block content %}
2157-<div id="content-main">
2158- {% block object-tools %}
2159- {% endblock %}
2160- <form action="." method="post" enctype="multipart/form-data">
2161- {% csrf_token %}
2162- <fieldset class="module aligned {{ fieldset.classes }}">
2163- {% for field in form.visible_fields %}
2164- <div class="form-row">
2165- {{ field.errors }}
2166- {{ field.label_tag }}{{ field }}
2167- {% if field.field.help_text %}<p class="help">{{ field.field.help_text|safe }}</p>{% endif %}
2168- </div>
2169- {% endfor %}
2170- {% for field in form.hidden_fields %}
2171- {{ field }}
2172- {% endfor %}
2173-
2174- </fieldset>
2175- <input type="submit" value="Save" />
2176- </form>
2177-</div>
2178-{% endblock %}
2179
2180=== removed file 'src/django_nova/templates/admin/django_nova/project/add_project_user.html'
2181--- src/django_nova/templates/admin/django_nova/project/add_project_user.html 2011-01-12 20:02:06 +0000
2182+++ src/django_nova/templates/admin/django_nova/project/add_project_user.html 1970-01-01 00:00:00 +0000
2183@@ -1,69 +0,0 @@
2184-{% extends "admin/django_nova/project/base_projects.html" %}
2185-{% load admin_modify adminmedia %}
2186-
2187-{% block extrahead %}
2188-{{ block.super }}
2189-{{ media }}
2190-
2191-<script type="text/javascript" src="/media/admin/js/jquery.min.js"></script>
2192-<script type="text/javascript" src="/media/admin/js/jquery.init.js"></script>
2193-
2194-<script type="text/javascript" src="/media/dashboard/js/django-admin.multiselect.js"></script>
2195-<link rel="stylesheet" type="text/css" href="/media/dashboard/css/django-admin-widgets.css" />
2196-
2197-<script type="text/javascript" charset="utf-8">
2198- django.jQuery(function(){
2199- django.jQuery.each(django.jQuery(".edit_user_roles select[multiple]"), function () {
2200- // "Locations" can be any label you want
2201- SelectFilter.init(this.id, "Roles", 0, "/media/admin/");
2202- });
2203- })
2204-</script>
2205-{% endblock %}
2206-
2207-{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/forms.css" />{% endblock %}
2208-
2209-{% block coltype %}colMS{% endblock %}
2210-
2211-{% block bodyclass %} change-form{% endblock %}
2212-
2213-{% block breadcrumbs %}
2214-<div class="breadcrumbs">
2215- <a href="/admin">Home</a> &rsaquo;
2216- <a href="{% url admin_projects %}">Projects</a> &rsaquo;
2217- <a href="{% url admin_project project.projectname %}">{{project.projectname}}</a> &rsaquo;
2218- User
2219- {{form.ProjectUserForm}}
2220-</div>
2221-{% endblock %}
2222-
2223-{% block content %}
2224-<div id="content-main">
2225- {% block object-tools %}
2226- {% endblock %}
2227- <form class="edit_user_roles" action="." method="post" enctype="multipart/form-data">
2228- {% csrf_token %}
2229- <fieldset class="module aligned {{ fieldset.classes }}">
2230- <input type="hidden" name="username" value="{{user.id}}" id="username" />
2231- {% for field in form.visible_fields %}
2232- <div class="form-row">
2233- {{ field.errors }}
2234- {{ field.label_tag }}{{ field }}
2235- {% if field.field.help_text %}<p class="help">{{ field.field.help_text|safe }}</p>{% endif %}
2236- </div>
2237- {% endfor %}
2238- {% for field in form.hidden_fields %}
2239- {{ field }}
2240- {% endfor %}
2241-
2242- </fieldset>
2243- <div class="submit-row">
2244- <p class="deletelink-box">
2245- <a href="{% url admin_project_delete_user project.projectname user.username %}" class="deletelink">Delete</a>
2246- </p>
2247- <input type="submit" value="Save" class="default" />
2248- </div>
2249-
2250- </form>
2251-</div>
2252-{% endblock %}
2253
2254=== removed file 'src/django_nova/templates/admin/django_nova/project/base_projects.html'
2255--- src/django_nova/templates/admin/django_nova/project/base_projects.html 2011-01-12 20:02:06 +0000
2256+++ src/django_nova/templates/admin/django_nova/project/base_projects.html 1970-01-01 00:00:00 +0000
2257@@ -1,16 +0,0 @@
2258-{% extends "admin/change_list.html" %}
2259-
2260-{% block extrastyle %}
2261- {{block.super}}
2262- <link rel="stylesheet" type="text/css" href="{{settings.MEDIA_URL}}/stylesheets/extra_admin.css" />
2263-{% endblock %}
2264-{% block breadcrumbs %}<div class="breadcrumbs"><a href="/admin/">Home</a>&nbsp;&rsaquo;&nbsp;Projects</div>{% endblock %}
2265-{% block content %}
2266- <div id="content-main">
2267- <div class="module filtered" id="changelist">
2268- <div id="toolbartable">
2269- {% block innercontent %}{% endblock %}
2270- </div>
2271- </div>
2272- </div>
2273-{% endblock %}
2274
2275=== removed file 'src/django_nova/templates/admin/django_nova/project/change_list.html'
2276--- src/django_nova/templates/admin/django_nova/project/change_list.html 2011-01-12 20:02:06 +0000
2277+++ src/django_nova/templates/admin/django_nova/project/change_list.html 1970-01-01 00:00:00 +0000
2278@@ -1,3 +0,0 @@
2279-{% extends "admin/change_list.html" %}
2280-{% load admin_extras %}
2281-{% block result_list %}{% project_result_list cl %}{% endblock %}
2282\ No newline at end of file
2283
2284=== removed file 'src/django_nova/templates/admin/django_nova/project/delete_project.html'
2285--- src/django_nova/templates/admin/django_nova/project/delete_project.html 2011-01-12 20:02:06 +0000
2286+++ src/django_nova/templates/admin/django_nova/project/delete_project.html 1970-01-01 00:00:00 +0000
2287@@ -1,25 +0,0 @@
2288-{% extends "admin/change_list.html" %}
2289-
2290-{% block extrastyle %}
2291- {{block.super}}
2292- <link rel="stylesheet" type="text/css" href="{{settings.MEDIA_URL}}/stylesheets/extra_admin.css" />
2293-{% endblock %}
2294-{% block breadcrumbs %}<div class="breadcrumbs"><a href="/admin/">Home</a>&nbsp;&rsaquo;&nbsp;<a href="/admin/projects">Projects</a>&nbsp;&rsaquo;&nbsp; <a href="{% url admin_project project.projectname %}">{{project.projectname}}</a>&nbsp;&rsaquo;&nbsp;Delete</div>{% endblock %}
2295-{% block content %}
2296- <div id="content-main">
2297- <div class="module filtered" id="changelist">
2298- <div id="toolbartable">
2299- <h1>Delete Project</h1>
2300- <p>Do you really want to delete this project?</p>
2301- <ul>
2302- <li><a href="{% url admin_project project.projectname %}">{{project.projectname}}</a></li>
2303- </ul>
2304-
2305- <form action="." method="post">
2306- {% csrf_token %}
2307- <p><input type="submit" value="Delete"></p>
2308- </form>
2309- </div>
2310- </div>
2311- </div>
2312-{% endblock %}
2313
2314=== removed file 'src/django_nova/templates/admin/django_nova/project/delete_project_user.html'
2315--- src/django_nova/templates/admin/django_nova/project/delete_project_user.html 2011-01-12 20:02:06 +0000
2316+++ src/django_nova/templates/admin/django_nova/project/delete_project_user.html 1970-01-01 00:00:00 +0000
2317@@ -1,25 +0,0 @@
2318-{% extends "admin/change_list.html" %}
2319-
2320-{% block extrastyle %}
2321- {{block.super}}
2322- <link rel="stylesheet" type="text/css" href="{{settings.MEDIA_URL}}/stylesheets/extra_admin.css" />
2323-{% endblock %}
2324-{% block breadcrumbs %}<div class="breadcrumbs"><a href="/admin/">Home</a>&nbsp;&rsaquo;&nbsp;<a href="/admin/projects">Projects</a>&nbsp;&rsaquo;&nbsp; <a href="{% url admin_project project.projectname %}">{{project.projectname}}</a>&nbsp;&rsaquo;&nbsp;Delete</div>{% endblock %}
2325-{% block content %}
2326- <div id="content-main">
2327- <div class="module filtered" id="changelist">
2328- <div id="toolbartable">
2329- <h1>Remove User From Project</h1>
2330- <p>Do you really want to remove this user from project?</p>
2331- <ul>
2332- <li><a href="{% url project_user project.projectname user.username %}">{{user.username}}</a> from <a href="{% url admin_project project.projectname %}">{{project.projectname}}</a></li>
2333- </ul>
2334-
2335- <form action="." method="post">
2336- {% csrf_token %}
2337- <p><input type="submit" value="Delete"></p>
2338- </form>
2339- </div>
2340- </div>
2341- </div>
2342-{% endblock %}
2343
2344=== removed file 'src/django_nova/templates/admin/django_nova/project/edit_project.html'
2345--- src/django_nova/templates/admin/django_nova/project/edit_project.html 2011-01-12 20:02:06 +0000
2346+++ src/django_nova/templates/admin/django_nova/project/edit_project.html 1970-01-01 00:00:00 +0000
2347@@ -1,95 +0,0 @@
2348-{% extends "admin/django_nova/project/base_projects.html" %}
2349-{% load admin_modify adminmedia %}
2350-
2351-{% block extrahead %}
2352-{{ block.super }}
2353-{{ media }}
2354-{% endblock %}
2355-
2356-{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/forms.css" />{% endblock %}
2357-
2358-{% block coltype %}colMS{% endblock %}
2359-
2360-{% block bodyclass %} change-form{% endblock %}
2361-
2362-{% block breadcrumbs %}
2363-<div class="breadcrumbs">
2364- <a href="/admin">Home</a> &rsaquo;
2365- <a href="{% url admin_projects %}">Projects</a> &rsaquo;
2366- <a href="{% url admin_project project.projectname %}">{{project.projectname}}</a> &rsaquo;
2367- Edit Project
2368- {{form.ProjectEditForm}}
2369-</div>
2370-{% endblock %}
2371-
2372-{% block content %}
2373-<div id="content-main">
2374- {% block object-tools %}
2375- {% endblock %}
2376- <form action="#" method="post" enctype="multipart/form-data">
2377- {% csrf_token %}
2378- <fieldset class="module aligned {{ fieldset.classes }}">
2379- {% for field in form.visible_fields %}
2380- <div class="form-row">
2381- {{ field.errors }}
2382- {{ field.label_tag }}{{ field }}
2383- {% if field.field.help_text %}<p class="help">{{ field.field.help_text|safe }}</p>{% endif %}
2384- </div>
2385- {% endfor %}
2386- {% for field in form.hidden_fields %}
2387- {{ field }}
2388- {% endfor %}
2389- <div class="form-row">
2390- <label for="project_name">Project Name</label>
2391- <span id="project_name" style="display: block; padding-top: 5px; padding-left: 5px; float: left;"><em>{{projectname}}</em></span>
2392- </div>
2393- <div class="form-row">
2394- <label for="project_description">Description</label>
2395- <span id="project_description" style="display: block; padding-top: 5px; padding-left: 5px; float: left;"><em>{{description}}</em></span>
2396- </div>
2397- <div class="form-row">
2398- <label for="project_manager">Project Manager</label>
2399- <span id="project_manager" style="display: block; padding-top: 5px; padding-left: 5px; float: left;"><em>{{manager}}</em></span>
2400- </div>
2401- </fieldset>
2402- <div class="submit-row">
2403- <p class="deletelink-box">
2404- <a href="{% url delete_project project.projectname %}" class="deletelink">Delete Project</a>
2405- </p>
2406- {# <input type="submit" value="Save" class="default" /> #}
2407- </div>
2408-
2409- </form>
2410-
2411-
2412- <table cellspacing="0" style="margin-top: 20px;">
2413- <thead>
2414- <tr>
2415- <th>Username</th>
2416- <th>Project Roles</th>
2417- <th>Global Roles</th>
2418- </tr>
2419- </thead>
2420- {% for user in users %}
2421- <tr class="{% cycle 'row1' 'row2' %}">
2422- <td>
2423- <a href="{%url project_user project.projectname user.memberId %}">{{user.memberId}} {% if user.memberId == project.projectManagerId %}(<em>project manager</em>){%endif %}</a>
2424-
2425- </td>
2426- <td>
2427- {{user.project_roles}}
2428- </td>
2429- <td>
2430- {{user.global_roles}}
2431- </td>
2432- </tr>
2433- {% endfor %}
2434- </table>
2435- <ul class="object-tools">
2436- <li>
2437- <a class="addlink" href="{% url add_project_user project.projectname %}">Add User</a>
2438- </li>
2439- </ul>
2440-
2441-</div>
2442-{% endblock %}
2443
2444=== removed file 'src/django_nova/templates/admin/django_nova/project/global_edit_user.html'
2445--- src/django_nova/templates/admin/django_nova/project/global_edit_user.html 2011-01-12 20:02:06 +0000
2446+++ src/django_nova/templates/admin/django_nova/project/global_edit_user.html 1970-01-01 00:00:00 +0000
2447@@ -1,71 +0,0 @@
2448-{% extends "admin/django_nova/project/base_projects.html" %}
2449-{% load admin_modify adminmedia %}
2450-
2451-{% block extrahead %}
2452-{{ block.super }}
2453-{{ media }}
2454-
2455-<script type="text/javascript" src="/media/admin/js/jquery.min.js"></script>
2456-<script type="text/javascript" src="/media/admin/js/jquery.init.js"></script>
2457-
2458-<script type="text/javascript" src="/media/dashboard/js/django-admin.multiselect.js"></script>
2459-<link rel="stylesheet" type="text/css" href="/media/dashboard/css/django-admin-widgets.css" />
2460-
2461-<script type="text/javascript" charset="utf-8">
2462- django.jQuery(function(){
2463- django.jQuery.each(django.jQuery("#global_users select"), function () {
2464- // "Locations" can be any label you want
2465- SelectFilter.init(this.id, "Roles", 0, "/media/admin/");
2466- });
2467- })
2468-</script>
2469-{% endblock %}
2470-
2471-{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/forms.css" />{% endblock %}
2472-
2473-{% block coltype %}colMS{% endblock %}
2474-
2475-{% block bodyclass %} change-form{% endblock %}
2476-
2477-{% block breadcrumbs %}
2478-<div class="breadcrumbs">
2479- <a href="/admin">Home</a> &rsaquo;
2480- <a href="{% url admin_users_list %}">Global Roles</a> &rsaquo;
2481- {{user.username}}
2482-</div>
2483-{% endblock %}
2484-
2485-{% block content %}
2486-<div id="content-main">
2487- {% block object-tools %}
2488- {% endblock %}
2489- <form action="." method="post" enctype="multipart/form-data" id="global_users">
2490- {% csrf_token %}
2491- <fieldset class="module aligned {{ fieldset.classes }}">
2492- <div class="form-row">
2493- <label for="id_username">Username</label>
2494- <span>{{user.username}}</span>
2495- </div>
2496- <input type="hidden" name="username" value="{{user.id}}" id="username" />
2497- {% for field in form.visible_fields %}
2498- <div class="form-row">
2499- {{ field.errors }}
2500- {{ field.label_tag }}{{ field }}
2501- {% if field.field.help_text %}<p class="help">{{ field.field.help_text|safe }}</p>{% endif %}
2502- </div>
2503- {% endfor %}
2504- {% for field in form.hidden_fields %}
2505- {{ field }}
2506- {% endfor %}
2507-
2508- </fieldset>
2509- <div class="submit-row">
2510- <p class="deletelink-box">
2511- {# <a href="{% url admin_project_delete_user project.projectname user.username %}" class="deletelink">Delete</a> #}
2512- </p>
2513- <input type="submit" value="Save" class="default" />
2514- </div>
2515-
2516- </form>
2517-</div>
2518-{% endblock %}
2519
2520=== removed file 'src/django_nova/templates/admin/django_nova/project/project_list.html'
2521--- src/django_nova/templates/admin/django_nova/project/project_list.html 2011-01-12 20:02:06 +0000
2522+++ src/django_nova/templates/admin/django_nova/project/project_list.html 1970-01-01 00:00:00 +0000
2523@@ -1,42 +0,0 @@
2524-{% extends "admin/django_nova/project/base_projects.html" %}
2525-{% block extrahead %}
2526- {{ block.super }}
2527-{% endblock %}
2528-{% block innercontent %}
2529- <ul class="object-tools">
2530- <li>
2531- <a class="addlink" href="{% url add_project %}">Add Project</a>
2532- </li>
2533- </ul>
2534- <table cellspacing="0" style="margin-top: 20px;">
2535- <thead>
2536- <tr>
2537- <th>Name</th>
2538- <th>Description</th>
2539- <th>Project Manager</th>
2540- <th>Send Credentials</th>
2541- <th>Start VPN</th>
2542- </tr>
2543- </thead>
2544- {% for project in projects %}
2545- <tr class="{% cycle 'row1' 'row2' %}">
2546- <td>
2547- <a href="{%url admin_project project.projectname %}">{{project.projectname}}</a>
2548- </td>
2549- <td>
2550- {{project.description}}
2551- </td>
2552- <td>
2553- {{project.projectManagerId}}
2554- </td>
2555- <td>
2556- <a href="{% url admin_project_sendcredentials project.projectname %}">Send Credentials</a>
2557- </td>
2558- <td>
2559- <a href="{% url admin_project_start_vpn project.projectname %}">Start VPN</a>
2560- </td>
2561-
2562- </tr>
2563- {% endfor %}
2564- </table>
2565-{% endblock %}
2566
2567=== removed file 'src/django_nova/templates/admin/django_nova/project/project_user.html'
2568--- src/django_nova/templates/admin/django_nova/project/project_user.html 2011-01-12 20:02:06 +0000
2569+++ src/django_nova/templates/admin/django_nova/project/project_user.html 1970-01-01 00:00:00 +0000
2570@@ -1,76 +0,0 @@
2571-{% extends "admin/django_nova/project/base_projects.html" %}
2572-{% load admin_modify adminmedia %}
2573-
2574-{% block extrahead %}
2575-{{ block.super }}
2576-{{ media }}
2577-
2578-<script type="text/javascript" src="/media/admin/js/jquery.min.js"></script>
2579-<script type="text/javascript" src="/media/admin/js/jquery.init.js"></script>
2580-
2581-<script type="text/javascript" src="/media/dashboard/js/django-admin.multiselect.js"></script>
2582-<link rel="stylesheet" type="text/css" href="/media/dashboard/css/django-admin-widgets.css" />
2583-
2584-<script type="text/javascript" charset="utf-8">
2585- django.jQuery(function(){
2586- django.jQuery.each(django.jQuery(".edit_user_roles select[multiple]"), function () {
2587- // "Locations" can be any label you want
2588- SelectFilter.init(this.id, "Roles", 0, "/media/admin/");
2589- });
2590- })
2591-</script>
2592-{% endblock %}
2593-
2594-{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/forms.css" />{% endblock %}
2595-
2596-{% block coltype %}colMS{% endblock %}
2597-
2598-{% block bodyclass %} change-form{% endblock %}
2599-
2600-{% block breadcrumbs %}
2601-<div class="breadcrumbs">
2602- <a href="/admin">Home</a> &rsaquo;
2603- <a href="{% url admin_projects %}">Projects</a> &rsaquo;
2604- <a href="{% url admin_project project.projectname %}">{{project.projectname}}</a> &rsaquo;
2605- User
2606- {{form.ProjectUserForm}}
2607-</div>
2608-{% endblock %}
2609-
2610-{% block content %}
2611-<div id="content-main">
2612- {% block object-tools %}
2613- {% endblock %}
2614- <form class="edit_user_roles" action="." method="post" enctype="multipart/form-data">
2615- {% csrf_token %}
2616- <fieldset class="module aligned {{ fieldset.classes }}">
2617- <div class="form-row">
2618- <label for="id_username">Username</label>
2619- <span>{{user.username}}</span>
2620- </div>
2621- <input type="hidden" name="username" value="{{user.id}}" id="username" />
2622- {% for field in form.visible_fields %}
2623- <div class="form-row">
2624- {{ field.errors }}
2625- {{ field.label_tag }}{{ field }}
2626- {% if field.field.help_text %}<p class="help">{{ field.field.help_text|safe }}</p>{% endif %}
2627- </div>
2628- {% endfor %}
2629- {% for field in form.hidden_fields %}
2630- {{ field }}
2631- {% endfor %}
2632-
2633- </fieldset>
2634- <div class="submit-row">
2635- {% if project.projectManagerId != user.username %}
2636- <p class="deletelink-box">
2637- <a href="{% url admin_project_delete_user project.projectname user.username %}" class="deletelink">Remove User From Project</a>
2638- </p>
2639- {% endif %}
2640-
2641- <input type="submit" value="Save" class="default" />
2642- </div>
2643-
2644- </form>
2645-</div>
2646-{% endblock %}
2647
2648=== removed file 'src/django_nova/templates/admin/django_nova/project/send_credentials.html'
2649--- src/django_nova/templates/admin/django_nova/project/send_credentials.html 2011-01-12 20:02:06 +0000
2650+++ src/django_nova/templates/admin/django_nova/project/send_credentials.html 1970-01-01 00:00:00 +0000
2651@@ -1,87 +0,0 @@
2652-{% extends "admin/base_site.html" %}
2653-{% load i18n admin_modify adminmedia %}
2654-
2655-{% block title %}Send project credentials{{ block.super }}{% endblock %}
2656-
2657-{% block extrahead %}
2658-{{ block.super }}
2659-{{ media }}
2660-
2661-<script type="text/javascript" src="/media/admin/js/jquery.min.js"></script>
2662-<script type="text/javascript" src="/media/admin/js/jquery.init.js"></script>
2663-
2664-<script type="text/javascript" src="/media/dashboard/js/django-admin.multiselect.js"></script>
2665-<link rel="stylesheet" type="text/css" href="/media/dashboard/css/django-admin-widgets.css" />
2666-
2667-<script type="text/javascript" charset="utf-8">
2668- django.jQuery(function(){
2669- django.jQuery.each(django.jQuery("#send_credentials select"), function () {
2670- // "Locations" can be any label you want
2671- SelectFilter.init(this.id, "Users", 0, "/media/admin/");
2672- });
2673- })
2674-</script>
2675-
2676-<style type="text/css" media="screen">
2677- .errorlist, .successlist {background:#fcc;border:1px solid #c66;color:#600;list-style:none; padding: 10px 5px; margin: 25px 0 25px 0; float: left; width: 100%;}
2678- .successlist {background: #CBFBD7; color: #1E5024; border-color: #6FBA5C;}
2679-</style>
2680-{% endblock %}
2681-
2682-
2683-{% block breadcrumbs %}
2684-<div class="breadcrumbs">
2685- <a href="/admin">Home</a> &rsaquo;
2686- <a href="{% url admin_projects %}">Projects</a> &rsaquo;
2687- <a href="{% url admin_project project.projectname %}">{{project.projectname}}</a> &rsaquo;
2688- Send Credentials
2689-</div>
2690-{% endblock %}
2691-
2692-{% block content %}
2693-<div id="content-main">
2694-
2695-
2696- {% if not success %}
2697- <h1>Send Credentials</h1>
2698- <h3>Select which users you would like to send credentials to from the '{{ project.projectname }}' project.</h3>
2699- {% else %}
2700- <h1>Credentials sent successfully</h1>
2701- {% endif %}
2702-
2703- <div class="status">
2704- {% if error %}
2705- <span class="errorlist">{{ error }}</span>
2706- {% endif %}
2707-
2708- {% if success %}
2709- <span class="successlist">{{ success }}</span>
2710- {% endif %}
2711-
2712- </div>
2713-
2714- {% if not success %}
2715- <form id="send_credentials" action="{% url admin_project_sendcredentials project.projectname %}" method="post">
2716- {% csrf_token %}
2717- <fieldset class="module aligned">
2718-
2719- {% for field in form.visible_fields %}
2720- <div class="form-row">
2721- {{ field.errors }}
2722- {{ field }}
2723- {% if field.field.help_text %}<p class="help">{{ field.field.help_text|safe }}</p>{% endif %}
2724- </div>
2725- {% endfor %}
2726- {% for field in form.hidden_fields %}
2727- {{ field }}
2728- {% endfor %}
2729-
2730- </fieldset>
2731- <div class="submit-row">
2732- <input style="margin-top:20px; margin-left:10px;" type="submit" value="Send Credentials" />
2733- </div>
2734-
2735- </form>
2736- {% endif %}
2737-</div>
2738-{% endblock %}
2739
2740=== removed file 'src/django_nova/templates/admin/django_nova/project/user_list.html'
2741--- src/django_nova/templates/admin/django_nova/project/user_list.html 2011-01-12 20:02:06 +0000
2742+++ src/django_nova/templates/admin/django_nova/project/user_list.html 1970-01-01 00:00:00 +0000
2743@@ -1,39 +0,0 @@
2744-{% extends "admin/django_nova/project/base_projects.html" %}
2745-{% block extrahead %}
2746- {{ block.super }}
2747-{% endblock %}
2748-
2749-{% block breadcrumbs %}
2750-<div class="breadcrumbs">
2751- <a href="/admin">Home</a> &rsaquo;
2752- Global Roles
2753-</div>
2754-{% endblock %}
2755-
2756-{% block innercontent %}
2757- <h1>Select a User</h1>
2758-
2759- <table cellspacing="0" style="margin-top: 20px;">
2760- <thead>
2761- <tr>
2762- <th>Username</th>
2763- <th>Global Roles</th>
2764- <th>Actions</th>
2765- </tr>
2766- </thead>
2767- {% for user in users %}
2768- <tr class="{% cycle 'row1' 'row2' %}">
2769- <td>
2770- {{user.username}}
2771- </td>
2772- <td>
2773- (temporarily hidden)
2774- {#user.roles#}
2775- </td>
2776- <td>
2777- <a href="{%url admin_user_roles user.username %}">Edit</a>
2778- </td>
2779- </tr>
2780- {% endfor %}
2781- </table>
2782-{% endblock %}
2783
2784=== removed directory 'src/django_nova/templates/django_nova'
2785=== removed file 'src/django_nova/templates/django_nova/_messages.html'
2786--- src/django_nova/templates/django_nova/_messages.html 2011-01-12 20:02:06 +0000
2787+++ src/django_nova/templates/django_nova/_messages.html 1970-01-01 00:00:00 +0000
2788@@ -1,41 +0,0 @@
2789-{% for message in messages %}
2790- <div class="message ui-widget">
2791- {% if message.tags == "info" %}
2792- <div class="ui-state-highlight ui-corner-all">
2793- <span class="close ui-icon ui-icon-circle-close"></span>
2794- <p>
2795- <span class="ui-icon ui-icon-info"></span>
2796- {{ message }}
2797- </p>
2798- </div>
2799- {% endif %}
2800- {% if message.tags == "warning" %}
2801- <div class="ui-state-highlight ui-corner-all" >
2802- <span class="close ui-icon ui-icon-circle-close"></span>
2803- <p>
2804- <span class="ui-icon ui-icon-alert"></span>
2805- {{ message }}
2806- </p>
2807- </div>
2808- {% endif %}
2809- {% if message.tags == "success" %}
2810- <div class="ui-state-highlight ui-corner-all success" >
2811- <span class="close ui-icon ui-icon-circle-close"></span>
2812- <p>
2813- <span class="ui-icon ui-icon-check"></span>
2814- {{ message }}
2815- </p>
2816- </div>
2817- {% endif %}
2818- {% if message.tags == "error" %}
2819- <div class="ui-state-error ui-corner-all" >
2820- <span class="close ui-icon ui-icon-circle-close"></span>
2821- <p>
2822- <span class="ui-icon ui-icon-alert"></span>
2823- {{ message }}
2824- </p>
2825- </div>
2826- {% endif %}
2827- </div>
2828-{% endfor %}
2829-
2830
2831=== removed file 'src/django_nova/templates/django_nova/base.html'
2832--- src/django_nova/templates/django_nova/base.html 2011-01-18 21:53:47 +0000
2833+++ src/django_nova/templates/django_nova/base.html 1970-01-01 00:00:00 +0000
2834@@ -1,85 +0,0 @@
2835-{% extends "base-sidebar.html" %}
2836-{% load region_tags %}
2837-{% load project_tags %}
2838-
2839-{% block headerjs %}
2840-{{ block.super }}
2841-{% endblock %}
2842-
2843-{% block region %}
2844- <div id="region_selector">
2845- {% load_regions %}
2846- <span id="project_name"><strong>Project:</strong> {{ project.projectname }}</span>
2847-
2848- <form id="frm_region" method="post" action="{% url region_change %}">
2849- {% csrf_token %}
2850- <fieldset>
2851- <input name="redirect_url" type="hidden" value="{{ request.get_full_path }}" />
2852- <noscript>
2853- <input id="btn_region_change" type="submit" value="Change" />
2854- </noscript>
2855-
2856- <div id="region_form">
2857- <label for="sel_region">Region: </label>
2858- <select id="sel_region" name="region">
2859- {% for region in regions %}
2860- <option{% if region.name == current_region.name %} selected{% endif %}>
2861- {{ region.name }}
2862- </option>
2863- {% endfor %}
2864- </select>
2865- </div>
2866-
2867- </fieldset>
2868- </form>
2869- </div>
2870-{% endblock %}
2871-
2872-{% block nav_projects %}
2873- {% load_projects %}
2874- <li>
2875- <h3 class="active"><a href="/">Projects</a></h3>
2876- <div id="projects">
2877- {% for p in projects %}
2878- <div id="{{ p.projectname }}" class="project{% if p.projectname == project.projectname %} active{% endif %}">
2879- <h4>
2880- <a class="project_link" href="/project/{{ p.projectname }}">{{ p.projectname }}</a>
2881- {% if p.projectManagerId == user.username %}
2882- <a id="manage_project_{{p.projectname}}"
2883- class="manage_link"
2884- href="{% url nova_project_manage p.projectname %}"
2885- title="Manage User Roles">Manage Project</a>
2886- {% endif %}
2887- </h4>
2888- {% if project.projectname == p.projectname %}
2889- <ul>
2890- <li {% if p.projectname == project.projectname and sidebar_selected == "instances" %}class="active"{% endif %}>
2891- <a id="lnk_instances_{{p.projectname}}" href="{% url nova_instances p.projectname %}">Instances</a>
2892- </li>
2893- <li {% if p.projectname == project.projectname and sidebar_selected == "images" %}class="active"{% endif %}>
2894- <a id="lnk_images_{{p.projectname}}" href="{% url nova_images p.projectname %}">Images</a>
2895- </li>
2896- <li {% if p.projectname == project.projectname and sidebar_selected == "keys" %}class="active"{% endif %}>
2897- <a id="lnk_keypairs_{{p.projectname}}" href="{% url nova_keypairs p.projectname %}">Keys</a>
2898- </li>
2899- <li {% if p.projectname == project.projectname and sidebar_selected == "volumes" %}class="active"{% endif %}>
2900- <a id="lnk_volumes_{{p.projectname}}" href="{% url nova_volumes p.projectname %}">Volumes</a>
2901- </li>
2902- </ul>
2903- {% endif %}
2904- </div>
2905- {% endfor %}
2906- </div>
2907- </li>
2908-{% endblock %}
2909-
2910-{% block footerjs %}
2911-{{ block.super }}
2912-<script type="text/javascript">
2913- $(function() {
2914- $('#sel_region').change(function() {
2915- $('#frm_region').submit();
2916- });
2917- });
2918-</script>
2919-{% endblock %}
2920
2921=== removed directory 'src/django_nova/templates/django_nova/credentials'
2922=== removed file 'src/django_nova/templates/django_nova/credentials/expired.html'
2923--- src/django_nova/templates/django_nova/credentials/expired.html 2011-02-01 19:18:59 +0000
2924+++ src/django_nova/templates/django_nova/credentials/expired.html 1970-01-01 00:00:00 +0000
2925@@ -1,17 +0,0 @@
2926-{% load django_nova_tags %}
2927-<!DOCTYPE html>
2928-<html lang="en" xml:lang="en">
2929- <head>
2930- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
2931- <title>Expired Token</title>
2932- </head>
2933- <body>
2934- <center>
2935- <h1>The link you clicked has expired.</h1>
2936- <p style="width:460px;">This credentials download link you have reached
2937- is either invalid or has expired. Each link is only good for one use. If
2938- you need to download your credentials again, please contact the
2939- {% site_branding %} support team.</p>
2940- </center>
2941- </body>
2942-</html>
2943
2944=== removed directory 'src/django_nova/templates/django_nova/images'
2945=== removed file 'src/django_nova/templates/django_nova/images/_launch_form.html'
2946--- src/django_nova/templates/django_nova/images/_launch_form.html 2011-01-12 20:02:06 +0000
2947+++ src/django_nova/templates/django_nova/images/_launch_form.html 1970-01-01 00:00:00 +0000
2948@@ -1,7 +0,0 @@
2949-{% for field in form %}
2950-<div class="{% cycle 'odd' 'even'%}">
2951- {{ field.label_tag }}
2952- {% if field.errors %}{{ field.errors }}{% endif %}
2953- {{ field }}
2954-</div>
2955-{% endfor %}
2956
2957=== removed file 'src/django_nova/templates/django_nova/images/_list.html'
2958--- src/django_nova/templates/django_nova/images/_list.html 2011-03-01 04:13:08 +0000
2959+++ src/django_nova/templates/django_nova/images/_list.html 1970-01-01 00:00:00 +0000
2960@@ -1,112 +0,0 @@
2961- <h3 class="image_list_heading"> {{ heading }} </h3>
2962- {% if images %}
2963- <table id="image_launch">
2964- <tr>
2965- <th>ID</th>
2966- <th>Description</th>
2967- <th colspan="2">Owner</th>
2968- </tr>
2969- {% for image in images %}
2970- {% if image.id == ami.id %}
2971- <td class="detail_wrapper" colspan="4">
2972- <div id="{{ ami.id }}" class="image_detail">
2973- <div class="column">
2974- <div class="image_detail_item">
2975- <span class="label">Owner: </span>
2976- <span class="data">{{ ami.ownerId }}</span>
2977- </div>
2978-
2979- <div class="image_detail_item">
2980- <span class="label">Description: </span>
2981- <span class="data">{{ ami.description }}</span>
2982- </div>
2983-
2984- <div class="image_detail_item">
2985- <span class="label">Location: </span>
2986- <span class="data">{{ ami.location }}</span>
2987- </div>
2988- </div>
2989-
2990- <div class="column">
2991- <div class="image_detail_item">
2992- <span class="label">ID: </span>
2993- <span class="data">{{ ami.id }}</span>
2994- </div>
2995- <div class="image_detail_item">
2996- <span class="label">Name: </span>
2997- <span class="data">{% if ami.displayName %}{{ ami.displayName }}{%else%}{{ ami.id }}{% endif %}</span>
2998- </div>
2999- <div class="image_detail_item">
3000- <span class="label">Type: </span>
3001- <span class="data">{{ ami.type }}</span>
3002- </div>
3003- <div class="image_detail_item">
3004- <span class="label">Architecture: </span>
3005- <span class="data">{{ ami.architecture }}</span>
3006- </div>
3007- </div>
3008-
3009- <div id="last" class="column">
3010- {% if ami.is_public %}
3011- <div id="public" class="privacy">Public Image</div>
3012- {% else %}
3013- <div id="private" class="privacy">Private Image</div>
3014- {% endif %}
3015-
3016- <a id="launch_{{ image.id }}" class="launch" href="{% url nova_images_launch project.projectname image.id %}" title="Click to launch image">Launch</a>
3017- {% if can_modify or user.username == ami.ownerId %}
3018- <a id="edit_image_link" href="{% url nova_images_update project.projectname ami.id %}">Edit Image</a>
3019- {% endif %}
3020-
3021- </div>
3022-
3023- {% if can_modify or user.username == ami.ownerId %}
3024- <span class="image_privacy">
3025- <form id="privacy_{{ ami.id }}" action="{% url nova_images_privacy project.projectname ami.id %}" method="post" accept-charset="utf-8">
3026- {% csrf_token %}
3027- {% if ami.is_public %}
3028- <input class="private" type="submit" value="Make Private" />
3029- {% else %}
3030- <input class="public" type="submit" value="Make Public" />
3031- {% endif %}
3032- </form>
3033- </span>
3034-
3035- <span class="delete">
3036- <form id="delete_{{ ami.id }}" action="{% url nova_images_remove project.projectname ami.id %}" method="post" accept-charset="utf-8">
3037- {% csrf_token %}
3038- <input type="submit" value="Remove Image" />
3039- </form>
3040- </span>
3041- {% endif %}
3042- </div>
3043- </td>
3044- {% else %}
3045- <tr class="{% cycle 'odd' 'even' %}">
3046- <td class="image_id">
3047- <a href="{% url nova_images_detail project.projectname image.id %}">{% if image.displayName %}{{ image.displayName }}{%else%}{{ image.id }}{% endif %}</a>
3048- </td>
3049- <td class="image_location odd">
3050- {% if image.description %}
3051- {{ image.description }}
3052- {% else %}
3053- {{ image.location }}
3054- {% endif %}
3055- </td>
3056- <td class="image_owner_id">{{ image.ownerId }}</td>
3057- <td class="image_launch_btn odd"><a id="launch_{{ image.id }}" class="launch" href="{% url nova_images_launch project.projectname image.id %}">Launch</a></td>
3058- {#<td class="odd"><a class="ui-state-default ui-corner-all" onclick="$('#dlg_launch').dialog('open');">Launch</a></td>#}
3059- </tr>
3060- {% endif %}
3061- {% endfor %}
3062- </table>
3063- {% else %}
3064- <div class="ui-widget">
3065- <div class="ui-state-highlight ui-corner-all">
3066- <p>
3067- <span class="ui-icon ui-icon-info"></span>
3068- No images currently available.
3069- </p>
3070- </div>
3071- </div>
3072- {% endif %}
3073
3074=== removed file 'src/django_nova/templates/django_nova/images/base.html'
3075--- src/django_nova/templates/django_nova/images/base.html 2011-01-16 21:28:02 +0000
3076+++ src/django_nova/templates/django_nova/images/base.html 1970-01-01 00:00:00 +0000
3077@@ -1,7 +0,0 @@
3078-{% extends "django_nova/base.html" %}
3079-{% load sidebar_tags %}
3080-
3081-{% block nav_projects %}
3082- {% sidebar_select images %}
3083- {{ block.super }}
3084-{% endblock %}
3085\ No newline at end of file
3086
3087=== removed file 'src/django_nova/templates/django_nova/images/detail_list.html'
3088--- src/django_nova/templates/django_nova/images/detail_list.html 2011-03-01 04:13:08 +0000
3089+++ src/django_nova/templates/django_nova/images/detail_list.html 1970-01-01 00:00:00 +0000
3090@@ -1,207 +0,0 @@
3091-{% extends "django_nova/images/base.html" %}
3092-
3093-{% block title %} - Launch an Image{% endblock %}
3094-
3095-{% block headerjs %}
3096-<script type="text/javascript" src="/media/django_nova/js/jquery.form.js"></script>
3097-{% endblock %}
3098-
3099-
3100-{% block content %}
3101- <div id="right_content">
3102- <div id="page_head">
3103- <h2 id="page_heading">Images</h2>
3104- <p id="page_description">Images are snapshots of running systems which can easily be deployed to run one or more instances.</p>
3105- </div>
3106-
3107- {% include "django_nova/_messages.html" %}
3108-
3109- {% if images %}
3110- <table id="image_launch">
3111- <tr>
3112- <th>ID</th>
3113- <th>Description</th>
3114- <th colspan="2">Owner</th>
3115- </tr>
3116- {% for image in images %}
3117- <tr class="{% cycle 'odd' 'even' %}">
3118- {% if image.id == ami.id %}
3119- <td class="detail_wrapper" colspan="4">
3120- <div id="{{ ami.id }}" class="image_detail">
3121- <div class="column">
3122- <div class="image_detail_item">
3123- <span class="label">Owner: </span>
3124- <span class="data">{{ ami.ownerId }}</span>
3125- </div>
3126-
3127- <div class="image_detail_item">
3128- <span class="label">Description: </span>
3129- <span class="data">{{ ami.description }}</span>
3130- </div>
3131-
3132- <div class="image_detail_item">
3133- <span class="label">Location: </span>
3134- <span class="data">{{ ami.location }}</span>
3135- </div>
3136- </div>
3137-
3138- <div class="column">
3139- <div class="image_detail_item">
3140- <span class="label">ID: </span>
3141- <span class="data">{{ ami.id }}</span>
3142- </div>
3143- <div class="image_detail_item">
3144- <span class="label">Name: </span>
3145- <span class="data">{% if ami.displayName %}{{ ami.displayName }}{%else%}{{ ami.id }}{% endif %}</span>
3146- </div>
3147- <div class="image_detail_item">
3148- <span class="label">Type: </span>
3149- <span class="data">{{ ami.type }}</span>
3150- </div>
3151- <div class="image_detail_item">
3152- <span class="label">Architecture: </span>
3153- <span class="data">{{ ami.architecture }}</span>
3154- </div>
3155- </div>
3156-
3157- <div id="last" class="column">
3158- {% if ami.is_public %}
3159- <div id="public" class="privacy">Public Image</div>
3160- {% else %}
3161- <div id="private" class="privacy">Private Image</div>
3162- {% endif %}
3163-
3164- <a id="launch_{{ image.id }}" class="launch" href="{% url nova_images_launch project.projectname image.id %}" title="Click to launch image">Launch</a>
3165- {% if can_modify or user.username == ami.ownerId %}
3166- <a id="edit_image_link" href="{% url nova_images_update project.projectname ami.id %}">Edit Image</a>
3167- {% endif %}
3168-
3169- </div>
3170-
3171- {% if can_modify or user.username == ami.ownerId %}
3172- <span class="image_privacy">
3173- <form id="privacy_{{ ami.id }}" action="{% url nova_images_privacy project.projectname ami.id %}" method="post" accept-charset="utf-8">
3174- {% csrf_token %}
3175- {% if ami.is_public %}
3176- <input class="private" type="submit" value="Make Private" />
3177- {% else %}
3178- <input class="public" type="submit" value="Make Public" />
3179- {% endif %}
3180- </form>
3181- </span>
3182-
3183- <span class="delete">
3184- <form id="delete_{{ ami.id }}" action="{% url nova_images_remove project.projectname ami.id %}" method="post" accept-charset="utf-8">
3185- {% csrf_token %}
3186- <input type="submit" value="Remove Image" />
3187- </form>
3188- </span>
3189- {% endif %}
3190- </div>
3191- </td>
3192- {% else %}
3193- <td class="image_id"><a href="{% url nova_images_detail project.projectname image.id %}">{{ image.id }}</a></td>
3194- <td class="image_location odd">
3195- {% if image.description %}
3196- {{ image.description }}
3197- {% else %}
3198- {{ image.location }}
3199- {% endif %}
3200- </td>
3201- <td class="image_owner_id">{{ image.ownerId }}</td>
3202- <td class="image_launch_btn odd"><a id="launch_{{ image.id }}" class="launch" href="{% url nova_images_launch project.projectname image.id %}">Launch</a></td>
3203- {#<td class="odd"><a class="ui-state-default ui-corner-all" onclick="$('#dlg_launch').dialog('open');">Launch</a></td>#}
3204- {% endif %}
3205- </tr>
3206- {% endfor %}
3207- </table>
3208- {% else %}
3209- <div class="ui-widget">
3210- <div class="ui-state-highlight ui-corner-all">
3211- <p>
3212- <span class="ui-icon ui-icon-info"></span>
3213- No images currently available.
3214- </p>
3215- </div>
3216- </div>
3217- {% endif %}
3218- </div>
3219-
3220- <div id="dlg_launch" title="Launch Instance" style="display:none;">
3221- <form id="frm_launch" action="url nova_images_launch project.projectname" method="post">
3222- {% csrf_token %}
3223- {% include "django_nova/images/_launch_form.html" %}
3224- </form>
3225- </div>
3226-
3227- <div id="dlg_confirm" title="Confirm Termination">
3228- <p>Are you sure you wish to unregister the <span id="ami_name"></span> image?</p>
3229- </div>
3230-
3231-{% endblock %}
3232-
3233-{% block footerjs %}
3234-{{ block.super }}
3235-<script type="text/javascript">
3236- var options = {
3237- success: handleResponse,
3238- beforeSubmit: showRequest,
3239- dataType: 'json'
3240- }
3241-
3242- // TODO: On dialog open, reset form and validation.
3243- $(function() {
3244- $('#dlg_launch').dialog({
3245- buttons: {
3246- 'Ok': function() {
3247- $('#frm_launch').ajaxSubmit(options);
3248- },
3249- 'Cancel': function() {
3250- $(this).dialog('close');
3251- }
3252- },
3253- autoOpen: false,
3254- resizable: false,
3255- width: 400,
3256- height: 400
3257- });
3258- });
3259-
3260- function showRequest(formData, jqForm, options) {
3261- var queryString = $.param(formData);
3262- alert('About to submit: \n\n' + queryString);
3263- return true;
3264- }
3265-
3266- function handleResponse(data, statusText, xhr, $form) {
3267- alert('status: ' + statusText + '\nsuccess:\n\n' + data.success);
3268- }
3269-
3270- $(function(){
3271- $('.delete form').submit(function() {
3272- ami_name = $(this).parent().parent().attr("id");
3273- $('#ami_name').text(ami_name);
3274- $('#dlg_confirm').dialog('open');
3275- return false;
3276- });
3277-
3278- $('#dlg_confirm').dialog({
3279- buttons: {
3280- 'Ok': onConfirmOK,
3281- 'Cancel': function() { $(this).dialog('close'); }
3282- },
3283- autoOpen: false,
3284- resizable: false,
3285- width: 500,
3286- height: 200
3287- });
3288- })
3289-
3290- function onConfirmOK() {
3291- $(this).dialog('close');
3292- form = document.getElementById('delete_' + ami_name);
3293- if(form) form.submit();
3294- }
3295-
3296-</script>
3297-{% endblock %}
3298
3299=== removed file 'src/django_nova/templates/django_nova/images/edit.html'
3300--- src/django_nova/templates/django_nova/images/edit.html 2011-01-16 21:28:02 +0000
3301+++ src/django_nova/templates/django_nova/images/edit.html 1970-01-01 00:00:00 +0000
3302@@ -1,35 +0,0 @@
3303-{% extends "django_nova/images/base.html" %}
3304-
3305-{% block title %} - Cloud Computing{% endblock %}
3306-
3307-{% block headerjs %}
3308-<script type="text/javascript" src="{{ COMMON_MEDIA_PREFIX }}js/jquery.form.js"></script>
3309-{% endblock %}
3310-
3311-{% block content %}
3312-<div id="right_content">
3313- <div id="page_head">
3314- <h2 id="page_heading">Edit Image</h2>
3315- <p id="page_description">From this page you can edit the name and description of an image that belongs to you.</p>
3316- </div>
3317-
3318- <div class="dash_block first">
3319- <h3 class="image_id">Edit Image: {{ ami.id }}</h3>
3320-
3321- <form class="edit_image" id="rename_{{ ami.id }}" action="{% url nova_images_update project.projectname ami.id %}" method="post">
3322- <fieldset>
3323- {% csrf_token %}
3324- {% for field in form %}
3325-
3326- {{ field.label_tag }}
3327- {% if field.errors %}{{ field.errors }}{% endif %}
3328- {{ field }}
3329- {% endfor %}
3330- <input type="submit" value="Update Image" />
3331- </fieldset>
3332- </form>
3333-
3334- </div>
3335-</div>
3336-
3337-{% endblock %}
3338
3339=== removed file 'src/django_nova/templates/django_nova/images/index.html'
3340--- src/django_nova/templates/django_nova/images/index.html 2011-01-17 06:58:19 +0000
3341+++ src/django_nova/templates/django_nova/images/index.html 1970-01-01 00:00:00 +0000
3342@@ -1,70 +0,0 @@
3343-{% extends "django_nova/images/base.html" %}
3344-
3345-{% block title %} - Launch an Image{% endblock %}
3346-
3347-{% block headerjs %}
3348-<script type="text/javascript" src="/media/django_nova/js/jquery.form.js"></script>
3349-{% endblock %}
3350-
3351-
3352-{% block content %}
3353- <div id="right_content">
3354- <div id="page_head">
3355- <h2 id="page_heading">Images</h2>
3356- <p id="page_description">Images are snapshots of running systems which can easily be deployed to run one or more instances.</p>
3357- </div>
3358-
3359- {% include "django_nova/_messages.html" %}
3360-
3361- {% for heading, images in image_lists.items %}
3362- {% include "django_nova/images/_list.html" %}
3363- {% endfor %}
3364-
3365- </div>
3366-
3367- <div id="dlg_launch" title="Launch Instance" style="display:none;">
3368- <form id="frm_launch" action="#" method="post">
3369- {% csrf_token %}
3370- {% include "django_nova/images/_launch_form.html" %}
3371- </form>
3372- </div>
3373-{% endblock %}
3374-
3375-{% block footerjs %}
3376-{{ block.super }}
3377-<script type="text/javascript">
3378- var options = {
3379- success: handleResponse,
3380- beforeSubmit: showRequest,
3381- dataType: 'json'
3382- }
3383-
3384- // TODO: On dialog open, reset form and validation.
3385- $(function() {
3386- $('#dlg_launch').dialog({
3387- buttons: {
3388- 'Ok': function() {
3389- $('#frm_launch').ajaxSubmit(options);
3390- },
3391- 'Cancel': function() {
3392- $(this).dialog('close');
3393- }
3394- },
3395- autoOpen: false,
3396- resizable: false,
3397- width: 400,
3398- height: 400
3399- });
3400- });
3401-
3402- function showRequest(formData, jqForm, options) {
3403- var queryString = $.param(formData);
3404- alert('About to submit: \n\n' + queryString);
3405- return true;
3406- }
3407-
3408- function handleResponse(data, statusText, xhr, $form) {
3409- alert('status: ' + statusText + '\nsuccess:\n\n' + data.success);
3410- }
3411-</script>
3412-{% endblock %}
3413
3414=== removed file 'src/django_nova/templates/django_nova/images/launch.html'
3415--- src/django_nova/templates/django_nova/images/launch.html 2011-01-16 21:28:02 +0000
3416+++ src/django_nova/templates/django_nova/images/launch.html 1970-01-01 00:00:00 +0000
3417@@ -1,32 +0,0 @@
3418-{% extends "django_nova/images/base.html" %}
3419-
3420-{% block title %} - Cloud Computing{% endblock %}
3421-
3422-{% block headerjs %}
3423-<script type="text/javascript" src="{{ COMMON_MEDIA_PREFIX }}js/jquery.form.js"></script>
3424-{% endblock %}
3425-
3426-{% block content %}
3427-<div id="right_content">
3428- <div id="page_head">
3429- <h2 id="page_heading">Launch Image</h2>
3430- <p id="page_description">You can launch up to five instances of an image at a time. Some images allow for custom configuration to be passed in via User data. (<a href="/kb/show/UserData/">read more</a>)</p>
3431- </div>
3432-
3433- <div class="dash_block first">
3434- <form id="frm_launch" action="{% url nova_images_launch project.projectname ami.id %}" method="post">
3435- {% csrf_token %}
3436- <fieldset>
3437- <h3 class="image_id">Launch Image {{ ami.id }}</h3>
3438- <div class="even">
3439- <label>Location</label>
3440- <span class="image_location">{{ ami.location }}</span>
3441- </div>
3442- {% include "django_nova/images/_launch_form.html" %}
3443- <input id="launch_image" type="submit" value="Launch" />
3444- </fieldset>
3445- </form>
3446- </div>
3447-</div>
3448-
3449-{% endblock %}
3450
3451=== removed directory 'src/django_nova/templates/django_nova/instances'
3452=== removed file 'src/django_nova/templates/django_nova/instances/_instances_list.html'
3453--- src/django_nova/templates/django_nova/instances/_instances_list.html 2011-01-12 20:02:06 +0000
3454+++ src/django_nova/templates/django_nova/instances/_instances_list.html 1970-01-01 00:00:00 +0000
3455@@ -1,104 +0,0 @@
3456- {% if instances %}
3457- <table style="width: 100%">
3458- <tr>
3459- <th>ID</th>
3460- <th>Image</th>
3461- <th>Size</th>
3462- <th>IP</th>
3463- <th colspan="2">State</th>
3464- </tr>
3465- {% for instance in instances %}
3466- <tr class="{% cycle 'odd' 'even' %}">
3467- {% if instance.id == selected_instance.id %}
3468- <td class="detail_wrapper" colspan="6">
3469- <div id="{{selected_instance.id}}" class="instance_detail">
3470- <div class="column">
3471- <div class="instance_detail_item">
3472- <span class="label">Instance ID: </span>
3473- <span class="data">{{ selected_instance.id }}</span>
3474- </div>
3475- <div class="instance_detail_item">
3476- <span class="label">Name: </span>
3477- <span class="data">{% if selected_instance.displayName != "" %}{{ selected_instance.displayName }}{% else %} None {% endif %}</span>
3478- </div>
3479- <div class="instance_detail_item">
3480- <span class="label">Description: </span>
3481- <span class="data" id="desc">{{ selected_instance.displayDescription }}</span>
3482- </div>
3483- </div>
3484-
3485- <div class="column">
3486- <div class="instance_detail_item">
3487- <span class="label">Region: </span>
3488- <span class="data">{{ selected_instance.region.name }}</span>
3489- </div>
3490- <div class="instance_detail_item">
3491- <span class="label">Size: </span>
3492- <span class="data">{{ selected_instance.instance_type }}</span>
3493- </div>
3494- <div class="instance_detail_item">
3495- <span class="label">State: </span>
3496- <span class="data">{{ selected_instance.state }}</span>
3497- </div>
3498- <div class="instance_detail_item">
3499- <span class="label">Image ID: </span>
3500- <span class="data">{{ selected_instance.image_id }}</span>
3501- </div>
3502- <div class="instance_detail_item">
3503- <span class="label">IP Address: </span>
3504- <span class="data">{{ selected_instance.dns_name }}</span>
3505- </div>
3506-
3507- </div>
3508-
3509- <div id="last" class="column">
3510- {% if instance.state == "running" %}
3511- <a href="{% url nova_instances_console project.projectname instance.id %}" id="console_{{instance.id}}" class="console" target="_blank">Show Console</a>{% endif %}
3512- <a id="edit_instance_link" href="{% url nova_instance_update project.projectname instance.id %}">Edit Instance</a>
3513-
3514-
3515- </div>
3516-
3517- <span class="delete">
3518- <form id="form_terminate_{{ instance.id }}" class="form-terminate" method="post" action="{% url nova_instances_terminate project.projectname %}" >
3519- <input name="instance_id" type="hidden" value="{{ instance.id }}" />
3520- <input id="terminate_{{instance.id}}" class="terminate" type="submit" value="Terminate" />
3521- {% csrf_token %}
3522- </form>
3523- </span>
3524-
3525- </div>
3526-
3527- </td>
3528- {% else %}
3529-
3530- <td><a href="{% url nova_instances_detail project.projectname instance.id %}">{{ instance.id }} {% if instance.displayName %}({{ instance.displayName }}){% endif %}
3531- </a></td>
3532- <td class="odd">{{ instance.image_id }}</td>
3533- <td>{{ instance.instance_type }}</td>
3534- <td class="odd">{{ instance.dns_name }}</td>
3535- <td>{{ instance.state }}</td>
3536- <td id="actions" class="odd">
3537- <form id="form_terminate_{{ instance.id }}" class="form-terminate" method="post" action="{% url nova_instances_terminate project.projectname %}" >
3538- <input name="instance_id" type="hidden" value="{{ instance.id }}" />
3539- <input id="terminate_{{instance.id}}" class="terminate" type="submit" value="Terminate" />
3540- {% csrf_token %}
3541- </form>
3542- {% if instance.state == "running" %}
3543- <a href="{% url nova_instances_console project.projectname instance.id %}" id="console_{{instance.id}}" class="console" target="_blank">Show Console</a>
3544- {% endif %}
3545- </td>
3546- {% endif %}
3547- </tr>
3548- {% endfor %}
3549- </table>
3550- {% else %}
3551- <div class="ui-widget">
3552- <div class="ui-state-highlight ui-corner-all">
3553- <p>
3554- <span class="ui-icon ui-icon-info"></span>
3555- No instances are currently running. You may start a new instance from the <a href="{% url nova_images project.projectname %}">images</a> tab.
3556- </p>
3557- </div>
3558- </div>
3559- {% endif %}
3560
3561=== removed file 'src/django_nova/templates/django_nova/instances/base.html'
3562--- src/django_nova/templates/django_nova/instances/base.html 2011-01-17 05:55:41 +0000
3563+++ src/django_nova/templates/django_nova/instances/base.html 1970-01-01 00:00:00 +0000
3564@@ -1,7 +0,0 @@
3565-{% extends "django_nova/base.html" %}
3566-{% load sidebar_tags %}
3567-
3568-{% block nav_projects %}
3569- {% sidebar_select instances %}
3570- {{ block.super }}
3571-{% endblock %}
3572\ No newline at end of file
3573
3574=== removed file 'src/django_nova/templates/django_nova/instances/detail_list.html'
3575--- src/django_nova/templates/django_nova/instances/detail_list.html 2011-01-17 05:55:41 +0000
3576+++ src/django_nova/templates/django_nova/instances/detail_list.html 1970-01-01 00:00:00 +0000
3577@@ -1,33 +0,0 @@
3578-{% extends "django_nova/instances/base.html" %}
3579-
3580-{% block title %} - Cloud Computing{% endblock %}
3581-
3582-{% block content %}
3583-
3584-<div id="right_content">
3585- <div id="page_head">
3586- <h2 id="page_heading">Instance ID: {{ instance.id }}</h2>
3587- <p id="page_description">Here you can see up to the minute performance data about your instance.</p>
3588- </div>
3589-
3590- {% include "django_nova/_messages.html" %}
3591-
3592-
3593- <div class="dash_block first">
3594- <h3 class="image_id">Edit Instance: {{ instance.id }}</h3>
3595-
3596- <form class="edit_instance" id="rename_{{ instance.id }}" action="{% url nova_instance_update project.projectname instance.id %}" method="post">
3597- <fieldset>
3598- {% csrf_token %}
3599- {% for field in form %}
3600-
3601- {{ field.label_tag }}
3602- {% if field.errors %}{{ field.errors }}{% endif %}
3603- {{ field }}
3604- {% endfor %}
3605- <input type="submit" value="Update Instance" />
3606- </fieldset>
3607- </form>
3608- </div>
3609-
3610-{% endblock %}
3611
3612=== removed file 'src/django_nova/templates/django_nova/instances/edit.html'
3613--- src/django_nova/templates/django_nova/instances/edit.html 2011-01-17 05:55:41 +0000
3614+++ src/django_nova/templates/django_nova/instances/edit.html 1970-01-01 00:00:00 +0000
3615@@ -1,34 +0,0 @@
3616-{% extends "django_nova/instances/base.html" %}
3617-
3618-{% block title %} - Cloud Computing{% endblock %}
3619-
3620-{% block headerjs %}
3621-<script type="text/javascript" src="{{ COMMON_MEDIA_PREFIX }}js/jquery.form.js"></script>
3622-{% endblock %}
3623-
3624-{% block content %}
3625-<div id="right_content">
3626- <div id="page_head">
3627- <h2 id="page_heading">Edit Instance</h2>
3628- <p id="page_description">From this page you can give your instance an alias, so you don't have to remember its unique id.</p>
3629- </div>
3630-
3631- <div class="dash_block first">
3632- <h3 class="image_id">Edit Instance: {{ instance.id }}</h3>
3633-
3634- <form class="edit_instance" id="rename_{{ selected_instance.id }}" action="{% url nova_instance_update project.projectname instance.id %}" method="post">
3635- <fieldset>
3636- {% csrf_token %}
3637- {% for field in update_form %}
3638-
3639- {{ field.label_tag }}
3640- {% if field.errors %}{{ field.errors }}{% endif %}
3641- {{ field }}
3642- {% endfor %}
3643- <input type="submit" value="Update Instance" />
3644- </fieldset>
3645- </form>
3646- </div>
3647-</div>
3648-
3649-{% endblock %}
3650
3651=== removed file 'src/django_nova/templates/django_nova/instances/index.html'
3652--- src/django_nova/templates/django_nova/instances/index.html 2011-02-27 21:52:13 +0000
3653+++ src/django_nova/templates/django_nova/instances/index.html 1970-01-01 00:00:00 +0000
3654@@ -1,98 +0,0 @@
3655-{% extends "django_nova/instances/base.html" %}
3656-
3657-{% block title %} - {{ project.projectname|capfirst }} Instances{% endblock %}
3658-{% block pageclass %}instances{% endblock %}
3659-
3660-{% block content %}
3661- <div id="page_head">
3662- <div id="spinner"></div>
3663-
3664- <h2 id="page_heading">Instances</h2>
3665- <p id="page_description">Instances are virtual servers launched from images. You can launch instances from the <a href="{% url nova_images project.projectname %}">images tab</a>.</p>
3666- </div>
3667-
3668- {% include "django_nova/_messages.html" %}
3669-
3670- <div id="instances">
3671- {% include "django_nova/instances/_instances_list.html" %}
3672- </div>
3673-
3674- <div id="dlg_confirm" title="Confirm Termination" style="display:none;">
3675- <p>Are you sure you wish to terminate instance <span id="spn_terminate"></span>?</p>
3676- </div>
3677-
3678- <div id="connection_error" style="display:none;" title="Connection Error">
3679- <p><span class="ui-icon ui-icon-alert"></span>A connection error has occurred. Please ensure you are still connected to VPN.</p>
3680- </div>
3681-{% endblock %}
3682-
3683-{% block footerjs %}
3684-{{ block.super }}
3685-<script type="text/javascript">
3686-
3687- $(function() {
3688- setInterval(function() {
3689- $('#spinner').show();
3690- {% if detail %}
3691- $('#instances').load('{% url nova_instances_refresh_detail project.projectname selected_instance.id %}', onInstancesUpdated);
3692- {% else %}
3693- $('#instances').load('{% url nova_instances_refresh project.projectname %}', onInstancesUpdated);
3694- {% endif %}
3695- }, 15000);
3696-
3697- initInstanceForms();
3698-
3699- $('#dlg_confirm').dialog({
3700- buttons: {
3701- 'Ok': onConfirmOK,
3702- 'Cancel': function() { $(this).dialog('close'); }
3703- },
3704- autoOpen: false,
3705- resizable: false,
3706- width: 500,
3707- height: 200
3708- });
3709- });
3710-
3711- var _terminateID = null;
3712-
3713- function initInstanceForms() {
3714- $('.form-terminate').submit(function() {
3715- _terminateID = $(this).children(':first').val()
3716- $('#spn_terminate').text(_terminateID);
3717- $('#dlg_confirm').dialog('open');
3718- return false;
3719- });
3720- }
3721-
3722- function onInstancesUpdated(response, status, xhr) {
3723- $('#spinner').hide();
3724-
3725- switch(xhr.status) {
3726- case 200:
3727- initInstanceForms();
3728- break;
3729-
3730- case 403:
3731- document.location = '{% url auth_login %}';
3732- break;
3733-
3734- default:
3735- $('#connection_error').dialog({
3736- dialogClass: 'alert',
3737- modal: true,
3738- closeOnEscape: true,
3739- buttons:{ "Close": function() { $(this).dialog("close"); } },
3740- });
3741- $('#connection_error').dialog('open');
3742- break;
3743- }
3744- }
3745-
3746- function onConfirmOK() {
3747- $(this).dialog('close');
3748- form = document.getElementById('form_terminate_' + _terminateID);
3749- if(form) form.submit();
3750- }
3751-</script>
3752-{% endblock %}
3753
3754=== removed file 'src/django_nova/templates/django_nova/instances/performance.html'
3755--- src/django_nova/templates/django_nova/instances/performance.html 2011-01-17 05:55:41 +0000
3756+++ src/django_nova/templates/django_nova/instances/performance.html 1970-01-01 00:00:00 +0000
3757@@ -1,58 +0,0 @@
3758-{% extends "django_nova/instances/base.html" %}
3759-
3760-{% block title %} - Cloud Computing{% endblock %}
3761-
3762-{% block content %}
3763-
3764-<div id="right_content">
3765- <div id="page_head">
3766- <h2 id="page_heading">Instance ID: {{ instance.id }} Performance</h2>
3767- <p id="page_description">Here you can see up to the minute performance data about your instance.</p>
3768- </div>
3769-
3770- {% include "django_nova/_messages.html" %}
3771-
3772- <p>
3773- <h1>CPU Usage</h1>
3774- <h3>Today</h3>
3775- <img src="{% url nova_instances_graph project.projectname instance.id "cpu-1d.png" %}" />
3776- </p>
3777- <p>
3778- <h3>This Week</h3>
3779- <img src="{% url nova_instances_graph project.projectname instance.id "cpu-1w.png" %}" />
3780- </p>
3781- <p>
3782- <h3>This Month</h3>
3783- <img src="{% url nova_instances_graph project.projectname instance.id "cpu-1m.png" %}" />
3784- </p>
3785-
3786- <p>
3787- <h1>Network Activity</h1>
3788- <h3>Today</h3>
3789- <img src="{% url nova_instances_graph project.projectname instance.id "net-1d.png" %}" />
3790- </p>
3791- <p>
3792- <h3>This Week</h3>
3793- <img src="{% url nova_instances_graph project.projectname instance.id "net-1w.png" %}" />
3794- </p>
3795- <p>
3796- <h3>This Month</h3>
3797- <img src="{% url nova_instances_graph project.projectname instance.id "net-1m.png" %}" />
3798- </p>
3799-
3800- <p>
3801- <h1>Disk Activity</h3>
3802- <h3>Today</h3>
3803- <img src="{% url nova_instances_graph project.projectname instance.id "disk-1d.png" %}" />
3804- </p>
3805- <p>
3806- <h3>This Week</h3>
3807- <img src="{% url nova_instances_graph project.projectname instance.id "disk-1w.png" %}" />
3808- </p>
3809- <p>
3810- <h3>This Month</h3>
3811- <img src="{% url nova_instances_graph project.projectname instance.id "disk-1m.png" %}" />
3812- </p>
3813-</div>
3814-
3815-{% endblock %}
3816
3817=== removed directory 'src/django_nova/templates/django_nova/keypairs'
3818=== removed file 'src/django_nova/templates/django_nova/keypairs/_create_form.html'
3819--- src/django_nova/templates/django_nova/keypairs/_create_form.html 2011-01-12 20:02:06 +0000
3820+++ src/django_nova/templates/django_nova/keypairs/_create_form.html 1970-01-01 00:00:00 +0000
3821@@ -1,5 +0,0 @@
3822-{% for field in create_form %}
3823-{{ field.label_tag }}
3824-{% if field.errors %}{{ field.errors }}{% endif %}
3825-{{ field }}
3826-{% endfor %}
3827
3828=== removed file 'src/django_nova/templates/django_nova/keypairs/_list.html'
3829--- src/django_nova/templates/django_nova/keypairs/_list.html 2011-01-12 20:02:06 +0000
3830+++ src/django_nova/templates/django_nova/keypairs/_list.html 1970-01-01 00:00:00 +0000
3831@@ -1,31 +0,0 @@
3832- {% if keypairs %}
3833- <table style="width: 100%">
3834- <tr>
3835- <th>Key Pair Name</th>
3836- <th>Fingerprint</th>
3837- <th>&nbsp;</th>
3838- </tr>
3839- {% for keypair in keypairs %}
3840- <tr class="{% cycle 'odd' 'even' %}">
3841- <td>{{ keypair.name }}</td>
3842- <td class="odd">{{ keypair.fingerprint }}</td>
3843- <td>
3844- <form id="form_key_delete_{{keypair.name}}" class="form-key-delete" method="post" action="{% url nova_keypairs_delete project.projectname %}">
3845- <input name="key_name" type="hidden" value="{{ keypair.name }}" />
3846- <input id="keypair_delete_{{keypair.name}}" class="delete" type="submit" value="Delete" />
3847- {% csrf_token %}
3848- </form>
3849- </td>
3850- </tr>
3851- {% endfor %}
3852- </table>
3853- {% else %}
3854- <div class="ui-widget">
3855- <div class="ui-state-highlight ui-corner-all">
3856- <p>
3857- <span class="ui-icon ui-icon-info"></span>
3858- No key pairs currently exist.
3859- </p>
3860- </div>
3861- </div>
3862- {% endif %}
3863
3864=== removed file 'src/django_nova/templates/django_nova/keypairs/base.html'
3865--- src/django_nova/templates/django_nova/keypairs/base.html 2011-01-17 05:55:41 +0000
3866+++ src/django_nova/templates/django_nova/keypairs/base.html 1970-01-01 00:00:00 +0000
3867@@ -1,7 +0,0 @@
3868-{% extends "django_nova/base.html" %}
3869-{% load sidebar_tags %}
3870-
3871-{% block nav_projects %}
3872- {% sidebar_select keys %}
3873- {{ block.super }}
3874-{% endblock %}
3875\ No newline at end of file
3876
3877=== removed file 'src/django_nova/templates/django_nova/keypairs/index.html'
3878--- src/django_nova/templates/django_nova/keypairs/index.html 2011-03-01 04:13:08 +0000
3879+++ src/django_nova/templates/django_nova/keypairs/index.html 1970-01-01 00:00:00 +0000
3880@@ -1,77 +0,0 @@
3881-{% extends "django_nova/keypairs/base.html" %}
3882-
3883-{% block title %} - Cloud Computing{% endblock %}
3884-
3885-{% block headerjs %}
3886-{{ block.super }}
3887-<script type="text/javascript" src="/media/dashboard/js/jquery.form.js"></script>
3888-{% endblock %}
3889-
3890-{% block content %}
3891- <div id="page_head">
3892- <h2 id="page_heading">Keys</h2>
3893- <p id="page_description">Key pairs are ssh credentials which are injected into images when they are launched. Creating a new key pair registers the public key and downloads the private key (a pem file). <em>Protect and use the key as a normal private key.</em></p>
3894- </div>
3895-
3896- {% include "django_nova/_messages.html" %}
3897-
3898- <div id="instances">
3899- {% include "django_nova/keypairs/_list.html" %}
3900- </div>
3901-
3902- <div class="dash_block first">
3903- <form id="frm_key_create" action="{% url nova_keypairs_add project.projectname %}" method="post">
3904- {% csrf_token %}
3905- <input id="js" name="js" type="hidden" value="0" />
3906- <fieldset>
3907- <h3>Create New Keypair</h3>
3908- {% include "django_nova/keypairs/_create_form.html" %}
3909- <input id="keypair_create" class="create" type="submit" value="Create" />
3910- </fieldset>
3911- </form>
3912- </div>
3913-
3914- <div id="dlg_confirm" title="Confirm Termination">
3915- <p>Are you sure you wish to delete key <span id="spn_delete_key_name"></span>?</p>
3916- </div>
3917-{% endblock %}
3918-
3919-{% block footerjs %}
3920-{{ block.super }}
3921-<script type="text/javascript">
3922- $(function() { $('#js').val('1'); });
3923-
3924- {% if download_key %}
3925- $(function() { window.location = '{% url nova_keypairs_download project.projectname download_key %}'; });
3926- {% endif %}
3927-
3928- $(function() {
3929- $('.form-key-delete').submit(function() {
3930- _key_name = $(this).children(':first').val()
3931- $('#spn_delete_key_name').text(_key_name);
3932- $('#dlg_confirm').dialog('open');
3933- return false;
3934- });
3935-
3936- $('#dlg_confirm').dialog({
3937- buttons: {
3938- 'Ok': onConfirmOK,
3939- 'Cancel': function() { $(this).dialog('close'); }
3940- },
3941- autoOpen: false,
3942- resizable: false,
3943- width: 500,
3944- height: 200
3945- });
3946-
3947- });
3948-
3949- var _terminateID = null;
3950-
3951- function onConfirmOK() {
3952- $(this).dialog('close');
3953- form = document.getElementById('form_key_delete_' + _key_name);
3954- if(form) form.submit();
3955- }
3956-</script>
3957-{% endblock %}
3958
3959=== removed directory 'src/django_nova/templates/django_nova/projects'
3960=== removed file 'src/django_nova/templates/django_nova/projects/edit_user.html'
3961--- src/django_nova/templates/django_nova/projects/edit_user.html 2011-01-16 03:46:33 +0000
3962+++ src/django_nova/templates/django_nova/projects/edit_user.html 1970-01-01 00:00:00 +0000
3963@@ -1,72 +0,0 @@
3964-{% extends "django_nova/base.html" %}
3965-{% block title %} - {{ project.projectname|capfirst }} Overview{% endblock %}
3966-{% block pageclass %}overview{% endblock %}
3967-
3968-{% block headerjs %}
3969-{{ block.super }}
3970-<script type="text/javascript" src="/media/dashboard/js/django-admin.multiselect.js"></script>
3971-<link rel="stylesheet" type="text/css" href="/media/dashboard/css/django-admin-widgets.css" />
3972-
3973-<script type="text/javascript" charset="utf-8">
3974- $(function(){
3975- $.each($("#user_edit form select"), function () {
3976- // "Locations" can be any label you want
3977- SelectFilter.init(this.id, "Roles", 0, "/media/admin/");
3978- });
3979- })
3980-</script>
3981-{% endblock %}
3982-
3983-
3984-{% block content %}
3985- <div id="page_head">
3986- <h2 id="page_heading">Edit User Roles</h2>
3987- <p id="page_description">From here you can edit multiple user roles.</p>
3988- </div>
3989-
3990- {% include "django_nova/_messages.html" %}
3991- <div id="user_edit" class="dash_block first">
3992- {% if user %}
3993-
3994- <form action="." method="post" enctype="multipart/form-data">
3995- {% csrf_token %}
3996- <fieldset class="module aligned {{ fieldset.classes }}">
3997- <h3 id="edit_{{ user.username }}">Edit Roles for User: {{ user.username }}</h3>
3998- <div class="form-row">
3999- <label>User</label>
4000- <span id="user_name">{{ user.username }}</span>
4001- </div>
4002- <input type="hidden" name="username" value="{{ user.id }}" id="username" />
4003-
4004- {% for field in form.visible_fields %}
4005- <div class="form-row">
4006- {{ field.errors }}
4007- {{ field.label_tag }}{{ field }}
4008- {% if field.field.help_text %}<p class="help">{{ field.field.help_text|safe }}</p>{% endif %}
4009- </div>
4010- {% endfor %}
4011- {% for field in form.hidden_fields %}
4012- {{ field }}
4013- {% endfor %}
4014- </fieldset>
4015- <div class="cancel">
4016- <a href="{% url nova_project_manage project.projectname %}">Cancel</a>
4017- </div>
4018- <div class="submit-row">
4019- <input type="submit" value="Save" class="default" />
4020- {# <a href="#" class="deletelink">Remove User</a> #}
4021- </div>
4022- </form>
4023- {% else %}
4024- <div class="ui-widget">
4025- <div class="ui-state-highlight ui-corner-all">
4026- <p>
4027- <span class="ui-icon ui-icon-info"></span>
4028- No users are currently associated with this project.
4029- </p>
4030- </div>
4031- </div>
4032- {% endif %}
4033- </div>
4034-{% endblock %}
4035-
4036
4037=== removed file 'src/django_nova/templates/django_nova/projects/index.html'
4038--- src/django_nova/templates/django_nova/projects/index.html 2011-01-12 20:02:06 +0000
4039+++ src/django_nova/templates/django_nova/projects/index.html 1970-01-01 00:00:00 +0000
4040@@ -1,26 +0,0 @@
4041-{% extends "django_nova/base.html" %}
4042-{% block title %} - {{ project.projectname|capfirst }} Overview{% endblock %}
4043-{% block pageclass %}overview{% endblock %}
4044-
4045-{% block content %}
4046- <div id="page_head">
4047- <h2><span>{{ project.projectname|capfirst }}</span> Overview</h2>
4048- </div>
4049-
4050- {% include "django_nova/_messages.html" %}
4051-
4052- <div id="welcome">
4053- <p>Welcome to the <span>{{ project.projectname|capfirst }}</span> Overview. From here you can manage your instances, images, keys, and security groups.</p>
4054- <p>To get started using the command line management tools, you can <a target="_blank" href="http://open.eucalyptus.com/wiki/Euca2oolsGuide_v1.1">download euca2ools</a> and use them with your x509 credentials.</p>
4055- </div>
4056-
4057- <div id="resources" class="dash_block">
4058- <h3>Project Resources</h3>
4059- <ul>
4060- <li><a href="{% url nova_download_credentials project.projectname %}">Generate X509 credentials.</a></li>
4061- <li><a href="{% url nova_instances project.projectname %}">View Instances&nbsp;(<strong>{{ instance_count }}</strong> running).</a></li>
4062- <li><a href="{% url nova_images project.projectname %}">View Images.</a></li>
4063- </ul>
4064- </div>
4065-{% endblock %}
4066-
4067
4068=== removed file 'src/django_nova/templates/django_nova/projects/manage.html'
4069--- src/django_nova/templates/django_nova/projects/manage.html 2011-01-12 20:02:06 +0000
4070+++ src/django_nova/templates/django_nova/projects/manage.html 1970-01-01 00:00:00 +0000
4071@@ -1,45 +0,0 @@
4072-{% extends "django_nova/base.html" %}
4073-{% block title %} - {{ project.projectname|capfirst }} Overview{% endblock %}
4074-{% block pageclass %}overview{% endblock %}
4075-
4076-{% block content %}
4077- <div id="page_head">
4078- <h2 id="page_heading">Manage Users and Roles</h2>
4079- <p id="page_description">From here you can manage users and roles.</p>
4080- </div>
4081-
4082- {% include "django_nova/_messages.html" %}
4083-
4084- <div id="users">
4085- {% if members %}
4086- <table style="width: 100%">
4087- <tr>
4088- <th>Username</th>
4089- <th>Project Roles</th>
4090- <th>Global Roles</th>
4091- <th>&nbsp;</th>
4092- </tr>
4093- {% for member in members %}
4094- <tr class="{% cycle 'odd' 'even' %}">
4095- <td>{{ member.memberId }} {% if project.projectManagerId == member.memberId %}(<em>project manager</em>){% endif %}</td>
4096- <td>{{ member.project_roles }}</td>
4097- <td>{{ member.global_roles }}</td>
4098- <td class="odd">
4099- <a href="{% url nova_project_edit_user project.projectname member.memberId%}">Edit</a>
4100- </td>
4101- </tr>
4102- {% endfor %}
4103- </table>
4104- {% else %}
4105- <div class="ui-widget">
4106- <div class="ui-state-highlight ui-corner-all">
4107- <p>
4108- <span class="ui-icon ui-icon-info"></span>
4109- No users are currently associated with this project.
4110- </p>
4111- </div>
4112- </div>
4113- {% endif %}
4114- </div>
4115-{% endblock %}
4116-
4117
4118=== removed directory 'src/django_nova/templates/django_nova/securitygroups'
4119=== removed file 'src/django_nova/templates/django_nova/securitygroups/_authorize_form.html'
4120--- src/django_nova/templates/django_nova/securitygroups/_authorize_form.html 2011-01-12 20:02:06 +0000
4121+++ src/django_nova/templates/django_nova/securitygroups/_authorize_form.html 1970-01-01 00:00:00 +0000
4122@@ -1,5 +0,0 @@
4123-{% for field in authorize_form %}
4124- {{ field.label_tag }}
4125- {% if field.errors %}{{ field.errors }}{% endif %}
4126- {{ field }}
4127-{% endfor %}
4128\ No newline at end of file
4129
4130=== removed file 'src/django_nova/templates/django_nova/securitygroups/_create_form.html'
4131--- src/django_nova/templates/django_nova/securitygroups/_create_form.html 2011-01-12 20:02:06 +0000
4132+++ src/django_nova/templates/django_nova/securitygroups/_create_form.html 1970-01-01 00:00:00 +0000
4133@@ -1,5 +0,0 @@
4134-{% for field in create_form %}
4135-{{ field.label_tag }}
4136-{% if field.errors %}{{ field.errors }}{% endif %}
4137-{{ field }}
4138-{% endfor %}
4139
4140=== removed file 'src/django_nova/templates/django_nova/securitygroups/_revoke_form.html'
4141--- src/django_nova/templates/django_nova/securitygroups/_revoke_form.html 2011-01-12 20:02:06 +0000
4142+++ src/django_nova/templates/django_nova/securitygroups/_revoke_form.html 1970-01-01 00:00:00 +0000
4143@@ -1,3 +0,0 @@
4144-<input type="hidden" name="protocol" value="{{ rule.ip_protocol }}" />
4145-<input type="hidden" name="from_port" value="{{ rule.from_port}}" />
4146-<input type="hidden" name="to_port" value="{{ rule.to_port }}" />
4147
4148=== removed file 'src/django_nova/templates/django_nova/securitygroups/base.html'
4149--- src/django_nova/templates/django_nova/securitygroups/base.html 2011-01-17 05:55:41 +0000
4150+++ src/django_nova/templates/django_nova/securitygroups/base.html 1970-01-01 00:00:00 +0000
4151@@ -1,7 +0,0 @@
4152-{% extends "django_nova/base.html" %}
4153-{% load sidebar_tags %}
4154-
4155-{% block nav_projects %}
4156- {% sidebar_select securitygroups %}
4157- {{ block.super }}
4158-{% endblock %}
4159\ No newline at end of file
4160
4161=== removed file 'src/django_nova/templates/django_nova/securitygroups/detail.html'
4162--- src/django_nova/templates/django_nova/securitygroups/detail.html 2011-01-17 05:55:41 +0000
4163+++ src/django_nova/templates/django_nova/securitygroups/detail.html 1970-01-01 00:00:00 +0000
4164@@ -1,62 +0,0 @@
4165-{% extends "django_nova/securitygroups/base.html" %}
4166-
4167-{% block title %} - Cloud Computing{% endblock %}
4168-
4169-{% block content %}
4170- <div id="dashboard_tabs">
4171- <div id="tabs-1" class="ui-tabs-panel ui-widget-content ui-corner-bottom dash-wrap" style="margin-left:0;min-height:300px;">
4172- <ul id="dashboard_nav">
4173- <li><a id="lnk_overview" href="{% url dashboard_project project.projectname %}">Overview</a></li>
4174- <li><a id="lnk_instances" href="{% url dashboard_instances project.projectname %}">Instances</a></li>
4175- <li><a id="lnk_images" href="{% url dashboard_images project.projectname %}">Images</a></li>
4176- <li><a id="lnk_keypairs" href="{% url dashboard_keypairs project.projectname %}">Keys</a></li>
4177- <li class="active"><a id="lnk_securitygroups" href="{% url dashboard_securitygroups project.projectname %}">Security Groups</a></li>
4178- <li><a id="lnk_volumes" href="{% url dashboard_volumes project.projectname %}">Volumes</a></li>
4179- </ul>
4180- <div id="right_content">
4181- <div id="page_head">
4182- <h2>Security Group: {{ securitygroup.name }}</h2>
4183- <p>Add and remove protocols to the security group by authorizing and revoking port forwarding. For instance<br /> [tcp, 80, 80] will allow access to HTTP from devices outside this security group.</p>
4184- </div>
4185-
4186- {% include "django_nova/_messages.html" %}
4187-
4188- <table>
4189- <tr>
4190- <th>Protocol</th>
4191- <th>From Port</th>
4192- <th>To Port</th>
4193- <th></th>
4194- </tr>
4195- {% for rule in securitygroup.rules %}
4196- <tr class="{% cycle 'odd' 'even' %}">
4197- <td>{{ rule.ip_protocol }}</td>
4198- <td class="odd">{{ rule.from_port }}</td>
4199- <td>{{ rule.to_port }}</td>
4200- <td class="odd">
4201- <form id="security_groups" method="post" action="{% url dashboard_securitygroups_revoke project.projectname securitygroup.name %}">
4202- {% csrf_token %}
4203- {% include "django_nova/securitygroups/_revoke_form.html" %}
4204- <input class="ui-state-default ui-corner-all" type="submit" value="Revoke" />
4205- </form>
4206- </td>
4207- </tr>
4208- {% endfor %}
4209- </table>
4210-
4211- <div class="block">
4212- <h3>Authorize</h3>
4213- <form id="authorize" method="post" action="{% url dashboard_securitygroups_authorize project.projectname securitygroup.name %}">
4214- {% csrf_token %}
4215- <fieldset>
4216- <input type="hidden" name="group" value="{{ securitygroup.name }}" />
4217- {% include "django_nova/securitygroups/_authorize_form.html" %}
4218- <input class="ui-state-default ui-corner-all" type="submit" value="Authorize">
4219- </fieldset>
4220- </form>
4221- </div>
4222- </div>
4223- <div class="clr"></div>
4224- </div>
4225- </div>
4226-{% endblock %}
4227
4228=== removed file 'src/django_nova/templates/django_nova/securitygroups/index.html'
4229--- src/django_nova/templates/django_nova/securitygroups/index.html 2011-01-17 05:55:41 +0000
4230+++ src/django_nova/templates/django_nova/securitygroups/index.html 1970-01-01 00:00:00 +0000
4231@@ -1,59 +0,0 @@
4232-{% extends "django_nova/securitygroups/base.html" %}
4233-
4234-{% block title %} - Cloud Computing{% endblock %}
4235-
4236-{% block content %}
4237- <div id="dashboard_tabs">
4238- <div id="tabs-1" class="ui-tabs-panel ui-widget-content ui-corner-bottom dash-wrap" style="margin-left:0px;min-height:300px;">
4239- <ul id="dashboard_nav">
4240- <li><a id="lnk_overview" href="{% url dashboard_project project.projectname %}">Overview</a></li>
4241- <li><a id="lnk_instances" href="{% url dashboard_instances project.projectname %}">Instances</a></li>
4242- <li><a id="lnk_images" href="{% url dashboard_images project.projectname %}">Images</a></li>
4243- <li><a id="lnk_keypairs" href="{% url dashboard_keypairs project.projectname %}">Keys</a></li>
4244- <li class="active"><a id="lnk_securitygroups" href="{% url dashboard_securitygroups project.projectname %}">Security Groups</a></li>
4245- <li><a id="lnk_volumes" href="{% url dashboard_volumes project.projectname %}">Volumes</a></li>
4246- </ul>
4247- <div id="right_content">
4248- <div id="page_head">
4249- <h2 id="page_heading">Security Groups</h2>
4250- <p id="page_description">Security groups are firewall rules which allow access to your instances from other groups as well as the internet. All ports/protocols are denied by default.</p>
4251- </div>
4252-
4253- {% include "django_nova/_messages.html" %}
4254-
4255- <table style="width:100%;">
4256- <tr>
4257- <th>Name</th>
4258- <th style="min-width:60%;">Description</th>
4259- <th>Rules</th>
4260- <th>&nbsp;</th>
4261- </tr>
4262- {% for securitygroup in securitygroups %}
4263- <tr class="{% cycle 'odd' 'even' %}">
4264- <td id="group_{{ securitygroup.id }}"><a href="{% url dashboard_securitygroups_detail project.projectname securitygroup.name %}">{{ securitygroup.name }}</a></td>
4265- <td id="group_{{ securitygroup.id }}_description" class="odd">{{ securitygroup.description }}</td>
4266- <td id="group_{{ securitygroup.id }}_rules">{{ securitygroup.rules|length }}</td>
4267- <td class="odd">
4268- <form id="delete_group_{{ securitygroup.id }}" method="post" action="{% url dashboard_securitygroups_delete project.projectname securitygroup.name %}">
4269- {% csrf_token %}
4270- <input class="ui-state-default ui-corner-all" type="submit" value="Delete">
4271- </form>
4272- </td>
4273- </tr>
4274- {% endfor %}
4275- </table>
4276- <div class="block">
4277- <form id="add_group_form" method="post" action="{% url dashboard_securitygroups_add project.projectname %}">
4278- {% csrf_token %}
4279- <fieldset>
4280- <h3>New Group</h3>
4281- {% include "django_nova/securitygroups/_create_form.html" %}
4282- <label>&nbsp;</label><input class="ui-state-default ui-corner-all" type="submit" value="Create" />
4283- </fieldset>
4284- </form>
4285- </div>
4286- </div>
4287- <div class="clr"></div>
4288- </div>
4289- </div>
4290-{% endblock %}
4291
4292=== removed directory 'src/django_nova/templates/django_nova/volumes'
4293=== removed file 'src/django_nova/templates/django_nova/volumes/_attach_form.html'
4294--- src/django_nova/templates/django_nova/volumes/_attach_form.html 2011-01-12 20:02:06 +0000
4295+++ src/django_nova/templates/django_nova/volumes/_attach_form.html 1970-01-01 00:00:00 +0000
4296@@ -1,5 +0,0 @@
4297-{% for field in attach_form %}
4298-{{ field.label_tag }}
4299-{% if field.errors %}{{ field.errors }}{% endif %}
4300-{{ field }}
4301-{% endfor %}
4302
4303=== removed file 'src/django_nova/templates/django_nova/volumes/_create_form.html'
4304--- src/django_nova/templates/django_nova/volumes/_create_form.html 2011-01-12 20:02:06 +0000
4305+++ src/django_nova/templates/django_nova/volumes/_create_form.html 1970-01-01 00:00:00 +0000
4306@@ -1,5 +0,0 @@
4307-{% for field in create_form %}
4308-{{ field.label_tag }}
4309-{% if field.errors %}{{ field.errors }}{% endif %}
4310-{{ field }}
4311-{% endfor %}
4312
4313=== removed file 'src/django_nova/templates/django_nova/volumes/base.html'
4314--- src/django_nova/templates/django_nova/volumes/base.html 2011-01-17 05:55:41 +0000
4315+++ src/django_nova/templates/django_nova/volumes/base.html 1970-01-01 00:00:00 +0000
4316@@ -1,7 +0,0 @@
4317-{% extends "django_nova/base.html" %}
4318-{% load sidebar_tags %}
4319-
4320-{% block nav_projects %}
4321- {% sidebar_select volumes %}
4322- {{ block.super }}
4323-{% endblock %}
4324\ No newline at end of file
4325
4326=== removed file 'src/django_nova/templates/django_nova/volumes/index.html'
4327--- src/django_nova/templates/django_nova/volumes/index.html 2011-01-17 05:55:41 +0000
4328+++ src/django_nova/templates/django_nova/volumes/index.html 1970-01-01 00:00:00 +0000
4329@@ -1,84 +0,0 @@
4330-{% extends "django_nova/volumes/base.html" %}
4331-
4332-{% block title %} - Cloud Computing{% endblock %}
4333-
4334-{% block content %}
4335- <div id="page_head">
4336- <h2 id="page_heading">Volumes</h2>
4337- <p id="page_description">Volumes provide persistent block storage. Creating a new volume gives you a raw block device which you may format with your choice of filesystems (ext3 is recommended). A volume may only be attached to a single instance at a time.</p>
4338- </div>
4339-
4340- {% include "django_nova/_messages.html" %}
4341-
4342- {% if volumes %}
4343- <table style="width: 100%">
4344- <tr>
4345- <th>ID</th>
4346- <th>Size</th>
4347- <th colspan="2">Status</th>
4348- </tr>
4349- {% for volume in volumes %}
4350- <tr class="{% cycle 'odd' 'even' %}">
4351- <td id="volume_{{ volume.id }}">{{ volume.id }} {{ volume.displayName }}</td>
4352- <td id="volume_{{ volume.id }}_size" class="odd">{{ volume.size }}GB</td>
4353- <td id="volume_{{ volume.id }})_status">
4354- {% if volume.status == "in-use" %}
4355- {% if volume.attachment_state == "attached" %}
4356- attached: {{ volume.attach_data.instance_id }}
4357- {% else %}
4358- {{ volume.attachment_state }}
4359- {% endif %}
4360- {% else %}
4361- {{ volume.status }}
4362- {% endif %}
4363- </td>
4364- {% if volume.attachment_state == "attached" %}
4365- <td class="odd">
4366- <form class="volume" action="{% url nova_volumes_detach project.projectname volume.id %}" method="post">
4367- {% csrf_token %}
4368- <input id="detach_{{ volume.id }}" class="detach" type="submit" value="Detach">
4369- </form>
4370- </td>
4371- {% else %}
4372- <td class="odd">
4373- <form class="volume" action="{% url nova_volumes_delete project.projectname volume.id %}" method="post">
4374- {% csrf_token %}
4375- <input id="delete_{{ volume.id }}" class="delete" type="submit" value="Delete">
4376- </form>
4377- </td>
4378- {% endif %}
4379- </tr>
4380- {% endfor %}
4381- </table>
4382- {% else %}
4383- <div class="ui-widget">
4384- <div class="ui-state-highlight ui-corner-all">
4385- <p>
4386- <span class="ui-icon ui-icon-info"></span>
4387- No volumes currently exist.
4388- </p>
4389- </div>
4390- </div>
4391- {% endif %}
4392- <div class="dash_block first">
4393- <form id="new_volume_form" method="post" action="{% url nova_volumes_add project.projectname %}">
4394- {% csrf_token %}
4395- <fieldset>
4396- <h3>Create New Volume</h3>
4397- {% include "django_nova/volumes/_create_form.html" %}
4398- <input id="create_volume" class="create" type="submit" value="Create" />
4399- </fieldset>
4400- </form>
4401- </div>
4402-
4403- <div class="dash_block">
4404- <form id="new_volume_form" method="post" action="{% url nova_volumes_attach project.projectname %}">
4405- {% csrf_token %}
4406- <fieldset>
4407- <h3>Attach Volume</h3>
4408- {% include "django_nova/volumes/_attach_form.html" %}
4409- <input id="attach_volume" class="attach" type="submit" value="Attach" />
4410- </fieldset>
4411- </form>
4412- </div>
4413-{% endblock %}
4414
4415=== removed directory 'src/django_nova/templatetags'
4416=== removed file 'src/django_nova/templatetags/__init__.py'
4417=== removed file 'src/django_nova/templatetags/admin_extras.py'
4418--- src/django_nova/templatetags/admin_extras.py 2011-01-12 20:02:06 +0000
4419+++ src/django_nova/templatetags/admin_extras.py 1970-01-01 00:00:00 +0000
4420@@ -1,50 +0,0 @@
4421-# vim: tabstop=4 shiftwidth=4 softtabstop=4
4422-
4423-# Copyright 2010 United States Government as represented by the
4424-# Administrator of the National Aeronautics and Space Administration.
4425-# All Rights Reserved.
4426-#
4427-# Licensed under the Apache License, Version 2.0 (the "License"); you may
4428-# not use this file except in compliance with the License. You may obtain
4429-# a copy of the License at
4430-#
4431-# http://www.apache.org/licenses/LICENSE-2.0
4432-#
4433-# Unless required by applicable law or agreed to in writing, software
4434-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4435-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4436-# License for the specific language governing permissions and limitations
4437-# under the License.
4438-"""
4439-Template tags for extending the Django admin interface.
4440-"""
4441-
4442-from django.contrib.admin.templatetags.admin_list import items_for_result, result_headers
4443-from django.core.urlresolvers import reverse
4444-from django.template import Library
4445-from django.utils.safestring import mark_safe
4446-
4447-
4448-register = Library()
4449-
4450-def project_result_list(cl):
4451- headers = list(result_headers(cl))
4452- headers.append({'text': mark_safe('&nbsp;')})
4453-
4454- results = list()
4455-
4456- for project in cl.result_list:
4457- rl = list(items_for_result(cl,project,None))
4458-
4459- url = reverse('admin_project_sendcredentials', args=[project.projectname])
4460- content = mark_safe('<td><a href="%s">Send Credentials</a></td>' % url)
4461-
4462- rl.append(content)
4463- results.append(rl)
4464-
4465- return {
4466- 'cl': cl,
4467- 'result_headers': headers,
4468- 'results': results
4469- }
4470-project_result_list = register.inclusion_tag("admin/change_list_results.html")(project_result_list)
4471
4472=== removed file 'src/django_nova/templatetags/django_nova_tags.py'
4473--- src/django_nova/templatetags/django_nova_tags.py 2011-02-01 19:18:59 +0000
4474+++ src/django_nova/templatetags/django_nova_tags.py 1970-01-01 00:00:00 +0000
4475@@ -1,37 +0,0 @@
4476-# vim: tabstop=4 shiftwidth=4 softtabstop=4
4477-
4478-# Copyright 2010 United States Government as represented by the
4479-# Administrator of the National Aeronautics and Space Administration.
4480-# All Rights Reserved.
4481-#
4482-# Licensed under the Apache License, Version 2.0 (the "License"); you may
4483-# not use this file except in compliance with the License. You may obtain
4484-# a copy of the License at
4485-#
4486-# http://www.apache.org/licenses/LICENSE-2.0
4487-#
4488-# Unless required by applicable law or agreed to in writing, software
4489-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4490-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4491-# License for the specific language governing permissions and limitations
4492-# under the License.
4493-
4494-"""
4495-Template tags for working with django_nova.
4496-"""
4497-
4498-from django import template
4499-from django.conf import settings
4500-
4501-
4502-register = template.Library()
4503-
4504-
4505-class SiteBrandingNode(template.Node):
4506- def render(self, context):
4507- return settings.SITE_BRANDING
4508-
4509-@register.tag
4510-def site_branding(parser, token):
4511- return SiteBrandingNode()
4512-
4513
4514=== removed file 'src/django_nova/templatetags/project_tags.py'
4515--- src/django_nova/templatetags/project_tags.py 2011-01-17 06:58:19 +0000
4516+++ src/django_nova/templatetags/project_tags.py 1970-01-01 00:00:00 +0000
4517@@ -1,39 +0,0 @@
4518- # vim: tabstop=4 shiftwidth=4 softtabstop=4
4519-
4520-# Copyright 2010 United States Government as represented by the
4521-# Administrator of the National Aeronautics and Space Administration.
4522-# All Rights Reserved.
4523-#
4524-# Licensed under the Apache License, Version 2.0 (the "License"); you may
4525-# not use this file except in compliance with the License. You may obtain
4526-# a copy of the License at
4527-#
4528-# http://www.apache.org/licenses/LICENSE-2.0
4529-#
4530-# Unless required by applicable law or agreed to in writing, software
4531-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4532-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4533-# License for the specific language governing permissions and limitations
4534-# under the License.
4535-
4536-"""
4537-Template tags for gathering contextual region data.
4538-"""
4539-
4540-from django import template
4541-from django_nova.shortcuts import get_projects
4542-
4543-
4544-register = template.Library()
4545-
4546-
4547-class ProjectsNode(template.Node):
4548- def render(self, context):
4549- # Store project list in template context.
4550- context['projects'] = get_projects(context['request'].user)
4551- return ''
4552-
4553-
4554-@register.tag
4555-def load_projects(parser, token):
4556- return ProjectsNode()
4557
4558=== removed file 'src/django_nova/templatetags/region_tags.py'
4559--- src/django_nova/templatetags/region_tags.py 2011-01-17 06:58:19 +0000
4560+++ src/django_nova/templatetags/region_tags.py 1970-01-01 00:00:00 +0000
4561@@ -1,40 +0,0 @@
4562-# vim: tabstop=4 shiftwidth=4 softtabstop=4
4563-
4564-# Copyright 2010 United States Government as represented by the
4565-# Administrator of the National Aeronautics and Space Administration.
4566-# All Rights Reserved.
4567-#
4568-# Licensed under the Apache License, Version 2.0 (the "License"); you may
4569-# not use this file except in compliance with the License. You may obtain
4570-# a copy of the License at
4571-#
4572-# http://www.apache.org/licenses/LICENSE-2.0
4573-#
4574-# Unless required by applicable law or agreed to in writing, software
4575-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4576-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4577-# License for the specific language governing permissions and limitations
4578-# under the License.
4579-"""
4580-Template tags for gathering contextual region data.
4581-"""
4582-
4583-from django import template
4584-from django_nova.shortcuts import get_current_region, get_all_regions
4585-
4586-
4587-register = template.Library()
4588-
4589-
4590-class RegionsNode(template.Node):
4591- def render(self, context):
4592- # Store region info in template context.
4593- context['current_region'] = get_current_region(context['request'])
4594- context['regions'] = get_all_regions()
4595- return ''
4596-
4597-
4598-@register.tag
4599-def load_regions(parser, token):
4600- return RegionsNode()
4601-
4602
4603=== removed file 'src/django_nova/templatetags/sidebar_tags.py'
4604--- src/django_nova/templatetags/sidebar_tags.py 2011-01-17 05:55:41 +0000
4605+++ src/django_nova/templatetags/sidebar_tags.py 1970-01-01 00:00:00 +0000
4606@@ -1,46 +0,0 @@
4607-# vim: tabstop=4 shiftwidth=4 softtabstop=4
4608-
4609-# Copyright 2010 United States Government as represented by the
4610-# Administrator of the National Aeronautics and Space Administration.
4611-# All Rights Reserved.
4612-#
4613-# Licensed under the Apache License, Version 2.0 (the "License"); you may
4614-# not use this file except in compliance with the License. You may obtain
4615-# a copy of the License at
4616-#
4617-# http://www.apache.org/licenses/LICENSE-2.0
4618-#
4619-# Unless required by applicable law or agreed to in writing, software
4620-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4621-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4622-# License for the specific language governing permissions and limitations
4623-# under the License.
4624-
4625-"""
4626-Template tags for rendering the sidebar.
4627-"""
4628-
4629-from django import template
4630-
4631-
4632-register = template.Library()
4633-
4634-
4635-class SidebarSelectNode(template.Node):
4636- def __init__(self, selected):
4637- self.selected = selected
4638-
4639- def render(self, context):
4640- # Store page type in template context.
4641- context['sidebar_selected'] = self.selected
4642- return ''
4643-
4644-
4645-@register.tag
4646-def sidebar_select(parser, token):
4647- try:
4648- tag_name, selected = token.split_contents()
4649- except ValueError:
4650- raise template.TemplateSyntaxError, "%r tag requires exactly one argument" % token.contents.split()[0]
4651- return SidebarSelectNode(str(selected))
4652-
4653
4654=== removed file 'src/django_nova/templatetags/truncate_filter.py'
4655--- src/django_nova/templatetags/truncate_filter.py 2011-01-12 20:02:06 +0000
4656+++ src/django_nova/templatetags/truncate_filter.py 1970-01-01 00:00:00 +0000
4657@@ -1,31 +0,0 @@
4658-# vim: tabstop=4 shiftwidth=4 softtabstop=4
4659-
4660-# Copyright 2010 United States Government as represented by the
4661-# Administrator of the National Aeronautics and Space Administration.
4662-# All Rights Reserved.
4663-#
4664-# Licensed under the Apache License, Version 2.0 (the "License"); you may
4665-# not use this file except in compliance with the License. You may obtain
4666-# a copy of the License at
4667-#
4668-# http://www.apache.org/licenses/LICENSE-2.0
4669-#
4670-# Unless required by applicable law or agreed to in writing, software
4671-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4672-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4673-# License for the specific language governing permissions and limitations
4674-# under the License.
4675-"""
4676-Template tags for truncating strings.
4677-"""
4678-
4679-from django import template
4680-
4681-register = template.Library()
4682-
4683-@register.filter("truncate")
4684-def truncate(value, size):
4685- if len(value) > size and size > 3:
4686- return value[0:(size-3)] + '...'
4687- else:
4688- return value[0:size]
4689
4690=== removed directory 'src/django_nova/tests'
4691=== removed file 'src/django_nova/tests/__init__.py'
4692--- src/django_nova/tests/__init__.py 2011-01-18 02:09:01 +0000
4693+++ src/django_nova/tests/__init__.py 1970-01-01 00:00:00 +0000
4694@@ -1,1 +0,0 @@
4695-from view_tests import *
4696\ No newline at end of file
4697
4698=== removed directory 'src/django_nova/tests/templates'
4699=== removed file 'src/django_nova/tests/templates/base-sidebar.html'
4700=== removed file 'src/django_nova/tests/urls.py'
4701--- src/django_nova/tests/urls.py 2011-02-11 03:07:22 +0000
4702+++ src/django_nova/tests/urls.py 1970-01-01 00:00:00 +0000
4703@@ -1,36 +0,0 @@
4704-# vim: tabstop=4 shiftwidth=4 softtabstop=4
4705-
4706-# Copyright 2010 United States Government as represented by the
4707-# Administrator of the National Aeronautics and Space Administration.
4708-# All Rights Reserved.
4709-#
4710-# Licensed under the Apache License, Version 2.0 (the "License"); you may
4711-# not use this file except in compliance with the License. You may obtain
4712-# a copy of the License at
4713-#
4714-# http://www.apache.org/licenses/LICENSE-2.0
4715-#
4716-# Unless required by applicable law or agreed to in writing, software
4717-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4718-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4719-# License for the specific language governing permissions and limitations
4720-# under the License.
4721-
4722-"""
4723-URL patterns for testing django-nova views.
4724-"""
4725-
4726-from django.conf.urls.defaults import *
4727-from django.conf.urls.defaults import *
4728-
4729-
4730-urlpatterns = patterns('',
4731- url(r'^projects/', include('django_nova.urls.project')),
4732- url(r'^region/', include('django_nova.urls.region')),
4733- url(r'^admin/projects/', include('django_nova.urls.admin_project')),
4734- url(r'^admin/roles/', include('django_nova.urls.admin_roles')),
4735- url(r'^credentials/download/(?P<auth_token>\w+)/$',
4736- 'django_nova.views.credentials.authorize_credentials',
4737- name='nova_credentials_authorize'),
4738-)
4739-
4740
4741=== removed directory 'src/django_nova/tests/view_tests'
4742=== removed file 'src/django_nova/tests/view_tests/__init__.py'
4743--- src/django_nova/tests/view_tests/__init__.py 2011-02-11 03:07:22 +0000
4744+++ src/django_nova/tests/view_tests/__init__.py 1970-01-01 00:00:00 +0000
4745@@ -1,7 +0,0 @@
4746-from credential_tests import *
4747-from image_tests import *
4748-from instance_tests import *
4749-from keypair_tests import *
4750-from region_tests import *
4751-from volume_tests import *
4752-
4753
4754=== removed file 'src/django_nova/tests/view_tests/base.py'
4755--- src/django_nova/tests/view_tests/base.py 2011-02-11 02:44:45 +0000
4756+++ src/django_nova/tests/view_tests/base.py 1970-01-01 00:00:00 +0000
4757@@ -1,90 +0,0 @@
4758-# vim: tabstop=4 shiftwidth=4 softtabstop=4
4759-
4760-# Copyright 2010 United States Government as represented by the
4761-# Administrator of the National Aeronautics and Space Administration.
4762-# All Rights Reserved.
4763-#
4764-# Licensed under the Apache License, Version 2.0 (the "License"); you may
4765-# not use this file except in compliance with the License. You may obtain
4766-# a copy of the License at
4767-#
4768-# http://www.apache.org/licenses/LICENSE-2.0
4769-#
4770-# Unless required by applicable law or agreed to in writing, software
4771-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4772-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4773-# License for the specific language governing permissions and limitations
4774-# under the License.
4775-
4776-"""
4777-Base classes for view based unit tests.
4778-"""
4779-
4780-import mox
4781-
4782-from django import test
4783-from django.conf import settings
4784-from django.contrib.auth import models as auth_models
4785-from django_nova import adminclient
4786-from django_nova import manager
4787-from django_nova import shortcuts
4788-
4789-
4790-TEST_PROJECT = 'test'
4791-TEST_USER = 'test'
4792-TEST_REGION = 'test'
4793-
4794-
4795-class BaseViewTests(test.TestCase):
4796- def setUp(self):
4797- self.mox = mox.Mox()
4798-
4799- def tearDown(self):
4800- self.mox.UnsetStubs()
4801-
4802- def assertRedirectsNoFollow(self, response, expected_url):
4803- self.assertEqual(response._headers['location'],
4804- ('Location', settings.TESTSERVER + expected_url))
4805- self.assertEqual(response.status_code, 302)
4806-
4807- def authenticateTestUser(self):
4808- user = auth_models.User.objects.create_user(TEST_USER,
4809- 'test@test.com',
4810- password='test')
4811- login = self.client.login(username=TEST_USER, password='test')
4812- self.failUnless(login, 'Unable to login')
4813- return user
4814-
4815-
4816-class BaseProjectViewTests(BaseViewTests):
4817- def setUp(self):
4818- super(BaseProjectViewTests, self).setUp()
4819-
4820- project = adminclient.ProjectInfo()
4821- project.projectname = TEST_PROJECT
4822- project.projectManagerId = TEST_USER
4823-
4824- self.user = self.authenticateTestUser()
4825- self.region = adminclient.RegionInfo(name=TEST_REGION,
4826- endpoint='http://test:8773/')
4827- self.project = manager.ProjectManager(self.user.username,
4828- project,
4829- self.region)
4830- self.mox.StubOutWithMock(shortcuts, 'get_project_or_404')
4831- shortcuts.get_project_or_404(mox.IgnoreArg(),
4832- 'test').AndReturn(self.project)
4833-
4834- def create_key_pair_choices(self, key_names):
4835- return [(k, k) for k in key_names]
4836-
4837- def create_instance_type_choices(self):
4838- return [('m1.medium', 'm1.medium'),
4839- ('m1.large', 'm1.large')]
4840-
4841- def create_instance_choices(self, instance_ids):
4842- return [(id, id) for id in instance_ids]
4843-
4844- def create_available_volume_choices(self, volumes):
4845- return [(v.id, '%s %s - %dGB' % (v.id, v.displayName, v.size)) \
4846- for v in volumes]
4847-
4848
4849=== removed file 'src/django_nova/tests/view_tests/credential_tests.py'
4850--- src/django_nova/tests/view_tests/credential_tests.py 2011-02-11 03:07:22 +0000
4851+++ src/django_nova/tests/view_tests/credential_tests.py 1970-01-01 00:00:00 +0000
4852@@ -1,70 +0,0 @@
4853-# vim: tabstop=4 shiftwidth=4 softtabstop=4
4854-
4855-# Copyright 2010 United States Government as represented by the
4856-# Administrator of the National Aeronautics and Space Administration.
4857-# All Rights Reserved.
4858-#
4859-# Licensed under the Apache License, Version 2.0 (the "License"); you may
4860-# not use this file except in compliance with the License. You may obtain
4861-# a copy of the License at
4862-#
4863-# http://www.apache.org/licenses/LICENSE-2.0
4864-#
4865-# Unless required by applicable law or agreed to in writing, software
4866-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4867-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4868-# License for the specific language governing permissions and limitations
4869-# under the License.
4870-
4871-"""
4872-Unit tests for credential views.
4873-"""
4874-
4875-import mox
4876-from django.conf import settings
4877-from django.core.urlresolvers import reverse
4878-from django_nova import models
4879-from django_nova.tests.view_tests.base import BaseViewTests
4880-
4881-
4882-class CredentialViewTests(BaseViewTests):
4883- def test_download_expired_credentials(self):
4884- auth_token = 'expired'
4885- self.mox.StubOutWithMock(models.CredentialsAuthorization,
4886- 'get_by_token')
4887- models.CredentialsAuthorization.get_by_token(auth_token) \
4888- .AndReturn(None)
4889- self.mox.ReplayAll()
4890-
4891- res = self.client.get(reverse('nova_credentials_authorize',
4892- args=[auth_token]))
4893- self.assertTemplateUsed(res, 'django_nova/credentials/expired.html')
4894-
4895- self.mox.VerifyAll()
4896-
4897- def test_download_good_credentials(self):
4898- auth_token = 'good'
4899-
4900- creds = models.CredentialsAuthorization()
4901- creds.username = 'test'
4902- creds.project = 'test'
4903- creds.auth_token = auth_token
4904-
4905- self.mox.StubOutWithMock(models.CredentialsAuthorization,
4906- 'get_by_token')
4907- self.mox.StubOutWithMock(creds, 'get_zip')
4908- models.CredentialsAuthorization.get_by_token(auth_token) \
4909- .AndReturn(creds)
4910- creds.get_zip().AndReturn('zip')
4911-
4912- self.mox.ReplayAll()
4913-
4914- res = self.client.get(reverse('nova_credentials_authorize',
4915- args=[auth_token]))
4916- self.assertEqual(res.status_code, 200)
4917- self.assertEqual(res['Content-Disposition'],
4918- 'attachment; filename=%s-test-test-x509.zip' %
4919- settings.SITE_NAME)
4920- self.assertContains(res, 'zip')
4921-
4922- self.mox.VerifyAll()
4923
4924=== removed file 'src/django_nova/tests/view_tests/image_tests.py'
4925--- src/django_nova/tests/view_tests/image_tests.py 2011-02-08 01:20:39 +0000
4926+++ src/django_nova/tests/view_tests/image_tests.py 1970-01-01 00:00:00 +0000
4927@@ -1,232 +0,0 @@
4928-# vim: tabstop=4 shiftwidth=4 softtabstop=4
4929-
4930-# Copyright 2010 United States Government as represented by the
4931-# Administrator of the National Aeronautics and Space Administration.
4932-# All Rights Reserved.
4933-#
4934-# Licensed under the Apache License, Version 2.0 (the "License"); you may
4935-# not use this file except in compliance with the License. You may obtain
4936-# a copy of the License at
4937-#
4938-# http://www.apache.org/licenses/LICENSE-2.0
4939-#
4940-# Unless required by applicable law or agreed to in writing, software
4941-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4942-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4943-# License for the specific language governing permissions and limitations
4944-# under the License.
4945-
4946-"""
4947-Unit tests for image views.
4948-"""
4949-
4950-import boto.ec2.image
4951-import boto.ec2.instance
4952-import mox
4953-
4954-from django.core.urlresolvers import reverse
4955-from django_nova import forms
4956-from django_nova import shortcuts
4957-from django_nova.tests.view_tests.base import BaseProjectViewTests, TEST_PROJECT
4958-
4959-
4960-TEST_IMAGE_ID = 'ami_test'
4961-TEST_INSTANCE_ID = 'i-abcdefg'
4962-TEST_KEY = 'foo'
4963-
4964-
4965-class ImageViewTests(BaseProjectViewTests):
4966- def setUp(self):
4967- self.ami = boto.ec2.image.Image()
4968- self.ami.id = TEST_IMAGE_ID
4969- setattr(self.ami, 'displayName', TEST_IMAGE_ID)
4970- setattr(self.ami, 'description', TEST_IMAGE_ID)
4971- super(ImageViewTests, self).setUp()
4972-
4973- def test_index(self):
4974- self.mox.StubOutWithMock(self.project, 'get_images')
4975- self.mox.StubOutWithMock(forms, 'get_key_pair_choices')
4976- self.mox.StubOutWithMock(forms, 'get_instance_type_choices')
4977-
4978- self.project.get_images().AndReturn([])
4979- forms.get_key_pair_choices(self.project).AndReturn([])
4980- forms.get_instance_type_choices().AndReturn([])
4981-
4982- self.mox.ReplayAll()
4983-
4984- res = self.client.get(reverse('nova_images', args=[TEST_PROJECT]))
4985- self.assertEqual(res.status_code, 200)
4986- self.assertTemplateUsed(res, 'django_nova/images/index.html')
4987- self.assertEqual(len(res.context['image_lists']), 3)
4988-
4989- self.mox.VerifyAll()
4990-
4991- def test_launch_form(self):
4992- self.mox.StubOutWithMock(self.project, 'get_image')
4993- self.mox.StubOutWithMock(forms, 'get_key_pair_choices')
4994- self.mox.StubOutWithMock(forms, 'get_instance_type_choices')
4995-
4996- self.project.get_image(TEST_IMAGE_ID).AndReturn(self.ami)
4997- forms.get_key_pair_choices(self.project).AndReturn([])
4998- forms.get_instance_type_choices().AndReturn([])
4999-
5000- self.mox.ReplayAll()
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes:
to status/vote changes: