From e52069015aa3ed0ba130f529ebfb93d53ea6053c Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Mon, 6 Jun 2011 15:32:48 -0400 Subject: [PATCH 01/24] Remove ipy from nova-manage and use netaddr --- bin/nova-manage | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index b0cd343f5f7e..5ac0b8a0c276 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -56,11 +56,11 @@ import gettext import glob import json +import netaddr import os import sys import time -import IPy # If ../nova/__init__.py exists, add ../ to Python search path, so that # it will override what happens to be installed in /usr/(local/)lib/python... @@ -513,7 +513,7 @@ class FloatingIpCommands(object): def create(self, host, range): """Creates floating ips for host by range arguments: host ip_range""" - for address in IPy.IP(range): + for address in netaddr.IPRange(range): db.floating_ip_create(context.get_admin_context(), {'address': str(address), 'host': host}) @@ -521,7 +521,7 @@ class FloatingIpCommands(object): def delete(self, ip_range): """Deletes floating ips by range arguments: range""" - for address in IPy.IP(ip_range): + for address in netaddr.IPRange(ip_range): db.floating_ip_destroy(context.get_admin_context(), str(address)) From 93f61c18134e6b4091114a7126f52d74e0d20df8 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Mon, 6 Jun 2011 15:33:35 -0400 Subject: [PATCH 02/24] Remove ipy from nova/api/ec2/cloud.py and use netaddr --- nova/api/ec2/cloud.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index b7a9a863326f..ceeaa3e48d7f 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -23,7 +23,7 @@ datastore. """ import base64 -import IPy +import netaddr import os import urllib import tempfile @@ -444,7 +444,7 @@ class CloudController(object): elif cidr_ip: # If this fails, it throws an exception. This is what we want. cidr_ip = urllib.unquote(cidr_ip).decode() - IPy.IP(cidr_ip) + netaddr.IPNetwork(cidr_ip) values['cidr'] = cidr_ip else: values['cidr'] = '0.0.0.0/0' From b7390c78054f839ac3340d771b9aae0109f5a98e Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Mon, 6 Jun 2011 15:34:51 -0400 Subject: [PATCH 03/24] Remove ipy from network code and replace with netaddr --- nova/network/linux_net.py | 4 +-- nova/network/manager.py | 43 ++++++++++++++++----------------- nova/tests/test_flat_network.py | 6 ++--- nova/tests/test_vlan_network.py | 6 ++--- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 815cd29c3a75..7b6f4497d11b 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -20,6 +20,7 @@ import calendar import inspect +import netaddr import os from nova import db @@ -27,7 +28,6 @@ from nova import exception from nova import flags from nova import log as logging from nova import utils -from IPy import IP LOG = logging.getLogger("nova.linux_net") @@ -700,7 +700,7 @@ def _dnsmasq_cmd(net): '--listen-address=%s' % net['gateway'], '--except-interface=lo', '--dhcp-range=%s,static,120s' % net['dhcp_start'], - '--dhcp-lease-max=%s' % IP(net['cidr']).len(), + '--dhcp-lease-max=%s' % len(netaddr.IPNetwork(net['cidr'])), '--dhcp-hostsfile=%s' % _dhcp_file(net['bridge'], 'conf'), '--dhcp-script=%s' % FLAGS.dhcpbridge, '--leasefile-ro'] diff --git a/nova/network/manager.py b/nova/network/manager.py index f726c4b265b6..f037312db4ba 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -45,10 +45,9 @@ topologies. All of the network commands are issued to a subclass of import datetime import math +import netaddr import socket -import IPy - from nova import context from nova import db from nova import exception @@ -294,8 +293,8 @@ class NetworkManager(manager.SchedulerDependentManager): def create_networks(self, context, cidr, num_networks, network_size, cidr_v6, label, *args, **kwargs): """Create networks based on parameters.""" - fixed_net = IPy.IP(cidr) - fixed_net_v6 = IPy.IP(cidr_v6) + fixed_net = netaddr.IPNetwork(cidr) + fixed_net_v6 = netaddr.IPNetwork(cidr_v6) significant_bits_v6 = 64 network_size_v6 = 1 << 64 count = 1 @@ -304,15 +303,15 @@ class NetworkManager(manager.SchedulerDependentManager): start_v6 = index * network_size_v6 significant_bits = 32 - int(math.log(network_size, 2)) cidr = '%s/%s' % (fixed_net[start], significant_bits) - project_net = IPy.IP(cidr) + project_net = netaddr.IPNetwork(cidr) net = {} net['bridge'] = FLAGS.flat_network_bridge net['dns'] = FLAGS.flat_network_dns net['cidr'] = cidr - net['netmask'] = str(project_net.netmask()) - net['gateway'] = str(project_net[1]) - net['broadcast'] = str(project_net.broadcast()) - net['dhcp_start'] = str(project_net[2]) + net['netmask'] = str(project_net.netmask) + net['gateway'] = str(list(project_net)[1]) + net['broadcast'] = str(project_net.broadcast) + net['dhcp_start'] = str(list(project_net)[2]) if num_networks > 1: net['label'] = '%s_%d' % (label, count) else: @@ -323,9 +322,9 @@ class NetworkManager(manager.SchedulerDependentManager): cidr_v6 = '%s/%s' % (fixed_net_v6[start_v6], significant_bits_v6) net['cidr_v6'] = cidr_v6 - project_net_v6 = IPy.IP(cidr_v6) - net['gateway_v6'] = str(project_net_v6[1]) - net['netmask_v6'] = str(project_net_v6.prefixlen()) + project_net_v6 = netaddr.IPNetwork(cidr_v6) + net['gateway_v6'] = str(list(project_net_v6)[1]) + net['netmask_v6'] = str(project_net_v6._prefixlen) network_ref = self.db.network_create_safe(context, net) @@ -349,7 +348,7 @@ class NetworkManager(manager.SchedulerDependentManager): # to properties of the manager class? bottom_reserved = self._bottom_reserved_ips top_reserved = self._top_reserved_ips - project_net = IPy.IP(network_ref['cidr']) + project_net = netaddr.IPNetwork(network_ref['cidr']) num_ips = len(project_net) for index in range(num_ips): address = str(project_net[index]) @@ -539,13 +538,13 @@ class VlanManager(NetworkManager): ' the vlan start cannot be greater' ' than 4094')) - fixed_net = IPy.IP(cidr) - if fixed_net.len() < num_networks * network_size: + fixed_net = netaddr.IPNetwork(cidr) + if len(fixed_net) < num_networks * network_size: raise ValueError(_('The network range is not big enough to fit ' '%(num_networks)s. Network size is %(network_size)s' % locals())) - fixed_net_v6 = IPy.IP(cidr_v6) + fixed_net_v6 = netaddr.IPNetwork(cidr_v6) network_size_v6 = 1 << 64 significant_bits_v6 = 64 for index in range(num_networks): @@ -554,14 +553,14 @@ class VlanManager(NetworkManager): start_v6 = index * network_size_v6 significant_bits = 32 - int(math.log(network_size, 2)) cidr = "%s/%s" % (fixed_net[start], significant_bits) - project_net = IPy.IP(cidr) + project_net = netaddr.IPNetwork(cidr) net = {} net['cidr'] = cidr - net['netmask'] = str(project_net.netmask()) - net['gateway'] = str(project_net[1]) - net['broadcast'] = str(project_net.broadcast()) - net['vpn_private_address'] = str(project_net[2]) - net['dhcp_start'] = str(project_net[3]) + net['netmask'] = str(project_net.netmask) + net['gateway'] = str(list(project_net)[1]) + net['broadcast'] = str(project_net.broadcast) + net['vpn_private_address'] = str(list(project_net)[2]) + net['dhcp_start'] = str(list(project_net)[3]) net['vlan'] = vlan net['bridge'] = 'br%s' % vlan if(FLAGS.use_ipv6): diff --git a/nova/tests/test_flat_network.py b/nova/tests/test_flat_network.py index dcc617e2539a..8544019c0440 100644 --- a/nova/tests/test_flat_network.py +++ b/nova/tests/test_flat_network.py @@ -18,7 +18,7 @@ """ Unit Tests for flat network code """ -import IPy +import netaddr import os import unittest @@ -45,8 +45,8 @@ class FlatNetworkTestCase(base.NetworkTestCase): self.context._project = self.projects[0] self.context.project_id = self.projects[0].id - pubnet = IPy.IP(flags.FLAGS.floating_range) - address = str(pubnet[0]) + 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: diff --git a/nova/tests/test_vlan_network.py b/nova/tests/test_vlan_network.py index 063b81832d17..a1c8ab11c62f 100644 --- a/nova/tests/test_vlan_network.py +++ b/nova/tests/test_vlan_network.py @@ -18,7 +18,7 @@ """ Unit Tests for vlan network code """ -import IPy +import netaddr import os from nova import context @@ -44,8 +44,8 @@ class VlanNetworkTestCase(base.NetworkTestCase): # TODO(vish): better way of adding floating ips self.context._project = self.projects[0] self.context.project_id = self.projects[0].id - pubnet = IPy.IP(flags.FLAGS.floating_range) - address = str(pubnet[0]) + 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: From 46bd8cbd1358a44534a620408b828ad08eef9cec Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Mon, 6 Jun 2011 15:35:33 -0400 Subject: [PATCH 04/24] Remove ipy from virt code and replace with netaddr --- nova/virt/libvirt/connection.py | 3 +-- nova/virt/libvirt/netutils.py | 14 +++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index c491418aefc1..da5911a1a038 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -38,6 +38,7 @@ Supports KVM, LXC, QEMU, UML, and XEN. import hashlib import multiprocessing +import netaddr import os import random import shutil @@ -52,8 +53,6 @@ from xml.etree import ElementTree from eventlet import greenthread from eventlet import tpool -import IPy - from nova import context from nova import db from nova import exception diff --git a/nova/virt/libvirt/netutils.py b/nova/virt/libvirt/netutils.py index 4d596078af4c..0bad84f7c23e 100644 --- a/nova/virt/libvirt/netutils.py +++ b/nova/virt/libvirt/netutils.py @@ -21,7 +21,7 @@ """Network-releated utilities for supporting libvirt connection code.""" -import IPy +import netaddr from nova import context from nova import db @@ -34,18 +34,18 @@ FLAGS = flags.FLAGS def get_net_and_mask(cidr): - net = IPy.IP(cidr) - return str(net.net()), str(net.netmask()) + net = netaddr.IPNetwork(cidr) + return str(net.ip), str(net.netmask) def get_net_and_prefixlen(cidr): - net = IPy.IP(cidr) - return str(net.net()), str(net.prefixlen()) + net = netaddr.IPNetwork(cidr) + return str(net.ip), str(net._prefixlen) def get_ip_version(cidr): - net = IPy.IP(cidr) - return int(net.version()) + net = netaddr.IPNetwork(cidr) + return int(net.version) def get_network_info(instance): From de42ebea7a8d055caeddd40edcdcaa6d64f1548e Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Mon, 6 Jun 2011 17:03:50 -0400 Subject: [PATCH 05/24] Convert stray import IPy --- nova/tests/test_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index 77f6aaff35c1..da92f206645e 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -18,7 +18,7 @@ """ Unit Tests for network code """ -import IPy +import netaddr import os from nova import test From 9effe34506c5a23f21b9132ff97a2217b0c99735 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Mon, 6 Jun 2011 17:04:12 -0400 Subject: [PATCH 06/24] Dropped requirement for IPy --- tools/pip-requires | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/pip-requires b/tools/pip-requires index e81ef944a01a..af8ce80cdea1 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -1,7 +1,6 @@ SQLAlchemy==0.6.3 pep8==0.5.0 pylint==0.19 -IPy==0.70 Cheetah==2.4.4 M2Crypto==0.20.2 amqplib==0.6.1 From 4b0b0361ed8d231844344d014412f7b647baae0b Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Mon, 6 Jun 2011 17:05:28 -0400 Subject: [PATCH 07/24] Remove more stray import IPy --- nova/tests/network/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/tests/network/base.py b/nova/tests/network/base.py index b06271c998a2..f6541682420d 100644 --- a/nova/tests/network/base.py +++ b/nova/tests/network/base.py @@ -18,7 +18,7 @@ """ Base class of Unit Tests for all network models """ -import IPy +import netaddr import os from nova import context From 0c3c0ef6e0604e24ab3f2ec25554a867fe64bd45 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Tue, 7 Jun 2011 10:39:30 -0400 Subject: [PATCH 08/24] Use IPNetwork rather than IPRange --- bin/nova-manage | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index 5ac0b8a0c276..1f8ccf268464 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -513,7 +513,7 @@ class FloatingIpCommands(object): def create(self, host, range): """Creates floating ips for host by range arguments: host ip_range""" - for address in netaddr.IPRange(range): + for address in netaddr.IPNetwork(range): db.floating_ip_create(context.get_admin_context(), {'address': str(address), 'host': host}) @@ -521,7 +521,7 @@ class FloatingIpCommands(object): def delete(self, ip_range): """Deletes floating ips by range arguments: range""" - for address in netaddr.IPRange(ip_range): + for address in netaddr.IPNetwork(ip_range): db.floating_ip_destroy(context.get_admin_context(), str(address)) From d1b6ebb4009e13ac2cf2309275a66a634e4f9171 Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Sat, 11 Jun 2011 16:42:58 -0400 Subject: [PATCH 09/24] Add ability to list ip blocks. --- nova/api/ec2/admin.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py index fcf7f674c652..37ae2e648b4b 100644 --- a/nova/api/ec2/admin.py +++ b/nova/api/ec2/admin.py @@ -369,3 +369,11 @@ class AdminController(object): raise exception.ApiError(_('Duplicate rule')) self.compute_api.trigger_provider_fw_rules_refresh(context) return {'status': 'OK', 'message': 'Added %s rules' % rules_added} + + def describe_external_address_blocks(self, context): + blocks = db.provider_fw_rule_get_all(context) + # NOTE(todd): use a set since we have icmp/udp/tcp rules with same cidr + blocks = set([b.cidr for b in blocks]) + blocks = [{'cidr': b} for b in blocks] + return {'externalIpBlockInfo': + list(sorted(blocks, key=lambda k: k['cidr']))} From ed3914eafa7d076fdcc03ee958f77528bcf20603 Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Sat, 11 Jun 2011 18:03:45 -0400 Subject: [PATCH 10/24] Add a method to delete provider firewall rules. --- nova/api/ec2/admin.py | 12 ++++++++++++ nova/db/api.py | 10 ++++++++++ nova/db/sqlalchemy/api.py | 21 +++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py index 37ae2e648b4b..da982d8dc0b3 100644 --- a/nova/api/ec2/admin.py +++ b/nova/api/ec2/admin.py @@ -377,3 +377,15 @@ class AdminController(object): blocks = [{'cidr': b} for b in blocks] return {'externalIpBlockInfo': list(sorted(blocks, key=lambda k: k['cidr']))} + + def remove_external_address_block(self, context, cidr): + LOG.audit(_('Removing ip block from %s'), cidr, context=context) + cidr = urllib.unquote(cidr).decode() + # raise if invalid + IPy.IP(cidr) + rules = db.provider_fw_rule_get_all_by_cidr(context, cidr) + for rule in rules: + db.provider_fw_rule_destroy(context, rule['id']) + if rules: + self.compute_api.trigger_provider_fw_rules_refresh(context) + return {'status': 'OK', 'message': 'Deleted %s rules' % len(rules)} diff --git a/nova/db/api.py b/nova/db/api.py index 798b2881c193..62368c438504 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -1004,6 +1004,16 @@ def provider_fw_rule_get_all(context): return IMPL.provider_fw_rule_get_all(context) +def provider_fw_rule_get_all_by_cidr(context, cidr): + """Get all provider-level firewall rules.""" + return IMPL.provider_fw_rule_get_all_by_cidr(context) + + +def provider_fw_rule_destroy(context, rule_id): + """Delete a provider firewall rule from the database.""" + return IMPL.provider_fw_rule_destroy(context) + + ################### diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 9612e456bc0a..c8802e354586 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -2093,6 +2093,7 @@ def provider_fw_rule_create(context, rule): return fw_rule_ref +@require_admin_context def provider_fw_rule_get_all(context): session = get_session() return session.query(models.ProviderFirewallRule).\ @@ -2100,6 +2101,26 @@ def provider_fw_rule_get_all(context): all() +@require_admin_context +def provider_fw_rule_get_all_by_cidr(context, cidr): + session = get_session() + return session.query(models.ProviderFirewallRule).\ + filter_by(deleted=can_read_deleted(context)).\ + filter_by(cidr=cidr).\ + all() + + +@require_admin_context +def provider_fw_rule_destroy(context, rule_id): + session = get_session() + with session.begin(): + session.query(models.ProviderFirewallRule).\ + filter_by(id=rule_id).\ + update({'deleted': True, + 'deleted_at': utils.utcnow(), + 'updated_at': literal_column('updated_at')}) + + ################### From 0a6aeacfedfd5e666e109b54c5c03908eeb47c31 Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Sat, 11 Jun 2011 18:38:44 -0400 Subject: [PATCH 11/24] fix method chaining in database layer to pass right parameters. --- nova/db/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/db/api.py b/nova/db/api.py index 62368c438504..6ff6ec2f31ba 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -1006,12 +1006,12 @@ def provider_fw_rule_get_all(context): def provider_fw_rule_get_all_by_cidr(context, cidr): """Get all provider-level firewall rules.""" - return IMPL.provider_fw_rule_get_all_by_cidr(context) + return IMPL.provider_fw_rule_get_all_by_cidr(context, cidr) def provider_fw_rule_destroy(context, rule_id): """Delete a provider firewall rule from the database.""" - return IMPL.provider_fw_rule_destroy(context) + return IMPL.provider_fw_rule_destroy(context, rule_id) ################### From 260af1f3edb7993a6b6374563ef2b46c7fa700df Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Mon, 20 Jun 2011 15:55:02 +0100 Subject: [PATCH 12/24] Enclosing tokens for xenapi filter in double quotes --- nova/network/xenapi_net.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nova/network/xenapi_net.py b/nova/network/xenapi_net.py index 709ef7f34b8b..7976a72657e7 100644 --- a/nova/network/xenapi_net.py +++ b/nova/network/xenapi_net.py @@ -56,8 +56,10 @@ def ensure_vlan_bridge(vlan_num, bridge, net_attrs=None): 'other_config': {}} network_ref = session.call_xenapi('network.create', network_rec) # 2 - find PIF for VLAN - expr = "field 'device' = '%s' and \ - field 'VLAN' = '-1'" % FLAGS.vlan_interface + # Note using double quotes inside single quotes as xapi filter + # only support tokens in double quotes + expr = 'field "device" = "%s" and \ + field "VLAN" = "-1"' % FLAGS.vlan_interface pifs = session.call_xenapi('PIF.get_all_records_where', expr) pif_ref = None # Multiple PIF are ok: we are dealing with a pool From 31e3aed4a25e0525797c7fc6cbdce0fa652b3878 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Mon, 20 Jun 2011 20:33:15 -0700 Subject: [PATCH 13/24] Remove the unnecessary insertion of whitespace. This happens to be enough to match this patch apply on recent versions of XenServer / Xen Cloud Platform. --- .../networking/etc/xensource/scripts/vif_5.6-fp1.patch | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/xenserver/networking/etc/xensource/scripts/vif_5.6-fp1.patch b/plugins/xenserver/networking/etc/xensource/scripts/vif_5.6-fp1.patch index feaf1312dd92..d42a11effaed 100644 --- a/plugins/xenserver/networking/etc/xensource/scripts/vif_5.6-fp1.patch +++ b/plugins/xenserver/networking/etc/xensource/scripts/vif_5.6-fp1.patch @@ -8,7 +8,7 @@ fi ;; -@@ -224,9 +225,11 @@ +@@ -224,6 +225,7 @@ remove) if [ "${TYPE}" = "vif" ] ;then @@ -16,7 +16,3 @@ xenstore-rm "${HOTPLUG}/hotplug" fi logger -t scripts-vif "${dev} has been removed" - remove_from_bridge - ;; - esac -+ From 35e922a2db9b45314108b35e438e9229bea4b977 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Tue, 21 Jun 2011 11:39:55 +0100 Subject: [PATCH 14/24] fix comment line --- nova/network/xenapi_net.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/network/xenapi_net.py b/nova/network/xenapi_net.py index 7976a72657e7..af295a4f8287 100644 --- a/nova/network/xenapi_net.py +++ b/nova/network/xenapi_net.py @@ -56,8 +56,8 @@ def ensure_vlan_bridge(vlan_num, bridge, net_attrs=None): 'other_config': {}} network_ref = session.call_xenapi('network.create', network_rec) # 2 - find PIF for VLAN - # Note using double quotes inside single quotes as xapi filter - # only support tokens in double quotes + # NOTE(salvatore-orlando): using double quotes inside single quotes + # as xapi filter only support tokens in double quotes expr = 'field "device" = "%s" and \ field "VLAN" = "-1"' % FLAGS.vlan_interface pifs = session.call_xenapi('PIF.get_all_records_where', expr) From 0e2b3e932d3e5fe00fed1da95e55808391d4832e Mon Sep 17 00:00:00 2001 From: Yuriy Taraday Date: Tue, 21 Jun 2011 16:55:45 +0400 Subject: [PATCH 15/24] Filter out datetime fields from instance_type --- nova/db/sqlalchemy/api.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 7119f43ebb0b..5dc2b9e7afb3 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -2510,7 +2510,10 @@ def instance_type_get_by_id(context, id): if not inst_type: raise exception.InstanceTypeNotFound(instance_type=id) else: - return dict(inst_type) + res = dict(inst_type) + for field in ['created_at', 'updated_at', 'deleted_at']: + res.pop(field, None) + return res @require_context @@ -2523,7 +2526,10 @@ def instance_type_get_by_name(context, name): if not inst_type: raise exception.InstanceTypeNotFoundByName(instance_type_name=name) else: - return dict(inst_type) + res = dict(inst_type) + for field in ['created_at', 'updated_at', 'deleted_at']: + res.pop(field, None) + return res @require_context @@ -2536,7 +2542,10 @@ def instance_type_get_by_flavor_id(context, id): if not inst_type: raise exception.FlavorNotFound(flavor_id=id) else: - return dict(inst_type) + res = dict(inst_type) + for field in ['created_at', 'updated_at', 'deleted_at']: + res.pop(field, None) + return res @require_admin_context From 92b0307879ae0142bc6e0ad78c7c0bbc009c0884 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 22 Jun 2011 15:11:23 -0400 Subject: [PATCH 16/24] updating glance image fixtures with checksum attribute; fixing glance image service to use checksum attribute --- nova/image/glance.py | 2 +- nova/tests/api/openstack/test_image_metadata.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/nova/image/glance.py b/nova/image/glance.py index 6e058ab2ff06..55d948a3258a 100644 --- a/nova/image/glance.py +++ b/nova/image/glance.py @@ -59,7 +59,7 @@ class GlanceImageService(service.BaseImageService): """Provides storage and retrieval of disk image objects within Glance.""" GLANCE_ONLY_ATTRS = ['size', 'location', 'disk_format', - 'container_format'] + 'container_format', 'checksum'] # NOTE(sirp): Overriding to use _translate_to_service provided by # BaseImageService diff --git a/nova/tests/api/openstack/test_image_metadata.py b/nova/tests/api/openstack/test_image_metadata.py index 56be0f1cc917..b55306efd016 100644 --- a/nova/tests/api/openstack/test_image_metadata.py +++ b/nova/tests/api/openstack/test_image_metadata.py @@ -37,6 +37,7 @@ class ImageMetaDataTest(unittest.TestCase): 'name': 'image1', 'deleted': False, 'container_format': None, + 'checksum': None, 'created_at': '2011-03-22T17:40:15', 'disk_format': None, 'updated_at': '2011-03-22T17:40:15', @@ -52,6 +53,7 @@ class ImageMetaDataTest(unittest.TestCase): 'name': 'image2', 'deleted': False, 'container_format': None, + 'checksum': None, 'created_at': '2011-03-22T17:40:15', 'disk_format': None, 'updated_at': '2011-03-22T17:40:15', @@ -67,6 +69,7 @@ class ImageMetaDataTest(unittest.TestCase): 'name': 'image3', 'deleted': False, 'container_format': None, + 'checksum': None, 'created_at': '2011-03-22T17:40:15', 'disk_format': None, 'updated_at': '2011-03-22T17:40:15', @@ -103,7 +106,10 @@ class ImageMetaDataTest(unittest.TestCase): res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(200, res.status_int) - self.assertEqual('value1', res_dict['metadata']['key1']) + expected = self.IMAGE_FIXTURES[0]['properties'] + self.assertEqual(len(expected), len(res_dict['metadata'])) + for (key, value) in res_dict['metadata'].items(): + self.assertEqual(value, res_dict['metadata'][key]) def test_show(self): req = webob.Request.blank('/v1.1/images/1/meta/key1') From c2a0f15457ec49e95de0a2e7cd6c8b60e81a4994 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Thu, 23 Jun 2011 09:57:22 -0400 Subject: [PATCH 17/24] Fixed typo --- nova/network/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/network/manager.py b/nova/network/manager.py index 38bcbe0e551c..bf0456522756 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -328,7 +328,7 @@ class NetworkManager(manager.SchedulerDependentManager): if gateway_v6: # use a pre-defined gateway if one is provided - net['gateway_v6'] = str(list(gateway_v6)[1])) + net['gateway_v6'] = str(list(gateway_v6)[1]) else: net['gateway_v6'] = str(list(project_net_v6)[1]) From ac4baa5990c45a6a521a1786e680426ba617c65a Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Thu, 23 Jun 2011 14:13:27 -0400 Subject: [PATCH 18/24] Add test for listing provider firewall rules. --- nova/tests/test_adminapi.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nova/tests/test_adminapi.py b/nova/tests/test_adminapi.py index 7ecaf1c095ce..2b90d49e9975 100644 --- a/nova/tests/test_adminapi.py +++ b/nova/tests/test_adminapi.py @@ -87,3 +87,10 @@ class AdminApiTestCase(test.TestCase): result = self.api.block_external_addresses(self.context, '1.1.1.1/32') self.assertEqual('OK', result['status']) self.assertEqual('Added 3 rules', result['message']) + + def test_list_blocked_ips(self): + """Make sure we can see the external blocks that exist.""" + result = self.api.describe_external_address_blocks(self.context) + num = len(db.provider_fw_rule_get_all(self.context)) + # we only list IP, not tcp/udp/icmp rules + self.assertEqual(num / 3, len(result['externalIpBlockInfo'])) From 6e2ebfa1dc29e50f74f1b337d1b5349bc3c78cdc Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Thu, 23 Jun 2011 14:16:11 -0400 Subject: [PATCH 19/24] Make sure there are actually rules to test against. --- nova/tests/test_adminapi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nova/tests/test_adminapi.py b/nova/tests/test_adminapi.py index 2b90d49e9975..4a96a3dd9f55 100644 --- a/nova/tests/test_adminapi.py +++ b/nova/tests/test_adminapi.py @@ -90,6 +90,7 @@ class AdminApiTestCase(test.TestCase): def test_list_blocked_ips(self): """Make sure we can see the external blocks that exist.""" + self.api.block_external_addresses(self.context, '1.1.1.2/32') result = self.api.describe_external_address_blocks(self.context) num = len(db.provider_fw_rule_get_all(self.context)) # we only list IP, not tcp/udp/icmp rules From 9a6e9a1af9359fb4a9261f59f57113f252f0d6e9 Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Thu, 23 Jun 2011 14:45:37 -0400 Subject: [PATCH 20/24] Make firewall rules tests idempotent, move IPy=>netaddr, add deltete test. --- nova/api/ec2/admin.py | 2 +- nova/tests/test_adminapi.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py index b8fc8f11498f..df7876b9d756 100644 --- a/nova/api/ec2/admin.py +++ b/nova/api/ec2/admin.py @@ -382,7 +382,7 @@ class AdminController(object): LOG.audit(_('Removing ip block from %s'), cidr, context=context) cidr = urllib.unquote(cidr).decode() # raise if invalid - IPy.IP(cidr) + netaddr.IPNetwork(cidr) rules = db.provider_fw_rule_get_all_by_cidr(context, cidr) for rule in rules: db.provider_fw_rule_destroy(context, rule['id']) diff --git a/nova/tests/test_adminapi.py b/nova/tests/test_adminapi.py index 4a96a3dd9f55..ce826fd5ba92 100644 --- a/nova/tests/test_adminapi.py +++ b/nova/tests/test_adminapi.py @@ -85,6 +85,7 @@ class AdminApiTestCase(test.TestCase): def test_block_external_ips(self): """Make sure provider firewall rules are created.""" result = self.api.block_external_addresses(self.context, '1.1.1.1/32') + self.api.remove_external_address_block(self.context, '1.1.1.1/32') self.assertEqual('OK', result['status']) self.assertEqual('Added 3 rules', result['message']) @@ -93,5 +94,18 @@ class AdminApiTestCase(test.TestCase): self.api.block_external_addresses(self.context, '1.1.1.2/32') result = self.api.describe_external_address_blocks(self.context) num = len(db.provider_fw_rule_get_all(self.context)) + self.api.remove_external_address_block(self.context, '1.1.1.2/32') # we only list IP, not tcp/udp/icmp rules self.assertEqual(num / 3, len(result['externalIpBlockInfo'])) + + def test_remove_ip_block(self): + """Remove ip blocks.""" + result = self.api.block_external_addresses(self.context, '1.1.1.3/32') + self.assertEqual('OK', result['status']) + num0 = len(db.provider_fw_rule_get_all(self.context)) + result = self.api.remove_external_address_block(self.context, + '1.1.1.3/32') + self.assertEqual('OK', result['status']) + self.assertEqual('Deleted 3 rules', result['message']) + num1 = len(db.provider_fw_rule_get_all(self.context)) + self.assert_(num1 < num0) From 51d93c5b1722bef9783cd7572c1464a084ece0aa Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Thu, 23 Jun 2011 14:52:58 -0400 Subject: [PATCH 21/24] libvirt test for deleting provider firewall rules. --- nova/tests/test_libvirt.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index ee94d3c171b0..d12e2106366f 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -1115,6 +1115,13 @@ class IptablesFirewallTestCase(test.TestCase): provjump_rules.append(rule) self.assertEqual(1, len(provjump_rules)) + # remove a rule from the db, cast to compute to refresh rule + db.provider_fw_rule_destroy(admin_ctxt, provider_fw1['id']) + self.fw.refresh_provider_fw_rules() + rules = [rule for rule in self.fw.iptables.ipv4['filter'].rules + if rule.chain == 'provider'] + self.assertEqual(1, len(rules)) + class NWFilterTestCase(test.TestCase): def setUp(self): From d4fc1d77a4b7c668453042b83e34da76ee3c3818 Mon Sep 17 00:00:00 2001 From: Yuriy Taraday Date: Fri, 24 Jun 2011 09:54:38 +0400 Subject: [PATCH 22/24] Unwind last commit, force anyjson to use our serialization methods. --- bin/nova-manage | 8 ++++---- nova/compute/api.py | 1 + nova/db/sqlalchemy/api.py | 15 +++------------ nova/utils.py | 9 +++++++++ 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index 0147ae21b837..e09ea495d121 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -874,10 +874,10 @@ class InstanceTypeCommands(object): try: instance_types.create(name, memory, vcpus, local_gb, flavorid, swap, rxtx_quota, rxtx_cap) - except exception.InvalidInputException: - print "Must supply valid parameters to create instance_type" - print e - sys.exit(1) + #except exception.InvalidInputException: + # print "Must supply valid parameters to create instance_type" + # print e + # sys.exit(1) except exception.ApiError, e: print "\n\n" print "\n%s" % e diff --git a/nova/compute/api.py b/nova/compute/api.py index f1c31a092621..9a77a2aa2c98 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -291,6 +291,7 @@ class API(base.Base): 'blob': zone_blob, 'num_instances': num_instances, } + LOG.debug(request_spec) rpc.cast(context, FLAGS.scheduler_topic, diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 5dc2b9e7afb3..7119f43ebb0b 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -2510,10 +2510,7 @@ def instance_type_get_by_id(context, id): if not inst_type: raise exception.InstanceTypeNotFound(instance_type=id) else: - res = dict(inst_type) - for field in ['created_at', 'updated_at', 'deleted_at']: - res.pop(field, None) - return res + return dict(inst_type) @require_context @@ -2526,10 +2523,7 @@ def instance_type_get_by_name(context, name): if not inst_type: raise exception.InstanceTypeNotFoundByName(instance_type_name=name) else: - res = dict(inst_type) - for field in ['created_at', 'updated_at', 'deleted_at']: - res.pop(field, None) - return res + return dict(inst_type) @require_context @@ -2542,10 +2536,7 @@ def instance_type_get_by_flavor_id(context, id): if not inst_type: raise exception.FlavorNotFound(flavor_id=id) else: - res = dict(inst_type) - for field in ['created_at', 'updated_at', 'deleted_at']: - res.pop(field, None) - return res + return dict(inst_type) @require_admin_context diff --git a/nova/utils.py b/nova/utils.py index 691134ada4b6..a77cf7993e43 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -525,6 +525,15 @@ def loads(s): return json.loads(s) +try: + import anyjson +except ImportError: + pass +else: + anyjson._modules.append(("nova.utils", "dumps", TypeError, "loads", ValueError)) + anyjson.force_implementation("nova.utils") + + _semaphores = {} From a1c5726a9e0095de88c9d10c09999b2dcdb6211e Mon Sep 17 00:00:00 2001 From: Yuriy Taraday Date: Fri, 24 Jun 2011 16:07:33 +0400 Subject: [PATCH 23/24] Remove extra debug line. --- nova/compute/api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nova/compute/api.py b/nova/compute/api.py index b570eb9864bb..af18741b60b2 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -325,7 +325,6 @@ class API(base.Base): 'blob': zone_blob, 'num_instances': num_instances, } - LOG.debug(request_spec) rpc.cast(context, FLAGS.scheduler_topic, From e253cd3cf01d29106daff1592a7c629307b449ff Mon Sep 17 00:00:00 2001 From: Yuriy Taraday Date: Sat, 25 Jun 2011 14:04:40 +0400 Subject: [PATCH 24/24] PEP8 fix --- nova/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nova/utils.py b/nova/utils.py index 8f9ca42c1a25..6d8324e5bd3b 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -531,7 +531,8 @@ try: except ImportError: pass else: - anyjson._modules.append(("nova.utils", "dumps", TypeError, "loads", ValueError)) + anyjson._modules.append(("nova.utils", "dumps", TypeError, + "loads", ValueError)) anyjson.force_implementation("nova.utils")