Cameron & Ed | Extract looping over groups and refreshing their rules to GroupRuleRefresher

This commit is contained in:
cameron-r 2014-11-05 14:49:02 -06:00
parent 6d4ec264a5
commit a8f09b1ccb
6 changed files with 80 additions and 96 deletions

View File

@ -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

22
group_rule_refresher.py Normal file
View File

@ -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
)

View File

@ -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]

View File

@ -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
)

View File

@ -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
)

View File

@ -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'])])