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

1from ocp_resources.utils.constants import TIMEOUT_4MINUTES 

2from ocp_resources.resource import NamespacedResource 

3from timeout_sampler import TimeoutExpiredError, TimeoutSampler 

4 

5TIMEOUT_5MINUTES = 300 

6 

7 

8class MachineSet(NamespacedResource): 

9 """ 

10 Machineset object. 

11 

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. 

18 

19 provider spec example: 

20 

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 """ 

47 

48 api_group = NamespacedResource.ApiGroup.MACHINE_OPENSHIFT_IO 

49 

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 {} 

79 

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 ) 

95 

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 } 

101 

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 } 

122 

123 @property 

124 def available_replicas(self): 

125 return self.instance.status.availableReplicas 

126 

127 @property 

128 def ready_replicas(self): 

129 return self.instance.status.readyReplicas 

130 

131 @property 

132 def desired_replicas(self): 

133 return self.instance.status.replicas 

134 

135 @property 

136 def provider_spec_value(self): 

137 return self.instance.spec.template.spec.providerSpec.value 

138 

139 def wait_for_replicas(self, timeout=TIMEOUT_5MINUTES, sleep=1): 

140 """ 

141 Wait for machine-set replicas to reach 'ready' state. 

142 

143 Args: 

144 timeout (int): maximum time to wait_for_replicas for the 'ready' state. 

145 sleep (int): sleep time between each sample. 

146 

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 

164 

165 def scale_replicas(self, replicas, wait_timeout=TIMEOUT_5MINUTES, sleep=1, wait=True): 

166 """ 

167 Scale down/up a machine-set replicas. 

168 

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. 

174 

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}}) 

180 

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