Skip to content

Commit

Permalink
feat: use sever groups
Browse files Browse the repository at this point in the history
  • Loading branch information
okozachenko1203 committed Aug 20, 2024
1 parent d32869b commit 9aaddac
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 0 deletions.
87 changes: 87 additions & 0 deletions magnum_cluster_api/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,45 @@ def delete(self):
)


class ClusterServerGroups:
def __init__(
self, context: context.RequestContext, cluster: magnum_objects.Cluster
) -> None:
self.cluster = cluster
self.osc = clients.get_openstack_api(self.context)

@property
def apply(self):
# Create a server group for controlplane
utils.ensure_server_group(
name=self.cluster.stack_id,
ctx=self.context,
policies=utils.get_controlplane_server_group_policies(self.cluster),
)

# Create a server group per a nodegroup
for ng in self.cluster.nodegroups:
if ng.role == "master":
continue
utils.ensure_server_group(
name=f"{self.cluster.stack_id}-{ng.name}",
ctx=self.context,
policies=utils.get_node_group_server_group_policies(ng),
)

@property
def delete(self):
# delete controlplane server group
utils.delete_server_group(name=self.cluster.stack_id)

# Create worker server groups
for ng in self.cluster.nodegroups:
if ng.role == "master":
continue

utils.delete_server_group(name=f"{self.cluster.stack_id}-{ng.name}")


class Base:
def __init__(self, api: pykube.HTTPClient):
self.api = api
Expand Down Expand Up @@ -1313,6 +1352,15 @@ def get_object(self) -> objects.ClusterClass:
},
},
},
{
"name": "serverGroupId",
"required": True,
"schema": {
"openAPIV3Schema": {
"type": "string",
},
},
},
],
"patches": [
{
Expand Down Expand Up @@ -1701,6 +1749,13 @@ def get_object(self) -> objects.ClusterClass:
"variable": "controlPlaneFlavor",
},
},
{
"op": "add",
"path": "/spec/template/spec/serverGroup/id",
"valueFrom": {
"variable": "serverGroupId",
},
},
],
},
{
Expand All @@ -1721,6 +1776,13 @@ def get_object(self) -> objects.ClusterClass:
"variable": "flavor",
},
},
{
"op": "add",
"path": "/spec/template/spec/serverGroup",
"valueFrom": {
"variable": "{{ .builtin.cluster.name }}-{{ .nodeGroupName }}",
},
},
],
},
{
Expand Down Expand Up @@ -2344,6 +2406,8 @@ def mutate_machine_deployment(
if machine_deployment.get("name") == node_group.name:
return machine_deployment

osc = clients.get_openstack_api(context)
server_group = osc.nova()
# At this point, this is all code that will be added for brand new machine
# deployments. We can bring any of this code into the above block if we
# want to change it for existing machine deployments.
Expand Down Expand Up @@ -2384,6 +2448,17 @@ def mutate_machine_deployment(
"name": "imageUUID",
"value": utils.get_image_uuid(node_group.image_id, context),
},
# NOTE(oleks): Override this using MachineDeployment-level variable for node groups
{
"name": "serverGroupId",
"value": utils.ensure_server_group(
name=f"{cluster.name}-{node_group.name}",
ctx=context,
policies=utils.get_node_group_server_group_policies(
node_group
),
),
},
],
},
}
Expand Down Expand Up @@ -2758,6 +2833,18 @@ def get_object(self) -> objects.Cluster:
"control_plane_availability_zones", ""
).split(","),
},
# NOTE(oleks): Set cluster-level variable serverGroupId using server group id for controlplane. # noqa: E501
# Override this using MachineDeployment-level variable for node groups
{
"name": "serverGroupId",
"value": utils.ensure_server_group(
name=self.cluster.stack_id,
ctx=self.context,
policies=utils.get_controlplane_server_group_policies(
self.cluster
),
),
},
],
},
},
Expand Down
83 changes: 83 additions & 0 deletions magnum_cluster_api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from magnum.api import attr_validator
from magnum.common import context, exception, neutron, octavia
from magnum.common import utils as magnum_utils
from novaclient import exceptions as nova_exception
from oslo_config import cfg
from oslo_serialization import base64
from oslo_utils import strutils, uuidutils
Expand All @@ -36,8 +37,11 @@
from magnum_cluster_api import image_utils, images, objects

AVAILABLE_OPERATING_SYSTEMS = ["ubuntu", "flatcar", "rockylinux"]
DEFAULT_SERVER_GROUP_POLICIES = ["soft-anti-affinity"]
CONF = cfg.CONF

SERVER_GROUP_NAME_ID_MAP = {}


def get_cluster_api_cloud_config_secret_name(cluster: magnum_objects.Cluster) -> str:
return f"{cluster.stack_id}-cloud-config"
Expand Down Expand Up @@ -491,3 +495,82 @@ def generate_api_cert_san_list(cluster: magnum_objects.Cluster):

# Add the additional cert SANs to the template
return "\n".join(f"- {san}" for san in additional_cert_sans_list if san)


def get_server_group_id(name: string):
server_group_id = SERVER_GROUP_NAME_ID_MAP.get(name)
if server_group_id:
return server_group_id

# Check if the server group exists already
osc = clients.get_openstack_api(self.context)
server_groups = osc.nova().server_groups.list(all_projects=True)
server_group_id_list = []
for sg in server_groups:
if sg.name == name:
server_group_id_list.append(sg.id)

if len(server_group_id_list) == 1:
SERVER_GROUP_NAME_ID_MAP[name] = server_group_id_list[0]
return server_group_id_list[0]

if len(server_group_id_list) > 1:
raise exception.Conflict(f"too many server groups with name {name} were found")

return None


def get_node_group_server_group_policies(
node_group: magnum_objects.NodeGroup,
):

policies = node_group.labels.get("server_group_policies", "").split(",")
if not policies:
policies = DEFAULT_SERVER_GROUP_POLICIES
return policies


def get_controlplane_server_group_policies(
cluster: magnum_objects.Cluster,
):

policies = cluster.labels.get("server_group_policies", "").split(",")
if not policies:
policies = DEFAULT_SERVER_GROUP_POLICIES
return policies


def ensure_server_group(
name: string,
ctx: context.RequestContext,
policies: list(string) = None,
):
# Retrieve existing server group id
# name = f"{cluster_name}-{node_group.name}"
server_group_id = get_server_group_id(name)
if server_group_id:
return server_group_id

# Create a new server group
osc = clients.get_openstack_api(ctx)
# policies = node_group.labels.get("server_group_policies", "").split(",")
if not policies:
policies = DEFAULT_SERVER_GROUP_POLICIES
server_group = osc.nova().server_groups.create(name=name, policies=policies)
SERVER_GROUP_NAME_ID_MAP[name] = server_group.id
return server_group.id


def delete_server_group(
name: string,
ctx: context.RequestContext,
):
server_group_id = get_server_group_id(name)
if server_group_id is None:
return

osc = clients.get_openstack_api(ctx)
try:
osc.nova().server_groups.delete(server_group_id)
except nova_exception.NotFound:
return

0 comments on commit 9aaddac

Please sign in to comment.