fix up tests
This commit is contained in:
		@@ -23,6 +23,7 @@ include nova/compute/interfaces.template
 | 
			
		||||
include nova/console/xvp.conf.template
 | 
			
		||||
include nova/db/sqlalchemy/migrate_repo/migrate.cfg
 | 
			
		||||
include nova/db/sqlalchemy/migrate_repo/README
 | 
			
		||||
include nova/db/sqlalchemy/migrate_repo/versions/*.sql
 | 
			
		||||
include nova/virt/interfaces.template
 | 
			
		||||
include nova/virt/libvirt*.xml.template
 | 
			
		||||
include nova/virt/cpuinfo.xml.template
 | 
			
		||||
 
 | 
			
		||||
@@ -59,14 +59,12 @@ def add_lease(mac, ip_address, _hostname, _interface):
 | 
			
		||||
        LOG.debug(_("leasing ip"))
 | 
			
		||||
        network_manager = utils.import_object(FLAGS.network_manager)
 | 
			
		||||
        network_manager.lease_fixed_ip(context.get_admin_context(),
 | 
			
		||||
                                       mac,
 | 
			
		||||
                                       ip_address)
 | 
			
		||||
    else:
 | 
			
		||||
        rpc.cast(context.get_admin_context(),
 | 
			
		||||
                 "%s.%s" % (FLAGS.network_topic, FLAGS.host),
 | 
			
		||||
                 {"method": "lease_fixed_ip",
 | 
			
		||||
                  "args": {"mac": mac,
 | 
			
		||||
                           "address": ip_address}})
 | 
			
		||||
                  "args": {"address": ip_address}})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def old_lease(mac, ip_address, hostname, interface):
 | 
			
		||||
@@ -81,14 +79,12 @@ def del_lease(mac, ip_address, _hostname, _interface):
 | 
			
		||||
        LOG.debug(_("releasing ip"))
 | 
			
		||||
        network_manager = utils.import_object(FLAGS.network_manager)
 | 
			
		||||
        network_manager.release_fixed_ip(context.get_admin_context(),
 | 
			
		||||
                                         mac,
 | 
			
		||||
                                         ip_address)
 | 
			
		||||
    else:
 | 
			
		||||
        rpc.cast(context.get_admin_context(),
 | 
			
		||||
                 "%s.%s" % (FLAGS.network_topic, FLAGS.host),
 | 
			
		||||
                 {"method": "release_fixed_ip",
 | 
			
		||||
                  "args": {"mac": mac,
 | 
			
		||||
                           "address": ip_address}})
 | 
			
		||||
                  "args": {"address": ip_address}})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def init_leases(interface):
 | 
			
		||||
 
 | 
			
		||||
@@ -172,17 +172,23 @@ class VpnCommands(object):
 | 
			
		||||
    def change(self, project_id, ip, port):
 | 
			
		||||
        """Change the ip and port for a vpn.
 | 
			
		||||
 | 
			
		||||
        this will update all networks associated with a project
 | 
			
		||||
        not sure if that's the desired behavior or not, patches accepted
 | 
			
		||||
 | 
			
		||||
        args: project, ip, port"""
 | 
			
		||||
        # TODO(tr3buchet): perhaps this shouldn't update all networks
 | 
			
		||||
        # associated with a project in the future
 | 
			
		||||
        project = self.manager.get_project(project_id)
 | 
			
		||||
        if not project:
 | 
			
		||||
            print 'No project %s' % (project_id)
 | 
			
		||||
            return
 | 
			
		||||
        admin = context.get_admin_context()
 | 
			
		||||
        network_ref = db.project_get_network(admin, project_id)
 | 
			
		||||
        db.network_update(admin,
 | 
			
		||||
                          network_ref['id'],
 | 
			
		||||
                          {'vpn_public_address': ip,
 | 
			
		||||
                           'vpn_public_port': int(port)})
 | 
			
		||||
        admin_context = context.get_admin_context()
 | 
			
		||||
        networks = db.project_get_networks(admin_context, project_id)
 | 
			
		||||
        for network in networks:
 | 
			
		||||
            db.network_update(admin_context,
 | 
			
		||||
                              network['id'],
 | 
			
		||||
                              {'vpn_public_address': ip,
 | 
			
		||||
                               'vpn_public_port': int(port)})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ShellCommands(object):
 | 
			
		||||
@@ -446,12 +452,13 @@ class ProjectCommands(object):
 | 
			
		||||
    def scrub(self, project_id):
 | 
			
		||||
        """Deletes data associated with project
 | 
			
		||||
        arguments: project_id"""
 | 
			
		||||
        ctxt = context.get_admin_context()
 | 
			
		||||
        network_ref = db.project_get_network(ctxt, project_id)
 | 
			
		||||
        db.network_disassociate(ctxt, network_ref['id'])
 | 
			
		||||
        groups = db.security_group_get_by_project(ctxt, project_id)
 | 
			
		||||
        admin_context = context.get_admin_context()
 | 
			
		||||
        networks = db.project_get_networks(admin_context, project_id)
 | 
			
		||||
        for network in networks:
 | 
			
		||||
            db.network_disassociate(admin_context, network['id'])
 | 
			
		||||
        groups = db.security_group_get_by_project(admin_context, project_id)
 | 
			
		||||
        for group in groups:
 | 
			
		||||
            db.security_group_destroy(ctxt, group['id'])
 | 
			
		||||
            db.security_group_destroy(admin_context, group['id'])
 | 
			
		||||
 | 
			
		||||
    def zipfile(self, project_id, user_id, filename='nova.zip'):
 | 
			
		||||
        """Exports credentials for project to a zip file
 | 
			
		||||
@@ -505,7 +512,7 @@ class FixedIpCommands(object):
 | 
			
		||||
                instance = fixed_ip['instance']
 | 
			
		||||
                hostname = instance['hostname']
 | 
			
		||||
                host = instance['host']
 | 
			
		||||
                mac_address = instance['mac_address']
 | 
			
		||||
                mac_address = fixed_ip['mac_address']['address']
 | 
			
		||||
            print "%-18s\t%-15s\t%-17s\t%-15s\t%s" % (
 | 
			
		||||
                    fixed_ip['network']['cidr'],
 | 
			
		||||
                    fixed_ip['address'],
 | 
			
		||||
@@ -515,13 +522,12 @@ class FixedIpCommands(object):
 | 
			
		||||
class FloatingIpCommands(object):
 | 
			
		||||
    """Class for managing floating ip."""
 | 
			
		||||
 | 
			
		||||
    def create(self, host, range):
 | 
			
		||||
        """Creates floating ips for host by range
 | 
			
		||||
        arguments: host ip_range"""
 | 
			
		||||
    def create(self, range):
 | 
			
		||||
        """Creates floating ips for zone by range
 | 
			
		||||
        arguments: ip_range"""
 | 
			
		||||
        for address in netaddr.IPNetwork(range):
 | 
			
		||||
            db.floating_ip_create(context.get_admin_context(),
 | 
			
		||||
                                  {'address': str(address),
 | 
			
		||||
                                   'host': host})
 | 
			
		||||
                                  {'address': str(address)})
 | 
			
		||||
 | 
			
		||||
    def delete(self, ip_range):
 | 
			
		||||
        """Deletes floating ips by range
 | 
			
		||||
@@ -532,7 +538,8 @@ class FloatingIpCommands(object):
 | 
			
		||||
 | 
			
		||||
    def list(self, host=None):
 | 
			
		||||
        """Lists all floating ips (optionally by host)
 | 
			
		||||
        arguments: [host]"""
 | 
			
		||||
        arguments: [host]
 | 
			
		||||
        Note: if host is given, only active floating IPs are returned"""
 | 
			
		||||
        ctxt = context.get_admin_context()
 | 
			
		||||
        if host is None:
 | 
			
		||||
            floating_ips = db.floating_ip_get_all(ctxt)
 | 
			
		||||
@@ -550,10 +557,23 @@ class FloatingIpCommands(object):
 | 
			
		||||
class NetworkCommands(object):
 | 
			
		||||
    """Class for managing networks."""
 | 
			
		||||
 | 
			
		||||
    def create(self, fixed_range=None, num_networks=None, network_size=None,
 | 
			
		||||
            vlan_start=None, vpn_start=None, fixed_range_v6=None,
 | 
			
		||||
            gateway_v6=None, label='public'):
 | 
			
		||||
        """Creates fixed ips for host by range"""
 | 
			
		||||
    def create(self, label=None, fixed_range=None, num_networks=None,
 | 
			
		||||
               network_size=None, vlan_start=None,
 | 
			
		||||
               vpn_start=None, fixed_range_v6=None, gateway_v6=None,
 | 
			
		||||
               flat_network_bridge=None, bridge_interface=None):
 | 
			
		||||
        """Creates fixed ips for host by range
 | 
			
		||||
        arguments: label, fixed_range, [num_networks=FLAG],
 | 
			
		||||
                   [network_size=FLAG], [vlan_start=FLAG],
 | 
			
		||||
                   [vpn_start=FLAG], [fixed_range_v6=FLAG], [gateway_v6=FLAG],
 | 
			
		||||
                   [flat_network_bridge=FLAG], [bridge_interface=FLAG]
 | 
			
		||||
        If you wish to use a later argument fill in the gaps with 0s
 | 
			
		||||
        Ex: network create private 10.0.0.0/8 1 15 0 0 0 0 xenbr1 eth1
 | 
			
		||||
            network create private 10.0.0.0/8 1 15
 | 
			
		||||
        """
 | 
			
		||||
        if not label:
 | 
			
		||||
            msg = _('a label (ex: public) is required to create networks.')
 | 
			
		||||
            print msg
 | 
			
		||||
            raise TypeError(msg)
 | 
			
		||||
        if not fixed_range:
 | 
			
		||||
            msg = _('Fixed range in the form of 10.0.0.0/8 is '
 | 
			
		||||
                    'required to create networks.')
 | 
			
		||||
@@ -569,11 +589,17 @@ class NetworkCommands(object):
 | 
			
		||||
            vpn_start = FLAGS.vpn_start
 | 
			
		||||
        if not fixed_range_v6:
 | 
			
		||||
            fixed_range_v6 = FLAGS.fixed_range_v6
 | 
			
		||||
        if not flat_network_bridge:
 | 
			
		||||
            flat_network_bridge = FLAGS.flat_network_bridge
 | 
			
		||||
        if not bridge_interface:
 | 
			
		||||
            bridge_interface = FLAGS.flat_interface or FLAGS.vlan_interface
 | 
			
		||||
        if not gateway_v6:
 | 
			
		||||
            gateway_v6 = FLAGS.gateway_v6
 | 
			
		||||
        net_manager = utils.import_object(FLAGS.network_manager)
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            net_manager.create_networks(context.get_admin_context(),
 | 
			
		||||
                                        label=label,
 | 
			
		||||
                                        cidr=fixed_range,
 | 
			
		||||
                                        num_networks=int(num_networks),
 | 
			
		||||
                                        network_size=int(network_size),
 | 
			
		||||
@@ -581,7 +607,8 @@ class NetworkCommands(object):
 | 
			
		||||
                                        vpn_start=int(vpn_start),
 | 
			
		||||
                                        cidr_v6=fixed_range_v6,
 | 
			
		||||
                                        gateway_v6=gateway_v6,
 | 
			
		||||
                                        label=label)
 | 
			
		||||
                                        bridge=flat_network_bridge,
 | 
			
		||||
                                        bridge_interface=bridge_interface)
 | 
			
		||||
        except ValueError, e:
 | 
			
		||||
            print e
 | 
			
		||||
            raise e
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								doc/build/html/.buildinfo
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								doc/build/html/.buildinfo
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +0,0 @@
 | 
			
		||||
# Sphinx build info version 1
 | 
			
		||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
 | 
			
		||||
config: 2a2fe6198f4be4a4d6f289b09d16d74a
 | 
			
		||||
tags: fbb0d17656682115ca4d033fb2f83ba1
 | 
			
		||||
							
								
								
									
										39
									
								
								doc/source/devref/multinic.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								doc/source/devref/multinic.rst
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
MultiNic
 | 
			
		||||
========
 | 
			
		||||
 | 
			
		||||
What is it
 | 
			
		||||
----------
 | 
			
		||||
 | 
			
		||||
Multinic allows an instance to have more than one vif connected to it. Each vif is representative of a separate network with its own IP block.
 | 
			
		||||
 | 
			
		||||
Managers
 | 
			
		||||
--------
 | 
			
		||||
 | 
			
		||||
Each of the network managers are designed to run independently of the compute manager. They expose a common API for the compute manager to call to determine and configure the network(s) for an instance. Direct calls to either the network api or especially the DB should be avoided by the virt layers.
 | 
			
		||||
 | 
			
		||||
On startup a manager looks in the networks table for networks it is assigned and configures itself to support that network. Using the periodic task, they will claim new networks that have no host set. Only one network per network-host will be claimed at a time. This allows for psuedo-loadbalancing if there are multiple network-hosts running.
 | 
			
		||||
 | 
			
		||||
Flat Manager 
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
    .. image:: /images/multinic_flat.png
 | 
			
		||||
 | 
			
		||||
The Flat manager is most similar to a traditional switched network environment. It assumes that the IP routing, DNS, DHCP (possibly) and bridge creation is handled by something else. That is it makes no attempt to configure any of this. It does keep track of a range of IPs for the instances that are connected to the network to be allocated.
 | 
			
		||||
 | 
			
		||||
Each instance will get a fixed IP from each network's pool. The guest operating system may be configured to gather this information through an agent or by the hypervisor injecting the files, or it may ignore it completely and come up with only a layer 2 connection.
 | 
			
		||||
 | 
			
		||||
Flat manager requires at least one nova-network process running that will listen to the API queue and respond to queries. It does not need to sit on any of the networks but it does keep track of the IPs it hands out to instances.
 | 
			
		||||
 | 
			
		||||
FlatDHCP Manager
 | 
			
		||||
----------------
 | 
			
		||||
 | 
			
		||||
    .. image:: /images/multinic_dhcp.png
 | 
			
		||||
 | 
			
		||||
FlatDHCP manager builds on the the Flat manager adding dnsmask (DNS and DHCP) and radvd (Router Advertisement) servers on the bridge for that network. The services run on the host that is assigned to that nework. The FlatDHCP manager will create its bridge as specified when the network was created on the network-host when the network host starts up or when a new network gets allocated to that host. Compute nodes will also create the bridges as necessary and connect instance VIFs to them.
 | 
			
		||||
 | 
			
		||||
VLAN Manager
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
    .. image:: /images/multinic_vlan.png
 | 
			
		||||
 | 
			
		||||
The VLAN manager sets up forwarding to/from a cloudpipe instance in addition to providing dnsmask (DNS and DHCP) and radvd (Router Advertisement) services for each network. The manager will create its bridge as specified when the network was created on the network-host when the network host starts up or when a new network gets allocated to that host. Compute nodes will also create the bridges as necessary and conenct instance VIFs to them.
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								doc/source/image_src/multinic_1.odg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/source/image_src/multinic_1.odg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								doc/source/image_src/multinic_2.odg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/source/image_src/multinic_2.odg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								doc/source/image_src/multinic_3.odg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/source/image_src/multinic_3.odg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								doc/source/images/multinic_dhcp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/source/images/multinic_dhcp.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 53 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								doc/source/images/multinic_flat.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/source/images/multinic_flat.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 40 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								doc/source/images/multinic_vlan.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/source/images/multinic_vlan.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 57 KiB  | 
@@ -630,13 +630,17 @@ class AuthManager(object):
 | 
			
		||||
        not been allocated for user.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        network_ref = db.project_get_network(context.get_admin_context(),
 | 
			
		||||
                                             Project.safe_id(project), False)
 | 
			
		||||
 | 
			
		||||
        if not network_ref:
 | 
			
		||||
        networks = db.project_get_networks(context.get_admin_context(),
 | 
			
		||||
                                           Project.safe_id(project), False)
 | 
			
		||||
        if not networks:
 | 
			
		||||
            return (None, None)
 | 
			
		||||
        return (network_ref['vpn_public_address'],
 | 
			
		||||
                network_ref['vpn_public_port'])
 | 
			
		||||
 | 
			
		||||
        # TODO(tr3buchet): not sure what you guys plan on doing with this
 | 
			
		||||
        # but it's possible for a project to have multiple sets of vpn data
 | 
			
		||||
        # for now I'm just returning the first one
 | 
			
		||||
        network = networks[0]
 | 
			
		||||
        return (network['vpn_public_address'],
 | 
			
		||||
                network['vpn_public_port'])
 | 
			
		||||
 | 
			
		||||
    def delete_project(self, project):
 | 
			
		||||
        """Deletes a project"""
 | 
			
		||||
 
 | 
			
		||||
@@ -149,6 +149,15 @@ class NovaException(Exception):
 | 
			
		||||
        return self._error_string
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VirtualInterfaceCreateException(NovaException):
 | 
			
		||||
    message = _("Virtual Interface creation failed")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VirtualInterfaceMacAddressException(NovaException):
 | 
			
		||||
    message = _("5 attempts to create virtual interface"
 | 
			
		||||
                "with unique mac address failed")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NotAuthorized(NovaException):
 | 
			
		||||
    message = _("Not authorized.")
 | 
			
		||||
 | 
			
		||||
@@ -387,32 +396,56 @@ class DatastoreNotFound(NotFound):
 | 
			
		||||
    message = _("Could not find the datastore reference(s) which the VM uses.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NoFixedIpsFoundForInstance(NotFound):
 | 
			
		||||
class FixedIpNotFound(NotFound):
 | 
			
		||||
    message = _("No fixed IP associated with id %(id)s.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FixedIpNotFoundForAddress(FixedIpNotFound):
 | 
			
		||||
    message = _("Fixed ip not found for address %(address)s.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FixedIpNotFoundForInstance(FixedIpNotFound):
 | 
			
		||||
    message = _("Instance %(instance_id)s has zero fixed ips.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FixedIpNotFoundForVirtualInterface(FixedIpNotFound):
 | 
			
		||||
    message = _("Virtual interface %(vif_id)s has zero associated fixed ips.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FixedIpNotFoundForHost(FixedIpNotFound):
 | 
			
		||||
    message = _("Host %(host)s has zero fixed ips.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NoMoreFixedIps(Error):
 | 
			
		||||
    message = _("Zero fixed ips available.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NoFixedIpsDefined(NotFound):
 | 
			
		||||
    message = _("Zero fixed ips could be found.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FloatingIpNotFound(NotFound):
 | 
			
		||||
    message = _("Floating ip %(floating_ip)s not found")
 | 
			
		||||
    message = _("Floating ip not found for id %(id)s.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FloatingIpNotFoundForFixedAddress(NotFound):
 | 
			
		||||
    message = _("Floating ip not found for fixed address %(fixed_ip)s.")
 | 
			
		||||
class FloatingIpNotFoundForAddress(FloatingIpNotFound):
 | 
			
		||||
    message = _("Floating ip not found for address %(address)s.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FloatingIpNotFoundForProject(FloatingIpNotFound):
 | 
			
		||||
    message = _("Floating ip not found for project %(project_id)s.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FloatingIpNotFoundForHost(FloatingIpNotFound):
 | 
			
		||||
    message = _("Floating ip not found for host %(host)s.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NoMoreFloatingIps(FloatingIpNotFound):
 | 
			
		||||
    message = _("Zero floating ips available.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NoFloatingIpsDefined(NotFound):
 | 
			
		||||
    message = _("Zero floating ips could be found.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NoFloatingIpsDefinedForHost(NoFloatingIpsDefined):
 | 
			
		||||
    message = _("Zero floating ips defined for host %(host)s.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NoFloatingIpsDefinedForInstance(NoFloatingIpsDefined):
 | 
			
		||||
    message = _("Zero floating ips defined for instance %(instance_id)s.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NoMoreFloatingIps(NotFound):
 | 
			
		||||
    message = _("Zero floating ips available.")
 | 
			
		||||
    message = _("Zero floating ips exist.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class KeypairNotFound(NotFound):
 | 
			
		||||
 
 | 
			
		||||
@@ -360,6 +360,7 @@ class FanoutPublisher(Publisher):
 | 
			
		||||
        self.exchange = '%s_fanout' % topic
 | 
			
		||||
        self.queue = '%s_fanout' % topic
 | 
			
		||||
        self.durable = False
 | 
			
		||||
        self.auto_delete = True
 | 
			
		||||
        LOG.info(_('Creating "%(exchange)s" fanout exchange'),
 | 
			
		||||
                 dict(exchange=self.exchange))
 | 
			
		||||
        super(FanoutPublisher, self).__init__(connection=connection)
 | 
			
		||||
 
 | 
			
		||||
@@ -114,7 +114,8 @@ def _process(func, zone):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def call_zone_method(context, method_name, errors_to_ignore=None,
 | 
			
		||||
                     novaclient_collection_name='zones', *args, **kwargs):
 | 
			
		||||
                     novaclient_collection_name='zones', zones=None,
 | 
			
		||||
                     *args, **kwargs):
 | 
			
		||||
    """Returns a list of (zone, call_result) objects."""
 | 
			
		||||
    if not isinstance(errors_to_ignore, (list, tuple)):
 | 
			
		||||
        # This will also handle the default None
 | 
			
		||||
@@ -122,7 +123,9 @@ def call_zone_method(context, method_name, errors_to_ignore=None,
 | 
			
		||||
 | 
			
		||||
    pool = greenpool.GreenPool()
 | 
			
		||||
    results = []
 | 
			
		||||
    for zone in db.zone_get_all(context):
 | 
			
		||||
    if zones is None:
 | 
			
		||||
        zones = db.zone_get_all(context)
 | 
			
		||||
    for zone in zones:
 | 
			
		||||
        try:
 | 
			
		||||
            nova = novaclient.OpenStack(zone.username, zone.password, None,
 | 
			
		||||
                    zone.api_url)
 | 
			
		||||
 
 | 
			
		||||
@@ -130,8 +130,7 @@ class Scheduler(object):
 | 
			
		||||
        # Checking instance is running.
 | 
			
		||||
        if (power_state.RUNNING != instance_ref['state'] or \
 | 
			
		||||
           'running' != instance_ref['state_description']):
 | 
			
		||||
            ec2_id = instance_ref['hostname']
 | 
			
		||||
            raise exception.InstanceNotRunning(instance_id=ec2_id)
 | 
			
		||||
            raise exception.InstanceNotRunning(instance_id=instance_ref['id'])
 | 
			
		||||
 | 
			
		||||
        # Checing volume node is running when any volumes are mounted
 | 
			
		||||
        # to the instance.
 | 
			
		||||
@@ -169,9 +168,9 @@ class Scheduler(object):
 | 
			
		||||
        # and dest is not same.
 | 
			
		||||
        src = instance_ref['host']
 | 
			
		||||
        if dest == src:
 | 
			
		||||
            ec2_id = instance_ref['hostname']
 | 
			
		||||
            raise exception.UnableToMigrateToSelf(instance_id=ec2_id,
 | 
			
		||||
                                                  host=dest)
 | 
			
		||||
            raise exception.UnableToMigrateToSelf(
 | 
			
		||||
                    instance_id=instance_ref['id'],
 | 
			
		||||
                    host=dest)
 | 
			
		||||
 | 
			
		||||
        # Checking dst host still has enough capacities.
 | 
			
		||||
        self.assert_compute_node_has_enough_resources(context,
 | 
			
		||||
@@ -246,7 +245,7 @@ class Scheduler(object):
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        # Getting instance information
 | 
			
		||||
        ec2_id = instance_ref['hostname']
 | 
			
		||||
        hostname = instance_ref['hostname']
 | 
			
		||||
 | 
			
		||||
        # Getting host information
 | 
			
		||||
        service_refs = db.service_get_all_compute_by_host(context, dest)
 | 
			
		||||
@@ -257,8 +256,9 @@ class Scheduler(object):
 | 
			
		||||
        mem_avail = mem_total - mem_used
 | 
			
		||||
        mem_inst = instance_ref['memory_mb']
 | 
			
		||||
        if mem_avail <= mem_inst:
 | 
			
		||||
            reason = _("Unable to migrate %(ec2_id)s to destination: %(dest)s "
 | 
			
		||||
                       "(host:%(mem_avail)s <= instance:%(mem_inst)s)")
 | 
			
		||||
            reason = _("Unable to migrate %(hostname)s to destination: "
 | 
			
		||||
                       "%(dest)s (host:%(mem_avail)s <= instance:"
 | 
			
		||||
                       "%(mem_inst)s)")
 | 
			
		||||
            raise exception.MigrationError(reason=reason % locals())
 | 
			
		||||
 | 
			
		||||
    def mounted_on_same_shared_storage(self, context, instance_ref, dest):
 | 
			
		||||
 
 | 
			
		||||
@@ -251,8 +251,7 @@ class JsonFilter(HostFilter):
 | 
			
		||||
        required_disk = instance_type['local_gb']
 | 
			
		||||
        query = ['and',
 | 
			
		||||
                    ['>=', '$compute.host_memory_free', required_ram],
 | 
			
		||||
                    ['>=', '$compute.disk_available', required_disk],
 | 
			
		||||
                ]
 | 
			
		||||
                    ['>=', '$compute.disk_available', required_disk]]
 | 
			
		||||
        return (self._full_name(), json.dumps(query))
 | 
			
		||||
 | 
			
		||||
    def _parse_string(self, string, host, services):
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,7 @@ from nova import flags
 | 
			
		||||
from nova import log as logging
 | 
			
		||||
from nova import rpc
 | 
			
		||||
 | 
			
		||||
from nova.compute import api as compute_api
 | 
			
		||||
from nova.scheduler import api
 | 
			
		||||
from nova.scheduler import driver
 | 
			
		||||
 | 
			
		||||
@@ -48,14 +49,25 @@ class InvalidBlob(exception.NovaException):
 | 
			
		||||
class ZoneAwareScheduler(driver.Scheduler):
 | 
			
		||||
    """Base class for creating Zone Aware Schedulers."""
 | 
			
		||||
 | 
			
		||||
    def _call_zone_method(self, context, method, specs):
 | 
			
		||||
    def _call_zone_method(self, context, method, specs, zones):
 | 
			
		||||
        """Call novaclient zone method. Broken out for testing."""
 | 
			
		||||
        return api.call_zone_method(context, method, specs=specs)
 | 
			
		||||
        return api.call_zone_method(context, method, specs=specs, zones=zones)
 | 
			
		||||
 | 
			
		||||
    def _provision_resource_locally(self, context, item, instance_id, kwargs):
 | 
			
		||||
    def _provision_resource_locally(self, context, build_plan_item,
 | 
			
		||||
                                    request_spec, kwargs):
 | 
			
		||||
        """Create the requested resource in this Zone."""
 | 
			
		||||
        host = item['hostname']
 | 
			
		||||
        host = build_plan_item['hostname']
 | 
			
		||||
        base_options = request_spec['instance_properties']
 | 
			
		||||
 | 
			
		||||
        # TODO(sandy): I guess someone needs to add block_device_mapping
 | 
			
		||||
        # support at some point? Also, OS API has no concept of security
 | 
			
		||||
        # groups.
 | 
			
		||||
        instance = compute_api.API().create_db_entry_for_new_instance(context,
 | 
			
		||||
            base_options, None, [])
 | 
			
		||||
 | 
			
		||||
        instance_id = instance['id']
 | 
			
		||||
        kwargs['instance_id'] = instance_id
 | 
			
		||||
 | 
			
		||||
        rpc.cast(context,
 | 
			
		||||
                 db.queue_get_for(context, "compute", host),
 | 
			
		||||
                 {"method": "run_instance",
 | 
			
		||||
@@ -115,8 +127,8 @@ class ZoneAwareScheduler(driver.Scheduler):
 | 
			
		||||
        nova.servers.create(name, image_ref, flavor_id, ipgroup, meta, files,
 | 
			
		||||
                            child_blob, reservation_id=reservation_id)
 | 
			
		||||
 | 
			
		||||
    def _provision_resource_from_blob(self, context, item, instance_id,
 | 
			
		||||
                                          request_spec, kwargs):
 | 
			
		||||
    def _provision_resource_from_blob(self, context, build_plan_item,
 | 
			
		||||
                                      instance_id, request_spec, kwargs):
 | 
			
		||||
        """Create the requested resource locally or in a child zone
 | 
			
		||||
           based on what is stored in the zone blob info.
 | 
			
		||||
 | 
			
		||||
@@ -132,12 +144,12 @@ class ZoneAwareScheduler(driver.Scheduler):
 | 
			
		||||
           request."""
 | 
			
		||||
 | 
			
		||||
        host_info = None
 | 
			
		||||
        if "blob" in item:
 | 
			
		||||
        if "blob" in build_plan_item:
 | 
			
		||||
            # Request was passed in from above. Is it for us?
 | 
			
		||||
            host_info = self._decrypt_blob(item['blob'])
 | 
			
		||||
        elif "child_blob" in item:
 | 
			
		||||
            host_info = self._decrypt_blob(build_plan_item['blob'])
 | 
			
		||||
        elif "child_blob" in build_plan_item:
 | 
			
		||||
            # Our immediate child zone provided this info ...
 | 
			
		||||
            host_info = item
 | 
			
		||||
            host_info = build_plan_item
 | 
			
		||||
 | 
			
		||||
        if not host_info:
 | 
			
		||||
            raise InvalidBlob()
 | 
			
		||||
@@ -147,19 +159,44 @@ class ZoneAwareScheduler(driver.Scheduler):
 | 
			
		||||
            self._ask_child_zone_to_create_instance(context, host_info,
 | 
			
		||||
                                                    request_spec, kwargs)
 | 
			
		||||
        else:
 | 
			
		||||
            self._provision_resource_locally(context, host_info,
 | 
			
		||||
                                             instance_id, kwargs)
 | 
			
		||||
            self._provision_resource_locally(context, host_info, request_spec,
 | 
			
		||||
                                             kwargs)
 | 
			
		||||
 | 
			
		||||
    def _provision_resource(self, context, item, instance_id, request_spec,
 | 
			
		||||
                           kwargs):
 | 
			
		||||
    def _provision_resource(self, context, build_plan_item, instance_id,
 | 
			
		||||
                            request_spec, kwargs):
 | 
			
		||||
        """Create the requested resource in this Zone or a child zone."""
 | 
			
		||||
        if "hostname" in item:
 | 
			
		||||
            self._provision_resource_locally(context, item, instance_id,
 | 
			
		||||
                            kwargs)
 | 
			
		||||
        if "hostname" in build_plan_item:
 | 
			
		||||
            self._provision_resource_locally(context, build_plan_item,
 | 
			
		||||
                                             request_spec, kwargs)
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        self._provision_resource_from_blob(context, item, instance_id,
 | 
			
		||||
                                               request_spec, kwargs)
 | 
			
		||||
        self._provision_resource_from_blob(context, build_plan_item,
 | 
			
		||||
                                           instance_id, request_spec, kwargs)
 | 
			
		||||
 | 
			
		||||
    def _adjust_child_weights(self, child_results, zones):
 | 
			
		||||
        """Apply the Scale and Offset values from the Zone definition
 | 
			
		||||
        to adjust the weights returned from the child zones. Alters
 | 
			
		||||
        child_results in place.
 | 
			
		||||
        """
 | 
			
		||||
        for zone, result in child_results:
 | 
			
		||||
            if not result:
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            for zone_rec in zones:
 | 
			
		||||
                if zone_rec['api_url'] != zone:
 | 
			
		||||
                    continue
 | 
			
		||||
 | 
			
		||||
                for item in result:
 | 
			
		||||
                    try:
 | 
			
		||||
                        offset = zone_rec['weight_offset']
 | 
			
		||||
                        scale = zone_rec['weight_scale']
 | 
			
		||||
                        raw_weight = item['weight']
 | 
			
		||||
                        cooked_weight = offset + scale * raw_weight
 | 
			
		||||
                        item['weight'] = cooked_weight
 | 
			
		||||
                        item['raw_weight'] = raw_weight
 | 
			
		||||
                    except KeyError:
 | 
			
		||||
                        LOG.exception(_("Bad child zone scaling values "
 | 
			
		||||
                                        "for Zone: %(zone)s") % locals())
 | 
			
		||||
 | 
			
		||||
    def schedule_run_instance(self, context, instance_id, request_spec,
 | 
			
		||||
                              *args, **kwargs):
 | 
			
		||||
@@ -261,8 +298,10 @@ class ZoneAwareScheduler(driver.Scheduler):
 | 
			
		||||
 | 
			
		||||
        # Next, tack on the best weights from the child zones ...
 | 
			
		||||
        json_spec = json.dumps(request_spec)
 | 
			
		||||
        all_zones = db.zone_get_all(context)
 | 
			
		||||
        child_results = self._call_zone_method(context, "select",
 | 
			
		||||
                specs=json_spec)
 | 
			
		||||
                specs=json_spec, zones=all_zones)
 | 
			
		||||
        self._adjust_child_weights(child_results, all_zones)
 | 
			
		||||
        for child_zone, result in child_results:
 | 
			
		||||
            for weighting in result:
 | 
			
		||||
                # Remember the child_zone so we can get back to
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								nova/test.py
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								nova/test.py
									
									
									
									
									
								
							@@ -30,11 +30,14 @@ import uuid
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
import mox
 | 
			
		||||
import nose.plugins.skip
 | 
			
		||||
import shutil
 | 
			
		||||
import stubout
 | 
			
		||||
from eventlet import greenthread
 | 
			
		||||
 | 
			
		||||
from nova import fakerabbit
 | 
			
		||||
from nova import flags
 | 
			
		||||
from nova import log
 | 
			
		||||
from nova import rpc
 | 
			
		||||
from nova import utils
 | 
			
		||||
from nova import service
 | 
			
		||||
@@ -47,6 +50,22 @@ flags.DEFINE_string('sqlite_clean_db', 'clean.sqlite',
 | 
			
		||||
flags.DEFINE_bool('fake_tests', True,
 | 
			
		||||
                  'should we use everything for testing')
 | 
			
		||||
 | 
			
		||||
LOG = log.getLogger('nova.tests')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class skip_test(object):
 | 
			
		||||
    """Decorator that skips a test."""
 | 
			
		||||
    def __init__(self, msg):
 | 
			
		||||
        self.message = msg
 | 
			
		||||
 | 
			
		||||
    def __call__(self, func):
 | 
			
		||||
        def _skipper(*args, **kw):
 | 
			
		||||
            """Wrapped skipper function."""
 | 
			
		||||
            raise nose.SkipTest(self.message)
 | 
			
		||||
        _skipper.__name__ = func.__name__
 | 
			
		||||
        _skipper.__doc__ = func.__doc__
 | 
			
		||||
        return _skipper
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def skip_if_fake(func):
 | 
			
		||||
    """Decorator that skips a test if running in fake mode."""
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,7 @@ def setup():
 | 
			
		||||
 | 
			
		||||
    from nova import context
 | 
			
		||||
    from nova import flags
 | 
			
		||||
    from nova import db
 | 
			
		||||
    from nova.db import migration
 | 
			
		||||
    from nova.network import manager as network_manager
 | 
			
		||||
    from nova.tests import fake_flags
 | 
			
		||||
@@ -53,14 +54,21 @@ def setup():
 | 
			
		||||
        return
 | 
			
		||||
    migration.db_sync()
 | 
			
		||||
    ctxt = context.get_admin_context()
 | 
			
		||||
    network_manager.VlanManager().create_networks(ctxt,
 | 
			
		||||
                                                  FLAGS.fixed_range,
 | 
			
		||||
                                                  FLAGS.num_networks,
 | 
			
		||||
                                                  FLAGS.network_size,
 | 
			
		||||
                                                  FLAGS.fixed_range_v6,
 | 
			
		||||
                                                  FLAGS.vlan_start,
 | 
			
		||||
                                                  FLAGS.vpn_start,
 | 
			
		||||
                                                  )
 | 
			
		||||
    network = network_manager.VlanManager()
 | 
			
		||||
    bridge_interface = FLAGS.flat_interface or FLAGS.vlan_interface
 | 
			
		||||
    network.create_networks(ctxt,
 | 
			
		||||
                            label='test',
 | 
			
		||||
                            cidr=FLAGS.fixed_range,
 | 
			
		||||
                            num_networks=FLAGS.num_networks,
 | 
			
		||||
                            network_size=FLAGS.network_size,
 | 
			
		||||
                            cidr_v6=FLAGS.fixed_range_v6,
 | 
			
		||||
                            gateway_v6=FLAGS.gateway_v6,
 | 
			
		||||
                            bridge=FLAGS.flat_network_bridge,
 | 
			
		||||
                            bridge_interface=bridge_interface,
 | 
			
		||||
                            vpn_start=FLAGS.vpn_start,
 | 
			
		||||
                            vlan_start=FLAGS.vlan_start)
 | 
			
		||||
    for net in db.network_get_all(ctxt):
 | 
			
		||||
        network.set_network_host(ctxt, net['id'])
 | 
			
		||||
 | 
			
		||||
    cleandb = os.path.join(FLAGS.state_path, FLAGS.sqlite_clean_db)
 | 
			
		||||
    shutil.copyfile(testdb, cleandb)
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,19 @@
 | 
			
		||||
# 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.
 | 
			
		||||
 | 
			
		||||
# NOTE(vish): this forces the fixtures from tests/__init.py:setup() to work
 | 
			
		||||
from nova.tests import *
 | 
			
		||||
 
 | 
			
		||||
@@ -268,7 +268,6 @@ class SimpleDriverTestCase(test.TestCase):
 | 
			
		||||
        inst['user_id'] = self.user.id
 | 
			
		||||
        inst['project_id'] = self.project.id
 | 
			
		||||
        inst['instance_type_id'] = '1'
 | 
			
		||||
        inst['mac_address'] = utils.generate_mac()
 | 
			
		||||
        inst['vcpus'] = kwargs.get('vcpus', 1)
 | 
			
		||||
        inst['ami_launch_index'] = 0
 | 
			
		||||
        inst['availability_zone'] = kwargs.get('availability_zone', None)
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,8 @@
 | 
			
		||||
Tests For Zone Aware Scheduler.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import nova.db
 | 
			
		||||
 | 
			
		||||
from nova import exception
 | 
			
		||||
from nova import test
 | 
			
		||||
from nova.scheduler import driver
 | 
			
		||||
@@ -79,7 +81,7 @@ class FakeEmptyZoneManager(zone_manager.ZoneManager):
 | 
			
		||||
        self.service_states = {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def fake_empty_call_zone_method(context, method, specs):
 | 
			
		||||
def fake_empty_call_zone_method(context, method, specs, zones):
 | 
			
		||||
    return []
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -98,7 +100,7 @@ def fake_ask_child_zone_to_create_instance(context, zone_info,
 | 
			
		||||
    was_called = True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def fake_provision_resource_locally(context, item, instance_id, kwargs):
 | 
			
		||||
def fake_provision_resource_locally(context, build_plan, request_spec, kwargs):
 | 
			
		||||
    global was_called
 | 
			
		||||
    was_called = True
 | 
			
		||||
 | 
			
		||||
@@ -118,7 +120,7 @@ def fake_decrypt_blob_returns_child_info(blob):
 | 
			
		||||
            'child_blob': True}  # values aren't important. Keys are.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def fake_call_zone_method(context, method, specs):
 | 
			
		||||
def fake_call_zone_method(context, method, specs, zones):
 | 
			
		||||
    return [
 | 
			
		||||
        ('zone1', [
 | 
			
		||||
            dict(weight=1, blob='AAAAAAA'),
 | 
			
		||||
@@ -141,6 +143,20 @@ def fake_call_zone_method(context, method, specs):
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def fake_zone_get_all(context):
 | 
			
		||||
    return [
 | 
			
		||||
        dict(id=1, api_url='zone1',
 | 
			
		||||
             username='admin', password='password',
 | 
			
		||||
             weight_offset=0.0, weight_scale=1.0),
 | 
			
		||||
        dict(id=2, api_url='zone2',
 | 
			
		||||
             username='admin', password='password',
 | 
			
		||||
             weight_offset=1000.0, weight_scale=1.0),
 | 
			
		||||
        dict(id=3, api_url='zone3',
 | 
			
		||||
             username='admin', password='password',
 | 
			
		||||
             weight_offset=0.0, weight_scale=1000.0),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ZoneAwareSchedulerTestCase(test.TestCase):
 | 
			
		||||
    """Test case for Zone Aware Scheduler."""
 | 
			
		||||
 | 
			
		||||
@@ -151,6 +167,7 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
 | 
			
		||||
        """
 | 
			
		||||
        sched = FakeZoneAwareScheduler()
 | 
			
		||||
        self.stubs.Set(sched, '_call_zone_method', fake_call_zone_method)
 | 
			
		||||
        self.stubs.Set(nova.db, 'zone_get_all', fake_zone_get_all)
 | 
			
		||||
 | 
			
		||||
        zm = FakeZoneManager()
 | 
			
		||||
        sched.set_zone_manager(zm)
 | 
			
		||||
@@ -168,12 +185,33 @@ class ZoneAwareSchedulerTestCase(test.TestCase):
 | 
			
		||||
        # 4 local hosts
 | 
			
		||||
        self.assertEqual(4, len(hostnames))
 | 
			
		||||
 | 
			
		||||
    def test_adjust_child_weights(self):
 | 
			
		||||
        """Make sure the weights returned by child zones are
 | 
			
		||||
        properly adjusted based on the scale/offset in the zone
 | 
			
		||||
        db entries.
 | 
			
		||||
        """
 | 
			
		||||
        sched = FakeZoneAwareScheduler()
 | 
			
		||||
        child_results = fake_call_zone_method(None, None, None, None)
 | 
			
		||||
        zones = fake_zone_get_all(None)
 | 
			
		||||
        sched._adjust_child_weights(child_results, zones)
 | 
			
		||||
        scaled = [130000, 131000, 132000, 3000]
 | 
			
		||||
        for zone, results in child_results:
 | 
			
		||||
            for item in results:
 | 
			
		||||
                w = item['weight']
 | 
			
		||||
                if zone == 'zone1':  # No change
 | 
			
		||||
                    self.assertTrue(w < 1000.0)
 | 
			
		||||
                if zone == 'zone2':  # Offset +1000
 | 
			
		||||
                    self.assertTrue(w >= 1000.0 and w < 2000)
 | 
			
		||||
                if zone == 'zone3':  # Scale x1000
 | 
			
		||||
                    self.assertEqual(scaled.pop(0), w)
 | 
			
		||||
 | 
			
		||||
    def test_empty_zone_aware_scheduler(self):
 | 
			
		||||
        """
 | 
			
		||||
        Ensure empty hosts & child_zones result in NoValidHosts exception.
 | 
			
		||||
        """
 | 
			
		||||
        sched = FakeZoneAwareScheduler()
 | 
			
		||||
        self.stubs.Set(sched, '_call_zone_method', fake_empty_call_zone_method)
 | 
			
		||||
        self.stubs.Set(nova.db, 'zone_get_all', fake_zone_get_all)
 | 
			
		||||
 | 
			
		||||
        zm = FakeEmptyZoneManager()
 | 
			
		||||
        sched.set_zone_manager(zm)
 | 
			
		||||
 
 | 
			
		||||
@@ -56,7 +56,6 @@ class AdminApiTestCase(test.TestCase):
 | 
			
		||||
        self.project = self.manager.create_project('proj', 'admin', 'proj')
 | 
			
		||||
        self.context = context.RequestContext(user=self.user,
 | 
			
		||||
                                              project=self.project)
 | 
			
		||||
        host = self.network.get_network_host(self.context.elevated())
 | 
			
		||||
 | 
			
		||||
        def fake_show(meh, context, id):
 | 
			
		||||
            return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1,
 | 
			
		||||
@@ -75,9 +74,6 @@ class AdminApiTestCase(test.TestCase):
 | 
			
		||||
        self.stubs.Set(rpc, 'cast', finish_cast)
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        network_ref = db.project_get_network(self.context,
 | 
			
		||||
                                             self.project.id)
 | 
			
		||||
        db.network_disassociate(self.context, network_ref['id'])
 | 
			
		||||
        self.manager.delete_project(self.project)
 | 
			
		||||
        self.manager.delete_user(self.user)
 | 
			
		||||
        super(AdminApiTestCase, self).tearDown()
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ class CloudTestCase(test.TestCase):
 | 
			
		||||
        self.project = self.manager.create_project('proj', 'admin', 'proj')
 | 
			
		||||
        self.context = context.RequestContext(user=self.user,
 | 
			
		||||
                                              project=self.project)
 | 
			
		||||
        host = self.network.get_network_host(self.context.elevated())
 | 
			
		||||
        host = self.network.host
 | 
			
		||||
 | 
			
		||||
        def fake_show(meh, context, id):
 | 
			
		||||
            return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1,
 | 
			
		||||
@@ -83,9 +83,10 @@ class CloudTestCase(test.TestCase):
 | 
			
		||||
        self.stubs.Set(rpc, 'cast', finish_cast)
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        network_ref = db.project_get_network(self.context,
 | 
			
		||||
                                             self.project.id)
 | 
			
		||||
        db.network_disassociate(self.context, network_ref['id'])
 | 
			
		||||
        networks = db.project_get_networks(self.context, self.project.id,
 | 
			
		||||
                                           associate=False)
 | 
			
		||||
        for network in networks:
 | 
			
		||||
            db.network_disassociate(self.context, network['id'])
 | 
			
		||||
        self.manager.delete_project(self.project)
 | 
			
		||||
        self.manager.delete_user(self.user)
 | 
			
		||||
        super(CloudTestCase, self).tearDown()
 | 
			
		||||
@@ -116,6 +117,7 @@ class CloudTestCase(test.TestCase):
 | 
			
		||||
                                  public_ip=address)
 | 
			
		||||
        db.floating_ip_destroy(self.context, address)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("Skipping this pending future merge")
 | 
			
		||||
    def test_allocate_address(self):
 | 
			
		||||
        address = "10.10.10.10"
 | 
			
		||||
        allocate = self.cloud.allocate_address
 | 
			
		||||
@@ -128,6 +130,7 @@ class CloudTestCase(test.TestCase):
 | 
			
		||||
                          allocate,
 | 
			
		||||
                          self.context)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("Skipping this pending future merge")
 | 
			
		||||
    def test_associate_disassociate_address(self):
 | 
			
		||||
        """Verifies associate runs cleanly without raising an exception"""
 | 
			
		||||
        address = "10.10.10.10"
 | 
			
		||||
@@ -135,8 +138,27 @@ class CloudTestCase(test.TestCase):
 | 
			
		||||
                              {'address': address,
 | 
			
		||||
                               'host': self.network.host})
 | 
			
		||||
        self.cloud.allocate_address(self.context)
 | 
			
		||||
        inst = db.instance_create(self.context, {'host': self.compute.host})
 | 
			
		||||
        fixed = self.network.allocate_fixed_ip(self.context, inst['id'])
 | 
			
		||||
        # TODO(jkoelker) Probably need to query for instance_type_id and
 | 
			
		||||
        #                make sure we get a valid one
 | 
			
		||||
        inst = db.instance_create(self.context, {'host': self.compute.host,
 | 
			
		||||
                                                 'instance_type_id': 1})
 | 
			
		||||
        networks = db.network_get_all(self.context)
 | 
			
		||||
        for network in networks:
 | 
			
		||||
            self.network.set_network_host(self.context, network['id'])
 | 
			
		||||
        project_id = self.context.project_id
 | 
			
		||||
        type_id = inst['instance_type_id']
 | 
			
		||||
        ips = self.network.allocate_for_instance(self.context,
 | 
			
		||||
                                                 instance_id=inst['id'],
 | 
			
		||||
                                                 instance_type_id=type_id,
 | 
			
		||||
                                                 project_id=project_id)
 | 
			
		||||
        # TODO(jkoelker) Make this mas bueno
 | 
			
		||||
        self.assertTrue(ips)
 | 
			
		||||
        self.assertTrue('ips' in ips[0][1])
 | 
			
		||||
        self.assertTrue(ips[0][1]['ips'])
 | 
			
		||||
        self.assertTrue('ip' in ips[0][1]['ips'][0])
 | 
			
		||||
 | 
			
		||||
        fixed = ips[0][1]['ips'][0]['ip']
 | 
			
		||||
 | 
			
		||||
        ec2_id = ec2utils.id_to_ec2_id(inst['id'])
 | 
			
		||||
        self.cloud.associate_address(self.context,
 | 
			
		||||
                                     instance_id=ec2_id,
 | 
			
		||||
@@ -217,6 +239,8 @@ class CloudTestCase(test.TestCase):
 | 
			
		||||
        db.service_destroy(self.context, service1['id'])
 | 
			
		||||
        db.service_destroy(self.context, service2['id'])
 | 
			
		||||
 | 
			
		||||
    # NOTE(jkoelker): this test relies on fixed_ip being in instances
 | 
			
		||||
    @test.skip_test("EC2 stuff needs fixed_ip in instance_ref")
 | 
			
		||||
    def test_describe_snapshots(self):
 | 
			
		||||
        """Makes sure describe_snapshots works and filters results."""
 | 
			
		||||
        vol = db.volume_create(self.context, {})
 | 
			
		||||
@@ -548,6 +572,8 @@ class CloudTestCase(test.TestCase):
 | 
			
		||||
        self.assertEqual('c00l 1m4g3', inst['display_name'])
 | 
			
		||||
        db.instance_destroy(self.context, inst['id'])
 | 
			
		||||
 | 
			
		||||
    # NOTE(jkoelker): This test relies on mac_address in instance
 | 
			
		||||
    @test.skip_test("EC2 stuff needs mac_address in instance_ref")
 | 
			
		||||
    def test_update_of_instance_wont_update_private_fields(self):
 | 
			
		||||
        inst = db.instance_create(self.context, {})
 | 
			
		||||
        ec2_id = ec2utils.id_to_ec2_id(inst['id'])
 | 
			
		||||
@@ -611,6 +637,7 @@ class CloudTestCase(test.TestCase):
 | 
			
		||||
        elevated = self.context.elevated(read_deleted=True)
 | 
			
		||||
        self._wait_for_state(elevated, instance_id, is_deleted)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skipping, test is hanging with multinic for rpc reasons")
 | 
			
		||||
    def test_stop_start_instance(self):
 | 
			
		||||
        """Makes sure stop/start instance works"""
 | 
			
		||||
        # enforce periodic tasks run in short time to avoid wait for 60s.
 | 
			
		||||
@@ -666,6 +693,7 @@ class CloudTestCase(test.TestCase):
 | 
			
		||||
        self.assertEqual(vol['status'], "available")
 | 
			
		||||
        self.assertEqual(vol['attach_status'], "detached")
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skipping, test is hanging with multinic for rpc reasons")
 | 
			
		||||
    def test_stop_start_with_volume(self):
 | 
			
		||||
        """Make sure run instance with block device mapping works"""
 | 
			
		||||
 | 
			
		||||
@@ -734,6 +762,7 @@ class CloudTestCase(test.TestCase):
 | 
			
		||||
 | 
			
		||||
        self._restart_compute_service()
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skipping, test is hanging with multinic for rpc reasons")
 | 
			
		||||
    def test_stop_with_attached_volume(self):
 | 
			
		||||
        """Make sure attach info is reflected to block device mapping"""
 | 
			
		||||
        # enforce periodic tasks run in short time to avoid wait for 60s.
 | 
			
		||||
@@ -809,6 +838,7 @@ class CloudTestCase(test.TestCase):
 | 
			
		||||
        greenthread.sleep(0.3)
 | 
			
		||||
        return result['snapshotId']
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skipping, test is hanging with multinic for rpc reasons")
 | 
			
		||||
    def test_run_with_snapshot(self):
 | 
			
		||||
        """Makes sure run/stop/start instance with snapshot works."""
 | 
			
		||||
        vol = self._volume_create()
 | 
			
		||||
 
 | 
			
		||||
@@ -93,7 +93,6 @@ class ComputeTestCase(test.TestCase):
 | 
			
		||||
        inst['project_id'] = self.project.id
 | 
			
		||||
        type_id = instance_types.get_instance_type_by_name('m1.tiny')['id']
 | 
			
		||||
        inst['instance_type_id'] = type_id
 | 
			
		||||
        inst['mac_address'] = utils.generate_mac()
 | 
			
		||||
        inst['ami_launch_index'] = 0
 | 
			
		||||
        inst.update(params)
 | 
			
		||||
        return db.instance_create(self.context, inst)['id']
 | 
			
		||||
@@ -131,7 +130,7 @@ class ComputeTestCase(test.TestCase):
 | 
			
		||||
        instance_ref = models.Instance()
 | 
			
		||||
        instance_ref['id'] = 1
 | 
			
		||||
        instance_ref['volumes'] = [vol1, vol2]
 | 
			
		||||
        instance_ref['hostname'] = 'i-00000001'
 | 
			
		||||
        instance_ref['hostname'] = 'hostname-1'
 | 
			
		||||
        instance_ref['host'] = 'dummy'
 | 
			
		||||
        return instance_ref
 | 
			
		||||
 | 
			
		||||
@@ -163,6 +162,18 @@ class ComputeTestCase(test.TestCase):
 | 
			
		||||
            db.security_group_destroy(self.context, group['id'])
 | 
			
		||||
            db.instance_destroy(self.context, ref[0]['id'])
 | 
			
		||||
 | 
			
		||||
    def test_default_hostname_generator(self):
 | 
			
		||||
        cases = [(None, 'server_1'), ('Hello, Server!', 'hello_server'),
 | 
			
		||||
                 ('<}\x1fh\x10e\x08l\x02l\x05o\x12!{>', 'hello')]
 | 
			
		||||
        for display_name, hostname in cases:
 | 
			
		||||
            ref = self.compute_api.create(self.context,
 | 
			
		||||
                instance_types.get_default_instance_type(), None,
 | 
			
		||||
                display_name=display_name)
 | 
			
		||||
            try:
 | 
			
		||||
                self.assertEqual(ref[0]['hostname'], hostname)
 | 
			
		||||
            finally:
 | 
			
		||||
                db.instance_destroy(self.context, ref[0]['id'])
 | 
			
		||||
 | 
			
		||||
    def test_destroy_instance_disassociates_security_groups(self):
 | 
			
		||||
        """Make sure destroying disassociates security groups"""
 | 
			
		||||
        group = self._create_group()
 | 
			
		||||
@@ -410,6 +421,7 @@ class ComputeTestCase(test.TestCase):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        self.stubs.Set(self.compute.driver, 'finish_resize', fake)
 | 
			
		||||
        self.stubs.Set(self.compute.network_api, 'get_instance_nw_info', fake)
 | 
			
		||||
        context = self.context.elevated()
 | 
			
		||||
        instance_id = self._create_instance()
 | 
			
		||||
        self.compute.prep_resize(context, instance_id, 1)
 | 
			
		||||
@@ -533,7 +545,7 @@ class ComputeTestCase(test.TestCase):
 | 
			
		||||
 | 
			
		||||
        dbmock = self.mox.CreateMock(db)
 | 
			
		||||
        dbmock.instance_get(c, i_id).AndReturn(instance_ref)
 | 
			
		||||
        dbmock.instance_get_fixed_address(c, i_id).AndReturn(None)
 | 
			
		||||
        dbmock.instance_get_fixed_addresses(c, i_id).AndReturn(None)
 | 
			
		||||
 | 
			
		||||
        self.compute.db = dbmock
 | 
			
		||||
        self.mox.ReplayAll()
 | 
			
		||||
@@ -553,7 +565,7 @@ class ComputeTestCase(test.TestCase):
 | 
			
		||||
        drivermock = self.mox.CreateMock(self.compute_driver)
 | 
			
		||||
 | 
			
		||||
        dbmock.instance_get(c, i_ref['id']).AndReturn(i_ref)
 | 
			
		||||
        dbmock.instance_get_fixed_address(c, i_ref['id']).AndReturn('dummy')
 | 
			
		||||
        dbmock.instance_get_fixed_addresses(c, i_ref['id']).AndReturn('dummy')
 | 
			
		||||
        for i in range(len(i_ref['volumes'])):
 | 
			
		||||
            vid = i_ref['volumes'][i]['id']
 | 
			
		||||
            volmock.setup_compute_volume(c, vid).InAnyOrder('g1')
 | 
			
		||||
@@ -581,7 +593,7 @@ class ComputeTestCase(test.TestCase):
 | 
			
		||||
        drivermock = self.mox.CreateMock(self.compute_driver)
 | 
			
		||||
 | 
			
		||||
        dbmock.instance_get(c, i_ref['id']).AndReturn(i_ref)
 | 
			
		||||
        dbmock.instance_get_fixed_address(c, i_ref['id']).AndReturn('dummy')
 | 
			
		||||
        dbmock.instance_get_fixed_addresses(c, i_ref['id']).AndReturn('dummy')
 | 
			
		||||
        self.mox.StubOutWithMock(compute_manager.LOG, 'info')
 | 
			
		||||
        compute_manager.LOG.info(_("%s has no volume."), i_ref['hostname'])
 | 
			
		||||
        netmock.setup_compute_network(c, i_ref['id'])
 | 
			
		||||
@@ -611,7 +623,7 @@ class ComputeTestCase(test.TestCase):
 | 
			
		||||
        volmock = self.mox.CreateMock(self.volume_manager)
 | 
			
		||||
 | 
			
		||||
        dbmock.instance_get(c, i_ref['id']).AndReturn(i_ref)
 | 
			
		||||
        dbmock.instance_get_fixed_address(c, i_ref['id']).AndReturn('dummy')
 | 
			
		||||
        dbmock.instance_get_fixed_addresses(c, i_ref['id']).AndReturn('dummy')
 | 
			
		||||
        for i in range(len(i_ref['volumes'])):
 | 
			
		||||
            volmock.setup_compute_volume(c, i_ref['volumes'][i]['id'])
 | 
			
		||||
        for i in range(FLAGS.live_migration_retry_count):
 | 
			
		||||
 
 | 
			
		||||
@@ -61,7 +61,6 @@ class ConsoleTestCase(test.TestCase):
 | 
			
		||||
        inst['user_id'] = self.user.id
 | 
			
		||||
        inst['project_id'] = self.project.id
 | 
			
		||||
        inst['instance_type_id'] = 1
 | 
			
		||||
        inst['mac_address'] = utils.generate_mac()
 | 
			
		||||
        inst['ami_launch_index'] = 0
 | 
			
		||||
        return db.instance_create(self.context, inst)['id']
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -105,24 +105,25 @@ class DirectTestCase(test.TestCase):
 | 
			
		||||
        self.assertEqual(rv['data'], 'baz')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DirectCloudTestCase(test_cloud.CloudTestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(DirectCloudTestCase, self).setUp()
 | 
			
		||||
        compute_handle = compute.API(image_service=self.cloud.image_service)
 | 
			
		||||
        volume_handle = volume.API()
 | 
			
		||||
        network_handle = network.API()
 | 
			
		||||
        direct.register_service('compute', compute_handle)
 | 
			
		||||
        direct.register_service('volume', volume_handle)
 | 
			
		||||
        direct.register_service('network', network_handle)
 | 
			
		||||
 | 
			
		||||
        self.router = direct.JsonParamsMiddleware(direct.Router())
 | 
			
		||||
        proxy = direct.Proxy(self.router)
 | 
			
		||||
        self.cloud.compute_api = proxy.compute
 | 
			
		||||
        self.cloud.volume_api = proxy.volume
 | 
			
		||||
        self.cloud.network_api = proxy.network
 | 
			
		||||
        compute_handle.volume_api = proxy.volume
 | 
			
		||||
        compute_handle.network_api = proxy.network
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        super(DirectCloudTestCase, self).tearDown()
 | 
			
		||||
        direct.ROUTES = {}
 | 
			
		||||
# NOTE(jkoelker): This fails using the EC2 api
 | 
			
		||||
#class DirectCloudTestCase(test_cloud.CloudTestCase):
 | 
			
		||||
#    def setUp(self):
 | 
			
		||||
#        super(DirectCloudTestCase, self).setUp()
 | 
			
		||||
#        compute_handle = compute.API(image_service=self.cloud.image_service)
 | 
			
		||||
#        volume_handle = volume.API()
 | 
			
		||||
#        network_handle = network.API()
 | 
			
		||||
#        direct.register_service('compute', compute_handle)
 | 
			
		||||
#        direct.register_service('volume', volume_handle)
 | 
			
		||||
#        direct.register_service('network', network_handle)
 | 
			
		||||
#
 | 
			
		||||
#        self.router = direct.JsonParamsMiddleware(direct.Router())
 | 
			
		||||
#        proxy = direct.Proxy(self.router)
 | 
			
		||||
#        self.cloud.compute_api = proxy.compute
 | 
			
		||||
#        self.cloud.volume_api = proxy.volume
 | 
			
		||||
#        self.cloud.network_api = proxy.network
 | 
			
		||||
#        compute_handle.volume_api = proxy.volume
 | 
			
		||||
#        compute_handle.network_api = proxy.network
 | 
			
		||||
#
 | 
			
		||||
#    def tearDown(self):
 | 
			
		||||
#        super(DirectCloudTestCase, self).tearDown()
 | 
			
		||||
#        direct.ROUTES = {}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,161 +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 flat network code
 | 
			
		||||
"""
 | 
			
		||||
import netaddr
 | 
			
		||||
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 = netaddr.IPRange(flags.FLAGS.floating_range)
 | 
			
		||||
        address = str(list(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)
 | 
			
		||||
@@ -54,12 +54,12 @@ def _create_network_info(count=1, ipv6=None):
 | 
			
		||||
    fake_ip = '0.0.0.0/0'
 | 
			
		||||
    fake_ip_2 = '0.0.0.1/0'
 | 
			
		||||
    fake_ip_3 = '0.0.0.1/0'
 | 
			
		||||
    network = {'gateway': fake,
 | 
			
		||||
               'gateway_v6': fake,
 | 
			
		||||
               'bridge': fake,
 | 
			
		||||
    network = {'bridge': fake,
 | 
			
		||||
               'cidr': fake_ip,
 | 
			
		||||
               'cidr_v6': fake_ip}
 | 
			
		||||
    mapping = {'mac': fake,
 | 
			
		||||
               'gateway': fake,
 | 
			
		||||
               'gateway6': fake,
 | 
			
		||||
               'ips': [{'ip': fake_ip}, {'ip': fake_ip}]}
 | 
			
		||||
    if ipv6:
 | 
			
		||||
        mapping['ip6s'] = [{'ip': fake_ip},
 | 
			
		||||
@@ -68,6 +68,24 @@ def _create_network_info(count=1, ipv6=None):
 | 
			
		||||
    return [(network, mapping) for x in xrange(0, count)]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _setup_networking(instance_id, ip='1.2.3.4'):
 | 
			
		||||
    ctxt = context.get_admin_context()
 | 
			
		||||
    network_ref = db.project_get_networks(ctxt,
 | 
			
		||||
                                           'fake',
 | 
			
		||||
                                           associate=True)[0]
 | 
			
		||||
    vif = {'address': '56:12:12:12:12:12',
 | 
			
		||||
           'network_id': network_ref['id'],
 | 
			
		||||
           'instance_id': instance_id}
 | 
			
		||||
    vif_ref = db.virtual_interface_create(ctxt, vif)
 | 
			
		||||
 | 
			
		||||
    fixed_ip = {'address': ip,
 | 
			
		||||
                'network_id': network_ref['id'],
 | 
			
		||||
                'virtual_interface_id': vif_ref['id']}
 | 
			
		||||
    db.fixed_ip_create(ctxt, fixed_ip)
 | 
			
		||||
    db.fixed_ip_update(ctxt, ip, {'allocated': True,
 | 
			
		||||
                                        'instance_id': instance_id})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CacheConcurrencyTestCase(test.TestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(CacheConcurrencyTestCase, self).setUp()
 | 
			
		||||
@@ -155,11 +173,15 @@ class LibvirtConnTestCase(test.TestCase):
 | 
			
		||||
        FLAGS.instances_path = ''
 | 
			
		||||
        self.call_libvirt_dependant_setup = False
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        self.manager.delete_project(self.project)
 | 
			
		||||
        self.manager.delete_user(self.user)
 | 
			
		||||
        super(LibvirtConnTestCase, self).tearDown()
 | 
			
		||||
 | 
			
		||||
    test_ip = '10.11.12.13'
 | 
			
		||||
    test_instance = {'memory_kb':     '1024000',
 | 
			
		||||
                     'basepath':      '/some/path',
 | 
			
		||||
                     'bridge_name':   'br100',
 | 
			
		||||
                     'mac_address':   '02:12:34:46:56:67',
 | 
			
		||||
                     'vcpus':         2,
 | 
			
		||||
                     'project_id':    'fake',
 | 
			
		||||
                     'bridge':        'br101',
 | 
			
		||||
@@ -241,6 +263,7 @@ class LibvirtConnTestCase(test.TestCase):
 | 
			
		||||
 | 
			
		||||
        return db.service_create(context.get_admin_context(), service_ref)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("Please review this test to ensure intent")
 | 
			
		||||
    def test_preparing_xml_info(self):
 | 
			
		||||
        conn = connection.LibvirtConnection(True)
 | 
			
		||||
        instance_ref = db.instance_create(self.context, self.test_instance)
 | 
			
		||||
@@ -272,23 +295,27 @@ class LibvirtConnTestCase(test.TestCase):
 | 
			
		||||
        self.assertTrue(params.find('PROJNETV6') > -1)
 | 
			
		||||
        self.assertTrue(params.find('PROJMASKV6') > -1)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skipping libvirt tests depends on get_network_info shim")
 | 
			
		||||
    def test_xml_and_uri_no_ramdisk_no_kernel(self):
 | 
			
		||||
        instance_data = dict(self.test_instance)
 | 
			
		||||
        self._check_xml_and_uri(instance_data,
 | 
			
		||||
                                expect_kernel=False, expect_ramdisk=False)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skipping libvirt tests depends on get_network_info shim")
 | 
			
		||||
    def test_xml_and_uri_no_ramdisk(self):
 | 
			
		||||
        instance_data = dict(self.test_instance)
 | 
			
		||||
        instance_data['kernel_id'] = 'aki-deadbeef'
 | 
			
		||||
        self._check_xml_and_uri(instance_data,
 | 
			
		||||
                                expect_kernel=True, expect_ramdisk=False)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skipping libvirt tests depends on get_network_info shim")
 | 
			
		||||
    def test_xml_and_uri_no_kernel(self):
 | 
			
		||||
        instance_data = dict(self.test_instance)
 | 
			
		||||
        instance_data['ramdisk_id'] = 'ari-deadbeef'
 | 
			
		||||
        self._check_xml_and_uri(instance_data,
 | 
			
		||||
                                expect_kernel=False, expect_ramdisk=False)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skipping libvirt tests depends on get_network_info shim")
 | 
			
		||||
    def test_xml_and_uri(self):
 | 
			
		||||
        instance_data = dict(self.test_instance)
 | 
			
		||||
        instance_data['ramdisk_id'] = 'ari-deadbeef'
 | 
			
		||||
@@ -296,6 +323,7 @@ class LibvirtConnTestCase(test.TestCase):
 | 
			
		||||
        self._check_xml_and_uri(instance_data,
 | 
			
		||||
                                expect_kernel=True, expect_ramdisk=True)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skipping libvirt tests depends on get_network_info shim")
 | 
			
		||||
    def test_xml_and_uri_rescue(self):
 | 
			
		||||
        instance_data = dict(self.test_instance)
 | 
			
		||||
        instance_data['ramdisk_id'] = 'ari-deadbeef'
 | 
			
		||||
@@ -303,6 +331,7 @@ class LibvirtConnTestCase(test.TestCase):
 | 
			
		||||
        self._check_xml_and_uri(instance_data, expect_kernel=True,
 | 
			
		||||
                                expect_ramdisk=True, rescue=True)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skipping libvirt tests depends on get_network_info shim")
 | 
			
		||||
    def test_lxc_container_and_uri(self):
 | 
			
		||||
        instance_data = dict(self.test_instance)
 | 
			
		||||
        self._check_xml_and_container(instance_data)
 | 
			
		||||
@@ -402,12 +431,18 @@ class LibvirtConnTestCase(test.TestCase):
 | 
			
		||||
        user_context = context.RequestContext(project=self.project,
 | 
			
		||||
                                              user=self.user)
 | 
			
		||||
        instance_ref = db.instance_create(user_context, instance)
 | 
			
		||||
        host = self.network.get_network_host(user_context.elevated())
 | 
			
		||||
        network_ref = db.project_get_network(context.get_admin_context(),
 | 
			
		||||
                                             self.project.id)
 | 
			
		||||
        # Re-get the instance so it's bound to an actual session
 | 
			
		||||
        instance_ref = db.instance_get(user_context, instance_ref['id'])
 | 
			
		||||
        network_ref = db.project_get_networks(context.get_admin_context(),
 | 
			
		||||
                                             self.project.id)[0]
 | 
			
		||||
 | 
			
		||||
        vif = {'address': '56:12:12:12:12:12',
 | 
			
		||||
               'network_id': network_ref['id'],
 | 
			
		||||
               'instance_id': instance_ref['id']}
 | 
			
		||||
        vif_ref = db.virtual_interface_create(self.context, vif)
 | 
			
		||||
        fixed_ip = {'address': self.test_ip,
 | 
			
		||||
                    'network_id': network_ref['id']}
 | 
			
		||||
                    'network_id': network_ref['id'],
 | 
			
		||||
                    'virtual_interface_id': vif_ref['id']}
 | 
			
		||||
 | 
			
		||||
        ctxt = context.get_admin_context()
 | 
			
		||||
        fixed_ip_ref = db.fixed_ip_create(ctxt, fixed_ip)
 | 
			
		||||
@@ -442,18 +477,10 @@ class LibvirtConnTestCase(test.TestCase):
 | 
			
		||||
        user_context = context.RequestContext(project=self.project,
 | 
			
		||||
                                              user=self.user)
 | 
			
		||||
        instance_ref = db.instance_create(user_context, instance)
 | 
			
		||||
        host = self.network.get_network_host(user_context.elevated())
 | 
			
		||||
        network_ref = db.project_get_network(context.get_admin_context(),
 | 
			
		||||
                                             self.project.id)
 | 
			
		||||
        network_ref = db.project_get_networks(context.get_admin_context(),
 | 
			
		||||
                                             self.project.id)[0]
 | 
			
		||||
 | 
			
		||||
        fixed_ip = {'address':    self.test_ip,
 | 
			
		||||
                    'network_id': network_ref['id']}
 | 
			
		||||
 | 
			
		||||
        ctxt = context.get_admin_context()
 | 
			
		||||
        fixed_ip_ref = db.fixed_ip_create(ctxt, fixed_ip)
 | 
			
		||||
        db.fixed_ip_update(ctxt, self.test_ip,
 | 
			
		||||
                                 {'allocated':   True,
 | 
			
		||||
                                  'instance_id': instance_ref['id']})
 | 
			
		||||
        _setup_networking(instance_ref['id'], ip=self.test_ip)
 | 
			
		||||
 | 
			
		||||
        type_uri_map = {'qemu': ('qemu:///system',
 | 
			
		||||
                             [(lambda t: t.find('.').get('type'), 'qemu'),
 | 
			
		||||
@@ -712,6 +739,7 @@ class LibvirtConnTestCase(test.TestCase):
 | 
			
		||||
        db.volume_destroy(self.context, volume_ref['id'])
 | 
			
		||||
        db.instance_destroy(self.context, instance_ref['id'])
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("test needs rewrite: instance no longer has mac_address")
 | 
			
		||||
    def test_spawn_with_network_info(self):
 | 
			
		||||
        # Skip if non-libvirt environment
 | 
			
		||||
        if not self.lazy_load_library_exists():
 | 
			
		||||
@@ -730,8 +758,8 @@ class LibvirtConnTestCase(test.TestCase):
 | 
			
		||||
        conn.firewall_driver.setattr('setup_basic_filtering', fake_none)
 | 
			
		||||
        conn.firewall_driver.setattr('prepare_instance_filter', fake_none)
 | 
			
		||||
 | 
			
		||||
        network = db.project_get_network(context.get_admin_context(),
 | 
			
		||||
                                         self.project.id)
 | 
			
		||||
        network = db.project_get_networks(context.get_admin_context(),
 | 
			
		||||
                                          self.project.id)[0]
 | 
			
		||||
        ip_dict = {'ip': self.test_ip,
 | 
			
		||||
                   'netmask': network['netmask'],
 | 
			
		||||
                   'enabled': '1'}
 | 
			
		||||
@@ -756,11 +784,6 @@ class LibvirtConnTestCase(test.TestCase):
 | 
			
		||||
        ip = conn.get_host_ip_addr()
 | 
			
		||||
        self.assertEquals(ip, FLAGS.my_ip)
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        self.manager.delete_project(self.project)
 | 
			
		||||
        self.manager.delete_user(self.user)
 | 
			
		||||
        super(LibvirtConnTestCase, self).tearDown()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NWFilterFakes:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
@@ -866,19 +889,24 @@ class IptablesFirewallTestCase(test.TestCase):
 | 
			
		||||
        return db.instance_create(self.context,
 | 
			
		||||
                                  {'user_id': 'fake',
 | 
			
		||||
                                   'project_id': 'fake',
 | 
			
		||||
                                   'mac_address': '56:12:12:12:12:12',
 | 
			
		||||
                                   'instance_type_id': 1})
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skipping libvirt tests depends on get_network_info shim")
 | 
			
		||||
    def test_static_filters(self):
 | 
			
		||||
        instance_ref = self._create_instance_ref()
 | 
			
		||||
        ip = '10.11.12.13'
 | 
			
		||||
 | 
			
		||||
        network_ref = db.project_get_network(self.context,
 | 
			
		||||
                                             'fake')
 | 
			
		||||
        network_ref = db.project_get_networks(self.context,
 | 
			
		||||
                                               'fake',
 | 
			
		||||
                                               associate=True)[0]
 | 
			
		||||
        vif = {'address': '56:12:12:12:12:12',
 | 
			
		||||
               'network_id': network_ref['id'],
 | 
			
		||||
               'instance_id': instance_ref['id']}
 | 
			
		||||
        vif_ref = db.virtual_interface_create(self.context, vif)
 | 
			
		||||
 | 
			
		||||
        fixed_ip = {'address': ip,
 | 
			
		||||
                    'network_id': network_ref['id']}
 | 
			
		||||
 | 
			
		||||
                    'network_id': network_ref['id'],
 | 
			
		||||
                    'virtual_interface_id': vif_ref['id']}
 | 
			
		||||
        admin_ctxt = context.get_admin_context()
 | 
			
		||||
        db.fixed_ip_create(admin_ctxt, fixed_ip)
 | 
			
		||||
        db.fixed_ip_update(admin_ctxt, ip, {'allocated': True,
 | 
			
		||||
@@ -1015,6 +1043,7 @@ class IptablesFirewallTestCase(test.TestCase):
 | 
			
		||||
        self.assertEquals(ipv6_network_rules,
 | 
			
		||||
                          ipv6_rules_per_network * networks_count)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skipping libvirt tests")
 | 
			
		||||
    def test_do_refresh_security_group_rules(self):
 | 
			
		||||
        instance_ref = self._create_instance_ref()
 | 
			
		||||
        self.mox.StubOutWithMock(self.fw,
 | 
			
		||||
@@ -1025,6 +1054,7 @@ class IptablesFirewallTestCase(test.TestCase):
 | 
			
		||||
        self.mox.ReplayAll()
 | 
			
		||||
        self.fw.do_refresh_security_group_rules("fake")
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skip libvirt test project_get_network no longer exists")
 | 
			
		||||
    def test_unfilter_instance_undefines_nwfilter(self):
 | 
			
		||||
        # Skip if non-libvirt environment
 | 
			
		||||
        if not self.lazy_load_library_exists():
 | 
			
		||||
@@ -1058,6 +1088,7 @@ class IptablesFirewallTestCase(test.TestCase):
 | 
			
		||||
 | 
			
		||||
        db.instance_destroy(admin_ctxt, instance_ref['id'])
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skip libvirt test project_get_network no longer exists")
 | 
			
		||||
    def test_provider_firewall_rules(self):
 | 
			
		||||
        # setup basic instance data
 | 
			
		||||
        instance_ref = self._create_instance_ref()
 | 
			
		||||
@@ -1207,7 +1238,6 @@ class NWFilterTestCase(test.TestCase):
 | 
			
		||||
        return db.instance_create(self.context,
 | 
			
		||||
                                  {'user_id': 'fake',
 | 
			
		||||
                                   'project_id': 'fake',
 | 
			
		||||
                                   'mac_address': '00:A0:C9:14:C8:29',
 | 
			
		||||
                                   'instance_type_id': 1})
 | 
			
		||||
 | 
			
		||||
    def _create_instance_type(self, params={}):
 | 
			
		||||
@@ -1225,6 +1255,7 @@ class NWFilterTestCase(test.TestCase):
 | 
			
		||||
        inst.update(params)
 | 
			
		||||
        return db.instance_type_create(context, inst)['id']
 | 
			
		||||
 | 
			
		||||
    @test.skip_test('Skipping this test')
 | 
			
		||||
    def test_creates_base_rule_first(self):
 | 
			
		||||
        # These come pre-defined by libvirt
 | 
			
		||||
        self.defined_filters = ['no-mac-spoofing',
 | 
			
		||||
@@ -1258,13 +1289,15 @@ class NWFilterTestCase(test.TestCase):
 | 
			
		||||
 | 
			
		||||
        ip = '10.11.12.13'
 | 
			
		||||
 | 
			
		||||
        network_ref = db.project_get_network(self.context, 'fake')
 | 
			
		||||
        fixed_ip = {'address': ip, 'network_id': network_ref['id']}
 | 
			
		||||
        #network_ref = db.project_get_networks(self.context, 'fake')[0]
 | 
			
		||||
        #fixed_ip = {'address': ip, 'network_id': network_ref['id']}
 | 
			
		||||
 | 
			
		||||
        admin_ctxt = context.get_admin_context()
 | 
			
		||||
        db.fixed_ip_create(admin_ctxt, fixed_ip)
 | 
			
		||||
        db.fixed_ip_update(admin_ctxt, ip, {'allocated': True,
 | 
			
		||||
                                            'instance_id': inst_id})
 | 
			
		||||
        #admin_ctxt = context.get_admin_context()
 | 
			
		||||
        #db.fixed_ip_create(admin_ctxt, fixed_ip)
 | 
			
		||||
        #db.fixed_ip_update(admin_ctxt, ip, {'allocated': True,
 | 
			
		||||
        #                                    'instance_id': inst_id})
 | 
			
		||||
 | 
			
		||||
        self._setup_networking(instance_ref['id'], ip=ip)
 | 
			
		||||
 | 
			
		||||
        def _ensure_all_called():
 | 
			
		||||
            instance_filter = 'nova-instance-%s-%s' % (instance_ref['name'],
 | 
			
		||||
@@ -1299,6 +1332,7 @@ class NWFilterTestCase(test.TestCase):
 | 
			
		||||
                                                 "fake")
 | 
			
		||||
        self.assertEquals(len(result), 3)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("skip libvirt test project_get_network no longer exists")
 | 
			
		||||
    def test_unfilter_instance_undefines_nwfilters(self):
 | 
			
		||||
        admin_ctxt = context.get_admin_context()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,196 +1,240 @@
 | 
			
		||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 | 
			
		||||
 | 
			
		||||
# Copyright 2010 United States Government as represented by the
 | 
			
		||||
# Administrator of the National Aeronautics and Space Administration.
 | 
			
		||||
# Copyright 2011 Rackspace
 | 
			
		||||
# 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
 | 
			
		||||
# 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
 | 
			
		||||
#      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 netaddr
 | 
			
		||||
import os
 | 
			
		||||
# 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 nova import db
 | 
			
		||||
from nova import flags
 | 
			
		||||
from nova import log as logging
 | 
			
		||||
from nova import test
 | 
			
		||||
from nova.network import linux_net
 | 
			
		||||
from nova.network import manager as network_manager
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IptablesManagerTestCase(test.TestCase):
 | 
			
		||||
    sample_filter = ['#Generated by iptables-save on Fri Feb 18 15:17:05 2011',
 | 
			
		||||
                     '*filter',
 | 
			
		||||
                     ':INPUT ACCEPT [2223527:305688874]',
 | 
			
		||||
                     ':FORWARD ACCEPT [0:0]',
 | 
			
		||||
                     ':OUTPUT ACCEPT [2172501:140856656]',
 | 
			
		||||
                     ':nova-compute-FORWARD - [0:0]',
 | 
			
		||||
                     ':nova-compute-INPUT - [0:0]',
 | 
			
		||||
                     ':nova-compute-local - [0:0]',
 | 
			
		||||
                     ':nova-compute-OUTPUT - [0:0]',
 | 
			
		||||
                     ':nova-filter-top - [0:0]',
 | 
			
		||||
                     '-A FORWARD -j nova-filter-top ',
 | 
			
		||||
                     '-A OUTPUT -j nova-filter-top ',
 | 
			
		||||
                     '-A nova-filter-top -j nova-compute-local ',
 | 
			
		||||
                     '-A INPUT -j nova-compute-INPUT ',
 | 
			
		||||
                     '-A OUTPUT -j nova-compute-OUTPUT ',
 | 
			
		||||
                     '-A FORWARD -j nova-compute-FORWARD ',
 | 
			
		||||
                     '-A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT ',
 | 
			
		||||
                     '-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT ',
 | 
			
		||||
                     '-A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT ',
 | 
			
		||||
                     '-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT ',
 | 
			
		||||
                     '-A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT ',
 | 
			
		||||
                     '-A FORWARD -i virbr0 -o virbr0 -j ACCEPT ',
 | 
			
		||||
                     '-A FORWARD -o virbr0 -j REJECT --reject-with '
 | 
			
		||||
                     'icmp-port-unreachable ',
 | 
			
		||||
                     '-A FORWARD -i virbr0 -j REJECT --reject-with '
 | 
			
		||||
                     'icmp-port-unreachable ',
 | 
			
		||||
                     'COMMIT',
 | 
			
		||||
                     '# Completed on Fri Feb 18 15:17:05 2011']
 | 
			
		||||
import mox
 | 
			
		||||
 | 
			
		||||
    sample_nat = ['# Generated by iptables-save on Fri Feb 18 15:17:05 2011',
 | 
			
		||||
                  '*nat',
 | 
			
		||||
                  ':PREROUTING ACCEPT [3936:762355]',
 | 
			
		||||
                  ':INPUT ACCEPT [2447:225266]',
 | 
			
		||||
                  ':OUTPUT ACCEPT [63491:4191863]',
 | 
			
		||||
                  ':POSTROUTING ACCEPT [63112:4108641]',
 | 
			
		||||
                  ':nova-compute-OUTPUT - [0:0]',
 | 
			
		||||
                  ':nova-compute-floating-ip-snat - [0:0]',
 | 
			
		||||
                  ':nova-compute-SNATTING - [0:0]',
 | 
			
		||||
                  ':nova-compute-PREROUTING - [0:0]',
 | 
			
		||||
                  ':nova-compute-POSTROUTING - [0:0]',
 | 
			
		||||
                  ':nova-postrouting-bottom - [0:0]',
 | 
			
		||||
                  '-A PREROUTING -j nova-compute-PREROUTING ',
 | 
			
		||||
                  '-A OUTPUT -j nova-compute-OUTPUT ',
 | 
			
		||||
                  '-A POSTROUTING -j nova-compute-POSTROUTING ',
 | 
			
		||||
                  '-A POSTROUTING -j nova-postrouting-bottom ',
 | 
			
		||||
                  '-A nova-postrouting-bottom -j nova-compute-SNATTING ',
 | 
			
		||||
                  '-A nova-compute-SNATTING -j nova-compute-floating-ip-snat ',
 | 
			
		||||
                  'COMMIT',
 | 
			
		||||
                  '# Completed on Fri Feb 18 15:17:05 2011']
 | 
			
		||||
 | 
			
		||||
FLAGS = flags.FLAGS
 | 
			
		||||
LOG = logging.getLogger('nova.tests.network')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
HOST = "testhost"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FakeModel(dict):
 | 
			
		||||
    """Represent a model from the db"""
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        self.update(kwargs)
 | 
			
		||||
 | 
			
		||||
        def __getattr__(self, name):
 | 
			
		||||
            return self[name]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
networks = [{'id': 0,
 | 
			
		||||
             'label': 'test0',
 | 
			
		||||
             'injected': False,
 | 
			
		||||
             'cidr': '192.168.0.0/24',
 | 
			
		||||
             'cidr_v6': '2001:db8::/64',
 | 
			
		||||
             'gateway_v6': '2001:db8::1',
 | 
			
		||||
             'netmask_v6': '64',
 | 
			
		||||
             'netmask': '255.255.255.0',
 | 
			
		||||
             'bridge': 'fa0',
 | 
			
		||||
             'bridge_interface': 'fake_fa0',
 | 
			
		||||
             'gateway': '192.168.0.1',
 | 
			
		||||
             'broadcast': '192.168.0.255',
 | 
			
		||||
             'dns': '192.168.0.1',
 | 
			
		||||
             'vlan': None,
 | 
			
		||||
             'host': None,
 | 
			
		||||
             'project_id': 'fake_project',
 | 
			
		||||
             'vpn_public_address': '192.168.0.2'},
 | 
			
		||||
            {'id': 1,
 | 
			
		||||
             'label': 'test1',
 | 
			
		||||
             'injected': False,
 | 
			
		||||
             'cidr': '192.168.1.0/24',
 | 
			
		||||
             'cidr_v6': '2001:db9::/64',
 | 
			
		||||
             'gateway_v6': '2001:db9::1',
 | 
			
		||||
             'netmask_v6': '64',
 | 
			
		||||
             'netmask': '255.255.255.0',
 | 
			
		||||
             'bridge': 'fa1',
 | 
			
		||||
             'bridge_interface': 'fake_fa1',
 | 
			
		||||
             'gateway': '192.168.1.1',
 | 
			
		||||
             'broadcast': '192.168.1.255',
 | 
			
		||||
             'dns': '192.168.0.1',
 | 
			
		||||
             'vlan': None,
 | 
			
		||||
             'host': None,
 | 
			
		||||
             'project_id': 'fake_project',
 | 
			
		||||
             'vpn_public_address': '192.168.1.2'}]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fixed_ips = [{'id': 0,
 | 
			
		||||
              'network_id': 0,
 | 
			
		||||
              'address': '192.168.0.100',
 | 
			
		||||
              'instance_id': 0,
 | 
			
		||||
              'allocated': False,
 | 
			
		||||
              'virtual_interface_id': 0,
 | 
			
		||||
              'floating_ips': []},
 | 
			
		||||
             {'id': 0,
 | 
			
		||||
              'network_id': 1,
 | 
			
		||||
              'address': '192.168.1.100',
 | 
			
		||||
              'instance_id': 0,
 | 
			
		||||
              'allocated': False,
 | 
			
		||||
              'virtual_interface_id': 0,
 | 
			
		||||
              'floating_ips': []}]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
flavor = {'id': 0,
 | 
			
		||||
          'rxtx_cap': 3}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
floating_ip_fields = {'id': 0,
 | 
			
		||||
                      'address': '192.168.10.100',
 | 
			
		||||
                      'fixed_ip_id': 0,
 | 
			
		||||
                      'project_id': None,
 | 
			
		||||
                      'auto_assigned': False}
 | 
			
		||||
 | 
			
		||||
vifs = [{'id': 0,
 | 
			
		||||
         'address': 'DE:AD:BE:EF:00:00',
 | 
			
		||||
         'network_id': 0,
 | 
			
		||||
         'network': FakeModel(**networks[0]),
 | 
			
		||||
         'instance_id': 0},
 | 
			
		||||
        {'id': 1,
 | 
			
		||||
         'address': 'DE:AD:BE:EF:00:01',
 | 
			
		||||
         'network_id': 1,
 | 
			
		||||
         'network': FakeModel(**networks[1]),
 | 
			
		||||
         'instance_id': 0}]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FlatNetworkTestCase(test.TestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(IptablesManagerTestCase, self).setUp()
 | 
			
		||||
        self.manager = linux_net.IptablesManager()
 | 
			
		||||
        super(FlatNetworkTestCase, self).setUp()
 | 
			
		||||
        self.network = network_manager.FlatManager(host=HOST)
 | 
			
		||||
        self.network.db = db
 | 
			
		||||
 | 
			
		||||
    def test_filter_rules_are_wrapped(self):
 | 
			
		||||
        current_lines = self.sample_filter
 | 
			
		||||
    def test_set_network_hosts(self):
 | 
			
		||||
        self.mox.StubOutWithMock(db, 'network_get_all')
 | 
			
		||||
        self.mox.StubOutWithMock(db, 'network_set_host')
 | 
			
		||||
        self.mox.StubOutWithMock(db, 'network_update')
 | 
			
		||||
 | 
			
		||||
        table = self.manager.ipv4['filter']
 | 
			
		||||
        table.add_rule('FORWARD', '-s 1.2.3.4/5 -j DROP')
 | 
			
		||||
        new_lines = self.manager._modify_rules(current_lines, table)
 | 
			
		||||
        self.assertTrue('-A run_tests.py-FORWARD '
 | 
			
		||||
                        '-s 1.2.3.4/5 -j DROP' in new_lines)
 | 
			
		||||
        db.network_get_all(mox.IgnoreArg()).AndReturn([networks[0]])
 | 
			
		||||
        db.network_set_host(mox.IgnoreArg(),
 | 
			
		||||
                            networks[0]['id'],
 | 
			
		||||
                            mox.IgnoreArg()).AndReturn(HOST)
 | 
			
		||||
        db.network_update(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg())
 | 
			
		||||
        self.mox.ReplayAll()
 | 
			
		||||
 | 
			
		||||
        table.remove_rule('FORWARD', '-s 1.2.3.4/5 -j DROP')
 | 
			
		||||
        new_lines = self.manager._modify_rules(current_lines, table)
 | 
			
		||||
        self.assertTrue('-A run_tests.py-FORWARD '
 | 
			
		||||
                        '-s 1.2.3.4/5 -j DROP' not in new_lines)
 | 
			
		||||
        self.network.set_network_hosts(None)
 | 
			
		||||
 | 
			
		||||
    def test_nat_rules(self):
 | 
			
		||||
        current_lines = self.sample_nat
 | 
			
		||||
        new_lines = self.manager._modify_rules(current_lines,
 | 
			
		||||
                                               self.manager.ipv4['nat'])
 | 
			
		||||
    def test_get_instance_nw_info(self):
 | 
			
		||||
        self.mox.StubOutWithMock(db, 'fixed_ip_get_by_instance')
 | 
			
		||||
        self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance')
 | 
			
		||||
        self.mox.StubOutWithMock(db, 'instance_type_get_by_id')
 | 
			
		||||
 | 
			
		||||
        for line in [':nova-compute-OUTPUT - [0:0]',
 | 
			
		||||
                     ':nova-compute-floating-ip-snat - [0:0]',
 | 
			
		||||
                     ':nova-compute-SNATTING - [0:0]',
 | 
			
		||||
                     ':nova-compute-PREROUTING - [0:0]',
 | 
			
		||||
                     ':nova-compute-POSTROUTING - [0:0]']:
 | 
			
		||||
            self.assertTrue(line in new_lines, "One of nova-compute's chains "
 | 
			
		||||
                                               "went missing.")
 | 
			
		||||
        db.fixed_ip_get_by_instance(mox.IgnoreArg(),
 | 
			
		||||
                                    mox.IgnoreArg()).AndReturn(fixed_ips)
 | 
			
		||||
        db.virtual_interface_get_by_instance(mox.IgnoreArg(),
 | 
			
		||||
                                             mox.IgnoreArg()).AndReturn(vifs)
 | 
			
		||||
        db.instance_type_get_by_id(mox.IgnoreArg(),
 | 
			
		||||
                                   mox.IgnoreArg()).AndReturn(flavor)
 | 
			
		||||
        self.mox.ReplayAll()
 | 
			
		||||
 | 
			
		||||
        seen_lines = set()
 | 
			
		||||
        for line in new_lines:
 | 
			
		||||
            line = line.strip()
 | 
			
		||||
            self.assertTrue(line not in seen_lines,
 | 
			
		||||
                            "Duplicate line: %s" % line)
 | 
			
		||||
            seen_lines.add(line)
 | 
			
		||||
        nw_info = self.network.get_instance_nw_info(None, 0, 0)
 | 
			
		||||
 | 
			
		||||
        last_postrouting_line = ''
 | 
			
		||||
        self.assertTrue(nw_info)
 | 
			
		||||
 | 
			
		||||
        for line in new_lines:
 | 
			
		||||
            if line.startswith('-A POSTROUTING'):
 | 
			
		||||
                last_postrouting_line = line
 | 
			
		||||
        for i, nw in enumerate(nw_info):
 | 
			
		||||
            i8 = i + 8
 | 
			
		||||
            check = {'bridge': 'fa%s' % i,
 | 
			
		||||
                     'cidr': '192.168.%s.0/24' % i,
 | 
			
		||||
                     'cidr_v6': '2001:db%s::/64' % i8,
 | 
			
		||||
                     'id': i,
 | 
			
		||||
                     'injected': 'DONTCARE'}
 | 
			
		||||
 | 
			
		||||
        self.assertTrue('-j nova-postrouting-bottom' in last_postrouting_line,
 | 
			
		||||
                        "Last POSTROUTING rule does not jump to "
 | 
			
		||||
                        "nova-postouting-bottom: %s" % last_postrouting_line)
 | 
			
		||||
            self.assertDictMatch(nw[0], check)
 | 
			
		||||
 | 
			
		||||
        for chain in ['POSTROUTING', 'PREROUTING', 'OUTPUT']:
 | 
			
		||||
            self.assertTrue('-A %s -j run_tests.py-%s' \
 | 
			
		||||
                            % (chain, chain) in new_lines,
 | 
			
		||||
                            "Built-in chain %s not wrapped" % (chain,))
 | 
			
		||||
            check = {'broadcast': '192.168.%s.255' % i,
 | 
			
		||||
                     'dns': 'DONTCARE',
 | 
			
		||||
                     'gateway': '192.168.%s.1' % i,
 | 
			
		||||
                     'gateway6': '2001:db%s::1' % i8,
 | 
			
		||||
                     'ip6s': 'DONTCARE',
 | 
			
		||||
                     'ips': 'DONTCARE',
 | 
			
		||||
                     'label': 'test%s' % i,
 | 
			
		||||
                     'mac': 'DE:AD:BE:EF:00:0%s' % i,
 | 
			
		||||
                     'rxtx_cap': 'DONTCARE'}
 | 
			
		||||
            self.assertDictMatch(nw[1], check)
 | 
			
		||||
 | 
			
		||||
    def test_filter_rules(self):
 | 
			
		||||
        current_lines = self.sample_filter
 | 
			
		||||
        new_lines = self.manager._modify_rules(current_lines,
 | 
			
		||||
                                               self.manager.ipv4['filter'])
 | 
			
		||||
            check = [{'enabled': 'DONTCARE',
 | 
			
		||||
                      'ip': '2001:db%s::dcad:beff:feef:%s' % (i8, i),
 | 
			
		||||
                      'netmask': '64'}]
 | 
			
		||||
            self.assertDictListMatch(nw[1]['ip6s'], check)
 | 
			
		||||
 | 
			
		||||
        for line in [':nova-compute-FORWARD - [0:0]',
 | 
			
		||||
                     ':nova-compute-INPUT - [0:0]',
 | 
			
		||||
                     ':nova-compute-local - [0:0]',
 | 
			
		||||
                     ':nova-compute-OUTPUT - [0:0]']:
 | 
			
		||||
            self.assertTrue(line in new_lines, "One of nova-compute's chains"
 | 
			
		||||
                                               " went missing.")
 | 
			
		||||
            check = [{'enabled': '1',
 | 
			
		||||
                      'ip': '192.168.%s.100' % i,
 | 
			
		||||
                      'netmask': '255.255.255.0'}]
 | 
			
		||||
            self.assertDictListMatch(nw[1]['ips'], check)
 | 
			
		||||
 | 
			
		||||
        seen_lines = set()
 | 
			
		||||
        for line in new_lines:
 | 
			
		||||
            line = line.strip()
 | 
			
		||||
            self.assertTrue(line not in seen_lines,
 | 
			
		||||
                            "Duplicate line: %s" % line)
 | 
			
		||||
            seen_lines.add(line)
 | 
			
		||||
 | 
			
		||||
        for chain in ['FORWARD', 'OUTPUT']:
 | 
			
		||||
            for line in new_lines:
 | 
			
		||||
                if line.startswith('-A %s' % chain):
 | 
			
		||||
                    self.assertTrue('-j nova-filter-top' in line,
 | 
			
		||||
                                    "First %s rule does not "
 | 
			
		||||
                                    "jump to nova-filter-top" % chain)
 | 
			
		||||
                    break
 | 
			
		||||
class VlanNetworkTestCase(test.TestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(VlanNetworkTestCase, self).setUp()
 | 
			
		||||
        self.network = network_manager.VlanManager(host=HOST)
 | 
			
		||||
        self.network.db = db
 | 
			
		||||
 | 
			
		||||
        self.assertTrue('-A nova-filter-top '
 | 
			
		||||
                        '-j run_tests.py-local' in new_lines,
 | 
			
		||||
                        "nova-filter-top does not jump to wrapped local chain")
 | 
			
		||||
    def test_vpn_allocate_fixed_ip(self):
 | 
			
		||||
        self.mox.StubOutWithMock(db, 'fixed_ip_associate')
 | 
			
		||||
        self.mox.StubOutWithMock(db, 'fixed_ip_update')
 | 
			
		||||
        self.mox.StubOutWithMock(db,
 | 
			
		||||
                              'virtual_interface_get_by_instance_and_network')
 | 
			
		||||
 | 
			
		||||
        for chain in ['INPUT', 'OUTPUT', 'FORWARD']:
 | 
			
		||||
            self.assertTrue('-A %s -j run_tests.py-%s' \
 | 
			
		||||
                            % (chain, chain) in new_lines,
 | 
			
		||||
                            "Built-in chain %s not wrapped" % (chain,))
 | 
			
		||||
        db.fixed_ip_associate(mox.IgnoreArg(),
 | 
			
		||||
                              mox.IgnoreArg(),
 | 
			
		||||
                              mox.IgnoreArg()).AndReturn('192.168.0.1')
 | 
			
		||||
        db.fixed_ip_update(mox.IgnoreArg(),
 | 
			
		||||
                           mox.IgnoreArg(),
 | 
			
		||||
                           mox.IgnoreArg())
 | 
			
		||||
        db.virtual_interface_get_by_instance_and_network(mox.IgnoreArg(),
 | 
			
		||||
                mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({'id': 0})
 | 
			
		||||
        self.mox.ReplayAll()
 | 
			
		||||
 | 
			
		||||
    def test_will_empty_chain(self):
 | 
			
		||||
        self.manager.ipv4['filter'].add_chain('test-chain')
 | 
			
		||||
        self.manager.ipv4['filter'].add_rule('test-chain', '-j DROP')
 | 
			
		||||
        old_count = len(self.manager.ipv4['filter'].rules)
 | 
			
		||||
        self.manager.ipv4['filter'].empty_chain('test-chain')
 | 
			
		||||
        self.assertEqual(old_count - 1, len(self.manager.ipv4['filter'].rules))
 | 
			
		||||
        network = dict(networks[0])
 | 
			
		||||
        network['vpn_private_address'] = '192.168.0.2'
 | 
			
		||||
        self.network.allocate_fixed_ip(None, 0, network, vpn=True)
 | 
			
		||||
 | 
			
		||||
    def test_will_empty_unwrapped_chain(self):
 | 
			
		||||
        self.manager.ipv4['filter'].add_chain('test-chain', wrap=False)
 | 
			
		||||
        self.manager.ipv4['filter'].add_rule('test-chain', '-j DROP',
 | 
			
		||||
                                             wrap=False)
 | 
			
		||||
        old_count = len(self.manager.ipv4['filter'].rules)
 | 
			
		||||
        self.manager.ipv4['filter'].empty_chain('test-chain', wrap=False)
 | 
			
		||||
        self.assertEqual(old_count - 1, len(self.manager.ipv4['filter'].rules))
 | 
			
		||||
    def test_allocate_fixed_ip(self):
 | 
			
		||||
        self.mox.StubOutWithMock(db, 'fixed_ip_associate_pool')
 | 
			
		||||
        self.mox.StubOutWithMock(db, 'fixed_ip_update')
 | 
			
		||||
        self.mox.StubOutWithMock(db,
 | 
			
		||||
                              'virtual_interface_get_by_instance_and_network')
 | 
			
		||||
 | 
			
		||||
    def test_will_not_empty_wrapped_when_unwrapped(self):
 | 
			
		||||
        self.manager.ipv4['filter'].add_chain('test-chain')
 | 
			
		||||
        self.manager.ipv4['filter'].add_rule('test-chain', '-j DROP')
 | 
			
		||||
        old_count = len(self.manager.ipv4['filter'].rules)
 | 
			
		||||
        self.manager.ipv4['filter'].empty_chain('test-chain', wrap=False)
 | 
			
		||||
        self.assertEqual(old_count, len(self.manager.ipv4['filter'].rules))
 | 
			
		||||
        db.fixed_ip_associate_pool(mox.IgnoreArg(),
 | 
			
		||||
                                   mox.IgnoreArg(),
 | 
			
		||||
                                   mox.IgnoreArg()).AndReturn('192.168.0.1')
 | 
			
		||||
        db.fixed_ip_update(mox.IgnoreArg(),
 | 
			
		||||
                           mox.IgnoreArg(),
 | 
			
		||||
                           mox.IgnoreArg())
 | 
			
		||||
        db.virtual_interface_get_by_instance_and_network(mox.IgnoreArg(),
 | 
			
		||||
                mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({'id': 0})
 | 
			
		||||
        self.mox.ReplayAll()
 | 
			
		||||
 | 
			
		||||
    def test_will_not_empty_unwrapped_when_wrapped(self):
 | 
			
		||||
        self.manager.ipv4['filter'].add_chain('test-chain', wrap=False)
 | 
			
		||||
        self.manager.ipv4['filter'].add_rule('test-chain', '-j DROP',
 | 
			
		||||
                                             wrap=False)
 | 
			
		||||
        old_count = len(self.manager.ipv4['filter'].rules)
 | 
			
		||||
        self.manager.ipv4['filter'].empty_chain('test-chain')
 | 
			
		||||
        self.assertEqual(old_count, len(self.manager.ipv4['filter'].rules))
 | 
			
		||||
        network = dict(networks[0])
 | 
			
		||||
        network['vpn_private_address'] = '192.168.0.2'
 | 
			
		||||
        self.network.allocate_fixed_ip(None, 0, network)
 | 
			
		||||
 | 
			
		||||
    def test_create_networks_too_big(self):
 | 
			
		||||
        self.assertRaises(ValueError, self.network.create_networks, None,
 | 
			
		||||
                          num_networks=4094, vlan_start=1)
 | 
			
		||||
 | 
			
		||||
    def test_create_networks_too_many(self):
 | 
			
		||||
        self.assertRaises(ValueError, self.network.create_networks, None,
 | 
			
		||||
                          num_networks=100, vlan_start=1,
 | 
			
		||||
                          cidr='192.168.0.1/24', network_size=100)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,242 +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 vlan network code
 | 
			
		||||
"""
 | 
			
		||||
import netaddr
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
from nova import context
 | 
			
		||||
from nova import db
 | 
			
		||||
from nova import exception
 | 
			
		||||
from nova import flags
 | 
			
		||||
from nova import log as logging
 | 
			
		||||
from nova import test
 | 
			
		||||
from nova import utils
 | 
			
		||||
from nova.auth import manager
 | 
			
		||||
from nova.tests.network import base
 | 
			
		||||
from nova.tests.network import binpath,\
 | 
			
		||||
    lease_ip, release_ip
 | 
			
		||||
 | 
			
		||||
FLAGS = flags.FLAGS
 | 
			
		||||
LOG = logging.getLogger('nova.tests.network')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VlanNetworkTestCase(base.NetworkTestCase):
 | 
			
		||||
    """Test cases for network code"""
 | 
			
		||||
    def test_public_network_association(self):
 | 
			
		||||
        """Makes sure that we can allocaate a public ip"""
 | 
			
		||||
        # TODO(vish): better way of adding floating ips
 | 
			
		||||
        self.context._project = self.projects[0]
 | 
			
		||||
        self.context.project_id = self.projects[0].id
 | 
			
		||||
        pubnet = netaddr.IPNetwork(flags.FLAGS.floating_range)
 | 
			
		||||
        address = str(list(pubnet)[0])
 | 
			
		||||
        try:
 | 
			
		||||
            db.floating_ip_get_by_address(context.get_admin_context(), address)
 | 
			
		||||
        except exception.NotFound:
 | 
			
		||||
            db.floating_ip_create(context.get_admin_context(),
 | 
			
		||||
                                  {'address': address,
 | 
			
		||||
                                   'host': FLAGS.host})
 | 
			
		||||
        float_addr = self.network.allocate_floating_ip(self.context,
 | 
			
		||||
                                                       self.projects[0].id)
 | 
			
		||||
        fix_addr = self._create_address(0)
 | 
			
		||||
        lease_ip(fix_addr)
 | 
			
		||||
        self.assertEqual(float_addr, str(pubnet[0]))
 | 
			
		||||
        self.network.associate_floating_ip(self.context, float_addr, fix_addr)
 | 
			
		||||
        address = db.instance_get_floating_address(context.get_admin_context(),
 | 
			
		||||
                                                   self.instance_id)
 | 
			
		||||
        self.assertEqual(address, float_addr)
 | 
			
		||||
        self.network.disassociate_floating_ip(self.context, float_addr)
 | 
			
		||||
        address = db.instance_get_floating_address(context.get_admin_context(),
 | 
			
		||||
                                                   self.instance_id)
 | 
			
		||||
        self.assertEqual(address, None)
 | 
			
		||||
        self.network.deallocate_floating_ip(self.context, float_addr)
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, fix_addr)
 | 
			
		||||
        release_ip(fix_addr)
 | 
			
		||||
        db.floating_ip_destroy(context.get_admin_context(), float_addr)
 | 
			
		||||
 | 
			
		||||
    def test_allocate_deallocate_fixed_ip(self):
 | 
			
		||||
        """Makes sure that we can allocate and deallocate a fixed ip"""
 | 
			
		||||
        address = self._create_address(0)
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address,
 | 
			
		||||
                                                      self.projects[0].id))
 | 
			
		||||
        lease_ip(address)
 | 
			
		||||
        self._deallocate_address(0, address)
 | 
			
		||||
 | 
			
		||||
        # Doesn't go away until it's dhcp released
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address,
 | 
			
		||||
                                                      self.projects[0].id))
 | 
			
		||||
 | 
			
		||||
        release_ip(address)
 | 
			
		||||
        self.assertFalse(self._is_allocated_in_project(address,
 | 
			
		||||
                                                       self.projects[0].id))
 | 
			
		||||
 | 
			
		||||
    def test_side_effects(self):
 | 
			
		||||
        """Ensures allocating and releasing has no side effects"""
 | 
			
		||||
        address = self._create_address(0)
 | 
			
		||||
        address2 = self._create_address(1, self.instance2_id)
 | 
			
		||||
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address,
 | 
			
		||||
                                                      self.projects[0].id))
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address2,
 | 
			
		||||
                                                      self.projects[1].id))
 | 
			
		||||
        self.assertFalse(self._is_allocated_in_project(address,
 | 
			
		||||
                                                       self.projects[1].id))
 | 
			
		||||
 | 
			
		||||
        # Addresses are allocated before they're issued
 | 
			
		||||
        lease_ip(address)
 | 
			
		||||
        lease_ip(address2)
 | 
			
		||||
 | 
			
		||||
        self._deallocate_address(0, address)
 | 
			
		||||
        release_ip(address)
 | 
			
		||||
        self.assertFalse(self._is_allocated_in_project(address,
 | 
			
		||||
                                                       self.projects[0].id))
 | 
			
		||||
 | 
			
		||||
        # First address release shouldn't affect the second
 | 
			
		||||
        self.assertTrue(self._is_allocated_in_project(address2,
 | 
			
		||||
                                                      self.projects[1].id))
 | 
			
		||||
 | 
			
		||||
        self._deallocate_address(1, address2)
 | 
			
		||||
        release_ip(address2)
 | 
			
		||||
        self.assertFalse(self._is_allocated_in_project(address2,
 | 
			
		||||
                                                 self.projects[1].id))
 | 
			
		||||
 | 
			
		||||
    def test_subnet_edge(self):
 | 
			
		||||
        """Makes sure that private ips don't overlap"""
 | 
			
		||||
        first = self._create_address(0)
 | 
			
		||||
        lease_ip(first)
 | 
			
		||||
        instance_ids = []
 | 
			
		||||
        for i in range(1, FLAGS.num_networks):
 | 
			
		||||
            instance_ref = self._create_instance(i, mac=utils.generate_mac())
 | 
			
		||||
            instance_ids.append(instance_ref['id'])
 | 
			
		||||
            address = self._create_address(i, instance_ref['id'])
 | 
			
		||||
            instance_ref = self._create_instance(i, mac=utils.generate_mac())
 | 
			
		||||
            instance_ids.append(instance_ref['id'])
 | 
			
		||||
            address2 = self._create_address(i, instance_ref['id'])
 | 
			
		||||
            instance_ref = self._create_instance(i, mac=utils.generate_mac())
 | 
			
		||||
            instance_ids.append(instance_ref['id'])
 | 
			
		||||
            address3 = self._create_address(i, instance_ref['id'])
 | 
			
		||||
            lease_ip(address)
 | 
			
		||||
            lease_ip(address2)
 | 
			
		||||
            lease_ip(address3)
 | 
			
		||||
            self.context._project = self.projects[i]
 | 
			
		||||
            self.context.project_id = self.projects[i].id
 | 
			
		||||
            self.assertFalse(self._is_allocated_in_project(address,
 | 
			
		||||
                                                     self.projects[0].id))
 | 
			
		||||
            self.assertFalse(self._is_allocated_in_project(address2,
 | 
			
		||||
                                                     self.projects[0].id))
 | 
			
		||||
            self.assertFalse(self._is_allocated_in_project(address3,
 | 
			
		||||
                                                     self.projects[0].id))
 | 
			
		||||
            self.network.deallocate_fixed_ip(self.context, address)
 | 
			
		||||
            self.network.deallocate_fixed_ip(self.context, address2)
 | 
			
		||||
            self.network.deallocate_fixed_ip(self.context, address3)
 | 
			
		||||
            release_ip(address)
 | 
			
		||||
            release_ip(address2)
 | 
			
		||||
            release_ip(address3)
 | 
			
		||||
        for instance_id in instance_ids:
 | 
			
		||||
            db.instance_destroy(context.get_admin_context(), instance_id)
 | 
			
		||||
        self.context._project = self.projects[0]
 | 
			
		||||
        self.context.project_id = self.projects[0].id
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, first)
 | 
			
		||||
        self._deallocate_address(0, first)
 | 
			
		||||
        release_ip(first)
 | 
			
		||||
 | 
			
		||||
    def test_vpn_ip_and_port_looks_valid(self):
 | 
			
		||||
        """Ensure the vpn ip and port are reasonable"""
 | 
			
		||||
        self.assert_(self.projects[0].vpn_ip)
 | 
			
		||||
        self.assert_(self.projects[0].vpn_port >= FLAGS.vpn_start)
 | 
			
		||||
        self.assert_(self.projects[0].vpn_port <= FLAGS.vpn_start +
 | 
			
		||||
                                                  FLAGS.num_networks)
 | 
			
		||||
 | 
			
		||||
    def test_too_many_networks(self):
 | 
			
		||||
        """Ensure error is raised if we run out of networks"""
 | 
			
		||||
        projects = []
 | 
			
		||||
        networks_left = (FLAGS.num_networks -
 | 
			
		||||
                         db.network_count(context.get_admin_context()))
 | 
			
		||||
        for i in range(networks_left):
 | 
			
		||||
            project = self.manager.create_project('many%s' % i, self.user)
 | 
			
		||||
            projects.append(project)
 | 
			
		||||
            db.project_get_network(context.get_admin_context(), project.id)
 | 
			
		||||
        project = self.manager.create_project('last', self.user)
 | 
			
		||||
        projects.append(project)
 | 
			
		||||
        self.assertRaises(db.NoMoreNetworks,
 | 
			
		||||
                          db.project_get_network,
 | 
			
		||||
                          context.get_admin_context(),
 | 
			
		||||
                          project.id)
 | 
			
		||||
        for project in projects:
 | 
			
		||||
            self.manager.delete_project(project)
 | 
			
		||||
 | 
			
		||||
    def test_ips_are_reused(self):
 | 
			
		||||
        """Makes sure that ip addresses that are deallocated get reused"""
 | 
			
		||||
        address = self._create_address(0)
 | 
			
		||||
        lease_ip(address)
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, address)
 | 
			
		||||
        release_ip(address)
 | 
			
		||||
 | 
			
		||||
        address2 = self._create_address(0)
 | 
			
		||||
        self.assertEqual(address, address2)
 | 
			
		||||
        lease_ip(address)
 | 
			
		||||
        self.network.deallocate_fixed_ip(self.context, address2)
 | 
			
		||||
        release_ip(address)
 | 
			
		||||
 | 
			
		||||
    def test_too_many_addresses(self):
 | 
			
		||||
        """Test for a NoMoreAddresses exception when all fixed ips are used.
 | 
			
		||||
        """
 | 
			
		||||
        admin_context = context.get_admin_context()
 | 
			
		||||
        network = db.project_get_network(admin_context, self.projects[0].id)
 | 
			
		||||
        num_available_ips = db.network_count_available_ips(admin_context,
 | 
			
		||||
                                                           network['id'])
 | 
			
		||||
        addresses = []
 | 
			
		||||
        instance_ids = []
 | 
			
		||||
        for i in range(num_available_ips):
 | 
			
		||||
            instance_ref = self._create_instance(0)
 | 
			
		||||
            instance_ids.append(instance_ref['id'])
 | 
			
		||||
            address = self._create_address(0, instance_ref['id'])
 | 
			
		||||
            addresses.append(address)
 | 
			
		||||
            lease_ip(address)
 | 
			
		||||
 | 
			
		||||
        ip_count = db.network_count_available_ips(context.get_admin_context(),
 | 
			
		||||
                                                  network['id'])
 | 
			
		||||
        self.assertEqual(ip_count, 0)
 | 
			
		||||
        self.assertRaises(db.NoMoreAddresses,
 | 
			
		||||
                          self.network.allocate_fixed_ip,
 | 
			
		||||
                          self.context,
 | 
			
		||||
                          'foo')
 | 
			
		||||
 | 
			
		||||
        for i in range(num_available_ips):
 | 
			
		||||
            self.network.deallocate_fixed_ip(self.context, addresses[i])
 | 
			
		||||
            release_ip(addresses[i])
 | 
			
		||||
            db.instance_destroy(context.get_admin_context(), instance_ids[i])
 | 
			
		||||
        ip_count = db.network_count_available_ips(context.get_admin_context(),
 | 
			
		||||
                                                  network['id'])
 | 
			
		||||
        self.assertEqual(ip_count, num_available_ips)
 | 
			
		||||
 | 
			
		||||
    def _is_allocated_in_project(self, address, project_id):
 | 
			
		||||
        """Returns true if address is in specified project"""
 | 
			
		||||
        project_net = db.project_get_network(context.get_admin_context(),
 | 
			
		||||
                                             project_id)
 | 
			
		||||
        network = db.fixed_ip_get_network(context.get_admin_context(),
 | 
			
		||||
                                          address)
 | 
			
		||||
        instance = db.fixed_ip_get_instance(context.get_admin_context(),
 | 
			
		||||
                                            address)
 | 
			
		||||
        # instance exists until release
 | 
			
		||||
        return instance is not None and network['id'] == project_net['id']
 | 
			
		||||
 | 
			
		||||
    def run(self, result=None):
 | 
			
		||||
        if(FLAGS.network_manager == 'nova.network.manager.VlanManager'):
 | 
			
		||||
            super(VlanNetworkTestCase, self).run(result)
 | 
			
		||||
@@ -1,251 +1,276 @@
 | 
			
		||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2011 Citrix Systems, Inc.
 | 
			
		||||
# Copyright 2011 OpenStack LLC.
 | 
			
		||||
#
 | 
			
		||||
#    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.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Test suite for VMWareAPI.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import stubout
 | 
			
		||||
 | 
			
		||||
from nova import context
 | 
			
		||||
from nova import db
 | 
			
		||||
from nova import flags
 | 
			
		||||
from nova import test
 | 
			
		||||
from nova import utils
 | 
			
		||||
from nova.auth import manager
 | 
			
		||||
from nova.compute import power_state
 | 
			
		||||
from nova.tests.glance import stubs as glance_stubs
 | 
			
		||||
from nova.tests.vmwareapi import db_fakes
 | 
			
		||||
from nova.tests.vmwareapi import stubs
 | 
			
		||||
from nova.virt import vmwareapi_conn
 | 
			
		||||
from nova.virt.vmwareapi import fake as vmwareapi_fake
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
FLAGS = flags.FLAGS
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VMWareAPIVMTestCase(test.TestCase):
 | 
			
		||||
    """Unit tests for Vmware API connection calls."""
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(VMWareAPIVMTestCase, self).setUp()
 | 
			
		||||
        self.flags(vmwareapi_host_ip='test_url',
 | 
			
		||||
                   vmwareapi_host_username='test_username',
 | 
			
		||||
                   vmwareapi_host_password='test_pass')
 | 
			
		||||
        self.manager = manager.AuthManager()
 | 
			
		||||
        self.user = self.manager.create_user('fake', 'fake', 'fake',
 | 
			
		||||
                                             admin=True)
 | 
			
		||||
        self.project = self.manager.create_project('fake', 'fake', 'fake')
 | 
			
		||||
        self.network = utils.import_object(FLAGS.network_manager)
 | 
			
		||||
        self.stubs = stubout.StubOutForTesting()
 | 
			
		||||
        vmwareapi_fake.reset()
 | 
			
		||||
        db_fakes.stub_out_db_instance_api(self.stubs)
 | 
			
		||||
        stubs.set_stubs(self.stubs)
 | 
			
		||||
        glance_stubs.stubout_glance_client(self.stubs)
 | 
			
		||||
        self.conn = vmwareapi_conn.get_connection(False)
 | 
			
		||||
 | 
			
		||||
    def _create_instance_in_the_db(self):
 | 
			
		||||
        values = {'name': 1,
 | 
			
		||||
                  'id': 1,
 | 
			
		||||
                  'project_id': self.project.id,
 | 
			
		||||
                  'user_id': self.user.id,
 | 
			
		||||
                  'image_ref': "1",
 | 
			
		||||
                  'kernel_id': "1",
 | 
			
		||||
                  'ramdisk_id': "1",
 | 
			
		||||
                  'instance_type': 'm1.large',
 | 
			
		||||
                  'mac_address': 'aa:bb:cc:dd:ee:ff',
 | 
			
		||||
                  }
 | 
			
		||||
        self.instance = db.instance_create(None, values)
 | 
			
		||||
 | 
			
		||||
    def _create_vm(self):
 | 
			
		||||
        """Create and spawn the VM."""
 | 
			
		||||
        self._create_instance_in_the_db()
 | 
			
		||||
        self.type_data = db.instance_type_get_by_name(None, 'm1.large')
 | 
			
		||||
        self.conn.spawn(self.instance)
 | 
			
		||||
        self._check_vm_record()
 | 
			
		||||
 | 
			
		||||
    def _check_vm_record(self):
 | 
			
		||||
        """
 | 
			
		||||
        Check if the spawned VM's properties correspond to the instance in
 | 
			
		||||
        the db.
 | 
			
		||||
        """
 | 
			
		||||
        instances = self.conn.list_instances()
 | 
			
		||||
        self.assertEquals(len(instances), 1)
 | 
			
		||||
 | 
			
		||||
        # Get Nova record for VM
 | 
			
		||||
        vm_info = self.conn.get_info(1)
 | 
			
		||||
 | 
			
		||||
        # Get record for VM
 | 
			
		||||
        vms = vmwareapi_fake._get_objects("VirtualMachine")
 | 
			
		||||
        vm = vms[0]
 | 
			
		||||
 | 
			
		||||
        # Check that m1.large above turned into the right thing.
 | 
			
		||||
        mem_kib = long(self.type_data['memory_mb']) << 10
 | 
			
		||||
        vcpus = self.type_data['vcpus']
 | 
			
		||||
        self.assertEquals(vm_info['max_mem'], mem_kib)
 | 
			
		||||
        self.assertEquals(vm_info['mem'], mem_kib)
 | 
			
		||||
        self.assertEquals(vm.get("summary.config.numCpu"), vcpus)
 | 
			
		||||
        self.assertEquals(vm.get("summary.config.memorySizeMB"),
 | 
			
		||||
                          self.type_data['memory_mb'])
 | 
			
		||||
 | 
			
		||||
        # Check that the VM is running according to Nova
 | 
			
		||||
        self.assertEquals(vm_info['state'], power_state.RUNNING)
 | 
			
		||||
 | 
			
		||||
        # Check that the VM is running according to vSphere API.
 | 
			
		||||
        self.assertEquals(vm.get("runtime.powerState"), 'poweredOn')
 | 
			
		||||
 | 
			
		||||
    def _check_vm_info(self, info, pwr_state=power_state.RUNNING):
 | 
			
		||||
        """
 | 
			
		||||
        Check if the get_info returned values correspond to the instance
 | 
			
		||||
        object in the db.
 | 
			
		||||
        """
 | 
			
		||||
        mem_kib = long(self.type_data['memory_mb']) << 10
 | 
			
		||||
        self.assertEquals(info["state"], pwr_state)
 | 
			
		||||
        self.assertEquals(info["max_mem"], mem_kib)
 | 
			
		||||
        self.assertEquals(info["mem"], mem_kib)
 | 
			
		||||
        self.assertEquals(info["num_cpu"], self.type_data['vcpus'])
 | 
			
		||||
 | 
			
		||||
    def test_list_instances(self):
 | 
			
		||||
        instances = self.conn.list_instances()
 | 
			
		||||
        self.assertEquals(len(instances), 0)
 | 
			
		||||
 | 
			
		||||
    def test_list_instances_1(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        instances = self.conn.list_instances()
 | 
			
		||||
        self.assertEquals(len(instances), 1)
 | 
			
		||||
 | 
			
		||||
    def test_spawn(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
 | 
			
		||||
    def test_snapshot(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        self.conn.snapshot(self.instance, "Test-Snapshot")
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
 | 
			
		||||
    def test_snapshot_non_existent(self):
 | 
			
		||||
        self._create_instance_in_the_db()
 | 
			
		||||
        self.assertRaises(Exception, self.conn.snapshot, self.instance,
 | 
			
		||||
                          "Test-Snapshot")
 | 
			
		||||
 | 
			
		||||
    def test_reboot(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        self.conn.reboot(self.instance)
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
 | 
			
		||||
    def test_reboot_non_existent(self):
 | 
			
		||||
        self._create_instance_in_the_db()
 | 
			
		||||
        self.assertRaises(Exception, self.conn.reboot, self.instance)
 | 
			
		||||
 | 
			
		||||
    def test_reboot_not_poweredon(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        self.conn.suspend(self.instance, self.dummy_callback_handler)
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.PAUSED)
 | 
			
		||||
        self.assertRaises(Exception, self.conn.reboot, self.instance)
 | 
			
		||||
 | 
			
		||||
    def test_suspend(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        self.conn.suspend(self.instance, self.dummy_callback_handler)
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.PAUSED)
 | 
			
		||||
 | 
			
		||||
    def test_suspend_non_existent(self):
 | 
			
		||||
        self._create_instance_in_the_db()
 | 
			
		||||
        self.assertRaises(Exception, self.conn.suspend, self.instance,
 | 
			
		||||
                          self.dummy_callback_handler)
 | 
			
		||||
 | 
			
		||||
    def test_resume(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        self.conn.suspend(self.instance, self.dummy_callback_handler)
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.PAUSED)
 | 
			
		||||
        self.conn.resume(self.instance, self.dummy_callback_handler)
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
 | 
			
		||||
    def test_resume_non_existent(self):
 | 
			
		||||
        self._create_instance_in_the_db()
 | 
			
		||||
        self.assertRaises(Exception, self.conn.resume, self.instance,
 | 
			
		||||
                          self.dummy_callback_handler)
 | 
			
		||||
 | 
			
		||||
    def test_resume_not_suspended(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        self.assertRaises(Exception, self.conn.resume, self.instance,
 | 
			
		||||
                          self.dummy_callback_handler)
 | 
			
		||||
 | 
			
		||||
    def test_get_info(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
 | 
			
		||||
    def test_destroy(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        instances = self.conn.list_instances()
 | 
			
		||||
        self.assertEquals(len(instances), 1)
 | 
			
		||||
        self.conn.destroy(self.instance)
 | 
			
		||||
        instances = self.conn.list_instances()
 | 
			
		||||
        self.assertEquals(len(instances), 0)
 | 
			
		||||
 | 
			
		||||
    def test_destroy_non_existent(self):
 | 
			
		||||
        self._create_instance_in_the_db()
 | 
			
		||||
        self.assertEquals(self.conn.destroy(self.instance), None)
 | 
			
		||||
 | 
			
		||||
    def test_pause(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def test_unpause(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def test_diagnostics(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def test_get_console_output(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def test_get_ajax_console(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def dummy_callback_handler(self, ret):
 | 
			
		||||
        """
 | 
			
		||||
        Dummy callback function to be passed to suspend, resume, etc., calls.
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        super(VMWareAPIVMTestCase, self).tearDown()
 | 
			
		||||
        vmwareapi_fake.cleanup()
 | 
			
		||||
        self.manager.delete_project(self.project)
 | 
			
		||||
        self.manager.delete_user(self.user)
 | 
			
		||||
        self.stubs.UnsetAll()
 | 
			
		||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2011 Citrix Systems, Inc.
 | 
			
		||||
# Copyright 2011 OpenStack LLC.
 | 
			
		||||
#
 | 
			
		||||
#    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.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Test suite for VMWareAPI.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import stubout
 | 
			
		||||
 | 
			
		||||
from nova import context
 | 
			
		||||
from nova import db
 | 
			
		||||
from nova import flags
 | 
			
		||||
from nova import test
 | 
			
		||||
from nova import utils
 | 
			
		||||
from nova.auth import manager
 | 
			
		||||
from nova.compute import power_state
 | 
			
		||||
from nova.tests.glance import stubs as glance_stubs
 | 
			
		||||
from nova.tests.vmwareapi import db_fakes
 | 
			
		||||
from nova.tests.vmwareapi import stubs
 | 
			
		||||
from nova.virt import vmwareapi_conn
 | 
			
		||||
from nova.virt.vmwareapi import fake as vmwareapi_fake
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
FLAGS = flags.FLAGS
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VMWareAPIVMTestCase(test.TestCase):
 | 
			
		||||
    """Unit tests for Vmware API connection calls."""
 | 
			
		||||
 | 
			
		||||
    # NOTE(jkoelker): This is leaking stubs into the db module.
 | 
			
		||||
    #                 Commenting out until updated for multi-nic.
 | 
			
		||||
    #def setUp(self):
 | 
			
		||||
    #    super(VMWareAPIVMTestCase, self).setUp()
 | 
			
		||||
    #    self.flags(vmwareapi_host_ip='test_url',
 | 
			
		||||
    #               vmwareapi_host_username='test_username',
 | 
			
		||||
    #               vmwareapi_host_password='test_pass')
 | 
			
		||||
    #    self.manager = manager.AuthManager()
 | 
			
		||||
    #    self.user = self.manager.create_user('fake', 'fake', 'fake',
 | 
			
		||||
    #                                         admin=True)
 | 
			
		||||
    #    self.project = self.manager.create_project('fake', 'fake', 'fake')
 | 
			
		||||
    #    self.network = utils.import_object(FLAGS.network_manager)
 | 
			
		||||
    #    self.stubs = stubout.StubOutForTesting()
 | 
			
		||||
    #    vmwareapi_fake.reset()
 | 
			
		||||
    #    db_fakes.stub_out_db_instance_api(self.stubs)
 | 
			
		||||
    #    stubs.set_stubs(self.stubs)
 | 
			
		||||
    #    glance_stubs.stubout_glance_client(self.stubs,
 | 
			
		||||
    #                                       glance_stubs.FakeGlance)
 | 
			
		||||
    #    self.conn = vmwareapi_conn.get_connection(False)
 | 
			
		||||
 | 
			
		||||
    #def tearDown(self):
 | 
			
		||||
    #    super(VMWareAPIVMTestCase, self).tearDown()
 | 
			
		||||
    #    vmwareapi_fake.cleanup()
 | 
			
		||||
    #    self.manager.delete_project(self.project)
 | 
			
		||||
    #    self.manager.delete_user(self.user)
 | 
			
		||||
    #    self.stubs.UnsetAll()
 | 
			
		||||
 | 
			
		||||
    def _create_instance_in_the_db(self):
 | 
			
		||||
        values = {'name': 1,
 | 
			
		||||
                  'id': 1,
 | 
			
		||||
                  'project_id': self.project.id,
 | 
			
		||||
                  'user_id': self.user.id,
 | 
			
		||||
                  'image_id': "1",
 | 
			
		||||
                  'kernel_id': "1",
 | 
			
		||||
                  'ramdisk_id': "1",
 | 
			
		||||
                  'instance_type': 'm1.large',
 | 
			
		||||
                  'mac_address': 'aa:bb:cc:dd:ee:ff',
 | 
			
		||||
                  }
 | 
			
		||||
        self.instance = db.instance_create(values)
 | 
			
		||||
 | 
			
		||||
    def _create_vm(self):
 | 
			
		||||
        """Create and spawn the VM."""
 | 
			
		||||
        self._create_instance_in_the_db()
 | 
			
		||||
        self.type_data = db.instance_type_get_by_name(None, 'm1.large')
 | 
			
		||||
        self.conn.spawn(self.instance)
 | 
			
		||||
        self._check_vm_record()
 | 
			
		||||
 | 
			
		||||
    def _check_vm_record(self):
 | 
			
		||||
        """
 | 
			
		||||
        Check if the spawned VM's properties correspond to the instance in
 | 
			
		||||
        the db.
 | 
			
		||||
        """
 | 
			
		||||
        instances = self.conn.list_instances()
 | 
			
		||||
        self.assertEquals(len(instances), 1)
 | 
			
		||||
 | 
			
		||||
        # Get Nova record for VM
 | 
			
		||||
        vm_info = self.conn.get_info(1)
 | 
			
		||||
 | 
			
		||||
        # Get record for VM
 | 
			
		||||
        vms = vmwareapi_fake._get_objects("VirtualMachine")
 | 
			
		||||
        vm = vms[0]
 | 
			
		||||
 | 
			
		||||
        # Check that m1.large above turned into the right thing.
 | 
			
		||||
        mem_kib = long(self.type_data['memory_mb']) << 10
 | 
			
		||||
        vcpus = self.type_data['vcpus']
 | 
			
		||||
        self.assertEquals(vm_info['max_mem'], mem_kib)
 | 
			
		||||
        self.assertEquals(vm_info['mem'], mem_kib)
 | 
			
		||||
        self.assertEquals(vm.get("summary.config.numCpu"), vcpus)
 | 
			
		||||
        self.assertEquals(vm.get("summary.config.memorySizeMB"),
 | 
			
		||||
                          self.type_data['memory_mb'])
 | 
			
		||||
 | 
			
		||||
        # Check that the VM is running according to Nova
 | 
			
		||||
        self.assertEquals(vm_info['state'], power_state.RUNNING)
 | 
			
		||||
 | 
			
		||||
        # Check that the VM is running according to vSphere API.
 | 
			
		||||
        self.assertEquals(vm.get("runtime.powerState"), 'poweredOn')
 | 
			
		||||
 | 
			
		||||
    def _check_vm_info(self, info, pwr_state=power_state.RUNNING):
 | 
			
		||||
        """
 | 
			
		||||
        Check if the get_info returned values correspond to the instance
 | 
			
		||||
        object in the db.
 | 
			
		||||
        """
 | 
			
		||||
        mem_kib = long(self.type_data['memory_mb']) << 10
 | 
			
		||||
        self.assertEquals(info["state"], pwr_state)
 | 
			
		||||
        self.assertEquals(info["max_mem"], mem_kib)
 | 
			
		||||
        self.assertEquals(info["mem"], mem_kib)
 | 
			
		||||
        self.assertEquals(info["num_cpu"], self.type_data['vcpus'])
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_list_instances(self):
 | 
			
		||||
        instances = self.conn.list_instances()
 | 
			
		||||
        self.assertEquals(len(instances), 0)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_list_instances_1(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        instances = self.conn.list_instances()
 | 
			
		||||
        self.assertEquals(len(instances), 1)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_spawn(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_snapshot(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        self.conn.snapshot(self.instance, "Test-Snapshot")
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_snapshot_non_existent(self):
 | 
			
		||||
        self._create_instance_in_the_db()
 | 
			
		||||
        self.assertRaises(Exception, self.conn.snapshot, self.instance,
 | 
			
		||||
                          "Test-Snapshot")
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_reboot(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        self.conn.reboot(self.instance)
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_reboot_non_existent(self):
 | 
			
		||||
        self._create_instance_in_the_db()
 | 
			
		||||
        self.assertRaises(Exception, self.conn.reboot, self.instance)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_reboot_not_poweredon(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        self.conn.suspend(self.instance, self.dummy_callback_handler)
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.PAUSED)
 | 
			
		||||
        self.assertRaises(Exception, self.conn.reboot, self.instance)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_suspend(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        self.conn.suspend(self.instance, self.dummy_callback_handler)
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.PAUSED)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_suspend_non_existent(self):
 | 
			
		||||
        self._create_instance_in_the_db()
 | 
			
		||||
        self.assertRaises(Exception, self.conn.suspend, self.instance,
 | 
			
		||||
                          self.dummy_callback_handler)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_resume(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        self.conn.suspend(self.instance, self.dummy_callback_handler)
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.PAUSED)
 | 
			
		||||
        self.conn.resume(self.instance, self.dummy_callback_handler)
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_resume_non_existent(self):
 | 
			
		||||
        self._create_instance_in_the_db()
 | 
			
		||||
        self.assertRaises(Exception, self.conn.resume, self.instance,
 | 
			
		||||
                          self.dummy_callback_handler)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_resume_not_suspended(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        self.assertRaises(Exception, self.conn.resume, self.instance,
 | 
			
		||||
                          self.dummy_callback_handler)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_get_info(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_destroy(self):
 | 
			
		||||
        self._create_vm()
 | 
			
		||||
        info = self.conn.get_info(1)
 | 
			
		||||
        self._check_vm_info(info, power_state.RUNNING)
 | 
			
		||||
        instances = self.conn.list_instances()
 | 
			
		||||
        self.assertEquals(len(instances), 1)
 | 
			
		||||
        self.conn.destroy(self.instance)
 | 
			
		||||
        instances = self.conn.list_instances()
 | 
			
		||||
        self.assertEquals(len(instances), 0)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_destroy_non_existent(self):
 | 
			
		||||
        self._create_instance_in_the_db()
 | 
			
		||||
        self.assertEquals(self.conn.destroy(self.instance), None)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_pause(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_unpause(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_diagnostics(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_get_console_output(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def test_get_ajax_console(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("DB stubbing not removed, needs updating for multi-nic")
 | 
			
		||||
    def dummy_callback_handler(self, ret):
 | 
			
		||||
        """
 | 
			
		||||
        Dummy callback function to be passed to suspend, resume, etc., calls.
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 
 | 
			
		||||
@@ -127,7 +127,6 @@ class VolumeTestCase(test.TestCase):
 | 
			
		||||
        inst['user_id'] = 'fake'
 | 
			
		||||
        inst['project_id'] = 'fake'
 | 
			
		||||
        inst['instance_type_id'] = '2'  # m1.tiny
 | 
			
		||||
        inst['mac_address'] = utils.generate_mac()
 | 
			
		||||
        inst['ami_launch_index'] = 0
 | 
			
		||||
        instance_id = db.instance_create(self.context, inst)['id']
 | 
			
		||||
        mountpoint = "/dev/sdf"
 | 
			
		||||
 
 | 
			
		||||
@@ -83,7 +83,6 @@ class XenAPIVolumeTestCase(test.TestCase):
 | 
			
		||||
                  'kernel_id': 2,
 | 
			
		||||
                  'ramdisk_id': 3,
 | 
			
		||||
                  'instance_type_id': '3',  # m1.large
 | 
			
		||||
                  'mac_address': 'aa:bb:cc:dd:ee:ff',
 | 
			
		||||
                  'os_type': 'linux',
 | 
			
		||||
                  'architecture': 'x86-64'}
 | 
			
		||||
 | 
			
		||||
@@ -211,11 +210,24 @@ class XenAPIVMTestCase(test.TestCase):
 | 
			
		||||
                'kernel_id': 2,
 | 
			
		||||
                'ramdisk_id': 3,
 | 
			
		||||
                'instance_type_id': '3',  # m1.large
 | 
			
		||||
                'mac_address': 'aa:bb:cc:dd:ee:ff',
 | 
			
		||||
                'os_type': 'linux',
 | 
			
		||||
                'architecture': 'x86-64'}
 | 
			
		||||
            network_info = [({'bridge': 'fa0', 'id': 0, 'injected': False},
 | 
			
		||||
                              {'broadcast': '192.168.0.255',
 | 
			
		||||
                               'dns': ['192.168.0.1'],
 | 
			
		||||
                               'gateway': '192.168.0.1',
 | 
			
		||||
                               'gateway6': 'dead:beef::1',
 | 
			
		||||
                               'ip6s': [{'enabled': '1',
 | 
			
		||||
                                         'ip': 'dead:beef::dcad:beff:feef:0',
 | 
			
		||||
                                               'netmask': '64'}],
 | 
			
		||||
                               'ips': [{'enabled': '1',
 | 
			
		||||
                                        'ip': '192.168.0.100',
 | 
			
		||||
                                        'netmask': '255.255.255.0'}],
 | 
			
		||||
                               'label': 'fake',
 | 
			
		||||
                               'mac': 'DE:AD:BE:EF:00:00',
 | 
			
		||||
                               'rxtx_cap': 3})]
 | 
			
		||||
            instance = db.instance_create(self.context, values)
 | 
			
		||||
            self.conn.spawn(instance)
 | 
			
		||||
            self.conn.spawn(instance, network_info)
 | 
			
		||||
 | 
			
		||||
        gt1 = eventlet.spawn(_do_build, 1, self.project.id, self.user.id)
 | 
			
		||||
        gt2 = eventlet.spawn(_do_build, 2, self.project.id, self.user.id)
 | 
			
		||||
@@ -320,22 +332,22 @@ class XenAPIVMTestCase(test.TestCase):
 | 
			
		||||
 | 
			
		||||
        if check_injection:
 | 
			
		||||
            xenstore_data = self.vm['xenstore_data']
 | 
			
		||||
            key = 'vm-data/networking/aabbccddeeff'
 | 
			
		||||
            key = 'vm-data/networking/DEADBEEF0000'
 | 
			
		||||
            xenstore_value = xenstore_data[key]
 | 
			
		||||
            tcpip_data = ast.literal_eval(xenstore_value)
 | 
			
		||||
            self.assertEquals(tcpip_data,
 | 
			
		||||
                              {'label': 'fake_flat_network',
 | 
			
		||||
                               'broadcast': '10.0.0.255',
 | 
			
		||||
                               'ips': [{'ip': '10.0.0.3',
 | 
			
		||||
                                        'netmask':'255.255.255.0',
 | 
			
		||||
                                        'enabled':'1'}],
 | 
			
		||||
                                'ip6s': [{'ip': 'fe80::a8bb:ccff:fedd:eeff',
 | 
			
		||||
                                          'netmask': '120',
 | 
			
		||||
                                          'enabled': '1'}],
 | 
			
		||||
                                'mac': 'aa:bb:cc:dd:ee:ff',
 | 
			
		||||
                                'dns': ['10.0.0.2'],
 | 
			
		||||
                                'gateway': '10.0.0.1',
 | 
			
		||||
                                'gateway6': 'fe80::a00:1'})
 | 
			
		||||
                              {'broadcast': '192.168.0.255',
 | 
			
		||||
                               'dns': ['192.168.0.1'],
 | 
			
		||||
                               'gateway': '192.168.0.1',
 | 
			
		||||
                               'gateway6': 'dead:beef::1',
 | 
			
		||||
                               'ip6s': [{'enabled': '1',
 | 
			
		||||
                                         'ip': 'dead:beef::dcad:beff:feef:0',
 | 
			
		||||
                                               'netmask': '64'}],
 | 
			
		||||
                               'ips': [{'enabled': '1',
 | 
			
		||||
                                        'ip': '192.168.0.100',
 | 
			
		||||
                                        'netmask': '255.255.255.0'}],
 | 
			
		||||
                               'label': 'fake',
 | 
			
		||||
                               'mac': 'DE:AD:BE:EF:00:00'})
 | 
			
		||||
 | 
			
		||||
    def check_vm_params_for_windows(self):
 | 
			
		||||
        self.assertEquals(self.vm['platform']['nx'], 'true')
 | 
			
		||||
@@ -381,11 +393,24 @@ class XenAPIVMTestCase(test.TestCase):
 | 
			
		||||
                  'kernel_id': kernel_id,
 | 
			
		||||
                  'ramdisk_id': ramdisk_id,
 | 
			
		||||
                  'instance_type_id': instance_type_id,
 | 
			
		||||
                  'mac_address': 'aa:bb:cc:dd:ee:ff',
 | 
			
		||||
                  'os_type': os_type,
 | 
			
		||||
                  'architecture': architecture}
 | 
			
		||||
        instance = db.instance_create(self.context, values)
 | 
			
		||||
        self.conn.spawn(instance)
 | 
			
		||||
        network_info = [({'bridge': 'fa0', 'id': 0, 'injected': True},
 | 
			
		||||
                          {'broadcast': '192.168.0.255',
 | 
			
		||||
                           'dns': ['192.168.0.1'],
 | 
			
		||||
                           'gateway': '192.168.0.1',
 | 
			
		||||
                           'gateway6': 'dead:beef::1',
 | 
			
		||||
                           'ip6s': [{'enabled': '1',
 | 
			
		||||
                                     'ip': 'dead:beef::dcad:beff:feef:0',
 | 
			
		||||
                                           'netmask': '64'}],
 | 
			
		||||
                           'ips': [{'enabled': '1',
 | 
			
		||||
                                    'ip': '192.168.0.100',
 | 
			
		||||
                                    'netmask': '255.255.255.0'}],
 | 
			
		||||
                           'label': 'fake',
 | 
			
		||||
                           'mac': 'DE:AD:BE:EF:00:00',
 | 
			
		||||
                           'rxtx_cap': 3})]
 | 
			
		||||
        self.conn.spawn(instance, network_info)
 | 
			
		||||
        self.create_vm_record(self.conn, os_type, instance_id)
 | 
			
		||||
        self.check_vm_record(self.conn, check_injection)
 | 
			
		||||
        self.assertTrue(instance.os_type)
 | 
			
		||||
@@ -467,11 +492,11 @@ class XenAPIVMTestCase(test.TestCase):
 | 
			
		||||
            index = config.index('auto eth0')
 | 
			
		||||
            self.assertEquals(config[index + 1:index + 8], [
 | 
			
		||||
                'iface eth0 inet static',
 | 
			
		||||
                'address 10.0.0.3',
 | 
			
		||||
                'address 192.168.0.100',
 | 
			
		||||
                'netmask 255.255.255.0',
 | 
			
		||||
                'broadcast 10.0.0.255',
 | 
			
		||||
                'gateway 10.0.0.1',
 | 
			
		||||
                'dns-nameservers 10.0.0.2',
 | 
			
		||||
                'broadcast 192.168.0.255',
 | 
			
		||||
                'gateway 192.168.0.1',
 | 
			
		||||
                'dns-nameservers 192.168.0.1',
 | 
			
		||||
                ''])
 | 
			
		||||
            self._tee_executed = True
 | 
			
		||||
            return '', ''
 | 
			
		||||
@@ -532,23 +557,37 @@ class XenAPIVMTestCase(test.TestCase):
 | 
			
		||||
        # guest agent is detected
 | 
			
		||||
        self.assertFalse(self._tee_executed)
 | 
			
		||||
 | 
			
		||||
    @test.skip_test("Never gets an address, not sure why")
 | 
			
		||||
    def test_spawn_vlanmanager(self):
 | 
			
		||||
        self.flags(xenapi_image_service='glance',
 | 
			
		||||
                   network_manager='nova.network.manager.VlanManager',
 | 
			
		||||
                   network_driver='nova.network.xenapi_net',
 | 
			
		||||
                   vlan_interface='fake0')
 | 
			
		||||
 | 
			
		||||
        def dummy(*args, **kwargs):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        self.stubs.Set(VMOps, 'create_vifs', dummy)
 | 
			
		||||
        # Reset network table
 | 
			
		||||
        xenapi_fake.reset_table('network')
 | 
			
		||||
        # Instance id = 2 will use vlan network (see db/fakes.py)
 | 
			
		||||
        fake_instance_id = 2
 | 
			
		||||
        ctxt = self.context.elevated()
 | 
			
		||||
        instance_ref = self._create_instance(2)
 | 
			
		||||
        network_bk = self.network
 | 
			
		||||
        # Ensure we use xenapi_net driver
 | 
			
		||||
        self.network = utils.import_object(FLAGS.network_manager)
 | 
			
		||||
        self.network.setup_compute_network(None, fake_instance_id)
 | 
			
		||||
        networks = self.network.db.network_get_all(ctxt)
 | 
			
		||||
        for network in networks:
 | 
			
		||||
            self.network.set_network_host(ctxt, network['id'])
 | 
			
		||||
 | 
			
		||||
        self.network.allocate_for_instance(ctxt, instance_id=instance_ref.id,
 | 
			
		||||
                instance_type_id=1, project_id=self.project.id)
 | 
			
		||||
        self.network.setup_compute_network(ctxt, instance_ref.id)
 | 
			
		||||
        self._test_spawn(glance_stubs.FakeGlance.IMAGE_MACHINE,
 | 
			
		||||
                         glance_stubs.FakeGlance.IMAGE_KERNEL,
 | 
			
		||||
                         glance_stubs.FakeGlance.IMAGE_RAMDISK,
 | 
			
		||||
                         instance_id=fake_instance_id)
 | 
			
		||||
                         instance_id=instance_ref.id,
 | 
			
		||||
                         create_record=False)
 | 
			
		||||
        # TODO(salvatore-orlando): a complete test here would require
 | 
			
		||||
        # a check for making sure the bridge for the VM's VIF is
 | 
			
		||||
        # consistent with bridge specified in nova db
 | 
			
		||||
@@ -560,7 +599,7 @@ class XenAPIVMTestCase(test.TestCase):
 | 
			
		||||
            vif_rec = xenapi_fake.get_record('VIF', vif_ref)
 | 
			
		||||
            self.assertEquals(vif_rec['qos_algorithm_type'], 'ratelimit')
 | 
			
		||||
            self.assertEquals(vif_rec['qos_algorithm_params']['kbps'],
 | 
			
		||||
                              str(4 * 1024))
 | 
			
		||||
                              str(3 * 1024))
 | 
			
		||||
 | 
			
		||||
    def test_rescue(self):
 | 
			
		||||
        self.flags(xenapi_inject_image=False)
 | 
			
		||||
@@ -582,22 +621,35 @@ class XenAPIVMTestCase(test.TestCase):
 | 
			
		||||
        self.vm = None
 | 
			
		||||
        self.stubs.UnsetAll()
 | 
			
		||||
 | 
			
		||||
    def _create_instance(self):
 | 
			
		||||
    def _create_instance(self, instance_id=1):
 | 
			
		||||
        """Creates and spawns a test instance."""
 | 
			
		||||
        stubs.stubout_loopingcall_start(self.stubs)
 | 
			
		||||
        values = {
 | 
			
		||||
            'id': 1,
 | 
			
		||||
            'id': instance_id,
 | 
			
		||||
            'project_id': self.project.id,
 | 
			
		||||
            'user_id': self.user.id,
 | 
			
		||||
            'image_ref': 1,
 | 
			
		||||
            'kernel_id': 2,
 | 
			
		||||
            'ramdisk_id': 3,
 | 
			
		||||
            'instance_type_id': '3',  # m1.large
 | 
			
		||||
            'mac_address': 'aa:bb:cc:dd:ee:ff',
 | 
			
		||||
            'os_type': 'linux',
 | 
			
		||||
            'architecture': 'x86-64'}
 | 
			
		||||
        instance = db.instance_create(self.context, values)
 | 
			
		||||
        self.conn.spawn(instance)
 | 
			
		||||
        network_info = [({'bridge': 'fa0', 'id': 0, 'injected': False},
 | 
			
		||||
                          {'broadcast': '192.168.0.255',
 | 
			
		||||
                           'dns': ['192.168.0.1'],
 | 
			
		||||
                           'gateway': '192.168.0.1',
 | 
			
		||||
                           'gateway6': 'dead:beef::1',
 | 
			
		||||
                           'ip6s': [{'enabled': '1',
 | 
			
		||||
                                     'ip': 'dead:beef::dcad:beff:feef:0',
 | 
			
		||||
                                           'netmask': '64'}],
 | 
			
		||||
                           'ips': [{'enabled': '1',
 | 
			
		||||
                                    'ip': '192.168.0.100',
 | 
			
		||||
                                    'netmask': '255.255.255.0'}],
 | 
			
		||||
                           'label': 'fake',
 | 
			
		||||
                           'mac': 'DE:AD:BE:EF:00:00',
 | 
			
		||||
                           'rxtx_cap': 3})]
 | 
			
		||||
        self.conn.spawn(instance, network_info)
 | 
			
		||||
        return instance
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -669,7 +721,6 @@ class XenAPIMigrateInstance(test.TestCase):
 | 
			
		||||
                  'ramdisk_id': None,
 | 
			
		||||
                  'local_gb': 5,
 | 
			
		||||
                  'instance_type_id': '3',  # m1.large
 | 
			
		||||
                  'mac_address': 'aa:bb:cc:dd:ee:ff',
 | 
			
		||||
                  'os_type': 'linux',
 | 
			
		||||
                  'architecture': 'x86-64'}
 | 
			
		||||
 | 
			
		||||
@@ -695,7 +746,22 @@ class XenAPIMigrateInstance(test.TestCase):
 | 
			
		||||
        stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests)
 | 
			
		||||
        stubs.stubout_loopingcall_start(self.stubs)
 | 
			
		||||
        conn = xenapi_conn.get_connection(False)
 | 
			
		||||
        conn.finish_resize(instance, dict(base_copy='hurr', cow='durr'))
 | 
			
		||||
        network_info = [({'bridge': 'fa0', 'id': 0, 'injected': False},
 | 
			
		||||
                          {'broadcast': '192.168.0.255',
 | 
			
		||||
                           'dns': ['192.168.0.1'],
 | 
			
		||||
                           'gateway': '192.168.0.1',
 | 
			
		||||
                           'gateway6': 'dead:beef::1',
 | 
			
		||||
                           'ip6s': [{'enabled': '1',
 | 
			
		||||
                                     'ip': 'dead:beef::dcad:beff:feef:0',
 | 
			
		||||
                                           'netmask': '64'}],
 | 
			
		||||
                           'ips': [{'enabled': '1',
 | 
			
		||||
                                    'ip': '192.168.0.100',
 | 
			
		||||
                                    'netmask': '255.255.255.0'}],
 | 
			
		||||
                           'label': 'fake',
 | 
			
		||||
                           'mac': 'DE:AD:BE:EF:00:00',
 | 
			
		||||
                           'rxtx_cap': 3})]
 | 
			
		||||
        conn.finish_resize(instance, dict(base_copy='hurr', cow='durr'),
 | 
			
		||||
                                                           network_info)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class XenAPIDetermineDiskImageTestCase(test.TestCase):
 | 
			
		||||
 
 | 
			
		||||
@@ -262,14 +262,6 @@ def generate_uid(topic, size=8):
 | 
			
		||||
    return '%s-%s' % (topic, ''.join(choices))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def generate_mac():
 | 
			
		||||
    mac = [0x02, 0x16, 0x3e,
 | 
			
		||||
           random.randint(0x00, 0x7f),
 | 
			
		||||
           random.randint(0x00, 0xff),
 | 
			
		||||
           random.randint(0x00, 0xff)]
 | 
			
		||||
    return ':'.join(map(lambda x: '%02x' % x, mac))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Default symbols to use for passwords. Avoids visually confusing characters.
 | 
			
		||||
# ~6 bits per symbol
 | 
			
		||||
DEFAULT_PASSWORD_SYMBOLS = ('23456789'  # Removed: 0,1
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user