diff options
| author | Vishvananda Ishaya <vishvananda@yahoo.com> | 2010-08-17 19:41:17 -0700 |
|---|---|---|
| committer | Vishvananda Ishaya <vishvananda@yahoo.com> | 2010-08-17 19:41:17 -0700 |
| commit | c41d9601555c78e3c91fb481fdfb3d50ffdf440b (patch) | |
| tree | 99b36699753acc67e144380e7ca0f18133db02c7 | |
| parent | f9214212f1aed4e574f6be6c32a6002a3621625e (diff) | |
| download | nova-c41d9601555c78e3c91fb481fdfb3d50ffdf440b.tar.gz nova-c41d9601555c78e3c91fb481fdfb3d50ffdf440b.tar.xz nova-c41d9601555c78e3c91fb481fdfb3d50ffdf440b.zip | |
progress on tests passing
| -rw-r--r-- | nova/compute/service.py | 11 | ||||
| -rw-r--r-- | nova/models.py | 50 | ||||
| -rw-r--r-- | nova/network/service.py | 46 | ||||
| -rw-r--r-- | nova/tests/fake_flags.py | 1 | ||||
| -rw-r--r-- | nova/tests/network_unittest.py | 67 | ||||
| -rw-r--r-- | nova/virt/fake.py | 16 |
6 files changed, 121 insertions, 70 deletions
diff --git a/nova/compute/service.py b/nova/compute/service.py index 13507a1bb..708134072 100644 --- a/nova/compute/service.py +++ b/nova/compute/service.py @@ -25,25 +25,19 @@ Compute Service: """ import base64 -import json import logging import os -import sys from twisted.internet import defer -from twisted.internet import task from nova import exception from nova import flags from nova import process from nova import service from nova import utils -from nova.compute import disk from nova import models from nova.compute import power_state -from nova.compute.instance_types import INSTANCE_TYPES from nova.network import service as network_service -from nova.objectstore import image # for image_path flag from nova.virt import connection as virt_connection from nova.volume import service as volume_service @@ -107,14 +101,15 @@ class ComputeService(service.Service): @exception.wrap_exception def run_instance(self, instance_id, **_kwargs): """ launch a new instance with specified options """ - if str(instance_id) in self._conn.list_instances(): + inst = models.Instance.find(instance_id) + if inst.name in self._conn.list_instances(): raise exception.Error("Instance has already been created") logging.debug("Starting instance %s..." % (instance_id)) inst = models.Instance.find(instance_id) # NOTE(vish): passing network type allows us to express the # network without making a call to network to find # out which type of network to setup - network_service.setup_compute_network(inst) + network_service.setup_compute_network(inst.project_id) inst.node_name = FLAGS.node_name inst.save() diff --git a/nova/models.py b/nova/models.py index 88627ae06..5fc4ba1cf 100644 --- a/nova/models.py +++ b/nova/models.py @@ -1,11 +1,43 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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. + +""" +SQLAlchemy models for nova data +""" +import os + from sqlalchemy.orm import relationship, backref, validates, exc -from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey, DateTime, Boolean, Text +from sqlalchemy import Table, Column, Integer, String +from sqlalchemy import MetaData, ForeignKey, DateTime, Boolean, Text from sqlalchemy.ext.declarative import declarative_base + from nova import auth from nova import exception +from nova import flags + +FLAGS=flags.FLAGS Base = declarative_base() +flags.DEFINE_string('sql_connection', + 'sqlite:///%s/nova.sqlite' % os.path.abspath("./"), + 'connection string for sql database') + class NovaBase(object): created_at = Column(DateTime) updated_at = Column(DateTime) @@ -17,7 +49,7 @@ class NovaBase(object): if NovaBase._engine is not None: return NovaBase._engine from sqlalchemy import create_engine - NovaBase._engine = create_engine('sqlite:////root/nova.sqlite', echo=False) + NovaBase._engine = create_engine(FLAGS.sql_connection, echo=False) Base.metadata.create_all(NovaBase._engine) return NovaBase._engine @@ -35,6 +67,11 @@ class NovaBase(object): return session.query(cls).all() @classmethod + def count(cls): + session = NovaBase.get_session() + return session.query(cls).count() + + @classmethod def find(cls, obj_id): session = NovaBase.get_session() #print cls @@ -136,7 +173,6 @@ class Instance(Base, NovaBase): reservation_id = Column(String) mac_address = Column(String) - fixed_ip = Column(String) def set_state(self, state_code, state_description=None): from nova.compute import power_state @@ -209,7 +245,7 @@ class NetworkIndex(Base, NovaBase): id = Column(Integer, primary_key=True) index = Column(Integer) network_id = Column(Integer, ForeignKey('networks.id'), nullable=True) - network = relationship(Network, backref=backref('vpn', + network = relationship(Network, backref=backref('network_index', uselist=False)) @@ -220,8 +256,6 @@ class FixedIp(Base, NovaBase): ip_str = Column(String, unique=True) network_id = Column(Integer, ForeignKey('networks.id'), nullable=False) network = relationship(Network, backref=backref('fixed_ips')) - instance = relationship(Instance, backref=backref('fixed_ip', - uselist=False)) instance_id = Column(Integer, ForeignKey('instances.id'), nullable=True) instance = relationship(Instance, backref=backref('fixed_ip', uselist=False)) @@ -241,8 +275,8 @@ class ElasticIp(Base, NovaBase): __tablename__ = 'elastic_ips' id = Column(Integer, primary_key=True) ip_str = Column(String, unique=True) - fixed_ip_id = Column(Integer, ForeignKey('fixed_ip.id'), nullable=True) - fixed_ip = relationship(Network, backref=backref('elastic_ips')) + fixed_ip_id = Column(Integer, ForeignKey('fixed_ips.id'), nullable=True) + fixed_ip = relationship(FixedIp, backref=backref('elastic_ips')) project_id = Column(String) #, ForeignKey('projects.id'), nullable=False) # FIXME: should be physical_node_id = Column(Integer) diff --git a/nova/network/service.py b/nova/network/service.py index 8ddc4bc84..115a7fa98 100644 --- a/nova/network/service.py +++ b/nova/network/service.py @@ -56,7 +56,7 @@ flags.DEFINE_string('flat_network_dns', '8.8.4.4', 'Dns for simple network') flags.DEFINE_integer('vlan_start', 100, 'First VLAN for private networks') -flags.DEFINE_integer('vlan_end', 4093, 'Last VLAN for private networks') +flags.DEFINE_integer('num_networks', 1000, 'Number of networks to support') flags.DEFINE_string('vpn_ip', utils.get_my_ip(), 'Public IP for the cloudpipe VPN servers') flags.DEFINE_integer('vpn_start', 1000, 'First Vpn port for private networks') @@ -90,7 +90,7 @@ def get_network_for_project(project_id): """Get network allocated to project from datastore""" project = manager.AuthManager().get_project(project_id) if not project: - raise exception.NotFound() + raise exception.NotFound("Couldn't find project %s" % project_id) return project.network @@ -121,14 +121,15 @@ class BaseNetworkService(service.Service): def allocate_fixed_ip(self, project_id, instance_id, *args, **kwargs): """Gets fixed ip from the pool""" + print "allocating", project_id, instance_id + network = get_network_for_project(project_id) session = models.NovaBase.get_session() - query = session.query(models.FixedIp).filter_by(project_id=project_id) + query = session.query(models.FixedIp).filter_by(network_id=network.id) query = query.filter_by(allocated=False).filter_by(reserved=False) query = query.filter_by(leased=False) while(True): - try: - fixed_ip = query.first() - except exc.NoResultFound: + fixed_ip = query.first() + if not fixed_ip: raise network_exception.NoMoreAddresses() # FIXME will this set backreference? fixed_ip.instance_id = instance_id @@ -225,6 +226,18 @@ class FlatNetworkService(BaseNetworkService): class VlanNetworkService(BaseNetworkService): """Vlan network with dhcp""" + def __init__(self, *args, **kwargs): + super(VlanNetworkService, self).__init__(*args, **kwargs) + self._ensure_network_indexes() + + def _ensure_network_indexes(self): + # NOTE(vish): this should probably be removed and added via + # admin command or fixtures + if models.NetworkIndex.count() == 0: + for i in range(FLAGS.num_networks): + network_index = models.NetworkIndex() + network_index.index = i + network_index.save() def allocate_fixed_ip(self, project_id, instance_id, is_vpn=False, *args, **kwargs): @@ -285,9 +298,7 @@ class VlanNetworkService(BaseNetworkService): def _on_set_network_host(self, network): """Called when this host becomes the host for a project""" - # FIXME add indexes to datastore - # index = self._get_network_index(network) - index = 0 + index = self._get_network_index(network) private_net = IPy.IP(FLAGS.private_range) start = index * FLAGS.network_size # minus one for the gateway. @@ -296,21 +307,22 @@ class VlanNetworkService(BaseNetworkService): vlan = FLAGS.vlan_start + index project_net = IPy.IP(network_str) network.network_str = network_str - network.netmask = project_net.netmask() + network.netmask = str(project_net.netmask()) network.vlan = vlan network.bridge = 'br%s' % vlan - network.gateway = project_net.gateway() - network.broadcast = project_net.broadast() - network.vpn_private_ip_str = project_net[2] + network.gateway = str(project_net[1]) + network.broadcast = str(project_net.broadcast()) + network.vpn_private_ip_str = str(project_net[2]) network.vpn_public_ip_str = FLAGS.vpn_ip network.vpn_public_port = FLAGS.vpn_start + index # create network fixed ips BOTTOM_RESERVED = 3 - TOP_RESERVED = 1 + FLAGS.vpn_client_cnt - for i in range(len(project_net)): + TOP_RESERVED = 1 + FLAGS.cnt_vpn_clients + num_ips = len(project_net) + for i in range(num_ips): fixed_ip = models.FixedIp() - fixed_ip.ip_str = project_net[i] - if i < BOTTOM_RESERVED or i > TOP_RESERVED: + fixed_ip.ip_str = str(project_net[i]) + if i < BOTTOM_RESERVED or num_ips - i < TOP_RESERVED: fixed_ip.reserved = True fixed_ip.network = network fixed_ip.save() diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py index a7310fb26..ecbc65937 100644 --- a/nova/tests/fake_flags.py +++ b/nova/tests/fake_flags.py @@ -26,3 +26,4 @@ FLAGS.fake_rabbit = True FLAGS.fake_network = True FLAGS.auth_driver = 'nova.auth.ldapdriver.FakeLdapDriver' FLAGS.verbose = True +FLAGS.sql_connection = 'sqlite:///:memory:' diff --git a/nova/tests/network_unittest.py b/nova/tests/network_unittest.py index 72dc88f27..8b7730d87 100644 --- a/nova/tests/network_unittest.py +++ b/nova/tests/network_unittest.py @@ -23,6 +23,7 @@ import os import logging from nova import flags +from nova import models from nova import test from nova import utils from nova.auth import manager @@ -47,16 +48,20 @@ class NetworkTestCase(test.TrialTestCase): self.manager = manager.AuthManager() self.user = self.manager.create_user('netuser', 'netuser', 'netuser') self.projects = [] - self.projects.append(self.manager.create_project('netuser', - 'netuser', - 'netuser')) + self.service = service.VlanNetworkService() for i in range(0, 6): name = 'project%s' % i self.projects.append(self.manager.create_project(name, 'netuser', name)) - vpn.NetworkData.create(self.projects[i].id) - self.service = service.VlanNetworkService() + # 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.image_id = 'fake' + instance.save() + self.instance = instance def tearDown(self): # pylint: disable=C0103 super(NetworkTestCase, self).tearDown() @@ -67,32 +72,34 @@ class NetworkTestCase(test.TrialTestCase): def test_public_network_allocation(self): """Makes sure that we can allocaate a public ip""" pubnet = IPy.IP(flags.FLAGS.public_range) - address = self.service.allocate_elastic_ip(self.user.id, - self.projects[0].id) + address = self.service.allocate_elastic_ip(self.projects[0].id) self.assertTrue(IPy.IP(address) in pubnet) def test_allocate_deallocate_fixed_ip(self): """Makes sure that we can allocate and deallocate a fixed ip""" - result = self.service.allocate_fixed_ip( - self.user.id, self.projects[0].id) - address = result['private_dns_name'] - mac = result['mac_address'] - net = model.get_project_network(self.projects[0].id, "default") + address = self.service.allocate_fixed_ip(self.projects[0].id, + self.instance.id) + net = service.get_project_network(self.projects[0].id) self.assertEqual(True, is_in_project(address, self.projects[0].id)) - hostname = "test-host" - issue_ip(mac, address, hostname, net.bridge_name) + issue_ip(self.instance.mac_address, + address, + self.instance.hostname, + net.bridge) self.service.deallocate_fixed_ip(address) # Doesn't go away until it's dhcp released self.assertEqual(True, is_in_project(address, self.projects[0].id)) - release_ip(mac, address, hostname, net.bridge_name) + release_ip(self.instance.mac_address, + address, + self.instance.hostname, + net.bridge) self.assertEqual(False, is_in_project(address, self.projects[0].id)) def test_side_effects(self): """Ensures allocating and releasing has no side effects""" hostname = "side-effect-host" - result = self.service.allocate_fixed_ip(self.user.id, + result = self.service.allocate_fixed_ip( self.projects[0].id) mac = result['mac_address'] address = result['private_dns_name'] @@ -101,8 +108,8 @@ class NetworkTestCase(test.TrialTestCase): secondmac = result['mac_address'] secondaddress = result['private_dns_name'] - net = model.get_project_network(self.projects[0].id, "default") - secondnet = model.get_project_network(self.projects[1].id, "default") + net = service.get_project_network(self.projects[0].id) + secondnet = service.get_project_network(self.projects[1].id) self.assertEqual(True, is_in_project(address, self.projects[0].id)) self.assertEqual(True, is_in_project(secondaddress, @@ -128,7 +135,7 @@ class NetworkTestCase(test.TrialTestCase): def test_subnet_edge(self): """Makes sure that private ips don't overlap""" - result = self.service.allocate_fixed_ip(self.user.id, + result = self.service.allocate_fixed_ip( self.projects[0].id) firstaddress = result['private_dns_name'] hostname = "toomany-hosts" @@ -146,7 +153,7 @@ class NetworkTestCase(test.TrialTestCase): self.user, project_id) mac3 = result['mac_address'] address3 = result['private_dns_name'] - net = model.get_project_network(project_id, "default") + net = service.get_project_network(project_id) issue_ip(mac, address, hostname, net.bridge_name) issue_ip(mac2, address2, hostname, net.bridge_name) issue_ip(mac3, address3, hostname, net.bridge_name) @@ -162,7 +169,7 @@ class NetworkTestCase(test.TrialTestCase): release_ip(mac, address, hostname, net.bridge_name) release_ip(mac2, address2, hostname, net.bridge_name) release_ip(mac3, address3, hostname, net.bridge_name) - net = model.get_project_network(self.projects[0].id, "default") + net = service.get_project_network(self.projects[0].id) self.service.deallocate_fixed_ip(firstaddress) release_ip(mac, firstaddress, hostname, net.bridge_name) @@ -184,12 +191,12 @@ class NetworkTestCase(test.TrialTestCase): def test_ips_are_reused(self): """Makes sure that ip addresses that are deallocated get reused""" result = self.service.allocate_fixed_ip( - self.user.id, self.projects[0].id) + self.projects[0].id) mac = result['mac_address'] address = result['private_dns_name'] hostname = "reuse-host" - net = model.get_project_network(self.projects[0].id, "default") + net = service.get_project_network(self.projects[0].id) issue_ip(mac, address, hostname, net.bridge_name) self.service.deallocate_fixed_ip(address) @@ -215,7 +222,7 @@ class NetworkTestCase(test.TrialTestCase): There are ips reserved at the bottom and top of the range. services (network, gateway, CloudPipe, broadcast) """ - net = model.get_project_network(self.projects[0].id, "default") + net = service.get_project_network(self.projects[0].id) num_preallocated_ips = len(net.assigned) net_size = flags.FLAGS.network_size num_available_ips = net_size - (net.num_bottom_reserved_ips + @@ -226,7 +233,7 @@ class NetworkTestCase(test.TrialTestCase): def test_too_many_addresses(self): """Test for a NoMoreAddresses exception when all fixed ips are used. """ - net = model.get_project_network(self.projects[0].id, "default") + net = service.get_project_network(self.projects[0].id) hostname = "toomany-hosts" macs = {} @@ -234,15 +241,17 @@ class NetworkTestCase(test.TrialTestCase): # Number of availaible ips is len of the available list num_available_ips = len(list(net.available)) for i in range(num_available_ips): - result = self.service.allocate_fixed_ip(self.user.id, + result = self.service.allocate_fixed_ip( self.projects[0].id) macs[i] = result['mac_address'] addresses[i] = result['private_dns_name'] issue_ip(macs[i], addresses[i], hostname, net.bridge_name) self.assertEqual(len(list(net.available)), 0) - self.assertRaises(NoMoreAddresses, self.service.allocate_fixed_ip, - self.user.id, self.projects[0].id) + self.assertRaises(NoMoreAddresses, + self.service.allocate_fixed_ip, + self.projects[0].id, + 0) for i in range(len(addresses)): self.service.deallocate_fixed_ip(addresses[i]) @@ -252,7 +261,7 @@ class NetworkTestCase(test.TrialTestCase): def is_in_project(address, project_id): """Returns true if address is in specified project""" - return address in model.get_project_network(project_id).assigned + return models.FixedIp.find_by_ip_str(address) == service.get_project_network(project_id) def binpath(script): diff --git a/nova/virt/fake.py b/nova/virt/fake.py index f7ee34695..060b53729 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -103,7 +103,7 @@ class FakeConnection(object): """ fake_instance = FakeInstance() - self.instances[instance.id] = fake_instance + self.instances[instance.name] = fake_instance fake_instance._state = power_state.RUNNING return defer.succeed(None) @@ -132,7 +132,7 @@ class FakeConnection(object): del self.instances[instance.name] return defer.succeed(None) - def get_info(self, instance_id): + def get_info(self, instance_name): """ Get a block of information about the given instance. This is returned as a dictionary containing 'state': The power_state of the instance, @@ -141,14 +141,14 @@ class FakeConnection(object): of virtual CPUs the instance has, 'cpu_time': The total CPU time used by the instance, in nanoseconds. """ - i = self.instances[instance_id] + i = self.instances[instance_name] return {'state': i._state, 'max_mem': 0, 'mem': 0, 'num_cpu': 2, 'cpu_time': 0} - def list_disks(self, instance_id): + def list_disks(self, instance_name): """ Return the IDs of all the virtual disks attached to the specified instance, as a list. These IDs are opaque to the caller (they are @@ -160,7 +160,7 @@ class FakeConnection(object): """ return ['A_DISK'] - def list_interfaces(self, instance_id): + def list_interfaces(self, instance_name): """ Return the IDs of all the virtual network interfaces attached to the specified instance, as a list. These IDs are opaque to the caller @@ -173,10 +173,10 @@ class FakeConnection(object): """ return ['A_VIF'] - def block_stats(self, instance_id, disk_id): + def block_stats(self, instance_name, disk_id): """ Return performance counters associated with the given disk_id on the - given instance_id. These are returned as [rd_req, rd_bytes, wr_req, + given instance_name. These are returned as [rd_req, rd_bytes, wr_req, wr_bytes, errs], where rd indicates read, wr indicates write, req is the total number of I/O requests made, bytes is the total number of bytes transferred, and errs is the number of requests held up due to a @@ -194,7 +194,7 @@ class FakeConnection(object): """ return [0L, 0L, 0L, 0L, null] - def interface_stats(self, instance_id, iface_id): + def interface_stats(self, instance_name, iface_id): """ Return performance counters associated with the given iface_id on the given instance_id. These are returned as [rx_bytes, rx_packets, |
