@@ -44,7 +44,19 @@ quark_opts = [
 | 
			
		||||
                       "sentinel hosts")),
 | 
			
		||||
    cfg.StrOpt("redis_sentinel_master",
 | 
			
		||||
               default='',
 | 
			
		||||
               help=_("The name label of the master redis sentinel"))]
 | 
			
		||||
               help=_("The name label of the master redis sentinel")),
 | 
			
		||||
    cfg.BoolOpt("redis_use_ssl",
 | 
			
		||||
                default=False,
 | 
			
		||||
                help=_("Configures whether or not to use SSL")),
 | 
			
		||||
    cfg.StrOpt("redis_ssl_certfile",
 | 
			
		||||
               default='',
 | 
			
		||||
               help=_("Path to the SSL cert")),
 | 
			
		||||
    cfg.StrOpt("redis_ssl_keyfile",
 | 
			
		||||
               default='',
 | 
			
		||||
               help=_("Path to the SSL keyfile")),
 | 
			
		||||
    cfg.StrOpt("redis_ssl_ca_certs",
 | 
			
		||||
               default='',
 | 
			
		||||
               help=_("Path to the SSL CA certs"))]
 | 
			
		||||
 | 
			
		||||
CONF.register_opts(quark_opts, "QUARK")
 | 
			
		||||
 | 
			
		||||
@@ -60,7 +72,17 @@ class Client(object):
 | 
			
		||||
        try:
 | 
			
		||||
            if CONF.QUARK.redis_use_sentinels:
 | 
			
		||||
                host, port = self._discover_master_sentinel()
 | 
			
		||||
            self._client = redis.Redis(host=host, port=port)
 | 
			
		||||
 | 
			
		||||
            kwargs = {"host": host, "port": port}
 | 
			
		||||
            if CONF.QUARK.redis_use_ssl:
 | 
			
		||||
                kwargs["ssl"] = True
 | 
			
		||||
                if CONF.QUARK.redis_ssl_certfile:
 | 
			
		||||
                    kwargs["ssl_certfile"] = CONF.QUARK.redis_ssl_certfile
 | 
			
		||||
                    kwargs["ssl_cert_reqs"] = "required"
 | 
			
		||||
                    kwargs["ssl_ca_certs"] = CONF.QUARK.redis_ssl_ca_certs
 | 
			
		||||
                    kwargs["ssl_keyfile"] = CONF.QUARK.redis_ssl_keyfile
 | 
			
		||||
 | 
			
		||||
            self._client = redis.StrictRedis(**kwargs)
 | 
			
		||||
        except redis.ConnectionError as e:
 | 
			
		||||
            LOG.exception(e)
 | 
			
		||||
            raise q_exc.SecurityGroupsCouldNotBeApplied()
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ class TestRedisSerialization(test_base.TestBase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(TestRedisSerialization, self).setUp()
 | 
			
		||||
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.Redis")
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.StrictRedis")
 | 
			
		||||
    def test_redis_key(self, redis):
 | 
			
		||||
        client = redis_client.Client()
 | 
			
		||||
        device_id = str(uuid.uuid4())
 | 
			
		||||
@@ -44,7 +44,7 @@ class TestRedisSerialization(test_base.TestBase):
 | 
			
		||||
        self.assertEqual(expected, redis_key)
 | 
			
		||||
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.Client.rule_key")
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.Redis")
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.StrictRedis")
 | 
			
		||||
    def test_apply_rules(self, rule_key, redis):
 | 
			
		||||
        client = redis_client.Client()
 | 
			
		||||
        port_id = 1
 | 
			
		||||
@@ -54,7 +54,7 @@ class TestRedisSerialization(test_base.TestBase):
 | 
			
		||||
 | 
			
		||||
    def test_client_connection_fails_gracefully(self):
 | 
			
		||||
        conn_err = redis.ConnectionError
 | 
			
		||||
        with mock.patch("redis.Redis") as redis_mock:
 | 
			
		||||
        with mock.patch("redis.StrictRedis") as redis_mock:
 | 
			
		||||
            redis_mock.side_effect = conn_err
 | 
			
		||||
            with self.assertRaises(q_exc.SecurityGroupsCouldNotBeApplied):
 | 
			
		||||
                redis_client.Client()
 | 
			
		||||
@@ -63,12 +63,12 @@ class TestRedisSerialization(test_base.TestBase):
 | 
			
		||||
        port_id = 1
 | 
			
		||||
        mac_address = netaddr.EUI("AA:BB:CC:DD:EE:FF")
 | 
			
		||||
        conn_err = redis.ConnectionError
 | 
			
		||||
        with mock.patch("redis.Redis") as redis_mock:
 | 
			
		||||
        with mock.patch("redis.StrictRedis") as redis_mock:
 | 
			
		||||
            client = redis_client.Client()
 | 
			
		||||
            redis_mock.set.side_effect = conn_err
 | 
			
		||||
            client.apply_rules(port_id, mac_address.value, [])
 | 
			
		||||
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.Redis")
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.StrictRedis")
 | 
			
		||||
    def test_serialize_group_no_rules(self, redis):
 | 
			
		||||
        client = redis_client.Client()
 | 
			
		||||
        group = models.SecurityGroup()
 | 
			
		||||
@@ -76,7 +76,7 @@ class TestRedisSerialization(test_base.TestBase):
 | 
			
		||||
        self.assertTrue(payload.get("id") is not None)
 | 
			
		||||
        self.assertEqual([], payload.get("rules"))
 | 
			
		||||
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.Redis")
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.StrictRedis")
 | 
			
		||||
    def test_serialize_group_with_rules(self, redis):
 | 
			
		||||
        rule_dict = {"ethertype": 0x800, "protocol": 6, "port_range_min": 80,
 | 
			
		||||
                     "port_range_max": 443, "direction": "ingress"}
 | 
			
		||||
@@ -98,7 +98,7 @@ class TestRedisSerialization(test_base.TestBase):
 | 
			
		||||
        self.assertEqual("", rule["source network"])
 | 
			
		||||
        self.assertEqual("", rule["destination network"])
 | 
			
		||||
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.Redis")
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.StrictRedis")
 | 
			
		||||
    def test_serialize_group_with_rules_and_remote_network(self, redis):
 | 
			
		||||
        rule_dict = {"ethertype": 0x800, "protocol": 1, "direction": "ingress",
 | 
			
		||||
                     "remote_ip_prefix": "192.168.0.0/24"}
 | 
			
		||||
@@ -120,7 +120,7 @@ class TestRedisSerialization(test_base.TestBase):
 | 
			
		||||
        self.assertEqual("::ffff:192.168.0.0/120", rule["source network"])
 | 
			
		||||
        self.assertEqual("", rule["destination network"])
 | 
			
		||||
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.Redis")
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.StrictRedis")
 | 
			
		||||
    def test_serialize_group_egress_rules(self, redis):
 | 
			
		||||
        rule_dict = {"ethertype": 0x800, "protocol": 1,
 | 
			
		||||
                     "direction": "egress",
 | 
			
		||||
@@ -159,7 +159,7 @@ class TestRedisSentinelConnection(test_base.TestBase):
 | 
			
		||||
        CONF.set_override("redis_sentinel_master", '', "QUARK")
 | 
			
		||||
 | 
			
		||||
    @mock.patch("redis.sentinel.Sentinel.discover_master")
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.Redis")
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.StrictRedis")
 | 
			
		||||
    def test_sentinel_connection(self, redis, discover_master):
 | 
			
		||||
        host = "127.0.0.1"
 | 
			
		||||
        port = 6379
 | 
			
		||||
@@ -173,7 +173,7 @@ class TestRedisSentinelConnection(test_base.TestBase):
 | 
			
		||||
            redis.assert_called_with(host=host, port=port)
 | 
			
		||||
 | 
			
		||||
    @mock.patch("redis.sentinel.Sentinel.discover_master")
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.Redis")
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.StrictRedis")
 | 
			
		||||
    def test_sentinel_connection_bad_format_raises(self, redis,
 | 
			
		||||
                                                   discover_master):
 | 
			
		||||
        sentinels = ""
 | 
			
		||||
@@ -182,3 +182,37 @@ class TestRedisSentinelConnection(test_base.TestBase):
 | 
			
		||||
        with self._stubs(True, sentinels, master_label):
 | 
			
		||||
            with self.assertRaises(TypeError):
 | 
			
		||||
                redis_client.Client()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestRedisSSHConnection(test_base.TestBase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(TestRedisSSHConnection, self).setUp()
 | 
			
		||||
 | 
			
		||||
    @contextlib.contextmanager
 | 
			
		||||
    def _stubs(self, use_sentinels, sentinels, master_label):
 | 
			
		||||
        CONF.set_override("redis_use_ssl", True, "QUARK")
 | 
			
		||||
        CONF.set_override("redis_ssl_certfile", 'my.cert', "QUARK")
 | 
			
		||||
        CONF.set_override("redis_ssl_ca_certs", 'server.cert', "QUARK")
 | 
			
		||||
        CONF.set_override("redis_ssl_keyfile", 'keyfile', "QUARK")
 | 
			
		||||
        yield
 | 
			
		||||
        CONF.set_override("redis_ssl_keyfile", '', "QUARK")
 | 
			
		||||
        CONF.set_override("redis_ssl_ca_certs", '', "QUARK")
 | 
			
		||||
        CONF.set_override("redis_ssl_certfile", '', "QUARK")
 | 
			
		||||
        CONF.set_override("redis_use_ssl", False, "QUARK")
 | 
			
		||||
 | 
			
		||||
    @mock.patch("redis.sentinel.Sentinel.discover_master")
 | 
			
		||||
    @mock.patch("quark.security_groups.redis_client.redis.StrictRedis")
 | 
			
		||||
    def test_sentinel_connection(self, redis, discover_master):
 | 
			
		||||
        host = "127.0.0.1"
 | 
			
		||||
        port = 6379
 | 
			
		||||
        sentinels = ["%s:%s" % (host, port)]
 | 
			
		||||
        master_label = "master"
 | 
			
		||||
        discover_master.return_value = (host, port)
 | 
			
		||||
 | 
			
		||||
        with self._stubs(True, sentinels, master_label):
 | 
			
		||||
            redis_client.Client()
 | 
			
		||||
            redis.assert_called_with(host=host, port=port, ssl=True,
 | 
			
		||||
                                     ssl_certfile="my.cert",
 | 
			
		||||
                                     ssl_keyfile="keyfile",
 | 
			
		||||
                                     ssl_ca_certs="server.cert",
 | 
			
		||||
                                     ssl_cert_reqs="required")
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user