merge master
This commit is contained in:
commit
2e59567f97
|
@ -0,0 +1,11 @@
|
|||
Antony Messerli <amesserl@rackspace.com> root <root@debian.ohthree.com>
|
||||
<amesserl@rackspace.com> <root@debian.ohthree.com>
|
||||
<brian.waldon@rackspace.com> <bcwaldon@gmail.com>
|
||||
Chris Behrens <cbehrens+github@codestud.com> comstud <cbehrens+github@codestud.com>
|
||||
<cbehrens+github@codestud.com> <cbehrens@codestud.com>
|
||||
Johannes Erdfelt <johannes.erdfelt@rackspace.com> jerdfelt <johannes@erdfelt.com>
|
||||
<johannes.erdfelt@rackspace.com> <johannes@erdfelt.com>
|
||||
<josh@jk0.org> <jkearney@nova.(none)>
|
||||
<sandy@darksecretsoftware.com> <sandy.walsh@rackspace.com>
|
||||
<sandy@darksecretsoftware.com> <sandy@sandywalsh.com>
|
||||
Andy Smith <github@anarkystic.com> termie <github@anarkystic.com>
|
9
AUTHORS
9
AUTHORS
|
@ -1,8 +1,10 @@
|
|||
Andrey Brindeyev <abrindeyev@griddynamics.com>
|
||||
Andy Smith <github@anarkystic.com>
|
||||
Antony Messerli <amesserl@rackspace.com>
|
||||
Brian Lamar <brian.lamar@rackspace.com>
|
||||
Brian Waldon <brian.waldon@rackspace.com>
|
||||
Chris Behrens <cbehrens@codestud.com>
|
||||
Christopher MacGown <chris@pistoncloud.com>
|
||||
Chris Behrens <cbehrens+github@codestud.com>
|
||||
Christopher MacGown <ignoti+github@gmail.com>
|
||||
Ed Leafe <ed@leafe.com>
|
||||
Eldar Nugaev <eldr@ya.ru>
|
||||
Ilya Alekseyev <ilyaalekseyev@acm.org>
|
||||
|
@ -12,5 +14,4 @@ Kevin L. Mitchell <kevin.mitchell@rackspace.com>
|
|||
Kirill Shileev <kshileev@griddynamics.com>
|
||||
Lvov Maxim <mlvov@mirantis.com>
|
||||
Matt Dietz <matt.dietz@rackspace.com>
|
||||
Sandy Walsh <sandy.walsh@rackspace.com>
|
||||
jerdfelt <johannes@erdfelt.com>
|
||||
Sandy Walsh <sandy@darksecretsoftware.com>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright 2010 Jacob Kaplan-Moss
|
||||
# Copyright 2011 Piston Cloud Computing
|
||||
# Copyright 2011 Piston Cloud Computing, Inc.
|
||||
|
||||
"""
|
||||
OpenStack Client interface. Handles the REST calls and responses.
|
||||
|
@ -141,7 +141,10 @@ class HTTPClient(httplib2.Http):
|
|||
headers['X-Auth-Project-Id'] = self.projectid
|
||||
|
||||
resp, body = self.request(self.auth_url, 'GET', headers=headers)
|
||||
self.management_url = resp['x-server-management-url']
|
||||
try:
|
||||
self.management_url = resp['x-server-management-url']
|
||||
except KeyError:
|
||||
raise exceptions.AuthorizationFailure()
|
||||
|
||||
self.auth_token = resp['x-auth-token']
|
||||
else:
|
||||
|
|
|
@ -8,6 +8,10 @@ class CommandError(Exception):
|
|||
pass
|
||||
|
||||
|
||||
class AuthorizationFailure(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ClientException(Exception):
|
||||
"""
|
||||
The base exception class for all exceptions this library raises.
|
||||
|
|
|
@ -166,6 +166,8 @@ class OpenStackComputeShell(object):
|
|||
self.cs.authenticate()
|
||||
except exc.Unauthorized:
|
||||
raise exc.CommandError("Invalid OpenStack Nova credentials.")
|
||||
except exc.AuthorizationFailure:
|
||||
raise exc.CommandError("Unable to authorize user")
|
||||
|
||||
args.func(self.cs, args)
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ from novaclient.v1_1 import flavors
|
|||
from novaclient.v1_1 import images
|
||||
from novaclient.v1_1 import keypairs
|
||||
from novaclient.v1_1 import servers
|
||||
from novaclient.v1_1 import quotas
|
||||
from novaclient.v1_1 import zones
|
||||
|
||||
|
||||
|
@ -32,6 +33,7 @@ class Client(object):
|
|||
# extensions
|
||||
self.keypairs = keypairs.KeypairManager(self)
|
||||
self.zones = zones.ZoneManager(self)
|
||||
self.quotas = quotas.QuotaSetManager(self)
|
||||
|
||||
self.client = client.HTTPClient(username,
|
||||
api_key,
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
# Copyright 2011 OpenStack LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from novaclient import base
|
||||
|
||||
|
||||
class QuotaSet(base.Resource):
|
||||
def get(self):
|
||||
self.manager.get(self)
|
||||
|
||||
def delete(self):
|
||||
self.manager.delete(self)
|
||||
|
||||
def update(self, *args, **kwargs):
|
||||
self.manager.update(self.tenant_id, *args, **kwargs)
|
||||
|
||||
|
||||
class QuotaSetManager(base.ManagerWithFind):
|
||||
resource_class = QuotaSet
|
||||
|
||||
def list(self, defaults=False):
|
||||
if defaults == True:
|
||||
return self._list('/os-quotas?defaults=True',
|
||||
'quota_set_list')
|
||||
else:
|
||||
return self._list("/os-quotas", "quota_set_list")
|
||||
|
||||
def get(self, tenant_id):
|
||||
if hasattr(tenant_id, 'tenant_id'):
|
||||
tenant_id = tenant_id.tenant_id
|
||||
return self._get("/os-quotas/%s" % (tenant_id), "quota_set")
|
||||
|
||||
def update(self, tenant_id, metadata_items=None,
|
||||
injected_file_content_bytes=None, volumes=None, gigabytes=None,
|
||||
ram=None, floating_ips=None, instances=None, injected_files=None,
|
||||
cores=None):
|
||||
|
||||
body = {'quota_set': {
|
||||
'tenant_id': tenant_id,
|
||||
'metadata_items': metadata_items,
|
||||
'injected_file_content_bytes': injected_file_content_bytes,
|
||||
'volumes': volumes,
|
||||
'gigabytes': gigabytes,
|
||||
'ram': ram,
|
||||
'floating_ips': floating_ips,
|
||||
'instances': instances,
|
||||
'injected_files': injected_files,
|
||||
'cores': cores,
|
||||
}}
|
||||
|
||||
for key in body['quota_set'].keys():
|
||||
if body['quota_set'][key] == None:
|
||||
body['quota_set'].pop(key)
|
||||
|
||||
return self._update('/os-quotas/%s' % (tenant_id), body)
|
||||
|
||||
def delete(self, tenant_id):
|
||||
if hasattr(tenant_id, 'tenant_id'):
|
||||
tenant_id = tenant_id.tenant_id
|
||||
self._delete("/os-quotas/%s" % (tenant_id))
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
[nosetests]
|
||||
with-coverage = true
|
||||
cover-package = novaclient
|
||||
cover-html = true
|
||||
cover-erase = true
|
||||
|
|
|
@ -2,6 +2,7 @@ import httplib2
|
|||
import mock
|
||||
|
||||
from novaclient import client
|
||||
from novaclient import exceptions
|
||||
from tests import utils
|
||||
|
||||
|
||||
|
@ -54,3 +55,13 @@ class ClientTest(utils.TestCase):
|
|||
headers=headers, body='[1, 2, 3]')
|
||||
|
||||
test_post_call()
|
||||
|
||||
def test_auth_failure(self):
|
||||
cl = get_client()
|
||||
|
||||
# response must not have x-server-management-url header
|
||||
@mock.patch.object(httplib2.Http, "request", mock_request)
|
||||
def test_auth_call():
|
||||
self.assertRaises(exceptions.AuthorizationFailure, cl.authenticate)
|
||||
|
||||
test_auth_call()
|
||||
|
|
|
@ -31,8 +31,13 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||
assert 'body' in kwargs
|
||||
|
||||
# Call the method
|
||||
<<<<<<< HEAD
|
||||
munged_url = url.strip('/').replace('/', '_') \
|
||||
.replace('.', '_').replace('-', '_')
|
||||
=======
|
||||
munged_url = url.strip('/').replace('/', '_').replace('.', '_')
|
||||
munged_url = munged_url.replace('-', '_')
|
||||
>>>>>>> rax/master
|
||||
callback = "%s_%s" % (method.lower(), munged_url)
|
||||
if not hasattr(self, callback):
|
||||
raise AssertionError('Called unknown API method: %s %s' % (method,
|
||||
|
@ -392,3 +397,44 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||
required=['name'])
|
||||
r = {'keypair': self.get_os_keypairs()[1]['keypairs'][0]}
|
||||
return (202, r)
|
||||
|
||||
#
|
||||
# Quotas
|
||||
#
|
||||
def get_os_quotas(self, *kw):
|
||||
return (200, {'quota_set_list': [{
|
||||
'tenant_id': 'test',
|
||||
'metadata_items': [],
|
||||
'injected_file_content_bytes': 1,
|
||||
'volumes': 1,
|
||||
'gigabytes': 1,
|
||||
'ram': 1,
|
||||
'floating_ips': 1,
|
||||
'instances': 1,
|
||||
'injected_files': 1,
|
||||
'cores': 1,
|
||||
}]})
|
||||
|
||||
def get_os_quotas_test(self, *kw):
|
||||
return (200, {'quota_set': {
|
||||
'tenant_id': 'test',
|
||||
'metadata_items': [],
|
||||
'injected_file_content_bytes': 1,
|
||||
'volumes': 1,
|
||||
'gigabytes': 1,
|
||||
'ram': 1,
|
||||
'floating_ips': 1,
|
||||
'instances': 1,
|
||||
'injected_files': 1,
|
||||
'cores': 1,
|
||||
}})
|
||||
|
||||
def delete_os_quotas_test(self, **kw):
|
||||
return (202, None)
|
||||
|
||||
def put_os_quotas_test(self, body, **kw):
|
||||
assert body.keys() == ['quota_set']
|
||||
fakes.assert_has_keys(body['quota_set'],
|
||||
required=['tenant_id'])
|
||||
r = self.get_os_quotas_test()[1]
|
||||
return (200, r)
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
# Copyright 2011 OpenStack LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from novaclient import exceptions
|
||||
from novaclient.v1_1 import quotas
|
||||
from tests.v1_1 import fakes
|
||||
from tests import utils
|
||||
|
||||
|
||||
cs = fakes.FakeClient()
|
||||
|
||||
|
||||
class QuoatsTest(utils.TestCase):
|
||||
def test_list_quotas(self):
|
||||
qs = cs.quotas.list()
|
||||
cs.assert_called('GET', '/os-quotas')
|
||||
[self.assertTrue(isinstance(q, quotas.QuotaSet)) for q in qs]
|
||||
|
||||
def test_delete_quota(self):
|
||||
q = cs.quotas.list()[0]
|
||||
q.delete()
|
||||
cs.assert_called('DELETE', '/os-quotas/test')
|
||||
cs.quotas.delete('test')
|
||||
cs.assert_called('DELETE', '/os-quotas/test')
|
||||
cs.quotas.delete(q)
|
||||
cs.assert_called('DELETE', '/os-quotas/test')
|
||||
|
||||
def test_update_quota(self):
|
||||
q = cs.quotas.list()[0]
|
||||
q.update(volumes=2)
|
||||
cs.assert_called('PUT', '/os-quotas/test')
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
git shortlog -se | cut -c8-
|
Loading…
Reference in New Issue