Skip to content

Commit

Permalink
Add bandwidth limit policy check
Browse files Browse the repository at this point in the history
Signed-off-by: Gondermann <[email protected]>
  • Loading branch information
gndrmnn committed Sep 12, 2024
1 parent 850f734 commit 7e2a9e9
Show file tree
Hide file tree
Showing 2 changed files with 260 additions and 0 deletions.
107 changes: 107 additions & 0 deletions openstack_project_manager/manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ def check_quota(
project.id, **{key: quota_should_be}
)

check_bandwidth_limit(configuration, project, quotaclass)

logger.info(f"{project.name} - check compute quota")
quotacompute = configuration.os_cloud.get_compute_quotas(project.id)
for key in quotaclass["compute"]:
Expand Down Expand Up @@ -270,6 +272,111 @@ def check_quota(
)


def update_bandwidth_policy_rule(
configuration: Configuration,
project: openstack.identity.v3.project.Project,
policy: openstack.network.v2.qos_policy.QoSPolicy,
direction: str,
max_kbps: int,
max_burst_kbps: int,
):
existingRules = configuration.os_cloud.list_qos_bandwidth_limit_rules(
policy.id, {"direction": direction}
)
existingRule = existingRules[0] if len(existingRules) > 0 else None

if max_kbps == -1 and max_burst_kbps == -1:
if existingRule:
logger.info(f"{project.name} - removing {direction} bandwidth limit rule")
configuration.os_cloud.delete_qos_bandwidth_limit_rule(
policy.id, existingRule.id
)
return

if not existingRule:
logger.info(f"{project.name} - creating new {direction} bandwidth limit rule")
configuration.os_cloud.create_qos_bandwidth_limit_rule(
policy.id,
max_kbps=max_kbps,
max_burst_kbps=max_burst_kbps,
direction=direction,
)
elif (
existingRule.max_kbps != max_kbps
or existingRule.max_burst_kbps != max_burst_kbps
):
logger.info(f"{project.name} - updating {direction} bandwidth limit rule")
configuration.os_cloud.update_qos_bandwidth_limit_rule(
policy.id,
existingRule.id,
max_kbps=max_kbps,
max_burst_kbps=max_burst_kbps,
)


def check_bandwidth_limit(
configuration: Configuration,
project: openstack.identity.v3.project.Project,
quotaclass: dict,
) -> None:

domain = configuration.os_cloud.get_domain(name_or_id=project.domain_id)
domain_name = domain.name.lower()

if domain_name == "default" and project.name in ["admin", "service"]:
logger.info(f"{project.name} - skip network bandwith limit policy check")
return

logger.info(f"{project.name} - check network bandwith limit policy")

limit_egress = -1
limit_egress_burst = -1
limit_ingress = -1
limit_ingress_burst = -1

if "bandwidth" in quotaclass:
if "egress" in quotaclass["bandwidth"]:
limit_egress = int(quotaclass["bandwidth"]["egress"])
if "egress_burst" in quotaclass["bandwidth"]:
limit_egress_burst = int(quotaclass["bandwidth"]["egress_burst"])
if "ingress" in quotaclass["bandwidth"]:
limit_ingress = int(quotaclass["bandwidth"]["ingress"])
if "ingress_burst" in quotaclass["bandwidth"]:
limit_ingress_burst = int(quotaclass["bandwidth"]["ingress_burst"])

existingPolicies = configuration.os_cloud.list_qos_policies(
{"name": "bw-limiter", "project_id": project.id}
)

if (
limit_egress == -1
and limit_egress_burst == -1
and limit_ingress == -1
and limit_ingress_burst == -1
):
# There are no limits defined (anymore) so we remove or skip the policy entirely
if len(existingPolicies) > 0:
logger.info(f"{project.name} - removing bandwidth limit policy")
for policy in existingPolicies:
configuration.os_cloud.delete_qos_policy(policy.id)
return

if len(existingPolicies) == 0:
logger.info(f"{project.name} - creating new bandwidth limit policy")
policy = configuration.os_cloud.create_qos_policy(
name="bw-limiter", default=True, project_id=project.id
)
else:
policy = existingPolicies[0]

update_bandwidth_policy_rule(
configuration, project, policy, "egress", limit_egress, limit_egress_burst
)
update_bandwidth_policy_rule(
configuration, project, policy, "ingress", limit_ingress, limit_ingress_burst
)


def manage_external_network_rbacs(
configuration: Configuration,
project: openstack.identity.v3.project.Project,
Expand Down
153 changes: 153 additions & 0 deletions test/unit/test_manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
get_quotaclass,
check_bool,
check_quota,
update_bandwidth_policy_rule,
manage_external_network_rbacs,
check_volume_types,
check_bandwidth_limit,
manage_private_volumetypes,
create_network_resources,
add_service_network,
Expand Down Expand Up @@ -289,6 +291,157 @@ def test_check_quota_2(self):
self.mock_os_cloud.set_volume_quotas.assert_any_call(ANY, gigabytes=3)


class TestCheckBandwidth(TestBase):
def setUp(self):
super().setUp()

self.mock_project = MagicMock()
self.mock_project.name = "test"
self.mock_project.id = 9012
self.mock_domain = MagicMock()
self.mock_domain.name = "test"
self.config.os_cloud.get_domain.return_value = self.mock_domain

def test_update_bandwidth_policy_rule_0(self):
mock_policy = MagicMock()
mock_policy.id = 5678
self.config.os_cloud.list_qos_bandwidth_limit_rules.return_value = []

update_bandwidth_policy_rule(
self.config, self.mock_project, mock_policy, "egress", -1, -1
)

self.config.os_cloud.delete_qos_bandwidth_limit_rule.assert_not_called()
self.config.os_cloud.create_qos_bandwidth_limit_rule.assert_not_called()
self.config.os_cloud.update_qos_bandwidth_limit_rule.assert_not_called()

def test_update_bandwidth_policy_rule_1(self):
mock_policy = MagicMock()
mock_policy.id = 5678
mock_rule = MagicMock()
mock_rule.id = 1234
self.config.os_cloud.list_qos_bandwidth_limit_rules.return_value = [mock_rule]

update_bandwidth_policy_rule(
self.config, self.mock_project, mock_policy, "egress", -1, -1
)

self.config.os_cloud.delete_qos_bandwidth_limit_rule.assert_called_once_with(
5678, 1234
)
self.config.os_cloud.create_qos_bandwidth_limit_rule.assert_not_called()
self.config.os_cloud.update_qos_bandwidth_limit_rule.assert_not_called()

def test_update_bandwidth_policy_rule_2(self):
mock_policy = MagicMock()
mock_policy.id = 5678
self.config.os_cloud.list_qos_bandwidth_limit_rules.return_value = []

update_bandwidth_policy_rule(
self.config, self.mock_project, mock_policy, "egress", 100, 200
)

self.config.os_cloud.delete_qos_bandwidth_limit_rule.assert_not_called()
self.config.os_cloud.create_qos_bandwidth_limit_rule.assert_called_once_with(
5678, max_kbps=100, max_burst_kbps=200, direction="egress"
)
self.config.os_cloud.update_qos_bandwidth_limit_rule.assert_not_called()

def test_update_bandwidth_policy_rule_3(self):
mock_policy = MagicMock()
mock_policy.id = 5678
mock_rule = MagicMock()
mock_rule.id = 1234
self.config.os_cloud.list_qos_bandwidth_limit_rules.return_value = [mock_rule]

update_bandwidth_policy_rule(
self.config, self.mock_project, mock_policy, "egress", 300, 400
)

self.config.os_cloud.delete_qos_bandwidth_limit_rule.assert_not_called()
self.config.os_cloud.create_qos_bandwidth_limit_rule.assert_not_called()
self.config.os_cloud.update_qos_bandwidth_limit_rule.assert_called_once_with(
5678, 1234, max_kbps=300, max_burst_kbps=400
)

@patch("openstack_project_manager.manage.update_bandwidth_policy_rule")
def test_check_bandwidth_limit_0(self, mock_update_bandwidth_policy_rule):
mock_admin_project = MagicMock()
mock_admin_project.name = "admin"
mock_default_domain = MagicMock()
mock_default_domain.name = "Default"
self.config.os_cloud.get_domain.return_value = mock_default_domain

check_bandwidth_limit(self.config, mock_admin_project, {})

self.config.os_cloud.list_qos_policies.assert_not_called()
self.config.os_cloud.delete_qos_policy.assert_not_called()
self.config.os_cloud.create_qos_policy.assert_not_called()
mock_update_bandwidth_policy_rule.assert_not_called()

@patch("openstack_project_manager.manage.update_bandwidth_policy_rule")
def test_check_bandwidth_limit_1(self, mock_update_bandwidth_policy_rule):
mock_policy = MagicMock()
mock_policy.id = 5678
self.config.os_cloud.list_qos_policies.return_value = [mock_policy]
mock_quota_class = {}

check_bandwidth_limit(self.config, self.mock_project, mock_quota_class)

self.config.os_cloud.delete_qos_policy.assert_called_once_with(5678)
self.config.os_cloud.create_qos_policy.assert_not_called()
mock_update_bandwidth_policy_rule.assert_not_called()

@patch("openstack_project_manager.manage.update_bandwidth_policy_rule")
def test_check_bandwidth_limit_2(self, mock_update_bandwidth_policy_rule):
self.config.os_cloud.list_qos_policies.return_value = []
mock_quota_class = {}

check_bandwidth_limit(self.config, self.mock_project, mock_quota_class)

self.config.os_cloud.delete_qos_policy.assert_not_called()
self.config.os_cloud.create_qos_policy.assert_not_called()
mock_update_bandwidth_policy_rule.assert_not_called()

@patch("openstack_project_manager.manage.update_bandwidth_policy_rule")
def test_check_bandwidth_limit_3(self, mock_update_bandwidth_policy_rule):
self.config.os_cloud.list_qos_policies.return_value = []
mock_quota_class = {"bandwidth": {"egress": 1000}}

check_bandwidth_limit(self.config, self.mock_project, mock_quota_class)

self.config.os_cloud.delete_qos_policy.assert_not_called()
self.config.os_cloud.create_qos_policy.assert_called_once_with(
name="bw-limiter", default=True, project_id=9012
)
mock_update_bandwidth_policy_rule.assert_any_call(
self.config, self.mock_project, ANY, "egress", 1000, -1
)
mock_update_bandwidth_policy_rule.assert_any_call(
self.config, self.mock_project, ANY, "ingress", -1, -1
)

@patch("openstack_project_manager.manage.update_bandwidth_policy_rule")
def test_check_bandwidth_limit_4(self, mock_update_bandwidth_policy_rule):
mock_policy = MagicMock()
mock_policy.id = 5678
self.config.os_cloud.list_qos_policies.return_value = [mock_policy]
mock_quota_class = {
"bandwidth": {"egress_burst": 1000, "ingress": 2000, "ingress_burst": 3000}
}

check_bandwidth_limit(self.config, self.mock_project, mock_quota_class)

self.config.os_cloud.delete_qos_policy.assert_not_called()
self.config.os_cloud.create_qos_policy.assert_not_called()
mock_update_bandwidth_policy_rule.assert_any_call(
self.config, self.mock_project, mock_policy, "egress", -1, 1000
)
mock_update_bandwidth_policy_rule.assert_any_call(
self.config, self.mock_project, mock_policy, "ingress", 2000, 3000
)


class TestManageExternalNetworkRbacs(TestBase):

def setUp(self):
Expand Down

0 comments on commit 7e2a9e9

Please sign in to comment.