Simple per-user instance quota checking in the create call. PEP8 fixes.
This commit is contained in:
parent
04110bd7ea
commit
25c97fa6c5
@ -50,6 +50,7 @@ block_device_mapping = /var/lib/mysql
|
||||
device_path = /var/lib/mysql
|
||||
mount_point = /var/lib/mysql
|
||||
max_accepted_volume_size = 10
|
||||
max_instances_per_user = 5
|
||||
volume_time_out=30
|
||||
|
||||
# Reddwarf DNS
|
||||
|
@ -61,7 +61,8 @@ nova_volume_service_type = volume
|
||||
nova_volume_service_name = Volume Service
|
||||
device_path = /dev/vdb
|
||||
mount_point = /var/lib/mysql
|
||||
max_accepted_volume_size = 10
|
||||
max_accepted_volume_size = 25
|
||||
max_instances_per_user = 5
|
||||
volume_time_out=30
|
||||
|
||||
# Auth
|
||||
|
@ -82,6 +82,16 @@ class OverLimit(ReddwarfError):
|
||||
"rate.")
|
||||
|
||||
|
||||
class QuotaExceeded(ReddwarfError):
|
||||
|
||||
message = _("User instance quota exceeded.")
|
||||
|
||||
|
||||
class VolumeQuotaExceeded(QuotaExceeded):
|
||||
|
||||
message = _("Instance volume quota exceeded.")
|
||||
|
||||
|
||||
class GuestError(ReddwarfError):
|
||||
|
||||
message = _("An error occurred communicating with the guest: "
|
||||
|
@ -56,6 +56,8 @@ class BaseController(wsgi.Controller):
|
||||
],
|
||||
webob.exc.HTTPRequestEntityTooLarge: [
|
||||
exception.OverLimit,
|
||||
exception.QuotaExceeded,
|
||||
exception.VolumeQuotaExceeded,
|
||||
],
|
||||
webob.exc.HTTPServerError: [
|
||||
exception.VolumeCreationFailure
|
||||
@ -246,6 +248,17 @@ class InstanceController(BaseController):
|
||||
raise exception.BadValue(msg=e)
|
||||
else:
|
||||
volume_size = None
|
||||
|
||||
instance_max = int(config.Config.get('max_instances_per_user', 5))
|
||||
number_instances = models.DBInstance.find_all(tenant_id=tenant_id,
|
||||
deleted=False).count()
|
||||
|
||||
if number_instances >= instance_max:
|
||||
# That's too many, pal. Got to cut you off.
|
||||
LOG.error(_("New instance would exceed user instance quota."))
|
||||
msg = "User instance quota of %d would be exceeded."
|
||||
raise exception.QuotaExceeded(msg % instance_max)
|
||||
|
||||
instance = models.Instance.create(context, name, flavor_id,
|
||||
image_id, databases, users,
|
||||
service_type, volume_size)
|
||||
@ -285,18 +298,18 @@ class InstanceController(BaseController):
|
||||
"integer value, %s cannot be accepted."
|
||||
% volume_size)
|
||||
raise exception.ReddwarfError(msg)
|
||||
max_size = int(config.Config.get('max_accepted_volume_size',
|
||||
1))
|
||||
max_size = int(config.Config.get('max_accepted_volume_size', 1))
|
||||
if int(volume_size) > max_size:
|
||||
msg = ("Volume 'size' cannot exceed maximum "
|
||||
"of %d Gb, %s cannot be accepted."
|
||||
% (max_size, volume_size))
|
||||
raise exception.ReddwarfError(msg)
|
||||
raise exception.VolumeQuotaExceeded(msg)
|
||||
|
||||
@staticmethod
|
||||
def _validate(body):
|
||||
"""Validate that the request has all the required parameters"""
|
||||
InstanceController._validate_body_not_empty(body)
|
||||
|
||||
try:
|
||||
body['instance']
|
||||
body['instance']['flavorRef']
|
||||
@ -315,6 +328,7 @@ class InstanceController(BaseController):
|
||||
raise exception.MissingKey(key="size")
|
||||
elif must_have_vol:
|
||||
raise exception.MissingKey(key="volume")
|
||||
|
||||
except KeyError as e:
|
||||
LOG.error(_("Create Instance Required field(s) - %s") % e)
|
||||
raise exception.ReddwarfError("Required element/key - %s "
|
||||
|
@ -59,6 +59,7 @@ class API(object):
|
||||
logging.error("Error running async task:")
|
||||
logging.error((traceback.format_exception(type_, value, tb)))
|
||||
raise type_, value, tb
|
||||
|
||||
eventlet.spawn_after(0, func)
|
||||
|
||||
def _get_routing_key(self):
|
||||
|
@ -80,4 +80,3 @@ class TaskManager(service.Manager):
|
||||
instance_tasks.create_instance(flavor_id, flavor_ram, image_id,
|
||||
databases, users, service_type,
|
||||
volume_size)
|
||||
|
||||
|
@ -148,7 +148,8 @@ class FreshInstanceTasks(FreshInstance):
|
||||
if utils.bool_from_string(dns_support):
|
||||
|
||||
def get_server():
|
||||
return nova_client.servers.get(self.db_info.compute_instance_id)
|
||||
c_id = self.db_info.compute_instance_id
|
||||
return nova_client.servers.get(c_id)
|
||||
|
||||
def ip_is_available(server):
|
||||
LOG.info("Polling for ip addresses: $%s " % server.addresses)
|
||||
@ -200,7 +201,7 @@ class BuiltInstanceTasks(BuiltInstance):
|
||||
dns_api.delete_instance_entry(instance_id=self.db_info.id)
|
||||
except Exception as ex:
|
||||
LOG.error("Error during dns entry for instance %s "
|
||||
% self.db_info.id )
|
||||
% self.db_info.id)
|
||||
LOG.error(ex)
|
||||
|
||||
def resize_volume(self, new_size):
|
||||
|
@ -21,4 +21,3 @@ from rsdns.client.dns_client import DNSaas
|
||||
from rsdns.client.dns_client import DNSaasClient
|
||||
from rsdns.client.domains import DomainsManager
|
||||
from rsdns.client.records import RecordsManager
|
||||
|
||||
|
@ -38,7 +38,7 @@ LOG = logging.getLogger('rsdns.client.dns_client')
|
||||
class DNSaasClient(HTTPClient):
|
||||
|
||||
def __init__(self, accountId, user, apikey, auth_url, management_base_url):
|
||||
tenant = "dbaas"
|
||||
tenant = "dbaas"
|
||||
super(DNSaasClient, self).__init__(user, apikey, tenant, auth_url)
|
||||
self.accountId = accountId
|
||||
self.management_base_url = management_base_url
|
||||
@ -48,7 +48,8 @@ class DNSaasClient(HTTPClient):
|
||||
|
||||
def authenticate(self):
|
||||
"""Set the management url and auth token"""
|
||||
req_body = {'credentials':{'username':self.user, 'key':self.api_key}}
|
||||
req_body = {'credentials': {'username': self.user,
|
||||
'key': self.api_key}}
|
||||
resp, body = self.request(self.auth_url, "POST", body=req_body)
|
||||
if 'access' in body:
|
||||
if not self.management_url:
|
||||
@ -103,6 +104,7 @@ class DNSaasClient(HTTPClient):
|
||||
|
||||
return resp, body
|
||||
|
||||
|
||||
class DNSaas(Client):
|
||||
"""
|
||||
Top-level object to access the DNSaas service
|
||||
@ -115,8 +117,9 @@ class DNSaas(Client):
|
||||
from rsdns.client.domains import DomainsManager
|
||||
from rsdns.client.records import RecordsManager
|
||||
|
||||
super(DNSaas, self).__init__(self, accountId, username, apikey, auth_url, management_base_url)
|
||||
super(DNSaas, self).__init__(self, accountId, username, apikey,
|
||||
auth_url, management_base_url)
|
||||
self.client = DNSaasClient(accountId, username, apikey, auth_url,
|
||||
management_base_url)
|
||||
self.domains = DomainsManager(self)
|
||||
self.records = RecordsManager(self)
|
||||
self.records = RecordsManager(self)
|
||||
|
@ -31,6 +31,7 @@ class Domain(base.Resource):
|
||||
def response_list_name(self):
|
||||
return "domains"
|
||||
|
||||
|
||||
class FutureDomain(FutureResource):
|
||||
|
||||
def convert_callback(self, resp, body):
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
|
||||
class RsDnsError(RuntimeError):
|
||||
|
||||
def __init__(self, error):
|
||||
@ -13,9 +14,10 @@ class RsDnsError(RuntimeError):
|
||||
def __str__(self):
|
||||
return self.message
|
||||
|
||||
|
||||
class FutureResource(object):
|
||||
"""Polls a callback url to return a resource."""
|
||||
|
||||
|
||||
def __init__(self, manager, jobId, callbackUrl, status, **kwargs):
|
||||
self.manager = manager
|
||||
self.jobId = jobId
|
||||
@ -41,8 +43,6 @@ class FutureResource(object):
|
||||
return None
|
||||
resp_list = body['response'][self.response_list_name()]
|
||||
self.result = self.manager.create_from_list(resp_list)
|
||||
#self.resource_class(self, res) for res in list]
|
||||
#self.result = Domain(self.manager, body['self.convert_callback(resp, body)
|
||||
return self.result
|
||||
|
||||
@property
|
||||
|
@ -53,7 +53,8 @@ class RecordsManager(base.ManagerWithFind):
|
||||
"""
|
||||
resource_class = Record
|
||||
|
||||
def create(self, domain, record_name, record_data, record_type, record_ttl):
|
||||
def create(self, domain, record_name, record_data, record_type,
|
||||
record_ttl):
|
||||
"""
|
||||
Create a new Record on the given domain
|
||||
|
||||
@ -61,14 +62,14 @@ class RecordsManager(base.ManagerWithFind):
|
||||
:param record: The ID of the :class:`Record` to get.
|
||||
:rtype: :class:`Record`
|
||||
"""
|
||||
data = {"records":[{"type": record_type, "name": record_name,
|
||||
"data": record_data, "ttl": record_ttl }]}
|
||||
data = {"records": [{"type": record_type, "name": record_name,
|
||||
"data": record_data, "ttl": record_ttl}]}
|
||||
resp, body = self.api.client.post("/domains/%s/records" % \
|
||||
base.getid(domain), body=data)
|
||||
if resp.status == 202:
|
||||
return FutureRecord(self, **body)
|
||||
raise RuntimeError("Did not expect response when creating a DNS record "
|
||||
"%s" % str(resp.status))
|
||||
raise RuntimeError("Did not expect response when creating a DNS "
|
||||
"record %s" % str(resp.status))
|
||||
|
||||
def create_from_list(self, list):
|
||||
return [self.resource_class(self, res) for res in list]
|
||||
@ -143,4 +144,3 @@ class RecordsManager(base.ManagerWithFind):
|
||||
else:
|
||||
raise RuntimeError("Next href had multiple offset params!")
|
||||
return (list, next_offset)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user