From a8f09b1ccb0c070561ce9a5fea71399430701664 Mon Sep 17 00:00:00 2001 From: cameron-r Date: Wed, 5 Nov 2014 14:49:02 -0600 Subject: [PATCH] Cameron & Ed | Extract looping over groups and refreshing their rules to GroupRuleRefresher --- ec2driver.py | 65 +++++++------------ group_rule_refresher.py | 22 +++++++ instance_rule_refresher.py | 11 ++++ rule_refresher.py | 29 --------- ...resher.py => test_group_rule_refresher.py} | 28 ++------ tests/unit/test_instance_rule_refresher.py | 21 ++++++ 6 files changed, 80 insertions(+), 96 deletions(-) create mode 100644 group_rule_refresher.py create mode 100644 instance_rule_refresher.py delete mode 100644 rule_refresher.py rename tests/unit/{test_rule_refresher.py => test_group_rule_refresher.py} (52%) create mode 100644 tests/unit/test_instance_rule_refresher.py diff --git a/ec2driver.py b/ec2driver.py index ada1465..f0c9c44 100644 --- a/ec2driver.py +++ b/ec2driver.py @@ -25,6 +25,8 @@ from boto.exception import EC2ResponseError from boto.regioninfo import RegionInfo from oslo.config import cfg from novaclient.v1_1 import client +from ec2_rule_service import EC2RuleService +from ec2_rule_transformer import EC2RuleTransformer from ec2driver_config import * from nova import block_device @@ -39,8 +41,13 @@ from nova.openstack.common import loopingcall from nova.virt import driver from nova.virt import virtapi from credentials import get_nova_creds +from instance_rule_refresher import InstanceRuleRefresher +from openstack_group_service import OpenstackGroupService +from openstack_rule_service import OpenstackRuleService +from openstack_rule_transformer import OpenstackRuleTransformer import rule_comparator +from group_rule_refresher import GroupRuleRefresher LOG = logging.getLogger(__name__) @@ -156,7 +163,20 @@ class EC2Driver(driver.ComputeDriver): aws_region, aws_access_key_id=CONF.ec2driver.ec2_access_key_id, aws_secret_access_key=CONF.ec2driver.ec2_secret_access_key) self.security_group_lock = Lock() - self.rule_comparator = rule_comparator.RuleComparator(self.ec2_conn) + + self.instance_rule_refresher = InstanceRuleRefresher( + GroupRuleRefresher( + ec2_connection=self.ec2_conn, + openstack_rule_service=OpenstackRuleService( + group_service=OpenstackGroupService(self.nova.security_groups), + openstack_rule_transformer=OpenstackRuleTransformer() + ), + ec2_rule_service=EC2RuleService( + ec2_connection=self.ec2_conn, + ec2_rule_transformer=EC2RuleTransformer() + ) + ) + ) if not '_EC2_NODES' in globals(): set_nodes([CONF.host]) @@ -720,48 +740,7 @@ class EC2Driver(driver.ComputeDriver): # TODO: lock for case when group is associated with multiple instances [Cameron & Ed] - openstack_instance = self.nova.servers.get(instance['id']) - - for group_dict in openstack_instance.security_groups: - - openstack_group =\ - [group for group in self.nova.security_groups.list() if group.name == group_dict['name']][0] - - ec2_group = self.ec2_conn.get_all_security_groups(groupnames=group_dict['name'])[0] - - for openstack_rule in openstack_group.rules: - equivalent_rule_found_in_ec2 = False - for ec2_rule in ec2_group.rules: - if self.rule_comparator.rules_are_equal(openstack_rule, ec2_rule): - equivalent_rule_found_in_ec2 = True - break - - if not equivalent_rule_found_in_ec2: - self.ec2_conn.authorize_security_group( - group_name=ec2_group.name, - ip_protocol=openstack_rule['ip_protocol'], - from_port=openstack_rule['from_port'], - to_port=openstack_rule['to_port'], - src_security_group_name=self._get_allowed_group_name_from_openstack_rule_if_present(openstack_rule), - cidr_ip=self._get_allowed_ip_range_from_openstack_rule_if_present(openstack_rule) - ) - - for ec2_rule in ec2_group.rules: - equivalent_rule_found_in_openstack = False - for openstack_rule in openstack_group.rules: - if self.rule_comparator.rules_are_equal(openstack_rule, ec2_rule): - equivalent_rule_found_in_openstack = True - break - - if not equivalent_rule_found_in_openstack: - self.ec2_conn.revoke_security_group( - group_name=ec2_group.name, - ip_protocol=ec2_rule.ip_protocol, - from_port=ec2_rule.from_port, - to_port=ec2_rule.to_port, - cidr_ip=ec2_rule.grants[0].cidr_ip, - src_security_group_group_id=ec2_rule.grants[0].group_id - ) + self.instance_rule_refresher.refresh(self.nova.servers.get(instance['id'])) return diff --git a/group_rule_refresher.py b/group_rule_refresher.py new file mode 100644 index 0000000..e8dafbb --- /dev/null +++ b/group_rule_refresher.py @@ -0,0 +1,22 @@ +class GroupRuleRefresher: + + def __init__(self, ec2_connection, openstack_rule_service, ec2_rule_service): + self.ec2_conn = ec2_connection + self.openstack_rule_service = openstack_rule_service + self.ec2_rule_service = ec2_rule_service + + def refresh(self, group_name): + openstack_rules = self.openstack_rule_service.get_rules_for_group(group_name) + ec2_rules = self.ec2_rule_service.get_rules_for_group(group_name) + + for rule in openstack_rules - ec2_rules: + self._create_rule_on_ec2(group_name, rule) + + def _create_rule_on_ec2(self, group_name, rule): + self.ec2_conn.authorize_security_group( + group_name=group_name, + ip_protocol=rule.ip_protocol, + from_port=rule.from_port, + to_port=rule.to_port, + cidr_ip=rule.ip_range + ) \ No newline at end of file diff --git a/instance_rule_refresher.py b/instance_rule_refresher.py new file mode 100644 index 0000000..03a0d70 --- /dev/null +++ b/instance_rule_refresher.py @@ -0,0 +1,11 @@ +class InstanceRuleRefresher: + + def __init__(self, group_rule_refresher): + self.group_rule_refresher = group_rule_refresher + + def refresh(self, instance): + for group_name in self._get_group_names(instance): + self.group_rule_refresher.refresh(group_name) + + def _get_group_names(self, instance): + return [group['name'] for group in instance.security_groups] diff --git a/rule_refresher.py b/rule_refresher.py deleted file mode 100644 index 0e64921..0000000 --- a/rule_refresher.py +++ /dev/null @@ -1,29 +0,0 @@ -class RuleRefresher: - - def __init__(self, ec2_conn, openstack_rule_service, ec2_rule_service): - self.ec2_conn = ec2_conn - self.openstack_rule_service = openstack_rule_service - self.ec2_rule_service = ec2_rule_service - - def refresh(self, openstack_instance): - for group_dict in openstack_instance.security_groups: - # openstack_group = [group for group in self.openstack_group_manager.list() if group.name == group_dict['name']][0] - # transformed_openstack_group = self.openstack_group_transformer.to_group(openstack_group) - # ec2_group = self.ec2_conn.get_all_security_groups(groupnames=group_dict['name'])[0] - # transformed_ec2_group = self.ec2_group_transformer.to_group(ec2_group) - - # TODO: transform openstack rules before finding difference - openstack_rules = self.openstack_rule_service.get_rules_for_group(group_dict['name']) - ec2_rules = self.ec2_rule_service.get_rules_for_group(group_dict['name']) - - for rule in openstack_rules - ec2_rules: - self._create_rule_on_ec2(group_dict['name'], rule) - - def _create_rule_on_ec2(self, group_name, rule): - self.ec2_conn.authorize_security_group( - group_name=group_name, - ip_protocol=rule.ip_protocol, - from_port=rule.from_port, - to_port=rule.to_port, - cidr_ip=rule.ip_range - ) \ No newline at end of file diff --git a/tests/unit/test_rule_refresher.py b/tests/unit/test_group_rule_refresher.py similarity index 52% rename from tests/unit/test_rule_refresher.py rename to tests/unit/test_group_rule_refresher.py index 4513a39..1166a71 100644 --- a/tests/unit/test_rule_refresher.py +++ b/tests/unit/test_group_rule_refresher.py @@ -3,7 +3,7 @@ import unittest from boto.ec2 import EC2Connection from mock import Mock -from nova.virt.ec2.rule_refresher import RuleRefresher +from nova.virt.ec2.group_rule_refresher import GroupRuleRefresher from nova.virt.ec2.rule import Rule from nova.virt.ec2.openstack_rule_service import OpenstackRuleService from nova.virt.ec2.ec2_rule_service import EC2RuleService @@ -11,7 +11,7 @@ from nova.virt.ec2.ec2_rule_service import EC2RuleService GROUP_NAME = 'secGroup' OTHER_GROUP_NAME = "otherSecGroup" -class TestRuleRefresher(unittest.TestCase): +class TestGroupRuleRefresher(unittest.TestCase): def setUp(self): self.new_rule = Rule('hjkl', 7, 8, '9.9.9.9/99') self.openstack_instance = Mock() @@ -20,19 +20,17 @@ class TestRuleRefresher(unittest.TestCase): self.openstack_rule_service = Mock(OpenstackRuleService) self.ec2_rule_service = Mock(EC2RuleService) - self.rule_refresher = RuleRefresher( + self.group_rule_refresher = GroupRuleRefresher( self.ec2_connection, self.openstack_rule_service, self.ec2_rule_service ) def test_should_add_rule_to_ec2_security_group_when_rule_associated_with_group_on_openstack(self): - self.openstack_instance.security_groups = [{'name': GROUP_NAME}] - self.openstack_rule_service.get_rules_for_group.return_value = set([self.new_rule]) self.ec2_rule_service.get_rules_for_group.return_value = set() - self.rule_refresher.refresh(self.openstack_instance) + self.group_rule_refresher.refresh(GROUP_NAME) self.ec2_connection.authorize_security_group.assert_called_once_with( group_name=GROUP_NAME, @@ -40,22 +38,4 @@ class TestRuleRefresher(unittest.TestCase): from_port=self.new_rule.from_port, to_port=self.new_rule.to_port, cidr_ip=self.new_rule.ip_range - ) - - def test_should_add_rule_to_corresponding_ec2_group_when_other_groups_present(self): - self.openstack_instance.security_groups = [{'name': GROUP_NAME}, {'name': OTHER_GROUP_NAME}] - - def mock_get_rules_for_openstack_group(group_name): - return set() if group_name == GROUP_NAME else set([self.new_rule]) - self.openstack_rule_service.get_rules_for_group.side_effect = mock_get_rules_for_openstack_group - self.ec2_rule_service.get_rules_for_group.return_value = set() - - self.rule_refresher.refresh(self.openstack_instance) - - self.ec2_connection.authorize_security_group.assert_called_once_with( - group_name=OTHER_GROUP_NAME, - ip_protocol=self.new_rule.ip_protocol, - from_port=self.new_rule.from_port, - to_port=self.new_rule.to_port, - cidr_ip=self.new_rule.ip_range ) \ No newline at end of file diff --git a/tests/unit/test_instance_rule_refresher.py b/tests/unit/test_instance_rule_refresher.py new file mode 100644 index 0000000..57b1727 --- /dev/null +++ b/tests/unit/test_instance_rule_refresher.py @@ -0,0 +1,21 @@ +import unittest +from mock import Mock, call +from nova.virt.ec2.group_rule_refresher import GroupRuleRefresher +from nova.virt.ec2.instance_rule_refresher import InstanceRuleRefresher + + +class TestInstanceRuleRefresher(unittest.TestCase): + + def test_should_call_group_rule_refresher_on_every_group_for_instance(self): + + group_rule_refresher = Mock(spec=GroupRuleRefresher) + + instance = Mock() + first_group = {'name': 'firstGroup'} + second_group = {'name': 'secondGroup'} + instance.security_groups = [first_group, second_group] + + instance_rule_refresher = InstanceRuleRefresher(group_rule_refresher) + instance_rule_refresher.refresh(instance) + + group_rule_refresher.refresh.assert_has_calls([call(first_group['name']), call(second_group['name'])]) \ No newline at end of file