Merge trunk
This commit is contained in:
		@@ -69,3 +69,150 @@ table.docutils {
 | 
			
		||||
.tweet_list li .tweet_avatar {
 | 
			
		||||
    float: left;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------
 | 
			
		||||
PURE CSS SPEECH BUBBLES
 | 
			
		||||
by Nicolas Gallagher
 | 
			
		||||
- http://nicolasgallagher.com/pure-css-speech-bubbles/
 | 
			
		||||
 | 
			
		||||
http://nicolasgallagher.com
 | 
			
		||||
http://twitter.com/necolas
 | 
			
		||||
 | 
			
		||||
Created: 02 March 2010
 | 
			
		||||
Version: 1.1 (21 October 2010)
 | 
			
		||||
 | 
			
		||||
Dual licensed under MIT and GNU GPLv2 © Nicolas Gallagher 
 | 
			
		||||
------------------------------------------ */
 | 
			
		||||
/* THE SPEECH BUBBLE
 | 
			
		||||
------------------------------------------------------------------------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
/* THE SPEECH BUBBLE
 | 
			
		||||
------------------------------------------------------------------------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
.triangle-border {
 | 
			
		||||
	position:relative;
 | 
			
		||||
	padding:15px;
 | 
			
		||||
	margin:1em 0 3em;
 | 
			
		||||
	border:5px solid #BC1518;
 | 
			
		||||
	color:#333;
 | 
			
		||||
	background:#fff;
 | 
			
		||||
	
 | 
			
		||||
	/* css3 */
 | 
			
		||||
	-moz-border-radius:10px;
 | 
			
		||||
	-webkit-border-radius:10px;
 | 
			
		||||
	border-radius:10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Variant : for left positioned triangle
 | 
			
		||||
------------------------------------------ */
 | 
			
		||||
 | 
			
		||||
.triangle-border.left {
 | 
			
		||||
	margin-left:30px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Variant : for right positioned triangle
 | 
			
		||||
------------------------------------------ */
 | 
			
		||||
 | 
			
		||||
.triangle-border.right {
 | 
			
		||||
	margin-right:30px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* THE TRIANGLE
 | 
			
		||||
------------------------------------------------------------------------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
.triangle-border:before {
 | 
			
		||||
	content:"";
 | 
			
		||||
	display:block; /* reduce the damage in FF3.0 */
 | 
			
		||||
	position:absolute;
 | 
			
		||||
	bottom:-40px; /* value = - border-top-width - border-bottom-width */
 | 
			
		||||
	left:40px; /* controls horizontal position */
 | 
			
		||||
	width:0;
 | 
			
		||||
	height:0;
 | 
			
		||||
	border:20px solid transparent;
 | 
			
		||||
	border-top-color:#BC1518;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* creates the smaller  triangle */
 | 
			
		||||
.triangle-border:after {
 | 
			
		||||
	content:"";
 | 
			
		||||
	display:block; /* reduce the damage in FF3.0 */
 | 
			
		||||
	position:absolute;
 | 
			
		||||
	bottom:-26px; /* value = - border-top-width - border-bottom-width */
 | 
			
		||||
	left:47px; /* value = (:before left) + (:before border-left) - (:after border-left) */
 | 
			
		||||
	width:0;
 | 
			
		||||
	height:0;
 | 
			
		||||
	border:13px solid transparent;
 | 
			
		||||
	border-top-color:#fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Variant : top
 | 
			
		||||
------------------------------------------ */
 | 
			
		||||
 | 
			
		||||
/* creates the larger triangle */
 | 
			
		||||
.triangle-border.top:before {
 | 
			
		||||
	top:-40px; /* value = - border-top-width - border-bottom-width */
 | 
			
		||||
	right:40px; /* controls horizontal position */
 | 
			
		||||
	bottom:auto;
 | 
			
		||||
	left:auto;
 | 
			
		||||
	border:20px solid transparent;
 | 
			
		||||
	border-bottom-color:#BC1518;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* creates the smaller  triangle */
 | 
			
		||||
.triangle-border.top:after {
 | 
			
		||||
	top:-26px; /* value = - border-top-width - border-bottom-width */
 | 
			
		||||
	right:47px; /* value = (:before right) + (:before border-right) - (:after border-right) */
 | 
			
		||||
	bottom:auto;
 | 
			
		||||
	left:auto;
 | 
			
		||||
	border:13px solid transparent;
 | 
			
		||||
	border-bottom-color:#fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Variant : left
 | 
			
		||||
------------------------------------------ */
 | 
			
		||||
 | 
			
		||||
/* creates the larger triangle */
 | 
			
		||||
.triangle-border.left:before {
 | 
			
		||||
	top:10px; /* controls vertical position */
 | 
			
		||||
	left:-30px; /* value = - border-left-width - border-right-width */
 | 
			
		||||
	bottom:auto;
 | 
			
		||||
	border-width:15px 30px 15px 0;
 | 
			
		||||
	border-style:solid;
 | 
			
		||||
	border-color:transparent #BC1518;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* creates the smaller  triangle */
 | 
			
		||||
.triangle-border.left:after {
 | 
			
		||||
	top:16px; /* value = (:before top) + (:before border-top) - (:after border-top) */
 | 
			
		||||
	left:-21px; /* value = - border-left-width - border-right-width */
 | 
			
		||||
	bottom:auto;
 | 
			
		||||
	border-width:9px 21px 9px 0;
 | 
			
		||||
	border-style:solid;
 | 
			
		||||
	border-color:transparent #fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Variant : right
 | 
			
		||||
------------------------------------------ */
 | 
			
		||||
 | 
			
		||||
/* creates the larger triangle */
 | 
			
		||||
.triangle-border.right:before {
 | 
			
		||||
	top:10px; /* controls vertical position */
 | 
			
		||||
	right:-30px; /* value = - border-left-width - border-right-width */
 | 
			
		||||
	bottom:auto;
 | 
			
		||||
    left:auto;
 | 
			
		||||
	border-width:15px 0 15px 30px;
 | 
			
		||||
	border-style:solid;
 | 
			
		||||
	border-color:transparent #BC1518;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* creates the smaller  triangle */
 | 
			
		||||
.triangle-border.right:after {
 | 
			
		||||
	top:16px; /* value = (:before top) + (:before border-top) - (:after border-top) */
 | 
			
		||||
	right:-21px; /* value = - border-left-width - border-right-width */
 | 
			
		||||
	bottom:auto;
 | 
			
		||||
    left:auto;
 | 
			
		||||
	border-width:9px 0 9px 21px;
 | 
			
		||||
	border-style:solid;
 | 
			
		||||
	border-color:transparent #fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -71,14 +71,23 @@
 | 
			
		||||
              </p>
 | 
			
		||||
          </div>
 | 
			
		||||
          <script type="text/javascript">$('#searchbox').show(0);</script>
 | 
			
		||||
          
 | 
			
		||||
          <p class="triangle-border right">
 | 
			
		||||
				Psst... hey. You're reading the latest content, but it might be out of sync with code. You can read <a href="http://nova.openstack.org/2011.1">Nova 2011.1 docs</a> or <a href="http://docs.openstack.org">all OpenStack docs</a> too.
 | 
			
		||||
			</p>
 | 
			
		||||
          
 | 
			
		||||
          {%- endif %}
 | 
			
		||||
 | 
			
		||||
          {%- if pagename == "index" %}
 | 
			
		||||
          
 | 
			
		||||
          
 | 
			
		||||
          <h3>{{ _('Twitter Feed') }}</h3>
 | 
			
		||||
                <div id="twitter_feed" class='twitter_feed'></div>
 | 
			
		||||
          {%- endif %}
 | 
			
		||||
          
 | 
			
		||||
          
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
          {%- endblock %}
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -90,6 +90,21 @@ class ComputeTestCase(test.TestCase):
 | 
			
		||||
        inst.update(params)
 | 
			
		||||
        return db.instance_create(self.context, inst)['id']
 | 
			
		||||
 | 
			
		||||
    def _create_instance_type(self, params={}):
 | 
			
		||||
        """Create a test instance"""
 | 
			
		||||
        context = self.context.elevated()
 | 
			
		||||
        inst = {}
 | 
			
		||||
        inst['name'] = 'm1.small'
 | 
			
		||||
        inst['memory_mb'] = '1024'
 | 
			
		||||
        inst['vcpus'] = '1'
 | 
			
		||||
        inst['local_gb'] = '20'
 | 
			
		||||
        inst['flavorid'] = '1'
 | 
			
		||||
        inst['swap'] = '2048'
 | 
			
		||||
        inst['rxtx_quota'] = 100
 | 
			
		||||
        inst['rxtx_cap'] = 200
 | 
			
		||||
        inst.update(params)
 | 
			
		||||
        return db.instance_type_create(context, inst)['id']
 | 
			
		||||
 | 
			
		||||
    def _create_group(self):
 | 
			
		||||
        values = {'name': 'testgroup',
 | 
			
		||||
                  'description': 'testgroup',
 | 
			
		||||
@@ -307,15 +322,53 @@ class ComputeTestCase(test.TestCase):
 | 
			
		||||
        """Ensure instance can be migrated/resized"""
 | 
			
		||||
        instance_id = self._create_instance()
 | 
			
		||||
        context = self.context.elevated()
 | 
			
		||||
 | 
			
		||||
        self.compute.run_instance(self.context, instance_id)
 | 
			
		||||
        db.instance_update(self.context, instance_id, {'host': 'foo'})
 | 
			
		||||
        self.compute.prep_resize(context, instance_id)
 | 
			
		||||
        self.compute.prep_resize(context, instance_id, 1)
 | 
			
		||||
        migration_ref = db.migration_get_by_instance_and_status(context,
 | 
			
		||||
                instance_id, 'pre-migrating')
 | 
			
		||||
        self.compute.resize_instance(context, instance_id,
 | 
			
		||||
                migration_ref['id'])
 | 
			
		||||
        self.compute.terminate_instance(context, instance_id)
 | 
			
		||||
 | 
			
		||||
    def test_resize_invalid_flavor_fails(self):
 | 
			
		||||
        """Ensure invalid flavors raise"""
 | 
			
		||||
        instance_id = self._create_instance()
 | 
			
		||||
        context = self.context.elevated()
 | 
			
		||||
        self.compute.run_instance(self.context, instance_id)
 | 
			
		||||
 | 
			
		||||
        self.assertRaises(exception.NotFound, self.compute_api.resize,
 | 
			
		||||
                context, instance_id, 200)
 | 
			
		||||
 | 
			
		||||
        self.compute.terminate_instance(context, instance_id)
 | 
			
		||||
 | 
			
		||||
    def test_resize_down_fails(self):
 | 
			
		||||
        """Ensure resizing down raises and fails"""
 | 
			
		||||
        context = self.context.elevated()
 | 
			
		||||
        instance_id = self._create_instance()
 | 
			
		||||
 | 
			
		||||
        self.compute.run_instance(self.context, instance_id)
 | 
			
		||||
        db.instance_update(self.context, instance_id,
 | 
			
		||||
                {'instance_type': 'm1.xlarge'})
 | 
			
		||||
 | 
			
		||||
        self.assertRaises(exception.ApiError, self.compute_api.resize,
 | 
			
		||||
                context, instance_id, 1)
 | 
			
		||||
 | 
			
		||||
        self.compute.terminate_instance(context, instance_id)
 | 
			
		||||
 | 
			
		||||
    def test_resize_same_size_fails(self):
 | 
			
		||||
        """Ensure invalid flavors raise"""
 | 
			
		||||
        context = self.context.elevated()
 | 
			
		||||
        instance_id = self._create_instance()
 | 
			
		||||
 | 
			
		||||
        self.compute.run_instance(self.context, instance_id)
 | 
			
		||||
 | 
			
		||||
        self.assertRaises(exception.ApiError, self.compute_api.resize,
 | 
			
		||||
                context, instance_id, 1)
 | 
			
		||||
 | 
			
		||||
        self.compute.terminate_instance(context, instance_id)
 | 
			
		||||
 | 
			
		||||
    def test_get_by_flavor_id(self):
 | 
			
		||||
        type = instance_types.get_by_flavor_id(1)
 | 
			
		||||
        self.assertEqual(type, 'm1.tiny')
 | 
			
		||||
@@ -326,10 +379,8 @@ class ComputeTestCase(test.TestCase):
 | 
			
		||||
        instance_id = self._create_instance()
 | 
			
		||||
        self.compute.run_instance(self.context, instance_id)
 | 
			
		||||
        self.assertRaises(exception.Error, self.compute.prep_resize,
 | 
			
		||||
                self.context, instance_id)
 | 
			
		||||
                self.context, instance_id, 1)
 | 
			
		||||
        self.compute.terminate_instance(self.context, instance_id)
 | 
			
		||||
        type = instance_types.get_by_flavor_id("1")
 | 
			
		||||
        self.assertEqual(type, 'm1.tiny')
 | 
			
		||||
 | 
			
		||||
    def _setup_other_managers(self):
 | 
			
		||||
        self.volume_manager = utils.import_object(FLAGS.volume_manager)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										161
									
								
								nova/tests/test_flat_network.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								nova/tests/test_flat_network.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,161 @@
 | 
			
		||||
# 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.
 | 
			
		||||
"""
 | 
			
		||||
Unit Tests for flat network code
 | 
			
		||||
"""
 | 
			
		||||
import IPy
 | 
			
		||||
import os
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
from nova import context
 | 
			
		||||
from nova import db
 | 
			
		||||
from nova import exception
 | 
			
		||||
from nova import flags
 | 
			
		||||
from nova import log as logging
 | 
			
		||||
from nova import test
 | 
			
		||||
from nova import utils
 | 
			
		||||
from nova.auth import manager
 | 
			
		||||
from nova.tests.network import base
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
FLAGS = flags.FLAGS
 | 
			
		||||
LOG = logging.getLogger('nova.tests.network')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FlatNetworkTestCase(base.NetworkTestCase):
 | 
			
		||||
    """Test cases for network code"""
 | 
			
		||||
    def test_public_network_association(self):
 | 
			
		||||
        """Makes sure that we can allocate a public ip"""
 | 
			
		||||
        # TODO(vish): better way of adding floating ips
 | 
			
		||||
 | 
			
		||||
        self.context._project = self.projects[0]
 | 
			
		||||
        self.context.project_id = self.projects[0].id
 | 
			
		||||
        pubnet = IPy.IP(flags.FLAGS.floating_range)
 | 
			
		||||
        address = str(pubnet[0])
 | 
			
		||||
        try:
 | 
			
		||||
            db.floating_ip_get_by_address(context.get_admin_context(), address)
 | 
			
		||||
        except exception.NotFound:
 | 
			
		||||
            db.floating_ip_create(context.get_admin_context(),
 | 
			
		||||
                                  {'address': address,
 | 
			
		||||
                                   'host': FLAGS.host})
 | 
			
		||||
 | 
			
		||||
        self.assertRaises(NotImplementedError,
 | 
			
		||||
                          self.network.allocate_floating_ip,
 | 
			
		||||
                          self.context, self.projects[0].id)
 | 
			
		||||
 | 
			
		||||
        fix_addr = self._create_address(0)
 | 
			
		||||
        float_addr = address
 | 
			
		||||
        self.assertRaises(NotImplementedError,
 | 
			
		||||
                          self.network.associate_floating_ip,
 | 
			
		||||
                          self.context, float_addr, fix_addr)
 | 
			
		||||
 | 
			
		||||
        address = db.instance_get_floating_address(context.get_admin_context(),
 | 
			
		||||
                                                   self.instance_id)
 | 
			
		||||
        self.assertEqual(address, None)
 | 
			
		||||
 | 
			
		||||
        self.assertRaises(NotImplementedError,
 | 
			
		||||
                          self.network.disassociate_floating_ip,
 | 
			
		||||
                          self.context, float_addr)
 | 
			
		||||
 | 
			
		||||
        address = db.instance_get_floating_address(context.get_admin_context(),
 | 
			
		||||
                                                   self.instance_id)
 | 
			
		||||
        self.assertEqual(address, None)
 | 
			
		||||
 | 
			
		||||
        self.assertRaises(NotImplementedError,
 | 
			
		||||
                          self.network.deallocate_floating_ip,
 | 
			
		||||
                          self.context, float_addr)
 | 
			
		||||
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, fix_addr)
 | 
			
		||||
        db.floating_ip_destroy(context.get_admin_context(), float_addr)
 | 
			
		||||
 | 
			
		||||
    def test_allocate_deallocate_fixed_ip(self):
 | 
			
		||||
        """Makes sure that we can allocate and deallocate a fixed ip"""
 | 
			
		||||
        address = self._create_address(0)
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address,
 | 
			
		||||
                                                      self.projects[0].id))
 | 
			
		||||
        self._deallocate_address(0, address)
 | 
			
		||||
 | 
			
		||||
        # check if the fixed ip address is really deallocated
 | 
			
		||||
        self.assertFalse(self._is_allocated_in_project(address,
 | 
			
		||||
                                                       self.projects[0].id))
 | 
			
		||||
 | 
			
		||||
    def test_side_effects(self):
 | 
			
		||||
        """Ensures allocating and releasing has no side effects"""
 | 
			
		||||
        address = self._create_address(0)
 | 
			
		||||
        address2 = self._create_address(1, self.instance2_id)
 | 
			
		||||
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address,
 | 
			
		||||
                                                      self.projects[0].id))
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address2,
 | 
			
		||||
                                                      self.projects[1].id))
 | 
			
		||||
 | 
			
		||||
        self._deallocate_address(0, address)
 | 
			
		||||
        self.assertFalse(self._is_allocated_in_project(address,
 | 
			
		||||
                                                       self.projects[0].id))
 | 
			
		||||
 | 
			
		||||
        # First address release shouldn't affect the second
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address2,
 | 
			
		||||
                                                      self.projects[0].id))
 | 
			
		||||
 | 
			
		||||
        self._deallocate_address(1, address2)
 | 
			
		||||
        self.assertFalse(self._is_allocated_in_project(address2,
 | 
			
		||||
                                                 self.projects[1].id))
 | 
			
		||||
 | 
			
		||||
    def test_ips_are_reused(self):
 | 
			
		||||
        """Makes sure that ip addresses that are deallocated get reused"""
 | 
			
		||||
        address = self._create_address(0)
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, address)
 | 
			
		||||
 | 
			
		||||
        address2 = self._create_address(0)
 | 
			
		||||
        self.assertEqual(address, address2)
 | 
			
		||||
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, address2)
 | 
			
		||||
 | 
			
		||||
    def test_too_many_addresses(self):
 | 
			
		||||
        """Test for a NoMoreAddresses exception when all fixed ips are used.
 | 
			
		||||
        """
 | 
			
		||||
        admin_context = context.get_admin_context()
 | 
			
		||||
        network = db.project_get_network(admin_context, self.projects[0].id)
 | 
			
		||||
        num_available_ips = db.network_count_available_ips(admin_context,
 | 
			
		||||
                                                           network['id'])
 | 
			
		||||
        addresses = []
 | 
			
		||||
        instance_ids = []
 | 
			
		||||
        for i in range(num_available_ips):
 | 
			
		||||
            instance_ref = self._create_instance(0)
 | 
			
		||||
            instance_ids.append(instance_ref['id'])
 | 
			
		||||
            address = self._create_address(0, instance_ref['id'])
 | 
			
		||||
            addresses.append(address)
 | 
			
		||||
 | 
			
		||||
        ip_count = db.network_count_available_ips(context.get_admin_context(),
 | 
			
		||||
                                                  network['id'])
 | 
			
		||||
        self.assertEqual(ip_count, 0)
 | 
			
		||||
        self.assertRaises(db.NoMoreAddresses,
 | 
			
		||||
                          self.network.allocate_fixed_ip,
 | 
			
		||||
                          self.context,
 | 
			
		||||
                          'foo')
 | 
			
		||||
 | 
			
		||||
        for i in range(num_available_ips):
 | 
			
		||||
            self.network.deallocate_fixed_ip(self.context, addresses[i])
 | 
			
		||||
            db.instance_destroy(context.get_admin_context(), instance_ids[i])
 | 
			
		||||
        ip_count = db.network_count_available_ips(context.get_admin_context(),
 | 
			
		||||
                                                  network['id'])
 | 
			
		||||
        self.assertEqual(ip_count, num_available_ips)
 | 
			
		||||
 | 
			
		||||
    def run(self, result=None):
 | 
			
		||||
        if(FLAGS.network_manager == 'nova.network.manager.FlatManager'):
 | 
			
		||||
            super(FlatNetworkTestCase, self).run(result)
 | 
			
		||||
@@ -21,9 +21,10 @@ import sys
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
import nova
 | 
			
		||||
from nova import test
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LocalizationTestCase(unittest.TestCase):
 | 
			
		||||
class LocalizationTestCase(test.TestCase):
 | 
			
		||||
    def test_multiple_positional_format_placeholders(self):
 | 
			
		||||
        pat = re.compile("\W_\(")
 | 
			
		||||
        single_pat = re.compile("\W%\W")
 | 
			
		||||
 
 | 
			
		||||
@@ -18,8 +18,12 @@ import errno
 | 
			
		||||
import os
 | 
			
		||||
import select
 | 
			
		||||
 | 
			
		||||
from eventlet import greenpool
 | 
			
		||||
from eventlet import greenthread
 | 
			
		||||
 | 
			
		||||
from nova import test
 | 
			
		||||
from nova.utils import parse_mailmap, str_dict_replace, synchronized
 | 
			
		||||
from nova import utils
 | 
			
		||||
from nova.utils import parse_mailmap, str_dict_replace
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProjectTestCase(test.TestCase):
 | 
			
		||||
@@ -63,7 +67,7 @@ class ProjectTestCase(test.TestCase):
 | 
			
		||||
 | 
			
		||||
class LockTestCase(test.TestCase):
 | 
			
		||||
    def test_synchronized_wrapped_function_metadata(self):
 | 
			
		||||
        @synchronized('whatever')
 | 
			
		||||
        @utils.synchronized('whatever')
 | 
			
		||||
        def foo():
 | 
			
		||||
            """Bar"""
 | 
			
		||||
            pass
 | 
			
		||||
@@ -72,11 +76,42 @@ class LockTestCase(test.TestCase):
 | 
			
		||||
        self.assertEquals(foo.__name__, 'foo', "Wrapped function's name "
 | 
			
		||||
                                               "got mangled")
 | 
			
		||||
 | 
			
		||||
    def test_synchronized(self):
 | 
			
		||||
    def test_synchronized_internally(self):
 | 
			
		||||
        """We can lock across multiple green threads"""
 | 
			
		||||
        saved_sem_num = len(utils._semaphores)
 | 
			
		||||
        seen_threads = list()
 | 
			
		||||
 | 
			
		||||
        @utils.synchronized('testlock2', external=False)
 | 
			
		||||
        def f(id):
 | 
			
		||||
            for x in range(10):
 | 
			
		||||
                seen_threads.append(id)
 | 
			
		||||
                greenthread.sleep(0)
 | 
			
		||||
 | 
			
		||||
        threads = []
 | 
			
		||||
        pool = greenpool.GreenPool(10)
 | 
			
		||||
        for i in range(10):
 | 
			
		||||
            threads.append(pool.spawn(f, i))
 | 
			
		||||
 | 
			
		||||
        for thread in threads:
 | 
			
		||||
            thread.wait()
 | 
			
		||||
 | 
			
		||||
        self.assertEquals(len(seen_threads), 100)
 | 
			
		||||
        # Looking at the seen threads, split it into chunks of 10, and verify
 | 
			
		||||
        # that the last 9 match the first in each chunk.
 | 
			
		||||
        for i in range(10):
 | 
			
		||||
            for j in range(9):
 | 
			
		||||
                self.assertEquals(seen_threads[i * 10],
 | 
			
		||||
                                  seen_threads[i * 10 + 1 + j])
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(saved_sem_num, len(utils._semaphores),
 | 
			
		||||
                         "Semaphore leak detected")
 | 
			
		||||
 | 
			
		||||
    def test_synchronized_externally(self):
 | 
			
		||||
        """We can lock across multiple processes"""
 | 
			
		||||
        rpipe1, wpipe1 = os.pipe()
 | 
			
		||||
        rpipe2, wpipe2 = os.pipe()
 | 
			
		||||
 | 
			
		||||
        @synchronized('testlock')
 | 
			
		||||
        @utils.synchronized('testlock1', external=True)
 | 
			
		||||
        def f(rpipe, wpipe):
 | 
			
		||||
            try:
 | 
			
		||||
                os.write(wpipe, "foo")
 | 
			
		||||
 
 | 
			
		||||
@@ -20,21 +20,10 @@ Unit Tests for network code
 | 
			
		||||
"""
 | 
			
		||||
import IPy
 | 
			
		||||
import os
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
from nova import context
 | 
			
		||||
from nova import db
 | 
			
		||||
from nova import exception
 | 
			
		||||
from nova import flags
 | 
			
		||||
from nova import log as logging
 | 
			
		||||
from nova import test
 | 
			
		||||
from nova import utils
 | 
			
		||||
from nova.auth import manager
 | 
			
		||||
from nova.network import linux_net
 | 
			
		||||
 | 
			
		||||
FLAGS = flags.FLAGS
 | 
			
		||||
LOG = logging.getLogger('nova.tests.network')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IptablesManagerTestCase(test.TestCase):
 | 
			
		||||
    sample_filter = ['#Generated by iptables-save on Fri Feb 18 15:17:05 2011',
 | 
			
		||||
@@ -175,363 +164,3 @@ class IptablesManagerTestCase(test.TestCase):
 | 
			
		||||
            self.assertTrue('-A %s -j run_tests.py-%s' \
 | 
			
		||||
                            % (chain, chain) in new_lines,
 | 
			
		||||
                            "Built-in chain %s not wrapped" % (chain,))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NetworkTestCase(test.TestCase):
 | 
			
		||||
    """Test cases for network code"""
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(NetworkTestCase, self).setUp()
 | 
			
		||||
        # NOTE(vish): if you change these flags, make sure to change the
 | 
			
		||||
        #             flags in the corresponding section in nova-dhcpbridge
 | 
			
		||||
        self.flags(connection_type='fake',
 | 
			
		||||
                   fake_call=True,
 | 
			
		||||
                   fake_network=True)
 | 
			
		||||
        self.manager = manager.AuthManager()
 | 
			
		||||
        self.user = self.manager.create_user('netuser', 'netuser', 'netuser')
 | 
			
		||||
        self.projects = []
 | 
			
		||||
        self.network = utils.import_object(FLAGS.network_manager)
 | 
			
		||||
        self.context = context.RequestContext(project=None, user=self.user)
 | 
			
		||||
        for i in range(FLAGS.num_networks):
 | 
			
		||||
            name = 'project%s' % i
 | 
			
		||||
            project = self.manager.create_project(name, 'netuser', name)
 | 
			
		||||
            self.projects.append(project)
 | 
			
		||||
            # create the necessary network data for the project
 | 
			
		||||
            user_context = context.RequestContext(project=self.projects[i],
 | 
			
		||||
                                                     user=self.user)
 | 
			
		||||
            host = self.network.get_network_host(user_context.elevated())
 | 
			
		||||
        instance_ref = self._create_instance(0)
 | 
			
		||||
        self.instance_id = instance_ref['id']
 | 
			
		||||
        instance_ref = self._create_instance(1)
 | 
			
		||||
        self.instance2_id = instance_ref['id']
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        # TODO(termie): this should really be instantiating clean datastores
 | 
			
		||||
        #               in between runs, one failure kills all the tests
 | 
			
		||||
        db.instance_destroy(context.get_admin_context(), self.instance_id)
 | 
			
		||||
        db.instance_destroy(context.get_admin_context(), self.instance2_id)
 | 
			
		||||
        for project in self.projects:
 | 
			
		||||
            self.manager.delete_project(project)
 | 
			
		||||
        self.manager.delete_user(self.user)
 | 
			
		||||
        super(NetworkTestCase, self).tearDown()
 | 
			
		||||
 | 
			
		||||
    def _create_instance(self, project_num, mac=None):
 | 
			
		||||
        if not mac:
 | 
			
		||||
            mac = utils.generate_mac()
 | 
			
		||||
        project = self.projects[project_num]
 | 
			
		||||
        self.context._project = project
 | 
			
		||||
        self.context.project_id = project.id
 | 
			
		||||
        return db.instance_create(self.context,
 | 
			
		||||
                                  {'project_id': project.id,
 | 
			
		||||
                                   'mac_address': mac})
 | 
			
		||||
 | 
			
		||||
    def _create_address(self, project_num, instance_id=None):
 | 
			
		||||
        """Create an address in given project num"""
 | 
			
		||||
        if instance_id is None:
 | 
			
		||||
            instance_id = self.instance_id
 | 
			
		||||
        self.context._project = self.projects[project_num]
 | 
			
		||||
        self.context.project_id = self.projects[project_num].id
 | 
			
		||||
        return self.network.allocate_fixed_ip(self.context, instance_id)
 | 
			
		||||
 | 
			
		||||
    def _deallocate_address(self, project_num, address):
 | 
			
		||||
        self.context._project = self.projects[project_num]
 | 
			
		||||
        self.context.project_id = self.projects[project_num].id
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, address)
 | 
			
		||||
 | 
			
		||||
    def test_private_ipv6(self):
 | 
			
		||||
        """Make sure ipv6 is OK"""
 | 
			
		||||
        if FLAGS.use_ipv6:
 | 
			
		||||
            instance_ref = self._create_instance(0)
 | 
			
		||||
            address = self._create_address(0, instance_ref['id'])
 | 
			
		||||
            network_ref = db.project_get_network(
 | 
			
		||||
                                                 context.get_admin_context(),
 | 
			
		||||
                                                 self.context.project_id)
 | 
			
		||||
            address_v6 = db.instance_get_fixed_address_v6(
 | 
			
		||||
                                                 context.get_admin_context(),
 | 
			
		||||
                                                 instance_ref['id'])
 | 
			
		||||
            self.assertEqual(instance_ref['mac_address'],
 | 
			
		||||
                             utils.to_mac(address_v6))
 | 
			
		||||
            instance_ref2 = db.fixed_ip_get_instance_v6(
 | 
			
		||||
                                                 context.get_admin_context(),
 | 
			
		||||
                                                 address_v6)
 | 
			
		||||
            self.assertEqual(instance_ref['id'], instance_ref2['id'])
 | 
			
		||||
            self.assertEqual(address_v6,
 | 
			
		||||
                             utils.to_global_ipv6(
 | 
			
		||||
                                                 network_ref['cidr_v6'],
 | 
			
		||||
                                                 instance_ref['mac_address']))
 | 
			
		||||
            self._deallocate_address(0, address)
 | 
			
		||||
            db.instance_destroy(context.get_admin_context(),
 | 
			
		||||
                                instance_ref['id'])
 | 
			
		||||
 | 
			
		||||
    def test_public_network_association(self):
 | 
			
		||||
        """Makes sure that we can allocaate a public ip"""
 | 
			
		||||
        # TODO(vish): better way of adding floating ips
 | 
			
		||||
        self.context._project = self.projects[0]
 | 
			
		||||
        self.context.project_id = self.projects[0].id
 | 
			
		||||
        pubnet = IPy.IP(flags.FLAGS.floating_range)
 | 
			
		||||
        address = str(pubnet[0])
 | 
			
		||||
        try:
 | 
			
		||||
            db.floating_ip_get_by_address(context.get_admin_context(), address)
 | 
			
		||||
        except exception.NotFound:
 | 
			
		||||
            db.floating_ip_create(context.get_admin_context(),
 | 
			
		||||
                                  {'address': address,
 | 
			
		||||
                                   'host': FLAGS.host})
 | 
			
		||||
        float_addr = self.network.allocate_floating_ip(self.context,
 | 
			
		||||
                                                       self.projects[0].id)
 | 
			
		||||
        fix_addr = self._create_address(0)
 | 
			
		||||
        lease_ip(fix_addr)
 | 
			
		||||
        self.assertEqual(float_addr, str(pubnet[0]))
 | 
			
		||||
        self.network.associate_floating_ip(self.context, float_addr, fix_addr)
 | 
			
		||||
        address = db.instance_get_floating_address(context.get_admin_context(),
 | 
			
		||||
                                                   self.instance_id)
 | 
			
		||||
        self.assertEqual(address, float_addr)
 | 
			
		||||
        self.network.disassociate_floating_ip(self.context, float_addr)
 | 
			
		||||
        address = db.instance_get_floating_address(context.get_admin_context(),
 | 
			
		||||
                                                   self.instance_id)
 | 
			
		||||
        self.assertEqual(address, None)
 | 
			
		||||
        self.network.deallocate_floating_ip(self.context, float_addr)
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, fix_addr)
 | 
			
		||||
        release_ip(fix_addr)
 | 
			
		||||
        db.floating_ip_destroy(context.get_admin_context(), float_addr)
 | 
			
		||||
 | 
			
		||||
    def test_allocate_deallocate_fixed_ip(self):
 | 
			
		||||
        """Makes sure that we can allocate and deallocate a fixed ip"""
 | 
			
		||||
        address = self._create_address(0)
 | 
			
		||||
        self.assertTrue(is_allocated_in_project(address, self.projects[0].id))
 | 
			
		||||
        lease_ip(address)
 | 
			
		||||
        self._deallocate_address(0, address)
 | 
			
		||||
 | 
			
		||||
        # Doesn't go away until it's dhcp released
 | 
			
		||||
        self.assertTrue(is_allocated_in_project(address, self.projects[0].id))
 | 
			
		||||
 | 
			
		||||
        release_ip(address)
 | 
			
		||||
        self.assertFalse(is_allocated_in_project(address, self.projects[0].id))
 | 
			
		||||
 | 
			
		||||
    def test_side_effects(self):
 | 
			
		||||
        """Ensures allocating and releasing has no side effects"""
 | 
			
		||||
        address = self._create_address(0)
 | 
			
		||||
        address2 = self._create_address(1, self.instance2_id)
 | 
			
		||||
 | 
			
		||||
        self.assertTrue(is_allocated_in_project(address, self.projects[0].id))
 | 
			
		||||
        self.assertTrue(is_allocated_in_project(address2, self.projects[1].id))
 | 
			
		||||
        self.assertFalse(is_allocated_in_project(address, self.projects[1].id))
 | 
			
		||||
 | 
			
		||||
        # Addresses are allocated before they're issued
 | 
			
		||||
        lease_ip(address)
 | 
			
		||||
        lease_ip(address2)
 | 
			
		||||
 | 
			
		||||
        self._deallocate_address(0, address)
 | 
			
		||||
        release_ip(address)
 | 
			
		||||
        self.assertFalse(is_allocated_in_project(address, self.projects[0].id))
 | 
			
		||||
 | 
			
		||||
        # First address release shouldn't affect the second
 | 
			
		||||
        self.assertTrue(is_allocated_in_project(address2, self.projects[1].id))
 | 
			
		||||
 | 
			
		||||
        self._deallocate_address(1, address2)
 | 
			
		||||
        release_ip(address2)
 | 
			
		||||
        self.assertFalse(is_allocated_in_project(address2,
 | 
			
		||||
                                                 self.projects[1].id))
 | 
			
		||||
 | 
			
		||||
    def test_subnet_edge(self):
 | 
			
		||||
        """Makes sure that private ips don't overlap"""
 | 
			
		||||
        first = self._create_address(0)
 | 
			
		||||
        lease_ip(first)
 | 
			
		||||
        instance_ids = []
 | 
			
		||||
        for i in range(1, FLAGS.num_networks):
 | 
			
		||||
            instance_ref = self._create_instance(i, mac=utils.generate_mac())
 | 
			
		||||
            instance_ids.append(instance_ref['id'])
 | 
			
		||||
            address = self._create_address(i, instance_ref['id'])
 | 
			
		||||
            instance_ref = self._create_instance(i, mac=utils.generate_mac())
 | 
			
		||||
            instance_ids.append(instance_ref['id'])
 | 
			
		||||
            address2 = self._create_address(i, instance_ref['id'])
 | 
			
		||||
            instance_ref = self._create_instance(i, mac=utils.generate_mac())
 | 
			
		||||
            instance_ids.append(instance_ref['id'])
 | 
			
		||||
            address3 = self._create_address(i, instance_ref['id'])
 | 
			
		||||
            lease_ip(address)
 | 
			
		||||
            lease_ip(address2)
 | 
			
		||||
            lease_ip(address3)
 | 
			
		||||
            self.context._project = self.projects[i]
 | 
			
		||||
            self.context.project_id = self.projects[i].id
 | 
			
		||||
            self.assertFalse(is_allocated_in_project(address,
 | 
			
		||||
                                                     self.projects[0].id))
 | 
			
		||||
            self.assertFalse(is_allocated_in_project(address2,
 | 
			
		||||
                                                     self.projects[0].id))
 | 
			
		||||
            self.assertFalse(is_allocated_in_project(address3,
 | 
			
		||||
                                                     self.projects[0].id))
 | 
			
		||||
            self.network.deallocate_fixed_ip(self.context, address)
 | 
			
		||||
            self.network.deallocate_fixed_ip(self.context, address2)
 | 
			
		||||
            self.network.deallocate_fixed_ip(self.context, address3)
 | 
			
		||||
            release_ip(address)
 | 
			
		||||
            release_ip(address2)
 | 
			
		||||
            release_ip(address3)
 | 
			
		||||
        for instance_id in instance_ids:
 | 
			
		||||
            db.instance_destroy(context.get_admin_context(), instance_id)
 | 
			
		||||
        self.context._project = self.projects[0]
 | 
			
		||||
        self.context.project_id = self.projects[0].id
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, first)
 | 
			
		||||
        self._deallocate_address(0, first)
 | 
			
		||||
        release_ip(first)
 | 
			
		||||
 | 
			
		||||
    def test_vpn_ip_and_port_looks_valid(self):
 | 
			
		||||
        """Ensure the vpn ip and port are reasonable"""
 | 
			
		||||
        self.assert_(self.projects[0].vpn_ip)
 | 
			
		||||
        self.assert_(self.projects[0].vpn_port >= FLAGS.vpn_start)
 | 
			
		||||
        self.assert_(self.projects[0].vpn_port <= FLAGS.vpn_start +
 | 
			
		||||
                                                  FLAGS.num_networks)
 | 
			
		||||
 | 
			
		||||
    def test_too_many_networks(self):
 | 
			
		||||
        """Ensure error is raised if we run out of networks"""
 | 
			
		||||
        projects = []
 | 
			
		||||
        networks_left = (FLAGS.num_networks -
 | 
			
		||||
                         db.network_count(context.get_admin_context()))
 | 
			
		||||
        for i in range(networks_left):
 | 
			
		||||
            project = self.manager.create_project('many%s' % i, self.user)
 | 
			
		||||
            projects.append(project)
 | 
			
		||||
            db.project_get_network(context.get_admin_context(), project.id)
 | 
			
		||||
        project = self.manager.create_project('last', self.user)
 | 
			
		||||
        projects.append(project)
 | 
			
		||||
        self.assertRaises(db.NoMoreNetworks,
 | 
			
		||||
                          db.project_get_network,
 | 
			
		||||
                          context.get_admin_context(),
 | 
			
		||||
                          project.id)
 | 
			
		||||
        for project in projects:
 | 
			
		||||
            self.manager.delete_project(project)
 | 
			
		||||
 | 
			
		||||
    def test_ips_are_reused(self):
 | 
			
		||||
        """Makes sure that ip addresses that are deallocated get reused"""
 | 
			
		||||
        address = self._create_address(0)
 | 
			
		||||
        lease_ip(address)
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, address)
 | 
			
		||||
        release_ip(address)
 | 
			
		||||
 | 
			
		||||
        address2 = self._create_address(0)
 | 
			
		||||
        self.assertEqual(address, address2)
 | 
			
		||||
        lease_ip(address)
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, address2)
 | 
			
		||||
        release_ip(address)
 | 
			
		||||
 | 
			
		||||
    def test_available_ips(self):
 | 
			
		||||
        """Make sure the number of available ips for the network is correct
 | 
			
		||||
 | 
			
		||||
        The number of available IP addresses depends on the test
 | 
			
		||||
        environment's setup.
 | 
			
		||||
 | 
			
		||||
        Network size is set in test fixture's setUp method.
 | 
			
		||||
 | 
			
		||||
        There are ips reserved at the bottom and top of the range.
 | 
			
		||||
        services (network, gateway, CloudPipe, broadcast)
 | 
			
		||||
        """
 | 
			
		||||
        network = db.project_get_network(context.get_admin_context(),
 | 
			
		||||
                                         self.projects[0].id)
 | 
			
		||||
        net_size = flags.FLAGS.network_size
 | 
			
		||||
        admin_context = context.get_admin_context()
 | 
			
		||||
        total_ips = (db.network_count_available_ips(admin_context,
 | 
			
		||||
                                                    network['id']) +
 | 
			
		||||
                     db.network_count_reserved_ips(admin_context,
 | 
			
		||||
                                                   network['id']) +
 | 
			
		||||
                     db.network_count_allocated_ips(admin_context,
 | 
			
		||||
                                                    network['id']))
 | 
			
		||||
        self.assertEqual(total_ips, net_size)
 | 
			
		||||
 | 
			
		||||
    def test_too_many_addresses(self):
 | 
			
		||||
        """Test for a NoMoreAddresses exception when all fixed ips are used.
 | 
			
		||||
        """
 | 
			
		||||
        admin_context = context.get_admin_context()
 | 
			
		||||
        network = db.project_get_network(admin_context, self.projects[0].id)
 | 
			
		||||
        num_available_ips = db.network_count_available_ips(admin_context,
 | 
			
		||||
                                                           network['id'])
 | 
			
		||||
        addresses = []
 | 
			
		||||
        instance_ids = []
 | 
			
		||||
        for i in range(num_available_ips):
 | 
			
		||||
            instance_ref = self._create_instance(0)
 | 
			
		||||
            instance_ids.append(instance_ref['id'])
 | 
			
		||||
            address = self._create_address(0, instance_ref['id'])
 | 
			
		||||
            addresses.append(address)
 | 
			
		||||
            lease_ip(address)
 | 
			
		||||
 | 
			
		||||
        ip_count = db.network_count_available_ips(context.get_admin_context(),
 | 
			
		||||
                                                  network['id'])
 | 
			
		||||
        self.assertEqual(ip_count, 0)
 | 
			
		||||
        self.assertRaises(db.NoMoreAddresses,
 | 
			
		||||
                          self.network.allocate_fixed_ip,
 | 
			
		||||
                          self.context,
 | 
			
		||||
                          'foo')
 | 
			
		||||
 | 
			
		||||
        for i in range(num_available_ips):
 | 
			
		||||
            self.network.deallocate_fixed_ip(self.context, addresses[i])
 | 
			
		||||
            release_ip(addresses[i])
 | 
			
		||||
            db.instance_destroy(context.get_admin_context(), instance_ids[i])
 | 
			
		||||
        ip_count = db.network_count_available_ips(context.get_admin_context(),
 | 
			
		||||
                                                  network['id'])
 | 
			
		||||
        self.assertEqual(ip_count, num_available_ips)
 | 
			
		||||
 | 
			
		||||
    def test_dhcp_lease_output(self):
 | 
			
		||||
        admin_ctxt = context.get_admin_context()
 | 
			
		||||
        address = self._create_address(0, self.instance_id)
 | 
			
		||||
        lease_ip(address)
 | 
			
		||||
        network_ref = db.network_get_by_instance(admin_ctxt, self.instance_id)
 | 
			
		||||
        leases = linux_net.get_dhcp_leases(context.get_admin_context(),
 | 
			
		||||
                                           network_ref['id'])
 | 
			
		||||
        for line in leases.split('\n'):
 | 
			
		||||
            seconds, mac, ip, hostname, client_id = line.split(' ')
 | 
			
		||||
            self.assertTrue(int(seconds) > time.time(), 'Lease expires in '
 | 
			
		||||
                                                        'the past')
 | 
			
		||||
            octets = mac.split(':')
 | 
			
		||||
            self.assertEqual(len(octets), 6, "Wrong number of octets "
 | 
			
		||||
                                             "in %s" % (max,))
 | 
			
		||||
            for octet in octets:
 | 
			
		||||
                self.assertEqual(len(octet), 2, "Oddly sized octet: %s"
 | 
			
		||||
                                                                    % (octet,))
 | 
			
		||||
                # This will throw an exception if the octet is invalid
 | 
			
		||||
                int(octet, 16)
 | 
			
		||||
 | 
			
		||||
            # And this will raise an exception in case of an invalid IP
 | 
			
		||||
            IPy.IP(ip)
 | 
			
		||||
 | 
			
		||||
        release_ip(address)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_allocated_in_project(address, project_id):
 | 
			
		||||
    """Returns true if address is in specified project"""
 | 
			
		||||
    project_net = db.project_get_network(context.get_admin_context(),
 | 
			
		||||
                                         project_id)
 | 
			
		||||
    network = db.fixed_ip_get_network(context.get_admin_context(), address)
 | 
			
		||||
    instance = db.fixed_ip_get_instance(context.get_admin_context(), address)
 | 
			
		||||
    # instance exists until release
 | 
			
		||||
    return instance is not None and network['id'] == project_net['id']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def binpath(script):
 | 
			
		||||
    """Returns the absolute path to a script in bin"""
 | 
			
		||||
    return os.path.abspath(os.path.join(__file__, "../../../bin", script))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def lease_ip(private_ip):
 | 
			
		||||
    """Run add command on dhcpbridge"""
 | 
			
		||||
    network_ref = db.fixed_ip_get_network(context.get_admin_context(),
 | 
			
		||||
                                          private_ip)
 | 
			
		||||
    instance_ref = db.fixed_ip_get_instance(context.get_admin_context(),
 | 
			
		||||
                                            private_ip)
 | 
			
		||||
    cmd = (binpath('nova-dhcpbridge'), 'add',
 | 
			
		||||
           instance_ref['mac_address'],
 | 
			
		||||
           private_ip, 'fake')
 | 
			
		||||
    env = {'DNSMASQ_INTERFACE': network_ref['bridge'],
 | 
			
		||||
           'TESTING': '1',
 | 
			
		||||
           'FLAGFILE': FLAGS.dhcpbridge_flagfile}
 | 
			
		||||
    (out, err) = utils.execute(*cmd, addl_env=env)
 | 
			
		||||
    LOG.debug("ISSUE_IP: %s, %s ", out, err)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def release_ip(private_ip):
 | 
			
		||||
    """Run del command on dhcpbridge"""
 | 
			
		||||
    network_ref = db.fixed_ip_get_network(context.get_admin_context(),
 | 
			
		||||
                                          private_ip)
 | 
			
		||||
    instance_ref = db.fixed_ip_get_instance(context.get_admin_context(),
 | 
			
		||||
                                            private_ip)
 | 
			
		||||
    cmd = (binpath('nova-dhcpbridge'), 'del',
 | 
			
		||||
           instance_ref['mac_address'],
 | 
			
		||||
           private_ip, 'fake')
 | 
			
		||||
    env = {'DNSMASQ_INTERFACE': network_ref['bridge'],
 | 
			
		||||
           'TESTING': '1',
 | 
			
		||||
           'FLAGFILE': FLAGS.dhcpbridge_flagfile}
 | 
			
		||||
    (out, err) = utils.execute(*cmd, addl_env=env)
 | 
			
		||||
    LOG.debug("RELEASE_IP: %s, %s ", out, err)
 | 
			
		||||
 
 | 
			
		||||
@@ -77,13 +77,11 @@ class CacheConcurrencyTestCase(test.TestCase):
 | 
			
		||||
        eventlet.sleep(0)
 | 
			
		||||
        try:
 | 
			
		||||
            self.assertFalse(done2.ready())
 | 
			
		||||
            self.assertTrue('fname' in conn._image_sems)
 | 
			
		||||
        finally:
 | 
			
		||||
            wait1.send()
 | 
			
		||||
        done1.wait()
 | 
			
		||||
        eventlet.sleep(0)
 | 
			
		||||
        self.assertTrue(done2.ready())
 | 
			
		||||
        self.assertFalse('fname' in conn._image_sems)
 | 
			
		||||
 | 
			
		||||
    def test_different_fname_concurrency(self):
 | 
			
		||||
        """Ensures that two different fname caches are concurrent"""
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										242
									
								
								nova/tests/test_vlan_network.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								nova/tests/test_vlan_network.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,242 @@
 | 
			
		||||
# 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.
 | 
			
		||||
"""
 | 
			
		||||
Unit Tests for vlan network code
 | 
			
		||||
"""
 | 
			
		||||
import IPy
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
from nova import context
 | 
			
		||||
from nova import db
 | 
			
		||||
from nova import exception
 | 
			
		||||
from nova import flags
 | 
			
		||||
from nova import log as logging
 | 
			
		||||
from nova import test
 | 
			
		||||
from nova import utils
 | 
			
		||||
from nova.auth import manager
 | 
			
		||||
from nova.tests.network import base
 | 
			
		||||
from nova.tests.network import binpath,\
 | 
			
		||||
    lease_ip, release_ip
 | 
			
		||||
 | 
			
		||||
FLAGS = flags.FLAGS
 | 
			
		||||
LOG = logging.getLogger('nova.tests.network')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VlanNetworkTestCase(base.NetworkTestCase):
 | 
			
		||||
    """Test cases for network code"""
 | 
			
		||||
    def test_public_network_association(self):
 | 
			
		||||
        """Makes sure that we can allocaate a public ip"""
 | 
			
		||||
        # TODO(vish): better way of adding floating ips
 | 
			
		||||
        self.context._project = self.projects[0]
 | 
			
		||||
        self.context.project_id = self.projects[0].id
 | 
			
		||||
        pubnet = IPy.IP(flags.FLAGS.floating_range)
 | 
			
		||||
        address = str(pubnet[0])
 | 
			
		||||
        try:
 | 
			
		||||
            db.floating_ip_get_by_address(context.get_admin_context(), address)
 | 
			
		||||
        except exception.NotFound:
 | 
			
		||||
            db.floating_ip_create(context.get_admin_context(),
 | 
			
		||||
                                  {'address': address,
 | 
			
		||||
                                   'host': FLAGS.host})
 | 
			
		||||
        float_addr = self.network.allocate_floating_ip(self.context,
 | 
			
		||||
                                                       self.projects[0].id)
 | 
			
		||||
        fix_addr = self._create_address(0)
 | 
			
		||||
        lease_ip(fix_addr)
 | 
			
		||||
        self.assertEqual(float_addr, str(pubnet[0]))
 | 
			
		||||
        self.network.associate_floating_ip(self.context, float_addr, fix_addr)
 | 
			
		||||
        address = db.instance_get_floating_address(context.get_admin_context(),
 | 
			
		||||
                                                   self.instance_id)
 | 
			
		||||
        self.assertEqual(address, float_addr)
 | 
			
		||||
        self.network.disassociate_floating_ip(self.context, float_addr)
 | 
			
		||||
        address = db.instance_get_floating_address(context.get_admin_context(),
 | 
			
		||||
                                                   self.instance_id)
 | 
			
		||||
        self.assertEqual(address, None)
 | 
			
		||||
        self.network.deallocate_floating_ip(self.context, float_addr)
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, fix_addr)
 | 
			
		||||
        release_ip(fix_addr)
 | 
			
		||||
        db.floating_ip_destroy(context.get_admin_context(), float_addr)
 | 
			
		||||
 | 
			
		||||
    def test_allocate_deallocate_fixed_ip(self):
 | 
			
		||||
        """Makes sure that we can allocate and deallocate a fixed ip"""
 | 
			
		||||
        address = self._create_address(0)
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address,
 | 
			
		||||
                                                      self.projects[0].id))
 | 
			
		||||
        lease_ip(address)
 | 
			
		||||
        self._deallocate_address(0, address)
 | 
			
		||||
 | 
			
		||||
        # Doesn't go away until it's dhcp released
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address,
 | 
			
		||||
                                                      self.projects[0].id))
 | 
			
		||||
 | 
			
		||||
        release_ip(address)
 | 
			
		||||
        self.assertFalse(self._is_allocated_in_project(address,
 | 
			
		||||
                                                       self.projects[0].id))
 | 
			
		||||
 | 
			
		||||
    def test_side_effects(self):
 | 
			
		||||
        """Ensures allocating and releasing has no side effects"""
 | 
			
		||||
        address = self._create_address(0)
 | 
			
		||||
        address2 = self._create_address(1, self.instance2_id)
 | 
			
		||||
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address,
 | 
			
		||||
                                                      self.projects[0].id))
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address2,
 | 
			
		||||
                                                      self.projects[1].id))
 | 
			
		||||
        self.assertFalse(self._is_allocated_in_project(address,
 | 
			
		||||
                                                       self.projects[1].id))
 | 
			
		||||
 | 
			
		||||
        # Addresses are allocated before they're issued
 | 
			
		||||
        lease_ip(address)
 | 
			
		||||
        lease_ip(address2)
 | 
			
		||||
 | 
			
		||||
        self._deallocate_address(0, address)
 | 
			
		||||
        release_ip(address)
 | 
			
		||||
        self.assertFalse(self._is_allocated_in_project(address,
 | 
			
		||||
                                                       self.projects[0].id))
 | 
			
		||||
 | 
			
		||||
        # First address release shouldn't affect the second
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address2,
 | 
			
		||||
                                                      self.projects[1].id))
 | 
			
		||||
 | 
			
		||||
        self._deallocate_address(1, address2)
 | 
			
		||||
        release_ip(address2)
 | 
			
		||||
        self.assertFalse(self._is_allocated_in_project(address2,
 | 
			
		||||
                                                 self.projects[1].id))
 | 
			
		||||
 | 
			
		||||
    def test_subnet_edge(self):
 | 
			
		||||
        """Makes sure that private ips don't overlap"""
 | 
			
		||||
        first = self._create_address(0)
 | 
			
		||||
        lease_ip(first)
 | 
			
		||||
        instance_ids = []
 | 
			
		||||
        for i in range(1, FLAGS.num_networks):
 | 
			
		||||
            instance_ref = self._create_instance(i, mac=utils.generate_mac())
 | 
			
		||||
            instance_ids.append(instance_ref['id'])
 | 
			
		||||
            address = self._create_address(i, instance_ref['id'])
 | 
			
		||||
            instance_ref = self._create_instance(i, mac=utils.generate_mac())
 | 
			
		||||
            instance_ids.append(instance_ref['id'])
 | 
			
		||||
            address2 = self._create_address(i, instance_ref['id'])
 | 
			
		||||
            instance_ref = self._create_instance(i, mac=utils.generate_mac())
 | 
			
		||||
            instance_ids.append(instance_ref['id'])
 | 
			
		||||
            address3 = self._create_address(i, instance_ref['id'])
 | 
			
		||||
            lease_ip(address)
 | 
			
		||||
            lease_ip(address2)
 | 
			
		||||
            lease_ip(address3)
 | 
			
		||||
            self.context._project = self.projects[i]
 | 
			
		||||
            self.context.project_id = self.projects[i].id
 | 
			
		||||
            self.assertFalse(self._is_allocated_in_project(address,
 | 
			
		||||
                                                     self.projects[0].id))
 | 
			
		||||
            self.assertFalse(self._is_allocated_in_project(address2,
 | 
			
		||||
                                                     self.projects[0].id))
 | 
			
		||||
            self.assertFalse(self._is_allocated_in_project(address3,
 | 
			
		||||
                                                     self.projects[0].id))
 | 
			
		||||
            self.network.deallocate_fixed_ip(self.context, address)
 | 
			
		||||
            self.network.deallocate_fixed_ip(self.context, address2)
 | 
			
		||||
            self.network.deallocate_fixed_ip(self.context, address3)
 | 
			
		||||
            release_ip(address)
 | 
			
		||||
            release_ip(address2)
 | 
			
		||||
            release_ip(address3)
 | 
			
		||||
        for instance_id in instance_ids:
 | 
			
		||||
            db.instance_destroy(context.get_admin_context(), instance_id)
 | 
			
		||||
        self.context._project = self.projects[0]
 | 
			
		||||
        self.context.project_id = self.projects[0].id
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, first)
 | 
			
		||||
        self._deallocate_address(0, first)
 | 
			
		||||
        release_ip(first)
 | 
			
		||||
 | 
			
		||||
    def test_vpn_ip_and_port_looks_valid(self):
 | 
			
		||||
        """Ensure the vpn ip and port are reasonable"""
 | 
			
		||||
        self.assert_(self.projects[0].vpn_ip)
 | 
			
		||||
        self.assert_(self.projects[0].vpn_port >= FLAGS.vpn_start)
 | 
			
		||||
        self.assert_(self.projects[0].vpn_port <= FLAGS.vpn_start +
 | 
			
		||||
                                                  FLAGS.num_networks)
 | 
			
		||||
 | 
			
		||||
    def test_too_many_networks(self):
 | 
			
		||||
        """Ensure error is raised if we run out of networks"""
 | 
			
		||||
        projects = []
 | 
			
		||||
        networks_left = (FLAGS.num_networks -
 | 
			
		||||
                         db.network_count(context.get_admin_context()))
 | 
			
		||||
        for i in range(networks_left):
 | 
			
		||||
            project = self.manager.create_project('many%s' % i, self.user)
 | 
			
		||||
            projects.append(project)
 | 
			
		||||
            db.project_get_network(context.get_admin_context(), project.id)
 | 
			
		||||
        project = self.manager.create_project('last', self.user)
 | 
			
		||||
        projects.append(project)
 | 
			
		||||
        self.assertRaises(db.NoMoreNetworks,
 | 
			
		||||
                          db.project_get_network,
 | 
			
		||||
                          context.get_admin_context(),
 | 
			
		||||
                          project.id)
 | 
			
		||||
        for project in projects:
 | 
			
		||||
            self.manager.delete_project(project)
 | 
			
		||||
 | 
			
		||||
    def test_ips_are_reused(self):
 | 
			
		||||
        """Makes sure that ip addresses that are deallocated get reused"""
 | 
			
		||||
        address = self._create_address(0)
 | 
			
		||||
        lease_ip(address)
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, address)
 | 
			
		||||
        release_ip(address)
 | 
			
		||||
 | 
			
		||||
        address2 = self._create_address(0)
 | 
			
		||||
        self.assertEqual(address, address2)
 | 
			
		||||
        lease_ip(address)
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, address2)
 | 
			
		||||
        release_ip(address)
 | 
			
		||||
 | 
			
		||||
    def test_too_many_addresses(self):
 | 
			
		||||
        """Test for a NoMoreAddresses exception when all fixed ips are used.
 | 
			
		||||
        """
 | 
			
		||||
        admin_context = context.get_admin_context()
 | 
			
		||||
        network = db.project_get_network(admin_context, self.projects[0].id)
 | 
			
		||||
        num_available_ips = db.network_count_available_ips(admin_context,
 | 
			
		||||
                                                           network['id'])
 | 
			
		||||
        addresses = []
 | 
			
		||||
        instance_ids = []
 | 
			
		||||
        for i in range(num_available_ips):
 | 
			
		||||
            instance_ref = self._create_instance(0)
 | 
			
		||||
            instance_ids.append(instance_ref['id'])
 | 
			
		||||
            address = self._create_address(0, instance_ref['id'])
 | 
			
		||||
            addresses.append(address)
 | 
			
		||||
            lease_ip(address)
 | 
			
		||||
 | 
			
		||||
        ip_count = db.network_count_available_ips(context.get_admin_context(),
 | 
			
		||||
                                                  network['id'])
 | 
			
		||||
        self.assertEqual(ip_count, 0)
 | 
			
		||||
        self.assertRaises(db.NoMoreAddresses,
 | 
			
		||||
                          self.network.allocate_fixed_ip,
 | 
			
		||||
                          self.context,
 | 
			
		||||
                          'foo')
 | 
			
		||||
 | 
			
		||||
        for i in range(num_available_ips):
 | 
			
		||||
            self.network.deallocate_fixed_ip(self.context, addresses[i])
 | 
			
		||||
            release_ip(addresses[i])
 | 
			
		||||
            db.instance_destroy(context.get_admin_context(), instance_ids[i])
 | 
			
		||||
        ip_count = db.network_count_available_ips(context.get_admin_context(),
 | 
			
		||||
                                                  network['id'])
 | 
			
		||||
        self.assertEqual(ip_count, num_available_ips)
 | 
			
		||||
 | 
			
		||||
    def _is_allocated_in_project(self, address, project_id):
 | 
			
		||||
        """Returns true if address is in specified project"""
 | 
			
		||||
        project_net = db.project_get_network(context.get_admin_context(),
 | 
			
		||||
                                             project_id)
 | 
			
		||||
        network = db.fixed_ip_get_network(context.get_admin_context(),
 | 
			
		||||
                                          address)
 | 
			
		||||
        instance = db.fixed_ip_get_instance(context.get_admin_context(),
 | 
			
		||||
                                            address)
 | 
			
		||||
        # instance exists until release
 | 
			
		||||
        return instance is not None and network['id'] == project_net['id']
 | 
			
		||||
 | 
			
		||||
    def run(self, result=None):
 | 
			
		||||
        if(FLAGS.network_manager == 'nova.network.manager.VlanManager'):
 | 
			
		||||
            super(VlanNetworkTestCase, self).run(result)
 | 
			
		||||
@@ -228,6 +228,9 @@ class FakeSessionForMigrationTests(fake.SessionBase):
 | 
			
		||||
    def VDI_get_by_uuid(*args):
 | 
			
		||||
        return 'hurr'
 | 
			
		||||
 | 
			
		||||
    def VDI_resize_online(*args):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def VM_start(self, _1, ref, _2, _3):
 | 
			
		||||
        vm = fake.get_record('VM', ref)
 | 
			
		||||
        if vm['power_state'] != 'Halted':
 | 
			
		||||
@@ -240,7 +243,7 @@ class FakeSessionForMigrationTests(fake.SessionBase):
 | 
			
		||||
 | 
			
		||||
def stub_out_migration_methods(stubs):
 | 
			
		||||
    def fake_get_snapshot(self, instance):
 | 
			
		||||
        return 'foo', 'bar'
 | 
			
		||||
        return 'vm_ref', dict(image='foo', snap='bar')
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def fake_get_vdi(cls, session, vm_ref):
 | 
			
		||||
@@ -249,7 +252,7 @@ def stub_out_migration_methods(stubs):
 | 
			
		||||
        vdi_rec = session.get_xenapi().VDI.get_record(vdi_ref)
 | 
			
		||||
        return vdi_ref, {'uuid': vdi_rec['uuid'], }
 | 
			
		||||
 | 
			
		||||
    def fake_shutdown(self, inst, vm, method='clean'):
 | 
			
		||||
    def fake_shutdown(self, inst, vm, hard=True):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,7 @@ from xml.sax import saxutils
 | 
			
		||||
 | 
			
		||||
from eventlet import event
 | 
			
		||||
from eventlet import greenthread
 | 
			
		||||
from eventlet import semaphore
 | 
			
		||||
from eventlet.green import subprocess
 | 
			
		||||
None
 | 
			
		||||
from nova import exception
 | 
			
		||||
@@ -334,6 +335,14 @@ def utcnow():
 | 
			
		||||
utcnow.override_time = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_older_than(before, seconds):
 | 
			
		||||
    """Return True if before is older than 'seconds'"""
 | 
			
		||||
    if utcnow() - before > datetime.timedelta(seconds=seconds):
 | 
			
		||||
        return True
 | 
			
		||||
    else:
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def utcnow_ts():
 | 
			
		||||
    """Timestamp version of our utcnow function."""
 | 
			
		||||
    return time.mktime(utcnow().timetuple())
 | 
			
		||||
@@ -531,17 +540,76 @@ def loads(s):
 | 
			
		||||
    return json.loads(s)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def synchronized(name):
 | 
			
		||||
_semaphores = {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class _NoopContextManager(object):
 | 
			
		||||
    def __enter__(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def __exit__(self, exc_type, exc_val, exc_tb):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def synchronized(name, external=False):
 | 
			
		||||
    """Synchronization decorator
 | 
			
		||||
 | 
			
		||||
    Decorating a method like so:
 | 
			
		||||
    @synchronized('mylock')
 | 
			
		||||
    def foo(self, *args):
 | 
			
		||||
       ...
 | 
			
		||||
 | 
			
		||||
    ensures that only one thread will execute the bar method at a time.
 | 
			
		||||
 | 
			
		||||
    Different methods can share the same lock:
 | 
			
		||||
    @synchronized('mylock')
 | 
			
		||||
    def foo(self, *args):
 | 
			
		||||
       ...
 | 
			
		||||
 | 
			
		||||
    @synchronized('mylock')
 | 
			
		||||
    def bar(self, *args):
 | 
			
		||||
       ...
 | 
			
		||||
 | 
			
		||||
    This way only one of either foo or bar can be executing at a time.
 | 
			
		||||
 | 
			
		||||
    The external keyword argument denotes whether this lock should work across
 | 
			
		||||
    multiple processes. This means that if two different workers both run a
 | 
			
		||||
    a method decorated with @synchronized('mylock', external=True), only one
 | 
			
		||||
    of them will execute at a time.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def wrap(f):
 | 
			
		||||
        @functools.wraps(f)
 | 
			
		||||
        def inner(*args, **kwargs):
 | 
			
		||||
            LOG.debug(_("Attempting to grab %(lock)s for method "
 | 
			
		||||
                        "%(method)s..." % {"lock": name,
 | 
			
		||||
            # NOTE(soren): If we ever go natively threaded, this will be racy.
 | 
			
		||||
            #              See http://stackoverflow.com/questions/5390569/dyn\
 | 
			
		||||
            #              amically-allocating-and-destroying-mutexes
 | 
			
		||||
            if name not in _semaphores:
 | 
			
		||||
                _semaphores[name] = semaphore.Semaphore()
 | 
			
		||||
            sem = _semaphores[name]
 | 
			
		||||
            LOG.debug(_('Attempting to grab semaphore "%(lock)s" for method '
 | 
			
		||||
                      '"%(method)s"...' % {"lock": name,
 | 
			
		||||
                                           "method": f.__name__}))
 | 
			
		||||
            lock = lockfile.FileLock(os.path.join(FLAGS.lock_path,
 | 
			
		||||
                                                  'nova-%s.lock' % name))
 | 
			
		||||
            with sem:
 | 
			
		||||
                if external:
 | 
			
		||||
                    LOG.debug(_('Attempting to grab file lock "%(lock)s" for '
 | 
			
		||||
                                'method "%(method)s"...' %
 | 
			
		||||
                                {"lock": name, "method": f.__name__}))
 | 
			
		||||
                    lock_file_path = os.path.join(FLAGS.lock_path,
 | 
			
		||||
                                                  'nova-%s.lock' % name)
 | 
			
		||||
                    lock = lockfile.FileLock(lock_file_path)
 | 
			
		||||
                else:
 | 
			
		||||
                    lock = _NoopContextManager()
 | 
			
		||||
 | 
			
		||||
                with lock:
 | 
			
		||||
                return f(*args, **kwargs)
 | 
			
		||||
                    retval = f(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
            # If no-one else is waiting for it, delete it.
 | 
			
		||||
            # See note about possible raciness above.
 | 
			
		||||
            if not sem.balance < 1:
 | 
			
		||||
                del _semaphores[name]
 | 
			
		||||
 | 
			
		||||
            return retval
 | 
			
		||||
        return inner
 | 
			
		||||
    return wrap
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user