summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Day <eday@oddments.org>2010-12-30 15:43:41 -0800
committerEric Day <eday@oddments.org>2010-12-30 15:43:41 -0800
commit71d715d422a746f4951877d8ff76e0ace355281e (patch)
treeaf70d798ec4310447fd7e10e0dd232b860a336fb
parent750a0c9b413ad3912d522355332cffadd9667d0c (diff)
downloadnova-71d715d422a746f4951877d8ff76e0ace355281e.tar.gz
nova-71d715d422a746f4951877d8ff76e0ace355281e.tar.xz
nova-71d715d422a746f4951877d8ff76e0ace355281e.zip
Moved network operation code in ec2 api into a generic network API class. Removed a circular dependency with compute/quota.
-rw-r--r--nova/api/ec2/cloud.py59
-rw-r--r--nova/compute/__init__.py20
-rw-r--r--nova/network/__init__.py79
-rw-r--r--nova/quota.py8
-rw-r--r--nova/tests/test_quota.py6
5 files changed, 93 insertions, 79 deletions
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 5ffc301be..d68c598e9 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -36,7 +36,7 @@ from nova import crypto
from nova import db
from nova import exception
from nova import flags
-from nova import quota
+from nova import network
from nova import rpc
from nova import utils
from nova import volume
@@ -87,11 +87,10 @@ class CloudController(object):
sent to the other nodes.
"""
def __init__(self):
- self.network_manager = utils.import_object(FLAGS.network_manager)
self.image_service = utils.import_object(FLAGS.image_service)
+ self.network_api = network.API()
self.volume_api = volume.API()
- self.compute_api = compute.API(self.network_manager,
- self.image_service,
+ self.compute_api = compute.API(self.image_service, self.network_api,
self.volume_api)
self.setup()
@@ -629,64 +628,20 @@ class CloudController(object):
return {'addressesSet': addresses}
def allocate_address(self, context, **kwargs):
- # check quota
- if quota.allowed_floating_ips(context, 1) < 1:
- logging.warn(_("Quota exceeeded for %s, tried to allocate "
- "address"),
- context.project_id)
- raise quota.QuotaError(_("Address quota exceeded. You cannot "
- "allocate any more addresses"))
- # NOTE(vish): We don't know which network host should get the ip
- # when we allocate, so just send it to any one. This
- # will probably need to move into a network supervisor
- # at some point.
- public_ip = rpc.call(context,
- FLAGS.network_topic,
- {"method": "allocate_floating_ip",
- "args": {"project_id": context.project_id}})
+ public_ip = self.network_api.allocate_floating_ip(context)
return {'addressSet': [{'publicIp': public_ip}]}
def release_address(self, context, public_ip, **kwargs):
- floating_ip_ref = db.floating_ip_get_by_address(context, public_ip)
- # NOTE(vish): We don't know which network host should get the ip
- # when we deallocate, so just send it to any one. This
- # will probably need to move into a network supervisor
- # at some point.
- rpc.cast(context,
- FLAGS.network_topic,
- {"method": "deallocate_floating_ip",
- "args": {"floating_address": floating_ip_ref['address']}})
+ self.network_api.release_floating_ip(context, public_ip)
return {'releaseResponse': ["Address released."]}
def associate_address(self, context, instance_id, public_ip, **kwargs):
instance_id = ec2_id_to_id(instance_id)
- instance_ref = self.compute_api.get(context, instance_id)
- fixed_address = db.instance_get_fixed_address(context,
- instance_ref['id'])
- floating_ip_ref = db.floating_ip_get_by_address(context, public_ip)
- # NOTE(vish): Perhaps we should just pass this on to compute and
- # let compute communicate with network.
- network_topic = self.compute_api.get_network_topic(context,
- instance_id)
- rpc.cast(context,
- network_topic,
- {"method": "associate_floating_ip",
- "args": {"floating_address": floating_ip_ref['address'],
- "fixed_address": fixed_address}})
+ self.compute_api.associate_floating_ip(context, instance_id, public_ip)
return {'associateResponse': ["Address associated."]}
def disassociate_address(self, context, public_ip, **kwargs):
- floating_ip_ref = db.floating_ip_get_by_address(context, public_ip)
- # NOTE(vish): Get the topic from the host name of the network of
- # the associated fixed ip.
- if not floating_ip_ref.get('fixed_ip'):
- raise exception.ApiError('Address is not associated.')
- host = floating_ip_ref['fixed_ip']['network']['host']
- topic = db.queue_get_for(context, FLAGS.network_topic, host)
- rpc.cast(context,
- topic,
- {"method": "disassociate_floating_ip",
- "args": {"floating_address": floating_ip_ref['address']}})
+ self.network_api.disassociate_floating_ip(context, public_ip)
return {'disassociateResponse': ["Address disassociated."]}
def run_instances(self, context, **kwargs):
diff --git a/nova/compute/__init__.py b/nova/compute/__init__.py
index fd1cdcd1b..14c242641 100644
--- a/nova/compute/__init__.py
+++ b/nova/compute/__init__.py
@@ -27,6 +27,7 @@ import time
from nova import db
from nova import exception
from nova import flags
+from nova import network
from nova import quota
from nova import rpc
from nova import utils
@@ -45,14 +46,14 @@ def generate_default_hostname(instance_id):
class API(base.Base):
"""API for interacting with the compute manager."""
- def __init__(self, network_manager=None, image_service=None,
- volume_api=None, **kwargs):
- if not network_manager:
- network_manager = utils.import_object(FLAGS.network_manager)
- self.network_manager = network_manager
+ def __init__(self, image_service=None, network_api=None, volume_api=None,
+ **kwargs):
if not image_service:
image_service = utils.import_object(FLAGS.image_service)
self.image_service = image_service
+ if not network_api:
+ network_api = network.API()
+ self.network_api = network_api
if not volume_api:
volume_api = volume.API()
self.volume_api = volume_api
@@ -83,8 +84,9 @@ class API(base.Base):
"""Create the number of instances requested if quota and
other arguments check out ok."""
+ type_data = instance_types.INSTANCE_TYPES[instance_type]
num_instances = quota.allowed_instances(context, max_count,
- instance_type)
+ type_data['vcpus'])
if num_instances < min_count:
logging.warn("Quota exceeeded for %s, tried to run %s instances",
context.project_id, min_count)
@@ -127,7 +129,6 @@ class API(base.Base):
key_pair = db.key_pair_get(context, context.user_id, key_name)
key_data = key_pair['public_key']
- type_data = instance_types.INSTANCE_TYPES[instance_type]
base_options = {
'reservation_id': utils.generate_uid('r'),
'image_id': image_id,
@@ -336,3 +337,8 @@ class API(base.Base):
"args": {"instance_id": instance['id'],
"volume_id": volume_id}})
return instance
+
+ def associate_floating_ip(self, context, instance_id, address):
+ instance = self.get(context, instance_id)
+ self.network_api.associate_floating_ip(context, address,
+ instance['fixed_ip'])
diff --git a/nova/network/__init__.py b/nova/network/__init__.py
index dcc54db09..cbd912047 100644
--- a/nova/network/__init__.py
+++ b/nova/network/__init__.py
@@ -17,16 +17,71 @@
# under the License.
"""
-:mod:`nova.network` -- Network Nodes
-=====================================================
-
-.. automodule:: nova.network
- :platform: Unix
- :synopsis: Network is responsible for managing networking
-.. moduleauthor:: Jesse Andrews <jesse@ansolabs.com>
-.. moduleauthor:: Devin Carlen <devin.carlen@gmail.com>
-.. moduleauthor:: Vishvananda Ishaya <vishvananda@yahoo.com>
-.. moduleauthor:: Joshua McKenty <joshua@cognition.ca>
-.. moduleauthor:: Manish Singh <yosh@gimp.org>
-.. moduleauthor:: Andy Smith <andy@anarkystic.com>
+Handles all requests relating to instances (guest vms).
"""
+
+import logging
+
+from nova import db
+from nova import flags
+from nova import quota
+from nova import rpc
+from nova.db import base
+
+FLAGS = flags.FLAGS
+
+
+class API(base.Base):
+ """API for interacting with the network manager."""
+
+ def allocate_floating_ip(self, context):
+ if quota.allowed_floating_ips(context, 1) < 1:
+ logging.warn(_("Quota exceeeded for %s, tried to allocate "
+ "address"),
+ context.project_id)
+ raise quota.QuotaError(_("Address quota exceeded. You cannot "
+ "allocate any more addresses"))
+ # NOTE(vish): We don't know which network host should get the ip
+ # when we allocate, so just send it to any one. This
+ # will probably need to move into a network supervisor
+ # at some point.
+ return rpc.call(context,
+ FLAGS.network_topic,
+ {"method": "allocate_floating_ip",
+ "args": {"project_id": context.project_id}})
+
+ def release_floating_ip(self, context, address):
+ floating_ip = self.db.floating_ip_get_by_address(context, address)
+ # NOTE(vish): We don't know which network host should get the ip
+ # when we deallocate, so just send it to any one. This
+ # will probably need to move into a network supervisor
+ # at some point.
+ rpc.cast(context,
+ FLAGS.network_topic,
+ {"method": "deallocate_floating_ip",
+ "args": {"floating_address": floating_ip['address']}})
+
+ def associate_floating_ip(self, context, floating_ip, fixed_ip):
+ if isinstance(fixed_ip, str) or isinstance(fixed_ip, unicode):
+ fixed_ip = self.db.fixed_ip_get_by_address(context, fixed_ip)
+ floating_ip = self.db.floating_ip_get_by_address(context, floating_ip)
+ # NOTE(vish): Perhaps we should just pass this on to compute and
+ # let compute communicate with network.
+ host = fixed_ip['network']['host']
+ rpc.cast(context,
+ self.db.queue_get_for(context, FLAGS.network_topic, host),
+ {"method": "associate_floating_ip",
+ "args": {"floating_address": floating_ip['address'],
+ "fixed_address": fixed_ip['address']}})
+
+ def disassociate_floating_ip(self, context, address):
+ floating_ip = self.db.floating_ip_get_by_address(context, address)
+ if not floating_ip.get('fixed_ip'):
+ raise exception.ApiError('Address is not associated.')
+ # NOTE(vish): Get the topic from the host name of the network of
+ # the associated fixed ip.
+ host = floating_ip['fixed_ip']['network']['host']
+ rpc.cast(context,
+ self.db.queue_get_for(context, FLAGS.network_topic, host),
+ {"method": "disassociate_floating_ip",
+ "args": {"floating_address": floating_ip['address']}})
diff --git a/nova/quota.py b/nova/quota.py
index f6ca9f77c..12dbfcf43 100644
--- a/nova/quota.py
+++ b/nova/quota.py
@@ -22,7 +22,6 @@ Quotas for instances, volumes, and floating ips
from nova import db
from nova import exception
from nova import flags
-from nova.compute import instance_types
FLAGS = flags.FLAGS
@@ -54,7 +53,7 @@ def get_quota(context, project_id):
return rval
-def allowed_instances(context, num_instances, instance_type):
+def allowed_instances(context, num_instances, cores_per_instance):
"""Check quota and return min(num_instances, allowed_instances)"""
project_id = context.project_id
context = context.elevated()
@@ -63,10 +62,9 @@ def allowed_instances(context, num_instances, instance_type):
quota = get_quota(context, project_id)
allowed_instances = quota['instances'] - used_instances
allowed_cores = quota['cores'] - used_cores
- type_cores = instance_types.INSTANCE_TYPES[instance_type]['vcpus']
- num_cores = num_instances * type_cores
+ num_cores = num_instances * cores_per_instance
allowed_instances = min(allowed_instances,
- int(allowed_cores // type_cores))
+ int(allowed_cores // cores_per_instance))
return min(num_instances, allowed_instances)
diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py
index 8cf2a5e54..c15818774 100644
--- a/nova/tests/test_quota.py
+++ b/nova/tests/test_quota.py
@@ -78,14 +78,14 @@ class QuotaTestCase(test.TestCase):
def test_quota_overrides(self):
"""Make sure overriding a projects quotas works"""
- num_instances = quota.allowed_instances(self.context, 100, 'm1.small')
+ num_instances = quota.allowed_instances(self.context, 100, 1)
self.assertEqual(num_instances, 2)
db.quota_create(self.context, {'project_id': self.project.id,
'instances': 10})
- num_instances = quota.allowed_instances(self.context, 100, 'm1.small')
+ num_instances = quota.allowed_instances(self.context, 100, 1)
self.assertEqual(num_instances, 4)
db.quota_update(self.context, self.project.id, {'cores': 100})
- num_instances = quota.allowed_instances(self.context, 100, 'm1.small')
+ num_instances = quota.allowed_instances(self.context, 100, 1)
self.assertEqual(num_instances, 10)
db.quota_destroy(self.context, self.project.id)