Coverage for ocp_resources/machine_set.py: 0%
46 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-30 10:48 +0200
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-30 10:48 +0200
1from ocp_resources.utils.constants import TIMEOUT_4MINUTES
2from ocp_resources.resource import NamespacedResource
3from timeout_sampler import TimeoutExpiredError, TimeoutSampler
5TIMEOUT_5MINUTES = 300
8class MachineSet(NamespacedResource):
9 """
10 Machineset object.
12 Args:
13 cluster_name (str): OpenShift cluster name.
14 machine_role (str): machine role. e.g.: 'worker'.
15 machine_type (str): machine role. e.g.: 'worker'.
16 replicas (int): amount of replicas the machine-set will have.
17 provider_spec (dict): provider spec information.
19 provider spec example:
21 {
22 "value": {
23 "apiVersion": "ovirtproviderconfig.machine.openshift.io/v1beta1",
24 "auto_pinning_policy": "none",
25 "cluster_id": "5612af70-f4f5-455d-b7df-fbad66accc38",
26 "cpu": {
27 "cores": 8,
28 "sockets": 1,
29 "threads": 1
30 },
31 "credentialsSecret": {
32 "name": "ovirt-credentials"
33 },
34 "kind": "OvirtMachineProviderSpec",
35 "memory_mb": 16000,
36 "os_disk": {
37 "size_gb": 31
38 },
39 "template_name": "ge2n1-gcwmg-rhcos",
40 "type": "server",
41 "userDataSecret": {
42 "name": "worker-user-data"
43 }
44 }
45 }
46 """
48 api_group = NamespacedResource.ApiGroup.MACHINE_OPENSHIFT_IO
50 def __init__(
51 self,
52 cluster_name=None,
53 name=None,
54 namespace=None,
55 teardown=True,
56 client=None,
57 machine_role="worker",
58 machine_type="worker",
59 replicas=1,
60 provider_spec=None,
61 yaml_file=None,
62 delete_timeout=TIMEOUT_4MINUTES,
63 **kwargs,
64 ):
65 super().__init__(
66 name=name,
67 namespace=namespace,
68 client=client,
69 teardown=teardown,
70 yaml_file=yaml_file,
71 delete_timeout=delete_timeout,
72 **kwargs,
73 )
74 self.replicas = replicas
75 self.cluster_name = cluster_name
76 self.machine_role = machine_role
77 self.machine_type = machine_type
78 self.provider_spec = provider_spec or {}
80 def to_dict(self) -> None:
81 super().to_dict()
82 if not self.kind_dict and not self.yaml_file:
83 _spec, _metadata, _labels = ("spec", "metadata", "labels")
84 (
85 _cluster_api_cluster,
86 _cluster_api_machine_role,
87 _cluster_api_machine_type,
88 _cluster_api_machineset,
89 ) = (
90 "cluster-api-cluster",
91 "cluster-api-machine-role",
92 "cluster-api-machine-type",
93 "cluster-api-machineset",
94 )
96 self.res[_metadata][_labels] = {
97 f"{self.api_group}/{_cluster_api_cluster}": self.cluster_name,
98 f"{self.api_group}/{_cluster_api_machine_role}": self.machine_role,
99 f"{self.api_group}/{_cluster_api_machine_type}": self.machine_type,
100 }
102 self.res[_spec] = {
103 "replicas": self.replicas,
104 "selector": {
105 "matchLabels": {
106 f"{self.api_group}/{_cluster_api_cluster}": self.cluster_name,
107 f"{self.api_group}/{_cluster_api_machineset}": (f"{self.cluster_name}-{self.machine_role}"),
108 }
109 },
110 "template": {
111 _metadata: {
112 _labels: {
113 f"{self.api_group}/{_cluster_api_cluster}": (self.cluster_name),
114 f"{self.api_group}/{_cluster_api_machine_role}": (self.machine_role),
115 f"{self.api_group}/{_cluster_api_machine_type}": (self.machine_type),
116 f"{self.api_group}/{_cluster_api_machineset}": (f"{self.cluster_name}-{self.machine_role}"),
117 }
118 },
119 _spec: {"providerSpec": self.provider_spec},
120 },
121 }
123 @property
124 def available_replicas(self):
125 return self.instance.status.availableReplicas
127 @property
128 def ready_replicas(self):
129 return self.instance.status.readyReplicas
131 @property
132 def desired_replicas(self):
133 return self.instance.status.replicas
135 @property
136 def provider_spec_value(self):
137 return self.instance.spec.template.spec.providerSpec.value
139 def wait_for_replicas(self, timeout=TIMEOUT_5MINUTES, sleep=1):
140 """
141 Wait for machine-set replicas to reach 'ready' state.
143 Args:
144 timeout (int): maximum time to wait_for_replicas for the 'ready' state.
145 sleep (int): sleep time between each sample.
147 Returns:
148 bool: True if machine-set reached 'ready' state, False otherwise.
149 """
150 try:
151 return any(
152 ready_replicas and ready_replicas == self.desired_replicas
153 for ready_replicas in TimeoutSampler(
154 wait_timeout=timeout, sleep=sleep, func=lambda: self.ready_replicas
155 )
156 )
157 except TimeoutExpiredError:
158 self.logger.error(
159 f"Machine-set {self.name} replicas failed to reach into 'ready' state,"
160 f" actual ready replicas: {self.ready_replicas}, desired replicas:"
161 f" {self.desired_replicas}"
162 )
163 return False
165 def scale_replicas(self, replicas, wait_timeout=TIMEOUT_5MINUTES, sleep=1, wait=True):
166 """
167 Scale down/up a machine-set replicas.
169 Args:
170 replicas (int): num of replicas to scale_replicas to.
171 wait_timeout (int): maximum time to wait_for_replicas for scaling the machine-set.
172 sleep (int): sleep time between each sample of the machine-set state.
173 wait (bool): True if waiting for machine-set to reach into 'ready' state, False otherwise.
175 Returns:
176 bool: True if scaling the machine-set was successful or wait=False, False otherwise.
177 """
178 super().to_dict()
179 self.res.update({"spec": {"replicas": replicas}})
181 self.logger.info(f"Scale machine-set from {self.desired_replicas} replicas to {replicas} replicas")
182 self.update(resource_dict=self.res)
183 if wait:
184 return self.wait_for_replicas(timeout=wait_timeout, sleep=sleep)
185 return True