Skip to content

Commit

Permalink
Blueprint xenapi-security-groups
Browse files Browse the repository at this point in the history
Provides two drivers for implementing security groups in xenapi:
1) domU driver that enforces security groups on the Openstack virtual appliance (use advised with FlatDHCP in HA mode)
2) dom0 driver that enforces security groups where VIFs are attached

Both drivers translate security groups into iptables rules.
Existing libvirt code has been refactored to reduce the amount of duplicated code to a minimum

Now Addressing reviewers's comments on style. Fixing issue spotted with snapshots
Change-Id: Ifa16a8f2508a709be03241bac0f942fe1a51d1e8
  • Loading branch information
Salvatore Orlando committed Jan 10, 2012
1 parent 799801f commit eac7888
Show file tree
Hide file tree
Showing 15 changed files with 915 additions and 286 deletions.
1 change: 0 additions & 1 deletion nova/compute/manager.py
Expand Up @@ -165,7 +165,6 @@ def __init__(self, compute_driver=None, *args, **kwargs):
# and re-document the module docstring
if not compute_driver:
compute_driver = FLAGS.compute_driver

try:
self.driver = utils.check_isinstance(
utils.import_object(compute_driver),
Expand Down
5 changes: 4 additions & 1 deletion nova/flags.py
Expand Up @@ -393,7 +393,10 @@ def _get_my_ip():
'maxinum VCs in a VSA')
DEFINE_integer('vsa_part_size_gb', 100,
'default partition size for shared capacity')

# Default firewall driver for security groups and provider firewall
DEFINE_string('firewall_driver',
'nova.virt.libvirt.firewall.IptablesFirewallDriver',
'Firewall driver (defaults to iptables)')
# The service to use for image search and retrieval
DEFINE_string('image_service', 'nova.image.glance.GlanceImageService',
'The service to use for retrieving and searching for images.')
Expand Down
292 changes: 283 additions & 9 deletions nova/tests/test_xenapi.py

Large diffs are not rendered by default.

89 changes: 85 additions & 4 deletions nova/tests/xenapi/stubs.py
Expand Up @@ -7,7 +7,6 @@
# 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
Expand All @@ -17,6 +16,7 @@
"""Stubouts, mocks and fixtures for the test suite"""

import eventlet
import json
import random

from nova.virt import xenapi_conn
Expand All @@ -27,6 +27,17 @@
from nova import utils


def stubout_firewall_driver(stubs, conn):

def fake_none(self, *args):
return

vmops = conn._vmops
stubs.Set(vmops.firewall_driver, 'setup_basic_filtering', fake_none)
stubs.Set(vmops.firewall_driver, 'prepare_instance_filter', fake_none)
stubs.Set(vmops.firewall_driver, 'instance_filter_exists', fake_none)


def stubout_instance_snapshot(stubs):
@classmethod
def fake_fetch_image(cls, context, session, instance, image, user,
Expand All @@ -42,7 +53,7 @@ def fake_wait_for_vhd_coalesce(*args):
stubs.Set(vm_utils, '_wait_for_vhd_coalesce', fake_wait_for_vhd_coalesce)


def stubout_session(stubs, cls, product_version=None):
def stubout_session(stubs, cls, product_version=None, **opt_args):
"""Stubs out three methods from XenAPISession"""
def fake_import(self):
"""Stubs out get_imported_xenapi of XenAPISession"""
Expand All @@ -51,7 +62,7 @@ def fake_import(self):
return __import__(fake_module, globals(), locals(), from_list, -1)

stubs.Set(xenapi_conn.XenAPISession, '_create_session',
lambda s, url: cls(url))
lambda s, url: cls(url, **opt_args))
stubs.Set(xenapi_conn.XenAPISession, 'get_imported_xenapi',
fake_import)
if product_version is None:
Expand Down Expand Up @@ -90,14 +101,24 @@ def f(_1):


def stubout_determine_is_pv_objectstore(stubs):
"""Assumes VMs never have PV kernels"""
"""Assumes VMs stu have PV kernels"""

@classmethod
def f(cls, *args):
return False
stubs.Set(vm_utils.VMHelper, '_determine_is_pv_objectstore', f)


def stubout_is_snapshot(stubs):
""" Always returns true
xenapi fake driver does not create vmrefs for snapshots """

@classmethod
def f(cls, *args):
return True
stubs.Set(vm_utils.VMHelper, 'is_snapshot', f)


def stubout_lookup_image(stubs):
"""Simulates a failure in lookup image."""
def f(_1, _2, _3, _4):
Expand Down Expand Up @@ -140,13 +161,26 @@ def _make_fake_vdi():

class FakeSessionForVMTests(fake.SessionBase):
""" Stubs out a XenAPISession for VM tests """

_fake_iptables_save_output = \
"# Generated by iptables-save v1.4.10 on Sun Nov 6 22:49:02 2011\n"\
"*filter\n"\
":INPUT ACCEPT [0:0]\n"\
":FORWARD ACCEPT [0:0]\n"\
":OUTPUT ACCEPT [0:0]\n"\
"COMMIT\n"\
"# Completed on Sun Nov 6 22:49:02 2011\n"

def __init__(self, uri):
super(FakeSessionForVMTests, self).__init__(uri)

def host_call_plugin(self, _1, _2, plugin, method, _5):
if (plugin, method) == ('glance', 'download_vhd'):
return fake.as_json(dict(vdi_type='os',
vdi_uuid=_make_fake_vdi()))
elif (plugin, method) == ("xenhost", "iptables_config"):
return fake.as_json(out=self._fake_iptables_save_output,
err='')
else:
return (super(FakeSessionForVMTests, self).
host_call_plugin(_1, _2, plugin, method, _5))
Expand Down Expand Up @@ -196,6 +230,53 @@ def VDI_set_name_label(self, session_ref, vdi_ref, name_label):
pass


class FakeSessionForFirewallTests(FakeSessionForVMTests):
""" Stubs out a XenApi Session for doing IPTable Firewall tests """

def __init__(self, uri, test_case=None):
super(FakeSessionForFirewallTests, self).__init__(uri)
if hasattr(test_case, '_in_filter_rules'):
self._in_filter_rules = test_case._in_filter_rules
if hasattr(test_case, '_in6_filter_rules'):
self._in6_filter_rules = test_case._in6_filter_rules
if hasattr(test_case, '_in_nat_rules'):
self._in_nat_rules = test_case._in_nat_rules
self._test_case = test_case

def host_call_plugin(self, _1, _2, plugin, method, args):
"""Mock method four host_call_plugin to be used in unit tests
for the dom0 iptables Firewall drivers for XenAPI
"""
if plugin == "xenhost" and method == "iptables_config":
# The command to execute is a json-encoded list
cmd_args = args.get('cmd_args', None)
cmd = json.loads(cmd_args)
if not cmd:
ret_str = ''
else:
output = ''
process_input = args.get('process_input', None)
if cmd == ['ip6tables-save', '-t', 'filter']:
output = '\n'.join(self._in6_filter_rules)
if cmd == ['iptables-save', '-t', 'filter']:
output = '\n'.join(self._in_filter_rules)
if cmd == ['iptables-save', '-t', 'nat']:
output = '\n'.join(self._in_nat_rules)
if cmd == ['iptables-restore', ]:
lines = process_input.split('\n')
if '*filter' in lines:
if self._test_case is not None:
self._test_case._out_rules = lines
output = '\n'.join(lines)
if cmd == ['ip6tables-restore', ]:
lines = process_input.split('\n')
if '*filter' in lines:
output = '\n'.join(lines)
ret_str = fake.as_json(out=output, err='')
return ret_str


def stub_out_vm_methods(stubs):
def fake_shutdown(self, inst, vm, method="clean"):
pass
Expand Down

0 comments on commit eac7888

Please sign in to comment.