Refactored network model access into data abstraction layer.
Also changed the name to floating_ip.
This commit is contained in:
		@@ -25,9 +25,9 @@ import logging
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
#              not true the ugly line below can be removed
 | 
			
		||||
# 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
 | 
			
		||||
#               not true the ugly line below can be removed
 | 
			
		||||
sys.path.append(os.path.abspath(os.path.join(__file__, "../../")))
 | 
			
		||||
 | 
			
		||||
from nova import flags
 | 
			
		||||
@@ -36,6 +36,7 @@ from nova import utils
 | 
			
		||||
from nova.network import linux_net
 | 
			
		||||
from nova.network import service
 | 
			
		||||
from nova import datastore # for redis_db flag
 | 
			
		||||
from nova.auth import manager # for auth flags
 | 
			
		||||
 | 
			
		||||
FLAGS = flags.FLAGS
 | 
			
		||||
 | 
			
		||||
@@ -43,16 +44,16 @@ FLAGS = flags.FLAGS
 | 
			
		||||
def add_lease(_mac, ip, _hostname, _interface):
 | 
			
		||||
    """Set the IP that was assigned by the DHCP server."""
 | 
			
		||||
    if FLAGS.fake_rabbit:
 | 
			
		||||
        logging.debug("leasing_ip")
 | 
			
		||||
        logging.debug("leasing ip")
 | 
			
		||||
        from nova import models
 | 
			
		||||
        print models.FixedIp.count()
 | 
			
		||||
        print models.Network.count()
 | 
			
		||||
        print FLAGS.sql_connection
 | 
			
		||||
        service.VlanNetworkService().lease_ip(ip)
 | 
			
		||||
        service.VlanNetworkService().lease_fixed_ip(ip)
 | 
			
		||||
    else:
 | 
			
		||||
        rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.node_name),
 | 
			
		||||
                 {"method": "lease_ip",
 | 
			
		||||
                  "args": {"fixed_ip_str": ip}})
 | 
			
		||||
                 {"method": "lease_fixed_ip",
 | 
			
		||||
                  "args": {"address": ip}})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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):
 | 
			
		||||
    """Called when a lease expires."""
 | 
			
		||||
    if FLAGS.fake_rabbit:
 | 
			
		||||
        logging.debug("releasing_ip")
 | 
			
		||||
        service.VlanNetworkService().release_ip(ip)
 | 
			
		||||
        logging.debug("releasing ip")
 | 
			
		||||
        service.VlanNetworkService().release_fixed_ip(ip)
 | 
			
		||||
    else:
 | 
			
		||||
        rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.node_name),
 | 
			
		||||
                 {"method": "release_ip",
 | 
			
		||||
                  "args": {"fixed_ip_str": ip}})
 | 
			
		||||
                 {"method": "release_fixed_ip",
 | 
			
		||||
                  "args": {"address": ip}})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def init_leases(interface):
 | 
			
		||||
 
 | 
			
		||||
@@ -311,7 +311,7 @@ class CloudController(object):
 | 
			
		||||
 | 
			
		||||
    def _get_address(self, context, public_ip):
 | 
			
		||||
        # 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):
 | 
			
		||||
            return address
 | 
			
		||||
        raise exception.NotFound("Address at ip %s not found" % public_ip)
 | 
			
		||||
@@ -459,7 +459,7 @@ class CloudController(object):
 | 
			
		||||
 | 
			
		||||
    def format_addresses(self, context):
 | 
			
		||||
        addresses = []
 | 
			
		||||
        for address in network_model.ElasticIp.all():
 | 
			
		||||
        for address in network_model.FloatingIp.all():
 | 
			
		||||
            # TODO(vish): implement a by_project iterator for addresses
 | 
			
		||||
            if (context.user.is_admin() or
 | 
			
		||||
                address['project_id'] == context.project.id):
 | 
			
		||||
@@ -481,7 +481,7 @@ class CloudController(object):
 | 
			
		||||
    def allocate_address(self, context, **kwargs):
 | 
			
		||||
        network_topic = yield self._get_network_topic(context)
 | 
			
		||||
        public_ip = yield rpc.call(network_topic,
 | 
			
		||||
                         {"method": "allocate_elastic_ip",
 | 
			
		||||
                         {"method": "allocate_floating_ip",
 | 
			
		||||
                          "args": {"user_id": context.user.id,
 | 
			
		||||
                                   "project_id": context.project.id}})
 | 
			
		||||
        defer.returnValue({'addressSet': [{'publicIp': public_ip}]})
 | 
			
		||||
@@ -492,8 +492,8 @@ class CloudController(object):
 | 
			
		||||
        # NOTE(vish): Should we make sure this works?
 | 
			
		||||
        network_topic = yield self._get_network_topic(context)
 | 
			
		||||
        rpc.cast(network_topic,
 | 
			
		||||
                         {"method": "deallocate_elastic_ip",
 | 
			
		||||
                          "args": {"elastic_ip": public_ip}})
 | 
			
		||||
                         {"method": "deallocate_floating_ip",
 | 
			
		||||
                          "args": {"floating_ip": public_ip}})
 | 
			
		||||
        defer.returnValue({'releaseResponse': ["Address released."]})
 | 
			
		||||
 | 
			
		||||
    @rbac.allow('netadmin')
 | 
			
		||||
@@ -503,8 +503,8 @@ class CloudController(object):
 | 
			
		||||
        address = self._get_address(context, public_ip)
 | 
			
		||||
        network_topic = yield self._get_network_topic(context)
 | 
			
		||||
        rpc.cast(network_topic,
 | 
			
		||||
                         {"method": "associate_elastic_ip",
 | 
			
		||||
                          "args": {"elastic_ip": address['address'],
 | 
			
		||||
                         {"method": "associate_floating_ip",
 | 
			
		||||
                          "args": {"floating_ip": address['address'],
 | 
			
		||||
                                   "fixed_ip": instance['private_dns_name'],
 | 
			
		||||
                                   "instance_id": instance['instance_id']}})
 | 
			
		||||
        defer.returnValue({'associateResponse': ["Address associated."]})
 | 
			
		||||
@@ -515,8 +515,8 @@ class CloudController(object):
 | 
			
		||||
        address = self._get_address(context, public_ip)
 | 
			
		||||
        network_topic = yield self._get_network_topic(context)
 | 
			
		||||
        rpc.cast(network_topic,
 | 
			
		||||
                         {"method": "disassociate_elastic_ip",
 | 
			
		||||
                          "args": {"elastic_ip": address['address']}})
 | 
			
		||||
                         {"method": "disassociate_floating_ip",
 | 
			
		||||
                          "args": {"floating_ip": address['address']}})
 | 
			
		||||
        defer.returnValue({'disassociateResponse': ["Address disassociated."]})
 | 
			
		||||
 | 
			
		||||
    @defer.inlineCallbacks
 | 
			
		||||
@@ -617,15 +617,15 @@ class CloudController(object):
 | 
			
		||||
                logging.warning("Instance %s was not found during terminate"
 | 
			
		||||
                                % i)
 | 
			
		||||
                continue
 | 
			
		||||
            elastic_ip = network_model.get_public_ip_for_instance(i)
 | 
			
		||||
            if elastic_ip:
 | 
			
		||||
                logging.debug("Disassociating address %s" % elastic_ip)
 | 
			
		||||
            floating_ip = network_model.get_public_ip_for_instance(i)
 | 
			
		||||
            if floating_ip:
 | 
			
		||||
                logging.debug("Disassociating address %s" % floating_ip)
 | 
			
		||||
                # NOTE(vish): Right now we don't really care if the ip is
 | 
			
		||||
                #             disassociated.  We may need to worry about
 | 
			
		||||
                #             checking this later.  Perhaps in the scheduler?
 | 
			
		||||
                rpc.cast(network_topic,
 | 
			
		||||
                         {"method": "disassociate_elastic_ip",
 | 
			
		||||
                          "args": {"elastic_ip": elastic_ip}})
 | 
			
		||||
                         {"method": "disassociate_floating_ip",
 | 
			
		||||
                          "args": {"floating_ip": floating_ip}})
 | 
			
		||||
 | 
			
		||||
            fixed_ip = instance.get('private_dns_name', None)
 | 
			
		||||
            if fixed_ip:
 | 
			
		||||
 
 | 
			
		||||
@@ -278,12 +278,12 @@ class FixedIp(Base, NovaBase):
 | 
			
		||||
            raise exception.NotFound("No model for ip str %s" % ip_str)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ElasticIp(Base, NovaBase):
 | 
			
		||||
    __tablename__ = 'elastic_ips'
 | 
			
		||||
class FloatingIp(Base, NovaBase):
 | 
			
		||||
    __tablename__ = 'floating_ips'
 | 
			
		||||
    id = Column(Integer, primary_key=True)
 | 
			
		||||
    ip_str = Column(String(255), unique=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)
 | 
			
		||||
    node_name = Column(String(255))  #, ForeignKey('physical_node.id'))
 | 
			
		||||
@@ -305,7 +305,7 @@ class Network(Base, NovaBase):
 | 
			
		||||
    kind = Column(String(255))
 | 
			
		||||
 | 
			
		||||
    injected = Column(Boolean, default=False)
 | 
			
		||||
    network_str = Column(String(255))
 | 
			
		||||
    cidr = Column(String(255))
 | 
			
		||||
    netmask = Column(String(255))
 | 
			
		||||
    bridge = Column(String(255))
 | 
			
		||||
    gateway = Column(String(255))
 | 
			
		||||
 
 | 
			
		||||
@@ -21,8 +21,8 @@ Unit Tests for network code
 | 
			
		||||
import IPy
 | 
			
		||||
import os
 | 
			
		||||
import logging
 | 
			
		||||
import tempfile
 | 
			
		||||
 | 
			
		||||
from nova import db
 | 
			
		||||
from nova import exception
 | 
			
		||||
from nova import flags
 | 
			
		||||
from nova import models
 | 
			
		||||
@@ -30,7 +30,6 @@ from nova import test
 | 
			
		||||
from nova import utils
 | 
			
		||||
from nova.auth import manager
 | 
			
		||||
from nova.network import service
 | 
			
		||||
from nova.network.exception import NoMoreAddresses, NoMoreNetworks
 | 
			
		||||
 | 
			
		||||
FLAGS = flags.FLAGS
 | 
			
		||||
 | 
			
		||||
@@ -59,49 +58,52 @@ class NetworkTestCase(test.TrialTestCase):
 | 
			
		||||
                                                             name))
 | 
			
		||||
            # create the necessary network data for the project
 | 
			
		||||
            self.service.set_network_host(self.projects[i].id)
 | 
			
		||||
        instance = models.Instance()
 | 
			
		||||
        instance.mac_address = utils.generate_mac()
 | 
			
		||||
        instance.hostname = 'fake'
 | 
			
		||||
        instance.save()
 | 
			
		||||
        self.instance_id = instance.id
 | 
			
		||||
        instance_id = db.instance_create(None,
 | 
			
		||||
                                         {'mac_address': utils.generate_mac()})
 | 
			
		||||
        self.instance_id = instance_id
 | 
			
		||||
        instance_id = db.instance_create(None,
 | 
			
		||||
                                         {'mac_address': utils.generate_mac()})
 | 
			
		||||
        self.instance2_id = instance_id
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):  # pylint: disable=C0103
 | 
			
		||||
        super(NetworkTestCase, self).tearDown()
 | 
			
		||||
        # TODO(termie): this should really be instantiating clean datastores
 | 
			
		||||
        #               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:
 | 
			
		||||
            self.manager.delete_project(project)
 | 
			
		||||
        self.manager.delete_user(self.user)
 | 
			
		||||
 | 
			
		||||
    def test_public_network_association(self):
 | 
			
		||||
        """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)
 | 
			
		||||
        ip_str = str(pubnet[0])
 | 
			
		||||
        try:
 | 
			
		||||
            elastic_ip = models.ElasticIp.find_by_ip_str(ip_str)
 | 
			
		||||
            floating_ip = models.FloatingIp.find_by_ip_str(ip_str)
 | 
			
		||||
        except exception.NotFound:
 | 
			
		||||
            elastic_ip = models.ElasticIp()
 | 
			
		||||
            elastic_ip.ip_str = ip_str
 | 
			
		||||
            elastic_ip.node_name = FLAGS.node_name
 | 
			
		||||
            elastic_ip.save()
 | 
			
		||||
        eaddress = self.service.allocate_elastic_ip(self.projects[0].id)
 | 
			
		||||
            floating_ip = models.FloatingIp()
 | 
			
		||||
            floating_ip.ip_str = ip_str
 | 
			
		||||
            floating_ip.node_name = FLAGS.node_name
 | 
			
		||||
            floating_ip.save()
 | 
			
		||||
        eaddress = self.service.allocate_floating_ip(self.projects[0].id)
 | 
			
		||||
        faddress = self.service.allocate_fixed_ip(self.projects[0].id,
 | 
			
		||||
                                                 self.instance_id)
 | 
			
		||||
        self.assertEqual(eaddress, str(pubnet[0]))
 | 
			
		||||
        self.service.associate_elastic_ip(eaddress, faddress)
 | 
			
		||||
        self.service.associate_floating_ip(eaddress, faddress)
 | 
			
		||||
        # FIXME datamodel abstraction
 | 
			
		||||
        self.assertEqual(elastic_ip.fixed_ip.ip_str, faddress)
 | 
			
		||||
        self.service.disassociate_elastic_ip(eaddress)
 | 
			
		||||
        self.assertEqual(elastic_ip.fixed_ip, None)
 | 
			
		||||
        self.service.deallocate_elastic_ip(eaddress)
 | 
			
		||||
        self.assertEqual(floating_ip.fixed_ip.ip_str, faddress)
 | 
			
		||||
        self.service.disassociate_floating_ip(eaddress)
 | 
			
		||||
        self.assertEqual(floating_ip.fixed_ip, None)
 | 
			
		||||
        self.service.deallocate_floating_ip(eaddress)
 | 
			
		||||
        self.service.deallocate_fixed_ip(faddress)
 | 
			
		||||
 | 
			
		||||
    def test_allocate_deallocate_fixed_ip(self):
 | 
			
		||||
        """Makes sure that we can allocate and deallocate a fixed ip"""
 | 
			
		||||
        address = self.service.allocate_fixed_ip(self.projects[0].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))
 | 
			
		||||
        issue_ip(address, net.bridge)
 | 
			
		||||
        self.service.deallocate_fixed_ip(address)
 | 
			
		||||
@@ -117,10 +119,10 @@ class NetworkTestCase(test.TrialTestCase):
 | 
			
		||||
        address = self.service.allocate_fixed_ip(self.projects[0].id,
 | 
			
		||||
                                                 self.instance_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)
 | 
			
		||||
        net2 = service.get_network_for_project(self.projects[1].id)
 | 
			
		||||
        net = db.project_get_network(None, self.projects[0].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(address2, self.projects[1].id))
 | 
			
		||||
@@ -151,7 +153,7 @@ class NetworkTestCase(test.TrialTestCase):
 | 
			
		||||
            address = 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)
 | 
			
		||||
            net = service.get_network_for_project(project_id)
 | 
			
		||||
            net = db.project_get_network(None, project_id)
 | 
			
		||||
            issue_ip(address, net.bridge)
 | 
			
		||||
            issue_ip(address2, net.bridge)
 | 
			
		||||
            issue_ip(address3, net.bridge)
 | 
			
		||||
@@ -167,7 +169,7 @@ class NetworkTestCase(test.TrialTestCase):
 | 
			
		||||
            release_ip(address, net.bridge)
 | 
			
		||||
            release_ip(address2, 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)
 | 
			
		||||
 | 
			
		||||
    def test_vpn_ip_and_port_looks_valid(self):
 | 
			
		||||
@@ -186,7 +188,7 @@ class NetworkTestCase(test.TrialTestCase):
 | 
			
		||||
            self.service.set_network_host(project.id)
 | 
			
		||||
            projects.append(project)
 | 
			
		||||
        project = self.manager.create_project('boom' , self.user)
 | 
			
		||||
        self.assertRaises(NoMoreNetworks,
 | 
			
		||||
        self.assertRaises(db.NoMoreNetworks,
 | 
			
		||||
                          self.service.set_network_host,
 | 
			
		||||
                          project.id)
 | 
			
		||||
        self.manager.delete_project(project)
 | 
			
		||||
@@ -198,7 +200,7 @@ class NetworkTestCase(test.TrialTestCase):
 | 
			
		||||
        """Makes sure that ip addresses that are deallocated get reused"""
 | 
			
		||||
        address = self.service.allocate_fixed_ip(self.projects[0].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)
 | 
			
		||||
        self.service.deallocate_fixed_ip(address)
 | 
			
		||||
        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.
 | 
			
		||||
        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
 | 
			
		||||
        total_ips = (available_ips(network) +
 | 
			
		||||
                     reserved_ips(network) +
 | 
			
		||||
@@ -229,7 +231,7 @@ class NetworkTestCase(test.TrialTestCase):
 | 
			
		||||
    def test_too_many_addresses(self):
 | 
			
		||||
        """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
 | 
			
		||||
 | 
			
		||||
@@ -242,7 +244,7 @@ class NetworkTestCase(test.TrialTestCase):
 | 
			
		||||
            issue_ip(addresses[i],network.bridge)
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(available_ips(network), 0)
 | 
			
		||||
        self.assertRaises(NoMoreAddresses,
 | 
			
		||||
        self.assertRaises(db.NoMoreAddresses,
 | 
			
		||||
                          self.service.allocate_fixed_ip,
 | 
			
		||||
                          self.projects[0].id,
 | 
			
		||||
                          self.instance_id)
 | 
			
		||||
@@ -274,11 +276,11 @@ def reserved_ips(network):
 | 
			
		||||
 | 
			
		||||
def is_allocated_in_project(address, project_id):
 | 
			
		||||
    """Returns true if address is in specified project"""
 | 
			
		||||
    fixed_ip = models.FixedIp.find_by_ip_str(address)
 | 
			
		||||
    project_net = service.get_network_for_project(project_id)
 | 
			
		||||
    fixed_ip = db.fixed_ip_get_by_address(None, address)
 | 
			
		||||
    project_net = db.project_get_network(None, project_id)
 | 
			
		||||
    # instance exists until release
 | 
			
		||||
    logging.error('fixed_ip.instance: %s', fixed_ip.instance)
 | 
			
		||||
    logging.error('project_net: %s', project_net)
 | 
			
		||||
    logging.debug('fixed_ip.instance: %s', fixed_ip.instance)
 | 
			
		||||
    logging.debug('project_net: %s', project_net)
 | 
			
		||||
    return fixed_ip.instance is not None and fixed_ip.network == project_net
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user