Cameron & Ed | Extract looping over groups and refreshing their rules to GroupRuleRefresher
This commit is contained in:
parent
6d4ec264a5
commit
a8f09b1ccb
65
ec2driver.py
65
ec2driver.py
|
@ -25,6 +25,8 @@ from boto.exception import EC2ResponseError
|
||||||
from boto.regioninfo import RegionInfo
|
from boto.regioninfo import RegionInfo
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
from novaclient.v1_1 import client
|
from novaclient.v1_1 import client
|
||||||
|
from ec2_rule_service import EC2RuleService
|
||||||
|
from ec2_rule_transformer import EC2RuleTransformer
|
||||||
|
|
||||||
from ec2driver_config import *
|
from ec2driver_config import *
|
||||||
from nova import block_device
|
from nova import block_device
|
||||||
|
@ -39,8 +41,13 @@ from nova.openstack.common import loopingcall
|
||||||
from nova.virt import driver
|
from nova.virt import driver
|
||||||
from nova.virt import virtapi
|
from nova.virt import virtapi
|
||||||
from credentials import get_nova_creds
|
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
|
import rule_comparator
|
||||||
|
from group_rule_refresher import GroupRuleRefresher
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
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)
|
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.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():
|
if not '_EC2_NODES' in globals():
|
||||||
set_nodes([CONF.host])
|
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]
|
# TODO: lock for case when group is associated with multiple instances [Cameron & Ed]
|
||||||
|
|
||||||
openstack_instance = self.nova.servers.get(instance['id'])
|
self.instance_rule_refresher.refresh(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
|
|
||||||
)
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
|
@ -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]
|
|
@ -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
|
|
||||||
)
|
|
|
@ -3,7 +3,7 @@ import unittest
|
||||||
from boto.ec2 import EC2Connection
|
from boto.ec2 import EC2Connection
|
||||||
from mock import Mock
|
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.rule import Rule
|
||||||
from nova.virt.ec2.openstack_rule_service import OpenstackRuleService
|
from nova.virt.ec2.openstack_rule_service import OpenstackRuleService
|
||||||
from nova.virt.ec2.ec2_rule_service import EC2RuleService
|
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'
|
GROUP_NAME = 'secGroup'
|
||||||
OTHER_GROUP_NAME = "otherSecGroup"
|
OTHER_GROUP_NAME = "otherSecGroup"
|
||||||
|
|
||||||
class TestRuleRefresher(unittest.TestCase):
|
class TestGroupRuleRefresher(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.new_rule = Rule('hjkl', 7, 8, '9.9.9.9/99')
|
self.new_rule = Rule('hjkl', 7, 8, '9.9.9.9/99')
|
||||||
self.openstack_instance = Mock()
|
self.openstack_instance = Mock()
|
||||||
|
@ -20,19 +20,17 @@ class TestRuleRefresher(unittest.TestCase):
|
||||||
self.openstack_rule_service = Mock(OpenstackRuleService)
|
self.openstack_rule_service = Mock(OpenstackRuleService)
|
||||||
self.ec2_rule_service = Mock(EC2RuleService)
|
self.ec2_rule_service = Mock(EC2RuleService)
|
||||||
|
|
||||||
self.rule_refresher = RuleRefresher(
|
self.group_rule_refresher = GroupRuleRefresher(
|
||||||
self.ec2_connection,
|
self.ec2_connection,
|
||||||
self.openstack_rule_service,
|
self.openstack_rule_service,
|
||||||
self.ec2_rule_service
|
self.ec2_rule_service
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_should_add_rule_to_ec2_security_group_when_rule_associated_with_group_on_openstack(self):
|
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.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.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(
|
self.ec2_connection.authorize_security_group.assert_called_once_with(
|
||||||
group_name=GROUP_NAME,
|
group_name=GROUP_NAME,
|
||||||
|
@ -40,22 +38,4 @@ class TestRuleRefresher(unittest.TestCase):
|
||||||
from_port=self.new_rule.from_port,
|
from_port=self.new_rule.from_port,
|
||||||
to_port=self.new_rule.to_port,
|
to_port=self.new_rule.to_port,
|
||||||
cidr_ip=self.new_rule.ip_range
|
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
|
|
||||||
)
|
)
|
|
@ -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'])])
|
Loading…
Reference in New Issue