summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVishvananda Ishaya <vishvananda@gmail.com>2010-08-04 18:00:13 -0700
committerVishvananda Ishaya <vishvananda@gmail.com>2010-08-04 18:00:13 -0700
commitc1e0abd5be3ac8473aaf255f77fb2357b5771ea9 (patch)
tree234182edf00ce44a127fe952ceec9074d67f88b7
parent6b70951e5b7cb8cabe5d6eb50fce7ae0a6e55d52 (diff)
fixed circular reference and tests
-rw-r--r--nova/auth/manager.py4
-rw-r--r--nova/network/model.py89
-rw-r--r--nova/network/networkdata.py116
-rw-r--r--nova/network/service.py5
-rw-r--r--nova/tests/auth_unittest.py14
-rw-r--r--nova/tests/network_unittest.py15
6 files changed, 136 insertions, 107 deletions
diff --git a/nova/auth/manager.py b/nova/auth/manager.py
index dacdeb383..463cfdf4a 100644
--- a/nova/auth/manager.py
+++ b/nova/auth/manager.py
@@ -37,7 +37,7 @@ from nova import objectstore # for flags
from nova import utils
from nova.auth import ldapdriver # for flags
from nova.auth import signer
-from nova.network import model
+from nova.network import networkdata
FLAGS = flags.FLAGS
@@ -529,7 +529,7 @@ class AuthManager(object):
@return: A tuple containing (ip, port) or None, None if vpn has
not been allocated for user.
"""
- network_data = model.NetworkData.lookup(Project.safe_id(project))
+ network_data = networkdata.NetworkData.lookup(Project.safe_id(project))
if not network_data:
raise exception.NotFound('project network data has not been set')
return (network_data.ip, network_data.port)
diff --git a/nova/network/model.py b/nova/network/model.py
index b065d174e..daac035e4 100644
--- a/nova/network/model.py
+++ b/nova/network/model.py
@@ -53,13 +53,6 @@ flags.DEFINE_integer('cnt_vpn_clients', 5,
flags.DEFINE_integer('cloudpipe_start_port', 12000,
'Starting port for mapped CloudPipe external ports')
-flags.DEFINE_string('vpn_ip', utils.get_my_ip(),
- 'Public IP for the cloudpipe VPN servers')
-flags.DEFINE_integer('vpn_start_port', 1000,
- 'Start port for the cloudpipe VPN servers')
-flags.DEFINE_integer('vpn_end_port', 2000,
- 'End port for the cloudpipe VPN servers')
-
logging.getLogger().setLevel(logging.DEBUG)
@@ -381,88 +374,6 @@ class PublicAddress(datastore.BasicModel):
return addr
-class NoMorePorts(exception.Error):
- pass
-
-
-class NetworkData(datastore.BasicModel):
- """Manages network host, and vpn ip and port for projects"""
- def __init__(self, project_id):
- self.project_id = project_id
- super(NetworkData, self).__init__()
-
- @property
- def identifier(self):
- """Identifier used for key in redis"""
- return self.project_id
-
- @classmethod
- def create(cls, project_id):
- """Creates a vpn for project
-
- This method finds a free ip and port and stores the associated
- values in the datastore.
- """
- # TODO(vish): will we ever need multiiple ips per host?
- port = cls.find_free_port_for_ip(FLAGS.vpn_ip)
- network_data = cls(project_id)
- # save ip for project
- network_data['host'] = FLAGS.node_name
- network_data['project'] = project_id
- network_data['ip'] = FLAGS.vpn_ip
- network_data['port'] = port
- network_data.save()
- return network_data
-
- @classmethod
- def find_free_port_for_ip(cls, ip):
- """Finds a free port for a given ip from the redis set"""
- # TODO(vish): these redis commands should be generalized and
- # placed into a base class. Conceptually, it is
- # similar to an association, but we are just
- # storing a set of values instead of keys that
- # should be turned into objects.
- redis = datastore.Redis.instance()
- key = 'ip:%s:ports' % ip
- # TODO(vish): these ports should be allocated through an admin
- # command instead of a flag
- if (not redis.exists(key) and
- not redis.exists(cls._redis_association_name('ip', ip))):
- for i in range(FLAGS.vpn_start_port, FLAGS.vpn_end_port + 1):
- redis.sadd(key, i)
-
- port = redis.spop(key)
- if not port:
- raise NoMorePorts()
- return port
-
- @classmethod
- def num_ports_for_ip(cls, ip):
- """Calculates the number of free ports for a given ip"""
- return datastore.Redis.instance().scard('ip:%s:ports' % ip)
-
- @property
- def ip(self):
- """The ip assigned to the project"""
- return self['ip']
-
- @property
- def port(self):
- """The port assigned to the project"""
- return int(self['port'])
-
- def save(self):
- """Saves the association to the given ip"""
- self.associate_with('ip', self.ip)
- super(NetworkData, self).save()
-
- def destroy(self):
- """Cleans up datastore and adds port back to pool"""
- self.unassociate_with('ip', self.ip)
- datastore.Redis.instance().sadd('ip:%s:ports' % self.ip, self.port)
- super(NetworkData, self).destroy()
-
-
DEFAULT_PORTS = [("tcp",80), ("tcp",22), ("udp",1194), ("tcp",443)]
class PublicNetworkController(BaseNetwork):
override_type = 'network'
diff --git a/nova/network/networkdata.py b/nova/network/networkdata.py
new file mode 100644
index 000000000..cec84287c
--- /dev/null
+++ b/nova/network/networkdata.py
@@ -0,0 +1,116 @@
+# 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.
+
+"""Network Data for projects"""
+
+from nova import datastore
+from nova import exception
+from nova import flags
+from nova import utils
+
+FLAGS = flags.FLAGS
+
+
+flags.DEFINE_string('vpn_ip', utils.get_my_ip(),
+ 'Public IP for the cloudpipe VPN servers')
+flags.DEFINE_integer('vpn_start_port', 1000,
+ 'Start port for the cloudpipe VPN servers')
+flags.DEFINE_integer('vpn_end_port', 2000,
+ 'End port for the cloudpipe VPN servers')
+
+class NoMorePorts(exception.Error):
+ pass
+
+
+class NetworkData(datastore.BasicModel):
+ """Manages network host, and vpn ip and port for projects"""
+ def __init__(self, project_id):
+ self.project_id = project_id
+ super(NetworkData, self).__init__()
+
+ @property
+ def identifier(self):
+ """Identifier used for key in redis"""
+ return self.project_id
+
+ @classmethod
+ def create(cls, project_id):
+ """Creates a vpn for project
+
+ This method finds a free ip and port and stores the associated
+ values in the datastore.
+ """
+ # TODO(vish): will we ever need multiiple ips per host?
+ port = cls.find_free_port_for_ip(FLAGS.vpn_ip)
+ network_data = cls(project_id)
+ # save ip for project
+ network_data['host'] = FLAGS.node_name
+ network_data['project'] = project_id
+ network_data['ip'] = FLAGS.vpn_ip
+ network_data['port'] = port
+ network_data.save()
+ return network_data
+
+ @classmethod
+ def find_free_port_for_ip(cls, ip):
+ """Finds a free port for a given ip from the redis set"""
+ # TODO(vish): these redis commands should be generalized and
+ # placed into a base class. Conceptually, it is
+ # similar to an association, but we are just
+ # storing a set of values instead of keys that
+ # should be turned into objects.
+ redis = datastore.Redis.instance()
+ key = 'ip:%s:ports' % ip
+ # TODO(vish): these ports should be allocated through an admin
+ # command instead of a flag
+ if (not redis.exists(key) and
+ not redis.exists(cls._redis_association_name('ip', ip))):
+ for i in range(FLAGS.vpn_start_port, FLAGS.vpn_end_port + 1):
+ redis.sadd(key, i)
+
+ port = redis.spop(key)
+ if not port:
+ raise NoMorePorts()
+ return port
+
+ @classmethod
+ def num_ports_for_ip(cls, ip):
+ """Calculates the number of free ports for a given ip"""
+ return datastore.Redis.instance().scard('ip:%s:ports' % ip)
+
+ @property
+ def ip(self):
+ """The ip assigned to the project"""
+ return self['ip']
+
+ @property
+ def port(self):
+ """The port assigned to the project"""
+ return int(self['port'])
+
+ def save(self):
+ """Saves the association to the given ip"""
+ self.associate_with('ip', self.ip)
+ super(NetworkData, self).save()
+
+ def destroy(self):
+ """Cleans up datastore and adds port back to pool"""
+ self.unassociate_with('ip', self.ip)
+ datastore.Redis.instance().sadd('ip:%s:ports' % self.ip, self.port)
+ super(NetworkData, self).destroy()
+
diff --git a/nova/network/service.py b/nova/network/service.py
index 243f9a720..afc20c0d5 100644
--- a/nova/network/service.py
+++ b/nova/network/service.py
@@ -28,6 +28,7 @@ from nova.auth import manager
from nova.exception import NotFound
from nova.network import exception
from nova.network import model
+from nova.network import networkdata
FLAGS = flags.FLAGS
@@ -81,7 +82,7 @@ class BaseNetworkService(service.Service):
self.network = model.PublicNetworkController()
def set_network_host(self, user_id, project_id, *args, **kwargs):
- """Safely becomes the host of the projects network"""
+ """Safely sets the host of the projects network"""
redis = datastore.Redis.instance()
key = _host_key(project_id)
if redis.setnx(key, FLAGS.node_name):
@@ -214,7 +215,7 @@ class VlanNetworkService(BaseNetworkService):
def _on_set_network_host(self, user_id, project_id,
*args, **kwargs):
"""Called when this host becomes the host for a project"""
- model.NetworkData.create(project_id)
+ networkdata.NetworkData.create(project_id)
@classmethod
def setup_compute_network(self, user_id, project_id, security_group,
diff --git a/nova/tests/auth_unittest.py b/nova/tests/auth_unittest.py
index 2167c2385..3bd0a432c 100644
--- a/nova/tests/auth_unittest.py
+++ b/nova/tests/auth_unittest.py
@@ -179,20 +179,6 @@ class AuthTestCase(test.BaseTestCase):
self.manager.remove_role('test1', 'sysadmin')
self.assertFalse(project.has_role('test1', 'sysadmin'))
- def test_212_vpn_ip_and_port_looks_valid(self):
- project = self.manager.get_project('testproj')
- self.assert_(project.vpn_ip)
- self.assert_(project.vpn_port >= FLAGS.vpn_start_port)
- self.assert_(project.vpn_port <= FLAGS.vpn_end_port)
-
- def test_213_too_many_vpns(self):
- vpns = []
- for i in xrange(manager.Vpn.num_ports_for_ip(FLAGS.vpn_ip)):
- vpns.append(manager.Vpn.create("vpnuser%s" % i))
- self.assertRaises(manager.NoMorePorts, manager.Vpn.create, "boom")
- for vpn in vpns:
- vpn.destroy()
-
def test_214_can_retrieve_project_by_user(self):
project = self.manager.create_project('testproj2', 'test2', 'Another test project', ['test2'])
self.assert_(len(self.manager.get_projects()) > 1)
diff --git a/nova/tests/network_unittest.py b/nova/tests/network_unittest.py
index 42cae327f..49147d4ec 100644
--- a/nova/tests/network_unittest.py
+++ b/nova/tests/network_unittest.py
@@ -25,6 +25,7 @@ from nova import test
from nova import utils
from nova.auth import manager
from nova.network import model
+from nova.network import networkdata
from nova.network import service
from nova.network.exception import NoMoreAddresses
@@ -154,6 +155,20 @@ class NetworkTestCase(test.TrialTestCase):
rv = self.service.deallocate_fixed_ip(firstaddress)
self.dnsmasq.release_ip(mac, firstaddress, hostname, net.bridge_name)
+ def test_212_vpn_ip_and_port_looks_valid(self):
+ networkdata.NetworkData.create(self.projects[0].id)
+ self.assert_(self.projects[0].vpn_ip)
+ self.assert_(self.projects[0].vpn_port >= FLAGS.vpn_start_port)
+ self.assert_(self.projects[0].vpn_port <= FLAGS.vpn_end_port)
+
+ def test_too_many_vpns(self):
+ vpns = []
+ for i in xrange(networkdata.NetworkData.num_ports_for_ip(FLAGS.vpn_ip)):
+ vpns.append(networkdata.NetworkData.create("vpnuser%s" % i))
+ self.assertRaises(networkdata.NoMorePorts, networkdata.NetworkData.create, "boom")
+ for vpn in vpns:
+ vpn.destroy()
+
def test_release_before_deallocate(self):
pass