summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVishvananda Ishaya <vishvananda@yahoo.com>2010-08-17 19:41:17 -0700
committerVishvananda Ishaya <vishvananda@yahoo.com>2010-08-17 19:41:17 -0700
commitc41d9601555c78e3c91fb481fdfb3d50ffdf440b (patch)
tree99b36699753acc67e144380e7ca0f18133db02c7
parentf9214212f1aed4e574f6be6c32a6002a3621625e (diff)
downloadnova-c41d9601555c78e3c91fb481fdfb3d50ffdf440b.tar.gz
nova-c41d9601555c78e3c91fb481fdfb3d50ffdf440b.tar.xz
nova-c41d9601555c78e3c91fb481fdfb3d50ffdf440b.zip
progress on tests passing
-rw-r--r--nova/compute/service.py11
-rw-r--r--nova/models.py50
-rw-r--r--nova/network/service.py46
-rw-r--r--nova/tests/fake_flags.py1
-rw-r--r--nova/tests/network_unittest.py67
-rw-r--r--nova/virt/fake.py16
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,