Merge lp:~termie/nova/move_tests into lp:~hudson-openstack/nova/trunk
- move_tests
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | Eric Day |
Proposed branch: | lp:~termie/nova/move_tests |
Merge into: | lp:~hudson-openstack/nova/trunk |
Diff against target: | 4302 lines |
To merge this branch: | bzr merge lp:~termie/nova/move_tests |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Eric Day (community) | Disapprove | ||
Soren Hansen (community) | Disapprove | ||
Review via email: mp+30739@code.launchpad.net |
Commit message
Description of the change
Move tests out of nova directory.
Mainly so that they aren't packaged with the nova code,
but also just for cleanliness.
Had to fix a small bug in the Network unittests where it was using relative paths.
Soren Hansen (soren) wrote : | # |
Oh, you should set your bzr whomi properly, by the way. "bzr help whoami" for more info.
Soren Hansen (soren) wrote : | # |
And one last thing: bzr supports moving files (using "bzr move" or "bzr rename" (one is an alias for the other)). Please use that when moving files in the future.
termie (termie) wrote : | # |
If that seems to be the common approach no objection here, I'm used to seeing it the other way around. A quick scan through the python repositories I have copies of on my laptop shows:
PIL --
boto -- out
bzr -- in
bzr-fastimport -- out
django -- out
eventlet -- out
google-
gunicorn -- out
mercurial -- out
nose -- out
redis-py -- out
pylint -- ?? wtf are they doing
pyosc -- n/a
python-cloudfiles -- out
python-daemon -- n/a
python-gflags -- n/a
twisted -- in
virtualenv -- n/a
zope -- in
TOTAL:
tests in package: 4
tests outside of package: 9
no package / no test: 5
... which actually makes me inclined to believe that having it out is actually the more common way.
Reconsider?
termie (termie) wrote : | # |
oh, forgot to delete PIL from the list, I had a source zip file.
termie (termie) wrote : | # |
swift also has them out.
If you will approve I will remake a branch using move/rename to clean this up.
Monty Taylor (mordred) wrote : | # |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 07/26/2010 03:10 PM, termie wrote:
> If that seems to be the common approach no objection here, I'm used to seeing it the other way around. A quick scan through the python repositories I have copies of on my laptop shows:
>
> PIL --
> boto -- out
> bzr -- in
> bzr-fastimport -- out
> django -- out
> eventlet -- out
> google-
> gunicorn -- out
> mercurial -- out
> nose -- out
> redis-py -- out
> pylint -- ?? wtf are they doing
> pyosc -- n/a
> python-cloudfiles -- out
> python-daemon -- n/a
> python-gflags -- n/a
> twisted -- in
> virtualenv -- n/a
> zope -- in
>
>
> TOTAL:
> tests in package: 4
> tests outside of package: 9
> no package / no test: 5
>
> ... which actually makes me inclined to believe that having it out is actually the more common way.
>
> Reconsider?
I can make good arguments for either... my personal preference is out
though. My arguments for out:
When I run pep8/pylint, I run it on nova/ ... if you have tests out,
then you don't have to keep them clean. :)
They don't get installed.
Tests are in a location, which means you can find them - and then they
consume the package to be tested just like anyone else. If they're in,
then they're sort of _part_ of that package, which means they may have a
slightly different view of things than things which are not part of that
package.
HOWEVER - I would vote that whichever we pick we should apply to both
swift and nova and then make that our best-practice for openstack
projects. Swift is currently out. Nova is currently in.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://
iEYEARECAAYFAkx
V0YAnRtvnwWn5b3
=Pgtq
-----END PGP SIGNATURE-----
Eric Day (eday) wrote : | # |
My preference would probably by out as well, and don't install them. I would still require pylint/pep8 to pass for everything in tests/ though, no reason to be sloppy there. :)
If we do go this way, definitely need to recreate this branch with proper move/rename though.
Soren Hansen (soren) wrote : | # |
On Mon, Jul 26, 2010 at 10:18:59PM -0000, Monty Taylor wrote:
> I can make good arguments for either... my personal preference is out
> though. My arguments for out:
>
> When I run pep8/pylint, I run it on nova/ ... if you have tests out,
> then you don't have to keep them clean. :)
>
> They don't get installed.
To me, both of those are good reasons why we should keep them in. :)
Soren Hansen (soren) wrote : | # |
To elaborate a bit: Tests are code. It should be just as pretty, neat, and wonderful as any other piece of code.
I want them to be installed so that people can run tests on the installed code as well. There might be environmental things that factor into the tests, so I think it's very valuable to be able to tell people who report bugs to run the test suite, for instance.
In fact, I think I'd much rather move the tests for e.g. the objectstore into nova/objectstor
termie (termie) wrote : | # |
> To elaborate a bit: Tests are code. It should be just as pretty, neat, and
> wonderful as any other piece of code.
>
I agree on the cleanliness, but that has little to do with where the tests live.
> I want them to be installed so that people can run tests on the installed code
> as well. There might be environmental things that factor into the tests, so I
> think it's very valuable to be able to tell people who report bugs to run the
> test suite, for instance.
I think this is a bogus statement, I don't think anybody has ever convinced a 'regular' user to run a test suite and I think any developer who is going to go through the trouble is fine downloading a package or checkout (or more likely going back to the package or checkout they've already downloaded and left in a folder somewhere) to get at the tests.
>
> In fact, I think I'd much rather move the tests for e.g. the objectstore into
> nova/objectstor
> to nova.objectstore are in nova.objectstor
That to me feels obscene, my opinion on subdirectories/
Test-code is self-similar, much more so than it is similar to, say, objectstore's code, and more than it is to anything else in the nova directory. Test code should generally look the same as other test code and, I think, should be thought of as an entity outside of nova twisting the switches and pulling the nobs to make sure all the lights come on at the right times.
In general I don't want people thinking that the test code is part of the nova install, I don't want people referencing the test code from their code, it is stuff that should never be run on a production machine and has no place there. We also already have 'smoketests' that are outside the repo, so there is some precedent.
Soren Hansen (soren) wrote : | # |
On Tue, Jul 27, 2010 at 12:59:43PM -0000, termie wrote:
>> To elaborate a bit: Tests are code. It should be just as pretty,
>> neat, and wonderful as any other piece of code.
> I agree on the cleanliness, but that has little to do with where the
> tests live.
I agree. It was a response to Monty's comment about not having pylint
shout at him about tests if they were not inside nova/.
>> I want them to be installed so that people can run tests on the
>> installed code as well. There might be environmental things that
>> factor into the tests, so I think it's very valuable to be able to
>> tell people who report bugs to run the test suite, for instance.
> I think this is a bogus statement, I don't think anybody has ever
> convinced a 'regular' user to run a test suite
I don't think I understand why you find it so far-fetched to tell a user
to "please run nova-run-tests" if they've reported a bug that looks odd
in some way. It can help identify broken dependencies, user-modified
code (people tend to tinker with stuff if they can, and since this is
all Python, bugs are just a simple $EDITOR away).
> and I think any developer who is going to go through the trouble is
> fine downloading a package or checkout (or more likely going back to
> the package or checkout they've already downloaded and left in a
> folder somewhere) to get at the tests.
I expect people doing vcs checkouts or otherwise installing from source
will be a rarity compared to people who install from packages from their
respective Linux distro.
>> In fact, I think I'd much rather move the tests for e.g. the
>> objectstore into nova/objectstor
>> to me that tests pertaining to nova.objectstore are in
>> nova.objectstor
> That to me feels obscene, my opinion on subdirectories/
> that they exist to hide things,
In that case, I think this conversation is going to difficult :) I treat
subdirectories much like shelves in my book case. I use both to keep
things orderly and arrange stuff according to some set of criteria. I
try to put stuff on the shelves instead of throwing them all on the
floor in front of bookcase. Sure, if the directory structure was
random, it'd be counterproductive, but if it's consistent and
predictable, it's a huge help in organising stuff.
> putting tests further down a hole only makes you forget it is there
> and makes it that much more difficult to keep track of and to get to
> when you are changing something: making things separate that have no
> need to be separate for the sake of having little bins to put
> everything in just means more bins to sort through when you need to
> find something.
I'm completely missing how this is an argument for putting the tests
_all the way outside the tree_.
> Test-code is self-similar, much more so than it is similar to, say,
> objectstore's code, and more than it is to anything else in the nova
> directory. Test code should generally look the same as other test code
> and, I think, should be thought of as an entity outside of nova
> twisting the switches and pulling the nobs to make sure all the lights
> come on at the right times.
I fundamentally disagree. I...
termie (termie) wrote : | # |
> >> I want them to be installed so that people can run tests on the
> >> installed code as well. There might be environmental things that
> >> factor into the tests, so I think it's very valuable to be able to
> >> tell people who report bugs to run the test suite, for instance.
> > I think this is a bogus statement, I don't think anybody has ever
> > convinced a 'regular' user to run a test suite
>
> I don't think I understand why you find it so far-fetched to tell a user
> to "please run nova-run-tests" if they've reported a bug that looks odd
> in some way. It can help identify broken dependencies, user-modified
> code (people tend to tinker with stuff if they can, and since this is
> all Python, bugs are just a simple $EDITOR away).
I agree with the sentiment, but
(a) I don't think unit tests should be testing system compatibility or touching the system much at all, though they still detect missing / invalid python dependencies from time to time. While it is true that we have a mixed bag of tests at the moment, I hope that in the future we will eventually manage to separate the integration tests from the unit tests.
(b) In the event that we have some tests that were relevant towards actually exercising the system they would also have to be pretty sure to "above all, do no harm" if we are expecting some poor user in an already unknown broken state to run them and not have his system worse off afterwards, at the moment the tests litter rather heavily.
(c) I think this use case is much better targeted by a specific set of checks that look for system compatibility / sanity and make sure they are non-invasive. And we would write tests for those checks to make sure they work that wouldn't be run when you run the checks. And since they non-invasive we can run them on install, or any other time.
>
> > and I think any developer who is going to go through the trouble is
> > fine downloading a package or checkout (or more likely going back to
> > the package or checkout they've already downloaded and left in a
> > folder somewhere) to get at the tests.
>
> I expect people doing vcs checkouts or otherwise installing from source
> will be a rarity compared to people who install from packages from their
> respective Linux distro.
Agreed that they are the the rarity, my point was that other users are less likely to be useful candidates for running a test suite.
>
> >> In fact, I think I'd much rather move the tests for e.g. the
> >> objectstore into nova/objectstor
> >> to me that tests pertaining to nova.objectstore are in
> >> nova.objectstor
> > That to me feels obscene, my opinion on subdirectories/
> > that they exist to hide things,
>
> In that case, I think this conversation is going to difficult :) I treat
> subdirectories much like shelves in my book case. I use both to keep
> things orderly and arrange stuff according to some set of criteria. I
> try to put stuff on the shelves instead of throwing them all on the
> floor in front of bookcase. Sure, if the directory structure was
> random, it'd be counterproductive, but if it's consistent and
> predictable, it's a huge h...
Soren Hansen (soren) wrote : | # |
On Tue, Jul 27, 2010 at 11:36:49PM -0000, termie wrote:
> A better one is your office, you keep the things you use often out in
> the open and you put the things you use less often and want out of
> sight in a tray or on a shelf (like a book, because you are unlikely
> to be using a book often). On my desk you will generally find a phone,
> a usb cable, my wallet, my keys and a variety of junk that could be
> put in a box but I would just have to take it back out of the box
> every couple days when I want to use it. Somewhere in the room will be
> drawers (what do you have in your drawers? do you even open them? I
> have ping pong paddles) and shelves. It's messy but if you were to
> attempt to find something on my desk it would be obvious how to
> proceed and you'd likely do it seconds.
Would your rather we put e.g. objectstore tests in
nova/objectstor
concern.
--
Soren Hansen
Ubuntu Developer
http://
Eric Day (eday) wrote : | # |
So, this thread has died. We should decide one way or another so we don't have an outstanding merge request. Anyone feel strongly enough to decide one way or another? The difference between 'nova/tests' vs just 'tests' seems pretty minor.
I actually like the idea of having the tests right alongside the files they test as Soren suggests. For example:
nova/objectstir
...
nova/objectstor
nova/rpc/
...
I can see the argument that this litters tests too much, but the test code is just as real as the production code. :) Having a directory with the same structure for tests (nova/tests/...) seems redundant.
Thoughts?
Soren Hansen (soren) wrote : | # |
Yes, test code is just as real as production code, but I also group production code into directories to keep things orderly. Such is my taste :)
...but sure, if this is what it takes to keep it inside nova/, let's go for it.
Eric Day (eday) wrote : | # |
Marking this as rejected. We'll keep tests as is since this stalled, and if we did want to move the tests out, we would need a new patch that uses bzr renames instead of rm/add anyways.
Preview Diff
1 | === removed directory 'nova/tests' |
2 | === removed directory 'nova/tests/CA' |
3 | === removed file 'nova/tests/CA/cacert.pem' |
4 | --- nova/tests/CA/cacert.pem 2010-05-28 06:05:26 +0000 |
5 | +++ nova/tests/CA/cacert.pem 1970-01-01 00:00:00 +0000 |
6 | @@ -1,17 +0,0 @@ |
7 | ------BEGIN CERTIFICATE----- |
8 | -MIICyzCCAjSgAwIBAgIJANiqHZUcbScCMA0GCSqGSIb3DQEBBAUAME4xEjAQBgNV |
9 | -BAoTCU5PVkEgUk9PVDEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzETMBEGA1UECBMK |
10 | -Q2FsaWZvcm5pYTELMAkGA1UEBhMCVVMwHhcNMTAwNTI4MDExOTI1WhcNMTEwNTI4 |
11 | -MDExOTI1WjBOMRIwEAYDVQQKEwlOT1ZBIFJPT1QxFjAUBgNVBAcTDU1vdW50YWlu |
12 | -IFZpZXcxEzARBgNVBAgTCkNhbGlmb3JuaWExCzAJBgNVBAYTAlVTMIGfMA0GCSqG |
13 | -SIb3DQEBAQUAA4GNADCBiQKBgQDobUnq8rpXA/HQZ2Uu9Me3SlqCayz3ws2wtvFQ |
14 | -koWPUzpriIYPkpprz2EaVu07Zb9uJHvjcoY07nYntl4jR8S7PH4XZhlVFn8AQWzs |
15 | -iThU4KJF71UfVM00dDrarSgVpyOIcFXO3iUvLoJj7+RUPjrWdLuJoMqnhicgLeHZ |
16 | -LAZ8ewIDAQABo4GwMIGtMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFMh1RMlTVtt8 |
17 | -EdESYpsTU08r0FnpMH4GA1UdIwR3MHWAFMh1RMlTVtt8EdESYpsTU08r0FnpoVKk |
18 | -UDBOMRIwEAYDVQQKEwlOT1ZBIFJPT1QxFjAUBgNVBAcTDU1vdW50YWluIFZpZXcx |
19 | -EzARBgNVBAgTCkNhbGlmb3JuaWExCzAJBgNVBAYTAlVTggkA2KodlRxtJwIwDQYJ |
20 | -KoZIhvcNAQEEBQADgYEAq+YCgflK36HCdodNu2ya3O6UDRUE2dW8n96tAOmvHqmR |
21 | -v38k8GIW0pjWDo+lZYnFmeJYd+QGcJl9fLzXxffV5k+rNCfr/gEYtznWLNUX7AZB |
22 | -b/VC7L+yK9qz08C8n51TslXaf3fUGkfkQxsvEP7+hi0qavdd/8eTbdheWahYwWg= |
23 | ------END CERTIFICATE----- |
24 | |
25 | === removed directory 'nova/tests/CA/private' |
26 | === removed file 'nova/tests/CA/private/cakey.pem' |
27 | --- nova/tests/CA/private/cakey.pem 2010-05-28 06:05:26 +0000 |
28 | +++ nova/tests/CA/private/cakey.pem 1970-01-01 00:00:00 +0000 |
29 | @@ -1,15 +0,0 @@ |
30 | ------BEGIN RSA PRIVATE KEY----- |
31 | -MIICXQIBAAKBgQDobUnq8rpXA/HQZ2Uu9Me3SlqCayz3ws2wtvFQkoWPUzpriIYP |
32 | -kpprz2EaVu07Zb9uJHvjcoY07nYntl4jR8S7PH4XZhlVFn8AQWzsiThU4KJF71Uf |
33 | -VM00dDrarSgVpyOIcFXO3iUvLoJj7+RUPjrWdLuJoMqnhicgLeHZLAZ8ewIDAQAB |
34 | -AoGBANQonmZ2Nh2jniFrn/LiwULP/ho6Fov6J6N8+n1focaYZCUwM58XZRmv7KUM |
35 | -X/PuBnVVnDibm2HJodTSJM/zfODnGO15kdmJ9X23FkkdTyuvphO5tYF0ONARXdfX |
36 | -9LbPcLYA14VSCZCKCye6mbv/xi0C/s7q6ZBoMl7XaeD9hgUxAkEA9lxQY/ZxcLV0 |
37 | -Ae5I2spBbtuXEGns11YnKnppc59RrAono1gaDeYY2WZRwztIcD6VtUv7qkzH6ubo |
38 | -shAG4fvnPQJBAPGFaDODs2ckPvxnILEbjpnZXGQqDCpQ3sVJ6nfu+qdAWS92ESNo |
39 | -Y6DC8zFjFaQFbKy6Jxr1VsvYDXhF8cmy7hcCQHkLElSLGWGPRdhNA268QTn+mlJu |
40 | -OPf0VHoCex1cAfzNYHxZJTP/AeaO501NK2I63cOd+aDK6M75dQtH5JnT8uECQQCg |
41 | -jVydkhk6oV+1jiCvW3BKWbIPa9w2bRgJ8n8JRzYc5Kvk3wm5jfVcsvvTgtip9mkt |
42 | -0XmZdCpEy9T4dRasTGP1AkBMhShiVP7+P+SIQlZtSn8ckTt9G6cefEjxsv0kVFZe |
43 | -SjkUO0ZifahF8r3Q1eEUSzdXEvicEwONvcpc7MLwfSD7 |
44 | ------END RSA PRIVATE KEY----- |
45 | |
46 | === removed file 'nova/tests/__init__.py' |
47 | --- nova/tests/__init__.py 2010-07-15 15:52:11 +0000 |
48 | +++ nova/tests/__init__.py 1970-01-01 00:00:00 +0000 |
49 | @@ -1,31 +0,0 @@ |
50 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
51 | - |
52 | -# Copyright 2010 United States Government as represented by the |
53 | -# Administrator of the National Aeronautics and Space Administration. |
54 | -# All Rights Reserved. |
55 | -# |
56 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
57 | -# not use this file except in compliance with the License. You may obtain |
58 | -# a copy of the License at |
59 | -# |
60 | -# http://www.apache.org/licenses/LICENSE-2.0 |
61 | -# |
62 | -# Unless required by applicable law or agreed to in writing, software |
63 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
64 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
65 | -# License for the specific language governing permissions and limitations |
66 | -# under the License. |
67 | - |
68 | -""" |
69 | -:mod:`nova.tests` -- Nova Unittests |
70 | -===================================================== |
71 | - |
72 | -.. automodule:: nova.tests |
73 | - :platform: Unix |
74 | -.. moduleauthor:: Jesse Andrews <jesse@ansolabs.com> |
75 | -.. moduleauthor:: Devin Carlen <devin.carlen@gmail.com> |
76 | -.. moduleauthor:: Vishvananda Ishaya <vishvananda@yahoo.com> |
77 | -.. moduleauthor:: Joshua McKenty <joshua@cognition.ca> |
78 | -.. moduleauthor:: Manish Singh <yosh@gimp.org> |
79 | -.. moduleauthor:: Andy Smith <andy@anarkystic.com> |
80 | -""" |
81 | |
82 | === removed file 'nova/tests/access_unittest.py' |
83 | --- nova/tests/access_unittest.py 2010-07-15 23:13:48 +0000 |
84 | +++ nova/tests/access_unittest.py 1970-01-01 00:00:00 +0000 |
85 | @@ -1,165 +0,0 @@ |
86 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
87 | - |
88 | -# Copyright 2010 United States Government as represented by the |
89 | -# Administrator of the National Aeronautics and Space Administration. |
90 | -# All Rights Reserved. |
91 | -# |
92 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
93 | -# not use this file except in compliance with the License. You may obtain |
94 | -# a copy of the License at |
95 | -# |
96 | -# http://www.apache.org/licenses/LICENSE-2.0 |
97 | -# |
98 | -# Unless required by applicable law or agreed to in writing, software |
99 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
100 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
101 | -# License for the specific language governing permissions and limitations |
102 | -# under the License. |
103 | - |
104 | -import unittest |
105 | -import logging |
106 | - |
107 | -from nova import exception |
108 | -from nova import flags |
109 | -from nova import test |
110 | -from nova.auth.users import UserManager |
111 | -from nova.auth import rbac |
112 | - |
113 | - |
114 | -FLAGS = flags.FLAGS |
115 | -class Context(object): |
116 | - pass |
117 | - |
118 | -class AccessTestCase(test.BaseTestCase): |
119 | - def setUp(self): |
120 | - super(AccessTestCase, self).setUp() |
121 | - FLAGS.fake_libvirt = True |
122 | - FLAGS.fake_storage = True |
123 | - um = UserManager.instance() |
124 | - # Make test users |
125 | - try: |
126 | - self.testadmin = um.create_user('testadmin') |
127 | - except Exception, err: |
128 | - logging.error(str(err)) |
129 | - try: |
130 | - self.testpmsys = um.create_user('testpmsys') |
131 | - except: pass |
132 | - try: |
133 | - self.testnet = um.create_user('testnet') |
134 | - except: pass |
135 | - try: |
136 | - self.testsys = um.create_user('testsys') |
137 | - except: pass |
138 | - # Assign some rules |
139 | - try: |
140 | - um.add_role('testadmin', 'cloudadmin') |
141 | - except: pass |
142 | - try: |
143 | - um.add_role('testpmsys', 'sysadmin') |
144 | - except: pass |
145 | - try: |
146 | - um.add_role('testnet', 'netadmin') |
147 | - except: pass |
148 | - try: |
149 | - um.add_role('testsys', 'sysadmin') |
150 | - except: pass |
151 | - |
152 | - # Make a test project |
153 | - try: |
154 | - self.project = um.create_project('testproj', 'testpmsys', 'a test project', ['testpmsys', 'testnet', 'testsys']) |
155 | - except: pass |
156 | - try: |
157 | - self.project.add_role(self.testnet, 'netadmin') |
158 | - except: pass |
159 | - try: |
160 | - self.project.add_role(self.testsys, 'sysadmin') |
161 | - except: pass |
162 | - self.context = Context() |
163 | - self.context.project = self.project |
164 | - #user is set in each test |
165 | - |
166 | - def tearDown(self): |
167 | - um = UserManager.instance() |
168 | - # Delete the test project |
169 | - um.delete_project('testproj') |
170 | - # Delete the test user |
171 | - um.delete_user('testadmin') |
172 | - um.delete_user('testpmsys') |
173 | - um.delete_user('testnet') |
174 | - um.delete_user('testsys') |
175 | - super(AccessTestCase, self).tearDown() |
176 | - |
177 | - def test_001_allow_all(self): |
178 | - self.context.user = self.testadmin |
179 | - self.assertTrue(self._allow_all(self.context)) |
180 | - self.context.user = self.testpmsys |
181 | - self.assertTrue(self._allow_all(self.context)) |
182 | - self.context.user = self.testnet |
183 | - self.assertTrue(self._allow_all(self.context)) |
184 | - self.context.user = self.testsys |
185 | - self.assertTrue(self._allow_all(self.context)) |
186 | - |
187 | - def test_002_allow_none(self): |
188 | - self.context.user = self.testadmin |
189 | - self.assertTrue(self._allow_none(self.context)) |
190 | - self.context.user = self.testpmsys |
191 | - self.assertRaises(exception.NotAuthorized, self._allow_none, self.context) |
192 | - self.context.user = self.testnet |
193 | - self.assertRaises(exception.NotAuthorized, self._allow_none, self.context) |
194 | - self.context.user = self.testsys |
195 | - self.assertRaises(exception.NotAuthorized, self._allow_none, self.context) |
196 | - |
197 | - def test_003_allow_project_manager(self): |
198 | - self.context.user = self.testadmin |
199 | - self.assertTrue(self._allow_project_manager(self.context)) |
200 | - self.context.user = self.testpmsys |
201 | - self.assertTrue(self._allow_project_manager(self.context)) |
202 | - self.context.user = self.testnet |
203 | - self.assertRaises(exception.NotAuthorized, self._allow_project_manager, self.context) |
204 | - self.context.user = self.testsys |
205 | - self.assertRaises(exception.NotAuthorized, self._allow_project_manager, self.context) |
206 | - |
207 | - def test_004_allow_sys_and_net(self): |
208 | - self.context.user = self.testadmin |
209 | - self.assertTrue(self._allow_sys_and_net(self.context)) |
210 | - self.context.user = self.testpmsys # doesn't have the per project sysadmin |
211 | - self.assertRaises(exception.NotAuthorized, self._allow_sys_and_net, self.context) |
212 | - self.context.user = self.testnet |
213 | - self.assertTrue(self._allow_sys_and_net(self.context)) |
214 | - self.context.user = self.testsys |
215 | - self.assertTrue(self._allow_sys_and_net(self.context)) |
216 | - |
217 | - def test_005_allow_sys_no_pm(self): |
218 | - self.context.user = self.testadmin |
219 | - self.assertTrue(self._allow_sys_no_pm(self.context)) |
220 | - self.context.user = self.testpmsys |
221 | - self.assertRaises(exception.NotAuthorized, self._allow_sys_no_pm, self.context) |
222 | - self.context.user = self.testnet |
223 | - self.assertRaises(exception.NotAuthorized, self._allow_sys_no_pm, self.context) |
224 | - self.context.user = self.testsys |
225 | - self.assertTrue(self._allow_sys_no_pm(self.context)) |
226 | - |
227 | - @rbac.allow('all') |
228 | - def _allow_all(self, context): |
229 | - return True |
230 | - |
231 | - @rbac.allow('none') |
232 | - def _allow_none(self, context): |
233 | - return True |
234 | - |
235 | - @rbac.allow('projectmanager') |
236 | - def _allow_project_manager(self, context): |
237 | - return True |
238 | - |
239 | - @rbac.allow('sysadmin', 'netadmin') |
240 | - def _allow_sys_and_net(self, context): |
241 | - return True |
242 | - |
243 | - @rbac.allow('sysadmin') |
244 | - @rbac.deny('projectmanager') |
245 | - def _allow_sys_no_pm(self, context): |
246 | - return True |
247 | - |
248 | -if __name__ == "__main__": |
249 | - # TODO: Implement use_fake as an option |
250 | - unittest.main() |
251 | |
252 | === removed file 'nova/tests/api_integration.py' |
253 | --- nova/tests/api_integration.py 2010-07-15 23:13:48 +0000 |
254 | +++ nova/tests/api_integration.py 1970-01-01 00:00:00 +0000 |
255 | @@ -1,54 +0,0 @@ |
256 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
257 | - |
258 | -# Copyright 2010 United States Government as represented by the |
259 | -# Administrator of the National Aeronautics and Space Administration. |
260 | -# All Rights Reserved. |
261 | -# |
262 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
263 | -# not use this file except in compliance with the License. You may obtain |
264 | -# a copy of the License at |
265 | -# |
266 | -# http://www.apache.org/licenses/LICENSE-2.0 |
267 | -# |
268 | -# Unless required by applicable law or agreed to in writing, software |
269 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
270 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
271 | -# License for the specific language governing permissions and limitations |
272 | -# under the License. |
273 | - |
274 | - |
275 | -import boto |
276 | -from boto.ec2.regioninfo import RegionInfo |
277 | -import unittest |
278 | - |
279 | - |
280 | -ACCESS_KEY = 'fake' |
281 | -SECRET_KEY = 'fake' |
282 | -CLC_IP = '127.0.0.1' |
283 | -CLC_PORT = 8773 |
284 | -REGION = 'test' |
285 | - |
286 | -def get_connection(): |
287 | - return boto.connect_ec2 ( |
288 | - aws_access_key_id=ACCESS_KEY, |
289 | - aws_secret_access_key=SECRET_KEY, |
290 | - is_secure=False, |
291 | - region=RegionInfo(None, REGION, CLC_IP), |
292 | - port=CLC_PORT, |
293 | - path='/services/Cloud', |
294 | - debug=99 |
295 | - ) |
296 | - |
297 | -class APIIntegrationTests(unittest.TestCase): |
298 | - def test_001_get_all_images(self): |
299 | - conn = get_connection() |
300 | - res = conn.get_all_images() |
301 | - |
302 | - |
303 | -if __name__ == '__main__': |
304 | - unittest.main() |
305 | - |
306 | -#print conn.get_all_key_pairs() |
307 | -#print conn.create_key_pair |
308 | -#print conn.create_security_group('name', 'description') |
309 | - |
310 | |
311 | === removed file 'nova/tests/api_unittest.py' |
312 | --- nova/tests/api_unittest.py 2010-07-15 23:13:48 +0000 |
313 | +++ nova/tests/api_unittest.py 1970-01-01 00:00:00 +0000 |
314 | @@ -1,199 +0,0 @@ |
315 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
316 | - |
317 | -# Copyright 2010 United States Government as represented by the |
318 | -# Administrator of the National Aeronautics and Space Administration. |
319 | -# All Rights Reserved. |
320 | -# |
321 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
322 | -# not use this file except in compliance with the License. You may obtain |
323 | -# a copy of the License at |
324 | -# |
325 | -# http://www.apache.org/licenses/LICENSE-2.0 |
326 | -# |
327 | -# Unless required by applicable law or agreed to in writing, software |
328 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
329 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
330 | -# License for the specific language governing permissions and limitations |
331 | -# under the License. |
332 | - |
333 | -import boto |
334 | -from boto.ec2 import regioninfo |
335 | -import httplib |
336 | -import random |
337 | -import StringIO |
338 | -from tornado import httpserver |
339 | -from twisted.internet import defer |
340 | - |
341 | -from nova import flags |
342 | -from nova import test |
343 | -from nova.auth import users |
344 | -from nova.endpoint import api |
345 | -from nova.endpoint import cloud |
346 | - |
347 | - |
348 | -FLAGS = flags.FLAGS |
349 | - |
350 | - |
351 | -# NOTE(termie): These are a bunch of helper methods and classes to short |
352 | -# circuit boto calls and feed them into our tornado handlers, |
353 | -# it's pretty damn circuitous so apologies if you have to fix |
354 | -# a bug in it |
355 | -def boto_to_tornado(method, path, headers, data, host, connection=None): |
356 | - """ translate boto requests into tornado requests |
357 | - |
358 | - connection should be a FakeTornadoHttpConnection instance |
359 | - """ |
360 | - headers = httpserver.HTTPHeaders() |
361 | - for k, v in headers.iteritems(): |
362 | - headers[k] = v |
363 | - |
364 | - req = httpserver.HTTPRequest(method=method, |
365 | - uri=path, |
366 | - headers=headers, |
367 | - body=data, |
368 | - host=host, |
369 | - remote_ip='127.0.0.1', |
370 | - connection=connection) |
371 | - return req |
372 | - |
373 | - |
374 | -def raw_to_httpresponse(s): |
375 | - """ translate a raw tornado http response into an httplib.HTTPResponse """ |
376 | - sock = FakeHttplibSocket(s) |
377 | - resp = httplib.HTTPResponse(sock) |
378 | - resp.begin() |
379 | - return resp |
380 | - |
381 | - |
382 | -class FakeHttplibSocket(object): |
383 | - """ a fake socket implementation for httplib.HTTPResponse, trivial """ |
384 | - def __init__(self, s): |
385 | - self.fp = StringIO.StringIO(s) |
386 | - |
387 | - def makefile(self, mode, other): |
388 | - return self.fp |
389 | - |
390 | - |
391 | -class FakeTornadoStream(object): |
392 | - """ a fake stream to satisfy tornado's assumptions, trivial """ |
393 | - def set_close_callback(self, f): |
394 | - pass |
395 | - |
396 | - |
397 | -class FakeTornadoConnection(object): |
398 | - """ a fake connection object for tornado to pass to its handlers |
399 | - |
400 | - web requests are expected to write to this as they get data and call |
401 | - finish when they are done with the request, we buffer the writes and |
402 | - kick off a callback when it is done so that we can feed the result back |
403 | - into boto. |
404 | - """ |
405 | - def __init__(self, d): |
406 | - self.d = d |
407 | - self._buffer = StringIO.StringIO() |
408 | - |
409 | - def write(self, chunk): |
410 | - self._buffer.write(chunk) |
411 | - |
412 | - def finish(self): |
413 | - s = self._buffer.getvalue() |
414 | - self.d.callback(s) |
415 | - |
416 | - xheaders = None |
417 | - |
418 | - @property |
419 | - def stream(self): |
420 | - return FakeTornadoStream() |
421 | - |
422 | - |
423 | -class FakeHttplibConnection(object): |
424 | - """ a fake httplib.HTTPConnection for boto to use |
425 | - |
426 | - requests made via this connection actually get translated and routed into |
427 | - our tornado app, we then wait for the response and turn it back into |
428 | - the httplib.HTTPResponse that boto expects. |
429 | - """ |
430 | - def __init__(self, app, host, is_secure=False): |
431 | - self.app = app |
432 | - self.host = host |
433 | - self.deferred = defer.Deferred() |
434 | - |
435 | - def request(self, method, path, data, headers): |
436 | - req = boto_to_tornado |
437 | - conn = FakeTornadoConnection(self.deferred) |
438 | - request = boto_to_tornado(connection=conn, |
439 | - method=method, |
440 | - path=path, |
441 | - headers=headers, |
442 | - data=data, |
443 | - host=self.host) |
444 | - handler = self.app(request) |
445 | - self.deferred.addCallback(raw_to_httpresponse) |
446 | - |
447 | - def getresponse(self): |
448 | - @defer.inlineCallbacks |
449 | - def _waiter(): |
450 | - result = yield self.deferred |
451 | - defer.returnValue(result) |
452 | - d = _waiter() |
453 | - # NOTE(termie): defer.returnValue above should ensure that |
454 | - # this deferred has already been called by the time |
455 | - # we get here, we are going to cheat and return |
456 | - # the result of the callback |
457 | - return d.result |
458 | - |
459 | - def close(self): |
460 | - pass |
461 | - |
462 | - |
463 | -class ApiEc2TestCase(test.BaseTestCase): |
464 | - def setUp(self): |
465 | - super(ApiEc2TestCase, self).setUp() |
466 | - |
467 | - self.users = users.UserManager.instance() |
468 | - self.cloud = cloud.CloudController() |
469 | - |
470 | - self.host = '127.0.0.1' |
471 | - |
472 | - self.app = api.APIServerApplication({'Cloud': self.cloud}) |
473 | - self.ec2 = boto.connect_ec2( |
474 | - aws_access_key_id='fake', |
475 | - aws_secret_access_key='fake', |
476 | - is_secure=False, |
477 | - region=regioninfo.RegionInfo(None, 'test', self.host), |
478 | - port=FLAGS.cc_port, |
479 | - path='/services/Cloud') |
480 | - |
481 | - self.mox.StubOutWithMock(self.ec2, 'new_http_connection') |
482 | - |
483 | - def expect_http(self, host=None, is_secure=False): |
484 | - http = FakeHttplibConnection( |
485 | - self.app, '%s:%d' % (self.host, FLAGS.cc_port), False) |
486 | - self.ec2.new_http_connection(host, is_secure).AndReturn(http) |
487 | - return http |
488 | - |
489 | - def test_describe_instances(self): |
490 | - self.expect_http() |
491 | - self.mox.ReplayAll() |
492 | - try: |
493 | - self.users.create_user('fake', 'fake', 'fake') |
494 | - except Exception, _err: |
495 | - pass # User may already exist |
496 | - self.assertEqual(self.ec2.get_all_instances(), []) |
497 | - self.users.delete_user('fake') |
498 | - |
499 | - |
500 | - def test_get_all_key_pairs(self): |
501 | - self.expect_http() |
502 | - self.mox.ReplayAll() |
503 | - keyname = "".join(random.choice("sdiuisudfsdcnpaqwertasd") for x in range(random.randint(4, 8))) |
504 | - try: |
505 | - self.users.create_user('fake', 'fake', 'fake') |
506 | - except Exception, _err: |
507 | - pass # User may already exist |
508 | - self.users.generate_key_pair('fake', keyname) |
509 | - |
510 | - rv = self.ec2.get_all_key_pairs() |
511 | - self.assertTrue(filter(lambda k: k.name == keyname, rv)) |
512 | - self.users.delete_user('fake') |
513 | - |
514 | |
515 | === removed directory 'nova/tests/bundle' |
516 | === removed file 'nova/tests/bundle/1mb.manifest.xml' |
517 | --- nova/tests/bundle/1mb.manifest.xml 2010-05-28 06:05:26 +0000 |
518 | +++ nova/tests/bundle/1mb.manifest.xml 1970-01-01 00:00:00 +0000 |
519 | @@ -1,1 +0,0 @@ |
520 | -<?xml version="1.0" ?><manifest><version>2007-10-10</version><bundler><name>euca-tools</name><version>1.2</version><release>31337</release></bundler><machine_configuration><architecture>x86_64</architecture></machine_configuration><image><name>1mb</name><user>42</user><type>machine</type><digest algorithm="SHA1">da39a3ee5e6b4b0d3255bfef95601890afd80709</digest><size>1048576</size><bundled_size>1136</bundled_size><ec2_encrypted_key algorithm="AES-128-CBC">33a2ea00dc64083dd9a10eb5e233635b42a7beb1670ab75452087d9de74c60aba1cd27c136fda56f62beb581de128fb1f10d072b9e556fd25e903107a57827c21f6ee8a93a4ff55b11311fcef217e3eefb07e81f71e88216f43b4b54029c1f2549f2925a839a73947d2d5aeecec4a62ece4af9156d557ae907978298296d9915</ec2_encrypted_key><user_encrypted_key algorithm="AES-128-CBC">4c11147fd8caf92447e90ce339928933d7579244c2f8ffb07cc0ea35f8738da8b90eff6c7a49671a84500e993e9462e4c36d5c19c0b3a2b397d035b4c0cce742b58e12552175d81d129b0425e9f71ebacb9aeb539fa9dd2ac36749fb82876f6902e5fb24b6ec19f35ec4c20acd50437fd30966e99c4d9a0647577970a8fa3023</user_encrypted_key><ec2_encrypted_iv>14bd082c9715f071160c69bbfb070f51d2ba1076775f1d988ccde150e515088156b248e4b5a64e46c4fe064feeeedfe14511f7fde478a51acb89f9b2f6c84b60593e5c3f792ba6b01fed9bf2158fdac03086374883b39d13a3ca74497eeaaf579fc3f26effc73bfd9446a2a8c4061f0874bfaca058905180e22d3d8881551cb3</ec2_encrypted_iv><user_encrypted_iv>8f7606f19f00e4e19535dd234b66b31b77e9c7bad3885d9c9efa75c863631fd4f82a009e17d789066d9cc6032a436f05384832f6d9a3283d3e63eab04fa0da5c8c87db9b17e854e842c3fb416507d067a266b44538125ce732e486098e8ebd1ca91fa3079f007fce7d14957a9b7e57282407ead3c6eb68fe975df3d83190021b</user_encrypted_iv><parts count="2"><part index="0"><filename>1mb.part.0</filename><digest algorithm="SHA1">c4413423cf7a57e71187e19bfd5cd4b514a64283</digest></part><part index="1"><filename>1mb.part.1</filename><digest algorithm="SHA1">9d4262e6589393d09a11a0332af169887bc2e57d</digest></part></parts></image><signature>4e00b5ba28114dda4a9df7eeae94be847ec46117a09a1cbe41e578660642f0660dda1776b39fb3bf826b6cfec019e2a5e9c566728d186b7400ebc989a30670eb1db26ce01e68bd9d3f31290370077a85b81c66b63c1e0d5499bac115c06c17a21a81b6d3a67ebbce6c17019095af7ab07f3796c708cc843e58efc12ddc788c5e</signature></manifest> |
521 | \ No newline at end of file |
522 | |
523 | === removed file 'nova/tests/bundle/1mb.part.0' |
524 | Binary files nova/tests/bundle/1mb.part.0 2010-05-28 06:05:26 +0000 and nova/tests/bundle/1mb.part.0 1970-01-01 00:00:00 +0000 differ |
525 | === removed file 'nova/tests/bundle/1mb.part.1' |
526 | --- nova/tests/bundle/1mb.part.1 2010-05-28 06:05:26 +0000 |
527 | +++ nova/tests/bundle/1mb.part.1 1970-01-01 00:00:00 +0000 |
528 | @@ -1,1 +0,0 @@ |
529 | -´ˆà «€ç‰°Æ³ |
530 | ¡ÀiDHW̽×JÈ8ïrV¼³h§X’·@Yj“~Ø |
531 | ·Gû5û 3Nt«˜•H6Ñ$§Ëgö™é Lá¢+³æ¤X†pm¬@,øŽ>7ÚÊ×užp¼ aü`¥V2X@£#ᶠ|
532 | \ No newline at end of file |
533 | |
534 | === removed file 'nova/tests/cloud_unittest.py' |
535 | --- nova/tests/cloud_unittest.py 2010-07-15 23:13:48 +0000 |
536 | +++ nova/tests/cloud_unittest.py 1970-01-01 00:00:00 +0000 |
537 | @@ -1,163 +0,0 @@ |
538 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
539 | - |
540 | -# Copyright 2010 United States Government as represented by the |
541 | -# Administrator of the National Aeronautics and Space Administration. |
542 | -# All Rights Reserved. |
543 | -# |
544 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
545 | -# not use this file except in compliance with the License. You may obtain |
546 | -# a copy of the License at |
547 | -# |
548 | -# http://www.apache.org/licenses/LICENSE-2.0 |
549 | -# |
550 | -# Unless required by applicable law or agreed to in writing, software |
551 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
552 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
553 | -# License for the specific language governing permissions and limitations |
554 | -# under the License. |
555 | - |
556 | -import logging |
557 | -import StringIO |
558 | -import time |
559 | -from tornado import ioloop |
560 | -from twisted.internet import defer |
561 | -import unittest |
562 | -from xml.etree import ElementTree |
563 | - |
564 | -from nova import flags |
565 | -from nova import rpc |
566 | -from nova import test |
567 | -from nova.auth import users |
568 | -from nova.compute import node |
569 | -from nova.endpoint import api |
570 | -from nova.endpoint import cloud |
571 | - |
572 | - |
573 | -FLAGS = flags.FLAGS |
574 | - |
575 | - |
576 | -class CloudTestCase(test.BaseTestCase): |
577 | - def setUp(self): |
578 | - super(CloudTestCase, self).setUp() |
579 | - self.flags(fake_libvirt=True, |
580 | - fake_storage=True, |
581 | - fake_users=True) |
582 | - |
583 | - self.conn = rpc.Connection.instance() |
584 | - logging.getLogger().setLevel(logging.DEBUG) |
585 | - |
586 | - # set up our cloud |
587 | - self.cloud = cloud.CloudController() |
588 | - self.cloud_consumer = rpc.AdapterConsumer(connection=self.conn, |
589 | - topic=FLAGS.cloud_topic, |
590 | - proxy=self.cloud) |
591 | - self.injected.append(self.cloud_consumer.attach_to_tornado(self.ioloop)) |
592 | - |
593 | - # set up a node |
594 | - self.node = node.Node() |
595 | - self.node_consumer = rpc.AdapterConsumer(connection=self.conn, |
596 | - topic=FLAGS.compute_topic, |
597 | - proxy=self.node) |
598 | - self.injected.append(self.node_consumer.attach_to_tornado(self.ioloop)) |
599 | - |
600 | - try: |
601 | - users.UserManager.instance().create_user('admin', 'admin', 'admin') |
602 | - except: pass |
603 | - admin = users.UserManager.instance().get_user('admin') |
604 | - project = users.UserManager.instance().create_project('proj', 'admin', 'proj') |
605 | - self.context = api.APIRequestContext(handler=None,project=project,user=admin) |
606 | - |
607 | - def tearDown(self): |
608 | - users.UserManager.instance().delete_project('proj') |
609 | - users.UserManager.instance().delete_user('admin') |
610 | - |
611 | - def test_console_output(self): |
612 | - if FLAGS.fake_libvirt: |
613 | - logging.debug("Can't test instances without a real virtual env.") |
614 | - return |
615 | - instance_id = 'foo' |
616 | - inst = yield self.node.run_instance(instance_id) |
617 | - output = yield self.cloud.get_console_output(self.context, [instance_id]) |
618 | - logging.debug(output) |
619 | - self.assert_(output) |
620 | - rv = yield self.node.terminate_instance(instance_id) |
621 | - |
622 | - def test_run_instances(self): |
623 | - if FLAGS.fake_libvirt: |
624 | - logging.debug("Can't test instances without a real virtual env.") |
625 | - return |
626 | - image_id = FLAGS.default_image |
627 | - instance_type = FLAGS.default_instance_type |
628 | - max_count = 1 |
629 | - kwargs = {'image_id': image_id, |
630 | - 'instance_type': instance_type, |
631 | - 'max_count': max_count} |
632 | - rv = yield self.cloud.run_instances(self.context, **kwargs) |
633 | - # TODO: check for proper response |
634 | - instance = rv['reservationSet'][0][rv['reservationSet'][0].keys()[0]][0] |
635 | - logging.debug("Need to watch instance %s until it's running..." % instance['instance_id']) |
636 | - while True: |
637 | - rv = yield defer.succeed(time.sleep(1)) |
638 | - info = self.cloud._get_instance(instance['instance_id']) |
639 | - logging.debug(info['state']) |
640 | - if info['state'] == node.Instance.RUNNING: |
641 | - break |
642 | - self.assert_(rv) |
643 | - |
644 | - if not FLAGS.fake_libvirt: |
645 | - time.sleep(45) # Should use boto for polling here |
646 | - for reservations in rv['reservationSet']: |
647 | - # for res_id in reservations.keys(): |
648 | - # logging.debug(reservations[res_id]) |
649 | - # for instance in reservations[res_id]: |
650 | - for instance in reservations[reservations.keys()[0]]: |
651 | - logging.debug("Terminating instance %s" % instance['instance_id']) |
652 | - rv = yield self.node.terminate_instance(instance['instance_id']) |
653 | - |
654 | - def test_instance_update_state(self): |
655 | - def instance(num): |
656 | - return { |
657 | - 'reservation_id': 'r-1', |
658 | - 'instance_id': 'i-%s' % num, |
659 | - 'image_id': 'ami-%s' % num, |
660 | - 'private_dns_name': '10.0.0.%s' % num, |
661 | - 'dns_name': '10.0.0%s' % num, |
662 | - 'ami_launch_index': str(num), |
663 | - 'instance_type': 'fake', |
664 | - 'availability_zone': 'fake', |
665 | - 'key_name': None, |
666 | - 'kernel_id': 'fake', |
667 | - 'ramdisk_id': 'fake', |
668 | - 'groups': ['default'], |
669 | - 'product_codes': None, |
670 | - 'state': 0x01, |
671 | - 'user_data': '' |
672 | - } |
673 | - rv = self.cloud._format_instances(self.context) |
674 | - self.assert_(len(rv['reservationSet']) == 0) |
675 | - |
676 | - # simulate launch of 5 instances |
677 | - # self.cloud.instances['pending'] = {} |
678 | - #for i in xrange(5): |
679 | - # inst = instance(i) |
680 | - # self.cloud.instances['pending'][inst['instance_id']] = inst |
681 | - |
682 | - #rv = self.cloud._format_instances(self.admin) |
683 | - #self.assert_(len(rv['reservationSet']) == 1) |
684 | - #self.assert_(len(rv['reservationSet'][0]['instances_set']) == 5) |
685 | - # report 4 nodes each having 1 of the instances |
686 | - #for i in xrange(4): |
687 | - # self.cloud.update_state('instances', {('node-%s' % i): {('i-%s' % i): instance(i)}}) |
688 | - |
689 | - # one instance should be pending still |
690 | - #self.assert_(len(self.cloud.instances['pending'].keys()) == 1) |
691 | - |
692 | - # check that the reservations collapse |
693 | - #rv = self.cloud._format_instances(self.admin) |
694 | - #self.assert_(len(rv['reservationSet']) == 1) |
695 | - #self.assert_(len(rv['reservationSet'][0]['instances_set']) == 5) |
696 | - |
697 | - # check that we can get metadata for each instance |
698 | - #for i in xrange(4): |
699 | - # data = self.cloud.get_metadata(instance(i)['private_dns_name']) |
700 | - # self.assert_(data['meta-data']['ami-id'] == 'ami-%s' % i) |
701 | |
702 | === removed file 'nova/tests/fake_flags.py' |
703 | --- nova/tests/fake_flags.py 2010-07-15 15:52:11 +0000 |
704 | +++ nova/tests/fake_flags.py 1970-01-01 00:00:00 +0000 |
705 | @@ -1,28 +0,0 @@ |
706 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
707 | - |
708 | -# Copyright 2010 United States Government as represented by the |
709 | -# Administrator of the National Aeronautics and Space Administration. |
710 | -# All Rights Reserved. |
711 | -# |
712 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
713 | -# not use this file except in compliance with the License. You may obtain |
714 | -# a copy of the License at |
715 | -# |
716 | -# http://www.apache.org/licenses/LICENSE-2.0 |
717 | -# |
718 | -# Unless required by applicable law or agreed to in writing, software |
719 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
720 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
721 | -# License for the specific language governing permissions and limitations |
722 | -# under the License. |
723 | - |
724 | -from nova import flags |
725 | - |
726 | -FLAGS = flags.FLAGS |
727 | - |
728 | -FLAGS.fake_libvirt = True |
729 | -FLAGS.fake_storage = True |
730 | -FLAGS.fake_rabbit = True |
731 | -FLAGS.fake_network = True |
732 | -FLAGS.fake_users = True |
733 | -FLAGS.verbose = True |
734 | |
735 | === removed file 'nova/tests/future_unittest.py' |
736 | --- nova/tests/future_unittest.py 2010-07-15 23:13:48 +0000 |
737 | +++ nova/tests/future_unittest.py 1970-01-01 00:00:00 +0000 |
738 | @@ -1,75 +0,0 @@ |
739 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
740 | - |
741 | -# Copyright 2010 United States Government as represented by the |
742 | -# Administrator of the National Aeronautics and Space Administration. |
743 | -# All Rights Reserved. |
744 | -# |
745 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
746 | -# not use this file except in compliance with the License. You may obtain |
747 | -# a copy of the License at |
748 | -# |
749 | -# http://www.apache.org/licenses/LICENSE-2.0 |
750 | -# |
751 | -# Unless required by applicable law or agreed to in writing, software |
752 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
753 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
754 | -# License for the specific language governing permissions and limitations |
755 | -# under the License. |
756 | - |
757 | -import logging |
758 | -import mox |
759 | -import StringIO |
760 | -import time |
761 | -from tornado import ioloop |
762 | -from twisted.internet import defer |
763 | -import unittest |
764 | -from xml.etree import ElementTree |
765 | - |
766 | -from nova import cloud |
767 | -from nova import exception |
768 | -from nova import flags |
769 | -from nova import node |
770 | -from nova import rpc |
771 | -from nova import test |
772 | - |
773 | - |
774 | -FLAGS = flags.FLAGS |
775 | - |
776 | - |
777 | -class AdminTestCase(test.BaseTestCase): |
778 | - def setUp(self): |
779 | - super(AdminTestCase, self).setUp() |
780 | - self.flags(fake_libvirt=True, |
781 | - fake_rabbit=True) |
782 | - |
783 | - self.conn = rpc.Connection.instance() |
784 | - |
785 | - logging.getLogger().setLevel(logging.INFO) |
786 | - |
787 | - # set up our cloud |
788 | - self.cloud = cloud.CloudController() |
789 | - self.cloud_consumer = rpc.AdapterConsumer(connection=self.conn, |
790 | - topic=FLAGS.cloud_topic, |
791 | - proxy=self.cloud) |
792 | - self.injected.append(self.cloud_consumer.attach_to_tornado(self.ioloop)) |
793 | - |
794 | - # set up a node |
795 | - self.node = node.Node() |
796 | - self.node_consumer = rpc.AdapterConsumer(connection=self.conn, |
797 | - topic=FLAGS.compute_topic, |
798 | - proxy=self.node) |
799 | - self.injected.append(self.node_consumer.attach_to_tornado(self.ioloop)) |
800 | - |
801 | - def test_flush_terminated(self): |
802 | - # Launch an instance |
803 | - |
804 | - # Wait until it's running |
805 | - |
806 | - # Terminate it |
807 | - |
808 | - # Wait until it's terminated |
809 | - |
810 | - # Flush terminated nodes |
811 | - |
812 | - # ASSERT that it's gone |
813 | - pass |
814 | |
815 | === removed file 'nova/tests/model_unittest.py' |
816 | --- nova/tests/model_unittest.py 2010-07-15 23:13:48 +0000 |
817 | +++ nova/tests/model_unittest.py 1970-01-01 00:00:00 +0000 |
818 | @@ -1,206 +0,0 @@ |
819 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
820 | - |
821 | -# Copyright 2010 United States Government as represented by the |
822 | -# Administrator of the National Aeronautics and Space Administration. |
823 | -# All Rights Reserved. |
824 | -# |
825 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
826 | -# not use this file except in compliance with the License. You may obtain |
827 | -# a copy of the License at |
828 | -# |
829 | -# http://www.apache.org/licenses/LICENSE-2.0 |
830 | -# |
831 | -# Unless required by applicable law or agreed to in writing, software |
832 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
833 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
834 | -# License for the specific language governing permissions and limitations |
835 | -# under the License. |
836 | - |
837 | -import logging |
838 | -import time |
839 | -from twisted.internet import defer |
840 | - |
841 | -from nova import exception |
842 | -from nova import flags |
843 | -from nova import test |
844 | -from nova import utils |
845 | -from nova.compute import model |
846 | -from nova.compute import node |
847 | - |
848 | - |
849 | -FLAGS = flags.FLAGS |
850 | - |
851 | - |
852 | -class ModelTestCase(test.TrialTestCase): |
853 | - def setUp(self): |
854 | - super(ModelTestCase, self).setUp() |
855 | - self.flags(fake_libvirt=True, |
856 | - fake_storage=True, |
857 | - fake_users=True) |
858 | - |
859 | - def tearDown(self): |
860 | - model.Instance('i-test').destroy() |
861 | - model.Host('testhost').destroy() |
862 | - model.Daemon('testhost', 'nova-testdaemon').destroy() |
863 | - |
864 | - def create_instance(self): |
865 | - inst = model.Instance('i-test') |
866 | - inst['reservation_id'] = 'r-test' |
867 | - inst['launch_time'] = '10' |
868 | - inst['user_id'] = 'fake' |
869 | - inst['project_id'] = 'fake' |
870 | - inst['instance_type'] = 'm1.tiny' |
871 | - inst['node_name'] = FLAGS.node_name |
872 | - inst['mac_address'] = utils.generate_mac() |
873 | - inst['ami_launch_index'] = 0 |
874 | - inst.save() |
875 | - return inst |
876 | - |
877 | - def create_host(self): |
878 | - host = model.Host('testhost') |
879 | - host.save() |
880 | - return host |
881 | - |
882 | - def create_daemon(self): |
883 | - daemon = model.Daemon('testhost', 'nova-testdaemon') |
884 | - daemon.save() |
885 | - return daemon |
886 | - |
887 | - @defer.inlineCallbacks |
888 | - def test_create_instance(self): |
889 | - """store with create_instace, then test that a load finds it""" |
890 | - instance = yield self.create_instance() |
891 | - old = yield model.Instance(instance.identifier) |
892 | - self.assertFalse(old.is_new_record()) |
893 | - |
894 | - @defer.inlineCallbacks |
895 | - def test_delete_instance(self): |
896 | - """create, then destroy, then make sure loads a new record""" |
897 | - instance = yield self.create_instance() |
898 | - yield instance.destroy() |
899 | - newinst = yield model.Instance('i-test') |
900 | - self.assertTrue(newinst.is_new_record()) |
901 | - |
902 | - @defer.inlineCallbacks |
903 | - def test_instance_added_to_set(self): |
904 | - """create, then check that it is listed for the project""" |
905 | - instance = yield self.create_instance() |
906 | - found = False |
907 | - for x in model.InstanceDirectory().all: |
908 | - if x.identifier == 'i-test': |
909 | - found = True |
910 | - self.assert_(found) |
911 | - |
912 | - @defer.inlineCallbacks |
913 | - def test_instance_associates_project(self): |
914 | - """create, then check that it is listed for the project""" |
915 | - instance = yield self.create_instance() |
916 | - found = False |
917 | - for x in model.InstanceDirectory().by_project(instance.project): |
918 | - if x.identifier == 'i-test': |
919 | - found = True |
920 | - self.assert_(found) |
921 | - |
922 | - @defer.inlineCallbacks |
923 | - def test_host_class_finds_hosts(self): |
924 | - host = yield self.create_host() |
925 | - self.assertEqual('testhost', model.Host.lookup('testhost').identifier) |
926 | - |
927 | - @defer.inlineCallbacks |
928 | - def test_host_class_doesnt_find_missing_hosts(self): |
929 | - rv = yield model.Host.lookup('woahnelly') |
930 | - self.assertEqual(None, rv) |
931 | - |
932 | - @defer.inlineCallbacks |
933 | - def test_create_host(self): |
934 | - """store with create_host, then test that a load finds it""" |
935 | - host = yield self.create_host() |
936 | - old = yield model.Host(host.identifier) |
937 | - self.assertFalse(old.is_new_record()) |
938 | - |
939 | - @defer.inlineCallbacks |
940 | - def test_delete_host(self): |
941 | - """create, then destroy, then make sure loads a new record""" |
942 | - instance = yield self.create_host() |
943 | - yield instance.destroy() |
944 | - newinst = yield model.Host('testhost') |
945 | - self.assertTrue(newinst.is_new_record()) |
946 | - |
947 | - @defer.inlineCallbacks |
948 | - def test_host_added_to_set(self): |
949 | - """create, then check that it is included in list""" |
950 | - instance = yield self.create_host() |
951 | - found = False |
952 | - for x in model.Host.all(): |
953 | - if x.identifier == 'testhost': |
954 | - found = True |
955 | - self.assert_(found) |
956 | - |
957 | - @defer.inlineCallbacks |
958 | - def test_create_daemon_two_args(self): |
959 | - """create a daemon with two arguments""" |
960 | - d = yield self.create_daemon() |
961 | - d = model.Daemon('testhost', 'nova-testdaemon') |
962 | - self.assertFalse(d.is_new_record()) |
963 | - |
964 | - @defer.inlineCallbacks |
965 | - def test_create_daemon_single_arg(self): |
966 | - """Create a daemon using the combined host:bin format""" |
967 | - d = yield model.Daemon("testhost:nova-testdaemon") |
968 | - d.save() |
969 | - d = model.Daemon('testhost:nova-testdaemon') |
970 | - self.assertFalse(d.is_new_record()) |
971 | - |
972 | - @defer.inlineCallbacks |
973 | - def test_equality_of_daemon_single_and_double_args(self): |
974 | - """Create a daemon using the combined host:bin arg, find with 2""" |
975 | - d = yield model.Daemon("testhost:nova-testdaemon") |
976 | - d.save() |
977 | - d = model.Daemon('testhost', 'nova-testdaemon') |
978 | - self.assertFalse(d.is_new_record()) |
979 | - |
980 | - @defer.inlineCallbacks |
981 | - def test_equality_daemon_of_double_and_single_args(self): |
982 | - """Create a daemon using the combined host:bin arg, find with 2""" |
983 | - d = yield self.create_daemon() |
984 | - d = model.Daemon('testhost:nova-testdaemon') |
985 | - self.assertFalse(d.is_new_record()) |
986 | - |
987 | - @defer.inlineCallbacks |
988 | - def test_delete_daemon(self): |
989 | - """create, then destroy, then make sure loads a new record""" |
990 | - instance = yield self.create_daemon() |
991 | - yield instance.destroy() |
992 | - newinst = yield model.Daemon('testhost', 'nova-testdaemon') |
993 | - self.assertTrue(newinst.is_new_record()) |
994 | - |
995 | - @defer.inlineCallbacks |
996 | - def test_daemon_heartbeat(self): |
997 | - """Create a daemon, sleep, heartbeat, check for update""" |
998 | - d = yield self.create_daemon() |
999 | - ts = d['updated_at'] |
1000 | - time.sleep(2) |
1001 | - d.heartbeat() |
1002 | - d2 = model.Daemon('testhost', 'nova-testdaemon') |
1003 | - ts2 = d2['updated_at'] |
1004 | - self.assert_(ts2 > ts) |
1005 | - |
1006 | - @defer.inlineCallbacks |
1007 | - def test_daemon_added_to_set(self): |
1008 | - """create, then check that it is included in list""" |
1009 | - instance = yield self.create_daemon() |
1010 | - found = False |
1011 | - for x in model.Daemon.all(): |
1012 | - if x.identifier == 'testhost:nova-testdaemon': |
1013 | - found = True |
1014 | - self.assert_(found) |
1015 | - |
1016 | - @defer.inlineCallbacks |
1017 | - def test_daemon_associates_host(self): |
1018 | - """create, then check that it is listed for the host""" |
1019 | - instance = yield self.create_daemon() |
1020 | - found = False |
1021 | - for x in model.Daemon.by_host('testhost'): |
1022 | - if x.identifier == 'testhost:nova-testdaemon': |
1023 | - found = True |
1024 | - self.assertTrue(found) |
1025 | |
1026 | === removed file 'nova/tests/network_unittest.py' |
1027 | --- nova/tests/network_unittest.py 2010-07-21 02:57:31 +0000 |
1028 | +++ nova/tests/network_unittest.py 1970-01-01 00:00:00 +0000 |
1029 | @@ -1,219 +0,0 @@ |
1030 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1031 | - |
1032 | -# Copyright 2010 United States Government as represented by the |
1033 | -# Administrator of the National Aeronautics and Space Administration. |
1034 | -# All Rights Reserved. |
1035 | -# |
1036 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
1037 | -# not use this file except in compliance with the License. You may obtain |
1038 | -# a copy of the License at |
1039 | -# |
1040 | -# http://www.apache.org/licenses/LICENSE-2.0 |
1041 | -# |
1042 | -# Unless required by applicable law or agreed to in writing, software |
1043 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
1044 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
1045 | -# License for the specific language governing permissions and limitations |
1046 | -# under the License. |
1047 | - |
1048 | -import IPy |
1049 | -import os |
1050 | -import logging |
1051 | - |
1052 | -from nova import flags |
1053 | -from nova import test |
1054 | -from nova import utils |
1055 | -from nova.auth import users |
1056 | -from nova.compute import network |
1057 | -from nova.compute.exception import NoMoreAddresses |
1058 | - |
1059 | -FLAGS = flags.FLAGS |
1060 | - |
1061 | -class NetworkTestCase(test.TrialTestCase): |
1062 | - def setUp(self): |
1063 | - super(NetworkTestCase, self).setUp() |
1064 | - self.flags(fake_libvirt=True, |
1065 | - fake_storage=True, |
1066 | - fake_network=True, |
1067 | - network_size=32) |
1068 | - logging.getLogger().setLevel(logging.DEBUG) |
1069 | - self.manager = users.UserManager.instance() |
1070 | - self.dnsmasq = FakeDNSMasq() |
1071 | - try: |
1072 | - self.manager.create_user('netuser', 'netuser', 'netuser') |
1073 | - except: pass |
1074 | - for i in range(0, 6): |
1075 | - name = 'project%s' % i |
1076 | - if not self.manager.get_project(name): |
1077 | - self.manager.create_project(name, 'netuser', name) |
1078 | - self.network = network.PublicNetworkController() |
1079 | - |
1080 | - def tearDown(self): |
1081 | - super(NetworkTestCase, self).tearDown() |
1082 | - for i in range(0, 6): |
1083 | - name = 'project%s' % i |
1084 | - self.manager.delete_project(name) |
1085 | - self.manager.delete_user('netuser') |
1086 | - |
1087 | - def test_public_network_allocation(self): |
1088 | - pubnet = IPy.IP(flags.FLAGS.public_range) |
1089 | - address = self.network.allocate_ip("netuser", "project0", "public") |
1090 | - self.assertTrue(IPy.IP(address) in pubnet) |
1091 | - self.assertTrue(IPy.IP(address) in self.network.network) |
1092 | - |
1093 | - def test_allocate_deallocate_ip(self): |
1094 | - address = network.allocate_ip( |
1095 | - "netuser", "project0", utils.generate_mac()) |
1096 | - logging.debug("Was allocated %s" % (address)) |
1097 | - net = network.get_project_network("project0", "default") |
1098 | - self.assertEqual(True, is_in_project(address, "project0")) |
1099 | - mac = utils.generate_mac() |
1100 | - hostname = "test-host" |
1101 | - self.dnsmasq.issue_ip(mac, address, hostname, net.bridge_name) |
1102 | - rv = network.deallocate_ip(address) |
1103 | - |
1104 | - # Doesn't go away until it's dhcp released |
1105 | - self.assertEqual(True, is_in_project(address, "project0")) |
1106 | - |
1107 | - self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name) |
1108 | - self.assertEqual(False, is_in_project(address, "project0")) |
1109 | - |
1110 | - def test_range_allocation(self): |
1111 | - mac = utils.generate_mac() |
1112 | - secondmac = utils.generate_mac() |
1113 | - hostname = "test-host" |
1114 | - address = network.allocate_ip( |
1115 | - "netuser", "project0", mac) |
1116 | - secondaddress = network.allocate_ip( |
1117 | - "netuser", "project1", secondmac) |
1118 | - net = network.get_project_network("project0", "default") |
1119 | - secondnet = network.get_project_network("project1", "default") |
1120 | - |
1121 | - self.assertEqual(True, is_in_project(address, "project0")) |
1122 | - self.assertEqual(True, is_in_project(secondaddress, "project1")) |
1123 | - self.assertEqual(False, is_in_project(address, "project1")) |
1124 | - |
1125 | - # Addresses are allocated before they're issued |
1126 | - self.dnsmasq.issue_ip(mac, address, hostname, net.bridge_name) |
1127 | - self.dnsmasq.issue_ip(secondmac, secondaddress, |
1128 | - hostname, secondnet.bridge_name) |
1129 | - |
1130 | - rv = network.deallocate_ip(address) |
1131 | - self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name) |
1132 | - self.assertEqual(False, is_in_project(address, "project0")) |
1133 | - |
1134 | - # First address release shouldn't affect the second |
1135 | - self.assertEqual(True, is_in_project(secondaddress, "project1")) |
1136 | - |
1137 | - rv = network.deallocate_ip(secondaddress) |
1138 | - self.dnsmasq.release_ip(secondmac, secondaddress, |
1139 | - hostname, secondnet.bridge_name) |
1140 | - self.assertEqual(False, is_in_project(secondaddress, "project1")) |
1141 | - |
1142 | - def test_subnet_edge(self): |
1143 | - secondaddress = network.allocate_ip("netuser", "project0", |
1144 | - utils.generate_mac()) |
1145 | - hostname = "toomany-hosts" |
1146 | - for project in range(1,5): |
1147 | - project_id = "project%s" % (project) |
1148 | - mac = utils.generate_mac() |
1149 | - mac2 = utils.generate_mac() |
1150 | - mac3 = utils.generate_mac() |
1151 | - address = network.allocate_ip( |
1152 | - "netuser", project_id, mac) |
1153 | - address2 = network.allocate_ip( |
1154 | - "netuser", project_id, mac2) |
1155 | - address3 = network.allocate_ip( |
1156 | - "netuser", project_id, mac3) |
1157 | - self.assertEqual(False, is_in_project(address, "project0")) |
1158 | - self.assertEqual(False, is_in_project(address2, "project0")) |
1159 | - self.assertEqual(False, is_in_project(address3, "project0")) |
1160 | - rv = network.deallocate_ip(address) |
1161 | - rv = network.deallocate_ip(address2) |
1162 | - rv = network.deallocate_ip(address3) |
1163 | - net = network.get_project_network(project_id, "default") |
1164 | - self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name) |
1165 | - self.dnsmasq.release_ip(mac2, address2, hostname, net.bridge_name) |
1166 | - self.dnsmasq.release_ip(mac3, address3, hostname, net.bridge_name) |
1167 | - net = network.get_project_network("project0", "default") |
1168 | - rv = network.deallocate_ip(secondaddress) |
1169 | - self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name) |
1170 | - |
1171 | - def test_release_before_deallocate(self): |
1172 | - pass |
1173 | - |
1174 | - def test_deallocate_before_issued(self): |
1175 | - pass |
1176 | - |
1177 | - def test_too_many_addresses(self): |
1178 | - """ |
1179 | - Here, we test that a proper NoMoreAddresses exception is raised. |
1180 | - |
1181 | - However, the number of available IP addresses depends on the test |
1182 | - environment's setup. |
1183 | - |
1184 | - Network size is set in test fixture's setUp method. |
1185 | - |
1186 | - There are FLAGS.cnt_vpn_clients addresses reserved for VPN (NUM_RESERVED_VPN_IPS) |
1187 | - |
1188 | - And there are NUM_STATIC_IPS that are always reserved by Nova for the necessary |
1189 | - services (gateway, CloudPipe, etc) |
1190 | - |
1191 | - So we should get flags.network_size - (NUM_STATIC_IPS + |
1192 | - NUM_PREALLOCATED_IPS + |
1193 | - NUM_RESERVED_VPN_IPS) |
1194 | - usable addresses |
1195 | - """ |
1196 | - net = network.get_project_network("project0", "default") |
1197 | - |
1198 | - # Determine expected number of available IP addresses |
1199 | - num_static_ips = net.num_static_ips |
1200 | - num_preallocated_ips = len(net.hosts.keys()) |
1201 | - num_reserved_vpn_ips = flags.FLAGS.cnt_vpn_clients |
1202 | - num_available_ips = flags.FLAGS.network_size - (num_static_ips + num_preallocated_ips + num_reserved_vpn_ips) |
1203 | - |
1204 | - hostname = "toomany-hosts" |
1205 | - macs = {} |
1206 | - addresses = {} |
1207 | - for i in range(0, (num_available_ips - 1)): |
1208 | - macs[i] = utils.generate_mac() |
1209 | - addresses[i] = network.allocate_ip("netuser", "project0", macs[i]) |
1210 | - self.dnsmasq.issue_ip(macs[i], addresses[i], hostname, net.bridge_name) |
1211 | - |
1212 | - self.assertRaises(NoMoreAddresses, network.allocate_ip, "netuser", "project0", utils.generate_mac()) |
1213 | - |
1214 | - for i in range(0, (num_available_ips - 1)): |
1215 | - rv = network.deallocate_ip(addresses[i]) |
1216 | - self.dnsmasq.release_ip(macs[i], addresses[i], hostname, net.bridge_name) |
1217 | - |
1218 | -def is_in_project(address, project_id): |
1219 | - return address in network.get_project_network(project_id).list_addresses() |
1220 | - |
1221 | -def _get_project_addresses(project_id): |
1222 | - project_addresses = [] |
1223 | - for addr in network.get_project_network(project_id).list_addresses(): |
1224 | - project_addresses.append(addr) |
1225 | - return project_addresses |
1226 | - |
1227 | -def binpath(script): |
1228 | - return os.path.abspath(os.path.join(__file__, "../../../bin", script)) |
1229 | - |
1230 | -class FakeDNSMasq(object): |
1231 | - def issue_ip(self, mac, ip, hostname, interface): |
1232 | - cmd = "%s add %s %s %s" % (binpath('nova-dhcpbridge'), |
1233 | - mac, ip, hostname) |
1234 | - env = {'DNSMASQ_INTERFACE': interface, |
1235 | - 'TESTING' : '1', |
1236 | - 'FLAGFILE' : FLAGS.dhcpbridge_flagfile} |
1237 | - (out, err) = utils.execute(cmd, addl_env=env) |
1238 | - logging.debug("ISSUE_IP: %s, %s " % (out, err)) |
1239 | - |
1240 | - def release_ip(self, mac, ip, hostname, interface): |
1241 | - cmd = "%s del %s %s %s" % (binpath('nova-dhcpbridge'), |
1242 | - mac, ip, hostname) |
1243 | - env = {'DNSMASQ_INTERFACE': interface, |
1244 | - 'TESTING' : '1', |
1245 | - 'FLAGFILE' : FLAGS.dhcpbridge_flagfile} |
1246 | - (out, err) = utils.execute(cmd, addl_env=env) |
1247 | - logging.debug("RELEASE_IP: %s, %s " % (out, err)) |
1248 | - |
1249 | |
1250 | === removed file 'nova/tests/node_unittest.py' |
1251 | --- nova/tests/node_unittest.py 2010-07-15 23:13:48 +0000 |
1252 | +++ nova/tests/node_unittest.py 1970-01-01 00:00:00 +0000 |
1253 | @@ -1,128 +0,0 @@ |
1254 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1255 | - |
1256 | -# Copyright 2010 United States Government as represented by the |
1257 | -# Administrator of the National Aeronautics and Space Administration. |
1258 | -# All Rights Reserved. |
1259 | -# |
1260 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
1261 | -# not use this file except in compliance with the License. You may obtain |
1262 | -# a copy of the License at |
1263 | -# |
1264 | -# http://www.apache.org/licenses/LICENSE-2.0 |
1265 | -# |
1266 | -# Unless required by applicable law or agreed to in writing, software |
1267 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
1268 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
1269 | -# License for the specific language governing permissions and limitations |
1270 | -# under the License. |
1271 | - |
1272 | -import logging |
1273 | -import time |
1274 | -from twisted.internet import defer |
1275 | -from xml.etree import ElementTree |
1276 | - |
1277 | -from nova import exception |
1278 | -from nova import flags |
1279 | -from nova import test |
1280 | -from nova import utils |
1281 | -from nova.compute import model |
1282 | -from nova.compute import node |
1283 | - |
1284 | - |
1285 | -FLAGS = flags.FLAGS |
1286 | - |
1287 | - |
1288 | -class InstanceXmlTestCase(test.TrialTestCase): |
1289 | - # @defer.inlineCallbacks |
1290 | - def test_serialization(self): |
1291 | - # TODO: Reimplement this, it doesn't make sense in redis-land |
1292 | - return |
1293 | - |
1294 | - # instance_id = 'foo' |
1295 | - # first_node = node.Node() |
1296 | - # inst = yield first_node.run_instance(instance_id) |
1297 | - # |
1298 | - # # force the state so that we can verify that it changes |
1299 | - # inst._s['state'] = node.Instance.NOSTATE |
1300 | - # xml = inst.toXml() |
1301 | - # self.assert_(ElementTree.parse(StringIO.StringIO(xml))) |
1302 | - # |
1303 | - # second_node = node.Node() |
1304 | - # new_inst = node.Instance.fromXml(second_node._conn, pool=second_node._pool, xml=xml) |
1305 | - # self.assertEqual(new_inst.state, node.Instance.RUNNING) |
1306 | - # rv = yield first_node.terminate_instance(instance_id) |
1307 | - |
1308 | - |
1309 | -class NodeConnectionTestCase(test.TrialTestCase): |
1310 | - def setUp(self): |
1311 | - logging.getLogger().setLevel(logging.DEBUG) |
1312 | - super(NodeConnectionTestCase, self).setUp() |
1313 | - self.flags(fake_libvirt=True, |
1314 | - fake_storage=True, |
1315 | - fake_users=True) |
1316 | - self.node = node.Node() |
1317 | - |
1318 | - def create_instance(self): |
1319 | - instdir = model.InstanceDirectory() |
1320 | - inst = instdir.new() |
1321 | - # TODO(ja): add ami, ari, aki, user_data |
1322 | - inst['reservation_id'] = 'r-fakeres' |
1323 | - inst['launch_time'] = '10' |
1324 | - inst['user_id'] = 'fake' |
1325 | - inst['project_id'] = 'fake' |
1326 | - inst['instance_type'] = 'm1.tiny' |
1327 | - inst['node_name'] = FLAGS.node_name |
1328 | - inst['mac_address'] = utils.generate_mac() |
1329 | - inst['ami_launch_index'] = 0 |
1330 | - inst.save() |
1331 | - return inst['instance_id'] |
1332 | - |
1333 | - @defer.inlineCallbacks |
1334 | - def test_run_describe_terminate(self): |
1335 | - instance_id = self.create_instance() |
1336 | - |
1337 | - rv = yield self.node.run_instance(instance_id) |
1338 | - |
1339 | - rv = yield self.node.describe_instances() |
1340 | - logging.info("Running instances: %s", rv) |
1341 | - self.assertEqual(rv[instance_id].name, instance_id) |
1342 | - |
1343 | - rv = yield self.node.terminate_instance(instance_id) |
1344 | - |
1345 | - rv = yield self.node.describe_instances() |
1346 | - logging.info("After terminating instances: %s", rv) |
1347 | - self.assertEqual(rv, {}) |
1348 | - |
1349 | - @defer.inlineCallbacks |
1350 | - def test_reboot(self): |
1351 | - instance_id = self.create_instance() |
1352 | - rv = yield self.node.run_instance(instance_id) |
1353 | - |
1354 | - rv = yield self.node.describe_instances() |
1355 | - self.assertEqual(rv[instance_id].name, instance_id) |
1356 | - |
1357 | - yield self.node.reboot_instance(instance_id) |
1358 | - |
1359 | - rv = yield self.node.describe_instances() |
1360 | - self.assertEqual(rv[instance_id].name, instance_id) |
1361 | - rv = yield self.node.terminate_instance(instance_id) |
1362 | - |
1363 | - @defer.inlineCallbacks |
1364 | - def test_console_output(self): |
1365 | - instance_id = self.create_instance() |
1366 | - rv = yield self.node.run_instance(instance_id) |
1367 | - |
1368 | - console = yield self.node.get_console_output(instance_id) |
1369 | - self.assert_(console) |
1370 | - rv = yield self.node.terminate_instance(instance_id) |
1371 | - |
1372 | - @defer.inlineCallbacks |
1373 | - def test_run_instance_existing(self): |
1374 | - instance_id = self.create_instance() |
1375 | - rv = yield self.node.run_instance(instance_id) |
1376 | - |
1377 | - rv = yield self.node.describe_instances() |
1378 | - self.assertEqual(rv[instance_id].name, instance_id) |
1379 | - |
1380 | - self.assertRaises(exception.Error, self.node.run_instance, instance_id) |
1381 | - rv = yield self.node.terminate_instance(instance_id) |
1382 | |
1383 | === removed file 'nova/tests/objectstore_unittest.py' |
1384 | --- nova/tests/objectstore_unittest.py 2010-07-15 23:13:48 +0000 |
1385 | +++ nova/tests/objectstore_unittest.py 1970-01-01 00:00:00 +0000 |
1386 | @@ -1,203 +0,0 @@ |
1387 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1388 | - |
1389 | -# Copyright 2010 United States Government as represented by the |
1390 | -# Administrator of the National Aeronautics and Space Administration. |
1391 | -# All Rights Reserved. |
1392 | -# |
1393 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
1394 | -# not use this file except in compliance with the License. You may obtain |
1395 | -# a copy of the License at |
1396 | -# |
1397 | -# http://www.apache.org/licenses/LICENSE-2.0 |
1398 | -# |
1399 | -# Unless required by applicable law or agreed to in writing, software |
1400 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
1401 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
1402 | -# License for the specific language governing permissions and limitations |
1403 | -# under the License. |
1404 | - |
1405 | -import glob |
1406 | -import hashlib |
1407 | -import logging |
1408 | -import os |
1409 | -import shutil |
1410 | -import tempfile |
1411 | - |
1412 | -from nova import flags |
1413 | -from nova import objectstore |
1414 | -from nova import test |
1415 | -from nova.auth import users |
1416 | - |
1417 | - |
1418 | -FLAGS = flags.FLAGS |
1419 | - |
1420 | -oss_tempdir = tempfile.mkdtemp(prefix='test_oss-') |
1421 | - |
1422 | - |
1423 | -# delete tempdirs from previous runs (we don't delete after test to allow |
1424 | -# checking the contents after running tests) |
1425 | -# TODO: This fails on the test box with a permission denied error |
1426 | -# Also, doing these things in a global tempdir means that different runs of |
1427 | -# the test suite on the same box could clobber each other. |
1428 | -#for path in glob.glob(os.path.abspath(os.path.join(oss_tempdir, '../test_oss-*'))): |
1429 | -# if path != oss_tempdir: |
1430 | -# shutil.rmtree(path) |
1431 | - |
1432 | - |
1433 | -# create bucket/images path |
1434 | -os.makedirs(os.path.join(oss_tempdir, 'images')) |
1435 | -os.makedirs(os.path.join(oss_tempdir, 'buckets')) |
1436 | - |
1437 | -class ObjectStoreTestCase(test.BaseTestCase): |
1438 | - def setUp(self): |
1439 | - super(ObjectStoreTestCase, self).setUp() |
1440 | - self.flags(fake_users=True, |
1441 | - buckets_path=os.path.join(oss_tempdir, 'buckets'), |
1442 | - images_path=os.path.join(oss_tempdir, 'images'), |
1443 | - ca_path=os.path.join(os.path.dirname(__file__), 'CA')) |
1444 | - logging.getLogger().setLevel(logging.DEBUG) |
1445 | - |
1446 | - self.um = users.UserManager.instance() |
1447 | - try: |
1448 | - self.um.create_user('user1') |
1449 | - except: pass |
1450 | - try: |
1451 | - self.um.create_user('user2') |
1452 | - except: pass |
1453 | - try: |
1454 | - self.um.create_user('admin_user', admin=True) |
1455 | - except: pass |
1456 | - try: |
1457 | - self.um.create_project('proj1', 'user1', 'a proj', ['user1']) |
1458 | - except: pass |
1459 | - try: |
1460 | - self.um.create_project('proj2', 'user2', 'a proj', ['user2']) |
1461 | - except: pass |
1462 | - class Context(object): pass |
1463 | - self.context = Context() |
1464 | - |
1465 | - def tearDown(self): |
1466 | - self.um.delete_project('proj1') |
1467 | - self.um.delete_project('proj2') |
1468 | - self.um.delete_user('user1') |
1469 | - self.um.delete_user('user2') |
1470 | - self.um.delete_user('admin_user') |
1471 | - super(ObjectStoreTestCase, self).tearDown() |
1472 | - |
1473 | - def test_buckets(self): |
1474 | - self.context.user = self.um.get_user('user1') |
1475 | - self.context.project = self.um.get_project('proj1') |
1476 | - objectstore.bucket.Bucket.create('new_bucket', self.context) |
1477 | - bucket = objectstore.bucket.Bucket('new_bucket') |
1478 | - |
1479 | - # creator is authorized to use bucket |
1480 | - self.assert_(bucket.is_authorized(self.context)) |
1481 | - |
1482 | - # another user is not authorized |
1483 | - self.context.user = self.um.get_user('user2') |
1484 | - self.context.project = self.um.get_project('proj2') |
1485 | - self.assert_(bucket.is_authorized(self.context) == False) |
1486 | - |
1487 | - # admin is authorized to use bucket |
1488 | - self.context.user = self.um.get_user('admin_user') |
1489 | - self.context.project = None |
1490 | - self.assert_(bucket.is_authorized(self.context)) |
1491 | - |
1492 | - # new buckets are empty |
1493 | - self.assert_(bucket.list_keys()['Contents'] == []) |
1494 | - |
1495 | - # storing keys works |
1496 | - bucket['foo'] = "bar" |
1497 | - |
1498 | - self.assert_(len(bucket.list_keys()['Contents']) == 1) |
1499 | - |
1500 | - self.assert_(bucket['foo'].read() == 'bar') |
1501 | - |
1502 | - # md5 of key works |
1503 | - self.assert_(bucket['foo'].md5 == hashlib.md5('bar').hexdigest()) |
1504 | - |
1505 | - # deleting non-empty bucket throws exception |
1506 | - exception = False |
1507 | - try: |
1508 | - bucket.delete() |
1509 | - except: |
1510 | - exception = True |
1511 | - |
1512 | - self.assert_(exception) |
1513 | - |
1514 | - # deleting key |
1515 | - del bucket['foo'] |
1516 | - |
1517 | - # deleting empty button |
1518 | - bucket.delete() |
1519 | - |
1520 | - # accessing deleted bucket throws exception |
1521 | - exception = False |
1522 | - try: |
1523 | - objectstore.bucket.Bucket('new_bucket') |
1524 | - except: |
1525 | - exception = True |
1526 | - |
1527 | - self.assert_(exception) |
1528 | - |
1529 | - def test_images(self): |
1530 | - self.context.user = self.um.get_user('user1') |
1531 | - self.context.project = self.um.get_project('proj1') |
1532 | - |
1533 | - # create a bucket for our bundle |
1534 | - objectstore.bucket.Bucket.create('image_bucket', self.context) |
1535 | - bucket = objectstore.bucket.Bucket('image_bucket') |
1536 | - |
1537 | - # upload an image manifest/parts |
1538 | - bundle_path = os.path.join(os.path.dirname(__file__), 'bundle') |
1539 | - for path in glob.glob(bundle_path + '/*'): |
1540 | - bucket[os.path.basename(path)] = open(path, 'rb').read() |
1541 | - |
1542 | - # register an image |
1543 | - objectstore.image.Image.register_aws_image('i-testing', 'image_bucket/1mb.manifest.xml', self.context) |
1544 | - |
1545 | - # verify image |
1546 | - my_img = objectstore.image.Image('i-testing') |
1547 | - result_image_file = os.path.join(my_img.path, 'image') |
1548 | - self.assertEqual(os.stat(result_image_file).st_size, 1048576) |
1549 | - |
1550 | - sha = hashlib.sha1(open(result_image_file).read()).hexdigest() |
1551 | - self.assertEqual(sha, '3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3') |
1552 | - |
1553 | - # verify image permissions |
1554 | - self.context.user = self.um.get_user('user2') |
1555 | - self.context.project = self.um.get_project('proj2') |
1556 | - self.assert_(my_img.is_authorized(self.context) == False) |
1557 | - |
1558 | -# class ApiObjectStoreTestCase(test.BaseTestCase): |
1559 | -# def setUp(self): |
1560 | -# super(ApiObjectStoreTestCase, self).setUp() |
1561 | -# FLAGS.fake_users = True |
1562 | -# FLAGS.buckets_path = os.path.join(tempdir, 'buckets') |
1563 | -# FLAGS.images_path = os.path.join(tempdir, 'images') |
1564 | -# FLAGS.ca_path = os.path.join(os.path.dirname(__file__), 'CA') |
1565 | -# |
1566 | -# self.users = users.UserManager.instance() |
1567 | -# self.app = handler.Application(self.users) |
1568 | -# |
1569 | -# self.host = '127.0.0.1' |
1570 | -# |
1571 | -# self.conn = boto.s3.connection.S3Connection( |
1572 | -# aws_access_key_id=user.access, |
1573 | -# aws_secret_access_key=user.secret, |
1574 | -# is_secure=False, |
1575 | -# calling_format=boto.s3.connection.OrdinaryCallingFormat(), |
1576 | -# port=FLAGS.s3_port, |
1577 | -# host=FLAGS.s3_host) |
1578 | -# |
1579 | -# self.mox.StubOutWithMock(self.ec2, 'new_http_connection') |
1580 | -# |
1581 | -# def tearDown(self): |
1582 | -# FLAGS.Reset() |
1583 | -# super(ApiObjectStoreTestCase, self).tearDown() |
1584 | -# |
1585 | -# def test_describe_instances(self): |
1586 | -# self.expect_http() |
1587 | -# self.mox.ReplayAll() |
1588 | -# |
1589 | -# self.assertEqual(self.ec2.get_all_instances(), []) |
1590 | |
1591 | === removed file 'nova/tests/process_unittest.py' |
1592 | --- nova/tests/process_unittest.py 2010-07-16 19:12:36 +0000 |
1593 | +++ nova/tests/process_unittest.py 1970-01-01 00:00:00 +0000 |
1594 | @@ -1,122 +0,0 @@ |
1595 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1596 | - |
1597 | -# Copyright 2010 United States Government as represented by the |
1598 | -# Administrator of the National Aeronautics and Space Administration. |
1599 | -# All Rights Reserved. |
1600 | -# |
1601 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
1602 | -# not use this file except in compliance with the License. You may obtain |
1603 | -# a copy of the License at |
1604 | -# |
1605 | -# http://www.apache.org/licenses/LICENSE-2.0 |
1606 | -# |
1607 | -# Unless required by applicable law or agreed to in writing, software |
1608 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
1609 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
1610 | -# License for the specific language governing permissions and limitations |
1611 | -# under the License. |
1612 | - |
1613 | -import logging |
1614 | -from twisted.internet import defer |
1615 | -from twisted.internet import reactor |
1616 | -from xml.etree import ElementTree |
1617 | - |
1618 | -from nova import exception |
1619 | -from nova import flags |
1620 | -from nova import process |
1621 | -from nova import test |
1622 | -from nova import utils |
1623 | - |
1624 | -FLAGS = flags.FLAGS |
1625 | - |
1626 | - |
1627 | -class ProcessTestCase(test.TrialTestCase): |
1628 | - def setUp(self): |
1629 | - logging.getLogger().setLevel(logging.DEBUG) |
1630 | - super(ProcessTestCase, self).setUp() |
1631 | - |
1632 | - def test_execute_stdout(self): |
1633 | - pool = process.ProcessPool(2) |
1634 | - d = pool.simple_execute('echo test') |
1635 | - def _check(rv): |
1636 | - self.assertEqual(rv[0], 'test\n') |
1637 | - self.assertEqual(rv[1], '') |
1638 | - |
1639 | - d.addCallback(_check) |
1640 | - d.addErrback(self.fail) |
1641 | - return d |
1642 | - |
1643 | - def test_execute_stderr(self): |
1644 | - pool = process.ProcessPool(2) |
1645 | - d = pool.simple_execute('cat BAD_FILE', error_ok=1) |
1646 | - def _check(rv): |
1647 | - self.assertEqual(rv[0], '') |
1648 | - self.assert_('No such file' in rv[1]) |
1649 | - |
1650 | - d.addCallback(_check) |
1651 | - d.addErrback(self.fail) |
1652 | - return d |
1653 | - |
1654 | - def test_execute_unexpected_stderr(self): |
1655 | - pool = process.ProcessPool(2) |
1656 | - d = pool.simple_execute('cat BAD_FILE') |
1657 | - d.addCallback(lambda x: self.fail('should have raised an error')) |
1658 | - d.addErrback(lambda failure: failure.trap(IOError)) |
1659 | - return d |
1660 | - |
1661 | - def test_max_processes(self): |
1662 | - pool = process.ProcessPool(2) |
1663 | - d1 = pool.simple_execute('sleep 0.01') |
1664 | - d2 = pool.simple_execute('sleep 0.01') |
1665 | - d3 = pool.simple_execute('sleep 0.005') |
1666 | - d4 = pool.simple_execute('sleep 0.005') |
1667 | - |
1668 | - called = [] |
1669 | - def _called(rv, name): |
1670 | - called.append(name) |
1671 | - |
1672 | - d1.addCallback(_called, 'd1') |
1673 | - d2.addCallback(_called, 'd2') |
1674 | - d3.addCallback(_called, 'd3') |
1675 | - d4.addCallback(_called, 'd4') |
1676 | - |
1677 | - # Make sure that d3 and d4 had to wait on the other two and were called |
1678 | - # in order |
1679 | - # NOTE(termie): there may be a race condition in this test if for some |
1680 | - # reason one of the sleeps takes longer to complete |
1681 | - # than it should |
1682 | - d4.addCallback(lambda x: self.assertEqual(called[2], 'd3')) |
1683 | - d4.addCallback(lambda x: self.assertEqual(called[3], 'd4')) |
1684 | - d4.addErrback(self.fail) |
1685 | - return d4 |
1686 | - |
1687 | - def test_kill_long_process(self): |
1688 | - pool = process.ProcessPool(2) |
1689 | - |
1690 | - d1 = pool.simple_execute('sleep 1') |
1691 | - d2 = pool.simple_execute('sleep 0.005') |
1692 | - |
1693 | - timeout = reactor.callLater(0.1, self.fail, 'should have been killed') |
1694 | - |
1695 | - # kill d1 and wait on it to end then cancel the timeout |
1696 | - d2.addCallback(lambda _: d1.process.signalProcess('KILL')) |
1697 | - d2.addCallback(lambda _: d1) |
1698 | - d2.addBoth(lambda _: timeout.active() and timeout.cancel()) |
1699 | - d2.addErrback(self.fail) |
1700 | - return d2 |
1701 | - |
1702 | - def test_process_exit_is_contained(self): |
1703 | - pool = process.ProcessPool(2) |
1704 | - |
1705 | - d1 = pool.simple_execute('sleep 1') |
1706 | - d1.addCallback(lambda x: self.fail('should have errbacked')) |
1707 | - d1.addErrback(lambda fail: fail.trap(IOError)) |
1708 | - reactor.callLater(0.05, d1.process.signalProcess, 'KILL') |
1709 | - |
1710 | - return d1 |
1711 | - |
1712 | - def test_shared_pool_is_singleton(self): |
1713 | - pool1 = process.SharedPool() |
1714 | - pool2 = process.SharedPool() |
1715 | - self.assert_(id(pool1) == id(pool2)) |
1716 | - |
1717 | |
1718 | === removed file 'nova/tests/real_flags.py' |
1719 | --- nova/tests/real_flags.py 2010-07-15 15:52:11 +0000 |
1720 | +++ nova/tests/real_flags.py 1970-01-01 00:00:00 +0000 |
1721 | @@ -1,28 +0,0 @@ |
1722 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1723 | - |
1724 | -# Copyright 2010 United States Government as represented by the |
1725 | -# Administrator of the National Aeronautics and Space Administration. |
1726 | -# All Rights Reserved. |
1727 | -# |
1728 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
1729 | -# not use this file except in compliance with the License. You may obtain |
1730 | -# a copy of the License at |
1731 | -# |
1732 | -# http://www.apache.org/licenses/LICENSE-2.0 |
1733 | -# |
1734 | -# Unless required by applicable law or agreed to in writing, software |
1735 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
1736 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
1737 | -# License for the specific language governing permissions and limitations |
1738 | -# under the License. |
1739 | - |
1740 | -from nova import flags |
1741 | - |
1742 | -FLAGS = flags.FLAGS |
1743 | - |
1744 | -FLAGS.fake_libvirt = False |
1745 | -FLAGS.fake_storage = False |
1746 | -FLAGS.fake_rabbit = False |
1747 | -FLAGS.fake_network = False |
1748 | -FLAGS.fake_users = False |
1749 | -FLAGS.verbose = False |
1750 | |
1751 | === removed file 'nova/tests/storage_unittest.py' |
1752 | --- nova/tests/storage_unittest.py 2010-07-15 23:16:09 +0000 |
1753 | +++ nova/tests/storage_unittest.py 1970-01-01 00:00:00 +0000 |
1754 | @@ -1,115 +0,0 @@ |
1755 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1756 | - |
1757 | -# Copyright 2010 United States Government as represented by the |
1758 | -# Administrator of the National Aeronautics and Space Administration. |
1759 | -# All Rights Reserved. |
1760 | -# |
1761 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
1762 | -# not use this file except in compliance with the License. You may obtain |
1763 | -# a copy of the License at |
1764 | -# |
1765 | -# http://www.apache.org/licenses/LICENSE-2.0 |
1766 | -# |
1767 | -# Unless required by applicable law or agreed to in writing, software |
1768 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
1769 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
1770 | -# License for the specific language governing permissions and limitations |
1771 | -# under the License. |
1772 | - |
1773 | -import logging |
1774 | - |
1775 | -from nova import exception |
1776 | -from nova import flags |
1777 | -from nova import test |
1778 | -from nova.compute import node |
1779 | -from nova.volume import storage |
1780 | - |
1781 | - |
1782 | -FLAGS = flags.FLAGS |
1783 | - |
1784 | - |
1785 | -class StorageTestCase(test.TrialTestCase): |
1786 | - def setUp(self): |
1787 | - logging.getLogger().setLevel(logging.DEBUG) |
1788 | - super(StorageTestCase, self).setUp() |
1789 | - self.mynode = node.Node() |
1790 | - self.mystorage = None |
1791 | - self.flags(fake_libvirt=True, |
1792 | - fake_storage=True) |
1793 | - self.mystorage = storage.BlockStore() |
1794 | - |
1795 | - def test_run_create_volume(self): |
1796 | - vol_size = '0' |
1797 | - user_id = 'fake' |
1798 | - project_id = 'fake' |
1799 | - volume_id = self.mystorage.create_volume(vol_size, user_id, project_id) |
1800 | - # TODO(termie): get_volume returns differently than create_volume |
1801 | - self.assertEqual(volume_id, |
1802 | - storage.get_volume(volume_id)['volume_id']) |
1803 | - |
1804 | - rv = self.mystorage.delete_volume(volume_id) |
1805 | - self.assertRaises(exception.Error, |
1806 | - storage.get_volume, |
1807 | - volume_id) |
1808 | - |
1809 | - def test_too_big_volume(self): |
1810 | - vol_size = '1001' |
1811 | - user_id = 'fake' |
1812 | - project_id = 'fake' |
1813 | - self.assertRaises(TypeError, |
1814 | - self.mystorage.create_volume, |
1815 | - vol_size, user_id, project_id) |
1816 | - |
1817 | - def test_too_many_volumes(self): |
1818 | - vol_size = '1' |
1819 | - user_id = 'fake' |
1820 | - project_id = 'fake' |
1821 | - num_shelves = FLAGS.last_shelf_id - FLAGS.first_shelf_id + 1 |
1822 | - total_slots = FLAGS.slots_per_shelf * num_shelves |
1823 | - vols = [] |
1824 | - for i in xrange(total_slots): |
1825 | - vid = self.mystorage.create_volume(vol_size, user_id, project_id) |
1826 | - vols.append(vid) |
1827 | - self.assertRaises(storage.NoMoreVolumes, |
1828 | - self.mystorage.create_volume, |
1829 | - vol_size, user_id, project_id) |
1830 | - for id in vols: |
1831 | - self.mystorage.delete_volume(id) |
1832 | - |
1833 | - def test_run_attach_detach_volume(self): |
1834 | - # Create one volume and one node to test with |
1835 | - instance_id = "storage-test" |
1836 | - vol_size = "5" |
1837 | - user_id = "fake" |
1838 | - project_id = 'fake' |
1839 | - mountpoint = "/dev/sdf" |
1840 | - volume_id = self.mystorage.create_volume(vol_size, user_id, project_id) |
1841 | - |
1842 | - volume_obj = storage.get_volume(volume_id) |
1843 | - volume_obj.start_attach(instance_id, mountpoint) |
1844 | - rv = yield self.mynode.attach_volume(volume_id, |
1845 | - instance_id, |
1846 | - mountpoint) |
1847 | - self.assertEqual(volume_obj['status'], "in-use") |
1848 | - self.assertEqual(volume_obj['attachStatus'], "attached") |
1849 | - self.assertEqual(volume_obj['instance_id'], instance_id) |
1850 | - self.assertEqual(volume_obj['mountpoint'], mountpoint) |
1851 | - |
1852 | - self.assertRaises(exception.Error, |
1853 | - self.mystorage.delete_volume, |
1854 | - volume_id) |
1855 | - |
1856 | - rv = yield self.mystorage.detach_volume(volume_id) |
1857 | - volume_obj = storage.get_volume(volume_id) |
1858 | - self.assertEqual(volume_obj['status'], "available") |
1859 | - |
1860 | - rv = self.mystorage.delete_volume(volume_id) |
1861 | - self.assertRaises(exception.Error, |
1862 | - storage.get_volume, |
1863 | - volume_id) |
1864 | - |
1865 | - def test_multi_node(self): |
1866 | - # TODO(termie): Figure out how to test with two nodes, |
1867 | - # each of them having a different FLAG for storage_node |
1868 | - # This will allow us to test cross-node interactions |
1869 | - pass |
1870 | |
1871 | === removed file 'nova/tests/users_unittest.py' |
1872 | --- nova/tests/users_unittest.py 2010-07-15 23:13:48 +0000 |
1873 | +++ nova/tests/users_unittest.py 1970-01-01 00:00:00 +0000 |
1874 | @@ -1,207 +0,0 @@ |
1875 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1876 | - |
1877 | -# Copyright 2010 United States Government as represented by the |
1878 | -# Administrator of the National Aeronautics and Space Administration. |
1879 | -# All Rights Reserved. |
1880 | -# |
1881 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
1882 | -# not use this file except in compliance with the License. You may obtain |
1883 | -# a copy of the License at |
1884 | -# |
1885 | -# http://www.apache.org/licenses/LICENSE-2.0 |
1886 | -# |
1887 | -# Unless required by applicable law or agreed to in writing, software |
1888 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
1889 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
1890 | -# License for the specific language governing permissions and limitations |
1891 | -# under the License. |
1892 | - |
1893 | -import logging |
1894 | -from M2Crypto import BIO |
1895 | -from M2Crypto import RSA |
1896 | -from M2Crypto import X509 |
1897 | -import unittest |
1898 | - |
1899 | -from nova import crypto |
1900 | -from nova import flags |
1901 | -from nova import test |
1902 | -from nova.auth import users |
1903 | -from nova.endpoint import cloud |
1904 | - |
1905 | -FLAGS = flags.FLAGS |
1906 | - |
1907 | - |
1908 | -class UserTestCase(test.BaseTestCase): |
1909 | - flush_db = False |
1910 | - def setUp(self): |
1911 | - super(UserTestCase, self).setUp() |
1912 | - self.flags(fake_libvirt=True, |
1913 | - fake_storage=True) |
1914 | - self.users = users.UserManager.instance() |
1915 | - |
1916 | - def test_001_can_create_users(self): |
1917 | - self.users.create_user('test1', 'access', 'secret') |
1918 | - self.users.create_user('test2') |
1919 | - |
1920 | - def test_002_can_get_user(self): |
1921 | - user = self.users.get_user('test1') |
1922 | - |
1923 | - def test_003_can_retreive_properties(self): |
1924 | - user = self.users.get_user('test1') |
1925 | - self.assertEqual('test1', user.id) |
1926 | - self.assertEqual('access', user.access) |
1927 | - self.assertEqual('secret', user.secret) |
1928 | - |
1929 | - def test_004_signature_is_valid(self): |
1930 | - #self.assertTrue(self.users.authenticate( **boto.generate_url ... ? ? ? )) |
1931 | - pass |
1932 | - #raise NotImplementedError |
1933 | - |
1934 | - def test_005_can_get_credentials(self): |
1935 | - return |
1936 | - credentials = self.users.get_user('test1').get_credentials() |
1937 | - self.assertEqual(credentials, |
1938 | - 'export EC2_ACCESS_KEY="access"\n' + |
1939 | - 'export EC2_SECRET_KEY="secret"\n' + |
1940 | - 'export EC2_URL="http://127.0.0.1:8773/services/Cloud"\n' + |
1941 | - 'export S3_URL="http://127.0.0.1:3333/"\n' + |
1942 | - 'export EC2_USER_ID="test1"\n') |
1943 | - |
1944 | - def test_006_test_key_storage(self): |
1945 | - user = self.users.get_user('test1') |
1946 | - user.create_key_pair('public', 'key', 'fingerprint') |
1947 | - key = user.get_key_pair('public') |
1948 | - self.assertEqual('key', key.public_key) |
1949 | - self.assertEqual('fingerprint', key.fingerprint) |
1950 | - |
1951 | - def test_007_test_key_generation(self): |
1952 | - user = self.users.get_user('test1') |
1953 | - private_key, fingerprint = user.generate_key_pair('public2') |
1954 | - key = RSA.load_key_string(private_key, callback=lambda: None) |
1955 | - bio = BIO.MemoryBuffer() |
1956 | - public_key = user.get_key_pair('public2').public_key |
1957 | - key.save_pub_key_bio(bio) |
1958 | - converted = crypto.ssl_pub_to_ssh_pub(bio.read()) |
1959 | - # assert key fields are equal |
1960 | - self.assertEqual(public_key.split(" ")[1].strip(), |
1961 | - converted.split(" ")[1].strip()) |
1962 | - |
1963 | - def test_008_can_list_key_pairs(self): |
1964 | - keys = self.users.get_user('test1').get_key_pairs() |
1965 | - self.assertTrue(filter(lambda k: k.name == 'public', keys)) |
1966 | - self.assertTrue(filter(lambda k: k.name == 'public2', keys)) |
1967 | - |
1968 | - def test_009_can_delete_key_pair(self): |
1969 | - self.users.get_user('test1').delete_key_pair('public') |
1970 | - keys = self.users.get_user('test1').get_key_pairs() |
1971 | - self.assertFalse(filter(lambda k: k.name == 'public', keys)) |
1972 | - |
1973 | - def test_010_can_list_users(self): |
1974 | - users = self.users.get_users() |
1975 | - logging.warn(users) |
1976 | - self.assertTrue(filter(lambda u: u.id == 'test1', users)) |
1977 | - |
1978 | - def test_101_can_add_user_role(self): |
1979 | - self.assertFalse(self.users.has_role('test1', 'itsec')) |
1980 | - self.users.add_role('test1', 'itsec') |
1981 | - self.assertTrue(self.users.has_role('test1', 'itsec')) |
1982 | - |
1983 | - def test_199_can_remove_user_role(self): |
1984 | - self.assertTrue(self.users.has_role('test1', 'itsec')) |
1985 | - self.users.remove_role('test1', 'itsec') |
1986 | - self.assertFalse(self.users.has_role('test1', 'itsec')) |
1987 | - |
1988 | - def test_201_can_create_project(self): |
1989 | - project = self.users.create_project('testproj', 'test1', 'A test project', ['test1']) |
1990 | - self.assertTrue(filter(lambda p: p.name == 'testproj', self.users.get_projects())) |
1991 | - self.assertEqual(project.name, 'testproj') |
1992 | - self.assertEqual(project.description, 'A test project') |
1993 | - self.assertEqual(project.project_manager_id, 'test1') |
1994 | - self.assertTrue(project.has_member('test1')) |
1995 | - |
1996 | - def test_202_user1_is_project_member(self): |
1997 | - self.assertTrue(self.users.get_user('test1').is_project_member('testproj')) |
1998 | - |
1999 | - def test_203_user2_is_not_project_member(self): |
2000 | - self.assertFalse(self.users.get_user('test2').is_project_member('testproj')) |
2001 | - |
2002 | - def test_204_user1_is_project_manager(self): |
2003 | - self.assertTrue(self.users.get_user('test1').is_project_manager('testproj')) |
2004 | - |
2005 | - def test_205_user2_is_not_project_manager(self): |
2006 | - self.assertFalse(self.users.get_user('test2').is_project_manager('testproj')) |
2007 | - |
2008 | - def test_206_can_add_user_to_project(self): |
2009 | - self.users.add_to_project('test2', 'testproj') |
2010 | - self.assertTrue(self.users.get_project('testproj').has_member('test2')) |
2011 | - |
2012 | - def test_208_can_remove_user_from_project(self): |
2013 | - self.users.remove_from_project('test2', 'testproj') |
2014 | - self.assertFalse(self.users.get_project('testproj').has_member('test2')) |
2015 | - |
2016 | - def test_209_can_generate_x509(self): |
2017 | - # MUST HAVE RUN CLOUD SETUP BY NOW |
2018 | - self.cloud = cloud.CloudController() |
2019 | - self.cloud.setup() |
2020 | - private_key, signed_cert_string = self.users.get_project('testproj').generate_x509_cert('test1') |
2021 | - logging.debug(signed_cert_string) |
2022 | - |
2023 | - # Need to verify that it's signed by the right intermediate CA |
2024 | - full_chain = crypto.fetch_ca(project_id='testproj', chain=True) |
2025 | - int_cert = crypto.fetch_ca(project_id='testproj', chain=False) |
2026 | - cloud_cert = crypto.fetch_ca() |
2027 | - logging.debug("CA chain:\n\n =====\n%s\n\n=====" % full_chain) |
2028 | - signed_cert = X509.load_cert_string(signed_cert_string) |
2029 | - chain_cert = X509.load_cert_string(full_chain) |
2030 | - int_cert = X509.load_cert_string(int_cert) |
2031 | - cloud_cert = X509.load_cert_string(cloud_cert) |
2032 | - self.assertTrue(signed_cert.verify(chain_cert.get_pubkey())) |
2033 | - self.assertTrue(signed_cert.verify(int_cert.get_pubkey())) |
2034 | - |
2035 | - if not FLAGS.use_intermediate_ca: |
2036 | - self.assertTrue(signed_cert.verify(cloud_cert.get_pubkey())) |
2037 | - else: |
2038 | - self.assertFalse(signed_cert.verify(cloud_cert.get_pubkey())) |
2039 | - |
2040 | - def test_210_can_add_project_role(self): |
2041 | - project = self.users.get_project('testproj') |
2042 | - self.assertFalse(project.has_role('test1', 'sysadmin')) |
2043 | - self.users.add_role('test1', 'sysadmin') |
2044 | - self.assertFalse(project.has_role('test1', 'sysadmin')) |
2045 | - project.add_role('test1', 'sysadmin') |
2046 | - self.assertTrue(project.has_role('test1', 'sysadmin')) |
2047 | - |
2048 | - def test_211_can_remove_project_role(self): |
2049 | - project = self.users.get_project('testproj') |
2050 | - self.assertTrue(project.has_role('test1', 'sysadmin')) |
2051 | - project.remove_role('test1', 'sysadmin') |
2052 | - self.assertFalse(project.has_role('test1', 'sysadmin')) |
2053 | - self.users.remove_role('test1', 'sysadmin') |
2054 | - self.assertFalse(project.has_role('test1', 'sysadmin')) |
2055 | - |
2056 | - def test_212_vpn_ip_and_port_looks_valid(self): |
2057 | - project = self.users.get_project('testproj') |
2058 | - self.assert_(project.vpn_ip) |
2059 | - self.assert_(project.vpn_port >= FLAGS.vpn_start_port) |
2060 | - self.assert_(project.vpn_port <= FLAGS.vpn_end_port) |
2061 | - |
2062 | - def test_213_too_many_vpns(self): |
2063 | - for i in xrange(users.Vpn.num_ports_for_ip(FLAGS.vpn_ip)): |
2064 | - users.Vpn.create("vpnuser%s" % i) |
2065 | - self.assertRaises(users.NoMorePorts, users.Vpn.create, "boom") |
2066 | - |
2067 | - def test_299_can_delete_project(self): |
2068 | - self.users.delete_project('testproj') |
2069 | - self.assertFalse(filter(lambda p: p.name == 'testproj', self.users.get_projects())) |
2070 | - |
2071 | - def test_999_can_delete_users(self): |
2072 | - self.users.delete_user('test1') |
2073 | - users = self.users.get_users() |
2074 | - self.assertFalse(filter(lambda u: u.id == 'test1', users)) |
2075 | - self.users.delete_user('test2') |
2076 | - self.assertEqual(self.users.get_user('test2'), None) |
2077 | - |
2078 | - |
2079 | -if __name__ == "__main__": |
2080 | - # TODO: Implement use_fake as an option |
2081 | - unittest.main() |
2082 | |
2083 | === removed file 'nova/tests/validator_unittest.py' |
2084 | --- nova/tests/validator_unittest.py 2010-07-15 23:13:48 +0000 |
2085 | +++ nova/tests/validator_unittest.py 1970-01-01 00:00:00 +0000 |
2086 | @@ -1,41 +0,0 @@ |
2087 | -# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
2088 | - |
2089 | -# Copyright 2010 United States Government as represented by the |
2090 | -# Administrator of the National Aeronautics and Space Administration. |
2091 | -# All Rights Reserved. |
2092 | -# |
2093 | -# Licensed under the Apache License, Version 2.0 (the "License"); you may |
2094 | -# not use this file except in compliance with the License. You may obtain |
2095 | -# a copy of the License at |
2096 | -# |
2097 | -# http://www.apache.org/licenses/LICENSE-2.0 |
2098 | -# |
2099 | -# Unless required by applicable law or agreed to in writing, software |
2100 | -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
2101 | -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2102 | -# License for the specific language governing permissions and limitations |
2103 | -# under the License. |
2104 | - |
2105 | -import logging |
2106 | -import unittest |
2107 | - |
2108 | -from nova import flags |
2109 | -from nova import test |
2110 | -from nova import validate |
2111 | - |
2112 | - |
2113 | -class ValidationTestCase(test.TrialTestCase): |
2114 | - def setUp(self): |
2115 | - super(ValidationTestCase, self).setUp() |
2116 | - |
2117 | - def tearDown(self): |
2118 | - super(ValidationTestCase, self).tearDown() |
2119 | - |
2120 | - def test_type_validation(self): |
2121 | - self.assertTrue(type_case("foo", 5, 1)) |
2122 | - self.assertRaises(TypeError, type_case, "bar", "5", 1) |
2123 | - self.assertRaises(TypeError, type_case, None, 5, 1) |
2124 | - |
2125 | -@validate.typetest(instanceid=str, size=int, number_of_instances=int) |
2126 | -def type_case(instanceid, size, number_of_instances): |
2127 | - return True |
2128 | |
2129 | === modified file 'run_tests.py' |
2130 | --- run_tests.py 2010-07-19 08:37:28 +0000 |
2131 | +++ run_tests.py 2010-07-23 03:41:08 +0000 |
2132 | @@ -49,17 +49,17 @@ |
2133 | from nova import flags |
2134 | from nova import twistd |
2135 | |
2136 | -from nova.tests.access_unittest import * |
2137 | -from nova.tests.api_unittest import * |
2138 | -from nova.tests.cloud_unittest import * |
2139 | -from nova.tests.model_unittest import * |
2140 | -from nova.tests.network_unittest import * |
2141 | -from nova.tests.node_unittest import * |
2142 | -from nova.tests.objectstore_unittest import * |
2143 | -from nova.tests.process_unittest import * |
2144 | -from nova.tests.storage_unittest import * |
2145 | -from nova.tests.users_unittest import * |
2146 | -from nova.tests.validator_unittest import * |
2147 | +from tests.access_unittest import * |
2148 | +from tests.api_unittest import * |
2149 | +from tests.cloud_unittest import * |
2150 | +from tests.model_unittest import * |
2151 | +from tests.network_unittest import * |
2152 | +from tests.node_unittest import * |
2153 | +from tests.objectstore_unittest import * |
2154 | +from tests.process_unittest import * |
2155 | +from tests.storage_unittest import * |
2156 | +from tests.users_unittest import * |
2157 | +from tests.validator_unittest import * |
2158 | |
2159 | |
2160 | FLAGS = flags.FLAGS |
2161 | @@ -79,7 +79,7 @@ |
2162 | |
2163 | # TODO(termie): these should make a call instead of doing work on import |
2164 | if FLAGS.fake_tests: |
2165 | - from nova.tests.fake_flags import * |
2166 | + from tests.fake_flags import * |
2167 | # use db 8 for fake tests |
2168 | FLAGS.redis_db = 8 |
2169 | if FLAGS.flush_db: |
2170 | @@ -87,7 +87,7 @@ |
2171 | r = datastore.Redis.instance() |
2172 | r.flushdb() |
2173 | else: |
2174 | - from nova.tests.real_flags import * |
2175 | + from tests.real_flags import * |
2176 | |
2177 | # Establish redirect for STDERR |
2178 | sys.stderr.flush() |
2179 | |
2180 | === added directory 'tests' |
2181 | === added directory 'tests/CA' |
2182 | === added file 'tests/CA/cacert.pem' |
2183 | --- tests/CA/cacert.pem 1970-01-01 00:00:00 +0000 |
2184 | +++ tests/CA/cacert.pem 2010-07-23 03:41:08 +0000 |
2185 | @@ -0,0 +1,17 @@ |
2186 | +-----BEGIN CERTIFICATE----- |
2187 | +MIICyzCCAjSgAwIBAgIJANiqHZUcbScCMA0GCSqGSIb3DQEBBAUAME4xEjAQBgNV |
2188 | +BAoTCU5PVkEgUk9PVDEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzETMBEGA1UECBMK |
2189 | +Q2FsaWZvcm5pYTELMAkGA1UEBhMCVVMwHhcNMTAwNTI4MDExOTI1WhcNMTEwNTI4 |
2190 | +MDExOTI1WjBOMRIwEAYDVQQKEwlOT1ZBIFJPT1QxFjAUBgNVBAcTDU1vdW50YWlu |
2191 | +IFZpZXcxEzARBgNVBAgTCkNhbGlmb3JuaWExCzAJBgNVBAYTAlVTMIGfMA0GCSqG |
2192 | +SIb3DQEBAQUAA4GNADCBiQKBgQDobUnq8rpXA/HQZ2Uu9Me3SlqCayz3ws2wtvFQ |
2193 | +koWPUzpriIYPkpprz2EaVu07Zb9uJHvjcoY07nYntl4jR8S7PH4XZhlVFn8AQWzs |
2194 | +iThU4KJF71UfVM00dDrarSgVpyOIcFXO3iUvLoJj7+RUPjrWdLuJoMqnhicgLeHZ |
2195 | +LAZ8ewIDAQABo4GwMIGtMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFMh1RMlTVtt8 |
2196 | +EdESYpsTU08r0FnpMH4GA1UdIwR3MHWAFMh1RMlTVtt8EdESYpsTU08r0FnpoVKk |
2197 | +UDBOMRIwEAYDVQQKEwlOT1ZBIFJPT1QxFjAUBgNVBAcTDU1vdW50YWluIFZpZXcx |
2198 | +EzARBgNVBAgTCkNhbGlmb3JuaWExCzAJBgNVBAYTAlVTggkA2KodlRxtJwIwDQYJ |
2199 | +KoZIhvcNAQEEBQADgYEAq+YCgflK36HCdodNu2ya3O6UDRUE2dW8n96tAOmvHqmR |
2200 | +v38k8GIW0pjWDo+lZYnFmeJYd+QGcJl9fLzXxffV5k+rNCfr/gEYtznWLNUX7AZB |
2201 | +b/VC7L+yK9qz08C8n51TslXaf3fUGkfkQxsvEP7+hi0qavdd/8eTbdheWahYwWg= |
2202 | +-----END CERTIFICATE----- |
2203 | |
2204 | === added directory 'tests/CA/private' |
2205 | === added file 'tests/CA/private/cakey.pem' |
2206 | --- tests/CA/private/cakey.pem 1970-01-01 00:00:00 +0000 |
2207 | +++ tests/CA/private/cakey.pem 2010-07-23 03:41:08 +0000 |
2208 | @@ -0,0 +1,15 @@ |
2209 | +-----BEGIN RSA PRIVATE KEY----- |
2210 | +MIICXQIBAAKBgQDobUnq8rpXA/HQZ2Uu9Me3SlqCayz3ws2wtvFQkoWPUzpriIYP |
2211 | +kpprz2EaVu07Zb9uJHvjcoY07nYntl4jR8S7PH4XZhlVFn8AQWzsiThU4KJF71Uf |
2212 | +VM00dDrarSgVpyOIcFXO3iUvLoJj7+RUPjrWdLuJoMqnhicgLeHZLAZ8ewIDAQAB |
2213 | +AoGBANQonmZ2Nh2jniFrn/LiwULP/ho6Fov6J6N8+n1focaYZCUwM58XZRmv7KUM |
2214 | +X/PuBnVVnDibm2HJodTSJM/zfODnGO15kdmJ9X23FkkdTyuvphO5tYF0ONARXdfX |
2215 | +9LbPcLYA14VSCZCKCye6mbv/xi0C/s7q6ZBoMl7XaeD9hgUxAkEA9lxQY/ZxcLV0 |
2216 | +Ae5I2spBbtuXEGns11YnKnppc59RrAono1gaDeYY2WZRwztIcD6VtUv7qkzH6ubo |
2217 | +shAG4fvnPQJBAPGFaDODs2ckPvxnILEbjpnZXGQqDCpQ3sVJ6nfu+qdAWS92ESNo |
2218 | +Y6DC8zFjFaQFbKy6Jxr1VsvYDXhF8cmy7hcCQHkLElSLGWGPRdhNA268QTn+mlJu |
2219 | +OPf0VHoCex1cAfzNYHxZJTP/AeaO501NK2I63cOd+aDK6M75dQtH5JnT8uECQQCg |
2220 | +jVydkhk6oV+1jiCvW3BKWbIPa9w2bRgJ8n8JRzYc5Kvk3wm5jfVcsvvTgtip9mkt |
2221 | +0XmZdCpEy9T4dRasTGP1AkBMhShiVP7+P+SIQlZtSn8ckTt9G6cefEjxsv0kVFZe |
2222 | +SjkUO0ZifahF8r3Q1eEUSzdXEvicEwONvcpc7MLwfSD7 |
2223 | +-----END RSA PRIVATE KEY----- |
2224 | |
2225 | === added file 'tests/__init__.py' |
2226 | --- tests/__init__.py 1970-01-01 00:00:00 +0000 |
2227 | +++ tests/__init__.py 2010-07-23 03:41:08 +0000 |
2228 | @@ -0,0 +1,31 @@ |
2229 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
2230 | + |
2231 | +# Copyright 2010 United States Government as represented by the |
2232 | +# Administrator of the National Aeronautics and Space Administration. |
2233 | +# All Rights Reserved. |
2234 | +# |
2235 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
2236 | +# not use this file except in compliance with the License. You may obtain |
2237 | +# a copy of the License at |
2238 | +# |
2239 | +# http://www.apache.org/licenses/LICENSE-2.0 |
2240 | +# |
2241 | +# Unless required by applicable law or agreed to in writing, software |
2242 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
2243 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2244 | +# License for the specific language governing permissions and limitations |
2245 | +# under the License. |
2246 | + |
2247 | +""" |
2248 | +:mod:`tests` -- Nova Unittests |
2249 | +===================================================== |
2250 | + |
2251 | +.. automodule:: tests |
2252 | + :platform: Unix |
2253 | +.. moduleauthor:: Jesse Andrews <jesse@ansolabs.com> |
2254 | +.. moduleauthor:: Devin Carlen <devin.carlen@gmail.com> |
2255 | +.. moduleauthor:: Vishvananda Ishaya <vishvananda@yahoo.com> |
2256 | +.. moduleauthor:: Joshua McKenty <joshua@cognition.ca> |
2257 | +.. moduleauthor:: Manish Singh <yosh@gimp.org> |
2258 | +.. moduleauthor:: Andy Smith <andy@anarkystic.com> |
2259 | +""" |
2260 | |
2261 | === added file 'tests/access_unittest.py' |
2262 | --- tests/access_unittest.py 1970-01-01 00:00:00 +0000 |
2263 | +++ tests/access_unittest.py 2010-07-23 03:41:08 +0000 |
2264 | @@ -0,0 +1,165 @@ |
2265 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
2266 | + |
2267 | +# Copyright 2010 United States Government as represented by the |
2268 | +# Administrator of the National Aeronautics and Space Administration. |
2269 | +# All Rights Reserved. |
2270 | +# |
2271 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
2272 | +# not use this file except in compliance with the License. You may obtain |
2273 | +# a copy of the License at |
2274 | +# |
2275 | +# http://www.apache.org/licenses/LICENSE-2.0 |
2276 | +# |
2277 | +# Unless required by applicable law or agreed to in writing, software |
2278 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
2279 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2280 | +# License for the specific language governing permissions and limitations |
2281 | +# under the License. |
2282 | + |
2283 | +import unittest |
2284 | +import logging |
2285 | + |
2286 | +from nova import exception |
2287 | +from nova import flags |
2288 | +from nova import test |
2289 | +from nova.auth.users import UserManager |
2290 | +from nova.auth import rbac |
2291 | + |
2292 | + |
2293 | +FLAGS = flags.FLAGS |
2294 | +class Context(object): |
2295 | + pass |
2296 | + |
2297 | +class AccessTestCase(test.BaseTestCase): |
2298 | + def setUp(self): |
2299 | + super(AccessTestCase, self).setUp() |
2300 | + FLAGS.fake_libvirt = True |
2301 | + FLAGS.fake_storage = True |
2302 | + um = UserManager.instance() |
2303 | + # Make test users |
2304 | + try: |
2305 | + self.testadmin = um.create_user('testadmin') |
2306 | + except Exception, err: |
2307 | + logging.error(str(err)) |
2308 | + try: |
2309 | + self.testpmsys = um.create_user('testpmsys') |
2310 | + except: pass |
2311 | + try: |
2312 | + self.testnet = um.create_user('testnet') |
2313 | + except: pass |
2314 | + try: |
2315 | + self.testsys = um.create_user('testsys') |
2316 | + except: pass |
2317 | + # Assign some rules |
2318 | + try: |
2319 | + um.add_role('testadmin', 'cloudadmin') |
2320 | + except: pass |
2321 | + try: |
2322 | + um.add_role('testpmsys', 'sysadmin') |
2323 | + except: pass |
2324 | + try: |
2325 | + um.add_role('testnet', 'netadmin') |
2326 | + except: pass |
2327 | + try: |
2328 | + um.add_role('testsys', 'sysadmin') |
2329 | + except: pass |
2330 | + |
2331 | + # Make a test project |
2332 | + try: |
2333 | + self.project = um.create_project('testproj', 'testpmsys', 'a test project', ['testpmsys', 'testnet', 'testsys']) |
2334 | + except: pass |
2335 | + try: |
2336 | + self.project.add_role(self.testnet, 'netadmin') |
2337 | + except: pass |
2338 | + try: |
2339 | + self.project.add_role(self.testsys, 'sysadmin') |
2340 | + except: pass |
2341 | + self.context = Context() |
2342 | + self.context.project = self.project |
2343 | + #user is set in each test |
2344 | + |
2345 | + def tearDown(self): |
2346 | + um = UserManager.instance() |
2347 | + # Delete the test project |
2348 | + um.delete_project('testproj') |
2349 | + # Delete the test user |
2350 | + um.delete_user('testadmin') |
2351 | + um.delete_user('testpmsys') |
2352 | + um.delete_user('testnet') |
2353 | + um.delete_user('testsys') |
2354 | + super(AccessTestCase, self).tearDown() |
2355 | + |
2356 | + def test_001_allow_all(self): |
2357 | + self.context.user = self.testadmin |
2358 | + self.assertTrue(self._allow_all(self.context)) |
2359 | + self.context.user = self.testpmsys |
2360 | + self.assertTrue(self._allow_all(self.context)) |
2361 | + self.context.user = self.testnet |
2362 | + self.assertTrue(self._allow_all(self.context)) |
2363 | + self.context.user = self.testsys |
2364 | + self.assertTrue(self._allow_all(self.context)) |
2365 | + |
2366 | + def test_002_allow_none(self): |
2367 | + self.context.user = self.testadmin |
2368 | + self.assertTrue(self._allow_none(self.context)) |
2369 | + self.context.user = self.testpmsys |
2370 | + self.assertRaises(exception.NotAuthorized, self._allow_none, self.context) |
2371 | + self.context.user = self.testnet |
2372 | + self.assertRaises(exception.NotAuthorized, self._allow_none, self.context) |
2373 | + self.context.user = self.testsys |
2374 | + self.assertRaises(exception.NotAuthorized, self._allow_none, self.context) |
2375 | + |
2376 | + def test_003_allow_project_manager(self): |
2377 | + self.context.user = self.testadmin |
2378 | + self.assertTrue(self._allow_project_manager(self.context)) |
2379 | + self.context.user = self.testpmsys |
2380 | + self.assertTrue(self._allow_project_manager(self.context)) |
2381 | + self.context.user = self.testnet |
2382 | + self.assertRaises(exception.NotAuthorized, self._allow_project_manager, self.context) |
2383 | + self.context.user = self.testsys |
2384 | + self.assertRaises(exception.NotAuthorized, self._allow_project_manager, self.context) |
2385 | + |
2386 | + def test_004_allow_sys_and_net(self): |
2387 | + self.context.user = self.testadmin |
2388 | + self.assertTrue(self._allow_sys_and_net(self.context)) |
2389 | + self.context.user = self.testpmsys # doesn't have the per project sysadmin |
2390 | + self.assertRaises(exception.NotAuthorized, self._allow_sys_and_net, self.context) |
2391 | + self.context.user = self.testnet |
2392 | + self.assertTrue(self._allow_sys_and_net(self.context)) |
2393 | + self.context.user = self.testsys |
2394 | + self.assertTrue(self._allow_sys_and_net(self.context)) |
2395 | + |
2396 | + def test_005_allow_sys_no_pm(self): |
2397 | + self.context.user = self.testadmin |
2398 | + self.assertTrue(self._allow_sys_no_pm(self.context)) |
2399 | + self.context.user = self.testpmsys |
2400 | + self.assertRaises(exception.NotAuthorized, self._allow_sys_no_pm, self.context) |
2401 | + self.context.user = self.testnet |
2402 | + self.assertRaises(exception.NotAuthorized, self._allow_sys_no_pm, self.context) |
2403 | + self.context.user = self.testsys |
2404 | + self.assertTrue(self._allow_sys_no_pm(self.context)) |
2405 | + |
2406 | + @rbac.allow('all') |
2407 | + def _allow_all(self, context): |
2408 | + return True |
2409 | + |
2410 | + @rbac.allow('none') |
2411 | + def _allow_none(self, context): |
2412 | + return True |
2413 | + |
2414 | + @rbac.allow('projectmanager') |
2415 | + def _allow_project_manager(self, context): |
2416 | + return True |
2417 | + |
2418 | + @rbac.allow('sysadmin', 'netadmin') |
2419 | + def _allow_sys_and_net(self, context): |
2420 | + return True |
2421 | + |
2422 | + @rbac.allow('sysadmin') |
2423 | + @rbac.deny('projectmanager') |
2424 | + def _allow_sys_no_pm(self, context): |
2425 | + return True |
2426 | + |
2427 | +if __name__ == "__main__": |
2428 | + # TODO: Implement use_fake as an option |
2429 | + unittest.main() |
2430 | |
2431 | === added file 'tests/api_integration.py' |
2432 | --- tests/api_integration.py 1970-01-01 00:00:00 +0000 |
2433 | +++ tests/api_integration.py 2010-07-23 03:41:08 +0000 |
2434 | @@ -0,0 +1,54 @@ |
2435 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
2436 | + |
2437 | +# Copyright 2010 United States Government as represented by the |
2438 | +# Administrator of the National Aeronautics and Space Administration. |
2439 | +# All Rights Reserved. |
2440 | +# |
2441 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
2442 | +# not use this file except in compliance with the License. You may obtain |
2443 | +# a copy of the License at |
2444 | +# |
2445 | +# http://www.apache.org/licenses/LICENSE-2.0 |
2446 | +# |
2447 | +# Unless required by applicable law or agreed to in writing, software |
2448 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
2449 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2450 | +# License for the specific language governing permissions and limitations |
2451 | +# under the License. |
2452 | + |
2453 | + |
2454 | +import boto |
2455 | +from boto.ec2.regioninfo import RegionInfo |
2456 | +import unittest |
2457 | + |
2458 | + |
2459 | +ACCESS_KEY = 'fake' |
2460 | +SECRET_KEY = 'fake' |
2461 | +CLC_IP = '127.0.0.1' |
2462 | +CLC_PORT = 8773 |
2463 | +REGION = 'test' |
2464 | + |
2465 | +def get_connection(): |
2466 | + return boto.connect_ec2 ( |
2467 | + aws_access_key_id=ACCESS_KEY, |
2468 | + aws_secret_access_key=SECRET_KEY, |
2469 | + is_secure=False, |
2470 | + region=RegionInfo(None, REGION, CLC_IP), |
2471 | + port=CLC_PORT, |
2472 | + path='/services/Cloud', |
2473 | + debug=99 |
2474 | + ) |
2475 | + |
2476 | +class APIIntegrationTests(unittest.TestCase): |
2477 | + def test_001_get_all_images(self): |
2478 | + conn = get_connection() |
2479 | + res = conn.get_all_images() |
2480 | + |
2481 | + |
2482 | +if __name__ == '__main__': |
2483 | + unittest.main() |
2484 | + |
2485 | +#print conn.get_all_key_pairs() |
2486 | +#print conn.create_key_pair |
2487 | +#print conn.create_security_group('name', 'description') |
2488 | + |
2489 | |
2490 | === added file 'tests/api_unittest.py' |
2491 | --- tests/api_unittest.py 1970-01-01 00:00:00 +0000 |
2492 | +++ tests/api_unittest.py 2010-07-23 03:41:08 +0000 |
2493 | @@ -0,0 +1,199 @@ |
2494 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
2495 | + |
2496 | +# Copyright 2010 United States Government as represented by the |
2497 | +# Administrator of the National Aeronautics and Space Administration. |
2498 | +# All Rights Reserved. |
2499 | +# |
2500 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
2501 | +# not use this file except in compliance with the License. You may obtain |
2502 | +# a copy of the License at |
2503 | +# |
2504 | +# http://www.apache.org/licenses/LICENSE-2.0 |
2505 | +# |
2506 | +# Unless required by applicable law or agreed to in writing, software |
2507 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
2508 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2509 | +# License for the specific language governing permissions and limitations |
2510 | +# under the License. |
2511 | + |
2512 | +import boto |
2513 | +from boto.ec2 import regioninfo |
2514 | +import httplib |
2515 | +import random |
2516 | +import StringIO |
2517 | +from tornado import httpserver |
2518 | +from twisted.internet import defer |
2519 | + |
2520 | +from nova import flags |
2521 | +from nova import test |
2522 | +from nova.auth import users |
2523 | +from nova.endpoint import api |
2524 | +from nova.endpoint import cloud |
2525 | + |
2526 | + |
2527 | +FLAGS = flags.FLAGS |
2528 | + |
2529 | + |
2530 | +# NOTE(termie): These are a bunch of helper methods and classes to short |
2531 | +# circuit boto calls and feed them into our tornado handlers, |
2532 | +# it's pretty damn circuitous so apologies if you have to fix |
2533 | +# a bug in it |
2534 | +def boto_to_tornado(method, path, headers, data, host, connection=None): |
2535 | + """ translate boto requests into tornado requests |
2536 | + |
2537 | + connection should be a FakeTornadoHttpConnection instance |
2538 | + """ |
2539 | + headers = httpserver.HTTPHeaders() |
2540 | + for k, v in headers.iteritems(): |
2541 | + headers[k] = v |
2542 | + |
2543 | + req = httpserver.HTTPRequest(method=method, |
2544 | + uri=path, |
2545 | + headers=headers, |
2546 | + body=data, |
2547 | + host=host, |
2548 | + remote_ip='127.0.0.1', |
2549 | + connection=connection) |
2550 | + return req |
2551 | + |
2552 | + |
2553 | +def raw_to_httpresponse(s): |
2554 | + """ translate a raw tornado http response into an httplib.HTTPResponse """ |
2555 | + sock = FakeHttplibSocket(s) |
2556 | + resp = httplib.HTTPResponse(sock) |
2557 | + resp.begin() |
2558 | + return resp |
2559 | + |
2560 | + |
2561 | +class FakeHttplibSocket(object): |
2562 | + """ a fake socket implementation for httplib.HTTPResponse, trivial """ |
2563 | + def __init__(self, s): |
2564 | + self.fp = StringIO.StringIO(s) |
2565 | + |
2566 | + def makefile(self, mode, other): |
2567 | + return self.fp |
2568 | + |
2569 | + |
2570 | +class FakeTornadoStream(object): |
2571 | + """ a fake stream to satisfy tornado's assumptions, trivial """ |
2572 | + def set_close_callback(self, f): |
2573 | + pass |
2574 | + |
2575 | + |
2576 | +class FakeTornadoConnection(object): |
2577 | + """ a fake connection object for tornado to pass to its handlers |
2578 | + |
2579 | + web requests are expected to write to this as they get data and call |
2580 | + finish when they are done with the request, we buffer the writes and |
2581 | + kick off a callback when it is done so that we can feed the result back |
2582 | + into boto. |
2583 | + """ |
2584 | + def __init__(self, d): |
2585 | + self.d = d |
2586 | + self._buffer = StringIO.StringIO() |
2587 | + |
2588 | + def write(self, chunk): |
2589 | + self._buffer.write(chunk) |
2590 | + |
2591 | + def finish(self): |
2592 | + s = self._buffer.getvalue() |
2593 | + self.d.callback(s) |
2594 | + |
2595 | + xheaders = None |
2596 | + |
2597 | + @property |
2598 | + def stream(self): |
2599 | + return FakeTornadoStream() |
2600 | + |
2601 | + |
2602 | +class FakeHttplibConnection(object): |
2603 | + """ a fake httplib.HTTPConnection for boto to use |
2604 | + |
2605 | + requests made via this connection actually get translated and routed into |
2606 | + our tornado app, we then wait for the response and turn it back into |
2607 | + the httplib.HTTPResponse that boto expects. |
2608 | + """ |
2609 | + def __init__(self, app, host, is_secure=False): |
2610 | + self.app = app |
2611 | + self.host = host |
2612 | + self.deferred = defer.Deferred() |
2613 | + |
2614 | + def request(self, method, path, data, headers): |
2615 | + req = boto_to_tornado |
2616 | + conn = FakeTornadoConnection(self.deferred) |
2617 | + request = boto_to_tornado(connection=conn, |
2618 | + method=method, |
2619 | + path=path, |
2620 | + headers=headers, |
2621 | + data=data, |
2622 | + host=self.host) |
2623 | + handler = self.app(request) |
2624 | + self.deferred.addCallback(raw_to_httpresponse) |
2625 | + |
2626 | + def getresponse(self): |
2627 | + @defer.inlineCallbacks |
2628 | + def _waiter(): |
2629 | + result = yield self.deferred |
2630 | + defer.returnValue(result) |
2631 | + d = _waiter() |
2632 | + # NOTE(termie): defer.returnValue above should ensure that |
2633 | + # this deferred has already been called by the time |
2634 | + # we get here, we are going to cheat and return |
2635 | + # the result of the callback |
2636 | + return d.result |
2637 | + |
2638 | + def close(self): |
2639 | + pass |
2640 | + |
2641 | + |
2642 | +class ApiEc2TestCase(test.BaseTestCase): |
2643 | + def setUp(self): |
2644 | + super(ApiEc2TestCase, self).setUp() |
2645 | + |
2646 | + self.users = users.UserManager.instance() |
2647 | + self.cloud = cloud.CloudController() |
2648 | + |
2649 | + self.host = '127.0.0.1' |
2650 | + |
2651 | + self.app = api.APIServerApplication({'Cloud': self.cloud}) |
2652 | + self.ec2 = boto.connect_ec2( |
2653 | + aws_access_key_id='fake', |
2654 | + aws_secret_access_key='fake', |
2655 | + is_secure=False, |
2656 | + region=regioninfo.RegionInfo(None, 'test', self.host), |
2657 | + port=FLAGS.cc_port, |
2658 | + path='/services/Cloud') |
2659 | + |
2660 | + self.mox.StubOutWithMock(self.ec2, 'new_http_connection') |
2661 | + |
2662 | + def expect_http(self, host=None, is_secure=False): |
2663 | + http = FakeHttplibConnection( |
2664 | + self.app, '%s:%d' % (self.host, FLAGS.cc_port), False) |
2665 | + self.ec2.new_http_connection(host, is_secure).AndReturn(http) |
2666 | + return http |
2667 | + |
2668 | + def test_describe_instances(self): |
2669 | + self.expect_http() |
2670 | + self.mox.ReplayAll() |
2671 | + try: |
2672 | + self.users.create_user('fake', 'fake', 'fake') |
2673 | + except Exception, _err: |
2674 | + pass # User may already exist |
2675 | + self.assertEqual(self.ec2.get_all_instances(), []) |
2676 | + self.users.delete_user('fake') |
2677 | + |
2678 | + |
2679 | + def test_get_all_key_pairs(self): |
2680 | + self.expect_http() |
2681 | + self.mox.ReplayAll() |
2682 | + keyname = "".join(random.choice("sdiuisudfsdcnpaqwertasd") for x in range(random.randint(4, 8))) |
2683 | + try: |
2684 | + self.users.create_user('fake', 'fake', 'fake') |
2685 | + except Exception, _err: |
2686 | + pass # User may already exist |
2687 | + self.users.generate_key_pair('fake', keyname) |
2688 | + |
2689 | + rv = self.ec2.get_all_key_pairs() |
2690 | + self.assertTrue(filter(lambda k: k.name == keyname, rv)) |
2691 | + self.users.delete_user('fake') |
2692 | + |
2693 | |
2694 | === added directory 'tests/bundle' |
2695 | === added file 'tests/bundle/1mb.manifest.xml' |
2696 | --- tests/bundle/1mb.manifest.xml 1970-01-01 00:00:00 +0000 |
2697 | +++ tests/bundle/1mb.manifest.xml 2010-07-23 03:41:08 +0000 |
2698 | @@ -0,0 +1,1 @@ |
2699 | +<?xml version="1.0" ?><manifest><version>2007-10-10</version><bundler><name>euca-tools</name><version>1.2</version><release>31337</release></bundler><machine_configuration><architecture>x86_64</architecture></machine_configuration><image><name>1mb</name><user>42</user><type>machine</type><digest algorithm="SHA1">da39a3ee5e6b4b0d3255bfef95601890afd80709</digest><size>1048576</size><bundled_size>1136</bundled_size><ec2_encrypted_key algorithm="AES-128-CBC">33a2ea00dc64083dd9a10eb5e233635b42a7beb1670ab75452087d9de74c60aba1cd27c136fda56f62beb581de128fb1f10d072b9e556fd25e903107a57827c21f6ee8a93a4ff55b11311fcef217e3eefb07e81f71e88216f43b4b54029c1f2549f2925a839a73947d2d5aeecec4a62ece4af9156d557ae907978298296d9915</ec2_encrypted_key><user_encrypted_key algorithm="AES-128-CBC">4c11147fd8caf92447e90ce339928933d7579244c2f8ffb07cc0ea35f8738da8b90eff6c7a49671a84500e993e9462e4c36d5c19c0b3a2b397d035b4c0cce742b58e12552175d81d129b0425e9f71ebacb9aeb539fa9dd2ac36749fb82876f6902e5fb24b6ec19f35ec4c20acd50437fd30966e99c4d9a0647577970a8fa3023</user_encrypted_key><ec2_encrypted_iv>14bd082c9715f071160c69bbfb070f51d2ba1076775f1d988ccde150e515088156b248e4b5a64e46c4fe064feeeedfe14511f7fde478a51acb89f9b2f6c84b60593e5c3f792ba6b01fed9bf2158fdac03086374883b39d13a3ca74497eeaaf579fc3f26effc73bfd9446a2a8c4061f0874bfaca058905180e22d3d8881551cb3</ec2_encrypted_iv><user_encrypted_iv>8f7606f19f00e4e19535dd234b66b31b77e9c7bad3885d9c9efa75c863631fd4f82a009e17d789066d9cc6032a436f05384832f6d9a3283d3e63eab04fa0da5c8c87db9b17e854e842c3fb416507d067a266b44538125ce732e486098e8ebd1ca91fa3079f007fce7d14957a9b7e57282407ead3c6eb68fe975df3d83190021b</user_encrypted_iv><parts count="2"><part index="0"><filename>1mb.part.0</filename><digest algorithm="SHA1">c4413423cf7a57e71187e19bfd5cd4b514a64283</digest></part><part index="1"><filename>1mb.part.1</filename><digest algorithm="SHA1">9d4262e6589393d09a11a0332af169887bc2e57d</digest></part></parts></image><signature>4e00b5ba28114dda4a9df7eeae94be847ec46117a09a1cbe41e578660642f0660dda1776b39fb3bf826b6cfec019e2a5e9c566728d186b7400ebc989a30670eb1db26ce01e68bd9d3f31290370077a85b81c66b63c1e0d5499bac115c06c17a21a81b6d3a67ebbce6c17019095af7ab07f3796c708cc843e58efc12ddc788c5e</signature></manifest> |
2700 | \ No newline at end of file |
2701 | |
2702 | === added file 'tests/bundle/1mb.part.0' |
2703 | Binary files tests/bundle/1mb.part.0 1970-01-01 00:00:00 +0000 and tests/bundle/1mb.part.0 2010-07-23 03:41:08 +0000 differ |
2704 | === added file 'tests/bundle/1mb.part.1' |
2705 | --- tests/bundle/1mb.part.1 1970-01-01 00:00:00 +0000 |
2706 | +++ tests/bundle/1mb.part.1 2010-07-23 03:41:08 +0000 |
2707 | @@ -0,0 +1,1 @@ |
2708 | +´ˆà «€ç‰°Æ³ |
2709 | ¡ÀiDHW̽×JÈ8ïrV¼³h§X’·@Yj“~Ø |
2710 | ·Gû5û 3Nt«˜•H6Ñ$§Ëgö™é Lá¢+³æ¤X†pm¬@,øŽ>7ÚÊ×užp¼ aü`¥V2X@£#ᶠ|
2711 | \ No newline at end of file |
2712 | |
2713 | === added file 'tests/cloud_unittest.py' |
2714 | --- tests/cloud_unittest.py 1970-01-01 00:00:00 +0000 |
2715 | +++ tests/cloud_unittest.py 2010-07-23 03:41:08 +0000 |
2716 | @@ -0,0 +1,163 @@ |
2717 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
2718 | + |
2719 | +# Copyright 2010 United States Government as represented by the |
2720 | +# Administrator of the National Aeronautics and Space Administration. |
2721 | +# All Rights Reserved. |
2722 | +# |
2723 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
2724 | +# not use this file except in compliance with the License. You may obtain |
2725 | +# a copy of the License at |
2726 | +# |
2727 | +# http://www.apache.org/licenses/LICENSE-2.0 |
2728 | +# |
2729 | +# Unless required by applicable law or agreed to in writing, software |
2730 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
2731 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2732 | +# License for the specific language governing permissions and limitations |
2733 | +# under the License. |
2734 | + |
2735 | +import logging |
2736 | +import StringIO |
2737 | +import time |
2738 | +from tornado import ioloop |
2739 | +from twisted.internet import defer |
2740 | +import unittest |
2741 | +from xml.etree import ElementTree |
2742 | + |
2743 | +from nova import flags |
2744 | +from nova import rpc |
2745 | +from nova import test |
2746 | +from nova.auth import users |
2747 | +from nova.compute import node |
2748 | +from nova.endpoint import api |
2749 | +from nova.endpoint import cloud |
2750 | + |
2751 | + |
2752 | +FLAGS = flags.FLAGS |
2753 | + |
2754 | + |
2755 | +class CloudTestCase(test.BaseTestCase): |
2756 | + def setUp(self): |
2757 | + super(CloudTestCase, self).setUp() |
2758 | + self.flags(fake_libvirt=True, |
2759 | + fake_storage=True, |
2760 | + fake_users=True) |
2761 | + |
2762 | + self.conn = rpc.Connection.instance() |
2763 | + logging.getLogger().setLevel(logging.DEBUG) |
2764 | + |
2765 | + # set up our cloud |
2766 | + self.cloud = cloud.CloudController() |
2767 | + self.cloud_consumer = rpc.AdapterConsumer(connection=self.conn, |
2768 | + topic=FLAGS.cloud_topic, |
2769 | + proxy=self.cloud) |
2770 | + self.injected.append(self.cloud_consumer.attach_to_tornado(self.ioloop)) |
2771 | + |
2772 | + # set up a node |
2773 | + self.node = node.Node() |
2774 | + self.node_consumer = rpc.AdapterConsumer(connection=self.conn, |
2775 | + topic=FLAGS.compute_topic, |
2776 | + proxy=self.node) |
2777 | + self.injected.append(self.node_consumer.attach_to_tornado(self.ioloop)) |
2778 | + |
2779 | + try: |
2780 | + users.UserManager.instance().create_user('admin', 'admin', 'admin') |
2781 | + except: pass |
2782 | + admin = users.UserManager.instance().get_user('admin') |
2783 | + project = users.UserManager.instance().create_project('proj', 'admin', 'proj') |
2784 | + self.context = api.APIRequestContext(handler=None,project=project,user=admin) |
2785 | + |
2786 | + def tearDown(self): |
2787 | + users.UserManager.instance().delete_project('proj') |
2788 | + users.UserManager.instance().delete_user('admin') |
2789 | + |
2790 | + def test_console_output(self): |
2791 | + if FLAGS.fake_libvirt: |
2792 | + logging.debug("Can't test instances without a real virtual env.") |
2793 | + return |
2794 | + instance_id = 'foo' |
2795 | + inst = yield self.node.run_instance(instance_id) |
2796 | + output = yield self.cloud.get_console_output(self.context, [instance_id]) |
2797 | + logging.debug(output) |
2798 | + self.assert_(output) |
2799 | + rv = yield self.node.terminate_instance(instance_id) |
2800 | + |
2801 | + def test_run_instances(self): |
2802 | + if FLAGS.fake_libvirt: |
2803 | + logging.debug("Can't test instances without a real virtual env.") |
2804 | + return |
2805 | + image_id = FLAGS.default_image |
2806 | + instance_type = FLAGS.default_instance_type |
2807 | + max_count = 1 |
2808 | + kwargs = {'image_id': image_id, |
2809 | + 'instance_type': instance_type, |
2810 | + 'max_count': max_count} |
2811 | + rv = yield self.cloud.run_instances(self.context, **kwargs) |
2812 | + # TODO: check for proper response |
2813 | + instance = rv['reservationSet'][0][rv['reservationSet'][0].keys()[0]][0] |
2814 | + logging.debug("Need to watch instance %s until it's running..." % instance['instance_id']) |
2815 | + while True: |
2816 | + rv = yield defer.succeed(time.sleep(1)) |
2817 | + info = self.cloud._get_instance(instance['instance_id']) |
2818 | + logging.debug(info['state']) |
2819 | + if info['state'] == node.Instance.RUNNING: |
2820 | + break |
2821 | + self.assert_(rv) |
2822 | + |
2823 | + if not FLAGS.fake_libvirt: |
2824 | + time.sleep(45) # Should use boto for polling here |
2825 | + for reservations in rv['reservationSet']: |
2826 | + # for res_id in reservations.keys(): |
2827 | + # logging.debug(reservations[res_id]) |
2828 | + # for instance in reservations[res_id]: |
2829 | + for instance in reservations[reservations.keys()[0]]: |
2830 | + logging.debug("Terminating instance %s" % instance['instance_id']) |
2831 | + rv = yield self.node.terminate_instance(instance['instance_id']) |
2832 | + |
2833 | + def test_instance_update_state(self): |
2834 | + def instance(num): |
2835 | + return { |
2836 | + 'reservation_id': 'r-1', |
2837 | + 'instance_id': 'i-%s' % num, |
2838 | + 'image_id': 'ami-%s' % num, |
2839 | + 'private_dns_name': '10.0.0.%s' % num, |
2840 | + 'dns_name': '10.0.0%s' % num, |
2841 | + 'ami_launch_index': str(num), |
2842 | + 'instance_type': 'fake', |
2843 | + 'availability_zone': 'fake', |
2844 | + 'key_name': None, |
2845 | + 'kernel_id': 'fake', |
2846 | + 'ramdisk_id': 'fake', |
2847 | + 'groups': ['default'], |
2848 | + 'product_codes': None, |
2849 | + 'state': 0x01, |
2850 | + 'user_data': '' |
2851 | + } |
2852 | + rv = self.cloud._format_instances(self.context) |
2853 | + self.assert_(len(rv['reservationSet']) == 0) |
2854 | + |
2855 | + # simulate launch of 5 instances |
2856 | + # self.cloud.instances['pending'] = {} |
2857 | + #for i in xrange(5): |
2858 | + # inst = instance(i) |
2859 | + # self.cloud.instances['pending'][inst['instance_id']] = inst |
2860 | + |
2861 | + #rv = self.cloud._format_instances(self.admin) |
2862 | + #self.assert_(len(rv['reservationSet']) == 1) |
2863 | + #self.assert_(len(rv['reservationSet'][0]['instances_set']) == 5) |
2864 | + # report 4 nodes each having 1 of the instances |
2865 | + #for i in xrange(4): |
2866 | + # self.cloud.update_state('instances', {('node-%s' % i): {('i-%s' % i): instance(i)}}) |
2867 | + |
2868 | + # one instance should be pending still |
2869 | + #self.assert_(len(self.cloud.instances['pending'].keys()) == 1) |
2870 | + |
2871 | + # check that the reservations collapse |
2872 | + #rv = self.cloud._format_instances(self.admin) |
2873 | + #self.assert_(len(rv['reservationSet']) == 1) |
2874 | + #self.assert_(len(rv['reservationSet'][0]['instances_set']) == 5) |
2875 | + |
2876 | + # check that we can get metadata for each instance |
2877 | + #for i in xrange(4): |
2878 | + # data = self.cloud.get_metadata(instance(i)['private_dns_name']) |
2879 | + # self.assert_(data['meta-data']['ami-id'] == 'ami-%s' % i) |
2880 | |
2881 | === added file 'tests/fake_flags.py' |
2882 | --- tests/fake_flags.py 1970-01-01 00:00:00 +0000 |
2883 | +++ tests/fake_flags.py 2010-07-23 03:41:08 +0000 |
2884 | @@ -0,0 +1,28 @@ |
2885 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
2886 | + |
2887 | +# Copyright 2010 United States Government as represented by the |
2888 | +# Administrator of the National Aeronautics and Space Administration. |
2889 | +# All Rights Reserved. |
2890 | +# |
2891 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
2892 | +# not use this file except in compliance with the License. You may obtain |
2893 | +# a copy of the License at |
2894 | +# |
2895 | +# http://www.apache.org/licenses/LICENSE-2.0 |
2896 | +# |
2897 | +# Unless required by applicable law or agreed to in writing, software |
2898 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
2899 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2900 | +# License for the specific language governing permissions and limitations |
2901 | +# under the License. |
2902 | + |
2903 | +from nova import flags |
2904 | + |
2905 | +FLAGS = flags.FLAGS |
2906 | + |
2907 | +FLAGS.fake_libvirt = True |
2908 | +FLAGS.fake_storage = True |
2909 | +FLAGS.fake_rabbit = True |
2910 | +FLAGS.fake_network = True |
2911 | +FLAGS.fake_users = True |
2912 | +FLAGS.verbose = True |
2913 | |
2914 | === added file 'tests/future_unittest.py' |
2915 | --- tests/future_unittest.py 1970-01-01 00:00:00 +0000 |
2916 | +++ tests/future_unittest.py 2010-07-23 03:41:08 +0000 |
2917 | @@ -0,0 +1,75 @@ |
2918 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
2919 | + |
2920 | +# Copyright 2010 United States Government as represented by the |
2921 | +# Administrator of the National Aeronautics and Space Administration. |
2922 | +# All Rights Reserved. |
2923 | +# |
2924 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
2925 | +# not use this file except in compliance with the License. You may obtain |
2926 | +# a copy of the License at |
2927 | +# |
2928 | +# http://www.apache.org/licenses/LICENSE-2.0 |
2929 | +# |
2930 | +# Unless required by applicable law or agreed to in writing, software |
2931 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
2932 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2933 | +# License for the specific language governing permissions and limitations |
2934 | +# under the License. |
2935 | + |
2936 | +import logging |
2937 | +import mox |
2938 | +import StringIO |
2939 | +import time |
2940 | +from tornado import ioloop |
2941 | +from twisted.internet import defer |
2942 | +import unittest |
2943 | +from xml.etree import ElementTree |
2944 | + |
2945 | +from nova import cloud |
2946 | +from nova import exception |
2947 | +from nova import flags |
2948 | +from nova import node |
2949 | +from nova import rpc |
2950 | +from nova import test |
2951 | + |
2952 | + |
2953 | +FLAGS = flags.FLAGS |
2954 | + |
2955 | + |
2956 | +class AdminTestCase(test.BaseTestCase): |
2957 | + def setUp(self): |
2958 | + super(AdminTestCase, self).setUp() |
2959 | + self.flags(fake_libvirt=True, |
2960 | + fake_rabbit=True) |
2961 | + |
2962 | + self.conn = rpc.Connection.instance() |
2963 | + |
2964 | + logging.getLogger().setLevel(logging.INFO) |
2965 | + |
2966 | + # set up our cloud |
2967 | + self.cloud = cloud.CloudController() |
2968 | + self.cloud_consumer = rpc.AdapterConsumer(connection=self.conn, |
2969 | + topic=FLAGS.cloud_topic, |
2970 | + proxy=self.cloud) |
2971 | + self.injected.append(self.cloud_consumer.attach_to_tornado(self.ioloop)) |
2972 | + |
2973 | + # set up a node |
2974 | + self.node = node.Node() |
2975 | + self.node_consumer = rpc.AdapterConsumer(connection=self.conn, |
2976 | + topic=FLAGS.compute_topic, |
2977 | + proxy=self.node) |
2978 | + self.injected.append(self.node_consumer.attach_to_tornado(self.ioloop)) |
2979 | + |
2980 | + def test_flush_terminated(self): |
2981 | + # Launch an instance |
2982 | + |
2983 | + # Wait until it's running |
2984 | + |
2985 | + # Terminate it |
2986 | + |
2987 | + # Wait until it's terminated |
2988 | + |
2989 | + # Flush terminated nodes |
2990 | + |
2991 | + # ASSERT that it's gone |
2992 | + pass |
2993 | |
2994 | === added file 'tests/model_unittest.py' |
2995 | --- tests/model_unittest.py 1970-01-01 00:00:00 +0000 |
2996 | +++ tests/model_unittest.py 2010-07-23 03:41:08 +0000 |
2997 | @@ -0,0 +1,206 @@ |
2998 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
2999 | + |
3000 | +# Copyright 2010 United States Government as represented by the |
3001 | +# Administrator of the National Aeronautics and Space Administration. |
3002 | +# All Rights Reserved. |
3003 | +# |
3004 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
3005 | +# not use this file except in compliance with the License. You may obtain |
3006 | +# a copy of the License at |
3007 | +# |
3008 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3009 | +# |
3010 | +# Unless required by applicable law or agreed to in writing, software |
3011 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
3012 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3013 | +# License for the specific language governing permissions and limitations |
3014 | +# under the License. |
3015 | + |
3016 | +import logging |
3017 | +import time |
3018 | +from twisted.internet import defer |
3019 | + |
3020 | +from nova import exception |
3021 | +from nova import flags |
3022 | +from nova import test |
3023 | +from nova import utils |
3024 | +from nova.compute import model |
3025 | +from nova.compute import node |
3026 | + |
3027 | + |
3028 | +FLAGS = flags.FLAGS |
3029 | + |
3030 | + |
3031 | +class ModelTestCase(test.TrialTestCase): |
3032 | + def setUp(self): |
3033 | + super(ModelTestCase, self).setUp() |
3034 | + self.flags(fake_libvirt=True, |
3035 | + fake_storage=True, |
3036 | + fake_users=True) |
3037 | + |
3038 | + def tearDown(self): |
3039 | + model.Instance('i-test').destroy() |
3040 | + model.Host('testhost').destroy() |
3041 | + model.Daemon('testhost', 'nova-testdaemon').destroy() |
3042 | + |
3043 | + def create_instance(self): |
3044 | + inst = model.Instance('i-test') |
3045 | + inst['reservation_id'] = 'r-test' |
3046 | + inst['launch_time'] = '10' |
3047 | + inst['user_id'] = 'fake' |
3048 | + inst['project_id'] = 'fake' |
3049 | + inst['instance_type'] = 'm1.tiny' |
3050 | + inst['node_name'] = FLAGS.node_name |
3051 | + inst['mac_address'] = utils.generate_mac() |
3052 | + inst['ami_launch_index'] = 0 |
3053 | + inst.save() |
3054 | + return inst |
3055 | + |
3056 | + def create_host(self): |
3057 | + host = model.Host('testhost') |
3058 | + host.save() |
3059 | + return host |
3060 | + |
3061 | + def create_daemon(self): |
3062 | + daemon = model.Daemon('testhost', 'nova-testdaemon') |
3063 | + daemon.save() |
3064 | + return daemon |
3065 | + |
3066 | + @defer.inlineCallbacks |
3067 | + def test_create_instance(self): |
3068 | + """store with create_instace, then test that a load finds it""" |
3069 | + instance = yield self.create_instance() |
3070 | + old = yield model.Instance(instance.identifier) |
3071 | + self.assertFalse(old.is_new_record()) |
3072 | + |
3073 | + @defer.inlineCallbacks |
3074 | + def test_delete_instance(self): |
3075 | + """create, then destroy, then make sure loads a new record""" |
3076 | + instance = yield self.create_instance() |
3077 | + yield instance.destroy() |
3078 | + newinst = yield model.Instance('i-test') |
3079 | + self.assertTrue(newinst.is_new_record()) |
3080 | + |
3081 | + @defer.inlineCallbacks |
3082 | + def test_instance_added_to_set(self): |
3083 | + """create, then check that it is listed for the project""" |
3084 | + instance = yield self.create_instance() |
3085 | + found = False |
3086 | + for x in model.InstanceDirectory().all: |
3087 | + if x.identifier == 'i-test': |
3088 | + found = True |
3089 | + self.assert_(found) |
3090 | + |
3091 | + @defer.inlineCallbacks |
3092 | + def test_instance_associates_project(self): |
3093 | + """create, then check that it is listed for the project""" |
3094 | + instance = yield self.create_instance() |
3095 | + found = False |
3096 | + for x in model.InstanceDirectory().by_project(instance.project): |
3097 | + if x.identifier == 'i-test': |
3098 | + found = True |
3099 | + self.assert_(found) |
3100 | + |
3101 | + @defer.inlineCallbacks |
3102 | + def test_host_class_finds_hosts(self): |
3103 | + host = yield self.create_host() |
3104 | + self.assertEqual('testhost', model.Host.lookup('testhost').identifier) |
3105 | + |
3106 | + @defer.inlineCallbacks |
3107 | + def test_host_class_doesnt_find_missing_hosts(self): |
3108 | + rv = yield model.Host.lookup('woahnelly') |
3109 | + self.assertEqual(None, rv) |
3110 | + |
3111 | + @defer.inlineCallbacks |
3112 | + def test_create_host(self): |
3113 | + """store with create_host, then test that a load finds it""" |
3114 | + host = yield self.create_host() |
3115 | + old = yield model.Host(host.identifier) |
3116 | + self.assertFalse(old.is_new_record()) |
3117 | + |
3118 | + @defer.inlineCallbacks |
3119 | + def test_delete_host(self): |
3120 | + """create, then destroy, then make sure loads a new record""" |
3121 | + instance = yield self.create_host() |
3122 | + yield instance.destroy() |
3123 | + newinst = yield model.Host('testhost') |
3124 | + self.assertTrue(newinst.is_new_record()) |
3125 | + |
3126 | + @defer.inlineCallbacks |
3127 | + def test_host_added_to_set(self): |
3128 | + """create, then check that it is included in list""" |
3129 | + instance = yield self.create_host() |
3130 | + found = False |
3131 | + for x in model.Host.all(): |
3132 | + if x.identifier == 'testhost': |
3133 | + found = True |
3134 | + self.assert_(found) |
3135 | + |
3136 | + @defer.inlineCallbacks |
3137 | + def test_create_daemon_two_args(self): |
3138 | + """create a daemon with two arguments""" |
3139 | + d = yield self.create_daemon() |
3140 | + d = model.Daemon('testhost', 'nova-testdaemon') |
3141 | + self.assertFalse(d.is_new_record()) |
3142 | + |
3143 | + @defer.inlineCallbacks |
3144 | + def test_create_daemon_single_arg(self): |
3145 | + """Create a daemon using the combined host:bin format""" |
3146 | + d = yield model.Daemon("testhost:nova-testdaemon") |
3147 | + d.save() |
3148 | + d = model.Daemon('testhost:nova-testdaemon') |
3149 | + self.assertFalse(d.is_new_record()) |
3150 | + |
3151 | + @defer.inlineCallbacks |
3152 | + def test_equality_of_daemon_single_and_double_args(self): |
3153 | + """Create a daemon using the combined host:bin arg, find with 2""" |
3154 | + d = yield model.Daemon("testhost:nova-testdaemon") |
3155 | + d.save() |
3156 | + d = model.Daemon('testhost', 'nova-testdaemon') |
3157 | + self.assertFalse(d.is_new_record()) |
3158 | + |
3159 | + @defer.inlineCallbacks |
3160 | + def test_equality_daemon_of_double_and_single_args(self): |
3161 | + """Create a daemon using the combined host:bin arg, find with 2""" |
3162 | + d = yield self.create_daemon() |
3163 | + d = model.Daemon('testhost:nova-testdaemon') |
3164 | + self.assertFalse(d.is_new_record()) |
3165 | + |
3166 | + @defer.inlineCallbacks |
3167 | + def test_delete_daemon(self): |
3168 | + """create, then destroy, then make sure loads a new record""" |
3169 | + instance = yield self.create_daemon() |
3170 | + yield instance.destroy() |
3171 | + newinst = yield model.Daemon('testhost', 'nova-testdaemon') |
3172 | + self.assertTrue(newinst.is_new_record()) |
3173 | + |
3174 | + @defer.inlineCallbacks |
3175 | + def test_daemon_heartbeat(self): |
3176 | + """Create a daemon, sleep, heartbeat, check for update""" |
3177 | + d = yield self.create_daemon() |
3178 | + ts = d['updated_at'] |
3179 | + time.sleep(2) |
3180 | + d.heartbeat() |
3181 | + d2 = model.Daemon('testhost', 'nova-testdaemon') |
3182 | + ts2 = d2['updated_at'] |
3183 | + self.assert_(ts2 > ts) |
3184 | + |
3185 | + @defer.inlineCallbacks |
3186 | + def test_daemon_added_to_set(self): |
3187 | + """create, then check that it is included in list""" |
3188 | + instance = yield self.create_daemon() |
3189 | + found = False |
3190 | + for x in model.Daemon.all(): |
3191 | + if x.identifier == 'testhost:nova-testdaemon': |
3192 | + found = True |
3193 | + self.assert_(found) |
3194 | + |
3195 | + @defer.inlineCallbacks |
3196 | + def test_daemon_associates_host(self): |
3197 | + """create, then check that it is listed for the host""" |
3198 | + instance = yield self.create_daemon() |
3199 | + found = False |
3200 | + for x in model.Daemon.by_host('testhost'): |
3201 | + if x.identifier == 'testhost:nova-testdaemon': |
3202 | + found = True |
3203 | + self.assertTrue(found) |
3204 | |
3205 | === added file 'tests/network_unittest.py' |
3206 | --- tests/network_unittest.py 1970-01-01 00:00:00 +0000 |
3207 | +++ tests/network_unittest.py 2010-07-23 03:41:08 +0000 |
3208 | @@ -0,0 +1,219 @@ |
3209 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
3210 | + |
3211 | +# Copyright 2010 United States Government as represented by the |
3212 | +# Administrator of the National Aeronautics and Space Administration. |
3213 | +# All Rights Reserved. |
3214 | +# |
3215 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
3216 | +# not use this file except in compliance with the License. You may obtain |
3217 | +# a copy of the License at |
3218 | +# |
3219 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3220 | +# |
3221 | +# Unless required by applicable law or agreed to in writing, software |
3222 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
3223 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3224 | +# License for the specific language governing permissions and limitations |
3225 | +# under the License. |
3226 | + |
3227 | +import IPy |
3228 | +import os |
3229 | +import logging |
3230 | + |
3231 | +from nova import flags |
3232 | +from nova import test |
3233 | +from nova import utils |
3234 | +from nova.auth import users |
3235 | +from nova.compute import network |
3236 | +from nova.compute.exception import NoMoreAddresses |
3237 | + |
3238 | +FLAGS = flags.FLAGS |
3239 | + |
3240 | +class NetworkTestCase(test.TrialTestCase): |
3241 | + def setUp(self): |
3242 | + super(NetworkTestCase, self).setUp() |
3243 | + self.flags(fake_libvirt=True, |
3244 | + fake_storage=True, |
3245 | + fake_network=True, |
3246 | + network_size=32) |
3247 | + logging.getLogger().setLevel(logging.DEBUG) |
3248 | + self.manager = users.UserManager.instance() |
3249 | + self.dnsmasq = FakeDNSMasq() |
3250 | + try: |
3251 | + self.manager.create_user('netuser', 'netuser', 'netuser') |
3252 | + except: pass |
3253 | + for i in range(0, 6): |
3254 | + name = 'project%s' % i |
3255 | + if not self.manager.get_project(name): |
3256 | + self.manager.create_project(name, 'netuser', name) |
3257 | + self.network = network.PublicNetworkController() |
3258 | + |
3259 | + def tearDown(self): |
3260 | + super(NetworkTestCase, self).tearDown() |
3261 | + for i in range(0, 6): |
3262 | + name = 'project%s' % i |
3263 | + self.manager.delete_project(name) |
3264 | + self.manager.delete_user('netuser') |
3265 | + |
3266 | + def test_public_network_allocation(self): |
3267 | + pubnet = IPy.IP(flags.FLAGS.public_range) |
3268 | + address = self.network.allocate_ip("netuser", "project0", "public") |
3269 | + self.assertTrue(IPy.IP(address) in pubnet) |
3270 | + self.assertTrue(IPy.IP(address) in self.network.network) |
3271 | + |
3272 | + def test_allocate_deallocate_ip(self): |
3273 | + address = network.allocate_ip( |
3274 | + "netuser", "project0", utils.generate_mac()) |
3275 | + logging.debug("Was allocated %s" % (address)) |
3276 | + net = network.get_project_network("project0", "default") |
3277 | + self.assertEqual(True, is_in_project(address, "project0")) |
3278 | + mac = utils.generate_mac() |
3279 | + hostname = "test-host" |
3280 | + self.dnsmasq.issue_ip(mac, address, hostname, net.bridge_name) |
3281 | + rv = network.deallocate_ip(address) |
3282 | + |
3283 | + # Doesn't go away until it's dhcp released |
3284 | + self.assertEqual(True, is_in_project(address, "project0")) |
3285 | + |
3286 | + self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name) |
3287 | + self.assertEqual(False, is_in_project(address, "project0")) |
3288 | + |
3289 | + def test_range_allocation(self): |
3290 | + mac = utils.generate_mac() |
3291 | + secondmac = utils.generate_mac() |
3292 | + hostname = "test-host" |
3293 | + address = network.allocate_ip( |
3294 | + "netuser", "project0", mac) |
3295 | + secondaddress = network.allocate_ip( |
3296 | + "netuser", "project1", secondmac) |
3297 | + net = network.get_project_network("project0", "default") |
3298 | + secondnet = network.get_project_network("project1", "default") |
3299 | + |
3300 | + self.assertEqual(True, is_in_project(address, "project0")) |
3301 | + self.assertEqual(True, is_in_project(secondaddress, "project1")) |
3302 | + self.assertEqual(False, is_in_project(address, "project1")) |
3303 | + |
3304 | + # Addresses are allocated before they're issued |
3305 | + self.dnsmasq.issue_ip(mac, address, hostname, net.bridge_name) |
3306 | + self.dnsmasq.issue_ip(secondmac, secondaddress, |
3307 | + hostname, secondnet.bridge_name) |
3308 | + |
3309 | + rv = network.deallocate_ip(address) |
3310 | + self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name) |
3311 | + self.assertEqual(False, is_in_project(address, "project0")) |
3312 | + |
3313 | + # First address release shouldn't affect the second |
3314 | + self.assertEqual(True, is_in_project(secondaddress, "project1")) |
3315 | + |
3316 | + rv = network.deallocate_ip(secondaddress) |
3317 | + self.dnsmasq.release_ip(secondmac, secondaddress, |
3318 | + hostname, secondnet.bridge_name) |
3319 | + self.assertEqual(False, is_in_project(secondaddress, "project1")) |
3320 | + |
3321 | + def test_subnet_edge(self): |
3322 | + secondaddress = network.allocate_ip("netuser", "project0", |
3323 | + utils.generate_mac()) |
3324 | + hostname = "toomany-hosts" |
3325 | + for project in range(1,5): |
3326 | + project_id = "project%s" % (project) |
3327 | + mac = utils.generate_mac() |
3328 | + mac2 = utils.generate_mac() |
3329 | + mac3 = utils.generate_mac() |
3330 | + address = network.allocate_ip( |
3331 | + "netuser", project_id, mac) |
3332 | + address2 = network.allocate_ip( |
3333 | + "netuser", project_id, mac2) |
3334 | + address3 = network.allocate_ip( |
3335 | + "netuser", project_id, mac3) |
3336 | + self.assertEqual(False, is_in_project(address, "project0")) |
3337 | + self.assertEqual(False, is_in_project(address2, "project0")) |
3338 | + self.assertEqual(False, is_in_project(address3, "project0")) |
3339 | + rv = network.deallocate_ip(address) |
3340 | + rv = network.deallocate_ip(address2) |
3341 | + rv = network.deallocate_ip(address3) |
3342 | + net = network.get_project_network(project_id, "default") |
3343 | + self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name) |
3344 | + self.dnsmasq.release_ip(mac2, address2, hostname, net.bridge_name) |
3345 | + self.dnsmasq.release_ip(mac3, address3, hostname, net.bridge_name) |
3346 | + net = network.get_project_network("project0", "default") |
3347 | + rv = network.deallocate_ip(secondaddress) |
3348 | + self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name) |
3349 | + |
3350 | + def test_release_before_deallocate(self): |
3351 | + pass |
3352 | + |
3353 | + def test_deallocate_before_issued(self): |
3354 | + pass |
3355 | + |
3356 | + def test_too_many_addresses(self): |
3357 | + """ |
3358 | + Here, we test that a proper NoMoreAddresses exception is raised. |
3359 | + |
3360 | + However, the number of available IP addresses depends on the test |
3361 | + environment's setup. |
3362 | + |
3363 | + Network size is set in test fixture's setUp method. |
3364 | + |
3365 | + There are FLAGS.cnt_vpn_clients addresses reserved for VPN (NUM_RESERVED_VPN_IPS) |
3366 | + |
3367 | + And there are NUM_STATIC_IPS that are always reserved by Nova for the necessary |
3368 | + services (gateway, CloudPipe, etc) |
3369 | + |
3370 | + So we should get flags.network_size - (NUM_STATIC_IPS + |
3371 | + NUM_PREALLOCATED_IPS + |
3372 | + NUM_RESERVED_VPN_IPS) |
3373 | + usable addresses |
3374 | + """ |
3375 | + net = network.get_project_network("project0", "default") |
3376 | + |
3377 | + # Determine expected number of available IP addresses |
3378 | + num_static_ips = net.num_static_ips |
3379 | + num_preallocated_ips = len(net.hosts.keys()) |
3380 | + num_reserved_vpn_ips = flags.FLAGS.cnt_vpn_clients |
3381 | + num_available_ips = flags.FLAGS.network_size - (num_static_ips + num_preallocated_ips + num_reserved_vpn_ips) |
3382 | + |
3383 | + hostname = "toomany-hosts" |
3384 | + macs = {} |
3385 | + addresses = {} |
3386 | + for i in range(0, (num_available_ips - 1)): |
3387 | + macs[i] = utils.generate_mac() |
3388 | + addresses[i] = network.allocate_ip("netuser", "project0", macs[i]) |
3389 | + self.dnsmasq.issue_ip(macs[i], addresses[i], hostname, net.bridge_name) |
3390 | + |
3391 | + self.assertRaises(NoMoreAddresses, network.allocate_ip, "netuser", "project0", utils.generate_mac()) |
3392 | + |
3393 | + for i in range(0, (num_available_ips - 1)): |
3394 | + rv = network.deallocate_ip(addresses[i]) |
3395 | + self.dnsmasq.release_ip(macs[i], addresses[i], hostname, net.bridge_name) |
3396 | + |
3397 | +def is_in_project(address, project_id): |
3398 | + return address in network.get_project_network(project_id).list_addresses() |
3399 | + |
3400 | +def _get_project_addresses(project_id): |
3401 | + project_addresses = [] |
3402 | + for addr in network.get_project_network(project_id).list_addresses(): |
3403 | + project_addresses.append(addr) |
3404 | + return project_addresses |
3405 | + |
3406 | +def binpath(script): |
3407 | + return os.path.join(utils.abspath("../bin"), script) |
3408 | + |
3409 | +class FakeDNSMasq(object): |
3410 | + def issue_ip(self, mac, ip, hostname, interface): |
3411 | + cmd = "%s add %s %s %s" % (binpath('nova-dhcpbridge'), |
3412 | + mac, ip, hostname) |
3413 | + env = {'DNSMASQ_INTERFACE': interface, |
3414 | + 'TESTING' : '1', |
3415 | + 'FLAGFILE' : FLAGS.dhcpbridge_flagfile} |
3416 | + (out, err) = utils.execute(cmd, addl_env=env) |
3417 | + logging.debug("ISSUE_IP: %s, %s " % (out, err)) |
3418 | + |
3419 | + def release_ip(self, mac, ip, hostname, interface): |
3420 | + cmd = "%s del %s %s %s" % (binpath('nova-dhcpbridge'), |
3421 | + mac, ip, hostname) |
3422 | + env = {'DNSMASQ_INTERFACE': interface, |
3423 | + 'TESTING' : '1', |
3424 | + 'FLAGFILE' : FLAGS.dhcpbridge_flagfile} |
3425 | + (out, err) = utils.execute(cmd, addl_env=env) |
3426 | + logging.debug("RELEASE_IP: %s, %s " % (out, err)) |
3427 | + |
3428 | |
3429 | === added file 'tests/node_unittest.py' |
3430 | --- tests/node_unittest.py 1970-01-01 00:00:00 +0000 |
3431 | +++ tests/node_unittest.py 2010-07-23 03:41:08 +0000 |
3432 | @@ -0,0 +1,128 @@ |
3433 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
3434 | + |
3435 | +# Copyright 2010 United States Government as represented by the |
3436 | +# Administrator of the National Aeronautics and Space Administration. |
3437 | +# All Rights Reserved. |
3438 | +# |
3439 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
3440 | +# not use this file except in compliance with the License. You may obtain |
3441 | +# a copy of the License at |
3442 | +# |
3443 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3444 | +# |
3445 | +# Unless required by applicable law or agreed to in writing, software |
3446 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
3447 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3448 | +# License for the specific language governing permissions and limitations |
3449 | +# under the License. |
3450 | + |
3451 | +import logging |
3452 | +import time |
3453 | +from twisted.internet import defer |
3454 | +from xml.etree import ElementTree |
3455 | + |
3456 | +from nova import exception |
3457 | +from nova import flags |
3458 | +from nova import test |
3459 | +from nova import utils |
3460 | +from nova.compute import model |
3461 | +from nova.compute import node |
3462 | + |
3463 | + |
3464 | +FLAGS = flags.FLAGS |
3465 | + |
3466 | + |
3467 | +class InstanceXmlTestCase(test.TrialTestCase): |
3468 | + # @defer.inlineCallbacks |
3469 | + def test_serialization(self): |
3470 | + # TODO: Reimplement this, it doesn't make sense in redis-land |
3471 | + return |
3472 | + |
3473 | + # instance_id = 'foo' |
3474 | + # first_node = node.Node() |
3475 | + # inst = yield first_node.run_instance(instance_id) |
3476 | + # |
3477 | + # # force the state so that we can verify that it changes |
3478 | + # inst._s['state'] = node.Instance.NOSTATE |
3479 | + # xml = inst.toXml() |
3480 | + # self.assert_(ElementTree.parse(StringIO.StringIO(xml))) |
3481 | + # |
3482 | + # second_node = node.Node() |
3483 | + # new_inst = node.Instance.fromXml(second_node._conn, pool=second_node._pool, xml=xml) |
3484 | + # self.assertEqual(new_inst.state, node.Instance.RUNNING) |
3485 | + # rv = yield first_node.terminate_instance(instance_id) |
3486 | + |
3487 | + |
3488 | +class NodeConnectionTestCase(test.TrialTestCase): |
3489 | + def setUp(self): |
3490 | + logging.getLogger().setLevel(logging.DEBUG) |
3491 | + super(NodeConnectionTestCase, self).setUp() |
3492 | + self.flags(fake_libvirt=True, |
3493 | + fake_storage=True, |
3494 | + fake_users=True) |
3495 | + self.node = node.Node() |
3496 | + |
3497 | + def create_instance(self): |
3498 | + instdir = model.InstanceDirectory() |
3499 | + inst = instdir.new() |
3500 | + # TODO(ja): add ami, ari, aki, user_data |
3501 | + inst['reservation_id'] = 'r-fakeres' |
3502 | + inst['launch_time'] = '10' |
3503 | + inst['user_id'] = 'fake' |
3504 | + inst['project_id'] = 'fake' |
3505 | + inst['instance_type'] = 'm1.tiny' |
3506 | + inst['node_name'] = FLAGS.node_name |
3507 | + inst['mac_address'] = utils.generate_mac() |
3508 | + inst['ami_launch_index'] = 0 |
3509 | + inst.save() |
3510 | + return inst['instance_id'] |
3511 | + |
3512 | + @defer.inlineCallbacks |
3513 | + def test_run_describe_terminate(self): |
3514 | + instance_id = self.create_instance() |
3515 | + |
3516 | + rv = yield self.node.run_instance(instance_id) |
3517 | + |
3518 | + rv = yield self.node.describe_instances() |
3519 | + logging.info("Running instances: %s", rv) |
3520 | + self.assertEqual(rv[instance_id].name, instance_id) |
3521 | + |
3522 | + rv = yield self.node.terminate_instance(instance_id) |
3523 | + |
3524 | + rv = yield self.node.describe_instances() |
3525 | + logging.info("After terminating instances: %s", rv) |
3526 | + self.assertEqual(rv, {}) |
3527 | + |
3528 | + @defer.inlineCallbacks |
3529 | + def test_reboot(self): |
3530 | + instance_id = self.create_instance() |
3531 | + rv = yield self.node.run_instance(instance_id) |
3532 | + |
3533 | + rv = yield self.node.describe_instances() |
3534 | + self.assertEqual(rv[instance_id].name, instance_id) |
3535 | + |
3536 | + yield self.node.reboot_instance(instance_id) |
3537 | + |
3538 | + rv = yield self.node.describe_instances() |
3539 | + self.assertEqual(rv[instance_id].name, instance_id) |
3540 | + rv = yield self.node.terminate_instance(instance_id) |
3541 | + |
3542 | + @defer.inlineCallbacks |
3543 | + def test_console_output(self): |
3544 | + instance_id = self.create_instance() |
3545 | + rv = yield self.node.run_instance(instance_id) |
3546 | + |
3547 | + console = yield self.node.get_console_output(instance_id) |
3548 | + self.assert_(console) |
3549 | + rv = yield self.node.terminate_instance(instance_id) |
3550 | + |
3551 | + @defer.inlineCallbacks |
3552 | + def test_run_instance_existing(self): |
3553 | + instance_id = self.create_instance() |
3554 | + rv = yield self.node.run_instance(instance_id) |
3555 | + |
3556 | + rv = yield self.node.describe_instances() |
3557 | + self.assertEqual(rv[instance_id].name, instance_id) |
3558 | + |
3559 | + self.assertRaises(exception.Error, self.node.run_instance, instance_id) |
3560 | + rv = yield self.node.terminate_instance(instance_id) |
3561 | |
3562 | === added file 'tests/objectstore_unittest.py' |
3563 | --- tests/objectstore_unittest.py 1970-01-01 00:00:00 +0000 |
3564 | +++ tests/objectstore_unittest.py 2010-07-23 03:41:08 +0000 |
3565 | @@ -0,0 +1,203 @@ |
3566 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
3567 | + |
3568 | +# Copyright 2010 United States Government as represented by the |
3569 | +# Administrator of the National Aeronautics and Space Administration. |
3570 | +# All Rights Reserved. |
3571 | +# |
3572 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
3573 | +# not use this file except in compliance with the License. You may obtain |
3574 | +# a copy of the License at |
3575 | +# |
3576 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3577 | +# |
3578 | +# Unless required by applicable law or agreed to in writing, software |
3579 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
3580 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3581 | +# License for the specific language governing permissions and limitations |
3582 | +# under the License. |
3583 | + |
3584 | +import glob |
3585 | +import hashlib |
3586 | +import logging |
3587 | +import os |
3588 | +import shutil |
3589 | +import tempfile |
3590 | + |
3591 | +from nova import flags |
3592 | +from nova import objectstore |
3593 | +from nova import test |
3594 | +from nova.auth import users |
3595 | + |
3596 | + |
3597 | +FLAGS = flags.FLAGS |
3598 | + |
3599 | +oss_tempdir = tempfile.mkdtemp(prefix='test_oss-') |
3600 | + |
3601 | + |
3602 | +# delete tempdirs from previous runs (we don't delete after test to allow |
3603 | +# checking the contents after running tests) |
3604 | +# TODO: This fails on the test box with a permission denied error |
3605 | +# Also, doing these things in a global tempdir means that different runs of |
3606 | +# the test suite on the same box could clobber each other. |
3607 | +#for path in glob.glob(os.path.abspath(os.path.join(oss_tempdir, '../test_oss-*'))): |
3608 | +# if path != oss_tempdir: |
3609 | +# shutil.rmtree(path) |
3610 | + |
3611 | + |
3612 | +# create bucket/images path |
3613 | +os.makedirs(os.path.join(oss_tempdir, 'images')) |
3614 | +os.makedirs(os.path.join(oss_tempdir, 'buckets')) |
3615 | + |
3616 | +class ObjectStoreTestCase(test.BaseTestCase): |
3617 | + def setUp(self): |
3618 | + super(ObjectStoreTestCase, self).setUp() |
3619 | + self.flags(fake_users=True, |
3620 | + buckets_path=os.path.join(oss_tempdir, 'buckets'), |
3621 | + images_path=os.path.join(oss_tempdir, 'images'), |
3622 | + ca_path=os.path.join(os.path.dirname(__file__), 'CA')) |
3623 | + logging.getLogger().setLevel(logging.DEBUG) |
3624 | + |
3625 | + self.um = users.UserManager.instance() |
3626 | + try: |
3627 | + self.um.create_user('user1') |
3628 | + except: pass |
3629 | + try: |
3630 | + self.um.create_user('user2') |
3631 | + except: pass |
3632 | + try: |
3633 | + self.um.create_user('admin_user', admin=True) |
3634 | + except: pass |
3635 | + try: |
3636 | + self.um.create_project('proj1', 'user1', 'a proj', ['user1']) |
3637 | + except: pass |
3638 | + try: |
3639 | + self.um.create_project('proj2', 'user2', 'a proj', ['user2']) |
3640 | + except: pass |
3641 | + class Context(object): pass |
3642 | + self.context = Context() |
3643 | + |
3644 | + def tearDown(self): |
3645 | + self.um.delete_project('proj1') |
3646 | + self.um.delete_project('proj2') |
3647 | + self.um.delete_user('user1') |
3648 | + self.um.delete_user('user2') |
3649 | + self.um.delete_user('admin_user') |
3650 | + super(ObjectStoreTestCase, self).tearDown() |
3651 | + |
3652 | + def test_buckets(self): |
3653 | + self.context.user = self.um.get_user('user1') |
3654 | + self.context.project = self.um.get_project('proj1') |
3655 | + objectstore.bucket.Bucket.create('new_bucket', self.context) |
3656 | + bucket = objectstore.bucket.Bucket('new_bucket') |
3657 | + |
3658 | + # creator is authorized to use bucket |
3659 | + self.assert_(bucket.is_authorized(self.context)) |
3660 | + |
3661 | + # another user is not authorized |
3662 | + self.context.user = self.um.get_user('user2') |
3663 | + self.context.project = self.um.get_project('proj2') |
3664 | + self.assert_(bucket.is_authorized(self.context) == False) |
3665 | + |
3666 | + # admin is authorized to use bucket |
3667 | + self.context.user = self.um.get_user('admin_user') |
3668 | + self.context.project = None |
3669 | + self.assert_(bucket.is_authorized(self.context)) |
3670 | + |
3671 | + # new buckets are empty |
3672 | + self.assert_(bucket.list_keys()['Contents'] == []) |
3673 | + |
3674 | + # storing keys works |
3675 | + bucket['foo'] = "bar" |
3676 | + |
3677 | + self.assert_(len(bucket.list_keys()['Contents']) == 1) |
3678 | + |
3679 | + self.assert_(bucket['foo'].read() == 'bar') |
3680 | + |
3681 | + # md5 of key works |
3682 | + self.assert_(bucket['foo'].md5 == hashlib.md5('bar').hexdigest()) |
3683 | + |
3684 | + # deleting non-empty bucket throws exception |
3685 | + exception = False |
3686 | + try: |
3687 | + bucket.delete() |
3688 | + except: |
3689 | + exception = True |
3690 | + |
3691 | + self.assert_(exception) |
3692 | + |
3693 | + # deleting key |
3694 | + del bucket['foo'] |
3695 | + |
3696 | + # deleting empty button |
3697 | + bucket.delete() |
3698 | + |
3699 | + # accessing deleted bucket throws exception |
3700 | + exception = False |
3701 | + try: |
3702 | + objectstore.bucket.Bucket('new_bucket') |
3703 | + except: |
3704 | + exception = True |
3705 | + |
3706 | + self.assert_(exception) |
3707 | + |
3708 | + def test_images(self): |
3709 | + self.context.user = self.um.get_user('user1') |
3710 | + self.context.project = self.um.get_project('proj1') |
3711 | + |
3712 | + # create a bucket for our bundle |
3713 | + objectstore.bucket.Bucket.create('image_bucket', self.context) |
3714 | + bucket = objectstore.bucket.Bucket('image_bucket') |
3715 | + |
3716 | + # upload an image manifest/parts |
3717 | + bundle_path = os.path.join(os.path.dirname(__file__), 'bundle') |
3718 | + for path in glob.glob(bundle_path + '/*'): |
3719 | + bucket[os.path.basename(path)] = open(path, 'rb').read() |
3720 | + |
3721 | + # register an image |
3722 | + objectstore.image.Image.register_aws_image('i-testing', 'image_bucket/1mb.manifest.xml', self.context) |
3723 | + |
3724 | + # verify image |
3725 | + my_img = objectstore.image.Image('i-testing') |
3726 | + result_image_file = os.path.join(my_img.path, 'image') |
3727 | + self.assertEqual(os.stat(result_image_file).st_size, 1048576) |
3728 | + |
3729 | + sha = hashlib.sha1(open(result_image_file).read()).hexdigest() |
3730 | + self.assertEqual(sha, '3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3') |
3731 | + |
3732 | + # verify image permissions |
3733 | + self.context.user = self.um.get_user('user2') |
3734 | + self.context.project = self.um.get_project('proj2') |
3735 | + self.assert_(my_img.is_authorized(self.context) == False) |
3736 | + |
3737 | +# class ApiObjectStoreTestCase(test.BaseTestCase): |
3738 | +# def setUp(self): |
3739 | +# super(ApiObjectStoreTestCase, self).setUp() |
3740 | +# FLAGS.fake_users = True |
3741 | +# FLAGS.buckets_path = os.path.join(tempdir, 'buckets') |
3742 | +# FLAGS.images_path = os.path.join(tempdir, 'images') |
3743 | +# FLAGS.ca_path = os.path.join(os.path.dirname(__file__), 'CA') |
3744 | +# |
3745 | +# self.users = users.UserManager.instance() |
3746 | +# self.app = handler.Application(self.users) |
3747 | +# |
3748 | +# self.host = '127.0.0.1' |
3749 | +# |
3750 | +# self.conn = boto.s3.connection.S3Connection( |
3751 | +# aws_access_key_id=user.access, |
3752 | +# aws_secret_access_key=user.secret, |
3753 | +# is_secure=False, |
3754 | +# calling_format=boto.s3.connection.OrdinaryCallingFormat(), |
3755 | +# port=FLAGS.s3_port, |
3756 | +# host=FLAGS.s3_host) |
3757 | +# |
3758 | +# self.mox.StubOutWithMock(self.ec2, 'new_http_connection') |
3759 | +# |
3760 | +# def tearDown(self): |
3761 | +# FLAGS.Reset() |
3762 | +# super(ApiObjectStoreTestCase, self).tearDown() |
3763 | +# |
3764 | +# def test_describe_instances(self): |
3765 | +# self.expect_http() |
3766 | +# self.mox.ReplayAll() |
3767 | +# |
3768 | +# self.assertEqual(self.ec2.get_all_instances(), []) |
3769 | |
3770 | === added file 'tests/process_unittest.py' |
3771 | --- tests/process_unittest.py 1970-01-01 00:00:00 +0000 |
3772 | +++ tests/process_unittest.py 2010-07-23 03:41:08 +0000 |
3773 | @@ -0,0 +1,122 @@ |
3774 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
3775 | + |
3776 | +# Copyright 2010 United States Government as represented by the |
3777 | +# Administrator of the National Aeronautics and Space Administration. |
3778 | +# All Rights Reserved. |
3779 | +# |
3780 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
3781 | +# not use this file except in compliance with the License. You may obtain |
3782 | +# a copy of the License at |
3783 | +# |
3784 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3785 | +# |
3786 | +# Unless required by applicable law or agreed to in writing, software |
3787 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
3788 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3789 | +# License for the specific language governing permissions and limitations |
3790 | +# under the License. |
3791 | + |
3792 | +import logging |
3793 | +from twisted.internet import defer |
3794 | +from twisted.internet import reactor |
3795 | +from xml.etree import ElementTree |
3796 | + |
3797 | +from nova import exception |
3798 | +from nova import flags |
3799 | +from nova import process |
3800 | +from nova import test |
3801 | +from nova import utils |
3802 | + |
3803 | +FLAGS = flags.FLAGS |
3804 | + |
3805 | + |
3806 | +class ProcessTestCase(test.TrialTestCase): |
3807 | + def setUp(self): |
3808 | + logging.getLogger().setLevel(logging.DEBUG) |
3809 | + super(ProcessTestCase, self).setUp() |
3810 | + |
3811 | + def test_execute_stdout(self): |
3812 | + pool = process.ProcessPool(2) |
3813 | + d = pool.simple_execute('echo test') |
3814 | + def _check(rv): |
3815 | + self.assertEqual(rv[0], 'test\n') |
3816 | + self.assertEqual(rv[1], '') |
3817 | + |
3818 | + d.addCallback(_check) |
3819 | + d.addErrback(self.fail) |
3820 | + return d |
3821 | + |
3822 | + def test_execute_stderr(self): |
3823 | + pool = process.ProcessPool(2) |
3824 | + d = pool.simple_execute('cat BAD_FILE', error_ok=1) |
3825 | + def _check(rv): |
3826 | + self.assertEqual(rv[0], '') |
3827 | + self.assert_('No such file' in rv[1]) |
3828 | + |
3829 | + d.addCallback(_check) |
3830 | + d.addErrback(self.fail) |
3831 | + return d |
3832 | + |
3833 | + def test_execute_unexpected_stderr(self): |
3834 | + pool = process.ProcessPool(2) |
3835 | + d = pool.simple_execute('cat BAD_FILE') |
3836 | + d.addCallback(lambda x: self.fail('should have raised an error')) |
3837 | + d.addErrback(lambda failure: failure.trap(IOError)) |
3838 | + return d |
3839 | + |
3840 | + def test_max_processes(self): |
3841 | + pool = process.ProcessPool(2) |
3842 | + d1 = pool.simple_execute('sleep 0.01') |
3843 | + d2 = pool.simple_execute('sleep 0.01') |
3844 | + d3 = pool.simple_execute('sleep 0.005') |
3845 | + d4 = pool.simple_execute('sleep 0.005') |
3846 | + |
3847 | + called = [] |
3848 | + def _called(rv, name): |
3849 | + called.append(name) |
3850 | + |
3851 | + d1.addCallback(_called, 'd1') |
3852 | + d2.addCallback(_called, 'd2') |
3853 | + d3.addCallback(_called, 'd3') |
3854 | + d4.addCallback(_called, 'd4') |
3855 | + |
3856 | + # Make sure that d3 and d4 had to wait on the other two and were called |
3857 | + # in order |
3858 | + # NOTE(termie): there may be a race condition in this test if for some |
3859 | + # reason one of the sleeps takes longer to complete |
3860 | + # than it should |
3861 | + d4.addCallback(lambda x: self.assertEqual(called[2], 'd3')) |
3862 | + d4.addCallback(lambda x: self.assertEqual(called[3], 'd4')) |
3863 | + d4.addErrback(self.fail) |
3864 | + return d4 |
3865 | + |
3866 | + def test_kill_long_process(self): |
3867 | + pool = process.ProcessPool(2) |
3868 | + |
3869 | + d1 = pool.simple_execute('sleep 1') |
3870 | + d2 = pool.simple_execute('sleep 0.005') |
3871 | + |
3872 | + timeout = reactor.callLater(0.1, self.fail, 'should have been killed') |
3873 | + |
3874 | + # kill d1 and wait on it to end then cancel the timeout |
3875 | + d2.addCallback(lambda _: d1.process.signalProcess('KILL')) |
3876 | + d2.addCallback(lambda _: d1) |
3877 | + d2.addBoth(lambda _: timeout.active() and timeout.cancel()) |
3878 | + d2.addErrback(self.fail) |
3879 | + return d2 |
3880 | + |
3881 | + def test_process_exit_is_contained(self): |
3882 | + pool = process.ProcessPool(2) |
3883 | + |
3884 | + d1 = pool.simple_execute('sleep 1') |
3885 | + d1.addCallback(lambda x: self.fail('should have errbacked')) |
3886 | + d1.addErrback(lambda fail: fail.trap(IOError)) |
3887 | + reactor.callLater(0.05, d1.process.signalProcess, 'KILL') |
3888 | + |
3889 | + return d1 |
3890 | + |
3891 | + def test_shared_pool_is_singleton(self): |
3892 | + pool1 = process.SharedPool() |
3893 | + pool2 = process.SharedPool() |
3894 | + self.assert_(id(pool1) == id(pool2)) |
3895 | + |
3896 | |
3897 | === added file 'tests/real_flags.py' |
3898 | --- tests/real_flags.py 1970-01-01 00:00:00 +0000 |
3899 | +++ tests/real_flags.py 2010-07-23 03:41:08 +0000 |
3900 | @@ -0,0 +1,28 @@ |
3901 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
3902 | + |
3903 | +# Copyright 2010 United States Government as represented by the |
3904 | +# Administrator of the National Aeronautics and Space Administration. |
3905 | +# All Rights Reserved. |
3906 | +# |
3907 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
3908 | +# not use this file except in compliance with the License. You may obtain |
3909 | +# a copy of the License at |
3910 | +# |
3911 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3912 | +# |
3913 | +# Unless required by applicable law or agreed to in writing, software |
3914 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
3915 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3916 | +# License for the specific language governing permissions and limitations |
3917 | +# under the License. |
3918 | + |
3919 | +from nova import flags |
3920 | + |
3921 | +FLAGS = flags.FLAGS |
3922 | + |
3923 | +FLAGS.fake_libvirt = False |
3924 | +FLAGS.fake_storage = False |
3925 | +FLAGS.fake_rabbit = False |
3926 | +FLAGS.fake_network = False |
3927 | +FLAGS.fake_users = False |
3928 | +FLAGS.verbose = False |
3929 | |
3930 | === added file 'tests/storage_unittest.py' |
3931 | --- tests/storage_unittest.py 1970-01-01 00:00:00 +0000 |
3932 | +++ tests/storage_unittest.py 2010-07-23 03:41:08 +0000 |
3933 | @@ -0,0 +1,115 @@ |
3934 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
3935 | + |
3936 | +# Copyright 2010 United States Government as represented by the |
3937 | +# Administrator of the National Aeronautics and Space Administration. |
3938 | +# All Rights Reserved. |
3939 | +# |
3940 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
3941 | +# not use this file except in compliance with the License. You may obtain |
3942 | +# a copy of the License at |
3943 | +# |
3944 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3945 | +# |
3946 | +# Unless required by applicable law or agreed to in writing, software |
3947 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
3948 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3949 | +# License for the specific language governing permissions and limitations |
3950 | +# under the License. |
3951 | + |
3952 | +import logging |
3953 | + |
3954 | +from nova import exception |
3955 | +from nova import flags |
3956 | +from nova import test |
3957 | +from nova.compute import node |
3958 | +from nova.volume import storage |
3959 | + |
3960 | + |
3961 | +FLAGS = flags.FLAGS |
3962 | + |
3963 | + |
3964 | +class StorageTestCase(test.TrialTestCase): |
3965 | + def setUp(self): |
3966 | + logging.getLogger().setLevel(logging.DEBUG) |
3967 | + super(StorageTestCase, self).setUp() |
3968 | + self.mynode = node.Node() |
3969 | + self.mystorage = None |
3970 | + self.flags(fake_libvirt=True, |
3971 | + fake_storage=True) |
3972 | + self.mystorage = storage.BlockStore() |
3973 | + |
3974 | + def test_run_create_volume(self): |
3975 | + vol_size = '0' |
3976 | + user_id = 'fake' |
3977 | + project_id = 'fake' |
3978 | + volume_id = self.mystorage.create_volume(vol_size, user_id, project_id) |
3979 | + # TODO(termie): get_volume returns differently than create_volume |
3980 | + self.assertEqual(volume_id, |
3981 | + storage.get_volume(volume_id)['volume_id']) |
3982 | + |
3983 | + rv = self.mystorage.delete_volume(volume_id) |
3984 | + self.assertRaises(exception.Error, |
3985 | + storage.get_volume, |
3986 | + volume_id) |
3987 | + |
3988 | + def test_too_big_volume(self): |
3989 | + vol_size = '1001' |
3990 | + user_id = 'fake' |
3991 | + project_id = 'fake' |
3992 | + self.assertRaises(TypeError, |
3993 | + self.mystorage.create_volume, |
3994 | + vol_size, user_id, project_id) |
3995 | + |
3996 | + def test_too_many_volumes(self): |
3997 | + vol_size = '1' |
3998 | + user_id = 'fake' |
3999 | + project_id = 'fake' |
4000 | + num_shelves = FLAGS.last_shelf_id - FLAGS.first_shelf_id + 1 |
4001 | + total_slots = FLAGS.slots_per_shelf * num_shelves |
4002 | + vols = [] |
4003 | + for i in xrange(total_slots): |
4004 | + vid = self.mystorage.create_volume(vol_size, user_id, project_id) |
4005 | + vols.append(vid) |
4006 | + self.assertRaises(storage.NoMoreVolumes, |
4007 | + self.mystorage.create_volume, |
4008 | + vol_size, user_id, project_id) |
4009 | + for id in vols: |
4010 | + self.mystorage.delete_volume(id) |
4011 | + |
4012 | + def test_run_attach_detach_volume(self): |
4013 | + # Create one volume and one node to test with |
4014 | + instance_id = "storage-test" |
4015 | + vol_size = "5" |
4016 | + user_id = "fake" |
4017 | + project_id = 'fake' |
4018 | + mountpoint = "/dev/sdf" |
4019 | + volume_id = self.mystorage.create_volume(vol_size, user_id, project_id) |
4020 | + |
4021 | + volume_obj = storage.get_volume(volume_id) |
4022 | + volume_obj.start_attach(instance_id, mountpoint) |
4023 | + rv = yield self.mynode.attach_volume(volume_id, |
4024 | + instance_id, |
4025 | + mountpoint) |
4026 | + self.assertEqual(volume_obj['status'], "in-use") |
4027 | + self.assertEqual(volume_obj['attachStatus'], "attached") |
4028 | + self.assertEqual(volume_obj['instance_id'], instance_id) |
4029 | + self.assertEqual(volume_obj['mountpoint'], mountpoint) |
4030 | + |
4031 | + self.assertRaises(exception.Error, |
4032 | + self.mystorage.delete_volume, |
4033 | + volume_id) |
4034 | + |
4035 | + rv = yield self.mystorage.detach_volume(volume_id) |
4036 | + volume_obj = storage.get_volume(volume_id) |
4037 | + self.assertEqual(volume_obj['status'], "available") |
4038 | + |
4039 | + rv = self.mystorage.delete_volume(volume_id) |
4040 | + self.assertRaises(exception.Error, |
4041 | + storage.get_volume, |
4042 | + volume_id) |
4043 | + |
4044 | + def test_multi_node(self): |
4045 | + # TODO(termie): Figure out how to test with two nodes, |
4046 | + # each of them having a different FLAG for storage_node |
4047 | + # This will allow us to test cross-node interactions |
4048 | + pass |
4049 | |
4050 | === added file 'tests/users_unittest.py' |
4051 | --- tests/users_unittest.py 1970-01-01 00:00:00 +0000 |
4052 | +++ tests/users_unittest.py 2010-07-23 03:41:08 +0000 |
4053 | @@ -0,0 +1,207 @@ |
4054 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
4055 | + |
4056 | +# Copyright 2010 United States Government as represented by the |
4057 | +# Administrator of the National Aeronautics and Space Administration. |
4058 | +# All Rights Reserved. |
4059 | +# |
4060 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
4061 | +# not use this file except in compliance with the License. You may obtain |
4062 | +# a copy of the License at |
4063 | +# |
4064 | +# http://www.apache.org/licenses/LICENSE-2.0 |
4065 | +# |
4066 | +# Unless required by applicable law or agreed to in writing, software |
4067 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
4068 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
4069 | +# License for the specific language governing permissions and limitations |
4070 | +# under the License. |
4071 | + |
4072 | +import logging |
4073 | +from M2Crypto import BIO |
4074 | +from M2Crypto import RSA |
4075 | +from M2Crypto import X509 |
4076 | +import unittest |
4077 | + |
4078 | +from nova import crypto |
4079 | +from nova import flags |
4080 | +from nova import test |
4081 | +from nova.auth import users |
4082 | +from nova.endpoint import cloud |
4083 | + |
4084 | +FLAGS = flags.FLAGS |
4085 | + |
4086 | + |
4087 | +class UserTestCase(test.BaseTestCase): |
4088 | + flush_db = False |
4089 | + def setUp(self): |
4090 | + super(UserTestCase, self).setUp() |
4091 | + self.flags(fake_libvirt=True, |
4092 | + fake_storage=True) |
4093 | + self.users = users.UserManager.instance() |
4094 | + |
4095 | + def test_001_can_create_users(self): |
4096 | + self.users.create_user('test1', 'access', 'secret') |
4097 | + self.users.create_user('test2') |
4098 | + |
4099 | + def test_002_can_get_user(self): |
4100 | + user = self.users.get_user('test1') |
4101 | + |
4102 | + def test_003_can_retreive_properties(self): |
4103 | + user = self.users.get_user('test1') |
4104 | + self.assertEqual('test1', user.id) |
4105 | + self.assertEqual('access', user.access) |
4106 | + self.assertEqual('secret', user.secret) |
4107 | + |
4108 | + def test_004_signature_is_valid(self): |
4109 | + #self.assertTrue(self.users.authenticate( **boto.generate_url ... ? ? ? )) |
4110 | + pass |
4111 | + #raise NotImplementedError |
4112 | + |
4113 | + def test_005_can_get_credentials(self): |
4114 | + return |
4115 | + credentials = self.users.get_user('test1').get_credentials() |
4116 | + self.assertEqual(credentials, |
4117 | + 'export EC2_ACCESS_KEY="access"\n' + |
4118 | + 'export EC2_SECRET_KEY="secret"\n' + |
4119 | + 'export EC2_URL="http://127.0.0.1:8773/services/Cloud"\n' + |
4120 | + 'export S3_URL="http://127.0.0.1:3333/"\n' + |
4121 | + 'export EC2_USER_ID="test1"\n') |
4122 | + |
4123 | + def test_006_test_key_storage(self): |
4124 | + user = self.users.get_user('test1') |
4125 | + user.create_key_pair('public', 'key', 'fingerprint') |
4126 | + key = user.get_key_pair('public') |
4127 | + self.assertEqual('key', key.public_key) |
4128 | + self.assertEqual('fingerprint', key.fingerprint) |
4129 | + |
4130 | + def test_007_test_key_generation(self): |
4131 | + user = self.users.get_user('test1') |
4132 | + private_key, fingerprint = user.generate_key_pair('public2') |
4133 | + key = RSA.load_key_string(private_key, callback=lambda: None) |
4134 | + bio = BIO.MemoryBuffer() |
4135 | + public_key = user.get_key_pair('public2').public_key |
4136 | + key.save_pub_key_bio(bio) |
4137 | + converted = crypto.ssl_pub_to_ssh_pub(bio.read()) |
4138 | + # assert key fields are equal |
4139 | + self.assertEqual(public_key.split(" ")[1].strip(), |
4140 | + converted.split(" ")[1].strip()) |
4141 | + |
4142 | + def test_008_can_list_key_pairs(self): |
4143 | + keys = self.users.get_user('test1').get_key_pairs() |
4144 | + self.assertTrue(filter(lambda k: k.name == 'public', keys)) |
4145 | + self.assertTrue(filter(lambda k: k.name == 'public2', keys)) |
4146 | + |
4147 | + def test_009_can_delete_key_pair(self): |
4148 | + self.users.get_user('test1').delete_key_pair('public') |
4149 | + keys = self.users.get_user('test1').get_key_pairs() |
4150 | + self.assertFalse(filter(lambda k: k.name == 'public', keys)) |
4151 | + |
4152 | + def test_010_can_list_users(self): |
4153 | + users = self.users.get_users() |
4154 | + logging.warn(users) |
4155 | + self.assertTrue(filter(lambda u: u.id == 'test1', users)) |
4156 | + |
4157 | + def test_101_can_add_user_role(self): |
4158 | + self.assertFalse(self.users.has_role('test1', 'itsec')) |
4159 | + self.users.add_role('test1', 'itsec') |
4160 | + self.assertTrue(self.users.has_role('test1', 'itsec')) |
4161 | + |
4162 | + def test_199_can_remove_user_role(self): |
4163 | + self.assertTrue(self.users.has_role('test1', 'itsec')) |
4164 | + self.users.remove_role('test1', 'itsec') |
4165 | + self.assertFalse(self.users.has_role('test1', 'itsec')) |
4166 | + |
4167 | + def test_201_can_create_project(self): |
4168 | + project = self.users.create_project('testproj', 'test1', 'A test project', ['test1']) |
4169 | + self.assertTrue(filter(lambda p: p.name == 'testproj', self.users.get_projects())) |
4170 | + self.assertEqual(project.name, 'testproj') |
4171 | + self.assertEqual(project.description, 'A test project') |
4172 | + self.assertEqual(project.project_manager_id, 'test1') |
4173 | + self.assertTrue(project.has_member('test1')) |
4174 | + |
4175 | + def test_202_user1_is_project_member(self): |
4176 | + self.assertTrue(self.users.get_user('test1').is_project_member('testproj')) |
4177 | + |
4178 | + def test_203_user2_is_not_project_member(self): |
4179 | + self.assertFalse(self.users.get_user('test2').is_project_member('testproj')) |
4180 | + |
4181 | + def test_204_user1_is_project_manager(self): |
4182 | + self.assertTrue(self.users.get_user('test1').is_project_manager('testproj')) |
4183 | + |
4184 | + def test_205_user2_is_not_project_manager(self): |
4185 | + self.assertFalse(self.users.get_user('test2').is_project_manager('testproj')) |
4186 | + |
4187 | + def test_206_can_add_user_to_project(self): |
4188 | + self.users.add_to_project('test2', 'testproj') |
4189 | + self.assertTrue(self.users.get_project('testproj').has_member('test2')) |
4190 | + |
4191 | + def test_208_can_remove_user_from_project(self): |
4192 | + self.users.remove_from_project('test2', 'testproj') |
4193 | + self.assertFalse(self.users.get_project('testproj').has_member('test2')) |
4194 | + |
4195 | + def test_209_can_generate_x509(self): |
4196 | + # MUST HAVE RUN CLOUD SETUP BY NOW |
4197 | + self.cloud = cloud.CloudController() |
4198 | + self.cloud.setup() |
4199 | + private_key, signed_cert_string = self.users.get_project('testproj').generate_x509_cert('test1') |
4200 | + logging.debug(signed_cert_string) |
4201 | + |
4202 | + # Need to verify that it's signed by the right intermediate CA |
4203 | + full_chain = crypto.fetch_ca(project_id='testproj', chain=True) |
4204 | + int_cert = crypto.fetch_ca(project_id='testproj', chain=False) |
4205 | + cloud_cert = crypto.fetch_ca() |
4206 | + logging.debug("CA chain:\n\n =====\n%s\n\n=====" % full_chain) |
4207 | + signed_cert = X509.load_cert_string(signed_cert_string) |
4208 | + chain_cert = X509.load_cert_string(full_chain) |
4209 | + int_cert = X509.load_cert_string(int_cert) |
4210 | + cloud_cert = X509.load_cert_string(cloud_cert) |
4211 | + self.assertTrue(signed_cert.verify(chain_cert.get_pubkey())) |
4212 | + self.assertTrue(signed_cert.verify(int_cert.get_pubkey())) |
4213 | + |
4214 | + if not FLAGS.use_intermediate_ca: |
4215 | + self.assertTrue(signed_cert.verify(cloud_cert.get_pubkey())) |
4216 | + else: |
4217 | + self.assertFalse(signed_cert.verify(cloud_cert.get_pubkey())) |
4218 | + |
4219 | + def test_210_can_add_project_role(self): |
4220 | + project = self.users.get_project('testproj') |
4221 | + self.assertFalse(project.has_role('test1', 'sysadmin')) |
4222 | + self.users.add_role('test1', 'sysadmin') |
4223 | + self.assertFalse(project.has_role('test1', 'sysadmin')) |
4224 | + project.add_role('test1', 'sysadmin') |
4225 | + self.assertTrue(project.has_role('test1', 'sysadmin')) |
4226 | + |
4227 | + def test_211_can_remove_project_role(self): |
4228 | + project = self.users.get_project('testproj') |
4229 | + self.assertTrue(project.has_role('test1', 'sysadmin')) |
4230 | + project.remove_role('test1', 'sysadmin') |
4231 | + self.assertFalse(project.has_role('test1', 'sysadmin')) |
4232 | + self.users.remove_role('test1', 'sysadmin') |
4233 | + self.assertFalse(project.has_role('test1', 'sysadmin')) |
4234 | + |
4235 | + def test_212_vpn_ip_and_port_looks_valid(self): |
4236 | + project = self.users.get_project('testproj') |
4237 | + self.assert_(project.vpn_ip) |
4238 | + self.assert_(project.vpn_port >= FLAGS.vpn_start_port) |
4239 | + self.assert_(project.vpn_port <= FLAGS.vpn_end_port) |
4240 | + |
4241 | + def test_213_too_many_vpns(self): |
4242 | + for i in xrange(users.Vpn.num_ports_for_ip(FLAGS.vpn_ip)): |
4243 | + users.Vpn.create("vpnuser%s" % i) |
4244 | + self.assertRaises(users.NoMorePorts, users.Vpn.create, "boom") |
4245 | + |
4246 | + def test_299_can_delete_project(self): |
4247 | + self.users.delete_project('testproj') |
4248 | + self.assertFalse(filter(lambda p: p.name == 'testproj', self.users.get_projects())) |
4249 | + |
4250 | + def test_999_can_delete_users(self): |
4251 | + self.users.delete_user('test1') |
4252 | + users = self.users.get_users() |
4253 | + self.assertFalse(filter(lambda u: u.id == 'test1', users)) |
4254 | + self.users.delete_user('test2') |
4255 | + self.assertEqual(self.users.get_user('test2'), None) |
4256 | + |
4257 | + |
4258 | +if __name__ == "__main__": |
4259 | + # TODO: Implement use_fake as an option |
4260 | + unittest.main() |
4261 | |
4262 | === added file 'tests/validator_unittest.py' |
4263 | --- tests/validator_unittest.py 1970-01-01 00:00:00 +0000 |
4264 | +++ tests/validator_unittest.py 2010-07-23 03:41:08 +0000 |
4265 | @@ -0,0 +1,41 @@ |
4266 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
4267 | + |
4268 | +# Copyright 2010 United States Government as represented by the |
4269 | +# Administrator of the National Aeronautics and Space Administration. |
4270 | +# All Rights Reserved. |
4271 | +# |
4272 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
4273 | +# not use this file except in compliance with the License. You may obtain |
4274 | +# a copy of the License at |
4275 | +# |
4276 | +# http://www.apache.org/licenses/LICENSE-2.0 |
4277 | +# |
4278 | +# Unless required by applicable law or agreed to in writing, software |
4279 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
4280 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
4281 | +# License for the specific language governing permissions and limitations |
4282 | +# under the License. |
4283 | + |
4284 | +import logging |
4285 | +import unittest |
4286 | + |
4287 | +from nova import flags |
4288 | +from nova import test |
4289 | +from nova import validate |
4290 | + |
4291 | + |
4292 | +class ValidationTestCase(test.TrialTestCase): |
4293 | + def setUp(self): |
4294 | + super(ValidationTestCase, self).setUp() |
4295 | + |
4296 | + def tearDown(self): |
4297 | + super(ValidationTestCase, self).tearDown() |
4298 | + |
4299 | + def test_type_validation(self): |
4300 | + self.assertTrue(type_case("foo", 5, 1)) |
4301 | + self.assertRaises(TypeError, type_case, "bar", "5", 1) |
4302 | + self.assertRaises(TypeError, type_case, None, 5, 1) |
4303 | + |
4304 | +@validate.typetest(instanceid=str, size=int, number_of_instances=int) |
4305 | +def type_case(instanceid, size, number_of_instances): |
4306 | + return True |
I actually prefer the tests right where they are, i.e. below the namespace to which they pertain. Looking through the python packages I have installed on my system, it also seems to be the prevailing approach, so -1 from me, I'm afraid.