Refactored network model access into data abstraction layer.

Also changed the name to floating_ip.
This commit is contained in:
Vishvananda Ishaya
2010-08-23 13:55:16 -07:00
parent 44a796c998
commit e64136c381
4 changed files with 66 additions and 63 deletions

View File

@@ -25,9 +25,9 @@ import logging
import os import os
import sys import sys
#TODO(joshua): there is concern that the user dnsmasq runs under will not # TODO(joshua): there is concern that the user dnsmasq runs under will not
# have nova in the path. This should be verified and if it is # have nova in the path. This should be verified and if it is
# not true the ugly line below can be removed # not true the ugly line below can be removed
sys.path.append(os.path.abspath(os.path.join(__file__, "../../"))) sys.path.append(os.path.abspath(os.path.join(__file__, "../../")))
from nova import flags from nova import flags
@@ -36,6 +36,7 @@ from nova import utils
from nova.network import linux_net from nova.network import linux_net
from nova.network import service from nova.network import service
from nova import datastore # for redis_db flag from nova import datastore # for redis_db flag
from nova.auth import manager # for auth flags
FLAGS = flags.FLAGS FLAGS = flags.FLAGS
@@ -43,16 +44,16 @@ FLAGS = flags.FLAGS
def add_lease(_mac, ip, _hostname, _interface): def add_lease(_mac, ip, _hostname, _interface):
"""Set the IP that was assigned by the DHCP server.""" """Set the IP that was assigned by the DHCP server."""
if FLAGS.fake_rabbit: if FLAGS.fake_rabbit:
logging.debug("leasing_ip") logging.debug("leasing ip")
from nova import models from nova import models
print models.FixedIp.count() print models.FixedIp.count()
print models.Network.count() print models.Network.count()
print FLAGS.sql_connection print FLAGS.sql_connection
service.VlanNetworkService().lease_ip(ip) service.VlanNetworkService().lease_fixed_ip(ip)
else: else:
rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.node_name), rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.node_name),
{"method": "lease_ip", {"method": "lease_fixed_ip",
"args": {"fixed_ip_str": ip}}) "args": {"address": ip}})
def old_lease(_mac, _ip, _hostname, _interface): def old_lease(_mac, _ip, _hostname, _interface):
@@ -63,12 +64,12 @@ def old_lease(_mac, _ip, _hostname, _interface):
def del_lease(_mac, ip, _hostname, _interface): def del_lease(_mac, ip, _hostname, _interface):
"""Called when a lease expires.""" """Called when a lease expires."""
if FLAGS.fake_rabbit: if FLAGS.fake_rabbit:
logging.debug("releasing_ip") logging.debug("releasing ip")
service.VlanNetworkService().release_ip(ip) service.VlanNetworkService().release_fixed_ip(ip)
else: else:
rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.node_name), rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.node_name),
{"method": "release_ip", {"method": "release_fixed_ip",
"args": {"fixed_ip_str": ip}}) "args": {"address": ip}})
def init_leases(interface): def init_leases(interface):

View File

@@ -311,7 +311,7 @@ class CloudController(object):
def _get_address(self, context, public_ip): def _get_address(self, context, public_ip):
# FIXME(vish) this should move into network.py # FIXME(vish) this should move into network.py
address = network_model.ElasticIp.lookup(public_ip) address = network_model.FloatingIp.lookup(public_ip)
if address and (context.user.is_admin() or address['project_id'] == context.project.id): if address and (context.user.is_admin() or address['project_id'] == context.project.id):
return address return address
raise exception.NotFound("Address at ip %s not found" % public_ip) raise exception.NotFound("Address at ip %s not found" % public_ip)
@@ -459,7 +459,7 @@ class CloudController(object):
def format_addresses(self, context): def format_addresses(self, context):
addresses = [] addresses = []
for address in network_model.ElasticIp.all(): for address in network_model.FloatingIp.all():
# TODO(vish): implement a by_project iterator for addresses # TODO(vish): implement a by_project iterator for addresses
if (context.user.is_admin() or if (context.user.is_admin() or
address['project_id'] == context.project.id): address['project_id'] == context.project.id):
@@ -481,7 +481,7 @@ class CloudController(object):
def allocate_address(self, context, **kwargs): def allocate_address(self, context, **kwargs):
network_topic = yield self._get_network_topic(context) network_topic = yield self._get_network_topic(context)
public_ip = yield rpc.call(network_topic, public_ip = yield rpc.call(network_topic,
{"method": "allocate_elastic_ip", {"method": "allocate_floating_ip",
"args": {"user_id": context.user.id, "args": {"user_id": context.user.id,
"project_id": context.project.id}}) "project_id": context.project.id}})
defer.returnValue({'addressSet': [{'publicIp': public_ip}]}) defer.returnValue({'addressSet': [{'publicIp': public_ip}]})
@@ -492,8 +492,8 @@ class CloudController(object):
# NOTE(vish): Should we make sure this works? # NOTE(vish): Should we make sure this works?
network_topic = yield self._get_network_topic(context) network_topic = yield self._get_network_topic(context)
rpc.cast(network_topic, rpc.cast(network_topic,
{"method": "deallocate_elastic_ip", {"method": "deallocate_floating_ip",
"args": {"elastic_ip": public_ip}}) "args": {"floating_ip": public_ip}})
defer.returnValue({'releaseResponse': ["Address released."]}) defer.returnValue({'releaseResponse': ["Address released."]})
@rbac.allow('netadmin') @rbac.allow('netadmin')
@@ -503,8 +503,8 @@ class CloudController(object):
address = self._get_address(context, public_ip) address = self._get_address(context, public_ip)
network_topic = yield self._get_network_topic(context) network_topic = yield self._get_network_topic(context)
rpc.cast(network_topic, rpc.cast(network_topic,
{"method": "associate_elastic_ip", {"method": "associate_floating_ip",
"args": {"elastic_ip": address['address'], "args": {"floating_ip": address['address'],
"fixed_ip": instance['private_dns_name'], "fixed_ip": instance['private_dns_name'],
"instance_id": instance['instance_id']}}) "instance_id": instance['instance_id']}})
defer.returnValue({'associateResponse': ["Address associated."]}) defer.returnValue({'associateResponse': ["Address associated."]})
@@ -515,8 +515,8 @@ class CloudController(object):
address = self._get_address(context, public_ip) address = self._get_address(context, public_ip)
network_topic = yield self._get_network_topic(context) network_topic = yield self._get_network_topic(context)
rpc.cast(network_topic, rpc.cast(network_topic,
{"method": "disassociate_elastic_ip", {"method": "disassociate_floating_ip",
"args": {"elastic_ip": address['address']}}) "args": {"floating_ip": address['address']}})
defer.returnValue({'disassociateResponse': ["Address disassociated."]}) defer.returnValue({'disassociateResponse': ["Address disassociated."]})
@defer.inlineCallbacks @defer.inlineCallbacks
@@ -617,15 +617,15 @@ class CloudController(object):
logging.warning("Instance %s was not found during terminate" logging.warning("Instance %s was not found during terminate"
% i) % i)
continue continue
elastic_ip = network_model.get_public_ip_for_instance(i) floating_ip = network_model.get_public_ip_for_instance(i)
if elastic_ip: if floating_ip:
logging.debug("Disassociating address %s" % elastic_ip) logging.debug("Disassociating address %s" % floating_ip)
# NOTE(vish): Right now we don't really care if the ip is # NOTE(vish): Right now we don't really care if the ip is
# disassociated. We may need to worry about # disassociated. We may need to worry about
# checking this later. Perhaps in the scheduler? # checking this later. Perhaps in the scheduler?
rpc.cast(network_topic, rpc.cast(network_topic,
{"method": "disassociate_elastic_ip", {"method": "disassociate_floating_ip",
"args": {"elastic_ip": elastic_ip}}) "args": {"floating_ip": floating_ip}})
fixed_ip = instance.get('private_dns_name', None) fixed_ip = instance.get('private_dns_name', None)
if fixed_ip: if fixed_ip:

View File

@@ -278,12 +278,12 @@ class FixedIp(Base, NovaBase):
raise exception.NotFound("No model for ip str %s" % ip_str) raise exception.NotFound("No model for ip str %s" % ip_str)
class ElasticIp(Base, NovaBase): class FloatingIp(Base, NovaBase):
__tablename__ = 'elastic_ips' __tablename__ = 'floating_ips'
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)
ip_str = Column(String(255), unique=True) ip_str = Column(String(255), unique=True)
fixed_ip_id = Column(Integer, ForeignKey('fixed_ips.id'), nullable=True) fixed_ip_id = Column(Integer, ForeignKey('fixed_ips.id'), nullable=True)
fixed_ip = relationship(FixedIp, backref=backref('elastic_ips')) fixed_ip = relationship(FixedIp, backref=backref('floating_ips'))
project_id = Column(String(255)) #, ForeignKey('projects.id'), nullable=False) project_id = Column(String(255)) #, ForeignKey('projects.id'), nullable=False)
node_name = Column(String(255)) #, ForeignKey('physical_node.id')) node_name = Column(String(255)) #, ForeignKey('physical_node.id'))
@@ -305,7 +305,7 @@ class Network(Base, NovaBase):
kind = Column(String(255)) kind = Column(String(255))
injected = Column(Boolean, default=False) injected = Column(Boolean, default=False)
network_str = Column(String(255)) cidr = Column(String(255))
netmask = Column(String(255)) netmask = Column(String(255))
bridge = Column(String(255)) bridge = Column(String(255))
gateway = Column(String(255)) gateway = Column(String(255))

View File

@@ -21,8 +21,8 @@ Unit Tests for network code
import IPy import IPy
import os import os
import logging import logging
import tempfile
from nova import db
from nova import exception from nova import exception
from nova import flags from nova import flags
from nova import models from nova import models
@@ -30,7 +30,6 @@ from nova import test
from nova import utils from nova import utils
from nova.auth import manager from nova.auth import manager
from nova.network import service from nova.network import service
from nova.network.exception import NoMoreAddresses, NoMoreNetworks
FLAGS = flags.FLAGS FLAGS = flags.FLAGS
@@ -59,49 +58,52 @@ class NetworkTestCase(test.TrialTestCase):
name)) name))
# create the necessary network data for the project # create the necessary network data for the project
self.service.set_network_host(self.projects[i].id) self.service.set_network_host(self.projects[i].id)
instance = models.Instance() instance_id = db.instance_create(None,
instance.mac_address = utils.generate_mac() {'mac_address': utils.generate_mac()})
instance.hostname = 'fake' self.instance_id = instance_id
instance.save() instance_id = db.instance_create(None,
self.instance_id = instance.id {'mac_address': utils.generate_mac()})
self.instance2_id = instance_id
def tearDown(self): # pylint: disable=C0103 def tearDown(self): # pylint: disable=C0103
super(NetworkTestCase, self).tearDown() super(NetworkTestCase, self).tearDown()
# TODO(termie): this should really be instantiating clean datastores # TODO(termie): this should really be instantiating clean datastores
# in between runs, one failure kills all the tests # in between runs, one failure kills all the tests
db.instance_destroy(None, self.instance_id)
db.instance_destroy(None, self.instance2_id)
for project in self.projects: for project in self.projects:
self.manager.delete_project(project) self.manager.delete_project(project)
self.manager.delete_user(self.user) self.manager.delete_user(self.user)
def test_public_network_association(self): def test_public_network_association(self):
"""Makes sure that we can allocaate a public ip""" """Makes sure that we can allocaate a public ip"""
# FIXME better way of adding elastic ips # TODO(vish): better way of adding floating ips
pubnet = IPy.IP(flags.FLAGS.public_range) pubnet = IPy.IP(flags.FLAGS.public_range)
ip_str = str(pubnet[0]) ip_str = str(pubnet[0])
try: try:
elastic_ip = models.ElasticIp.find_by_ip_str(ip_str) floating_ip = models.FloatingIp.find_by_ip_str(ip_str)
except exception.NotFound: except exception.NotFound:
elastic_ip = models.ElasticIp() floating_ip = models.FloatingIp()
elastic_ip.ip_str = ip_str floating_ip.ip_str = ip_str
elastic_ip.node_name = FLAGS.node_name floating_ip.node_name = FLAGS.node_name
elastic_ip.save() floating_ip.save()
eaddress = self.service.allocate_elastic_ip(self.projects[0].id) eaddress = self.service.allocate_floating_ip(self.projects[0].id)
faddress = self.service.allocate_fixed_ip(self.projects[0].id, faddress = self.service.allocate_fixed_ip(self.projects[0].id,
self.instance_id) self.instance_id)
self.assertEqual(eaddress, str(pubnet[0])) self.assertEqual(eaddress, str(pubnet[0]))
self.service.associate_elastic_ip(eaddress, faddress) self.service.associate_floating_ip(eaddress, faddress)
# FIXME datamodel abstraction # FIXME datamodel abstraction
self.assertEqual(elastic_ip.fixed_ip.ip_str, faddress) self.assertEqual(floating_ip.fixed_ip.ip_str, faddress)
self.service.disassociate_elastic_ip(eaddress) self.service.disassociate_floating_ip(eaddress)
self.assertEqual(elastic_ip.fixed_ip, None) self.assertEqual(floating_ip.fixed_ip, None)
self.service.deallocate_elastic_ip(eaddress) self.service.deallocate_floating_ip(eaddress)
self.service.deallocate_fixed_ip(faddress) self.service.deallocate_fixed_ip(faddress)
def test_allocate_deallocate_fixed_ip(self): def test_allocate_deallocate_fixed_ip(self):
"""Makes sure that we can allocate and deallocate a fixed ip""" """Makes sure that we can allocate and deallocate a fixed ip"""
address = self.service.allocate_fixed_ip(self.projects[0].id, address = self.service.allocate_fixed_ip(self.projects[0].id,
self.instance_id) self.instance_id)
net = service.get_network_for_project(self.projects[0].id) net = db.project_get_network(None, self.projects[0].id)
self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) self.assertTrue(is_allocated_in_project(address, self.projects[0].id))
issue_ip(address, net.bridge) issue_ip(address, net.bridge)
self.service.deallocate_fixed_ip(address) self.service.deallocate_fixed_ip(address)
@@ -117,10 +119,10 @@ class NetworkTestCase(test.TrialTestCase):
address = self.service.allocate_fixed_ip(self.projects[0].id, address = self.service.allocate_fixed_ip(self.projects[0].id,
self.instance_id) self.instance_id)
address2 = self.service.allocate_fixed_ip(self.projects[1].id, address2 = self.service.allocate_fixed_ip(self.projects[1].id,
self.instance_id) self.instance2_id)
net = service.get_network_for_project(self.projects[0].id) net = db.project_get_network(None, self.projects[0].id)
net2 = service.get_network_for_project(self.projects[1].id) net2 = db.project_get_network(None, self.projects[1].id)
self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) self.assertTrue(is_allocated_in_project(address, self.projects[0].id))
self.assertTrue(is_allocated_in_project(address2, self.projects[1].id)) self.assertTrue(is_allocated_in_project(address2, self.projects[1].id))
@@ -151,7 +153,7 @@ class NetworkTestCase(test.TrialTestCase):
address = self.service.allocate_fixed_ip(project_id, self.instance_id) address = self.service.allocate_fixed_ip(project_id, self.instance_id)
address2 = self.service.allocate_fixed_ip(project_id, self.instance_id) address2 = self.service.allocate_fixed_ip(project_id, self.instance_id)
address3 = self.service.allocate_fixed_ip(project_id, self.instance_id) address3 = self.service.allocate_fixed_ip(project_id, self.instance_id)
net = service.get_network_for_project(project_id) net = db.project_get_network(None, project_id)
issue_ip(address, net.bridge) issue_ip(address, net.bridge)
issue_ip(address2, net.bridge) issue_ip(address2, net.bridge)
issue_ip(address3, net.bridge) issue_ip(address3, net.bridge)
@@ -167,7 +169,7 @@ class NetworkTestCase(test.TrialTestCase):
release_ip(address, net.bridge) release_ip(address, net.bridge)
release_ip(address2, net.bridge) release_ip(address2, net.bridge)
release_ip(address3, net.bridge) release_ip(address3, net.bridge)
net = service.get_network_for_project(self.projects[0].id) net = db.project_get_network(None, self.projects[0].id)
self.service.deallocate_fixed_ip(first) self.service.deallocate_fixed_ip(first)
def test_vpn_ip_and_port_looks_valid(self): def test_vpn_ip_and_port_looks_valid(self):
@@ -186,7 +188,7 @@ class NetworkTestCase(test.TrialTestCase):
self.service.set_network_host(project.id) self.service.set_network_host(project.id)
projects.append(project) projects.append(project)
project = self.manager.create_project('boom' , self.user) project = self.manager.create_project('boom' , self.user)
self.assertRaises(NoMoreNetworks, self.assertRaises(db.NoMoreNetworks,
self.service.set_network_host, self.service.set_network_host,
project.id) project.id)
self.manager.delete_project(project) self.manager.delete_project(project)
@@ -198,7 +200,7 @@ class NetworkTestCase(test.TrialTestCase):
"""Makes sure that ip addresses that are deallocated get reused""" """Makes sure that ip addresses that are deallocated get reused"""
address = self.service.allocate_fixed_ip(self.projects[0].id, address = self.service.allocate_fixed_ip(self.projects[0].id,
self.instance_id) self.instance_id)
net = service.get_network_for_project(self.projects[0].id) net = db.project_get_network(None, self.projects[0].id)
issue_ip(address, net.bridge) issue_ip(address, net.bridge)
self.service.deallocate_fixed_ip(address) self.service.deallocate_fixed_ip(address)
release_ip(address, net.bridge) release_ip(address, net.bridge)
@@ -219,7 +221,7 @@ class NetworkTestCase(test.TrialTestCase):
There are ips reserved at the bottom and top of the range. There are ips reserved at the bottom and top of the range.
services (network, gateway, CloudPipe, broadcast) services (network, gateway, CloudPipe, broadcast)
""" """
network = service.get_network_for_project(self.projects[0].id) network = db.project_get_network(None, self.projects[0].id)
net_size = flags.FLAGS.network_size net_size = flags.FLAGS.network_size
total_ips = (available_ips(network) + total_ips = (available_ips(network) +
reserved_ips(network) + reserved_ips(network) +
@@ -229,7 +231,7 @@ class NetworkTestCase(test.TrialTestCase):
def test_too_many_addresses(self): def test_too_many_addresses(self):
"""Test for a NoMoreAddresses exception when all fixed ips are used. """Test for a NoMoreAddresses exception when all fixed ips are used.
""" """
network = service.get_network_for_project(self.projects[0].id) network = db.project_get_network(None, self.projects[0].id)
# Number of availaible ips is len of the available list # Number of availaible ips is len of the available list
@@ -242,7 +244,7 @@ class NetworkTestCase(test.TrialTestCase):
issue_ip(addresses[i],network.bridge) issue_ip(addresses[i],network.bridge)
self.assertEqual(available_ips(network), 0) self.assertEqual(available_ips(network), 0)
self.assertRaises(NoMoreAddresses, self.assertRaises(db.NoMoreAddresses,
self.service.allocate_fixed_ip, self.service.allocate_fixed_ip,
self.projects[0].id, self.projects[0].id,
self.instance_id) self.instance_id)
@@ -274,11 +276,11 @@ def reserved_ips(network):
def is_allocated_in_project(address, project_id): def is_allocated_in_project(address, project_id):
"""Returns true if address is in specified project""" """Returns true if address is in specified project"""
fixed_ip = models.FixedIp.find_by_ip_str(address) fixed_ip = db.fixed_ip_get_by_address(None, address)
project_net = service.get_network_for_project(project_id) project_net = db.project_get_network(None, project_id)
# instance exists until release # instance exists until release
logging.error('fixed_ip.instance: %s', fixed_ip.instance) logging.debug('fixed_ip.instance: %s', fixed_ip.instance)
logging.error('project_net: %s', project_net) logging.debug('project_net: %s', project_net)
return fixed_ip.instance is not None and fixed_ip.network == project_net return fixed_ip.instance is not None and fixed_ip.network == project_net