merged trunk
This commit is contained in:
@@ -44,18 +44,20 @@ flags.DECLARE('auth_driver', 'nova.auth.manager')
|
||||
flags.DECLARE('redis_db', 'nova.datastore')
|
||||
flags.DECLARE('network_size', 'nova.network.manager')
|
||||
flags.DECLARE('num_networks', 'nova.network.manager')
|
||||
flags.DECLARE('update_dhcp_on_disassociate', 'nova.network.manager')
|
||||
|
||||
|
||||
def add_lease(_mac, ip_address, _hostname, _interface):
|
||||
def add_lease(mac, ip_address, _hostname, _interface):
|
||||
"""Set the IP that was assigned by the DHCP server."""
|
||||
if FLAGS.fake_rabbit:
|
||||
logging.debug("leasing ip")
|
||||
network_manager = utils.import_object(FLAGS.network_manager)
|
||||
network_manager.lease_fixed_ip(None, ip_address)
|
||||
network_manager.lease_fixed_ip(None, mac, ip_address)
|
||||
else:
|
||||
rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.node_name),
|
||||
rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.host),
|
||||
{"method": "lease_fixed_ip",
|
||||
"args": {"context": None,
|
||||
"mac": mac,
|
||||
"address": ip_address}})
|
||||
|
||||
|
||||
@@ -64,16 +66,17 @@ def old_lease(_mac, _ip_address, _hostname, _interface):
|
||||
logging.debug("Adopted old lease or got a change of mac/hostname")
|
||||
|
||||
|
||||
def del_lease(_mac, ip_address, _hostname, _interface):
|
||||
def del_lease(mac, ip_address, _hostname, _interface):
|
||||
"""Called when a lease expires."""
|
||||
if FLAGS.fake_rabbit:
|
||||
logging.debug("releasing ip")
|
||||
network_manager = utils.import_object(FLAGS.network_manager)
|
||||
network_manager.release_fixed_ip(None, ip_address)
|
||||
network_manager.release_fixed_ip(None, mac, ip_address)
|
||||
else:
|
||||
rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.node_name),
|
||||
rpc.cast("%s.%s" % (FLAGS.network_topic, FLAGS.host),
|
||||
{"method": "release_fixed_ip",
|
||||
"args": {"context": None,
|
||||
"mac": mac,
|
||||
"address": ip_address}})
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,37 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# Interactive shell based on Django:
|
||||
#
|
||||
# Copyright (c) 2005, the Lawrence Journal-World
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of Django nor the names of its contributors may be used
|
||||
# to endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
"""
|
||||
CLI interface for nova management.
|
||||
Connects to the running ADMIN api in the api daemon.
|
||||
@@ -103,6 +134,29 @@ class VpnCommands(object):
|
||||
self.pipe.launch_vpn_instance(project_id)
|
||||
|
||||
|
||||
class ShellCommands(object):
|
||||
def run(self):
|
||||
"Runs a Python interactive interpreter. Tries to use IPython, if it's available."
|
||||
try:
|
||||
import IPython
|
||||
# Explicitly pass an empty list as arguments, because otherwise IPython
|
||||
# would use sys.argv from this script.
|
||||
shell = IPython.Shell.IPShell(argv=[])
|
||||
shell.mainloop()
|
||||
except ImportError:
|
||||
import code
|
||||
try: # Try activating rlcompleter, because it's handy.
|
||||
import readline
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
# We don't have to wrap the following import in a 'try', because
|
||||
# we already know 'readline' was imported successfully.
|
||||
import rlcompleter
|
||||
readline.parse_and_bind("tab:complete")
|
||||
code.interact()
|
||||
|
||||
|
||||
class RoleCommands(object):
|
||||
"""Class for managing roles."""
|
||||
|
||||
@@ -256,6 +310,7 @@ CATEGORIES = [
|
||||
('user', UserCommands),
|
||||
('project', ProjectCommands),
|
||||
('role', RoleCommands),
|
||||
('shell', ShellCommands),
|
||||
('vpn', VpnCommands),
|
||||
('floating', FloatingIpCommands)
|
||||
]
|
||||
|
||||
@@ -90,13 +90,14 @@ class CloudController(object):
|
||||
|
||||
def _get_mpi_data(self, project_id):
|
||||
result = {}
|
||||
for instance in db.instance_get_by_project(project_id):
|
||||
line = '%s slots=%d' % (instance.fixed_ip['str_id'],
|
||||
INSTANCE_TYPES[instance['instance_type']]['vcpus'])
|
||||
if instance['key_name'] in result:
|
||||
result[instance['key_name']].append(line)
|
||||
else:
|
||||
result[instance['key_name']] = [line]
|
||||
for instance in db.instance_get_by_project(None, project_id):
|
||||
if instance['fixed_ip']:
|
||||
line = '%s slots=%d' % (instance['fixed_ip']['str_id'],
|
||||
INSTANCE_TYPES[instance['instance_type']]['vcpus'])
|
||||
if instance['key_name'] in result:
|
||||
result[instance['key_name']].append(line)
|
||||
else:
|
||||
result[instance['key_name']] = [line]
|
||||
return result
|
||||
|
||||
def get_metadata(self, address):
|
||||
@@ -114,13 +115,13 @@ class CloudController(object):
|
||||
else:
|
||||
keys = ''
|
||||
hostname = instance_ref['hostname']
|
||||
floating_ip = db.instance_get_floating_ip_address(None,
|
||||
instance_ref['id'])
|
||||
floating_ip = db.instance_get_floating_address(None,
|
||||
instance_ref['id'])
|
||||
data = {
|
||||
'user-data': base64.b64decode(instance_ref['user_data']),
|
||||
'meta-data': {
|
||||
'ami-id': instance_ref['image_id'],
|
||||
'ami-launch-index': instance_ref['ami_launch_index'],
|
||||
'ami-launch-index': instance_ref['launch_index'],
|
||||
'ami-manifest-path': 'FIXME',
|
||||
'block-device-mapping': { # TODO(vish): replace with real data
|
||||
'ami': 'sda1',
|
||||
@@ -136,7 +137,7 @@ class CloudController(object):
|
||||
'local-ipv4': address,
|
||||
'kernel-id': instance_ref['kernel_id'],
|
||||
'placement': {
|
||||
'availaibility-zone': instance_ref['availability_zone'],
|
||||
'availability-zone': 'nova' # TODO(vish): real zone
|
||||
},
|
||||
'public-hostname': hostname,
|
||||
'public-ipv4': floating_ip or '',
|
||||
@@ -376,12 +377,14 @@ class CloudController(object):
|
||||
def _format_instances(self, context, reservation_id=None):
|
||||
reservations = {}
|
||||
if reservation_id:
|
||||
instances = db.instance_get_by_reservation(context, reservation_id)
|
||||
instances = db.instance_get_by_reservation(context,
|
||||
reservation_id)
|
||||
else:
|
||||
if not context.user.is_admin():
|
||||
instances = db.instance_get_all(context)
|
||||
else:
|
||||
instances = db.instance_get_by_project(context, context.project.id)
|
||||
instances = db.instance_get_by_project(context,
|
||||
context.project.id)
|
||||
for instance in instances:
|
||||
if not context.user.is_admin():
|
||||
if instance['image_id'] == FLAGS.vpn_image_id:
|
||||
@@ -393,15 +396,16 @@ class CloudController(object):
|
||||
'code': instance['state'],
|
||||
'name': instance['state_description']
|
||||
}
|
||||
fixed_addr = None
|
||||
floating_addr = None
|
||||
if instance['fixed_ip']['floating_ips']:
|
||||
floating_addr = instance['fixed_ip']['floating_ips'][0]['str_id']
|
||||
i['publicDnsName'] = floating_addr
|
||||
fixed_addr = instance['fixed_ip']['str_id']
|
||||
if instance['fixed_ip']:
|
||||
fixed_addr = instance['fixed_ip']['str_id']
|
||||
if instance['fixed_ip']['floating_ips']:
|
||||
fixed = instance['fixed_ip']
|
||||
floating_addr = fixed['floating_ips'][0]['str_id']
|
||||
i['privateDnsName'] = fixed_addr
|
||||
if not i['publicDnsName']:
|
||||
i['publicDnsName'] = i['privateDnsName']
|
||||
i['dnsName'] = None
|
||||
i['publicDnsName'] = floating_addr
|
||||
i['dnsName'] = i['publicDnsName'] or i['privateDnsName']
|
||||
i['keyName'] = instance['key_name']
|
||||
if context.user.is_admin():
|
||||
i['keyName'] = '%s (%s, %s)' % (i['keyName'],
|
||||
@@ -435,8 +439,10 @@ class CloudController(object):
|
||||
context.project.id)
|
||||
for floating_ip_ref in iterator:
|
||||
address = floating_ip_ref['str_id']
|
||||
instance_ref = db.floating_ip_get_instance(context, address)
|
||||
instance_id = instance_ref['str_id']
|
||||
instance_id = None
|
||||
if (floating_ip_ref['fixed_ip']
|
||||
and floating_ip_ref['fixed_ip']['instance']):
|
||||
instance_id = floating_ip_ref['fixed_ip']['instance']['str_id']
|
||||
address_rv = {'public_ip': address,
|
||||
'instance_id': instance_id}
|
||||
if context.user.is_admin():
|
||||
@@ -584,12 +590,13 @@ class CloudController(object):
|
||||
base_options['local_gb'] = type_data['local_gb']
|
||||
|
||||
for num in range(num_instances):
|
||||
inst_id = db.instance_create(context, base_options)['id']
|
||||
instance_ref = db.instance_create(context, base_options)
|
||||
inst_id = instance_ref['id']
|
||||
|
||||
inst = {}
|
||||
inst['mac_address'] = utils.generate_mac()
|
||||
inst['launch_index'] = num
|
||||
inst['hostname'] = inst_id
|
||||
inst['hostname'] = instance_ref['str_id']
|
||||
db.instance_update(context, inst_id, inst)
|
||||
address = self.network_manager.allocate_fixed_ip(context,
|
||||
inst_id,
|
||||
@@ -647,7 +654,7 @@ class CloudController(object):
|
||||
# NOTE(vish): Currently, nothing needs to be done on the
|
||||
# network node until release. If this changes,
|
||||
# we will need to cast here.
|
||||
db.fixed_ip_deallocate(context, address)
|
||||
self.network.deallocate_fixed_ip(context, address)
|
||||
|
||||
host = instance_ref['host']
|
||||
if host:
|
||||
|
||||
@@ -29,6 +29,7 @@ from nova import rpc
|
||||
from nova import test
|
||||
from nova import utils
|
||||
from nova.auth import manager
|
||||
from nova.compute import power_state
|
||||
from nova.endpoint import api
|
||||
from nova.endpoint import cloud
|
||||
|
||||
@@ -94,7 +95,7 @@ class CloudTestCase(test.BaseTestCase):
|
||||
rv = yield defer.succeed(time.sleep(1))
|
||||
info = self.cloud._get_instance(instance['instance_id'])
|
||||
logging.debug(info['state'])
|
||||
if info['state'] == node.Instance.RUNNING:
|
||||
if info['state'] == power_state.RUNNING:
|
||||
break
|
||||
self.assert_(rv)
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ from nova import flags
|
||||
from nova import test
|
||||
from nova import utils
|
||||
from nova.auth import manager
|
||||
from nova.endpoint import api
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
|
||||
@@ -48,7 +49,7 @@ class NetworkTestCase(test.TrialTestCase):
|
||||
self.user = self.manager.create_user('netuser', 'netuser', 'netuser')
|
||||
self.projects = []
|
||||
self.network = utils.import_object(FLAGS.network_manager)
|
||||
self.context = None
|
||||
self.context = api.APIRequestContext(None, project=None, user=self.user)
|
||||
for i in range(5):
|
||||
name = 'project%s' % i
|
||||
self.projects.append(self.manager.create_project(name,
|
||||
@@ -75,12 +76,10 @@ class NetworkTestCase(test.TrialTestCase):
|
||||
|
||||
def _create_address(self, project_num, instance_id=None):
|
||||
"""Create an address in given project num"""
|
||||
net = db.project_get_network(None, self.projects[project_num].id)
|
||||
address = db.fixed_ip_allocate(None, net['id'])
|
||||
if instance_id is None:
|
||||
instance_id = self.instance_id
|
||||
db.fixed_ip_instance_associate(None, address, instance_id)
|
||||
return address
|
||||
self.context.project = self.projects[project_num]
|
||||
return self.network.allocate_fixed_ip(self.context, instance_id)
|
||||
|
||||
def test_public_network_association(self):
|
||||
"""Makes sure that we can allocaate a public ip"""
|
||||
@@ -103,14 +102,14 @@ class NetworkTestCase(test.TrialTestCase):
|
||||
address = db.instance_get_floating_address(None, self.instance_id)
|
||||
self.assertEqual(address, None)
|
||||
self.network.deallocate_floating_ip(self.context, float_addr)
|
||||
db.fixed_ip_deallocate(None, fix_addr)
|
||||
self.network.deallocate_fixed_ip(self.context, fix_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)
|
||||
db.fixed_ip_deallocate(None, address)
|
||||
self.network.deallocate_fixed_ip(self.context, address)
|
||||
|
||||
# Doesn't go away until it's dhcp released
|
||||
self.assertTrue(is_allocated_in_project(address, self.projects[0].id))
|
||||
@@ -131,14 +130,14 @@ class NetworkTestCase(test.TrialTestCase):
|
||||
lease_ip(address)
|
||||
lease_ip(address2)
|
||||
|
||||
db.fixed_ip_deallocate(None, address)
|
||||
self.network.deallocate_fixed_ip(self.context, 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))
|
||||
|
||||
db.fixed_ip_deallocate(None, address2)
|
||||
self.network.deallocate_fixed_ip(self.context, address2)
|
||||
release_ip(address2)
|
||||
self.assertFalse(is_allocated_in_project(address2,
|
||||
self.projects[1].id))
|
||||
@@ -147,10 +146,23 @@ class NetworkTestCase(test.TrialTestCase):
|
||||
"""Makes sure that private ips don't overlap"""
|
||||
first = self._create_address(0)
|
||||
lease_ip(first)
|
||||
instance_ids = []
|
||||
for i in range(1, 5):
|
||||
address = self._create_address(i)
|
||||
address2 = self._create_address(i)
|
||||
address3 = self._create_address(i)
|
||||
mac = utils.generate_mac()
|
||||
instance_ref = db.instance_create(None,
|
||||
{'mac_address': mac})
|
||||
instance_ids.append(instance_ref['id'])
|
||||
address = self._create_address(i, instance_ref['id'])
|
||||
mac = utils.generate_mac()
|
||||
instance_ref = db.instance_create(None,
|
||||
{'mac_address': mac})
|
||||
instance_ids.append(instance_ref['id'])
|
||||
address2 = self._create_address(i, instance_ref['id'])
|
||||
mac = utils.generate_mac()
|
||||
instance_ref = db.instance_create(None,
|
||||
{'mac_address': mac})
|
||||
instance_ids.append(instance_ref['id'])
|
||||
address3 = self._create_address(i, instance_ref['id'])
|
||||
lease_ip(address)
|
||||
lease_ip(address2)
|
||||
lease_ip(address3)
|
||||
@@ -160,14 +172,16 @@ class NetworkTestCase(test.TrialTestCase):
|
||||
self.projects[0].id))
|
||||
self.assertFalse(is_allocated_in_project(address3,
|
||||
self.projects[0].id))
|
||||
db.fixed_ip_deallocate(None, address)
|
||||
db.fixed_ip_deallocate(None, address2)
|
||||
db.fixed_ip_deallocate(None, address3)
|
||||
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(None, instance_id)
|
||||
release_ip(first)
|
||||
db.fixed_ip_deallocate(None, first)
|
||||
self.network.deallocate_fixed_ip(self.context, first)
|
||||
|
||||
def test_vpn_ip_and_port_looks_valid(self):
|
||||
"""Ensure the vpn ip and port are reasonable"""
|
||||
@@ -194,12 +208,12 @@ class NetworkTestCase(test.TrialTestCase):
|
||||
"""Makes sure that ip addresses that are deallocated get reused"""
|
||||
address = self._create_address(0)
|
||||
lease_ip(address)
|
||||
db.fixed_ip_deallocate(None, address)
|
||||
self.network.deallocate_fixed_ip(self.context, address)
|
||||
release_ip(address)
|
||||
|
||||
address2 = self._create_address(0)
|
||||
self.assertEqual(address, address2)
|
||||
db.fixed_ip_deallocate(None, address2)
|
||||
self.network.deallocate_fixed_ip(self.context, address2)
|
||||
|
||||
def test_available_ips(self):
|
||||
"""Make sure the number of available ips for the network is correct
|
||||
@@ -226,21 +240,27 @@ class NetworkTestCase(test.TrialTestCase):
|
||||
num_available_ips = db.network_count_available_ips(None,
|
||||
network['id'])
|
||||
addresses = []
|
||||
instance_ids = []
|
||||
for i in range(num_available_ips):
|
||||
address = self._create_address(0)
|
||||
mac = utils.generate_mac()
|
||||
instance_ref = db.instance_create(None,
|
||||
{'mac_address': mac})
|
||||
instance_ids.append(instance_ref['id'])
|
||||
address = self._create_address(0, instance_ref['id'])
|
||||
addresses.append(address)
|
||||
lease_ip(address)
|
||||
|
||||
self.assertEqual(db.network_count_available_ips(None,
|
||||
network['id']), 0)
|
||||
self.assertRaises(db.NoMoreAddresses,
|
||||
db.fixed_ip_allocate,
|
||||
None,
|
||||
network['id'])
|
||||
self.network.allocate_fixed_ip,
|
||||
self.context,
|
||||
'foo')
|
||||
|
||||
for i in range(len(addresses)):
|
||||
db.fixed_ip_deallocate(None, addresses[i])
|
||||
for i in range(num_available_ips):
|
||||
self.network.deallocate_fixed_ip(self.context, addresses[i])
|
||||
release_ip(addresses[i])
|
||||
db.instance_destroy(None, instance_ids[i])
|
||||
self.assertEqual(db.network_count_available_ips(None,
|
||||
network['id']),
|
||||
num_available_ips)
|
||||
@@ -263,7 +283,10 @@ def binpath(script):
|
||||
def lease_ip(private_ip):
|
||||
"""Run add command on dhcpbridge"""
|
||||
network_ref = db.fixed_ip_get_network(None, private_ip)
|
||||
cmd = "%s add fake %s fake" % (binpath('nova-dhcpbridge'), private_ip)
|
||||
instance_ref = db.fixed_ip_get_instance(None, private_ip)
|
||||
cmd = "%s add %s %s fake" % (binpath('nova-dhcpbridge'),
|
||||
instance_ref['mac_address'],
|
||||
private_ip)
|
||||
env = {'DNSMASQ_INTERFACE': network_ref['bridge'],
|
||||
'TESTING': '1',
|
||||
'FLAGFILE': FLAGS.dhcpbridge_flagfile}
|
||||
@@ -274,7 +297,10 @@ def lease_ip(private_ip):
|
||||
def release_ip(private_ip):
|
||||
"""Run del command on dhcpbridge"""
|
||||
network_ref = db.fixed_ip_get_network(None, private_ip)
|
||||
cmd = "%s del fake %s fake" % (binpath('nova-dhcpbridge'), private_ip)
|
||||
instance_ref = db.fixed_ip_get_instance(None, private_ip)
|
||||
cmd = "%s del %s %s fake" % (binpath('nova-dhcpbridge'),
|
||||
instance_ref['mac_address'],
|
||||
private_ip)
|
||||
env = {'DNSMASQ_INTERFACE': network_ref['bridge'],
|
||||
'TESTING': '1',
|
||||
'FLAGFILE': FLAGS.dhcpbridge_flagfile}
|
||||
|
||||
Reference in New Issue
Block a user