From f7beae47ca505443eb86ea1a4fba6b47c1658755 Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Thu, 24 Feb 2011 17:07:59 -0800
Subject: IPV6 FlatManager changes
---
nova/db/sqlalchemy/api.py | 11 ++--
.../versions/007_add_ipv6_flatmanager.py | 75 ++++++++++++++++++++++
nova/db/sqlalchemy/models.py | 3 +
nova/network/manager.py | 35 +++++++++-
nova/virt/interfaces.template | 16 +++--
nova/virt/libvirt_conn.py | 27 +++++---
6 files changed, 149 insertions(+), 18 deletions(-)
create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index d8751bef4..9bc59de60 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -833,10 +833,13 @@ def instance_get_fixed_address_v6(context, instance_id):
session = get_session()
with session.begin():
instance_ref = instance_get(context, instance_id, session=session)
- network_ref = network_get_by_instance(context, instance_id)
- prefix = network_ref.cidr_v6
- mac = instance_ref.mac_address
- return utils.to_global_ipv6(prefix, mac)
+ if 'nova.network.manager.FlatManager' == FLAGS.network_manager:
+ return instance_ref.fixed_ip['addressv6']
+ else:
+ network_ref = network_get_by_instance(context, instance_id)
+ prefix = network_ref.cidr_v6
+ mac = instance_ref.mac_address
+ return utils.to_global_ipv6(prefix, mac)
@require_context
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py b/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
new file mode 100644
index 000000000..2951cbc0a
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
@@ -0,0 +1,75 @@
+# Copyright 2010 OpenStack LLC.
+# 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.
+
+from sqlalchemy import *
+from migrate import *
+
+from nova import log as logging
+
+
+meta = MetaData()
+
+
+# Table stub-definitions
+# Just for the ForeignKey and column creation to succeed, these are not the
+# actual definitions of instances or services.
+#
+networks = Table('networks', meta,
+ Column('id', Integer(), primary_key=True, nullable=False),
+ )
+
+fixed_ips = Table('fixed_ips', meta,
+ Column('id', Integer(), primary_key=True, nullable=False),
+ )
+
+#
+# New Tables
+#
+# None
+
+#
+# Tables to alter
+#
+# None
+
+#
+# Columns to add to existing tables
+#
+
+networks_gatewayv6 = Column(
+ 'gatewayv6',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False))
+
+networks_netmaskv6 = Column(
+ 'netmaskv6',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False))
+
+fixed_ips_addressv6 = Column(
+ 'addressv6',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False))
+
+
+def upgrade(migrate_engine):
+ # Upgrade operations go here. Don't create your own engine;
+ # bind migrate_engine to your metadata
+ meta.bind = migrate_engine
+
+ # Add columns to existing tables
+ networks.create_column(networks_gatewayv6)
+ networks.create_column(networks_netmaskv6)
+ fixed_ips.create_column(fixed_ips_addressv6)
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 1882efeba..4fa4d443c 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -385,6 +385,8 @@ class Network(BASE, NovaBase):
ra_server = Column(String(255))
+ gatewayv6 = Column(String(255))
+ netmaskv6 = Column(String(255))
netmask = Column(String(255))
bridge = Column(String(255))
gateway = Column(String(255))
@@ -425,6 +427,7 @@ class FixedIp(BASE, NovaBase):
__tablename__ = 'fixed_ips'
id = Column(Integer, primary_key=True)
address = Column(String(255))
+ addressv6 = Column(String(255))
network_id = Column(Integer, ForeignKey('networks.id'), nullable=True)
network = relationship(Network, backref=backref('fixed_ips'))
instance_id = Column(Integer, ForeignKey('instances.id'), nullable=True)
diff --git a/nova/network/manager.py b/nova/network/manager.py
index 12a0c5018..61b5dc07f 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -361,9 +361,11 @@ class FlatManager(NetworkManager):
fixed_net = IPy.IP(cidr)
fixed_net_v6 = IPy.IP(cidr_v6)
significant_bits_v6 = 64
+ network_size_v6 = 1 << 64
count = 1
for index in range(num_networks):
start = index * network_size
+ start_v6 = index * network_size_v6
significant_bits = 32 - int(math.log(network_size, 2))
cidr = "%s/%s" % (fixed_net[start], significant_bits)
project_net = IPy.IP(cidr)
@@ -382,14 +384,45 @@ class FlatManager(NetworkManager):
count += 1
if(FLAGS.use_ipv6):
- cidr_v6 = "%s/%s" % (fixed_net_v6[0], significant_bits_v6)
+ cidr_v6 = "%s/%s" % (fixed_net_v6[start_v6],
+ significant_bits_v6)
net['cidr_v6'] = cidr_v6
+ project_net_v6 = IPy.IP(cidr_v6)
+ net['gatewayv6'] = str(project_net_v6[1])
+ net['netmaskv6'] = str(project_net_v6.prefixlen())
network_ref = self.db.network_create_safe(context, net)
if network_ref:
self._create_fixed_ips(context, network_ref['id'])
+ def _create_fixed_ips(self, context, network_id):
+ """Create all fixed ips for network."""
+ network_ref = self.db.network_get(context, network_id)
+ # NOTE(vish): Should these be properties of the network as opposed
+ # to properties of the manager class?
+ bottom_reserved = self._bottom_reserved_ips
+ top_reserved = self._top_reserved_ips
+ project_net = IPy.IP(network_ref['cidr'])
+
+ if(FLAGS.use_ipv6):
+ project_net_v6 = IPy.IP(network_ref['cidr_v6'])
+
+ num_ips = len(project_net)
+ addressv6 = None
+ for index in range(num_ips):
+ address = str(project_net[index])
+ if(FLAGS.use_ipv6):
+ addressv6 = str(project_net_v6[index])
+ if index < bottom_reserved or num_ips - index < top_reserved:
+ reserved = True
+ else:
+ reserved = False
+ self.db.fixed_ip_create(context, {'network_id': network_id,
+ 'address': address,
+ 'addressv6': addressv6,
+ 'reserved': reserved})
+
def get_network_host(self, context):
"""Get the network host for the current context."""
network_ref = self.db.network_get_by_bridge(context,
diff --git a/nova/virt/interfaces.template b/nova/virt/interfaces.template
index 87b92b84a..1db745f9f 100644
--- a/nova/virt/interfaces.template
+++ b/nova/virt/interfaces.template
@@ -8,10 +8,16 @@ iface lo inet loopback
# The primary network interface
auto eth0
iface eth0 inet static
- address %(address)s
- netmask %(netmask)s
- broadcast %(broadcast)s
- gateway %(gateway)s
- dns-nameservers %(dns)s
+ address ${address}
+ netmask ${netmask}
+ broadcast ${broadcast}
+ gateway ${gateway}
+ dns-nameservers ${dns}
+#if $use_ipv6
+iface eth0 inet6 static
+ address ${addressv6}
+ netmask ${netmaskv6}
+ gateway ${gatewayv6}
+#end if
diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py
index 4e0fd106f..b7712f76e 100644
--- a/nova/virt/libvirt_conn.py
+++ b/nova/virt/libvirt_conn.py
@@ -146,6 +146,7 @@ class LibvirtConnection(object):
self.libvirt_uri = self.get_uri()
self.libvirt_xml = open(FLAGS.libvirt_xml_template).read()
+ self.interfaces_xml = open(FLAGS.injected_network_template).read()
self._wrapped_conn = None
self.read_only = read_only
@@ -628,17 +629,27 @@ class LibvirtConnection(object):
inst['id'])
if network_ref['injected']:
admin_context = context.get_admin_context()
- address = db.instance_get_fixed_address(admin_context, inst['id'])
+ address = db.instance_get_fixed_address(admin_context,
+ inst['id'])
+ addressv6 = db.instance_get_fixed_address_v6(admin_context,
+ inst['id'])
ra_server = network_ref['ra_server']
if not ra_server:
ra_server = "fd00::"
- with open(FLAGS.injected_network_template) as f:
- net = f.read() % {'address': address,
- 'netmask': network_ref['netmask'],
- 'gateway': network_ref['gateway'],
- 'broadcast': network_ref['broadcast'],
- 'dns': network_ref['dns'],
- 'ra_server': ra_server}
+
+ interfaces_info = {'address': address,
+ 'netmask': network_ref['netmask'],
+ 'gateway': network_ref['gateway'],
+ 'broadcast': network_ref['broadcast'],
+ 'dns': network_ref['dns'],
+ 'ra_server': ra_server,
+ 'addressv6': addressv6,
+ 'gatewayv6': network_ref['gatewayv6'],
+ 'netmaskv6': network_ref['netmaskv6'],
+ 'use_ipv6': FLAGS.use_ipv6}
+
+ net = str(Template(self.interfaces_xml,
+ searchList=[interfaces_info]))
if key or net:
inst_name = inst['name']
img_id = inst.image_id
--
cgit
From 20e9df05acdb89382023af1ac98cf040c827e18d Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Fri, 25 Feb 2011 14:49:33 -0800
Subject: DescribeInstances modified to return ipv6 fixed ip address in case of
flatmanager
---
nova/api/ec2/cloud.py | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 7458d307a..15799670c 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -701,9 +701,13 @@ class CloudController(object):
fixed = instance['fixed_ip']
floating_addr = fixed['floating_ips'][0]['address']
if instance['fixed_ip']['network'] and 'use_v6' in kwargs:
- i['dnsNameV6'] = utils.to_global_ipv6(
- instance['fixed_ip']['network']['cidr_v6'],
- instance['mac_address'])
+ if FLAGS.network_manager == \
+ 'nova.network.manager.FlatManager':
+ i['dnsNameV6'] = instance['fixed_ip']['addressv6']
+ else:
+ i['dnsNameV6'] = utils.to_global_ipv6(
+ instance['fixed_ip']['network']['cidr_v6'],
+ instance['mac_address'])
i['privateDnsName'] = fixed_addr
i['publicDnsName'] = floating_addr
--
cgit
From df0a4d66f7059db94e1de365fed8b8d244e16534 Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Tue, 1 Mar 2011 17:12:47 -0800
Subject: Changed ra_server to gateway_v6 and removed addressv6 column from
fixed_ips db table
---
nova/api/ec2/cloud.py | 4 ---
nova/db/sqlalchemy/api.py | 11 +++---
.../versions/007_add_ipv6_flatmanager.py | 24 ++++---------
nova/db/sqlalchemy/models.py | 5 ++-
nova/network/linux_net.py | 2 +-
nova/network/manager.py | 37 +++++---------------
nova/virt/interfaces.template | 6 ++--
nova/virt/libvirt.xml.template | 4 +--
nova/virt/libvirt_conn.py | 40 +++++++++++-----------
9 files changed, 47 insertions(+), 86 deletions(-)
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 15799670c..b3779a4da 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -701,10 +701,6 @@ class CloudController(object):
fixed = instance['fixed_ip']
floating_addr = fixed['floating_ips'][0]['address']
if instance['fixed_ip']['network'] and 'use_v6' in kwargs:
- if FLAGS.network_manager == \
- 'nova.network.manager.FlatManager':
- i['dnsNameV6'] = instance['fixed_ip']['addressv6']
- else:
i['dnsNameV6'] = utils.to_global_ipv6(
instance['fixed_ip']['network']['cidr_v6'],
instance['mac_address'])
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index 9bc59de60..d8751bef4 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -833,13 +833,10 @@ def instance_get_fixed_address_v6(context, instance_id):
session = get_session()
with session.begin():
instance_ref = instance_get(context, instance_id, session=session)
- if 'nova.network.manager.FlatManager' == FLAGS.network_manager:
- return instance_ref.fixed_ip['addressv6']
- else:
- network_ref = network_get_by_instance(context, instance_id)
- prefix = network_ref.cidr_v6
- mac = instance_ref.mac_address
- return utils.to_global_ipv6(prefix, mac)
+ network_ref = network_get_by_instance(context, instance_id)
+ prefix = network_ref.cidr_v6
+ mac = instance_ref.mac_address
+ return utils.to_global_ipv6(prefix, mac)
@require_context
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py b/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
index 2951cbc0a..e09f46652 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
@@ -30,10 +30,6 @@ networks = Table('networks', meta,
Column('id', Integer(), primary_key=True, nullable=False),
)
-fixed_ips = Table('fixed_ips', meta,
- Column('id', Integer(), primary_key=True, nullable=False),
- )
-
#
# New Tables
#
@@ -42,24 +38,19 @@ fixed_ips = Table('fixed_ips', meta,
#
# Tables to alter
#
-# None
+
#
# Columns to add to existing tables
#
-networks_gatewayv6 = Column(
- 'gatewayv6',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False))
-
-networks_netmaskv6 = Column(
- 'netmaskv6',
+networks_gateway_v6 = Column(
+ 'gateway_v6',
String(length=255, convert_unicode=False, assert_unicode=None,
unicode_error=None, _warn_on_bytestring=False))
-fixed_ips_addressv6 = Column(
- 'addressv6',
+networks_netmask_v6 = Column(
+ 'netmask_v6',
String(length=255, convert_unicode=False, assert_unicode=None,
unicode_error=None, _warn_on_bytestring=False))
@@ -70,6 +61,5 @@ def upgrade(migrate_engine):
meta.bind = migrate_engine
# Add columns to existing tables
- networks.create_column(networks_gatewayv6)
- networks.create_column(networks_netmaskv6)
- fixed_ips.create_column(fixed_ips_addressv6)
+ networks.create_column(networks_gateway_v6)
+ networks.create_column(networks_netmask_v6)
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 4fa4d443c..f235054d2 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -385,8 +385,8 @@ class Network(BASE, NovaBase):
ra_server = Column(String(255))
- gatewayv6 = Column(String(255))
- netmaskv6 = Column(String(255))
+ gateway_v6 = Column(String(255))
+ netmask_v6 = Column(String(255))
netmask = Column(String(255))
bridge = Column(String(255))
gateway = Column(String(255))
@@ -427,7 +427,6 @@ class FixedIp(BASE, NovaBase):
__tablename__ = 'fixed_ips'
id = Column(Integer, primary_key=True)
address = Column(String(255))
- addressv6 = Column(String(255))
network_id = Column(Integer, ForeignKey('networks.id'), nullable=True)
network = relationship(Network, backref=backref('fixed_ips'))
instance_id = Column(Integer, ForeignKey('instances.id'), nullable=True)
diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py
index 535ce87bc..e375568f1 100644
--- a/nova/network/linux_net.py
+++ b/nova/network/linux_net.py
@@ -361,7 +361,7 @@ interface %s
command = _ra_cmd(network_ref)
_execute(command)
db.network_update(context, network_id,
- {"ra_server":
+ {"gateway_v6":
utils.get_my_linklocal(network_ref['bridge'])})
diff --git a/nova/network/manager.py b/nova/network/manager.py
index 61b5dc07f..bdeeae293 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -388,41 +388,14 @@ class FlatManager(NetworkManager):
significant_bits_v6)
net['cidr_v6'] = cidr_v6
project_net_v6 = IPy.IP(cidr_v6)
- net['gatewayv6'] = str(project_net_v6[1])
- net['netmaskv6'] = str(project_net_v6.prefixlen())
+ net['gateway_v6'] = str(project_net_v6[1])
+ net['netmask_v6'] = str(project_net_v6.prefixlen())
network_ref = self.db.network_create_safe(context, net)
if network_ref:
self._create_fixed_ips(context, network_ref['id'])
- def _create_fixed_ips(self, context, network_id):
- """Create all fixed ips for network."""
- network_ref = self.db.network_get(context, network_id)
- # NOTE(vish): Should these be properties of the network as opposed
- # to properties of the manager class?
- bottom_reserved = self._bottom_reserved_ips
- top_reserved = self._top_reserved_ips
- project_net = IPy.IP(network_ref['cidr'])
-
- if(FLAGS.use_ipv6):
- project_net_v6 = IPy.IP(network_ref['cidr_v6'])
-
- num_ips = len(project_net)
- addressv6 = None
- for index in range(num_ips):
- address = str(project_net[index])
- if(FLAGS.use_ipv6):
- addressv6 = str(project_net_v6[index])
- if index < bottom_reserved or num_ips - index < top_reserved:
- reserved = True
- else:
- reserved = False
- self.db.fixed_ip_create(context, {'network_id': network_id,
- 'address': address,
- 'addressv6': addressv6,
- 'reserved': reserved})
-
def get_network_host(self, context):
"""Get the network host for the current context."""
network_ref = self.db.network_get_by_bridge(context,
@@ -448,6 +421,12 @@ class FlatManager(NetworkManager):
net = {}
net['injected'] = FLAGS.flat_injected
net['dns'] = FLAGS.flat_network_dns
+
+ if not FLAGS.fake_network:
+ if(FLAGS.use_ipv6):
+ net['gateway_v6'] = \
+ utils.get_my_linklocal(FLAGS.flat_network_bridge)
+
self.db.network_update(context, network_id, net)
def allocate_floating_ip(self, context, project_id):
diff --git a/nova/virt/interfaces.template b/nova/virt/interfaces.template
index 1db745f9f..3b34e54f4 100644
--- a/nova/virt/interfaces.template
+++ b/nova/virt/interfaces.template
@@ -16,8 +16,8 @@ iface eth0 inet static
#if $use_ipv6
iface eth0 inet6 static
- address ${addressv6}
- netmask ${netmaskv6}
- gateway ${gatewayv6}
+ address ${address_v6}
+ netmask ${netmask_v6}
+ gateway ${gateway_v6}
#end if
diff --git a/nova/virt/libvirt.xml.template b/nova/virt/libvirt.xml.template
index 88bfbc668..ef2d2cd6b 100644
--- a/nova/virt/libvirt.xml.template
+++ b/nova/virt/libvirt.xml.template
@@ -79,8 +79,8 @@
#if $getVar('extra_params', False)
${extra_params}
#end if
-#if $getVar('ra_server', False)
-
+#if $getVar('gateway_v6', False)
+
#end if
diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py
index b7712f76e..38fa2338e 100644
--- a/nova/virt/libvirt_conn.py
+++ b/nova/virt/libvirt_conn.py
@@ -631,21 +631,21 @@ class LibvirtConnection(object):
admin_context = context.get_admin_context()
address = db.instance_get_fixed_address(admin_context,
inst['id'])
- addressv6 = db.instance_get_fixed_address_v6(admin_context,
+ address_v6 = db.instance_get_fixed_address_v6(admin_context,
inst['id'])
- ra_server = network_ref['ra_server']
- if not ra_server:
- ra_server = "fd00::"
+ gateway_v6 = network_ref['gateway_v6']
+ if not gateway_v6:
+ gateway_v6 = "fd00::"
interfaces_info = {'address': address,
'netmask': network_ref['netmask'],
'gateway': network_ref['gateway'],
'broadcast': network_ref['broadcast'],
'dns': network_ref['dns'],
- 'ra_server': ra_server,
- 'addressv6': addressv6,
- 'gatewayv6': network_ref['gatewayv6'],
- 'netmaskv6': network_ref['netmaskv6'],
+ 'gateway_v6': gateway_v6,
+ 'address_v6': address_v6,
+ 'gateway_v6': network_ref['gateway_v6'],
+ 'netmask_v6': network_ref['netmask_v6'],
'use_ipv6': FLAGS.use_ipv6}
net = str(Template(self.interfaces_xml,
@@ -683,7 +683,7 @@ class LibvirtConnection(object):
instance['id'])
# Assume that the gateway also acts as the dhcp server.
dhcp_server = network['gateway']
- ra_server = network['ra_server']
+ gateway_v6 = network['gateway_v6']
if FLAGS.allow_project_net_traffic:
if FLAGS.use_ipv6:
@@ -728,8 +728,8 @@ class LibvirtConnection(object):
'local': instance_type['local_gb'],
'driver_type': driver_type}
- if ra_server:
- xml_info['ra_server'] = ra_server + "/128"
+ if gateway_v6:
+ xml_info['gateway_v6'] = gateway_v6 + "/128"
if not rescue:
if instance['kernel_id']:
xml_info['kernel'] = xml_info['basepath'] + "/kernel"
@@ -921,10 +921,10 @@ class FirewallDriver(object):
"""
raise NotImplementedError()
- def _ra_server_for_instance(self, instance):
+ def _gateway_v6_for_instance(self, instance):
network = db.network_get_by_instance(context.get_admin_context(),
instance['id'])
- return network['ra_server']
+ return network['gateway_v6']
class NWFilterFirewall(FirewallDriver):
@@ -1140,8 +1140,8 @@ class NWFilterFirewall(FirewallDriver):
'nova-base-ipv6',
'nova-allow-dhcp-server']
if FLAGS.use_ipv6:
- ra_server = self._ra_server_for_instance(instance)
- if ra_server:
+ gateway_v6 = self._gateway_v6_for_instance(instance)
+ if gateway_v6:
instance_secgroup_filter_children += ['nova-allow-ra-server']
ctxt = context.get_admin_context()
@@ -1328,10 +1328,10 @@ class IptablesFirewallDriver(FirewallDriver):
our_rules += ['-A %s -s %s -j ACCEPT' % (chain_name, cidr)]
elif(ip_version == 6):
# Allow RA responses
- ra_server = self._ra_server_for_instance(instance)
- if ra_server:
+ gateway_v6 = self._gateway_v6_for_instance(instance)
+ if gateway_v6:
our_rules += ['-A %s -s %s -p icmpv6 -j ACCEPT' %
- (chain_name, ra_server + "/128")]
+ (chain_name, gateway_v6 + "/128")]
#Allow project network traffic
if (FLAGS.allow_project_net_traffic):
cidrv6 = self._project_cidrv6_for_instance(instance)
@@ -1427,10 +1427,10 @@ class IptablesFirewallDriver(FirewallDriver):
instance['id'])
return network['gateway']
- def _ra_server_for_instance(self, instance):
+ def _gateway_v6_for_instance(self, instance):
network = db.network_get_by_instance(context.get_admin_context(),
instance['id'])
- return network['ra_server']
+ return network['gateway_v6']
def _project_cidr_for_instance(self, instance):
network = db.network_get_by_instance(context.get_admin_context(),
--
cgit
From 0a9ba675c88ae0b2a18f47524d24075409261658 Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Thu, 3 Mar 2011 15:39:23 -0800
Subject: altered ra_server name to gateway_v6
---
.../versions/007_add_ipv6_flatmanager.py | 14 ++--
.../versions/007_add_ipv6_to_fixed_ips.py | 90 ----------------------
2 files changed, 6 insertions(+), 98 deletions(-)
delete mode 100644 nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_to_fixed_ips.py
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py b/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
index e09f46652..937712970 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
@@ -28,7 +28,10 @@ meta = MetaData()
#
networks = Table('networks', meta,
Column('id', Integer(), primary_key=True, nullable=False),
- )
+ Column('ra_server', String(length=255, convert_unicode=False,
+ assert_unicode=None, unicode_error=None,
+ _warn_on_bytestring=False))
+ )
#
# New Tables
@@ -43,12 +46,6 @@ networks = Table('networks', meta,
#
# Columns to add to existing tables
#
-
-networks_gateway_v6 = Column(
- 'gateway_v6',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False))
-
networks_netmask_v6 = Column(
'netmask_v6',
String(length=255, convert_unicode=False, assert_unicode=None,
@@ -60,6 +57,7 @@ def upgrade(migrate_engine):
# bind migrate_engine to your metadata
meta.bind = migrate_engine
+ # Alter column name
+ networks.c.ra_server.alter(name='gateway_v6')
# Add columns to existing tables
- networks.create_column(networks_gateway_v6)
networks.create_column(networks_netmask_v6)
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_to_fixed_ips.py b/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_to_fixed_ips.py
deleted file mode 100644
index 427934d53..000000000
--- a/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_to_fixed_ips.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# Copyright 2011 OpenStack LLC
-# 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.
-
-from sqlalchemy import *
-from migrate import *
-
-from nova import log as logging
-
-
-meta = MetaData()
-
-
-# Table stub-definitions
-# Just for the ForeignKey and column creation to succeed, these are not the
-# actual definitions of instances or services.
-#
-fixed_ips = Table(
- "fixed_ips",
- meta,
- Column(
- "id",
- Integer(),
- primary_key=True,
- nullable=False))
-
-#
-# New Tables
-#
-# None
-
-#
-# Tables to alter
-#
-# None
-
-#
-# Columns to add to existing tables
-#
-
-fixed_ips_addressV6 = Column(
- "addressV6",
- String(
- length=255,
- convert_unicode=False,
- assert_unicode=None,
- unicode_error=None,
- _warn_on_bytestring=False))
-
-
-fixed_ips_netmaskV6 = Column(
- "netmaskV6",
- String(
- length=3,
- convert_unicode=False,
- assert_unicode=None,
- unicode_error=None,
- _warn_on_bytestring=False))
-
-
-fixed_ips_gatewayV6 = Column(
- "gatewayV6",
- String(
- length=255,
- convert_unicode=False,
- assert_unicode=None,
- unicode_error=None,
- _warn_on_bytestring=False))
-
-
-def upgrade(migrate_engine):
- # Upgrade operations go here. Don't create your own engine;
- # bind migrate_engine to your metadata
- meta.bind = migrate_engine
-
- # Add columns to existing tables
- fixed_ips.create_column(fixed_ips_addressV6)
- fixed_ips.create_column(fixed_ips_netmaskV6)
- fixed_ips.create_column(fixed_ips_gatewayV6)
--
cgit
From 35be7d39866f6ac1017dd94d33d9c01f47a6bc74 Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Thu, 3 Mar 2011 15:44:01 -0800
Subject: Removed properties added to fixed_ips by xs-ipv6 BP
---
nova/db/sqlalchemy/models.py | 3 ---
nova/network/manager.py | 2 +-
2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 4c94cd3db..7b4683427 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -458,9 +458,6 @@ class FixedIp(BASE, NovaBase):
allocated = Column(Boolean, default=False)
leased = Column(Boolean, default=False)
reserved = Column(Boolean, default=False)
- addressV6 = Column(String(255))
- netmaskV6 = Column(String(3))
- gatewayV6 = Column(String(255))
class User(BASE, NovaBase):
diff --git a/nova/network/manager.py b/nova/network/manager.py
index fb6e16772..686ab9732 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -167,7 +167,7 @@ class NetworkManager(manager.Manager):
# with a network, or a cluster of computes with a network
# and use that network here with a method like
# network_get_by_compute_host
- network_ref = self.db.network_get_by_bridge(context,
+ network_ref = self.db.network_get_by_bridge(context.elevated(),
FLAGS.flat_network_bridge)
address = self.db.fixed_ip_associate_pool(context.elevated(),
network_ref['id'],
--
cgit
From aa09f87060c1d1885b7a557ff26a3c421ad42df8 Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Thu, 3 Mar 2011 17:31:37 -0800
Subject: remove ra_server from model and fix migration issue while running
unit tests
---
.../versions/007_add_ipv6_flatmanager.py | 60 +++++++++++++++++++---
nova/db/sqlalchemy/models.py | 2 -
2 files changed, 54 insertions(+), 8 deletions(-)
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py b/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
index 937712970..d14f52af1 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
@@ -12,6 +12,7 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
+from lib2to3.fixer_util import String
from sqlalchemy import *
from migrate import *
@@ -27,12 +28,59 @@ meta = MetaData()
# actual definitions of instances or services.
#
networks = Table('networks', meta,
+ Column('created_at', DateTime(timezone=False)),
+ Column('updated_at', DateTime(timezone=False)),
+ Column('deleted_at', DateTime(timezone=False)),
+ Column('deleted', Boolean(create_constraint=True, name=None)),
Column('id', Integer(), primary_key=True, nullable=False),
- Column('ra_server', String(length=255, convert_unicode=False,
- assert_unicode=None, unicode_error=None,
- _warn_on_bytestring=False))
- )
-
+ Column('injected', Boolean(create_constraint=True, name=None)),
+ Column('cidr',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('netmask',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('bridge',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('gateway',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('broadcast',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('dns',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('vlan', Integer()),
+ Column('vpn_public_address',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('vpn_public_port', Integer()),
+ Column('vpn_private_address',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('dhcp_start',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('project_id',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('host',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('cidr_v6',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column(
+ 'ra_server',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column(
+ 'label',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False))
+ )
#
# New Tables
#
@@ -59,5 +107,5 @@ def upgrade(migrate_engine):
# Alter column name
networks.c.ra_server.alter(name='gateway_v6')
- # Add columns to existing tables
+ # Add new column to existing table
networks.create_column(networks_netmask_v6)
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 7b4683427..14ff46647 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -402,8 +402,6 @@ class Network(BASE, NovaBase):
cidr = Column(String(255), unique=True)
cidr_v6 = Column(String(255), unique=True)
- ra_server = Column(String(255))
-
gateway_v6 = Column(String(255))
netmask_v6 = Column(String(255))
netmask = Column(String(255))
--
cgit
From 1831f31af0ac21ded3535f15777bd5147c615c34 Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Fri, 4 Mar 2011 11:52:18 -0800
Subject: added flatmanager unit testcases and renamed test_network.py to
test_vlan_network.py
---
nova/tests/test_flat_network.py | 276 +++++++++++++++++++++++++++++
nova/tests/test_network.py | 369 ---------------------------------------
nova/tests/test_vlan_network.py | 373 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 649 insertions(+), 369 deletions(-)
create mode 100644 nova/tests/test_flat_network.py
delete mode 100644 nova/tests/test_network.py
create mode 100644 nova/tests/test_vlan_network.py
diff --git a/nova/tests/test_flat_network.py b/nova/tests/test_flat_network.py
new file mode 100644
index 000000000..91a49920d
--- /dev/null
+++ b/nova/tests/test_flat_network.py
@@ -0,0 +1,276 @@
+# 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 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
+
+FLAGS = flags.FLAGS
+LOG = logging.getLogger('nova.tests.network')
+
+
+class FlatNetworkTestCase(test.TestCase):
+ """Test cases for network code"""
+ def setUp(self):
+ super(FlatNetworkTestCase, 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(5):
+ 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(FlatNetworkTestCase, 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 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(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(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._deallocate_address(0, 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[0].id))
+
+ self._deallocate_address(1, address2)
+ self.assertFalse(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_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)
+
+ 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)
+
+
+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)
+ project_net = db.network_get_by_bridge(context.get_admin_context(),
+ FLAGS.flat_network_bridge)
+ 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))
diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py
deleted file mode 100644
index ce1c77210..000000000
--- a/nova/tests/test_network.py
+++ /dev/null
@@ -1,369 +0,0 @@
-# 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 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
-
-FLAGS = flags.FLAGS
-LOG = logging.getLogger('nova.tests.network')
-
-
-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 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 = "%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}
- (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 = "%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}
- (out, err) = utils.execute(cmd, addl_env=env)
- LOG.debug("RELEASE_IP: %s, %s ", out, err)
diff --git a/nova/tests/test_vlan_network.py b/nova/tests/test_vlan_network.py
new file mode 100644
index 000000000..be39313bb
--- /dev/null
+++ b/nova/tests/test_vlan_network.py
@@ -0,0 +1,373 @@
+# 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 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
+
+FLAGS = flags.FLAGS
+LOG = logging.getLogger('nova.tests.network')
+
+
+class VlanNetworkTestCase(test.TestCase):
+ """Test cases for network code"""
+ def setUp(self):
+ super(VlanNetworkTestCase, 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(VlanNetworkTestCase, self).tearDown()
+
+ def run(self, result=None):
+ if(FLAGS.network_manager == 'nova.network.manager.VlanManager'):
+ super(VlanNetworkTestCase, self).run(result)
+
+ 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 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 = "%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}
+ (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 = "%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}
+ (out, err) = utils.execute(cmd, addl_env=env)
+ LOG.debug("RELEASE_IP: %s, %s ", out, err)
--
cgit
From a74bf3381ada34f35c43d6f307fbae9abecfb255 Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Tue, 8 Mar 2011 10:30:48 -0800
Subject: abstracted network code in the base class for flat and vlan
---
nova/network/manager.py | 8 +-
nova/tests/network/__init__.py | 47 +++++++++
nova/tests/network/base.py | 154 ++++++++++++++++++++++++++++++
nova/tests/test_flat_network.py | 147 ++++------------------------
nova/tests/test_vlan_network.py | 205 ++++++++--------------------------------
5 files changed, 259 insertions(+), 302 deletions(-)
create mode 100644 nova/tests/network/__init__.py
create mode 100644 nova/tests/network/base.py
diff --git a/nova/network/manager.py b/nova/network/manager.py
index 686ab9732..670ff55fd 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -404,9 +404,11 @@ class FlatManager(NetworkManager):
net = {}
net['injected'] = FLAGS.flat_injected
net['dns'] = FLAGS.flat_network_dns
- if(FLAGS.use_ipv6):
- net['gateway_v6'] = \
- utils.get_my_linklocal(FLAGS.flat_network_bridge)
+ if not FLAGS.fake_network:
+ if(FLAGS.use_ipv6):
+ net['gateway_v6'] = \
+ utils.get_my_linklocal(
+ FLAGS.flat_network_bridge)
self.db.network_update(context, network_id, net)
def allocate_floating_ip(self, context, project_id):
diff --git a/nova/tests/network/__init__.py b/nova/tests/network/__init__.py
new file mode 100644
index 000000000..e51065983
--- /dev/null
+++ b/nova/tests/network/__init__.py
@@ -0,0 +1,47 @@
+import os
+
+from nova import context
+from nova import db
+from nova import flags
+from nova import log as logging
+from nova import utils
+
+FLAGS = flags.FLAGS
+LOG = logging.getLogger('nova.tests.network')
+
+
+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 = "%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}
+ (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 = "%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}
+ (out, err) = utils.execute(cmd, addl_env=env)
+ LOG.debug("RELEASE_IP: %s, %s ", out, err)
diff --git a/nova/tests/network/base.py b/nova/tests/network/base.py
new file mode 100644
index 000000000..2dd8178ff
--- /dev/null
+++ b/nova/tests/network/base.py
@@ -0,0 +1,154 @@
+# 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.
+"""
+Base class of Unit Tests for all network models
+"""
+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
+
+FLAGS = flags.FLAGS
+LOG = logging.getLogger('nova.tests.network')
+
+
+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 _is_allocated_in_project(self, address, project_id):
+ """Returns true if address is in specified project"""
+ project_net = db.network_get_by_bridge(context.get_admin_context(),
+ FLAGS.flat_network_bridge)
+ 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 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_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)
diff --git a/nova/tests/test_flat_network.py b/nova/tests/test_flat_network.py
index 91a49920d..a9a934158 100644
--- a/nova/tests/test_flat_network.py
+++ b/nova/tests/test_flat_network.py
@@ -30,96 +30,15 @@ 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(test.TestCase):
+class FlatNetworkTestCase(base.NetworkTestCase):
"""Test cases for network code"""
- def setUp(self):
- super(FlatNetworkTestCase, 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(5):
- 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(FlatNetworkTestCase, 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 allocate a public ip"""
# TODO(vish): better way of adding floating ips
@@ -167,28 +86,34 @@ class FlatNetworkTestCase(test.TestCase):
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))
+ 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(is_allocated_in_project(address, self.projects[0].id))
+ 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(is_allocated_in_project(address, self.projects[0].id))
- self.assertTrue(is_allocated_in_project(address2, self.projects[1].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(is_allocated_in_project(address, self.projects[0].id))
+ self.assertFalse(self._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[0].id))
+ self.assertTrue(self._is_allocated_in_project(address2,
+ self.projects[0].id))
self._deallocate_address(1, address2)
- self.assertFalse(is_allocated_in_project(address2,
+ self.assertFalse(self._is_allocated_in_project(address2,
self.projects[1].id))
def test_ips_are_reused(self):
@@ -201,29 +126,6 @@ class FlatNetworkTestCase(test.TestCase):
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
-
- 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.
"""
@@ -257,20 +159,3 @@ class FlatNetworkTestCase(test.TestCase):
def run(self, result=None):
if(FLAGS.network_manager == 'nova.network.manager.FlatManager'):
super(FlatNetworkTestCase, self).run(result)
-
-
-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)
- project_net = db.network_get_by_bridge(context.get_admin_context(),
- FLAGS.flat_network_bridge)
- 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))
diff --git a/nova/tests/test_vlan_network.py b/nova/tests/test_vlan_network.py
index be39313bb..f3478320b 100644
--- a/nova/tests/test_vlan_network.py
+++ b/nova/tests/test_vlan_network.py
@@ -29,100 +29,16 @@ 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(test.TestCase):
+class VlanNetworkTestCase(base.NetworkTestCase):
"""Test cases for network code"""
- def setUp(self):
- super(VlanNetworkTestCase, 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(VlanNetworkTestCase, self).tearDown()
-
- def run(self, result=None):
- if(FLAGS.network_manager == 'nova.network.manager.VlanManager'):
- super(VlanNetworkTestCase, self).run(result)
-
- 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
@@ -157,24 +73,30 @@ class VlanNetworkTestCase(test.TestCase):
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))
+ 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(is_allocated_in_project(address, self.projects[0].id))
+ self.assertTrue(self._is_allocated_in_project(address,
+ self.projects[0].id))
release_ip(address)
- self.assertFalse(is_allocated_in_project(address, self.projects[0].id))
+ 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(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))
+ 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)
@@ -182,14 +104,16 @@ class VlanNetworkTestCase(test.TestCase):
self._deallocate_address(0, address)
release_ip(address)
- self.assertFalse(is_allocated_in_project(address, self.projects[0].id))
+ self.assertFalse(self._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.assertTrue(self._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.assertFalse(self._is_allocated_in_project(address2,
self.projects[1].id))
def test_subnet_edge(self):
@@ -212,11 +136,11 @@ class VlanNetworkTestCase(test.TestCase):
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.assertFalse(self._is_allocated_in_project(address,
self.projects[0].id))
- self.assertFalse(is_allocated_in_project(address2,
+ self.assertFalse(self._is_allocated_in_project(address2,
self.projects[0].id))
- self.assertFalse(is_allocated_in_project(address3,
+ 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)
@@ -270,29 +194,6 @@ class VlanNetworkTestCase(test.TestCase):
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.
"""
@@ -325,49 +226,17 @@ class VlanNetworkTestCase(test.TestCase):
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 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 = "%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}
- (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 = "%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}
- (out, err) = utils.execute(cmd, addl_env=env)
- LOG.debug("RELEASE_IP: %s, %s ", out, err)
+ def run(self, result=None):
+ if(FLAGS.network_manager == 'nova.network.manager.VlanManager'):
+ super(VlanNetworkTestCase, self).run(result)
--
cgit
From 80a6dc5504378ae3d96829d96c02f50b9daa3029 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 9 Mar 2011 13:46:05 -0600
Subject: stuff
---
nova/compute/api.py | 15 +++++++++++++--
nova/compute/manager.py | 17 ++++++++++++++---
2 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 33d25fc4b..93f0a12c1 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -456,12 +456,23 @@ class API(base.Base):
self.db.instance_update(context, instance_id,
{'host': migration_ref['dest_compute'], })
- def resize(self, context, instance_id, flavor):
+ def resize(self, context, instance_id, flavor_id):
"""Resize a running instance."""
+ instance = self.db.instance_get(context, instance_id)
+ current_instance_type = self.db.instance_type_get_by_flavor_id(
+ context, instance['flavor_id'])
+ new_instance_type = self.db.instance_type_get_by_flavor_id(
+ context, flavor_id)
+
+ if current_instance_type.memory_mb > new_instance_typ.memory_mb:
+ raise exception.ApiError(_("Invalid flavor: cannot downsize"
+ "instances"))
+
self._cast_scheduler_message(context,
{"method": "prep_resize",
"args": {"topic": FLAGS.compute_topic,
- "instance_id": instance_id, }},)
+ "instance_id": instance_id,
+ "instance_type": new_instance_type}})
def pause(self, context, instance_id):
"""Pause the given instance."""
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index b3e864154..f85ad91df 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -447,7 +447,7 @@ class ComputeManager(manager.Manager):
@exception.wrap_exception
@checks_instance_lock
- def prep_resize(self, context, instance_id):
+ def prep_resize(self, context, instance_id, flavor_id):
"""Initiates the process of moving a running instance to another
host, possibly changing the RAM and disk size in the process"""
context = context.elevated()
@@ -456,12 +456,17 @@ class ComputeManager(manager.Manager):
raise exception.Error(_(
'Migration error: destination same as source!'))
+ instance_type = self.db.instance_type_get_by_flavor_id(context,
+ flavor_id)
migration_ref = self.db.migration_create(context,
{'instance_id': instance_id,
'source_compute': instance_ref['host'],
'dest_compute': FLAGS.host,
'dest_host': self.driver.get_host_ip_addr(),
+ 'old_flavor': instance_type['flavor_id'],
+ 'new_flavor': flavor_id,
'status': 'pre-migrating'})
+
LOG.audit(_('instance %s: migrating to '), instance_id,
context=context)
topic = self.db.queue_get_for(context, FLAGS.compute_topic,
@@ -487,8 +492,14 @@ class ComputeManager(manager.Manager):
self.db.migration_update(context, migration_id,
{'status': 'post-migrating', })
- #TODO(mdietz): This is where we would update the VM record
- #after resizing
+ #TODO(mdietz): apply the rest of the instance_type attributes going
+ #after they're supported
+ self.db.instance_update(context, instance_ref,
+ dict(memory_mb=instance_type['memory_mb'],
+ vcpus=instance_type['vcpus'],
+ local_gb=instance_type['local_gb']))
+ self.driver.resize_instance(context, instance_ref)
+
service = self.db.service_get_by_host_and_topic(context,
migration_ref['dest_compute'], FLAGS.compute_topic)
topic = self.db.queue_get_for(context, FLAGS.compute_topic,
--
cgit
From 25bbe2afb0be3c79264376dd6a11e2bc97847702 Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Thu, 10 Mar 2011 11:17:34 -0800
Subject: fixed formatting and redundant imports
---
nova/api/ec2/cloud.py | 6 +++---
.../db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py | 1 -
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 6ed6186be..c6309f03c 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -701,9 +701,9 @@ class CloudController(object):
fixed = instance['fixed_ip']
floating_addr = fixed['floating_ips'][0]['address']
if instance['fixed_ip']['network'] and 'use_v6' in kwargs:
- i['dnsNameV6'] = utils.to_global_ipv6(
- instance['fixed_ip']['network']['cidr_v6'],
- instance['mac_address'])
+ i['dnsNameV6'] = utils.to_global_ipv6(
+ instance['fixed_ip']['network']['cidr_v6'],
+ instance['mac_address'])
i['privateDnsName'] = fixed_addr
i['publicDnsName'] = floating_addr
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py b/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
index d14f52af1..b8514c439 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/007_add_ipv6_flatmanager.py
@@ -12,7 +12,6 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
-from lib2to3.fixer_util import String
from sqlalchemy import *
from migrate import *
--
cgit
From 998975651ac2f2df7a3f8af16d62d197f451180f Mon Sep 17 00:00:00 2001
From: Justin Santa Barbara
Date: Thu, 10 Mar 2011 13:53:27 -0800
Subject: Test login. Uncovered bug732866
---
nova/tests/integrated/integrated_helpers.py | 182 ++++++++++++++++++++++++++++
nova/tests/integrated/test_login.py | 77 ++++++++++++
2 files changed, 259 insertions(+)
create mode 100644 nova/tests/integrated/integrated_helpers.py
create mode 100644 nova/tests/integrated/test_login.py
diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py
new file mode 100644
index 000000000..691ead6e1
--- /dev/null
+++ b/nova/tests/integrated/integrated_helpers.py
@@ -0,0 +1,182 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Justin Santa Barbara
+# 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.
+
+"""
+Provides common functionality for integrated unit tests
+"""
+
+import random
+import string
+
+from nova import exception
+from nova import flags
+from nova import service
+from nova import test # For the flags
+from nova.auth import manager
+from nova.exception import Error
+from nova.log import logging
+from nova.tests.integrated.api import client
+
+
+FLAGS = flags.FLAGS
+
+LOG = logging.getLogger('nova.tests.integrated')
+
+
+def generate_random_alphanumeric(length):
+ """Creates a random alphanumeric string of specified length"""
+ return ''.join(random.choice(string.ascii_uppercase + string.digits)
+ for _x in range(length))
+
+
+def generate_random_numeric(length):
+ """Creates a random numeric string of specified length"""
+ return ''.join(random.choice(string.digits)
+ for _x in range(length))
+
+
+def generate_new_element(items, prefix, numeric=False):
+ """Creates a random string with prefix, that is not in 'items' list"""
+ while True:
+ if numeric:
+ candidate = prefix + generate_random_numeric(8)
+ else:
+ candidate = prefix + generate_random_alphanumeric(8)
+ if not candidate in items:
+ return candidate
+ print "Random collision on %s" % candidate
+
+
+class TestUser(object):
+ def __init__(self, name, secret, auth_url):
+ self.name = name
+ self.secret = secret
+ self.auth_url = auth_url
+
+ if not auth_url:
+ raise exception.Error("auth_url is required")
+ self.openstack_api = client.TestOpenStackClient(self.name,
+ self.secret,
+ self.auth_url)
+
+
+class IntegratedUnitTestContext(object):
+ __INSTANCE = None
+
+ def __init__(self):
+ self.auth_manager = manager.AuthManager()
+
+ self.wsgi_server = None
+ self.wsgi_apps = []
+ self.api_service = None
+
+ self.services = []
+ self.auth_url = None
+ self.project_name = None
+
+ self.setup()
+
+ def setup(self):
+ self._start_services()
+
+ self._create_test_user()
+
+ def _create_test_user(self):
+ self.test_user = self._create_unittest_user()
+
+ # No way to currently pass this through the OpenStack API
+ self.project_name = 'openstack'
+ self._configure_project(self.project_name, self.test_user)
+
+ def _start_services(self):
+ # WSGI shutdown broken :-(
+ if not self.api_service:
+ self._start_api_service()
+
+ def cleanup(self):
+ for service in self.services:
+ service.kill()
+ self.services = []
+ # TODO(justinsb): Shutdown WSGI & anything else we startup
+ # WSGI shutdown broken :-(
+ # self.wsgi_server.terminate()
+ # self.wsgi_server = None
+ self.test_user = None
+
+ def _create_unittest_user(self):
+ users = self.auth_manager.get_users()
+ user_names = [user.name for user in users]
+ auth_name = generate_new_element(user_names, 'unittest_user_')
+ auth_key = generate_random_alphanumeric(16)
+
+ # Right now there's a bug where auth_name and auth_key are reversed
+ auth_key = auth_name
+
+ self.auth_manager.create_user(auth_name, auth_name, auth_key, False)
+ return TestUser(auth_name, auth_key, self.auth_url)
+
+ def _configure_project(self, project_name, user):
+ projects = self.auth_manager.get_projects()
+ project_names = [project.name for project in projects]
+ if not project_name in project_names:
+ project = self.auth_manager.create_project(project_name,
+ user.name,
+ description=None,
+ member_users=None)
+ else:
+ self.auth_manager.add_to_project(user.name, project_name)
+
+ def _start_api_service(self):
+ api_service = service.ApiService.create()
+ api_service.start()
+
+ if not api_service:
+ raise Exception("API Service was None")
+
+ # WSGI shutdown broken :-(
+ #self.services.append(volume_service)
+ self.api_service = api_service
+
+ self.auth_url = 'http://localhost:8774/v1.0'
+
+ return api_service
+
+ # WSGI shutdown broken :-(
+ #@staticmethod
+ #def get():
+ # if not IntegratedUnitTestContext.__INSTANCE:
+ # IntegratedUnitTestContext.startup()
+ # #raise Error("Must call IntegratedUnitTestContext::startup")
+ # return IntegratedUnitTestContext.__INSTANCE
+
+ @staticmethod
+ def startup():
+ # Because WSGI shutdown is broken at the moment, we have to recycle
+ if IntegratedUnitTestContext.__INSTANCE:
+ #raise Error("Multiple calls to IntegratedUnitTestContext.startup")
+ IntegratedUnitTestContext.__INSTANCE.setup()
+ else:
+ IntegratedUnitTestContext.__INSTANCE = IntegratedUnitTestContext()
+ return IntegratedUnitTestContext.__INSTANCE
+
+ @staticmethod
+ def shutdown():
+ if not IntegratedUnitTestContext.__INSTANCE:
+ raise Error("Must call IntegratedUnitTestContext::startup")
+ IntegratedUnitTestContext.__INSTANCE.cleanup()
+ # WSGI shutdown broken :-(
+ #IntegratedUnitTestContext.__INSTANCE = None
diff --git a/nova/tests/integrated/test_login.py b/nova/tests/integrated/test_login.py
new file mode 100644
index 000000000..990dcaaf4
--- /dev/null
+++ b/nova/tests/integrated/test_login.py
@@ -0,0 +1,77 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Justin Santa Barbara
+# 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.
+
+import unittest
+
+from nova import flags
+from nova.log import logging
+from nova.tests.integrated import integrated_helpers
+from nova.tests.integrated.api import client
+
+LOG = logging.getLogger('nova.tests.integrated')
+
+FLAGS = flags.FLAGS
+FLAGS.verbose = True
+
+
+class LoginTest(unittest.TestCase):
+ def setUp(self):
+ super(LoginTest, self).setUp()
+ context = integrated_helpers.IntegratedUnitTestContext.startup()
+ self.user = context.test_user
+ self.api = self.user.openstack_api
+
+ def tearDown(self):
+ integrated_helpers.IntegratedUnitTestContext.shutdown()
+ super(LoginTest, self).tearDown()
+
+ def test_login(self):
+ """Simple check - we list flavors - so we know we're logged in"""
+ flavors = self.api.get_flavors()
+ for flavor in flavors:
+ LOG.debug(_("flavor: %s") % flavor)
+
+ def test_bad_login_password(self):
+ """Test that I get a 401 with a bad username"""
+ bad_credentials_api = client.TestOpenStackClient(self.user.name,
+ "notso_password",
+ self.user.auth_url)
+
+ self.assertRaises(client.OpenstackApiAuthenticationException,
+ bad_credentials_api.get_flavors)
+
+ def test_bad_login_username(self):
+ """Test that I get a 401 with a bad password"""
+ bad_credentials_api = client.TestOpenStackClient("notso_username",
+ self.user.secret,
+ self.user.auth_url)
+
+ self.assertRaises(client.OpenstackApiAuthenticationException,
+ bad_credentials_api.get_flavors)
+
+
+ def test_bad_login_both_bad(self):
+ """Test that I get a 401 with both bad username and bad password"""
+ bad_credentials_api = client.TestOpenStackClient("notso_username",
+ "notso_password",
+ self.user.auth_url)
+
+ self.assertRaises(client.OpenstackApiAuthenticationException,
+ bad_credentials_api.get_flavors)
+
+if __name__ == "__main__":
+ unittest.main()
--
cgit
From 4a9f4f4eef4e6fd6ab84ec2e03437144f9ab62f8 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Thu, 10 Mar 2011 16:07:50 -0600
Subject: More resize
---
nova/compute/manager.py | 68 ++++++++++++++++++++++++++++++-----------------
nova/virt/xenapi/vmops.py | 13 +++++++--
nova/virt/xenapi_conn.py | 9 ++++---
3 files changed, 60 insertions(+), 30 deletions(-)
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 399356a13..f73e81345 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -429,21 +429,37 @@ class ComputeManager(manager.Manager):
instance_ref = self.db.instance_get(context, instance_id)
migration_ref = self.db.migration_get(context, migration_id)
- #TODO(mdietz): we may want to split these into separate methods.
- if migration_ref['source_compute'] == FLAGS.host:
- self.driver._start(instance_ref)
- self.db.migration_update(context, migration_id,
- {'status': 'reverted'})
- else:
- self.driver.destroy(instance_ref)
- topic = self.db.queue_get_for(context, FLAGS.compute_topic,
- instance_ref['host'])
- rpc.cast(context, topic,
- {'method': 'revert_resize',
- 'args': {
- 'migration_id': migration_ref['id'],
- 'instance_id': instance_id, },
- })
+ self.driver.destroy(instance_ref)
+ topic = self.db.queue_get_for(context, FLAGS.compute_topic,
+ instance_ref['host'])
+ rpc.cast(context, topic,
+ {'method': 'finish_revert_resize',
+ 'args': {
+ 'migration_id': migration_ref['id'],
+ 'instance_id': instance_id, },
+ })
+
+ @exception.wrap_exception
+ @checks_instance_lock
+ def finish_revert_resize(self, context, instance_id, migration_id):
+ """Finishes the second half of reverting a resize, powering back on
+ the source instance and reverting the resized attributes in the
+ database"""
+ instance_ref = self.db.instance_get(context, instance_id)
+ migration_ref = self.db.migration_get(context, migration_id)
+ instance_type = self.db.instance_type_get_by_flavor_id(context,
+ migration_ref['old_flavor_id'])
+
+ #Just roll back the record. There's no need to resize down since
+ #the 'old' VM already has the preferred attributes
+ self.db.instance_update(context,
+ dict(memory_mb=instance_type['memory_mb'],
+ vcpus=instance_type['vcpus'],
+ local_gb=instance_type['local_gb']))
+
+ self.driver._start(instance_ref)
+ self.db.migration_update(context, migration_id,
+ {'status': 'reverted'})
@exception.wrap_exception
@checks_instance_lock
@@ -463,8 +479,8 @@ class ComputeManager(manager.Manager):
'source_compute': instance_ref['host'],
'dest_compute': FLAGS.host,
'dest_host': self.driver.get_host_ip_addr(),
- 'old_flavor': instance_type['flavor_id'],
- 'new_flavor': flavor_id,
+ 'old_flavor_id': instance_type['flavor_id'],
+ 'new_flavor_id': flavor_id,
'status': 'pre-migrating'})
LOG.audit(_('instance %s: migrating to '), instance_id,
@@ -492,13 +508,7 @@ class ComputeManager(manager.Manager):
self.db.migration_update(context, migration_id,
{'status': 'post-migrating', })
- #TODO(mdietz): apply the rest of the instance_type attributes going
- #after they're supported
- self.db.instance_update(context, instance_ref,
- dict(memory_mb=instance_type['memory_mb'],
- vcpus=instance_type['vcpus'],
- local_gb=instance_type['local_gb']))
- self.driver.resize_instance(context, instance_ref)
+
service = self.db.service_get_by_host_and_topic(context,
migration_ref['dest_compute'], FLAGS.compute_topic)
@@ -520,7 +530,17 @@ class ComputeManager(manager.Manager):
migration_ref = self.db.migration_get(context, migration_id)
instance_ref = self.db.instance_get(context,
migration_ref['instance_id'])
+
+ #TODO(mdietz): apply the rest of the instance_type attributes going
+ #after they're supported
+ instance_type = self.db.instance_type_get_by_flavor_id(context,
+ migration_ref['new_flavor_id'])
+ self.db.instance_update(context, instance_ref,
+ dict(memory_mb=instance_type['memory_mb'],
+ vcpus=instance_type['vcpus'],
+ local_gb=instance_type['local_gb']))
+ self.driver.resize_instance(instance_ref, disk_info)
self.driver.finish_resize(instance_ref, disk_info)
self.db.migration_update(context, migration_id,
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 562ecd4d5..9e0bd6a75 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -365,9 +365,18 @@ class VMOps(object):
return new_cow_uuid
- def resize(self, instance, flavor):
+ def resize_instance(self, instance, vdi_uuid):
"""Resize a running instance by changing it's RAM and disk size """
- raise NotImplementedError()
+ vm_ref = VMHelper.lookup(self._session, instance.name)
+ vdi_ref, vm_vdi_rec = \
+ VMHelper.get_vdi_for_vm_safely(self._session, vm_ref)
+ new_disk_size = instance.local_gb
+
+ #TODO(mdietz): this will need to be adjusted for swap later
+ task = self._session.call_xenapi('VDI.resize_online', vdi_ref,
+ new_disk_size)
+ vm_ref = VMHelper.lookup(self._session, instance.name)
+ self._session.wait_for_task(task, instance.id)
def reboot(self, instance):
"""Reboot VM instance"""
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index b63a5f8c3..92b262479 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -158,6 +158,11 @@ class XenAPIConnection(object):
"""Create VM instance"""
self._vmops.spawn(instance)
+ def resize_instance(self, instance, disk_info):
+ """Resizes instance attributes such as RAM and disk space to the
+ attributes specified by the record"""
+ self._vmops.resize_instance(instance, disk_info['cow'])
+
def finish_resize(self, instance, disk_info):
"""Completes a resize, turning on the migrated instance"""
vdi_uuid = self._vmops.attach_disk(instance, disk_info['base_copy'],
@@ -168,10 +173,6 @@ class XenAPIConnection(object):
""" Create snapshot from a running VM instance """
self._vmops.snapshot(instance, image_id)
- def resize(self, instance, flavor):
- """Resize a VM instance"""
- raise NotImplementedError()
-
def reboot(self, instance):
"""Reboot VM instance"""
self._vmops.reboot(instance)
--
cgit
From 3d6430ecd114daa21c72c3d215daaa94f0e87e62 Mon Sep 17 00:00:00 2001
From: Justin Santa Barbara
Date: Thu, 10 Mar 2011 14:12:41 -0800
Subject: Re-removed the code that was deleted upstream but somehow didn't get
merged in. Bizarre!
---
nova/tests/integrated/api/client.py | 21 ---------------------
1 file changed, 21 deletions(-)
diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py
index 0ce480ae7..da8d87e07 100644
--- a/nova/tests/integrated/api/client.py
+++ b/nova/tests/integrated/api/client.py
@@ -172,27 +172,6 @@ class TestOpenStackClient(object):
kwargs.setdefault('check_response_status', [200, 202])
return self.api_request(relative_uri, **kwargs)
- def get_keys_detail(self):
- return self.api_get('/keys/detail')['keys']
-
- def post_key(self, key):
- return self.api_post('/keys', key)['key']
-
- def delete_key(self, key_id):
- return self.api_delete('/keys/%s' % key_id)
-
- def get_volume(self, volume_id):
- return self.api_get('/volumes/%s' % volume_id)['volume']
-
- def get_volumes_detail(self):
- return self.api_get('/volumes/detail')['volumes']
-
- def post_volume(self, volume):
- return self.api_post('/volumes', volume)['volume']
-
- def delete_volume(self, volume_id):
- return self.api_delete('/volumes/%s' % volume_id)
-
def get_server(self, server_id):
return self.api_get('/servers/%s' % server_id)['server']
--
cgit
From 29bc4f5074ca3ada98a25a745077b998b4c5509c Mon Sep 17 00:00:00 2001
From: Justin Santa Barbara
Date: Thu, 10 Mar 2011 14:14:01 -0800
Subject: Pep8 / Style
---
nova/tests/integrated/test_login.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/nova/tests/integrated/test_login.py b/nova/tests/integrated/test_login.py
index 990dcaaf4..e362f92d6 100644
--- a/nova/tests/integrated/test_login.py
+++ b/nova/tests/integrated/test_login.py
@@ -22,6 +22,7 @@ from nova.log import logging
from nova.tests.integrated import integrated_helpers
from nova.tests.integrated.api import client
+
LOG = logging.getLogger('nova.tests.integrated')
FLAGS = flags.FLAGS
@@ -63,7 +64,6 @@ class LoginTest(unittest.TestCase):
self.assertRaises(client.OpenstackApiAuthenticationException,
bad_credentials_api.get_flavors)
-
def test_bad_login_both_bad(self):
"""Test that I get a 401 with both bad username and bad password"""
bad_credentials_api = client.TestOpenStackClient("notso_username",
--
cgit
From 0d3e950ed4b0c8abbd619d4ac8724b4c3ce45bf1 Mon Sep 17 00:00:00 2001
From: Justin Santa Barbara
Date: Thu, 10 Mar 2011 14:21:36 -0800
Subject: Document known bug numbers by the code which is degraded until the
bugs are fixed
---
nova/tests/integrated/api/client.py | 1 +
nova/tests/integrated/integrated_helpers.py | 6 ++++++
2 files changed, 7 insertions(+)
diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py
index da8d87e07..6fba2930a 100644
--- a/nova/tests/integrated/api/client.py
+++ b/nova/tests/integrated/api/client.py
@@ -109,6 +109,7 @@ class TestOpenStackClient(object):
LOG.debug(_("%(auth_uri)s => code %(http_status)s") % locals())
# Until bug732866 is fixed, we can't check this properly...
+ # bug732866
#if http_status == 401:
if http_status != 204:
raise OpenstackApiAuthenticationException(response=response)
diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py
index 691ead6e1..47093636e 100644
--- a/nova/tests/integrated/integrated_helpers.py
+++ b/nova/tests/integrated/integrated_helpers.py
@@ -104,6 +104,7 @@ class IntegratedUnitTestContext(object):
def _start_services(self):
# WSGI shutdown broken :-(
+ # bug731668
if not self.api_service:
self._start_api_service()
@@ -112,6 +113,7 @@ class IntegratedUnitTestContext(object):
service.kill()
self.services = []
# TODO(justinsb): Shutdown WSGI & anything else we startup
+ # bug731668
# WSGI shutdown broken :-(
# self.wsgi_server.terminate()
# self.wsgi_server = None
@@ -124,6 +126,7 @@ class IntegratedUnitTestContext(object):
auth_key = generate_random_alphanumeric(16)
# Right now there's a bug where auth_name and auth_key are reversed
+ # bug732907
auth_key = auth_name
self.auth_manager.create_user(auth_name, auth_name, auth_key, False)
@@ -156,6 +159,7 @@ class IntegratedUnitTestContext(object):
return api_service
# WSGI shutdown broken :-(
+ # bug731668
#@staticmethod
#def get():
# if not IntegratedUnitTestContext.__INSTANCE:
@@ -166,6 +170,7 @@ class IntegratedUnitTestContext(object):
@staticmethod
def startup():
# Because WSGI shutdown is broken at the moment, we have to recycle
+ # bug731668
if IntegratedUnitTestContext.__INSTANCE:
#raise Error("Multiple calls to IntegratedUnitTestContext.startup")
IntegratedUnitTestContext.__INSTANCE.setup()
@@ -179,4 +184,5 @@ class IntegratedUnitTestContext(object):
raise Error("Must call IntegratedUnitTestContext::startup")
IntegratedUnitTestContext.__INSTANCE.cleanup()
# WSGI shutdown broken :-(
+ # bug731668
#IntegratedUnitTestContext.__INSTANCE = None
--
cgit
From e891e48b63065a7218627289a908aece0f6a3730 Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Fri, 11 Mar 2011 10:31:08 -0800
Subject: Made changes to xs-ipv6 code impacted because of addition of
flatmanger ipv6 support
---
nova/virt/xenapi/vmops.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 9ac83efb0..52d2652f9 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -617,9 +617,10 @@ class VMOps(object):
def ip6_dict(ip6):
return {
- "ip": ip6.addressV6,
- "netmask": ip6.netmaskV6,
- "gateway": ip6.gatewayV6,
+ "ip": utils.to_global_ipv6(network['cidr_v6'],
+ instance['mac_address']),
+ "netmask": network['netmask_v6'],
+ "gateway": network['gateway_v6'],
"enabled": "1"}
mac_id = instance.mac_address.replace(':', '')
--
cgit
From 6cd90a95d632d45d1c906d412e3240f730e88b95 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Fri, 11 Mar 2011 15:35:55 -0600
Subject: New migration
---
.../versions/010_add_flavors_to_migrations.py | 44 ++++++++++++++++++++++
nova/db/sqlalchemy/models.py | 2 +
nova/tests/test_compute.py | 2 -
3 files changed, 46 insertions(+), 2 deletions(-)
create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/010_add_flavors_to_migrations.py
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/010_add_flavors_to_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/010_add_flavors_to_migrations.py
new file mode 100644
index 000000000..412caedd0
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/010_add_flavors_to_migrations.py
@@ -0,0 +1,44 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2010 OpenStack LLC.
+# 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.from sqlalchemy import *
+
+from sqlalchemy import *
+from migrate import *
+
+from nova import log as logging
+
+
+meta = MetaData()
+
+migrations = Table('migrations', meta,
+ Column('id', Integer(), primary_key=True, nullable=False),
+ )
+
+#
+# Tables to alter
+#
+#
+
+old_flavor_id = Column('old_flavor_id', Integer())
+new_flavor_id = Column('new_flavor_id', Integer())
+
+
+def upgrade(migrate_engine):
+ # Upgrade operations go here. Don't create your own engine;
+ # bind migrate_engine to your metadata
+ meta.bind = migrate_engine
+ migrations.create_column(old_flavor_id)
+ migrations.create_column(new_flavor_id)
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 6ef284e65..73cd8a4cc 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -396,6 +396,8 @@ class Migration(BASE, NovaBase):
source_compute = Column(String(255))
dest_compute = Column(String(255))
dest_host = Column(String(255))
+ old_flavor_id = Column(Integer())
+ new_flavor_id = Column(Integer())
instance_id = Column(Integer, ForeignKey('instances.id'), nullable=True)
#TODO(_cerberus_): enum
status = Column(String(255))
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index 643b2e93a..3d25a8997 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -299,5 +299,3 @@ class ComputeTestCase(test.TestCase):
self.assertRaises(exception.Error, self.compute.prep_resize,
self.context, instance_id)
self.compute.terminate_instance(self.context, instance_id)
- type = instance_types.get_by_flavor_id("1")
- self.assertEqual(type, 'm1.tiny')
--
cgit
From bacce305a99dff77aa0e24c64cb937514e368ec1 Mon Sep 17 00:00:00 2001
From: Anne Gentle
Date: Fri, 11 Mar 2011 17:13:56 -0600
Subject: Adding a sidebar element to the nova.openstack.org site to point
people to additional versions of the site.
---
doc/source/_static/tweaks.css | 147 ++++++++++++++++++++++++++++++++++++++++++
doc/source/_theme/layout.html | 11 +++-
2 files changed, 157 insertions(+), 1 deletion(-)
diff --git a/doc/source/_static/tweaks.css b/doc/source/_static/tweaks.css
index 1a18dbac6..7c57c8f35 100644
--- a/doc/source/_static/tweaks.css
+++ b/doc/source/_static/tweaks.css
@@ -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;
+}
+
diff --git a/doc/source/_theme/layout.html b/doc/source/_theme/layout.html
index e3eb54b71..958c512e4 100644
--- a/doc/source/_theme/layout.html
+++ b/doc/source/_theme/layout.html
@@ -71,12 +71,21 @@
+
+
+ Psst... hey. You're reading the latest content, but it might be out of sync with code. You can read Nova 2011.1 docs or all OpenStack docs too.
+
+
{%- endif %}
{%- if pagename == "index" %}
- {{ _('Twitter Feed') }}
+
+
+ {{ _('Twitter Feed') }}
{%- endif %}
+
+
{%- endblock %}
--
cgit
From 1c4afe23157233b7081872ccbc6ea5fa1ff0015a Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Fri, 11 Mar 2011 17:30:51 -0600
Subject: Some unit tests
---
nova/compute/api.py | 9 ++++++---
nova/tests/test_compute.py | 24 ++++++++++++++++++++++++
2 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 1393c01d5..0dc2bb3d3 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -460,10 +460,13 @@ class API(base.Base):
def resize(self, context, instance_id, flavor_id):
"""Resize a running instance."""
instance = self.db.instance_get(context, instance_id)
- current_instance_type = self.db.instance_type_get_by_flavor_id(
- context, instance['flavor_id'])
+ current_instance_type = self.db.instance_type_get_by_name(
+ context, instance['instance_type'])
+
new_instance_type = self.db.instance_type_get_by_flavor_id(
- context, flavor_id)
+ context, flavor_id)
+ if not new_instance_type:
+ raise exception.ApiError(_("Requested flavor does not exist"))
if current_instance_type.memory_mb > new_instance_typ.memory_mb:
raise exception.ApiError(_("Invalid flavor: cannot downsize"
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index 3d25a8997..c53284216 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -287,6 +287,30 @@ class ComputeTestCase(test.TestCase):
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.ApiError, self.compute_api.resize,
+ context, instance_id, 200)
+
+ self.compute.terminate_instance(context, instance_id)
+
+ def test_resize_down_fails(self):
+ """Ensure invalid flavors raise"""
+ instance_id = self._create_instance()
+ context = self.context.elevated()
+ self.compute.run_instance(self.context, instance_id)
+ db.instance_update(self.context, instance_id,
+ {'instance_type': 'm1.large'})
+
+ 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')
--
cgit
From d45947d83fa22f98b0889d269d447fabaa764a3c Mon Sep 17 00:00:00 2001
From: Anne Gentle
Date: Mon, 14 Mar 2011 09:48:58 -0500
Subject: Fixes link to 2011.1 instad of just to trunk docs
---
doc/source/_theme/layout.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc/source/_theme/layout.html b/doc/source/_theme/layout.html
index 958c512e4..0a37a7943 100644
--- a/doc/source/_theme/layout.html
+++ b/doc/source/_theme/layout.html
@@ -73,7 +73,7 @@
- Psst... hey. You're reading the latest content, but it might be out of sync with code. You can read Nova 2011.1 docs or all OpenStack docs too.
+ Psst... hey. You're reading the latest content, but it might be out of sync with code. You can read Nova 2011.1 docs or all OpenStack docs too.
{%- endif %}
--
cgit
From af5e752e8eb21d0e9192d9acd9e75586bdec3685 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Mon, 14 Mar 2011 11:55:55 -0500
Subject: Compute test
---
nova/tests/test_compute.py | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index c53284216..47e0f66fb 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -76,6 +76,20 @@ 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"""
+ 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(self.context, inst)['id']
+
def _create_group(self):
values = {'name': 'testgroup',
'description': 'testgroup',
@@ -301,10 +315,17 @@ class ComputeTestCase(test.TestCase):
def test_resize_down_fails(self):
"""Ensure invalid flavors raise"""
instance_id = self._create_instance()
+
+ small_inst_type_id = self._create_instance_type(dict(flavorid=1,
+ memory_mb=512))
+ big_inst_type_id = self._create_instance_type(dict(flavorid=2,
+ name='m1.wowzers', memory_mb=8192))
+
context = self.context.elevated()
self.compute.run_instance(self.context, instance_id)
- db.instance_update(self.context, instance_id,
- {'instance_type': 'm1.large'})
+ db.instance_update(self.context, instance_id,
+ {'instance_type': 'm1.wowzers',
+ 'memory_gb': 8192})
self.assertRaises(exception.ApiError, self.compute_api.resize,
context, instance_id, 1)
--
cgit
From 1f763599d733de1ded1074dee828237256eda01d Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Mon, 14 Mar 2011 16:59:46 +0000
Subject: Migration moved again
---
.../versions/010_add_flavors_to_migrations.py | 44 ----------------------
.../versions/011_add_flavors_to_migrations.py | 44 ++++++++++++++++++++++
2 files changed, 44 insertions(+), 44 deletions(-)
delete mode 100644 nova/db/sqlalchemy/migrate_repo/versions/010_add_flavors_to_migrations.py
create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/011_add_flavors_to_migrations.py
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/010_add_flavors_to_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/010_add_flavors_to_migrations.py
deleted file mode 100644
index 412caedd0..000000000
--- a/nova/db/sqlalchemy/migrate_repo/versions/010_add_flavors_to_migrations.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2010 OpenStack LLC.
-# 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.from sqlalchemy import *
-
-from sqlalchemy import *
-from migrate import *
-
-from nova import log as logging
-
-
-meta = MetaData()
-
-migrations = Table('migrations', meta,
- Column('id', Integer(), primary_key=True, nullable=False),
- )
-
-#
-# Tables to alter
-#
-#
-
-old_flavor_id = Column('old_flavor_id', Integer())
-new_flavor_id = Column('new_flavor_id', Integer())
-
-
-def upgrade(migrate_engine):
- # Upgrade operations go here. Don't create your own engine;
- # bind migrate_engine to your metadata
- meta.bind = migrate_engine
- migrations.create_column(old_flavor_id)
- migrations.create_column(new_flavor_id)
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/011_add_flavors_to_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/011_add_flavors_to_migrations.py
new file mode 100644
index 000000000..412caedd0
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/011_add_flavors_to_migrations.py
@@ -0,0 +1,44 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2010 OpenStack LLC.
+# 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.from sqlalchemy import *
+
+from sqlalchemy import *
+from migrate import *
+
+from nova import log as logging
+
+
+meta = MetaData()
+
+migrations = Table('migrations', meta,
+ Column('id', Integer(), primary_key=True, nullable=False),
+ )
+
+#
+# Tables to alter
+#
+#
+
+old_flavor_id = Column('old_flavor_id', Integer())
+new_flavor_id = Column('new_flavor_id', Integer())
+
+
+def upgrade(migrate_engine):
+ # Upgrade operations go here. Don't create your own engine;
+ # bind migrate_engine to your metadata
+ meta.bind = migrate_engine
+ migrations.create_column(old_flavor_id)
+ migrations.create_column(new_flavor_id)
--
cgit
From 1ebae577150ce64d81d102c2e162acfe5a72528b Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Mon, 14 Mar 2011 12:07:27 -0500
Subject: Test changes
---
nova/compute/api.py | 2 +-
nova/tests/test_compute.py | 15 ++++++++++++---
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 3920f2af8..9d238c7d0 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -482,7 +482,7 @@ class API(base.Base):
{"method": "prep_resize",
"args": {"topic": FLAGS.compute_topic,
"instance_id": instance_id,
- "instance_type": new_instance_type}})
+ "flavor_id": flavor_id}})
def pause(self, context, instance_id):
"""Pause the given instance."""
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index 47e0f66fb..265421837 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -292,14 +292,18 @@ class ComputeTestCase(test.TestCase):
"""Ensure instance can be migrated/resized"""
instance_id = self._create_instance()
context = self.context.elevated()
+ small_inst_type_id = self._create_instance_type(dict(flavorid=1,
+ memory_mb=512, name='m1.small'))
+
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)
+ self.db.instance_type_purge(context, 'm1.small')
def test_resize_invalid_flavor_fails(self):
"""Ensure invalid flavors raise"""
@@ -317,7 +321,7 @@ class ComputeTestCase(test.TestCase):
instance_id = self._create_instance()
small_inst_type_id = self._create_instance_type(dict(flavorid=1,
- memory_mb=512))
+ memory_mb=512, name='m1.small'))
big_inst_type_id = self._create_instance_type(dict(flavorid=2,
name='m1.wowzers', memory_mb=8192))
@@ -331,6 +335,8 @@ class ComputeTestCase(test.TestCase):
context, instance_id, 1)
self.compute.terminate_instance(context, instance_id)
+ self.db.instance_type_purge(context, 'm1.small')
+ self.db.instance_type_purge(context, 'm1.wowzers')
def test_get_by_flavor_id(self):
type = instance_types.get_by_flavor_id(1)
@@ -340,7 +346,10 @@ class ComputeTestCase(test.TestCase):
"""Ensure instance fails to migrate when source and destination are
the same host"""
instance_id = self._create_instance()
+ small_inst_type_id = self._create_instance_type(dict(flavorid=1,
+ memory_mb=512, name='m1.small'))
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)
+ self.db.instance_type_purge(context, 'm1.small')
--
cgit
From e509cd70e7a2e8a430b2b24af50adcf1ad763564 Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Mon, 14 Mar 2011 17:24:39 +0000
Subject: Test fixes and some typos
---
nova/compute/api.py | 4 ++--
nova/compute/manager.py | 2 +-
nova/db/sqlalchemy/api.py | 4 ++--
nova/tests/test_compute.py | 23 +++++------------------
4 files changed, 10 insertions(+), 23 deletions(-)
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 9d238c7d0..0e9bf2424 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -468,13 +468,13 @@ class API(base.Base):
instance = self.db.instance_get(context, instance_id)
current_instance_type = self.db.instance_type_get_by_name(
context, instance['instance_type'])
-
+
new_instance_type = self.db.instance_type_get_by_flavor_id(
context, flavor_id)
if not new_instance_type:
raise exception.ApiError(_("Requested flavor does not exist"))
- if current_instance_type.memory_mb > new_instance_typ.memory_mb:
+ if current_instance_type['memory_mb'] > new_instance_type['memory_mb']:
raise exception.ApiError(_("Invalid flavor: cannot downsize"
"instances"))
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index f73e81345..57d175ec7 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -479,7 +479,7 @@ class ComputeManager(manager.Manager):
'source_compute': instance_ref['host'],
'dest_compute': FLAGS.host,
'dest_host': self.driver.get_host_ip_addr(),
- 'old_flavor_id': instance_type['flavor_id'],
+ 'old_flavor_id': instance_type['flavorid'],
'new_flavor_id': flavor_id,
'status': 'pre-migrating'})
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index 8b541757a..50267e21f 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -2185,8 +2185,8 @@ def instance_type_create(_context, values):
instance_type_ref = models.InstanceTypes()
instance_type_ref.update(values)
instance_type_ref.save()
- except:
- raise exception.DBError
+ except Exception, e:
+ raise exception.DBError(e)
return instance_type_ref
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index 265421837..a6defd644 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -78,6 +78,7 @@ class ComputeTestCase(test.TestCase):
def _create_instance_type(self, params={}):
"""Create a test instance"""
+ context = self.context.elevated()
inst = {}
inst['name'] = 'm1.small'
inst['memory_mb'] = '1024'
@@ -88,7 +89,7 @@ class ComputeTestCase(test.TestCase):
inst['rxtx_quota'] = 100
inst['rxtx_cap'] = 200
inst.update(params)
- return db.instance_type_create(self.context, inst)['id']
+ return db.instance_type_create(context, inst)['id']
def _create_group(self):
values = {'name': 'testgroup',
@@ -292,8 +293,6 @@ class ComputeTestCase(test.TestCase):
"""Ensure instance can be migrated/resized"""
instance_id = self._create_instance()
context = self.context.elevated()
- small_inst_type_id = self._create_instance_type(dict(flavorid=1,
- memory_mb=512, name='m1.small'))
self.compute.run_instance(self.context, instance_id)
db.instance_update(self.context, instance_id, {'host': 'foo'})
@@ -303,7 +302,6 @@ class ComputeTestCase(test.TestCase):
self.compute.resize_instance(context, instance_id,
migration_ref['id'])
self.compute.terminate_instance(context, instance_id)
- self.db.instance_type_purge(context, 'm1.small')
def test_resize_invalid_flavor_fails(self):
"""Ensure invalid flavors raise"""
@@ -311,32 +309,24 @@ class ComputeTestCase(test.TestCase):
context = self.context.elevated()
self.compute.run_instance(self.context, instance_id)
- self.assertRaises(exception.ApiError, self.compute_api.resize,
+ 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 invalid flavors raise"""
+ context = self.context.elevated()
instance_id = self._create_instance()
- small_inst_type_id = self._create_instance_type(dict(flavorid=1,
- memory_mb=512, name='m1.small'))
- big_inst_type_id = self._create_instance_type(dict(flavorid=2,
- name='m1.wowzers', memory_mb=8192))
-
- context = self.context.elevated()
self.compute.run_instance(self.context, instance_id)
db.instance_update(self.context, instance_id,
- {'instance_type': 'm1.wowzers',
- 'memory_gb': 8192})
+ {'instance_type': 'm1.xlarge'})
self.assertRaises(exception.ApiError, self.compute_api.resize,
context, instance_id, 1)
self.compute.terminate_instance(context, instance_id)
- self.db.instance_type_purge(context, 'm1.small')
- self.db.instance_type_purge(context, 'm1.wowzers')
def test_get_by_flavor_id(self):
type = instance_types.get_by_flavor_id(1)
@@ -346,10 +336,7 @@ class ComputeTestCase(test.TestCase):
"""Ensure instance fails to migrate when source and destination are
the same host"""
instance_id = self._create_instance()
- small_inst_type_id = self._create_instance_type(dict(flavorid=1,
- memory_mb=512, name='m1.small'))
self.compute.run_instance(self.context, instance_id)
self.assertRaises(exception.Error, self.compute.prep_resize,
self.context, instance_id, 1)
self.compute.terminate_instance(self.context, instance_id)
- self.db.instance_type_purge(context, 'm1.small')
--
cgit
From 06051ac8660983aae9ea6e72ab9bb1a31ceed9af Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Mon, 14 Mar 2011 11:08:00 -0700
Subject: Reverted unmodified files
---
tools/ajaxterm/README.txt | 240 +++++++++++++++++++++++-----------------------
1 file changed, 120 insertions(+), 120 deletions(-)
diff --git a/tools/ajaxterm/README.txt b/tools/ajaxterm/README.txt
index a649771c5..4b0ae99af 100644
--- a/tools/ajaxterm/README.txt
+++ b/tools/ajaxterm/README.txt
@@ -1,120 +1,120 @@
-= [http://antony.lesuisse.org/qweb/trac/wiki/AjaxTerm Ajaxterm] =
-
-Ajaxterm is a web based terminal. It was totally inspired and works almost
-exactly like http://anyterm.org/ except it's much easier to install (see
-comparaison with anyterm below).
-
-Ajaxterm written in python (and some AJAX javascript for client side) and depends only on python2.3 or better.[[BR]]
-Ajaxterm is '''very simple to install''' on Linux, MacOS X, FreeBSD, Solaris, cygwin and any Unix that runs python2.3.[[BR]]
-Ajaxterm was written by Antony Lesuisse (email: al AT udev.org), License Public Domain.
-
-Use the [/qweb/forum/viewforum.php?id=2 Forum], if you have any question or remark.
-
-== News ==
-
- * 2006-10-29: v0.10 allow space in login, cgi launch fix, redhat init
- * 2006-07-12: v0.9 change uid, daemon fix (Daniel Fischer)
- * 2006-07-04: v0.8 add login support to ssh (Sven Geggus), change max width to 256
- * 2006-05-31: v0.7 minor fixes, daemon option
- * 2006-05-23: v0.6 Applied debian and gentoo patches, renamed to Ajaxterm, default port 8022
-
-== Download and Install ==
-
- * Release: [/qweb/files/Ajaxterm-0.10.tar.gz Ajaxterm-0.10.tar.gz]
- * Browse src: [/qweb/trac/browser/trunk/ajaxterm/ ajaxterm/]
-
-To install Ajaxterm issue the following commands:
-{{{
-wget http://antony.lesuisse.org/qweb/files/Ajaxterm-0.10.tar.gz
-tar zxvf Ajaxterm-0.10.tar.gz
-cd Ajaxterm-0.10
-./ajaxterm.py
-}}}
-Then point your browser to this URL : http://localhost:8022/
-
-== Screenshot ==
-
-{{{
-#!html
-
-}}}
-
-== Documentation and Caveats ==
-
- * Ajaxterm only support latin1, if you use Ubuntu or any LANG==en_US.UTF-8 distribution don't forget to "unset LANG".
-
- * If run as root ajaxterm will run /bin/login, otherwise it will run ssh
- localhost. To use an other command use the -c option.
-
- * By default Ajaxterm only listen at 127.0.0.1:8022. For remote access, it is
- strongly recommended to use '''https SSL/TLS''', and that is simple to
- configure if you use the apache web server using mod_proxy.[[BR]][[BR]]
- Using ssl will also speed up ajaxterm (probably because of keepalive).[[BR]][[BR]]
- Here is an configuration example:
-
-{{{
- Listen 443
- NameVirtualHost *:443
-
-
- ServerName localhost
- SSLEngine On
- SSLCertificateKeyFile ssl/apache.pem
- SSLCertificateFile ssl/apache.pem
-
- ProxyRequests Off
-
- Order deny,allow
- Allow from all
-
- ProxyPass /ajaxterm/ http://localhost:8022/
- ProxyPassReverse /ajaxterm/ http://localhost:8022/
-
-}}}
-
- * Using GET HTTP request seems to speed up ajaxterm, just click on GET in the
- interface, but be warned that your keystrokes might be loggued (by apache or
- any proxy). I usually enable it after the login.
-
- * Ajaxterm commandline usage:
-
-{{{
-usage: ajaxterm.py [options]
-
-options:
- -h, --help show this help message and exit
- -pPORT, --port=PORT Set the TCP port (default: 8022)
- -cCMD, --command=CMD set the command (default: /bin/login or ssh localhost)
- -l, --log log requests to stderr (default: quiet mode)
- -d, --daemon run as daemon in the background
- -PPIDFILE, --pidfile=PIDFILE
- set the pidfile (default: /var/run/ajaxterm.pid)
- -iINDEX_FILE, --index=INDEX_FILE
- default index file (default: ajaxterm.html)
- -uUID, --uid=UID Set the daemon's user id
-}}}
-
- * Ajaxterm was first written as a demo for qweb (my web framework), but
- actually doesn't use many features of qweb.
-
- * Compared to anyterm:
- * There are no partial updates, ajaxterm updates either all the screen or
- nothing. That make the code simpler and I also think it's faster. HTTP
- replies are always gzencoded. When used in 80x25 mode, almost all of
- them are below the 1500 bytes (size of an ethernet frame) and we just
- replace the screen with the reply (no javascript string handling).
- * Ajaxterm polls the server for updates with an exponentially growing
- timeout when the screen hasn't changed. The timeout is also resetted as
- soon as a key is pressed. Anyterm blocks on a pending request and use a
- parallel connection for keypresses. The anyterm approch is better
- when there aren't any keypress.
-
- * Ajaxterm files are released in the Public Domain, (except [http://sarissa.sourceforge.net/doc/ sarissa*] which are LGPL).
-
-== TODO ==
-
- * insert mode ESC [ 4 h
- * change size x,y from gui (sending signal)
- * vt102 graphic codepage
- * use innerHTML or prototype instead of sarissa
-
+= [http://antony.lesuisse.org/qweb/trac/wiki/AjaxTerm Ajaxterm] =
+
+Ajaxterm is a web based terminal. It was totally inspired and works almost
+exactly like http://anyterm.org/ except it's much easier to install (see
+comparaison with anyterm below).
+
+Ajaxterm written in python (and some AJAX javascript for client side) and depends only on python2.3 or better.[[BR]]
+Ajaxterm is '''very simple to install''' on Linux, MacOS X, FreeBSD, Solaris, cygwin and any Unix that runs python2.3.[[BR]]
+Ajaxterm was written by Antony Lesuisse (email: al AT udev.org), License Public Domain.
+
+Use the [/qweb/forum/viewforum.php?id=2 Forum], if you have any question or remark.
+
+== News ==
+
+ * 2006-10-29: v0.10 allow space in login, cgi launch fix, redhat init
+ * 2006-07-12: v0.9 change uid, daemon fix (Daniel Fischer)
+ * 2006-07-04: v0.8 add login support to ssh (Sven Geggus), change max width to 256
+ * 2006-05-31: v0.7 minor fixes, daemon option
+ * 2006-05-23: v0.6 Applied debian and gentoo patches, renamed to Ajaxterm, default port 8022
+
+== Download and Install ==
+
+ * Release: [/qweb/files/Ajaxterm-0.10.tar.gz Ajaxterm-0.10.tar.gz]
+ * Browse src: [/qweb/trac/browser/trunk/ajaxterm/ ajaxterm/]
+
+To install Ajaxterm issue the following commands:
+{{{
+wget http://antony.lesuisse.org/qweb/files/Ajaxterm-0.10.tar.gz
+tar zxvf Ajaxterm-0.10.tar.gz
+cd Ajaxterm-0.10
+./ajaxterm.py
+}}}
+Then point your browser to this URL : http://localhost:8022/
+
+== Screenshot ==
+
+{{{
+#!html
+
+}}}
+
+== Documentation and Caveats ==
+
+ * Ajaxterm only support latin1, if you use Ubuntu or any LANG==en_US.UTF-8 distribution don't forget to "unset LANG".
+
+ * If run as root ajaxterm will run /bin/login, otherwise it will run ssh
+ localhost. To use an other command use the -c option.
+
+ * By default Ajaxterm only listen at 127.0.0.1:8022. For remote access, it is
+ strongly recommended to use '''https SSL/TLS''', and that is simple to
+ configure if you use the apache web server using mod_proxy.[[BR]][[BR]]
+ Using ssl will also speed up ajaxterm (probably because of keepalive).[[BR]][[BR]]
+ Here is an configuration example:
+
+{{{
+ Listen 443
+ NameVirtualHost *:443
+
+
+ ServerName localhost
+ SSLEngine On
+ SSLCertificateKeyFile ssl/apache.pem
+ SSLCertificateFile ssl/apache.pem
+
+ ProxyRequests Off
+
+ Order deny,allow
+ Allow from all
+
+ ProxyPass /ajaxterm/ http://localhost:8022/
+ ProxyPassReverse /ajaxterm/ http://localhost:8022/
+
+}}}
+
+ * Using GET HTTP request seems to speed up ajaxterm, just click on GET in the
+ interface, but be warned that your keystrokes might be loggued (by apache or
+ any proxy). I usually enable it after the login.
+
+ * Ajaxterm commandline usage:
+
+{{{
+usage: ajaxterm.py [options]
+
+options:
+ -h, --help show this help message and exit
+ -pPORT, --port=PORT Set the TCP port (default: 8022)
+ -cCMD, --command=CMD set the command (default: /bin/login or ssh localhost)
+ -l, --log log requests to stderr (default: quiet mode)
+ -d, --daemon run as daemon in the background
+ -PPIDFILE, --pidfile=PIDFILE
+ set the pidfile (default: /var/run/ajaxterm.pid)
+ -iINDEX_FILE, --index=INDEX_FILE
+ default index file (default: ajaxterm.html)
+ -uUID, --uid=UID Set the daemon's user id
+}}}
+
+ * Ajaxterm was first written as a demo for qweb (my web framework), but
+ actually doesn't use many features of qweb.
+
+ * Compared to anyterm:
+ * There are no partial updates, ajaxterm updates either all the screen or
+ nothing. That make the code simpler and I also think it's faster. HTTP
+ replies are always gzencoded. When used in 80x25 mode, almost all of
+ them are below the 1500 bytes (size of an ethernet frame) and we just
+ replace the screen with the reply (no javascript string handling).
+ * Ajaxterm polls the server for updates with an exponentially growing
+ timeout when the screen hasn't changed. The timeout is also resetted as
+ soon as a key is pressed. Anyterm blocks on a pending request and use a
+ parallel connection for keypresses. The anyterm approch is better
+ when there aren't any keypress.
+
+ * Ajaxterm files are released in the Public Domain, (except [http://sarissa.sourceforge.net/doc/ sarissa*] which are LGPL).
+
+== TODO ==
+
+ * insert mode ESC [ 4 h
+ * change size x,y from gui (sending signal)
+ * vt102 graphic codepage
+ * use innerHTML or prototype instead of sarissa
+
--
cgit
--
cgit
--
cgit
From 5b1422afe12d4e9b7fdfdc6a61cdcd51962dab4d Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Mon, 14 Mar 2011 14:43:53 -0700
Subject: Fix for LP Bug #704300
---
nova/virt/libvirt_conn.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py
index 0b306c950..e0222956e 100644
--- a/nova/virt/libvirt_conn.py
+++ b/nova/virt/libvirt_conn.py
@@ -339,7 +339,11 @@ class LibvirtConnection(object):
def reboot(self, instance):
self.destroy(instance, False)
xml = self.to_xml(instance)
+ self.firewall_driver.setup_basic_filtering(instance)
+ self.firewall_driver.prepare_instance_filter(instance)
self._conn.createXML(xml, 0)
+ self.firewall_driver.apply_instance_filter(instance)
+
timer = utils.LoopingCall(f=None)
def _wait_for_reboot():
--
cgit
From 2b20306fcaddcb6b9bc57fb55b17230d709cd1ce Mon Sep 17 00:00:00 2001
From: Justin Santa Barbara
Date: Mon, 14 Mar 2011 22:23:38 -0700
Subject: Derive unit test from standard nova.test.TestCase
---
nova/tests/integrated/test_login.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/nova/tests/integrated/test_login.py b/nova/tests/integrated/test_login.py
index e362f92d6..5fa558bdf 100644
--- a/nova/tests/integrated/test_login.py
+++ b/nova/tests/integrated/test_login.py
@@ -18,6 +18,7 @@
import unittest
from nova import flags
+from nova import test
from nova.log import logging
from nova.tests.integrated import integrated_helpers
from nova.tests.integrated.api import client
@@ -29,7 +30,7 @@ FLAGS = flags.FLAGS
FLAGS.verbose = True
-class LoginTest(unittest.TestCase):
+class LoginTest(test.TestCase):
def setUp(self):
super(LoginTest, self).setUp()
context = integrated_helpers.IntegratedUnitTestContext.startup()
@@ -73,5 +74,6 @@ class LoginTest(unittest.TestCase):
self.assertRaises(client.OpenstackApiAuthenticationException,
bad_credentials_api.get_flavors)
+
if __name__ == "__main__":
unittest.main()
--
cgit
From db8beffc9acd90c748512c1fa9c127d39756232c Mon Sep 17 00:00:00 2001
From: Justin Santa Barbara
Date: Mon, 14 Mar 2011 22:36:30 -0700
Subject: Reapplied rename of Openstack -> OpenStack. Easier to do it by hand
than to ask Bazaar to do it.
---
nova/tests/integrated/api/client.py | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py
index 6fba2930a..568e8c17e 100644
--- a/nova/tests/integrated/api/client.py
+++ b/nova/tests/integrated/api/client.py
@@ -24,7 +24,7 @@ from nova import log as logging
LOG = logging.getLogger('nova.tests.api')
-class OpenstackApiException(Exception):
+class OpenStackApiException(Exception):
def __init__(self, message=None, response=None):
self.response = response
if not message:
@@ -37,22 +37,22 @@ class OpenstackApiException(Exception):
message = _('%(message)s\nStatus Code: %(_status)s\n'
'Body: %(_body)s') % locals()
- super(OpenstackApiException, self).__init__(message)
+ super(OpenStackApiException, self).__init__(message)
-class OpenstackApiAuthenticationException(OpenstackApiException):
+class OpenStackApiAuthenticationException(OpenStackApiException):
def __init__(self, response=None, message=None):
if not message:
message = _("Authentication error")
- super(OpenstackApiAuthenticationException, self).__init__(message,
+ super(OpenStackApiAuthenticationException, self).__init__(message,
response)
-class OpenstackApiNotFoundException(OpenstackApiException):
+class OpenStackApiNotFoundException(OpenStackApiException):
def __init__(self, response=None, message=None):
if not message:
message = _("Item not found")
- super(OpenstackApiNotFoundException, self).__init__(message, response)
+ super(OpenStackApiNotFoundException, self).__init__(message, response)
class TestOpenStackClient(object):
@@ -82,7 +82,7 @@ class TestOpenStackClient(object):
conn = httplib.HTTPSConnection(hostname,
port=port)
else:
- raise OpenstackApiException("Unknown scheme: %s" % url)
+ raise OpenStackApiException("Unknown scheme: %s" % url)
relative_url = parsed_url.path
if parsed_url.query:
@@ -112,7 +112,7 @@ class TestOpenStackClient(object):
# bug732866
#if http_status == 401:
if http_status != 204:
- raise OpenstackApiAuthenticationException(response=response)
+ raise OpenStackApiAuthenticationException(response=response)
auth_headers = {}
for k, v in response.getheaders():
@@ -139,9 +139,9 @@ class TestOpenStackClient(object):
if check_response_status:
if not http_status in check_response_status:
if http_status == 404:
- raise OpenstackApiNotFoundException(response=response)
+ raise OpenStackApiNotFoundException(response=response)
else:
- raise OpenstackApiException(
+ raise OpenStackApiException(
message=_("Unexpected status code"),
response=response)
--
cgit
From e0563f49792441af106c52e662bdada3c7997feb Mon Sep 17 00:00:00 2001
From: Justin Santa Barbara
Date: Mon, 14 Mar 2011 22:43:21 -0700
Subject: Reapplied rename to another file.
---
nova/tests/integrated/test_login.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/nova/tests/integrated/test_login.py b/nova/tests/integrated/test_login.py
index 5fa558bdf..501f8c919 100644
--- a/nova/tests/integrated/test_login.py
+++ b/nova/tests/integrated/test_login.py
@@ -53,7 +53,7 @@ class LoginTest(test.TestCase):
"notso_password",
self.user.auth_url)
- self.assertRaises(client.OpenstackApiAuthenticationException,
+ self.assertRaises(client.OpenStackApiAuthenticationException,
bad_credentials_api.get_flavors)
def test_bad_login_username(self):
@@ -62,7 +62,7 @@ class LoginTest(test.TestCase):
self.user.secret,
self.user.auth_url)
- self.assertRaises(client.OpenstackApiAuthenticationException,
+ self.assertRaises(client.OpenStackApiAuthenticationException,
bad_credentials_api.get_flavors)
def test_bad_login_both_bad(self):
@@ -71,7 +71,7 @@ class LoginTest(test.TestCase):
"notso_password",
self.user.auth_url)
- self.assertRaises(client.OpenstackApiAuthenticationException,
+ self.assertRaises(client.OpenStackApiAuthenticationException,
bad_credentials_api.get_flavors)
--
cgit
From f1acc3d199a1a92b531a3e74ed54a8b2fcdb999c Mon Sep 17 00:00:00 2001
From: Justin Santa Barbara
Date: Tue, 15 Mar 2011 13:52:03 -0700
Subject: Now that the fix for 732866, stop working around the bug
---
nova/tests/integrated/api/client.py | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py
index 568e8c17e..fc7c344e7 100644
--- a/nova/tests/integrated/api/client.py
+++ b/nova/tests/integrated/api/client.py
@@ -108,10 +108,7 @@ class TestOpenStackClient(object):
http_status = response.status
LOG.debug(_("%(auth_uri)s => code %(http_status)s") % locals())
- # Until bug732866 is fixed, we can't check this properly...
- # bug732866
- #if http_status == 401:
- if http_status != 204:
+ if http_status == 401:
raise OpenStackApiAuthenticationException(response=response)
auth_headers = {}
--
cgit
From 67c871a257c684de3cb0f1416b1b2b6e9a99fe23 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Tue, 15 Mar 2011 17:37:07 -0500
Subject: Moving the migration again
---
.../versions/011_add_flavors_to_migrations.py | 44 ----------------------
.../versions/012_add_flavors_to_migrations.py | 44 ++++++++++++++++++++++
2 files changed, 44 insertions(+), 44 deletions(-)
delete mode 100644 nova/db/sqlalchemy/migrate_repo/versions/011_add_flavors_to_migrations.py
create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/012_add_flavors_to_migrations.py
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/011_add_flavors_to_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/011_add_flavors_to_migrations.py
deleted file mode 100644
index 412caedd0..000000000
--- a/nova/db/sqlalchemy/migrate_repo/versions/011_add_flavors_to_migrations.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2010 OpenStack LLC.
-# 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.from sqlalchemy import *
-
-from sqlalchemy import *
-from migrate import *
-
-from nova import log as logging
-
-
-meta = MetaData()
-
-migrations = Table('migrations', meta,
- Column('id', Integer(), primary_key=True, nullable=False),
- )
-
-#
-# Tables to alter
-#
-#
-
-old_flavor_id = Column('old_flavor_id', Integer())
-new_flavor_id = Column('new_flavor_id', Integer())
-
-
-def upgrade(migrate_engine):
- # Upgrade operations go here. Don't create your own engine;
- # bind migrate_engine to your metadata
- meta.bind = migrate_engine
- migrations.create_column(old_flavor_id)
- migrations.create_column(new_flavor_id)
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/012_add_flavors_to_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/012_add_flavors_to_migrations.py
new file mode 100644
index 000000000..412caedd0
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/012_add_flavors_to_migrations.py
@@ -0,0 +1,44 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2010 OpenStack LLC.
+# 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.from sqlalchemy import *
+
+from sqlalchemy import *
+from migrate import *
+
+from nova import log as logging
+
+
+meta = MetaData()
+
+migrations = Table('migrations', meta,
+ Column('id', Integer(), primary_key=True, nullable=False),
+ )
+
+#
+# Tables to alter
+#
+#
+
+old_flavor_id = Column('old_flavor_id', Integer())
+new_flavor_id = Column('new_flavor_id', Integer())
+
+
+def upgrade(migrate_engine):
+ # Upgrade operations go here. Don't create your own engine;
+ # bind migrate_engine to your metadata
+ meta.bind = migrate_engine
+ migrations.create_column(old_flavor_id)
+ migrations.create_column(new_flavor_id)
--
cgit
From 74987666f89b4d15ffcf17b43b3752135ba08a65 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Tue, 15 Mar 2011 18:48:17 -0500
Subject: A few fixes
---
nova/compute/manager.py | 2 +-
nova/virt/xenapi/vmops.py | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 39b28f6a9..307c91650 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -541,7 +541,7 @@ class ComputeManager(manager.Manager):
#after they're supported
instance_type = self.db.instance_type_get_by_flavor_id(context,
migration_ref['new_flavor_id'])
- self.db.instance_update(context, instance_ref,
+ self.db.instance_update(context, instance_id,
dict(memory_mb=instance_type['memory_mb'],
vcpus=instance_type['vcpus'],
local_gb=instance_type['local_gb']))
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index d1aaf998f..119d6dba8 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -304,7 +304,7 @@ class VMOps(object):
try:
# transfer the base copy
template_vm_ref, template_vdi_uuids = self._get_snapshot(instance)
- base_copy_uuid = template_vdi_uuids[1]
+ base_copy_uuid = template_vdi_uuids['snap']
vdi_ref, vm_vdi_rec = \
VMHelper.get_vdi_for_vm_safely(self._session, vm_ref)
cow_uuid = vm_vdi_rec['uuid']
@@ -319,7 +319,7 @@ class VMOps(object):
self._session.wait_for_task(task, instance.id)
# Now power down the instance and transfer the COW VHD
- self._shutdown(instance, vm_ref, method='clean')
+ self._shutdown(instance, vm_ref)
params = {'host': dest,
'vdi_uuid': cow_uuid,
--
cgit
From 39e722b58b87297aee770637f6a82ee1f206aecf Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Tue, 15 Mar 2011 18:51:22 -0500
Subject: Tweak
---
nova/virt/xenapi/vmops.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 119d6dba8..958201695 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -319,7 +319,7 @@ class VMOps(object):
self._session.wait_for_task(task, instance.id)
# Now power down the instance and transfer the COW VHD
- self._shutdown(instance, vm_ref)
+ self._shutdown(instance, vm_ref, hard=False)
params = {'host': dest,
'vdi_uuid': cow_uuid,
@@ -447,7 +447,8 @@ class VMOps(object):
"""Shutdown an instance"""
state = self.get_info(instance['name'])['state']
if state == power_state.SHUTDOWN:
- LOG.warn(_("VM %(vm)s already halted, skipping shutdown...") %
+ instance_name = instance.name
+ LOG.warn(_("VM %(instance_name)s already halted, skipping shutdown...") %
locals())
return
--
cgit
From 9650e73db3e18f839f8abf7a47aebb6fbf8c9e36 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Tue, 15 Mar 2011 19:10:50 -0500
Subject: Plugin
---
nova/virt/xenapi/vmops.py | 1 -
plugins/xenserver/xenapi/etc/xapi.d/plugins/migration | 1 +
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 958201695..cdc4a417c 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -370,7 +370,6 @@ class VMOps(object):
#TODO(mdietz): this will need to be adjusted for swap later
task = self._session.call_xenapi('VDI.resize_online', vdi_ref,
new_disk_size)
- vm_ref = VMHelper.lookup(self._session, instance.name)
self._session.wait_for_task(task, instance.id)
def reboot(self, instance):
diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration b/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration
index 4aa89863a..6008e71bf 100644
--- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration
+++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration
@@ -22,6 +22,7 @@ XenAPI Plugin for transfering data between host nodes
import os
import os.path
import pickle
+import shlex
import shutil
import subprocess
--
cgit
From e2f8c143eab3b43acd9e3658a480f75f435e7d42 Mon Sep 17 00:00:00 2001
From: Koji Iida
Date: Wed, 16 Mar 2011 19:51:06 +0900
Subject: Updating gateway_v6 in _on_set_network_host() is not required for
FlatManager
---
nova/network/manager.py | 5 -----
1 file changed, 5 deletions(-)
diff --git a/nova/network/manager.py b/nova/network/manager.py
index c51eb9ad0..7e28e6da2 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -404,11 +404,6 @@ class FlatManager(NetworkManager):
net = {}
net['injected'] = FLAGS.flat_injected
net['dns'] = FLAGS.flat_network_dns
- if not FLAGS.fake_network:
- if(FLAGS.use_ipv6):
- net['gateway_v6'] = \
- utils.get_my_linklocal(
- FLAGS.flat_network_bridge)
self.db.network_update(context, network_id, net)
def allocate_floating_ip(self, context, project_id):
--
cgit
From 8964cbecc10885bc6eff08544d62db1747fb14ef Mon Sep 17 00:00:00 2001
From: Koji Iida
Date: Wed, 16 Mar 2011 20:24:20 +0900
Subject: pep8 clean
---
nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py b/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py
index be1edc8f6..9f98f436f 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py
@@ -83,8 +83,7 @@ networks = Table('networks', meta,
Column(
'label',
String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False))
- )
+ unicode_error=None, _warn_on_bytestring=False)))
fixed_ips = Table('fixed_ips', meta,
Column('created_at', DateTime(timezone=False)),
--
cgit
From 2e81ce6bb5b1083220e7ae5c17113fd44465ddbf Mon Sep 17 00:00:00 2001
From: Koji Iida
Date: Wed, 16 Mar 2011 21:17:19 +0900
Subject: Fix instance creation fail under use_ipv6=false and FlatManager
---
nova/virt/libvirt_conn.py | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py
index 9efbb3342..a850bad87 100644
--- a/nova/virt/libvirt_conn.py
+++ b/nova/virt/libvirt_conn.py
@@ -660,11 +660,10 @@ class LibvirtConnection(object):
if network_ref['injected']:
admin_context = context.get_admin_context()
address = db.instance_get_fixed_address(admin_context, inst['id'])
- address_v6 = db.instance_get_fixed_address_v6(admin_context,
- inst['id'])
- gateway_v6 = network_ref['gateway_v6']
- if not gateway_v6:
- gateway_v6 = "fd00::"
+ address_v6 = None
+ if FLAGS.use_ipv6:
+ address_v6 = db.instance_get_fixed_address_v6(admin_context,
+ inst['id'])
interfaces_info = {'address': address,
'netmask': network_ref['netmask'],
--
cgit
From d1469d1566a67d41cb4de4ff06deaf441e099062 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 11:26:40 -0500
Subject: Some typos
---
nova/compute/api.py | 4 +++-
plugins/xenserver/xenapi/etc/xapi.d/plugins/migration | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 0e9bf2424..08947eb3a 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -443,6 +443,8 @@ class API(base.Base):
params = {'migration_id': migration_ref['id']}
self._cast_compute_message('revert_resize', context, instance_id,
migration_ref['dest_compute'], params=params)
+ self.db.migration_update(context, migration_ref['id'],
+ {'status': 'reverted'})
def confirm_resize(self, context, instance_id):
"""Confirms a migration/resize, deleting the 'old' instance in the
@@ -458,7 +460,7 @@ class API(base.Base):
self._cast_compute_message('confirm_resize', context, instance_id,
migration_ref['source_compute'], params=params)
- self.db.migration_update(context, migration_id,
+ self.db.migration_update(context, migration_ref['id'],
{'status': 'confirmed'})
self.db.instance_update(context, instance_id,
{'host': migration_ref['dest_compute'], })
diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration b/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration
index 6008e71bf..75c653408 100644
--- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration
+++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration
@@ -98,7 +98,7 @@ def transfer_vhd(session, args):
logging.debug("Preparing to transmit %s to %s" % (source_path,
dest_path))
- ssh_cmd = 'ssh -o StrictHostKeyChecking=no'
+ ssh_cmd = '\"ssh -o StrictHostKeyChecking=no\"'
rsync_args = shlex.split('nohup /usr/bin/rsync -av --progress -e %s %s %s'
% (ssh_cmd, source_path, dest_path))
--
cgit
From 9cb503ae9d4112fa464f2284631ad1e24f8f7ce4 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 11:38:40 -0500
Subject: Stuff
---
nova/virt/xenapi/vmops.py | 3 +--
nova/virt/xenapi_conn.py | 6 +-----
2 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index cdc4a417c..ebaa4a69a 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -363,8 +363,7 @@ class VMOps(object):
def resize_instance(self, instance, vdi_uuid):
"""Resize a running instance by changing it's RAM and disk size """
vm_ref = VMHelper.lookup(self._session, instance.name)
- vdi_ref, vm_vdi_rec = \
- VMHelper.get_vdi_for_vm_safely(self._session, vm_ref)
+ vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
new_disk_size = instance.local_gb
#TODO(mdietz): this will need to be adjusted for swap later
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index 6b1b51fee..b8256d205 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -164,15 +164,11 @@ class XenAPIConnection(object):
"""Create VM instance"""
self._vmops.spawn(instance)
- def resize_instance(self, instance, disk_info):
- """Resizes instance attributes such as RAM and disk space to the
- attributes specified by the record"""
- self._vmops.resize_instance(instance, disk_info['cow'])
-
def finish_resize(self, instance, disk_info):
"""Completes a resize, turning on the migrated instance"""
vdi_uuid = self._vmops.attach_disk(instance, disk_info['base_copy'],
disk_info['cow'])
+ self._vmops.resize_instance(instance, vdi_uuid)
self._vmops._spawn_with_disk(instance, vdi_uuid)
def snapshot(self, instance, image_id):
--
cgit
From dee86f53b0d1dccbc69d354b66ca7a4767e81d43 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 11:54:10 -0500
Subject: tweak
---
nova/compute/manager.py | 1 -
nova/virt/xenapi/vmops.py | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 307c91650..1587660a3 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -546,7 +546,6 @@ class ComputeManager(manager.Manager):
vcpus=instance_type['vcpus'],
local_gb=instance_type['local_gb']))
- self.driver.resize_instance(instance_ref, disk_info)
self.driver.finish_resize(instance_ref, disk_info)
self.db.migration_update(context, migration_id,
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index ebaa4a69a..483b0cb82 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -364,7 +364,7 @@ class VMOps(object):
"""Resize a running instance by changing it's RAM and disk size """
vm_ref = VMHelper.lookup(self._session, instance.name)
vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
- new_disk_size = instance.local_gb
+ new_disk_size = instance.local_gb * 1024
#TODO(mdietz): this will need to be adjusted for swap later
task = self._session.call_xenapi('VDI.resize_online', vdi_ref,
--
cgit
From d99a8d48cf38eb6be01587f9b377f48ff6cd88a2 Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Wed, 16 Mar 2011 17:09:13 +0000
Subject: Logging statements
---
nova/virt/xenapi/vmops.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 483b0cb82..c292822ca 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -363,13 +363,16 @@ class VMOps(object):
def resize_instance(self, instance, vdi_uuid):
"""Resize a running instance by changing it's RAM and disk size """
vm_ref = VMHelper.lookup(self._session, instance.name)
- vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
new_disk_size = instance.local_gb * 1024
+ LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %d megs") % (vdi_uuid,
+ instance.name, new_disk_size))
+ vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
#TODO(mdietz): this will need to be adjusted for swap later
task = self._session.call_xenapi('VDI.resize_online', vdi_ref,
new_disk_size)
self._session.wait_for_task(task, instance.id)
+ LOG.debug(_("Resize instance %s complete") % (instance.name))
def reboot(self, instance):
"""Reboot VM instance"""
--
cgit
From a31e715617e5af107bc79caeedf0aff41f65fb07 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 12:57:45 -0500
Subject: The geebees
---
nova/virt/xenapi/vmops.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index c292822ca..b449437c9 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -363,7 +363,7 @@ class VMOps(object):
def resize_instance(self, instance, vdi_uuid):
"""Resize a running instance by changing it's RAM and disk size """
vm_ref = VMHelper.lookup(self._session, instance.name)
- new_disk_size = instance.local_gb * 1024
+ new_disk_size = str(instance.local_gb * 1024 * 1024)
LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %d megs") % (vdi_uuid,
instance.name, new_disk_size))
vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
--
cgit
From e2399c434386a31114273f2cf6f14586a25480c2 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 13:06:49 -0500
Subject: Derped again
---
nova/virt/xenapi/vmops.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index b449437c9..7f80de8a9 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -363,8 +363,10 @@ class VMOps(object):
def resize_instance(self, instance, vdi_uuid):
"""Resize a running instance by changing it's RAM and disk size """
vm_ref = VMHelper.lookup(self._session, instance.name)
- new_disk_size = str(instance.local_gb * 1024 * 1024)
- LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %d megs") % (vdi_uuid,
+
+ #The new disk size must be in bytes
+ new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024)
+ LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %s megs") % (vdi_uuid,
instance.name, new_disk_size))
vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
--
cgit
From 647f5f0d0283b3852115d821b80a965b0bc92c35 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 13:24:51 -0500
Subject: chchchchchanges
---
nova/virt/xenapi/vmops.py | 19 ++++++++++---------
nova/virt/xenapi_conn.py | 3 ++-
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 7f80de8a9..6ff0aad15 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -72,7 +72,7 @@ class VMOps(object):
LOG.debug(_("Starting instance %s"), instance.name)
self._session.call_xenapi('VM.start', vm_ref, False, False)
- def create_disk(self, instance):
+ def _create_disk(self, instance):
user = AuthManager().get_user(instance.user_id)
project = AuthManager().get_project(instance.project_id)
disk_image_type = VMHelper.determine_disk_image_type(instance)
@@ -81,11 +81,11 @@ class VMOps(object):
return vdi_uuid
def spawn(self, instance):
- vdi_uuid = self.create_disk(instance)
- self._spawn_with_disk(instance, vdi_uuid=vdi_uuid)
+ vdi_uuid = self._create_disk(instance)
+ vm_ref = self._create_vm(instance, vdi_uuid)
+ self._spawn(instance, vm_ref)
- def _spawn_with_disk(self, instance, vdi_uuid):
- """Create VM instance"""
+ def _create_vm(self, instance, vdi_uuid):
instance_name = instance.name
vm_ref = VMHelper.lookup(self._session, instance_name)
if vm_ref is not None:
@@ -130,7 +130,10 @@ class VMOps(object):
# inject_network_info and create vifs
networks = self.inject_network_info(instance)
self.create_vifs(instance, networks)
+ return vm_ref
+ def _spawn(self, instance, vm_ref):
+ """Spawn a new instance"""
LOG.debug(_('Starting VM %s...'), vm_ref)
self._start(instance, vm_ref)
LOG.info(_('Spawning VM %(instance_name)s created %(vm_ref)s.')
@@ -364,16 +367,14 @@ class VMOps(object):
"""Resize a running instance by changing it's RAM and disk size """
vm_ref = VMHelper.lookup(self._session, instance.name)
+ #TODO(mdietz): this will need to be adjusted for swap later
#The new disk size must be in bytes
new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024)
LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %s megs") % (vdi_uuid,
instance.name, new_disk_size))
vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
- #TODO(mdietz): this will need to be adjusted for swap later
- task = self._session.call_xenapi('VDI.resize_online', vdi_ref,
- new_disk_size)
- self._session.wait_for_task(task, instance.id)
+ self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size)
LOG.debug(_("Resize instance %s complete") % (instance.name))
def reboot(self, instance):
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index b8256d205..fd68c0fe7 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -168,8 +168,9 @@ class XenAPIConnection(object):
"""Completes a resize, turning on the migrated instance"""
vdi_uuid = self._vmops.attach_disk(instance, disk_info['base_copy'],
disk_info['cow'])
+ self._vmops._create_vm(instance, vdi_uuid)
self._vmops.resize_instance(instance, vdi_uuid)
- self._vmops._spawn_with_disk(instance, vdi_uuid)
+ self._vmops._spawn_with_disk(instance)
def snapshot(self, instance, image_id):
""" Create snapshot from a running VM instance """
--
cgit
From 11e7b6a08d1557a0986b480c032958cd30762f33 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 13:31:05 -0500
Subject: chchchchchanges
---
nova/virt/xenapi/vmops.py | 2 --
nova/virt/xenapi_conn.py | 4 ++--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 6ff0aad15..92594c9c6 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -365,8 +365,6 @@ class VMOps(object):
def resize_instance(self, instance, vdi_uuid):
"""Resize a running instance by changing it's RAM and disk size """
- vm_ref = VMHelper.lookup(self._session, instance.name)
-
#TODO(mdietz): this will need to be adjusted for swap later
#The new disk size must be in bytes
new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024)
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index fd68c0fe7..046f74c8d 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -168,9 +168,9 @@ class XenAPIConnection(object):
"""Completes a resize, turning on the migrated instance"""
vdi_uuid = self._vmops.attach_disk(instance, disk_info['base_copy'],
disk_info['cow'])
- self._vmops._create_vm(instance, vdi_uuid)
+ vm_ref = self._vmops._create_vm(instance, vdi_uuid)
self._vmops.resize_instance(instance, vdi_uuid)
- self._vmops._spawn_with_disk(instance)
+ self._vmops._spawn(instance, vm_ref)
def snapshot(self, instance, image_id):
""" Create snapshot from a running VM instance """
--
cgit
From d8c3ea5e6b594e6285650c5bdac6302b7be295dc Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 13:39:43 -0500
Subject: chchchchchanges
---
nova/virt/xenapi/vmops.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 92594c9c6..931fc1cb4 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -136,6 +136,7 @@ class VMOps(object):
"""Spawn a new instance"""
LOG.debug(_('Starting VM %s...'), vm_ref)
self._start(instance, vm_ref)
+ instance_name = instance.name
LOG.info(_('Spawning VM %(instance_name)s created %(vm_ref)s.')
% locals())
--
cgit
From ebd452eab95c2f205d3f7419c08c288030c38aba Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 13:53:49 -0500
Subject: chchchchchanges
---
nova/compute/manager.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 1587660a3..351e02f51 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -546,6 +546,7 @@ class ComputeManager(manager.Manager):
vcpus=instance_type['vcpus'],
local_gb=instance_type['local_gb']))
+ instance_ref = self.db.instance_get(context, instance_id)
self.driver.finish_resize(instance_ref, disk_info)
self.db.migration_update(context, migration_id,
--
cgit
From 1d4d0e26ae6ece5e68417deaa4ddcf4b7757bd37 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 14:09:14 -0500
Subject: Fudge
---
nova/compute/api.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 08947eb3a..ddf439b35 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -468,11 +468,15 @@ class API(base.Base):
def resize(self, context, instance_id, flavor_id):
"""Resize a running instance."""
instance = self.db.instance_get(context, instance_id)
+ LOG.debug(_("Resizing instance %s to flavor %d") %
+ (instance.name, flavor_id))
current_instance_type = self.db.instance_type_get_by_name(
context, instance['instance_type'])
new_instance_type = self.db.instance_type_get_by_flavor_id(
context, flavor_id)
+ LOG.debug(_("Old instance type %s -> New instance type %s") %
+ (current_instance_type['name'], new_instance_type['name']))
if not new_instance_type:
raise exception.ApiError(_("Requested flavor does not exist"))
--
cgit
From 3459cfb89bd90605e54fd1fb28b8b38089f3e236 Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Wed, 16 Mar 2011 15:20:08 -0400
Subject: update image service documentation
---
nova/image/service.py | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/nova/image/service.py b/nova/image/service.py
index c09052cab..78d8f33e9 100644
--- a/nova/image/service.py
+++ b/nova/image/service.py
@@ -40,9 +40,9 @@ class BaseImageService(object):
:retval: a sequence of mappings with the following signature
{'id': opaque id of image,
'name': name of image,
- 'created_at': creation timestamp,
- 'updated_at': modification timestamp,
- 'deleted_at': deletion timestamp or None,
+ 'created_at': creation datetime object,
+ 'updated_at': modification datetime object,
+ 'deleted_at': deletion datetime object or None,
'deleted': boolean indicating if image has been deleted,
'status': string description of image status,
'is_public': boolean indicating if image is public
@@ -64,9 +64,9 @@ class BaseImageService(object):
{'id': opaque id of image,
'name': name of image,
- 'created_at': creation timestamp,
- 'updated_at': modification timestamp,
- 'deleted_at': deletion timestamp or None,
+ 'created_at': creation datetime object,
+ 'updated_at': modification datetime object,
+ 'deleted_at': deletion datetime object or None,
'deleted': boolean indicating if image has been deleted,
'status': string description of image status,
'is_public': boolean indicating if image is public
--
cgit
From 007c2802e542bf954f0aa5b589f2adc3a1bfa89a Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 15:41:53 -0500
Subject: Reverting
---
nova/virt/xenapi/vmops.py | 10 +++-------
nova/virt/xenapi_conn.py | 8 ++++----
2 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 931fc1cb4..7525ff5ec 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -85,7 +85,8 @@ class VMOps(object):
vm_ref = self._create_vm(instance, vdi_uuid)
self._spawn(instance, vm_ref)
- def _create_vm(self, instance, vdi_uuid):
+ def _spawn(self, instance, vdi_uuid):
+ """Spawn a new instance"""
instance_name = instance.name
vm_ref = VMHelper.lookup(self._session, instance_name)
if vm_ref is not None:
@@ -130,13 +131,8 @@ class VMOps(object):
# inject_network_info and create vifs
networks = self.inject_network_info(instance)
self.create_vifs(instance, networks)
- return vm_ref
-
- def _spawn(self, instance, vm_ref):
- """Spawn a new instance"""
LOG.debug(_('Starting VM %s...'), vm_ref)
self._start(instance, vm_ref)
- instance_name = instance.name
LOG.info(_('Spawning VM %(instance_name)s created %(vm_ref)s.')
% locals())
@@ -343,7 +339,7 @@ class VMOps(object):
# sensible so we don't need to blindly pass around dictionaries
return {'base_copy': base_copy_uuid, 'cow': cow_uuid}
- def attach_disk(self, instance, base_copy_uuid, cow_uuid):
+ def link_disks(self, instance, base_copy_uuid, cow_uuid):
"""Links the base copy VHD to the COW via the XAPI plugin"""
vm_ref = VMHelper.lookup(self._session, instance.name)
new_base_copy_uuid = str(uuid.uuid4())
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index 046f74c8d..99ec53c11 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -166,11 +166,11 @@ class XenAPIConnection(object):
def finish_resize(self, instance, disk_info):
"""Completes a resize, turning on the migrated instance"""
- vdi_uuid = self._vmops.attach_disk(instance, disk_info['base_copy'],
+ vdi_uuid = self._vmops.link_disks(instance, disk_info['base_copy'],
disk_info['cow'])
- vm_ref = self._vmops._create_vm(instance, vdi_uuid)
- self._vmops.resize_instance(instance, vdi_uuid)
- self._vmops._spawn(instance, vm_ref)
+ #vm_ref = self._vmops._create_vm(instance, vdi_uuid)
+ #self._vmops.resize_instance(instance, vdi_uuid)
+ self._vmops._spawn(instance, vdi_uuid)
def snapshot(self, instance, image_id):
""" Create snapshot from a running VM instance """
--
cgit
From d95187aaf144cb40558f48d584a6bb8e07c6937d Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Wed, 16 Mar 2011 14:13:57 -0700
Subject: converted new lines from CRLF to LF
---
.../versions/012_add_ipv6_flatmanager.py | 302 +++++++++----------
nova/tests/network/__init__.py | 94 +++---
nova/tests/network/base.py | 308 ++++++++++----------
nova/tests/test_flat_network.py | 322 ++++++++++-----------
4 files changed, 513 insertions(+), 513 deletions(-)
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py b/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py
index 9f98f436f..5f5e3d007 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py
@@ -1,151 +1,151 @@
-# Copyright 2010 OpenStack LLC.
-# 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.
-
-from sqlalchemy import *
-from migrate import *
-
-from nova import log as logging
-
-
-meta = MetaData()
-
-
-# Table stub-definitions
-# Just for the ForeignKey and column creation to succeed, these are not the
-# actual definitions of instances or services.
-#
-
-#
-# Tables to alter
-#
-networks = Table('networks', meta,
- Column('created_at', DateTime(timezone=False)),
- Column('updated_at', DateTime(timezone=False)),
- Column('deleted_at', DateTime(timezone=False)),
- Column('deleted', Boolean(create_constraint=True, name=None)),
- Column('id', Integer(), primary_key=True, nullable=False),
- Column('injected', Boolean(create_constraint=True, name=None)),
- Column('cidr',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)),
- Column('netmask',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)),
- Column('bridge',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)),
- Column('gateway',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)),
- Column('broadcast',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)),
- Column('dns',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)),
- Column('vlan', Integer()),
- Column('vpn_public_address',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)),
- Column('vpn_public_port', Integer()),
- Column('vpn_private_address',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)),
- Column('dhcp_start',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)),
- Column('project_id',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)),
- Column('host',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)),
- Column('cidr_v6',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)),
- Column('ra_server', String(length=255,
- convert_unicode=False,
- assert_unicode=None,
- unicode_error=None,
- _warn_on_bytestring=False)),
- Column(
- 'label',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)))
-
-fixed_ips = Table('fixed_ips', meta,
- Column('created_at', DateTime(timezone=False)),
- Column('updated_at', DateTime(timezone=False)),
- Column('deleted_at', DateTime(timezone=False)),
- Column('deleted', Boolean(create_constraint=True, name=None)),
- Column('id', Integer(), primary_key=True, nullable=False),
- Column('address',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False)),
- Column('network_id',
- Integer(),
- ForeignKey('networks.id'),
- nullable=True),
- Column('instance_id',
- Integer(),
- ForeignKey('instances.id'),
- nullable=True),
- Column('allocated', Boolean(create_constraint=True, name=None)),
- Column('leased', Boolean(create_constraint=True, name=None)),
- Column('reserved', Boolean(create_constraint=True, name=None)),
- Column("addressV6", String(length=255,
- convert_unicode=False,
- assert_unicode=None,
- unicode_error=None,
- _warn_on_bytestring=False)),
- Column("netmaskV6", String(length=3,
- convert_unicode=False,
- assert_unicode=None,
- unicode_error=None,
- _warn_on_bytestring=False)),
- Column("gatewayV6", String(length=255,
- convert_unicode=False,
- assert_unicode=None,
- unicode_error=None,
- _warn_on_bytestring=False)),
- )
-#
-# New Tables
-#
-# None
-
-#
-# Columns to add to existing tables
-#
-networks_netmask_v6 = Column(
- 'netmask_v6',
- String(length=255, convert_unicode=False, assert_unicode=None,
- unicode_error=None, _warn_on_bytestring=False))
-
-
-def upgrade(migrate_engine):
- # Upgrade operations go here. Don't create your own engine;
- # bind migrate_engine to your metadata
- meta.bind = migrate_engine
-
- # Alter column name
- networks.c.ra_server.alter(name='gateway_v6')
- # Add new column to existing table
- networks.create_column(networks_netmask_v6)
-
- # drop existing columns from table
- fixed_ips.c.addressV6.drop()
- fixed_ips.c.netmaskV6.drop()
- fixed_ips.c.gatewayV6.drop()
+# Copyright 2010 OpenStack LLC.
+# 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.
+
+from sqlalchemy import *
+from migrate import *
+
+from nova import log as logging
+
+
+meta = MetaData()
+
+
+# Table stub-definitions
+# Just for the ForeignKey and column creation to succeed, these are not the
+# actual definitions of instances or services.
+#
+
+#
+# Tables to alter
+#
+networks = Table('networks', meta,
+ Column('created_at', DateTime(timezone=False)),
+ Column('updated_at', DateTime(timezone=False)),
+ Column('deleted_at', DateTime(timezone=False)),
+ Column('deleted', Boolean(create_constraint=True, name=None)),
+ Column('id', Integer(), primary_key=True, nullable=False),
+ Column('injected', Boolean(create_constraint=True, name=None)),
+ Column('cidr',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('netmask',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('bridge',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('gateway',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('broadcast',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('dns',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('vlan', Integer()),
+ Column('vpn_public_address',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('vpn_public_port', Integer()),
+ Column('vpn_private_address',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('dhcp_start',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('project_id',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('host',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('cidr_v6',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('ra_server', String(length=255,
+ convert_unicode=False,
+ assert_unicode=None,
+ unicode_error=None,
+ _warn_on_bytestring=False)),
+ Column(
+ 'label',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)))
+
+fixed_ips = Table('fixed_ips', meta,
+ Column('created_at', DateTime(timezone=False)),
+ Column('updated_at', DateTime(timezone=False)),
+ Column('deleted_at', DateTime(timezone=False)),
+ Column('deleted', Boolean(create_constraint=True, name=None)),
+ Column('id', Integer(), primary_key=True, nullable=False),
+ Column('address',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False)),
+ Column('network_id',
+ Integer(),
+ ForeignKey('networks.id'),
+ nullable=True),
+ Column('instance_id',
+ Integer(),
+ ForeignKey('instances.id'),
+ nullable=True),
+ Column('allocated', Boolean(create_constraint=True, name=None)),
+ Column('leased', Boolean(create_constraint=True, name=None)),
+ Column('reserved', Boolean(create_constraint=True, name=None)),
+ Column("addressV6", String(length=255,
+ convert_unicode=False,
+ assert_unicode=None,
+ unicode_error=None,
+ _warn_on_bytestring=False)),
+ Column("netmaskV6", String(length=3,
+ convert_unicode=False,
+ assert_unicode=None,
+ unicode_error=None,
+ _warn_on_bytestring=False)),
+ Column("gatewayV6", String(length=255,
+ convert_unicode=False,
+ assert_unicode=None,
+ unicode_error=None,
+ _warn_on_bytestring=False)),
+ )
+#
+# New Tables
+#
+# None
+
+#
+# Columns to add to existing tables
+#
+networks_netmask_v6 = Column(
+ 'netmask_v6',
+ String(length=255, convert_unicode=False, assert_unicode=None,
+ unicode_error=None, _warn_on_bytestring=False))
+
+
+def upgrade(migrate_engine):
+ # Upgrade operations go here. Don't create your own engine;
+ # bind migrate_engine to your metadata
+ meta.bind = migrate_engine
+
+ # Alter column name
+ networks.c.ra_server.alter(name='gateway_v6')
+ # Add new column to existing table
+ networks.create_column(networks_netmask_v6)
+
+ # drop existing columns from table
+ fixed_ips.c.addressV6.drop()
+ fixed_ips.c.netmaskV6.drop()
+ fixed_ips.c.gatewayV6.drop()
diff --git a/nova/tests/network/__init__.py b/nova/tests/network/__init__.py
index 8f71a30ba..e0d479f8c 100644
--- a/nova/tests/network/__init__.py
+++ b/nova/tests/network/__init__.py
@@ -1,47 +1,47 @@
-import os
-
-from nova import context
-from nova import db
-from nova import flags
-from nova import log as logging
-from nova import utils
-
-FLAGS = flags.FLAGS
-LOG = logging.getLogger('nova.tests.network')
-
-
-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)
+import os
+
+from nova import context
+from nova import db
+from nova import flags
+from nova import log as logging
+from nova import utils
+
+FLAGS = flags.FLAGS
+LOG = logging.getLogger('nova.tests.network')
+
+
+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)
diff --git a/nova/tests/network/base.py b/nova/tests/network/base.py
index 2dd8178ff..988a1de72 100644
--- a/nova/tests/network/base.py
+++ b/nova/tests/network/base.py
@@ -1,154 +1,154 @@
-# 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.
-"""
-Base class of Unit Tests for all network models
-"""
-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
-
-FLAGS = flags.FLAGS
-LOG = logging.getLogger('nova.tests.network')
-
-
-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 _is_allocated_in_project(self, address, project_id):
- """Returns true if address is in specified project"""
- project_net = db.network_get_by_bridge(context.get_admin_context(),
- FLAGS.flat_network_bridge)
- 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 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_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)
+# 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.
+"""
+Base class of Unit Tests for all network models
+"""
+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
+
+FLAGS = flags.FLAGS
+LOG = logging.getLogger('nova.tests.network')
+
+
+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 _is_allocated_in_project(self, address, project_id):
+ """Returns true if address is in specified project"""
+ project_net = db.network_get_by_bridge(context.get_admin_context(),
+ FLAGS.flat_network_bridge)
+ 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 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_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)
diff --git a/nova/tests/test_flat_network.py b/nova/tests/test_flat_network.py
index b6f7762c5..dcc617e25 100644
--- a/nova/tests/test_flat_network.py
+++ b/nova/tests/test_flat_network.py
@@ -1,161 +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)
+# 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)
--
cgit
From 0e63a45f40a2069d497878b7c05d00522c3a2774 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 16:24:38 -0500
Subject: Again
---
nova/virt/xenapi/vmops.py | 13 ++++++++-----
nova/virt/xenapi_conn.py | 6 +++---
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 7525ff5ec..ab98ef000 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -85,8 +85,7 @@ class VMOps(object):
vm_ref = self._create_vm(instance, vdi_uuid)
self._spawn(instance, vm_ref)
- def _spawn(self, instance, vdi_uuid):
- """Spawn a new instance"""
+ def _create_vm(self, instance, vdi_uuid):
instance_name = instance.name
vm_ref = VMHelper.lookup(self._session, instance_name)
if vm_ref is not None:
@@ -131,8 +130,13 @@ class VMOps(object):
# inject_network_info and create vifs
networks = self.inject_network_info(instance)
self.create_vifs(instance, networks)
+ return vm_ref
+
+ def _spawn(self, instance, vm_ref):
+ """Spawn a new instance"""
LOG.debug(_('Starting VM %s...'), vm_ref)
self._start(instance, vm_ref)
+ instance_name = instance.name
LOG.info(_('Spawning VM %(instance_name)s created %(vm_ref)s.')
% locals())
@@ -365,10 +369,9 @@ class VMOps(object):
#TODO(mdietz): this will need to be adjusted for swap later
#The new disk size must be in bytes
new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024)
- LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %s megs") % (vdi_uuid,
- instance.name, new_disk_size))
+ LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %sGB") % (vdi_uuid,
+ instance.name, instance.local_gb))
vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
-
self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size)
LOG.debug(_("Resize instance %s complete") % (instance.name))
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index 99ec53c11..2b0f82a4a 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -168,9 +168,9 @@ class XenAPIConnection(object):
"""Completes a resize, turning on the migrated instance"""
vdi_uuid = self._vmops.link_disks(instance, disk_info['base_copy'],
disk_info['cow'])
- #vm_ref = self._vmops._create_vm(instance, vdi_uuid)
- #self._vmops.resize_instance(instance, vdi_uuid)
- self._vmops._spawn(instance, vdi_uuid)
+ vm_ref = self._vmops._create_vm(instance, vdi_uuid)
+ self._vmops.resize_instance(instance, vdi_uuid)
+ self._vmops._spawn(instance, vm_ref)
def snapshot(self, instance, image_id):
""" Create snapshot from a running VM instance """
--
cgit
From c7da5632e954c860defc322e971936a8d60eb8fd Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 16:55:58 -0500
Subject: foo
---
nova/virt/xenapi/vmops.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index ab98ef000..9719e05b9 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -308,7 +308,7 @@ class VMOps(object):
try:
# transfer the base copy
template_vm_ref, template_vdi_uuids = self._get_snapshot(instance)
- base_copy_uuid = template_vdi_uuids['snap']
+ base_copy_uuid = template_vdi_uuids['image']
vdi_ref, vm_vdi_rec = \
VMHelper.get_vdi_for_vm_safely(self._session, vm_ref)
cow_uuid = vm_vdi_rec['uuid']
--
cgit
From cc2d4728d32d016ef803d0def456cac6e315e8fa Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Wed, 16 Mar 2011 17:56:40 -0400
Subject: get started testing
---
nova/image/glance.py | 6 ++++--
nova/tests/image/__init__.py | 0
nova/tests/image/test_glance.py | 18 ++++++++++++++++++
3 files changed, 22 insertions(+), 2 deletions(-)
create mode 100644 nova/tests/image/__init__.py
create mode 100644 nova/tests/image/test_glance.py
diff --git a/nova/image/glance.py b/nova/image/glance.py
index 15fca69b8..3b448db4b 100644
--- a/nova/image/glance.py
+++ b/nova/image/glance.py
@@ -37,8 +37,10 @@ GlanceClient = utils.import_class('glance.client.Client')
class GlanceImageService(service.BaseImageService):
"""Provides storage and retrieval of disk image objects within Glance."""
- def __init__(self):
- self.client = GlanceClient(FLAGS.glance_host, FLAGS.glance_port)
+ def __init__(self, client=None):
+ if client is None:
+ self.client = GlanceClient(FLAGS.glance_host, FLAGS.glance_port)
+ self.client = client
def index(self, context):
"""
diff --git a/nova/tests/image/__init__.py b/nova/tests/image/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py
new file mode 100644
index 000000000..b568f593d
--- /dev/null
+++ b/nova/tests/image/test_glance.py
@@ -0,0 +1,18 @@
+import unittest
+
+from nova.image import glance
+
+class StubGlanceClient(object):
+
+ def __init__(self, images):
+ self._images = images
+
+ def get_image_meta(id):
+ return self._images[id]
+
+class TestGlance(unittest.TestCase):
+
+ def test(self):
+ images = {'xyz': "image"}
+ client = StubGlanceClient(images)
+ service = glance.GlanceImageService(client)
--
cgit
From 8385599f941c5fe886de570b67f5e57e64e96468 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 16:58:46 -0500
Subject: hurr
---
nova/db/sqlalchemy/api.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index f4773ce32..84db330ec 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -2206,8 +2206,8 @@ def migration_get_by_instance_and_status(context, instance_id, status):
filter_by(instance_id=instance_id).\
filter_by(status=status).first()
if not result:
- raise exception.NotFound(_("No migration found with instance id %s")
- % migration_id)
+ raise exception.NotFound(_("No migration found for instance %d")
+ "with status %s" % (instance_id, status))
return result
--
cgit
From 524eb966045192dd535648929d70cac091d8e24e Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 17:00:22 -0500
Subject: hurr
---
nova/db/sqlalchemy/api.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index 84db330ec..7e358e64b 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -2206,8 +2206,8 @@ def migration_get_by_instance_and_status(context, instance_id, status):
filter_by(instance_id=instance_id).\
filter_by(status=status).first()
if not result:
- raise exception.NotFound(_("No migration found for instance %d")
- "with status %s" % (instance_id, status))
+ raise exception.NotFound(_("No migration found for instance %d"
+ "with status %s" % (instance_id, status)))
return result
--
cgit
From bf2f491f3e7aa5522d306c2182c3d220eb49a55f Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 17:56:48 -0500
Subject: foo
---
nova/compute/manager.py | 5 +++--
nova/db/sqlalchemy/api.py | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 351e02f51..e69544b6e 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -458,7 +458,7 @@ class ComputeManager(manager.Manager):
#Just roll back the record. There's no need to resize down since
#the 'old' VM already has the preferred attributes
- self.db.instance_update(context,
+ self.db.instance_update(context, instance_id
dict(memory_mb=instance_type['memory_mb'],
vcpus=instance_type['vcpus'],
local_gb=instance_type['local_gb']))
@@ -542,7 +542,8 @@ class ComputeManager(manager.Manager):
instance_type = self.db.instance_type_get_by_flavor_id(context,
migration_ref['new_flavor_id'])
self.db.instance_update(context, instance_id,
- dict(memory_mb=instance_type['memory_mb'],
+ dict(instance_type=instance_type['name'],
+ memory_mb=instance_type['memory_mb'],
vcpus=instance_type['vcpus'],
local_gb=instance_type['local_gb']))
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index 7e358e64b..47b84af50 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -2206,7 +2206,7 @@ def migration_get_by_instance_and_status(context, instance_id, status):
filter_by(instance_id=instance_id).\
filter_by(status=status).first()
if not result:
- raise exception.NotFound(_("No migration found for instance %d"
+ raise exception.NotFound(_("No migration found for instance %s"
"with status %s" % (instance_id, status)))
return result
--
cgit
From 3c0ae08b71c860383c215fa30c36693fd80f34c2 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Wed, 16 Mar 2011 17:58:16 -0500
Subject: foo
---
nova/compute/manager.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index e69544b6e..3135d5801 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -458,7 +458,7 @@ class ComputeManager(manager.Manager):
#Just roll back the record. There's no need to resize down since
#the 'old' VM already has the preferred attributes
- self.db.instance_update(context, instance_id
+ self.db.instance_update(context, instance_id,
dict(memory_mb=instance_type['memory_mb'],
vcpus=instance_type['vcpus'],
local_gb=instance_type['local_gb']))
--
cgit
From aa13754d04c17ae9985017e22ae4f68916bc2781 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Thu, 17 Mar 2011 10:03:47 -0500
Subject: Foo
---
nova/compute/manager.py | 1 -
nova/virt/xenapi/vmops.py | 3 ++-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 3135d5801..b8c3c24cd 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -547,7 +547,6 @@ class ComputeManager(manager.Manager):
vcpus=instance_type['vcpus'],
local_gb=instance_type['local_gb']))
- instance_ref = self.db.instance_get(context, instance_id)
self.driver.finish_resize(instance_ref, disk_info)
self.db.migration_update(context, migration_id,
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 9719e05b9..b5003f0f8 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -307,7 +307,7 @@ class VMOps(object):
template_vdi_uuids = template_vm_ref = None
try:
# transfer the base copy
- template_vm_ref, template_vdi_uuids = self._get_snapshot(instance)
+ template_vm_ref, template_vdi_uuids = selimage._get_snapshot(instance)
base_copy_uuid = template_vdi_uuids['image']
vdi_ref, vm_vdi_rec = \
VMHelper.get_vdi_for_vm_safely(self._session, vm_ref)
@@ -368,6 +368,7 @@ class VMOps(object):
"""Resize a running instance by changing it's RAM and disk size """
#TODO(mdietz): this will need to be adjusted for swap later
#The new disk size must be in bytes
+
new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024)
LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %sGB") % (vdi_uuid,
instance.name, instance.local_gb))
--
cgit
From 4f1f5bb1ed2cbb57e9ba8ea481ae31c0e6acc7bd Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Thu, 17 Mar 2011 11:03:07 -0500
Subject: refactoring
---
nova/compute/manager.py | 5 +----
nova/virt/xenapi/vmops.py | 22 +++++++++++++++++-----
nova/virt/xenapi_conn.py | 10 +++++-----
3 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index b8c3c24cd..6b784f1e3 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -463,7 +463,7 @@ class ComputeManager(manager.Manager):
vcpus=instance_type['vcpus'],
local_gb=instance_type['local_gb']))
- self.driver._start(instance_ref)
+ self.driver.revert_resize(instance_ref)
self.db.migration_update(context, migration_id,
{'status': 'reverted'})
@@ -514,8 +514,6 @@ class ComputeManager(manager.Manager):
self.db.migration_update(context, migration_id,
{'status': 'post-migrating', })
-
-
service = self.db.service_get_by_host_and_topic(context,
migration_ref['dest_compute'], FLAGS.compute_topic)
topic = self.db.queue_get_for(context, FLAGS.compute_topic,
@@ -536,7 +534,6 @@ class ComputeManager(manager.Manager):
migration_ref = self.db.migration_get(context, migration_id)
instance_ref = self.db.instance_get(context,
migration_ref['instance_id'])
-
#TODO(mdietz): apply the rest of the instance_type attributes going
#after they're supported
instance_type = self.db.instance_type_get_by_flavor_id(context,
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index b5003f0f8..ee99a9918 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -62,6 +62,17 @@ class VMOps(object):
vm_refs.append(vm_rec["name_label"])
return vm_refs
+ def revert_resize(self, instance):
+ vm_ref = VMHelper.lookup(self._session, instance.name)
+ self._start(instance, vm_ref)
+
+ def finish_resize(self, instance, disk_info):
+ vdi_uuid = self._vmops.link_disks(instance, disk_info['base_copy'],
+ disk_info['cow'])
+ vm_ref = self._create_vm(instance, vdi_uuid)
+ self.resize_instance(instance, vdi_uuid)
+ self._spawn(instance, vm_ref)
+
def _start(self, instance, vm_ref=None):
"""Power on a VM instance"""
if not vm_ref:
@@ -307,7 +318,8 @@ class VMOps(object):
template_vdi_uuids = template_vm_ref = None
try:
# transfer the base copy
- template_vm_ref, template_vdi_uuids = selimage._get_snapshot(instance)
+ template_vm_ref, template_vdi_uuids = \
+ self.image._get_snapshot(instance)
base_copy_uuid = template_vdi_uuids['image']
vdi_ref, vm_vdi_rec = \
VMHelper.get_vdi_for_vm_safely(self._session, vm_ref)
@@ -370,8 +382,8 @@ class VMOps(object):
#The new disk size must be in bytes
new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024)
- LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %sGB") % (vdi_uuid,
- instance.name, instance.local_gb))
+ LOG.debug(_("Resizpng VDI %s for instance %s. Expanding to %sGB") %
+ (vdi_uuid, instance.name, instance.local_gb))
vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size)
LOG.debug(_("Resize instance %s complete") % (instance.name))
@@ -451,8 +463,8 @@ class VMOps(object):
state = self.get_info(instance['name'])['state']
if state == power_state.SHUTDOWN:
instance_name = instance.name
- LOG.warn(_("VM %(instance_name)s already halted, skipping shutdown...") %
- locals())
+ LOG.warn(_("VM %(instance_name)s already halted,"
+ "skipping shutdown...") % locals())
return
instance_id = instance.id
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index 2b0f82a4a..da2fb51f1 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -164,13 +164,13 @@ class XenAPIConnection(object):
"""Create VM instance"""
self._vmops.spawn(instance)
+ def revert_resize(self, instance):
+ """Reverts a resize, powering back on the instance"""
+ self._vmops.revert_resize(instance)
+
def finish_resize(self, instance, disk_info):
"""Completes a resize, turning on the migrated instance"""
- vdi_uuid = self._vmops.link_disks(instance, disk_info['base_copy'],
- disk_info['cow'])
- vm_ref = self._vmops._create_vm(instance, vdi_uuid)
- self._vmops.resize_instance(instance, vdi_uuid)
- self._vmops._spawn(instance, vm_ref)
+ self._vmops.finish_resize(instance, disk_info)
def snapshot(self, instance, image_id):
""" Create snapshot from a running VM instance """
--
cgit
From 1ffef31839f3c1f4386d5df834af6d53483c09ed Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Thu, 17 Mar 2011 11:16:59 -0500
Subject: oh come on
---
nova/virt/xenapi/vmops.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index ee99a9918..b6bcc60ea 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -318,8 +318,7 @@ class VMOps(object):
template_vdi_uuids = template_vm_ref = None
try:
# transfer the base copy
- template_vm_ref, template_vdi_uuids = \
- self.image._get_snapshot(instance)
+ template_vm_ref, template_vdi_uuids = self._get_snapshot(instance)
base_copy_uuid = template_vdi_uuids['image']
vdi_ref, vm_vdi_rec = \
VMHelper.get_vdi_for_vm_safely(self._session, vm_ref)
--
cgit
From e79eaca86c4073cc8bc6c59be83d0f1bf5e2cea4 Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Thu, 17 Mar 2011 12:20:22 -0400
Subject: glance image service show testcases
---
nova/image/glance.py | 14 +++++++++
nova/tests/image/test_glance.py | 64 ++++++++++++++++++++++++++++++++++++-----
2 files changed, 71 insertions(+), 7 deletions(-)
diff --git a/nova/image/glance.py b/nova/image/glance.py
index 3b448db4b..d0c191ea1 100644
--- a/nova/image/glance.py
+++ b/nova/image/glance.py
@@ -18,6 +18,8 @@
from __future__ import absolute_import
+import datetime as dt
+
from glance.common import exception as glance_exception
from nova import exception
@@ -60,6 +62,18 @@ class GlanceImageService(service.BaseImageService):
"""
try:
image = self.client.get_image_meta(image_id)
+ if 'created_at' in image:
+ image['created_at'] = \
+ dt.datetime.strptime(image['created_at'],
+ "%Y-%m-%dT%H:%M:%S.%f")
+ if 'updated_at' in image:
+ image['updated_at'] = \
+ dt.datetime.strptime(image['updated_at'],
+ "%Y-%m-%dT%H:%M:%S.%f")
+ if 'deleted_at' in image and image['deleted_at'] is not None:
+ image['deleted_at'] = \
+ dt.datetime.strptime(image['deleted_at'],
+ "%Y-%m-%dT%H:%M:%S.%f")
except glance_exception.NotFound:
raise exception.NotFound
return image
diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py
index b568f593d..971a32a17 100644
--- a/nova/tests/image/test_glance.py
+++ b/nova/tests/image/test_glance.py
@@ -1,3 +1,4 @@
+import datetime as dt
import unittest
from nova.image import glance
@@ -5,14 +6,63 @@ from nova.image import glance
class StubGlanceClient(object):
def __init__(self, images):
- self._images = images
+ self.images = images
- def get_image_meta(id):
- return self._images[id]
+ def get_image_meta(self, id):
+ return self.images[id]
+
+ def get_images_detailed(self):
+ return self.images
class TestGlance(unittest.TestCase):
- def test(self):
- images = {'xyz': "image"}
- client = StubGlanceClient(images)
- service = glance.GlanceImageService(client)
+ def setUp(self):
+ self.client = StubGlanceClient(None)
+ self.service = glance.GlanceImageService(self.client)
+
+ def test_show_passes_through_to_client(self):
+ self.client.images = {'xyz': "image"}
+ self.assertEqual(self.service.show({}, 'xyz'), "image")
+
+ def test_detail_passes_through_to_client(self):
+ self.client.images = "these are the images"
+ self.assertEqual(self.service.detail({}), self.client.images)
+
+ def test_show_makes_create_datetimes(self):
+ create_time = dt.datetime.utcnow()
+ self.client.images = {'xyz': {
+ 'id': "id",
+ 'name': "my awesome image",
+ 'created_at': create_time.isoformat(),
+ }}
+ actual = self.service.show({}, 'xyz')
+ self.assertEqual(actual['created_at'], create_time)
+
+ def test_show_makes_update_datetimes(self):
+ update_time = dt.datetime.utcnow()
+ self.client.images = {'abc': {
+ 'id': "id",
+ 'name': "my okay image",
+ 'updated_at': update_time.isoformat(),
+ }}
+ actual = self.service.show({}, 'abc')
+ self.assertEqual(actual['updated_at'], update_time)
+
+ def test_show_makes_delete_datetimes(self):
+ delete_time = dt.datetime.utcnow()
+ self.client.images = {'123': {
+ 'id': "123",
+ 'name': "my lame image",
+ 'deleted_at': delete_time.isoformat(),
+ }}
+ actual = self.service.show({}, '123')
+ self.assertEqual(actual['deleted_at'], delete_time)
+
+ def test_show_handles_deleted_at_none(self):
+ self.client.images = {'747': {
+ 'id': "747",
+ 'name': "not deleted",
+ 'deleted_at': None,
+ }}
+ actual = self.service.show({}, '747')
+ self.assertEqual(actual['deleted_at'], None)
--
cgit
From d6ae8e4c2f6011497b1db23fcbafb23b663f924d Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Thu, 17 Mar 2011 11:24:24 -0500
Subject: Foo
---
nova/compute/manager.py | 1 +
nova/virt/xenapi/vmops.py | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 6b784f1e3..186b6f6a5 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -544,6 +544,7 @@ class ComputeManager(manager.Manager):
vcpus=instance_type['vcpus'],
local_gb=instance_type['local_gb']))
+ instance_ref = self.db.instance_get(context, instance_id)
self.driver.finish_resize(instance_ref, disk_info)
self.db.migration_update(context, migration_id,
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index b6bcc60ea..326d43aa9 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -67,7 +67,7 @@ class VMOps(object):
self._start(instance, vm_ref)
def finish_resize(self, instance, disk_info):
- vdi_uuid = self._vmops.link_disks(instance, disk_info['base_copy'],
+ vdi_uuid = self.link_disks(instance, disk_info['base_copy'],
disk_info['cow'])
vm_ref = self._create_vm(instance, vdi_uuid)
self.resize_instance(instance, vdi_uuid)
--
cgit
From b135bc23cca1494049dd9978cb18b52f2b4d99c7 Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Thu, 17 Mar 2011 12:30:32 -0400
Subject: refactor to simpler implementation
---
nova/image/glance.py | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/nova/image/glance.py b/nova/image/glance.py
index d0c191ea1..188b6e588 100644
--- a/nova/image/glance.py
+++ b/nova/image/glance.py
@@ -62,22 +62,25 @@ class GlanceImageService(service.BaseImageService):
"""
try:
image = self.client.get_image_meta(image_id)
- if 'created_at' in image:
- image['created_at'] = \
- dt.datetime.strptime(image['created_at'],
- "%Y-%m-%dT%H:%M:%S.%f")
- if 'updated_at' in image:
- image['updated_at'] = \
- dt.datetime.strptime(image['updated_at'],
- "%Y-%m-%dT%H:%M:%S.%f")
- if 'deleted_at' in image and image['deleted_at'] is not None:
- image['deleted_at'] = \
- dt.datetime.strptime(image['deleted_at'],
- "%Y-%m-%dT%H:%M:%S.%f")
except glance_exception.NotFound:
raise exception.NotFound
+ return self._convert_timestamps_to_datetimes(image)
+
+ def _convert_timestamps_to_datetimes(self, image):
+ """
+ Returns image with known timestamp fields converted to datetime objects
+ """
+ for attr in ['created_at', 'updated_at', 'deleted_at']:
+ if attr in image and image[attr] is not None:
+ image[attr] = self._parse_glance_iso8601_timestamp(image[attr])
return image
+ def _parse_glance_iso8601_timestamp(self, timestamp):
+ """
+ Parse a subset of iso8601 timestamps into datetime objects
+ """
+ return dt.datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%f")
+
def show_by_name(self, context, name):
"""
Returns a dict containing image data for the given name.
--
cgit
From 686e113188aaf8195aed7bea8bf70c21b6bff498 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Thu, 17 Mar 2011 12:04:49 -0500
Subject: Mapping the resize status
---
nova/api/openstack/servers.py | 8 +++++++-
nova/compute/manager.py | 2 ++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index 47ed254ec..59234b0de 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -61,7 +61,13 @@ def _translate_detail_keys(inst):
for k, v in mapped_keys.iteritems():
inst_dict[k] = inst[v]
- inst_dict['status'] = power_mapping[inst_dict['status']]
+ context = req.environ['nova.context'].elevated()
+ migration = self.db.migrate_get_by_instance_and_status(context,
+ inst['id'], 'finished')
+ if migration:
+ inst_dict['status'] = 'resize-confirm'
+ else
+ inst_dict['status'] = power_mapping[inst_dict['status']]
inst_dict['addresses'] = dict(public=[], private=[])
# grab single private fixed ip
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 186b6f6a5..7993298b9 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -544,6 +544,8 @@ class ComputeManager(manager.Manager):
vcpus=instance_type['vcpus'],
local_gb=instance_type['local_gb']))
+ # reload the updated instance ref
+ # FIXME: is there reload functionality?
instance_ref = self.db.instance_get(context, instance_id)
self.driver.finish_resize(instance_ref, disk_info)
--
cgit
From 3afeb8466fa9f005edc9da182b1e0af6ffb00ade Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Thu, 17 Mar 2011 12:05:43 -0500
Subject: Mapping the resize status
---
nova/api/openstack/servers.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index 59234b0de..fd835c247 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -66,7 +66,7 @@ def _translate_detail_keys(inst):
inst['id'], 'finished')
if migration:
inst_dict['status'] = 'resize-confirm'
- else
+ else:
inst_dict['status'] = power_mapping[inst_dict['status']]
inst_dict['addresses'] = dict(public=[], private=[])
--
cgit
From 3ee835c60d2b43086b1e324501025d1f0221da27 Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Thu, 17 Mar 2011 13:50:41 -0400
Subject: handle timestamps in glance service detail
---
nova/image/glance.py | 3 ++-
nova/tests/image/test_glance.py | 27 ++++++++++++++++++++++++---
2 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/nova/image/glance.py b/nova/image/glance.py
index 188b6e588..7706a42e4 100644
--- a/nova/image/glance.py
+++ b/nova/image/glance.py
@@ -54,7 +54,8 @@ class GlanceImageService(service.BaseImageService):
"""
Calls out to Glance for a list of detailed image information
"""
- return self.client.get_images_detailed()
+ for image in self.client.get_images_detailed():
+ yield self._convert_timestamps_to_datetimes(image)
def show(self, context, image_id):
"""
diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py
index 971a32a17..16fe0e7c0 100644
--- a/nova/tests/image/test_glance.py
+++ b/nova/tests/image/test_glance.py
@@ -12,7 +12,7 @@ class StubGlanceClient(object):
return self.images[id]
def get_images_detailed(self):
- return self.images
+ return self.images.itervalues()
class TestGlance(unittest.TestCase):
@@ -25,8 +25,8 @@ class TestGlance(unittest.TestCase):
self.assertEqual(self.service.show({}, 'xyz'), "image")
def test_detail_passes_through_to_client(self):
- self.client.images = "these are the images"
- self.assertEqual(self.service.detail({}), self.client.images)
+ self.client.images = {1: "an image"}
+ self.assertEqual(list(self.service.detail({})), ["an image"])
def test_show_makes_create_datetimes(self):
create_time = dt.datetime.utcnow()
@@ -66,3 +66,24 @@ class TestGlance(unittest.TestCase):
}}
actual = self.service.show({}, '747')
self.assertEqual(actual['deleted_at'], None)
+
+ def test_detail_handles_timestamps(self):
+ now = dt.datetime.utcnow()
+ image1 = {
+ 'id': 1,
+ 'name': 'image 1',
+ 'created_at': now.isoformat(),
+ 'updated_at': now.isoformat(),
+ 'deleted_at': None,
+ }
+ image2 = {
+ 'id': 2,
+ 'name': 'image 2',
+ 'deleted_at': now.isoformat(),
+ }
+ self.client.images = {1: image1, 2: image2}
+ i1, i2 = self.service.detail({})
+ self.assertEqual(i1['created_at'], now)
+ self.assertEqual(i1['updated_at'], now)
+ self.assertEqual(i1['deleted_at'], None)
+ self.assertEqual(i2['deleted_at'], now)
--
cgit
From 66c237a4d321887830e5282781870525abf00365 Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Thu, 17 Mar 2011 14:04:31 -0400
Subject: teach glance image server get to handle timestamps
---
nova/image/glance.py | 2 +-
nova/tests/image/test_glance.py | 30 +++++++++++++++++++++++++++++-
2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/nova/image/glance.py b/nova/image/glance.py
index 7706a42e4..f725fe176 100644
--- a/nova/image/glance.py
+++ b/nova/image/glance.py
@@ -108,7 +108,7 @@ class GlanceImageService(service.BaseImageService):
raise exception.NotFound
for chunk in image_chunks:
data.write(chunk)
- return metadata
+ return self._convert_timestamps_to_datetimes(metadata)
def create(self, context, metadata, data=None):
"""
diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py
index 16fe0e7c0..1e6c45219 100644
--- a/nova/tests/image/test_glance.py
+++ b/nova/tests/image/test_glance.py
@@ -14,7 +14,17 @@ class StubGlanceClient(object):
def get_images_detailed(self):
return self.images.itervalues()
-class TestGlance(unittest.TestCase):
+ def get_image(self, id):
+ return self.images[id], []
+
+
+class NullWriter(object):
+
+ def write(self, *arg, **kwargs):
+ pass
+
+
+class TestGlanceImageServiceDatetimes(unittest.TestCase):
def setUp(self):
self.client = StubGlanceClient(None)
@@ -87,3 +97,21 @@ class TestGlance(unittest.TestCase):
self.assertEqual(i1['updated_at'], now)
self.assertEqual(i1['deleted_at'], None)
self.assertEqual(i2['deleted_at'], now)
+
+ def test_get_handles_timestamps(self):
+ now = dt.datetime.utcnow()
+ self.client.images = {'abcd': {
+ 'id': 'abcd',
+ 'name': 'nifty image',
+ 'created_at': now.isoformat(),
+ 'updated_at': now.isoformat(),
+ 'deleted_at': now.isoformat(),
+ }}
+ actual = self.service.get({}, 'abcd', NullWriter())
+ for attr in ('created_at', 'updated_at', 'deleted_at'):
+ self.assertEqual(actual[attr], now)
+
+ def test_get_handles_deleted_at_none(self):
+ self.client.images = {'abcd': {'deleted_at': None}}
+ actual = self.service.get({}, 'abcd', NullWriter())
+ self.assertEqual(actual['deleted_at'], None)
--
cgit
From c8e474d04dce462650c2a9f57cbcb106ce3ef0c9 Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Thu, 17 Mar 2011 14:05:08 -0400
Subject: pep8
---
nova/tests/image/test_glance.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py
index 1e6c45219..9b17cf261 100644
--- a/nova/tests/image/test_glance.py
+++ b/nova/tests/image/test_glance.py
@@ -3,6 +3,7 @@ import unittest
from nova.image import glance
+
class StubGlanceClient(object):
def __init__(self, images):
--
cgit
From 4334ca9d6b0ac8a9b2edb1fbcbf0bc4df28b2961 Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Thu, 17 Mar 2011 15:04:28 -0400
Subject: get api openstack test_images working
---
nova/image/glance.py | 7 ++++---
nova/tests/api/openstack/test_images.py | 8 ++++----
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/nova/image/glance.py b/nova/image/glance.py
index f725fe176..55dc5488d 100644
--- a/nova/image/glance.py
+++ b/nova/image/glance.py
@@ -42,7 +42,8 @@ class GlanceImageService(service.BaseImageService):
def __init__(self, client=None):
if client is None:
self.client = GlanceClient(FLAGS.glance_host, FLAGS.glance_port)
- self.client = client
+ else:
+ self.client = client
def index(self, context):
"""
@@ -54,8 +55,8 @@ class GlanceImageService(service.BaseImageService):
"""
Calls out to Glance for a list of detailed image information
"""
- for image in self.client.get_images_detailed():
- yield self._convert_timestamps_to_datetimes(image)
+ return [self._convert_timestamps_to_datetimes(image)
+ for image in self.client.get_images_detailed()]
def show(self, context, image_id):
"""
diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py
index 76f758929..47dd11e5b 100644
--- a/nova/tests/api/openstack/test_images.py
+++ b/nova/tests/api/openstack/test_images.py
@@ -182,8 +182,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
{'id': '23g2ogk23k4hhkk4k42l',
'imageId': '23g2ogk23k4hhkk4k42l',
'name': 'public image #1',
- 'created_at': str(datetime.datetime.utcnow()),
- 'updated_at': str(datetime.datetime.utcnow()),
+ 'created_at': datetime.datetime.utcnow().isoformat(),
+ 'updated_at': datetime.datetime.utcnow().isoformat(),
'deleted_at': None,
'deleted': False,
'is_public': True,
@@ -192,8 +192,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
{'id': 'slkduhfas73kkaskgdas',
'imageId': 'slkduhfas73kkaskgdas',
'name': 'public image #2',
- 'created_at': str(datetime.datetime.utcnow()),
- 'updated_at': str(datetime.datetime.utcnow()),
+ 'created_at': datetime.datetime.utcnow().isoformat(),
+ 'updated_at': datetime.datetime.utcnow().isoformat(),
'deleted_at': None,
'deleted': False,
'is_public': True,
--
cgit
From 25c407b6ade499dd0bdd470e7fd46682c34a98b7 Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Thu, 17 Mar 2011 19:13:09 +0000
Subject: Get the migration out
---
nova/api/openstack/servers.py | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index fd835c247..601a68508 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -20,6 +20,8 @@ import traceback
from webob import exc
from nova import compute
+from nova import context
+from nova import db
from nova import exception
from nova import flags
from nova import log as logging
@@ -61,12 +63,12 @@ def _translate_detail_keys(inst):
for k, v in mapped_keys.iteritems():
inst_dict[k] = inst[v]
- context = req.environ['nova.context'].elevated()
- migration = self.db.migrate_get_by_instance_and_status(context,
- inst['id'], 'finished')
- if migration:
+ ctxt = context.get_admin_context()
+ try:
+ migration = db.migration_get_by_instance_and_status(ctxt,
+ inst['id'], 'finished')
inst_dict['status'] = 'resize-confirm'
- else:
+ except Exception, e:
inst_dict['status'] = power_mapping[inst_dict['status']]
inst_dict['addresses'] = dict(public=[], private=[])
--
cgit
From 2f1a1d293915cde6e15c85e0bb43fb21ae26f7b0 Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Thu, 17 Mar 2011 15:29:54 -0400
Subject: handle create and update requests, and update the base image service
documentation to reflect the (defacto) behavior
---
nova/image/glance.py | 7 +++---
nova/image/service.py | 4 +--
nova/tests/image/test_glance.py | 54 ++++++++++++++++++++++++++++++++++++++++-
3 files changed, 59 insertions(+), 6 deletions(-)
diff --git a/nova/image/glance.py b/nova/image/glance.py
index 55dc5488d..fbb578585 100644
--- a/nova/image/glance.py
+++ b/nova/image/glance.py
@@ -118,7 +118,8 @@ class GlanceImageService(service.BaseImageService):
:raises AlreadyExists if the image already exist.
"""
- return self.client.add_image(metadata, data)
+ return self._convert_timestamps_to_datetimes(
+ self.client.add_image(metadata, data))
def update(self, context, image_id, metadata, data=None):
"""Replace the contents of the given image with the new data.
@@ -127,10 +128,10 @@ class GlanceImageService(service.BaseImageService):
"""
try:
- result = self.client.update_image(image_id, metadata, data)
+ metadata = self.client.update_image(image_id, metadata, data)
except glance_exception.NotFound:
raise exception.NotFound
- return result
+ return self._convert_timestamps_to_datetimes(metadata)
def delete(self, context, image_id):
"""
diff --git a/nova/image/service.py b/nova/image/service.py
index 78d8f33e9..e907381c9 100644
--- a/nova/image/service.py
+++ b/nova/image/service.py
@@ -88,7 +88,7 @@ class BaseImageService(object):
def create(self, context, metadata, data=None):
"""
- Store the image metadata and data and return the new image id.
+ Store the image metadata and data and return the new image metadata.
:raises AlreadyExists if the image already exist.
@@ -96,7 +96,7 @@ class BaseImageService(object):
raise NotImplementedError
def update(self, context, image_id, metadata, data=None):
- """Update the given image with the new metadata and data.
+ """Update the given image metadata and data and return the metadata
:raises NotFound if the image does not exist.
diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py
index 9b17cf261..6e94aa909 100644
--- a/nova/tests/image/test_glance.py
+++ b/nova/tests/image/test_glance.py
@@ -6,8 +6,10 @@ from nova.image import glance
class StubGlanceClient(object):
- def __init__(self, images):
+ def __init__(self, images, add_response=None, update_response=None):
self.images = images
+ self.add_response = add_response
+ self.update_response = update_response
def get_image_meta(self, id):
return self.images[id]
@@ -18,6 +20,12 @@ class StubGlanceClient(object):
def get_image(self, id):
return self.images[id], []
+ def add_image(self, metadata, data):
+ return self.add_response
+
+ def update_image(self, image_id, metadata, data):
+ return self.update_response
+
class NullWriter(object):
@@ -116,3 +124,47 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase):
self.client.images = {'abcd': {'deleted_at': None}}
actual = self.service.get({}, 'abcd', NullWriter())
self.assertEqual(actual['deleted_at'], None)
+
+ def test_create_handles_timestamps(self):
+ now = dt.datetime.utcnow()
+ self.client.add_response = {
+ 'id': 'abcd',
+ 'name': 'blah',
+ 'created_at': now.isoformat(),
+ 'updated_at': now.isoformat(),
+ 'deleted_at': now.isoformat(),
+ }
+ actual = self.service.create({}, {})
+ for attr in ('created_at', 'updated_at', 'deleted_at'):
+ self.assertEqual(actual[attr], now)
+
+ def test_create_handles_deleted_at_none(self):
+ self.client.add_response = {
+ 'id': 'abcd',
+ 'name': 'blah',
+ 'deleted_at': None,
+ }
+ actual = self.service.create({}, {})
+ self.assertEqual(actual['deleted_at'], None)
+
+ def test_update_handles_timestamps(self):
+ now = dt.datetime.utcnow()
+ self.client.update_response = {
+ 'id': 'abcd',
+ 'name': 'blah',
+ 'created_at': now.isoformat(),
+ 'updated_at': now.isoformat(),
+ 'deleted_at': now.isoformat(),
+ }
+ actual = self.service.update({}, 'dummy_id', {})
+ for attr in ('created_at', 'updated_at', 'deleted_at'):
+ self.assertEqual(actual[attr], now)
+
+ def test_create_handles_deleted_at_none(self):
+ self.client.update_response = {
+ 'id': 'abcd',
+ 'name': 'blah',
+ 'deleted_at': None,
+ }
+ actual = self.service.update({}, 'dummy_id', {})
+ self.assertEqual(actual['deleted_at'], None)
--
cgit
From f7d5dea09568c6440918264d97ecdbcc316c0ec4 Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Thu, 17 Mar 2011 15:31:48 -0500
Subject: pep8
---
nova/api/openstack/servers.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index b0e355232..050450457 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -69,7 +69,7 @@ def _translate_detail_keys(inst):
ctxt = context.get_admin_context()
try:
migration = db.migration_get_by_instance_and_status(ctxt,
- inst['id'], 'finished')
+ inst['id'], 'finished')
inst_dict['status'] = 'resize-confirm'
except Exception, e:
inst_dict['status'] = power_mapping[inst_dict['status']]
--
cgit
From b605b53e4b652e0a3f364d505b5fd7240fd4ea36 Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Thu, 17 Mar 2011 20:44:15 +0000
Subject: Test changes
---
nova/tests/api/openstack/test_servers.py | 22 ++++++++++++----------
nova/tests/xenapi/stubs.py | 7 +++++--
2 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py
index 03e00af2a..14b72e097 100644
--- a/nova/tests/api/openstack/test_servers.py
+++ b/nova/tests/api/openstack/test_servers.py
@@ -491,16 +491,6 @@ class ServersTest(test.TestCase):
req.body = json.dumps(body)
res = req.get_response(fakes.wsgi_app())
- def test_server_resize(self):
- body = dict(server=dict(
- name='server_test', imageId=2, flavorId=2, metadata={},
- personality={}))
- req = webob.Request.blank('/v1.0/servers/1/action')
- req.method = 'POST'
- req.content_type = 'application/json'
- req.body = json.dumps(body)
- res = req.get_response(fakes.wsgi_app())
-
def test_delete_server_instance(self):
req = webob.Request.blank('/v1.0/servers/1')
req.method = 'DELETE'
@@ -556,6 +546,18 @@ class ServersTest(test.TestCase):
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
+ def test_resized_server_has_correct_status(self):
+ req = self.webreq('/1', 'GET', dict(resize=dict(flavorId=3)))
+ def fake_migration_get(*args):
+ return {}
+
+ self.stubs.Set(nova.db, 'migration_get_by_instance_and_status',
+ fake_migration_get)
+ res = req.get_response(fakes.wsgi_app())
+ body = json.loads(res.body)
+ self.assertEqual(body['server']['status'], 'resize-confirm')
+
+
def test_confirm_resize_server(self):
req = self.webreq('/1/action', 'POST', dict(confirmResize=None))
diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py
index 70d46a1fb..7f9706a3d 100644
--- a/nova/tests/xenapi/stubs.py
+++ b/nova/tests/xenapi/stubs.py
@@ -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
--
cgit
From 8d5ffa079e768adec969a4e8ab540c24a7faaaa6 Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Thu, 17 Mar 2011 20:45:18 +0000
Subject: Pep8
---
nova/tests/api/openstack/test_servers.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py
index 14b72e097..07ebfdd88 100644
--- a/nova/tests/api/openstack/test_servers.py
+++ b/nova/tests/api/openstack/test_servers.py
@@ -548,6 +548,7 @@ class ServersTest(test.TestCase):
def test_resized_server_has_correct_status(self):
req = self.webreq('/1', 'GET', dict(resize=dict(flavorId=3)))
+
def fake_migration_get(*args):
return {}
@@ -556,7 +557,6 @@ class ServersTest(test.TestCase):
res = req.get_response(fakes.wsgi_app())
body = json.loads(res.body)
self.assertEqual(body['server']['status'], 'resize-confirm')
-
def test_confirm_resize_server(self):
req = self.webreq('/1/action', 'POST', dict(confirmResize=None))
--
cgit
From 2f4c1802c7e482a447d348f049ff429b3d1a640c Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Fri, 18 Mar 2011 16:06:43 -0400
Subject: fix date formatting in images controller show
---
nova/api/openstack/images.py | 6 +++++
nova/tests/api/openstack/fakes.py | 20 +++++++++-----
nova/tests/api/openstack/test_images.py | 46 ++++++++++++++++-----------------
3 files changed, 43 insertions(+), 29 deletions(-)
diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py
index 98f0dd96b..94e05823e 100644
--- a/nova/api/openstack/images.py
+++ b/nova/api/openstack/images.py
@@ -143,6 +143,7 @@ class Controller(wsgi.Controller):
image = self._service.show(req.environ['nova.context'], image_id)
_convert_image_id_to_hash(image)
+ self._format_image_dates(image)
return dict(image=image)
def delete(self, req, id):
@@ -164,3 +165,8 @@ class Controller(wsgi.Controller):
# Users may not modify public images, and that's all that
# we support for now.
raise faults.Fault(exc.HTTPNotFound())
+
+ def _format_image_dates(self, image):
+ for attr in ['created_at', 'updated_at', 'deleted_at']:
+ if image[attr] is not None:
+ image[attr] = image[attr].strftime('%Y-%m-%dT%H:%M:%SZ')
diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py
index 15f8a5b56..9573cf128 100644
--- a/nova/tests/api/openstack/fakes.py
+++ b/nova/tests/api/openstack/fakes.py
@@ -15,6 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
import datetime
import json
import random
@@ -151,22 +152,23 @@ def stub_out_glance(stubs, initial_fixtures=None):
for f in self.fixtures]
def fake_get_images_detailed(self):
- return self.fixtures
+ return copy.deepcopy(self.fixtures)
def fake_get_image_meta(self, image_id):
- for f in self.fixtures:
- if f['id'] == image_id:
- return f
+ image = self._find_image(image_id)
+ if image:
+ return copy.deepcopy(image)
raise glance_exc.NotFound
def fake_add_image(self, image_meta, data=None):
+ image_meta = copy.deepcopy(image_meta)
id = ''.join(random.choice(string.letters) for _ in range(20))
image_meta['id'] = id
self.fixtures.append(image_meta)
return image_meta
def fake_update_image(self, image_id, image_meta, data=None):
- f = self.fake_get_image_meta(image_id)
+ f = self._find_image(image_id)
if not f:
raise glance_exc.NotFound
@@ -174,7 +176,7 @@ def stub_out_glance(stubs, initial_fixtures=None):
return f
def fake_delete_image(self, image_id):
- f = self.fake_get_image_meta(image_id)
+ f = self._find_image(image_id)
if not f:
raise glance_exc.NotFound
@@ -183,6 +185,12 @@ def stub_out_glance(stubs, initial_fixtures=None):
##def fake_delete_all(self):
## self.fixtures = []
+ def _find_image(self, image_id):
+ for f in self.fixtures:
+ if f['id'] == image_id:
+ return f
+ return None
+
GlanceClient = glance_client.Client
fake = FakeGlanceClient(initial_fixtures)
diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py
index 47dd11e5b..b771966f1 100644
--- a/nova/tests/api/openstack/test_images.py
+++ b/nova/tests/api/openstack/test_images.py
@@ -21,7 +21,7 @@ and as a WSGI layer
"""
import json
-import datetime
+import datetime as dt
import shutil
import tempfile
@@ -177,13 +177,13 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
"""Test of the OpenStack API /images application controller"""
# Registered images at start of each test.
-
+ now = dt.datetime.utcnow()
IMAGE_FIXTURES = [
{'id': '23g2ogk23k4hhkk4k42l',
'imageId': '23g2ogk23k4hhkk4k42l',
'name': 'public image #1',
- 'created_at': datetime.datetime.utcnow().isoformat(),
- 'updated_at': datetime.datetime.utcnow().isoformat(),
+ 'created_at': now.isoformat(),
+ 'updated_at': now.isoformat(),
'deleted_at': None,
'deleted': False,
'is_public': True,
@@ -192,8 +192,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
{'id': 'slkduhfas73kkaskgdas',
'imageId': 'slkduhfas73kkaskgdas',
'name': 'public image #2',
- 'created_at': datetime.datetime.utcnow().isoformat(),
- 'updated_at': datetime.datetime.utcnow().isoformat(),
+ 'created_at': now.isoformat(),
+ 'updated_at': now.isoformat(),
'deleted_at': None,
'deleted': False,
'is_public': True,
@@ -235,20 +235,20 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
- def _is_equivalent_subset(x, y):
- if set(x) <= set(y):
- for k, v in x.iteritems():
- if x[k] != y[k]:
- if x[k] == 'active' and y[k] == 'available':
- continue
- return False
- return True
- return False
-
- for image in res_dict['images']:
- for image_fixture in self.IMAGE_FIXTURES:
- if _is_equivalent_subset(image, image_fixture):
- break
- else:
- self.assertEquals(1, 2, "image %s not in fixtures!" %
- str(image))
+ for image in self.IMAGE_FIXTURES:
+ expected = {
+ 'id': abs(hash(image['imageId'])),
+ 'name': image['name'],
+ 'status': 'active',
+ }
+ self.assertTrue(expected in res_dict['images'])
+
+ def test_show_image(self):
+ expected = self.IMAGE_FIXTURES[0]
+ id = abs(hash(expected['id']))
+ expected_time = self.now.strftime('%Y-%m-%dT%H:%M:%SZ')
+ req = webob.Request.blank('/v1.0/images/%s' % id)
+ res = req.get_response(fakes.wsgi_app())
+ actual = json.loads(res.body)['image']
+ self.assertEqual(expected_time, actual['created_at'])
+ self.assertEqual(expected_time, actual['updated_at'])
--
cgit
From 9351bd5538ea0fc0a77c4dee13406ac7a71ca1ae Mon Sep 17 00:00:00 2001
From: Cerberus
Date: Fri, 18 Mar 2011 17:01:44 -0500
Subject: Seriously?
---
nova/virt/xenapi/vmops.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index b27fe2216..4dca26f61 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -383,7 +383,7 @@ class VMOps(object):
#The new disk size must be in bytes
new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024)
- LOG.debug(_("Resizpng VDI %s for instance %s. Expanding to %sGB") %
+ LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %sGB") %
(vdi_uuid, instance.name, instance.local_gb))
vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size)
--
cgit
From a3fe673108602e27cca132209e87369fa8bf1323 Mon Sep 17 00:00:00 2001
From: Tushar Patil
Date: Fri, 18 Mar 2011 19:46:04 -0700
Subject: Changed Copyright to NTT for newly added files for flatmanager ipv6
---
.../versions/012_add_ipv6_flatmanager.py | 2 +-
nova/tests/network/__init__.py | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py b/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py
index 5f5e3d007..8c9cf3377 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py
@@ -1,4 +1,4 @@
-# Copyright 2010 OpenStack LLC.
+# Copyright (c) 2011 NTT.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
diff --git a/nova/tests/network/__init__.py b/nova/tests/network/__init__.py
index e0d479f8c..97f96b6fa 100644
--- a/nova/tests/network/__init__.py
+++ b/nova/tests/network/__init__.py
@@ -1,3 +1,23 @@
+# 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.
+"""
+Utility methods
+"""
import os
from nova import context
--
cgit
From 27ae9700739bd6a1e6f9db90e407f450ff3e770b Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Mon, 21 Mar 2011 16:35:38 -0400
Subject: added licenses
---
nova/tests/image/__init__.py | 17 +++++++++++++++++
nova/tests/image/test_glance.py | 19 +++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/nova/tests/image/__init__.py b/nova/tests/image/__init__.py
index e69de29bb..fae25bca7 100644
--- a/nova/tests/image/__init__.py
+++ b/nova/tests/image/__init__.py
@@ -0,0 +1,17 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 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.
diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py
index 6e94aa909..fcd686c84 100644
--- a/nova/tests/image/test_glance.py
+++ b/nova/tests/image/test_glance.py
@@ -1,3 +1,22 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 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.
+
+
import datetime as dt
import unittest
--
cgit
From 414c615a3ac2e61f312f8383f764114e7d782de1 Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Mon, 21 Mar 2011 16:40:26 -0400
Subject: fix licenses
---
nova/tests/image/__init__.py | 3 +--
nova/tests/image/test_glance.py | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/nova/tests/image/__init__.py b/nova/tests/image/__init__.py
index fae25bca7..b94e2e54e 100644
--- a/nova/tests/image/__init__.py
+++ b/nova/tests/image/__init__.py
@@ -1,7 +1,6 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2011 United States Government as represented by the
-# Administrator of the National Aeronautics and Space Administration.
+# Copyright 2011 Openstack LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py
index fcd686c84..d49b3dfdb 100644
--- a/nova/tests/image/test_glance.py
+++ b/nova/tests/image/test_glance.py
@@ -1,7 +1,6 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2011 United States Government as represented by the
-# Administrator of the National Aeronautics and Space Administration.
+# Copyright 2011 Openstack LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
--
cgit
From 39783f386a473ed28c786bb72a29e8403503c40c Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Mon, 21 Mar 2011 17:09:53 -0400
Subject: make bcwaldon happy
---
nova/api/openstack/images.py | 2 +-
nova/image/glance.py | 6 +++---
nova/tests/api/openstack/test_images.py | 4 ++--
nova/tests/image/test_glance.py | 8 ++++----
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py
index 94e05823e..99c14275a 100644
--- a/nova/api/openstack/images.py
+++ b/nova/api/openstack/images.py
@@ -168,5 +168,5 @@ class Controller(wsgi.Controller):
def _format_image_dates(self, image):
for attr in ['created_at', 'updated_at', 'deleted_at']:
- if image[attr] is not None:
+ if image.get(attr) is not None:
image[attr] = image[attr].strftime('%Y-%m-%dT%H:%M:%SZ')
diff --git a/nova/image/glance.py b/nova/image/glance.py
index fbb578585..171b28fde 100644
--- a/nova/image/glance.py
+++ b/nova/image/glance.py
@@ -18,7 +18,7 @@
from __future__ import absolute_import
-import datetime as dt
+import datetime
from glance.common import exception as glance_exception
@@ -73,7 +73,7 @@ class GlanceImageService(service.BaseImageService):
Returns image with known timestamp fields converted to datetime objects
"""
for attr in ['created_at', 'updated_at', 'deleted_at']:
- if attr in image and image[attr] is not None:
+ if image.get(attr) is not None:
image[attr] = self._parse_glance_iso8601_timestamp(image[attr])
return image
@@ -81,7 +81,7 @@ class GlanceImageService(service.BaseImageService):
"""
Parse a subset of iso8601 timestamps into datetime objects
"""
- return dt.datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%f")
+ return datetime.datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%f")
def show_by_name(self, context, name):
"""
diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py
index b771966f1..a866c764d 100644
--- a/nova/tests/api/openstack/test_images.py
+++ b/nova/tests/api/openstack/test_images.py
@@ -21,7 +21,7 @@ and as a WSGI layer
"""
import json
-import datetime as dt
+import datetime
import shutil
import tempfile
@@ -177,7 +177,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
"""Test of the OpenStack API /images application controller"""
# Registered images at start of each test.
- now = dt.datetime.utcnow()
+ now = datetime.datetime.utcnow()
IMAGE_FIXTURES = [
{'id': '23g2ogk23k4hhkk4k42l',
'imageId': '23g2ogk23k4hhkk4k42l',
diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py
index d49b3dfdb..30021dbc1 100644
--- a/nova/tests/image/test_glance.py
+++ b/nova/tests/image/test_glance.py
@@ -58,12 +58,12 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase):
self.service = glance.GlanceImageService(self.client)
def test_show_passes_through_to_client(self):
- self.client.images = {'xyz': "image"}
- self.assertEqual(self.service.show({}, 'xyz'), "image")
+ self.client.images = {'xyz': {'foo': 'bar'}}
+ self.assertEqual(self.service.show({}, 'xyz'), {'foo': 'bar'})
def test_detail_passes_through_to_client(self):
- self.client.images = {1: "an image"}
- self.assertEqual(list(self.service.detail({})), ["an image"])
+ self.client.images = {1: {'foo': 'bar'}}
+ self.assertEqual(list(self.service.detail({})), [{'foo': 'bar'}])
def test_show_makes_create_datetimes(self):
create_time = dt.datetime.utcnow()
--
cgit
From 0cff0a13bac3539a46b3b932bfd016df7f190196 Mon Sep 17 00:00:00 2001
From: Vishvananda Ishaya
Date: Mon, 21 Mar 2011 14:20:13 -0700
Subject: import greenthread in libvirt
---
nova/virt/libvirt_conn.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py
index e80b9fbdf..f57f1a675 100644
--- a/nova/virt/libvirt_conn.py
+++ b/nova/virt/libvirt_conn.py
@@ -46,10 +46,9 @@ import time
import uuid
from xml.dom import minidom
-
+from eventlet import greenthread
from eventlet import tpool
from eventlet import semaphore
-
import IPy
from nova import context
--
cgit
From e1b9db2ac1af8f38084f9794a430e0292f110ed6 Mon Sep 17 00:00:00 2001
From: Mark Washenberger
Date: Mon, 21 Mar 2011 17:23:36 -0400
Subject: get rid of another datetime alias
---
nova/tests/image/test_glance.py | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py
index 30021dbc1..f1f8504f3 100644
--- a/nova/tests/image/test_glance.py
+++ b/nova/tests/image/test_glance.py
@@ -16,7 +16,7 @@
# under the License.
-import datetime as dt
+import datetime
import unittest
from nova.image import glance
@@ -66,7 +66,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase):
self.assertEqual(list(self.service.detail({})), [{'foo': 'bar'}])
def test_show_makes_create_datetimes(self):
- create_time = dt.datetime.utcnow()
+ create_time = datetime.datetime.utcnow()
self.client.images = {'xyz': {
'id': "id",
'name': "my awesome image",
@@ -76,7 +76,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase):
self.assertEqual(actual['created_at'], create_time)
def test_show_makes_update_datetimes(self):
- update_time = dt.datetime.utcnow()
+ update_time = datetime.datetime.utcnow()
self.client.images = {'abc': {
'id': "id",
'name': "my okay image",
@@ -86,7 +86,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase):
self.assertEqual(actual['updated_at'], update_time)
def test_show_makes_delete_datetimes(self):
- delete_time = dt.datetime.utcnow()
+ delete_time = datetime.datetime.utcnow()
self.client.images = {'123': {
'id': "123",
'name': "my lame image",
@@ -105,7 +105,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase):
self.assertEqual(actual['deleted_at'], None)
def test_detail_handles_timestamps(self):
- now = dt.datetime.utcnow()
+ now = datetime.datetime.utcnow()
image1 = {
'id': 1,
'name': 'image 1',
@@ -126,7 +126,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase):
self.assertEqual(i2['deleted_at'], now)
def test_get_handles_timestamps(self):
- now = dt.datetime.utcnow()
+ now = datetime.datetime.utcnow()
self.client.images = {'abcd': {
'id': 'abcd',
'name': 'nifty image',
@@ -144,7 +144,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase):
self.assertEqual(actual['deleted_at'], None)
def test_create_handles_timestamps(self):
- now = dt.datetime.utcnow()
+ now = datetime.datetime.utcnow()
self.client.add_response = {
'id': 'abcd',
'name': 'blah',
@@ -166,7 +166,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase):
self.assertEqual(actual['deleted_at'], None)
def test_update_handles_timestamps(self):
- now = dt.datetime.utcnow()
+ now = datetime.datetime.utcnow()
self.client.update_response = {
'id': 'abcd',
'name': 'blah',
--
cgit
From 4b8ed5afd1fd3e616eda0015f9bf16c7097f5476 Mon Sep 17 00:00:00 2001
From: Todd Willey
Date: Tue, 22 Mar 2011 03:13:12 -0400
Subject: vpn changes
---
nova/api/ec2/admin.py | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py
index d9a4ef999..208fe5c4f 100644
--- a/nova/api/ec2/admin.py
+++ b/nova/api/ec2/admin.py
@@ -28,6 +28,7 @@ from nova import exception
from nova import flags
from nova import log as logging
from nova import utils
+from nova.api.ec2 import ec2utils
from nova.auth import manager
@@ -92,15 +93,18 @@ def vpn_dict(project, vpn_instance):
'public_ip': project.vpn_ip,
'public_port': project.vpn_port}
if vpn_instance:
- rv['instance_id'] = vpn_instance['ec2_id']
+ rv['instance_id'] = ec2utils.id_to_ec2_id(vpn_instance['id'])
rv['created_at'] = utils.isotime(vpn_instance['created_at'])
address = vpn_instance.get('fixed_ip', None)
if address:
rv['internal_ip'] = address['address']
- if utils.vpn_ping(project.vpn_ip, project.vpn_port):
- rv['state'] = 'running'
+ if project.vpn_ip and project.vpn_port:
+ if utils.vpn_ping(project.vpn_ip, project.vpn_port):
+ rv['state'] = 'running'
+ else:
+ rv['state'] = 'down'
else:
- rv['state'] = 'down'
+ rv['state'] = 'down - invalid project vpn config'
else:
rv['state'] = 'pending'
return rv
@@ -279,7 +283,7 @@ class AdminController(object):
", ensure it isn't running, and try "
"again in a few minutes")
instance = self._vpn_for(context, project)
- return {'instance_id': instance['ec2_id']}
+ return {'instance_id': ec2utils.id_to_ec2_id(instance['id'])}
def describe_vpns(self, context):
vpns = []
--
cgit
From e827b8dbae1faef2cc070c7e26395979571bcd46 Mon Sep 17 00:00:00 2001
From: Hisaharu Ishii
Date: Tue, 22 Mar 2011 20:27:51 +0900
Subject: Wrap update_ra in utils.synchronized.
---
nova/network/linux_net.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py
index ee36407a6..e283dee37 100644
--- a/nova/network/linux_net.py
+++ b/nova/network/linux_net.py
@@ -595,6 +595,7 @@ def update_dhcp(context, network_id):
_execute(*command, addl_env=env)
+@utils.synchronized('radvd_start')
def update_ra(context, network_id):
network_ref = db.network_get(context, network_id)
--
cgit
From e648698bd171357228881a10d76e7853938e8feb Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Tue, 22 Mar 2011 17:00:36 +0000
Subject: Fix
---
nova/tests/test_localization.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/nova/tests/test_localization.py b/nova/tests/test_localization.py
index 393d71038..132a308fd 100644
--- a/nova/tests/test_localization.py
+++ b/nova/tests/test_localization.py
@@ -21,9 +21,9 @@ 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")
--
cgit
From 116c0d52d21ebd6ed55a61467aac5d8c06a4b086 Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Tue, 22 Mar 2011 17:46:17 +0000
Subject: Merge stuff
---
nova/api/openstack/servers.py | 4 ++--
nova/api/openstack/views/servers.py | 5 +++--
nova/compute/api.py | 8 ++++----
nova/db/sqlalchemy/api.py | 4 ++--
nova/virt/xenapi/vmops.py | 4 ++--
5 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index db5942e92..f3367e118 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -36,7 +36,7 @@ from nova.api.openstack.views import addresses as addresses_views
from nova.auth import manager as auth_manager
from nova.compute import instance_types
from nova.compute import power_state
-prom nova.quota import QuotaError
+from nova.quota import QuotaError
import nova.api.openstack
@@ -44,7 +44,7 @@ LOG = logging.getLogger('server')
FLAGS = flags.FLAGS
-plass Controller(wsgi.Controller):
+class Controller(wsgi.Controller):
""" The Server API controller for the OpenStack API """
_serialization_metadata = {
diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py
index 6d54a7a7e..9fd25999a 100644
--- a/nova/api/openstack/views/servers.py
+++ b/nova/api/openstack/views/servers.py
@@ -89,8 +89,9 @@ class ViewBuilder(object):
migration = db.migration_get_by_instance_and_status(ctxt,
inst['id'], 'finished')
inst_dict['status'] = 'resize-confirm'
- except Exception, e:
- inst_dict['status'] = power_mapping[inst_dict['status']]
+ except:
+ pass
+
inst_dict['addresses'] = self.addresses_builder.build(inst)
# Return the metadata as a dictionary
diff --git a/nova/compute/api.py b/nova/compute/api.py
index dbf99e7c5..748aba004 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -489,15 +489,15 @@ class API(base.Base):
def resize(self, context, instance_id, flavor_id):
"""Resize a running instance."""
instance = self.db.instance_get(context, instance_id)
- LOG.debug(_("Resizing instance %(instance_type['name'] to flavor"
- "%(flavor_id)") % locals())
current_instance_type = self.db.instance_type_get_by_name(
context, instance['instance_type'])
new_instance_type = self.db.instance_type_get_by_flavor_id(
context, flavor_id)
- LOG.debug(_("Old instance type %s -> New instance type %s"),
- (current_instance_type['name'], new_instance_type['name']))
+ current_instance_type_name = current_instance_type['name']
+ new_instance_type_name = new_instance_type['name']
+ LOG.debug(_("Old instance type %(current_instance_type_name)s, "
+ " new instance type %(new_instance_type_name)s") % locals())
if not new_instance_type:
raise exception.ApiError(_("Requested flavor does not exist"))
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index ac7f7cbf1..98810cb48 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -2220,8 +2220,8 @@ def migration_get_by_instance_and_status(context, instance_id, status):
filter_by(instance_id=instance_id).\
filter_by(status=status).first()
if not result:
- raise exception.NotFound(_("No migration found for instance %s"
- "with status %s" % (instance_id, status)))
+ raise exception.NotFound(_("No migration found for instance "
+ "%(instance_id) with status %(status)") % locals())
return result
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 1f5d2d155..c1a65c997 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -387,8 +387,8 @@ class VMOps(object):
#The new disk size must be in bytes
new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024)
- LOG.debug(_("Resizing VDI %s for instance %s. Expanding to %sGB"),
- (vdi_uuid, instance.name, instance.local_gb))
+ LOG.debug(_("Resizing VDI %(vdi_uuid) for instance %(instance.name). "
+ "Expanding to %(instance.local_gb)GB") % locals())
vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size)
LOG.debug(_("Resize instance %s complete") % (instance.name))
--
cgit
From 3b3889a19c4efa8dc917f772613543780f361df3 Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Tue, 22 Mar 2011 17:55:40 +0000
Subject: tweak
---
nova/virt/xenapi/vmops.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index c1a65c997..8ac944966 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -387,8 +387,8 @@ class VMOps(object):
#The new disk size must be in bytes
new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024)
- LOG.debug(_("Resizing VDI %(vdi_uuid) for instance %(instance.name). "
- "Expanding to %(instance.local_gb)GB") % locals())
+ LOG.debug(_("Resizing VDI %(vdi_uuid) for instance %(instance.name)s. "
+ "Expanding to %(instance.local_gb)f GB") % locals())
vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size)
LOG.debug(_("Resize instance %s complete") % (instance.name))
--
cgit
From 4c76bcc12954734d19afcb5e4519e35c23e39d6d Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Tue, 22 Mar 2011 18:04:09 +0000
Subject: tweak
---
nova/virt/xenapi/vmops.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 8ac944966..383096d63 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -387,8 +387,10 @@ class VMOps(object):
#The new disk size must be in bytes
new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024)
- LOG.debug(_("Resizing VDI %(vdi_uuid) for instance %(instance.name)s. "
- "Expanding to %(instance.local_gb)f GB") % locals())
+ instance_name = instance.name
+ instance_local_gb = instance.local_gb
+ LOG.debug(_("Resizing VDI %(vdi_uuid)s for instance %(instance_name)s."
+ " Expanding to %(instance_local_gb)d GB") % locals())
vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size)
LOG.debug(_("Resize instance %s complete") % (instance.name))
--
cgit
From 8792383dfbd630388e6a51a76910e73203a3793f Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Tue, 22 Mar 2011 18:24:00 +0000
Subject: Tweak
---
nova/api/openstack/views/servers.py | 4 ++++
.../sqlalchemy/migrate_repo/versions/012_add_flavors_to_migrations.py | 1 +
nova/tests/test_localization.py | 1 +
3 files changed, 6 insertions(+)
diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py
index 9fd25999a..709052f22 100644
--- a/nova/api/openstack/views/servers.py
+++ b/nova/api/openstack/views/servers.py
@@ -16,7 +16,10 @@
# under the License.
import hashlib
+
from nova.compute import power_state
+import nova.context
+from nova import db
from nova.api.openstack import common
from nova.api.openstack.views import addresses as addresses_view
from nova.api.openstack.views import flavors as flavors_view
@@ -86,6 +89,7 @@ class ViewBuilder(object):
inst_dict['status'] = power_mapping[inst_dict['status']]
try:
+ ctxt = nova.context.get_admin_context()
migration = db.migration_get_by_instance_and_status(ctxt,
inst['id'], 'finished')
inst_dict['status'] = 'resize-confirm'
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/012_add_flavors_to_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/012_add_flavors_to_migrations.py
index e677ba14d..3fb92e85c 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/012_add_flavors_to_migrations.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/012_add_flavors_to_migrations.py
@@ -43,6 +43,7 @@ def upgrade(migrate_engine):
migrations.create_column(old_flavor_id)
migrations.create_column(new_flavor_id)
+
def downgrade(migrate_engine):
meta.bind = migrate_engine
migrations.drop_column(old_flavor_id)
diff --git a/nova/tests/test_localization.py b/nova/tests/test_localization.py
index 132a308fd..a25809a79 100644
--- a/nova/tests/test_localization.py
+++ b/nova/tests/test_localization.py
@@ -23,6 +23,7 @@ import unittest
import nova
from nova import test
+
class LocalizationTestCase(test.TestCase):
def test_multiple_positional_format_placeholders(self):
pat = re.compile("\W_\(")
--
cgit
From d06bce4b64b57551a722688a4038a4eaffa34278 Mon Sep 17 00:00:00 2001
From: Todd Willey
Date: Tue, 22 Mar 2011 16:34:02 -0400
Subject: typo fix.
---
nova/api/ec2/admin.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py
index d9a4ef999..f32d0804f 100644
--- a/nova/api/ec2/admin.py
+++ b/nova/api/ec2/admin.py
@@ -60,7 +60,7 @@ def project_dict(project):
def host_dict(host, compute_service, instances, volume_service, volumes, now):
"""Convert a host model object to a result dict"""
- rv = {'hostanme': host, 'instance_count': len(instances),
+ rv = {'hostname': host, 'instance_count': len(instances),
'volume_count': len(volumes)}
if compute_service:
latest = compute_service['updated_at'] or compute_service['created_at']
--
cgit
From 0dc2140d645d94d585fa8e3e5d189cd776574d28 Mon Sep 17 00:00:00 2001
From: Koji Iida
Date: Wed, 23 Mar 2011 13:14:54 +0900
Subject: Fix to avoid db migration failure in virtualenv
---
nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py b/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py
index 8c9cf3377..e87085668 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/012_add_ipv6_flatmanager.py
@@ -26,6 +26,9 @@ meta = MetaData()
# Just for the ForeignKey and column creation to succeed, these are not the
# actual definitions of instances or services.
#
+instances = Table('instances', meta,
+ Column('id', Integer(), primary_key=True, nullable=False),
+ )
#
# Tables to alter
--
cgit
From 846b09925da07c2858052143d5fff4766a782cf1 Mon Sep 17 00:00:00 2001
From: Anthony Young
Date: Tue, 22 Mar 2011 22:54:34 -0700
Subject: Fix for lp740742 - format describe_instance_output correctly to
prevent errors in dashboard
---
nova/api/ec2/admin.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py
index 037184b40..d8d90ad83 100644
--- a/nova/api/ec2/admin.py
+++ b/nova/api/ec2/admin.py
@@ -120,7 +120,8 @@ class AdminController(object):
def describe_instance_types(self, context, **_kwargs):
"""Returns all active instance types data (vcpus, memory, etc.)"""
- return {'instanceTypeSet': [db.instance_type_get_all(context)]}
+ return {'instanceTypeSet': [instance_dict(v) for v in
+ db.instance_type_get_all(context).values()]}
def describe_user(self, _context, name, **_kwargs):
"""Returns user data, including access and secret keys."""
--
cgit
From 3362be7e9f2feda33e14ab4fb7c6f70277df1cf5 Mon Sep 17 00:00:00 2001
From: Salvatore Orlando
Date: Wed, 23 Mar 2011 12:53:10 +0000
Subject: Checking whether cidr_v6 is not null before populating ipv6 key in
network info map (VMOps._get_network_info)
---
nova/virt/xenapi/vmops.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 499c6d8a1..b51489ebc 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -723,8 +723,9 @@ class VMOps(object):
'mac': instance.mac_address,
'rxtx_cap': flavor['rxtx_cap'],
'dns': [network['dns']],
- 'ips': [ip_dict(ip) for ip in network_IPs],
- 'ip6s': [ip6_dict(ip) for ip in network_IPs]}
+ 'ips': [ip_dict(ip) for ip in network_IPs]}
+ if network['cidr_v6']:
+ info['ip6s'] = [ip6_dict(ip) for ip in network_IPs]
network_info.append((network, info))
return network_info
--
cgit
From c3d47689a762bfa4aa38c7d4700bb1969d37d1d1 Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Wed, 23 Mar 2011 18:56:23 +0000
Subject: merge prop changes
---
nova/api/openstack/views/servers.py | 9 +++------
nova/compute/api.py | 13 ++++++++++++-
nova/compute/manager.py | 8 ++++----
3 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py
index 709052f22..a21a6e7ff 100644
--- a/nova/api/openstack/views/servers.py
+++ b/nova/api/openstack/views/servers.py
@@ -18,6 +18,7 @@
import hashlib
from nova.compute import power_state
+import nova.compute.api
import nova.context
from nova import db
from nova.api.openstack import common
@@ -87,14 +88,10 @@ class ViewBuilder(object):
for k, v in mapped_keys.iteritems():
inst_dict[k] = inst[v]
+ ctxt = nova.context.get_admin_context()
inst_dict['status'] = power_mapping[inst_dict['status']]
- try:
- ctxt = nova.context.get_admin_context()
- migration = db.migration_get_by_instance_and_status(ctxt,
- inst['id'], 'finished')
+ if nova.compute.api.has_finished_migration(ctxt, inst['id']):
inst_dict['status'] = 'resize-confirm'
- except:
- pass
inst_dict['addresses'] = self.addresses_builder.build(inst)
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 748aba004..78110c048 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -253,6 +253,16 @@ class API(base.Base):
return [dict(x.iteritems()) for x in instances]
+ def has_finished_migration(self, context, instance_id):
+ """Retrieves whether or not a finished migration exists for
+ an instance"""
+ try:
+ db.migration_get_by_instance_and_status(ctxt, inst['id'],
+ 'finished')
+ return True
+ except Exception, e:
+ return False
+
def ensure_default_security_group(self, context):
""" Create security group for the security context if it
does not already exist
@@ -499,7 +509,8 @@ class API(base.Base):
LOG.debug(_("Old instance type %(current_instance_type_name)s, "
" new instance type %(new_instance_type_name)s") % locals())
if not new_instance_type:
- raise exception.ApiError(_("Requested flavor does not exist"))
+ raise exception.ApiError(_("Requested flavor %(flavor_id)d "
+ "does not exist") % locals())
if current_instance_type['memory_mb'] >= \
new_instance_type['memory_mb']:
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 78ef33ac2..ac63f68ea 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -458,8 +458,8 @@ class ComputeManager(manager.Manager):
instance_type = self.db.instance_type_get_by_flavor_id(context,
migration_ref['old_flavor_id'])
- #Just roll back the record. There's no need to resize down since
- #the 'old' VM already has the preferred attributes
+ # Just roll back the record. There's no need to resize down since
+ # the 'old' VM already has the preferred attributes
self.db.instance_update(context, instance_id,
dict(memory_mb=instance_type['memory_mb'],
vcpus=instance_type['vcpus'],
@@ -536,8 +536,8 @@ class ComputeManager(manager.Manager):
migration_ref = self.db.migration_get(context, migration_id)
instance_ref = self.db.instance_get(context,
migration_ref['instance_id'])
- #TODO(mdietz): apply the rest of the instance_type attributes going
- #after they're supported
+ # TODO(mdietz): apply the rest of the instance_type attributes going
+ # after they're supported
instance_type = self.db.instance_type_get_by_flavor_id(context,
migration_ref['new_flavor_id'])
self.db.instance_update(context, instance_id,
--
cgit
From 1aa576ee43cdf6520df6b5c8429f8d426bafc72a Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Wed, 23 Mar 2011 18:59:24 +0000
Subject: Moving the migration yet again
---
.../versions/012_add_flavors_to_migrations.py | 50 ----------------------
.../versions/013_add_flavors_to_migrations.py | 50 ++++++++++++++++++++++
2 files changed, 50 insertions(+), 50 deletions(-)
delete mode 100644 nova/db/sqlalchemy/migrate_repo/versions/012_add_flavors_to_migrations.py
create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/013_add_flavors_to_migrations.py
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/012_add_flavors_to_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/012_add_flavors_to_migrations.py
deleted file mode 100644
index 3fb92e85c..000000000
--- a/nova/db/sqlalchemy/migrate_repo/versions/012_add_flavors_to_migrations.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 OpenStack LLC.
-# 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.from sqlalchemy import *
-
-from sqlalchemy import *
-from migrate import *
-
-from nova import log as logging
-
-
-meta = MetaData()
-
-migrations = Table('migrations', meta,
- Column('id', Integer(), primary_key=True, nullable=False),
- )
-
-#
-# Tables to alter
-#
-#
-
-old_flavor_id = Column('old_flavor_id', Integer())
-new_flavor_id = Column('new_flavor_id', Integer())
-
-
-def upgrade(migrate_engine):
- # Upgrade operations go here. Don't create your own engine;
- # bind migrate_engine to your metadata
- meta.bind = migrate_engine
- migrations.create_column(old_flavor_id)
- migrations.create_column(new_flavor_id)
-
-
-def downgrade(migrate_engine):
- meta.bind = migrate_engine
- migrations.drop_column(old_flavor_id)
- migrations.drop_column(new_flavor_id)
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/013_add_flavors_to_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/013_add_flavors_to_migrations.py
new file mode 100644
index 000000000..3fb92e85c
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/013_add_flavors_to_migrations.py
@@ -0,0 +1,50 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 OpenStack LLC.
+# 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.from sqlalchemy import *
+
+from sqlalchemy import *
+from migrate import *
+
+from nova import log as logging
+
+
+meta = MetaData()
+
+migrations = Table('migrations', meta,
+ Column('id', Integer(), primary_key=True, nullable=False),
+ )
+
+#
+# Tables to alter
+#
+#
+
+old_flavor_id = Column('old_flavor_id', Integer())
+new_flavor_id = Column('new_flavor_id', Integer())
+
+
+def upgrade(migrate_engine):
+ # Upgrade operations go here. Don't create your own engine;
+ # bind migrate_engine to your metadata
+ meta.bind = migrate_engine
+ migrations.create_column(old_flavor_id)
+ migrations.create_column(new_flavor_id)
+
+
+def downgrade(migrate_engine):
+ meta.bind = migrate_engine
+ migrations.drop_column(old_flavor_id)
+ migrations.drop_column(new_flavor_id)
--
cgit
From 5a5c7d22e7a00c9a3b34f8c08db70b644eee2d92 Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Wed, 23 Mar 2011 19:16:03 +0000
Subject: Unit test cleanup
---
nova/api/openstack/views/servers.py | 5 +++--
nova/compute/api.py | 2 +-
nova/db/sqlalchemy/api.py | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py
index a21a6e7ff..18d31a29d 100644
--- a/nova/api/openstack/views/servers.py
+++ b/nova/api/openstack/views/servers.py
@@ -18,7 +18,7 @@
import hashlib
from nova.compute import power_state
-import nova.compute.api
+import nova.compute
import nova.context
from nova import db
from nova.api.openstack import common
@@ -90,7 +90,8 @@ class ViewBuilder(object):
ctxt = nova.context.get_admin_context()
inst_dict['status'] = power_mapping[inst_dict['status']]
- if nova.compute.api.has_finished_migration(ctxt, inst['id']):
+ compute_api = nova.compute.API()
+ if compute_api.has_finished_migration(ctxt, inst['id']):
inst_dict['status'] = 'resize-confirm'
inst_dict['addresses'] = self.addresses_builder.build(inst)
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 78110c048..c2738f6f5 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -257,7 +257,7 @@ class API(base.Base):
"""Retrieves whether or not a finished migration exists for
an instance"""
try:
- db.migration_get_by_instance_and_status(ctxt, inst['id'],
+ db.migration_get_by_instance_and_status(context, instance_id,
'finished')
return True
except Exception, e:
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index 98810cb48..d7b5aff46 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -2221,7 +2221,7 @@ def migration_get_by_instance_and_status(context, instance_id, status):
filter_by(status=status).first()
if not result:
raise exception.NotFound(_("No migration found for instance "
- "%(instance_id) with status %(status)") % locals())
+ "%(instance_id)s with status %(status)s") % locals())
return result
--
cgit
From 8eab4f6ecaf51221b335e76d9e532a1f159c2f2d Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Wed, 23 Mar 2011 19:44:32 +0000
Subject: Forgot extraneous module import
---
nova/api/openstack/servers.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index f3367e118..d392ab57f 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -23,7 +23,6 @@ from webob import exc
from nova import compute
from nova import context
-from nova import db
from nova import exception
from nova import flags
from nova import log as logging
--
cgit
From 0218a11bb1d5275d5b99c98aea1edba0f45f56e2 Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Wed, 23 Mar 2011 19:48:26 +0000
Subject: Forgot extraneous module import again
---
nova/api/openstack/views/servers.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py
index 18d31a29d..68f712e56 100644
--- a/nova/api/openstack/views/servers.py
+++ b/nova/api/openstack/views/servers.py
@@ -20,7 +20,6 @@ import hashlib
from nova.compute import power_state
import nova.compute
import nova.context
-from nova import db
from nova.api.openstack import common
from nova.api.openstack.views import addresses as addresses_view
from nova.api.openstack.views import flavors as flavors_view
--
cgit
From 98b4f0924257dcfa12e4881950472e983f08ef1d Mon Sep 17 00:00:00 2001
From: "matt.dietz@rackspace.com" <>
Date: Wed, 23 Mar 2011 21:04:42 +0000
Subject: merge prop fixes
---
nova/compute/api.py | 10 +++++++---
nova/tests/test_compute.py | 14 +++++++++++++-
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/nova/compute/api.py b/nova/compute/api.py
index c2738f6f5..01eead4ac 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -260,7 +260,7 @@ class API(base.Base):
db.migration_get_by_instance_and_status(context, instance_id,
'finished')
return True
- except Exception, e:
+ except exception.NotFound:
return False
def ensure_default_security_group(self, context):
@@ -512,10 +512,14 @@ class API(base.Base):
raise exception.ApiError(_("Requested flavor %(flavor_id)d "
"does not exist") % locals())
- if current_instance_type['memory_mb'] >= \
- new_instance_type['memory_mb']:
+ current_memory_mb = current_instance_type['memory_mb']
+ new_memory_mb = new_instance_type['memory_mb']
+ if current_memory_mb > new_memory_mb:
raise exception.ApiError(_("Invalid flavor: cannot downsize"
"instances"))
+ if current_memory_mb == new_memory_mb:
+ raise exception.ApiError(_("Invalid flavor: cannot use"
+ "the same flavor. "))
self._cast_scheduler_message(context,
{"method": "prep_resize",
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index 444be5dd8..44d04a12f 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -336,7 +336,7 @@ class ComputeTestCase(test.TestCase):
self.compute.terminate_instance(context, instance_id)
def test_resize_down_fails(self):
- """Ensure invalid flavors raise"""
+ """Ensure resizing down raises and fails"""
context = self.context.elevated()
instance_id = self._create_instance()
@@ -349,6 +349,18 @@ class ComputeTestCase(test.TestCase):
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')
--
cgit