openshift-python-wrapper 4.11.61__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ocp_resources/__init__.py +0 -0
- ocp_resources/api_service.py +9 -0
- ocp_resources/backup.py +52 -0
- ocp_resources/benchmark.py +92 -0
- ocp_resources/catalog_source.py +63 -0
- ocp_resources/catalog_source_config.py +86 -0
- ocp_resources/cdi.py +13 -0
- ocp_resources/cdi_config.py +52 -0
- ocp_resources/chaos_engine.py +30 -0
- ocp_resources/chaos_result.py +11 -0
- ocp_resources/cluster_operator.py +5 -0
- ocp_resources/cluster_role.py +70 -0
- ocp_resources/cluster_role_binding.py +36 -0
- ocp_resources/cluster_service_version.py +8 -0
- ocp_resources/cluster_version.py +5 -0
- ocp_resources/configmap.py +37 -0
- ocp_resources/console_cli_download.py +9 -0
- ocp_resources/console_plugin.py +9 -0
- ocp_resources/console_quick_start.py +9 -0
- ocp_resources/constants.py +26 -0
- ocp_resources/csidriver.py +9 -0
- ocp_resources/custom_resource_definition.py +5 -0
- ocp_resources/daemonset.py +61 -0
- ocp_resources/data_import_cron.py +100 -0
- ocp_resources/data_source.py +59 -0
- ocp_resources/datavolume.py +275 -0
- ocp_resources/deployment.py +65 -0
- ocp_resources/destination_rule.py +11 -0
- ocp_resources/event.py +114 -0
- ocp_resources/forklift_controller.py +10 -0
- ocp_resources/gateway.py +11 -0
- ocp_resources/hook.py +52 -0
- ocp_resources/host.py +64 -0
- ocp_resources/hostpath_provisioner.py +50 -0
- ocp_resources/hyperconverged.py +43 -0
- ocp_resources/image.py +9 -0
- ocp_resources/image_content_source_policy.py +9 -0
- ocp_resources/image_stream.py +48 -0
- ocp_resources/imagestreamtag.py +9 -0
- ocp_resources/infrastructure.py +18 -0
- ocp_resources/installplan.py +8 -0
- ocp_resources/job.py +65 -0
- ocp_resources/kube_descheduler.py +65 -0
- ocp_resources/kubevirt.py +5 -0
- ocp_resources/kubevirt_common_templates_bundle.py +5 -0
- ocp_resources/kubevirt_metrics_aggregation.py +5 -0
- ocp_resources/kubevirt_node_labeller_bundle.py +5 -0
- ocp_resources/kubevirt_template_validaotr.py +5 -0
- ocp_resources/logger.py +76 -0
- ocp_resources/machine.py +50 -0
- ocp_resources/machine_config.py +5 -0
- ocp_resources/machine_config_pool.py +9 -0
- ocp_resources/machine_health_check.py +76 -0
- ocp_resources/machine_set.py +189 -0
- ocp_resources/migration.py +63 -0
- ocp_resources/migration_policy.py +66 -0
- ocp_resources/mtv.py +171 -0
- ocp_resources/mutating_webhook_config.py +9 -0
- ocp_resources/namespace.py +40 -0
- ocp_resources/network.py +5 -0
- ocp_resources/network_addons_config.py +9 -0
- ocp_resources/network_attachment_definition.py +24 -0
- ocp_resources/network_map.py +64 -0
- ocp_resources/network_policy.py +9 -0
- ocp_resources/nmstate.py +9 -0
- ocp_resources/node.py +41 -0
- ocp_resources/node_health_check.py +10 -0
- ocp_resources/node_maintenance.py +40 -0
- ocp_resources/node_network_configuration_enactment.py +20 -0
- ocp_resources/node_network_configuration_policy.py +472 -0
- ocp_resources/node_network_state.py +121 -0
- ocp_resources/oauth.py +9 -0
- ocp_resources/operator_condition.py +5 -0
- ocp_resources/operator_group.py +37 -0
- ocp_resources/operator_hub.py +5 -0
- ocp_resources/operator_source.py +50 -0
- ocp_resources/package_manifest.py +5 -0
- ocp_resources/peer_authentication.py +18 -0
- ocp_resources/persistent_volume.py +27 -0
- ocp_resources/persistent_volume_claim.py +103 -0
- ocp_resources/plan.py +143 -0
- ocp_resources/pod.py +175 -0
- ocp_resources/pod_disruption_budget.py +53 -0
- ocp_resources/priority_class.py +48 -0
- ocp_resources/project.py +60 -0
- ocp_resources/prometheus.py +9 -0
- ocp_resources/prometheus_rule.py +9 -0
- ocp_resources/provider.py +59 -0
- ocp_resources/replicaset.py +11 -0
- ocp_resources/resource.py +1383 -0
- ocp_resources/restore.py +52 -0
- ocp_resources/role.py +11 -0
- ocp_resources/role_binding.py +67 -0
- ocp_resources/route.py +76 -0
- ocp_resources/secret.py +75 -0
- ocp_resources/security_context_constraints.py +9 -0
- ocp_resources/service.py +16 -0
- ocp_resources/service_account.py +9 -0
- ocp_resources/service_mesh_control_plane.py +11 -0
- ocp_resources/service_mesh_member_roll.py +14 -0
- ocp_resources/service_monitor.py +9 -0
- ocp_resources/sriov_network.py +54 -0
- ocp_resources/sriov_network_node_policy.py +67 -0
- ocp_resources/sriov_network_node_state.py +44 -0
- ocp_resources/ssp.py +9 -0
- ocp_resources/storage_class.py +47 -0
- ocp_resources/storage_map.py +67 -0
- ocp_resources/storage_profile.py +7 -0
- ocp_resources/subscription.py +66 -0
- ocp_resources/tekton_tasks.py +9 -0
- ocp_resources/template.py +74 -0
- ocp_resources/upload_token_request.py +39 -0
- ocp_resources/utils.py +278 -0
- ocp_resources/validating_webhook_config.py +9 -0
- ocp_resources/virtual_machine.py +177 -0
- ocp_resources/virtual_machine_Instance_replica_set.py +9 -0
- ocp_resources/virtual_machine_cluster_flavor.py +5 -0
- ocp_resources/virtual_machine_flavor.py +5 -0
- ocp_resources/virtual_machine_import.py +307 -0
- ocp_resources/virtual_machine_instance.py +322 -0
- ocp_resources/virtual_machine_instance_migration.py +36 -0
- ocp_resources/virtual_machine_instance_preset.py +9 -0
- ocp_resources/virtual_machine_restore.py +99 -0
- ocp_resources/virtual_machine_snapshot.py +96 -0
- ocp_resources/virtual_service.py +11 -0
- ocp_resources/vm_import_config.py +9 -0
- ocp_resources/volume_snapshot.py +9 -0
- ocp_resources/volume_snapshot_class.py +9 -0
- openshift_python_wrapper-4.11.61.dist-info/LICENSE +201 -0
- openshift_python_wrapper-4.11.61.dist-info/METADATA +188 -0
- openshift_python_wrapper-4.11.61.dist-info/RECORD +132 -0
- openshift_python_wrapper-4.11.61.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from ocp_resources.constants import TIMEOUT_4MINUTES
|
|
2
|
+
from ocp_resources.resource import NamespacedResource
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class MachineHealthCheck(NamespacedResource):
|
|
6
|
+
"""
|
|
7
|
+
MachineHealthCheck object.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
api_group = NamespacedResource.ApiGroup.MACHINE_OPENSHIFT_IO
|
|
11
|
+
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
name=None,
|
|
15
|
+
namespace=None,
|
|
16
|
+
cluster_name=None,
|
|
17
|
+
machineset_name=None,
|
|
18
|
+
client=None,
|
|
19
|
+
machine_role="worker",
|
|
20
|
+
machine_type="worker",
|
|
21
|
+
node_startup_timeout="120m",
|
|
22
|
+
max_unhealthy=2, # can also be a persentage, for e.g. "40%"
|
|
23
|
+
unhealthy_timeout="300s",
|
|
24
|
+
reboot_strategy=False,
|
|
25
|
+
teardown=True,
|
|
26
|
+
yaml_file=None,
|
|
27
|
+
delete_timeout=TIMEOUT_4MINUTES,
|
|
28
|
+
**kwargs,
|
|
29
|
+
):
|
|
30
|
+
super().__init__(
|
|
31
|
+
name=name,
|
|
32
|
+
namespace=namespace,
|
|
33
|
+
client=client,
|
|
34
|
+
teardown=teardown,
|
|
35
|
+
yaml_file=yaml_file,
|
|
36
|
+
delete_timeout=delete_timeout,
|
|
37
|
+
**kwargs,
|
|
38
|
+
)
|
|
39
|
+
self.cluster_name = cluster_name
|
|
40
|
+
self.machineset_name = machineset_name
|
|
41
|
+
self.machine_role = machine_role
|
|
42
|
+
self.machine_type = machine_type
|
|
43
|
+
self.node_startup_timeout = node_startup_timeout
|
|
44
|
+
self.max_unhealthy = max_unhealthy
|
|
45
|
+
self.unhealthy_timeout = unhealthy_timeout
|
|
46
|
+
self.reboot_strategy = reboot_strategy
|
|
47
|
+
|
|
48
|
+
def to_dict(self):
|
|
49
|
+
super().to_dict()
|
|
50
|
+
if not self.yaml_file:
|
|
51
|
+
if self.reboot_strategy:
|
|
52
|
+
self.res["metadata"]["annotations"] = {
|
|
53
|
+
f"{self.api_group}/remediation-strategy": "external-baremetal"
|
|
54
|
+
}
|
|
55
|
+
self.res.setdefault("spec", {})
|
|
56
|
+
self.res["spec"]["nodeStartupTimeout"] = self.node_startup_timeout
|
|
57
|
+
self.res["spec"]["maxUnhealthy"] = self.max_unhealthy
|
|
58
|
+
self.res["spec"].setdefault("selector", {})
|
|
59
|
+
self.res["spec"]["selector"]["matchLabels"] = {
|
|
60
|
+
f"{self.api_group}/cluster-api-cluster": self.cluster_name,
|
|
61
|
+
f"{self.api_group}/cluster-api-machine-role": self.machine_role,
|
|
62
|
+
f"{self.api_group}/cluster-api-machine-type": self.machine_type,
|
|
63
|
+
f"{self.api_group}/cluster-api-machineset": self.machineset_name,
|
|
64
|
+
}
|
|
65
|
+
self.res["spec"]["unhealthyConditions"] = [
|
|
66
|
+
{
|
|
67
|
+
"type": self.Condition.READY,
|
|
68
|
+
"timeout": self.unhealthy_timeout,
|
|
69
|
+
"status": self.Condition.Status.FALSE,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"type": self.Condition.READY,
|
|
73
|
+
"timeout": self.unhealthy_timeout,
|
|
74
|
+
"status": self.Condition.Status.UNKNOWN,
|
|
75
|
+
},
|
|
76
|
+
]
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
from ocp_resources.constants import TIMEOUT_4MINUTES
|
|
2
|
+
from ocp_resources.resource import NamespacedResource
|
|
3
|
+
from ocp_resources.utils import TimeoutExpiredError, TimeoutSampler
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
TIMEOUT_5MINUTES = 300
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MachineSet(NamespacedResource):
|
|
10
|
+
"""
|
|
11
|
+
Machineset object.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
cluster_name (str): OpenShift cluster name.
|
|
15
|
+
machine_role (str): machine role. e.g.: 'worker'.
|
|
16
|
+
machine_type (str): machine role. e.g.: 'worker'.
|
|
17
|
+
replicas (int): amount of replicas the machine-set will have.
|
|
18
|
+
provider_spec (dict): provider spec information.
|
|
19
|
+
|
|
20
|
+
provider spec example:
|
|
21
|
+
|
|
22
|
+
{
|
|
23
|
+
"value": {
|
|
24
|
+
"apiVersion": "ovirtproviderconfig.machine.openshift.io/v1beta1",
|
|
25
|
+
"auto_pinning_policy": "none",
|
|
26
|
+
"cluster_id": "5612af70-f4f5-455d-b7df-fbad66accc38",
|
|
27
|
+
"cpu": {
|
|
28
|
+
"cores": 8,
|
|
29
|
+
"sockets": 1,
|
|
30
|
+
"threads": 1
|
|
31
|
+
},
|
|
32
|
+
"credentialsSecret": {
|
|
33
|
+
"name": "ovirt-credentials"
|
|
34
|
+
},
|
|
35
|
+
"kind": "OvirtMachineProviderSpec",
|
|
36
|
+
"memory_mb": 16000,
|
|
37
|
+
"os_disk": {
|
|
38
|
+
"size_gb": 31
|
|
39
|
+
},
|
|
40
|
+
"template_name": "ge2n1-gcwmg-rhcos",
|
|
41
|
+
"type": "server",
|
|
42
|
+
"userDataSecret": {
|
|
43
|
+
"name": "worker-user-data"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
api_group = NamespacedResource.ApiGroup.MACHINE_OPENSHIFT_IO
|
|
50
|
+
|
|
51
|
+
def __init__(
|
|
52
|
+
self,
|
|
53
|
+
cluster_name=None,
|
|
54
|
+
name=None,
|
|
55
|
+
namespace=None,
|
|
56
|
+
teardown=True,
|
|
57
|
+
client=None,
|
|
58
|
+
machine_role="worker",
|
|
59
|
+
machine_type="worker",
|
|
60
|
+
replicas=1,
|
|
61
|
+
provider_spec=None,
|
|
62
|
+
yaml_file=None,
|
|
63
|
+
delete_timeout=TIMEOUT_4MINUTES,
|
|
64
|
+
**kwargs,
|
|
65
|
+
):
|
|
66
|
+
super().__init__(
|
|
67
|
+
name=name,
|
|
68
|
+
namespace=namespace,
|
|
69
|
+
client=client,
|
|
70
|
+
teardown=teardown,
|
|
71
|
+
yaml_file=yaml_file,
|
|
72
|
+
delete_timeout=delete_timeout,
|
|
73
|
+
**kwargs,
|
|
74
|
+
)
|
|
75
|
+
self.replicas = replicas
|
|
76
|
+
self.cluster_name = cluster_name
|
|
77
|
+
self.machine_role = machine_role
|
|
78
|
+
self.machine_type = machine_type
|
|
79
|
+
self.provider_spec = provider_spec or {}
|
|
80
|
+
|
|
81
|
+
def to_dict(self):
|
|
82
|
+
super().to_dict()
|
|
83
|
+
if not self.yaml_file:
|
|
84
|
+
_spec, _metadata, _labels = ("spec", "metadata", "labels")
|
|
85
|
+
(
|
|
86
|
+
_cluster_api_cluster,
|
|
87
|
+
_cluster_api_machine_role,
|
|
88
|
+
_cluster_api_machine_type,
|
|
89
|
+
_cluster_api_machineset,
|
|
90
|
+
) = (
|
|
91
|
+
"cluster-api-cluster",
|
|
92
|
+
"cluster-api-machine-role",
|
|
93
|
+
"cluster-api-machine-type",
|
|
94
|
+
"cluster-api-machineset",
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
self.res[_metadata][_labels] = {
|
|
98
|
+
f"{self.api_group}/{_cluster_api_cluster}": self.cluster_name,
|
|
99
|
+
f"{self.api_group}/{_cluster_api_machine_role}": self.machine_role,
|
|
100
|
+
f"{self.api_group}/{_cluster_api_machine_type}": self.machine_type,
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
self.res[_spec] = {
|
|
104
|
+
"replicas": self.replicas,
|
|
105
|
+
"selector": {
|
|
106
|
+
"matchLabels": {
|
|
107
|
+
f"{self.api_group}/{_cluster_api_cluster}": self.cluster_name,
|
|
108
|
+
f"{self.api_group}/{_cluster_api_machineset}": f"{self.cluster_name}-{self.machine_role}",
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"template": {
|
|
112
|
+
_metadata: {
|
|
113
|
+
_labels: {
|
|
114
|
+
f"{self.api_group}/{_cluster_api_cluster}": self.cluster_name,
|
|
115
|
+
f"{self.api_group}/{_cluster_api_machine_role}": self.machine_role,
|
|
116
|
+
f"{self.api_group}/{_cluster_api_machine_type}": self.machine_type,
|
|
117
|
+
f"{self.api_group}/{_cluster_api_machineset}": f"{self.cluster_name}-{self.machine_role}",
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
_spec: {"providerSpec": self.provider_spec},
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def available_replicas(self):
|
|
126
|
+
return self.instance.status.availableReplicas
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def ready_replicas(self):
|
|
130
|
+
return self.instance.status.readyReplicas
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def desired_replicas(self):
|
|
134
|
+
return self.instance.status.replicas
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def provider_spec_value(self):
|
|
138
|
+
return self.instance.spec.template.spec.providerSpec.value
|
|
139
|
+
|
|
140
|
+
def wait_for_replicas(self, timeout=TIMEOUT_5MINUTES, sleep=1):
|
|
141
|
+
"""
|
|
142
|
+
Wait for machine-set replicas to reach 'ready' state.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
timeout (int): maximum time to wait_for_replicas for the 'ready' state.
|
|
146
|
+
sleep (int): sleep time between each sample.
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
bool: True if machine-set reached 'ready' state, False otherwise.
|
|
150
|
+
"""
|
|
151
|
+
try:
|
|
152
|
+
return any(
|
|
153
|
+
ready_replicas and ready_replicas == self.desired_replicas
|
|
154
|
+
for ready_replicas in TimeoutSampler(
|
|
155
|
+
wait_timeout=timeout, sleep=sleep, func=lambda: self.ready_replicas
|
|
156
|
+
)
|
|
157
|
+
)
|
|
158
|
+
except TimeoutExpiredError:
|
|
159
|
+
self.logger.error(
|
|
160
|
+
f"Machine-set {self.name} replicas failed to reach into 'ready' state, actual ready replicas: "
|
|
161
|
+
f"{self.ready_replicas}, desired replicas: {self.desired_replicas}"
|
|
162
|
+
)
|
|
163
|
+
return False
|
|
164
|
+
|
|
165
|
+
def scale_replicas(
|
|
166
|
+
self, replicas, wait_timeout=TIMEOUT_5MINUTES, sleep=1, wait=True
|
|
167
|
+
):
|
|
168
|
+
"""
|
|
169
|
+
Scale down/up a machine-set replicas.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
replicas (int): num of replicas to scale_replicas to.
|
|
173
|
+
wait_timeout (int): maximum time to wait_for_replicas for scaling the machine-set.
|
|
174
|
+
sleep (int): sleep time between each sample of the machine-set state.
|
|
175
|
+
wait (bool): True if waiting for machine-set to reach into 'ready' state, False otherwise.
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
bool: True if scaling the machine-set was successful or wait=False, False otherwise.
|
|
179
|
+
"""
|
|
180
|
+
super().to_dict()
|
|
181
|
+
self.res.update({"spec": {"replicas": replicas}})
|
|
182
|
+
|
|
183
|
+
self.logger.info(
|
|
184
|
+
f"Scale machine-set from {self.desired_replicas} replicas to {replicas} replicas"
|
|
185
|
+
)
|
|
186
|
+
self.update(resource_dict=self.res)
|
|
187
|
+
if wait:
|
|
188
|
+
return self.wait_for_replicas(timeout=wait_timeout, sleep=sleep)
|
|
189
|
+
return True
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from ocp_resources.constants import TIMEOUT_4MINUTES
|
|
2
|
+
from ocp_resources.mtv import MTV
|
|
3
|
+
from ocp_resources.resource import NamespacedResource
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(NamespacedResource, MTV):
|
|
7
|
+
"""
|
|
8
|
+
Migration Toolkit For Virtualization (MTV) Migration object.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
plan_name (str): MTV Plan CR name.
|
|
12
|
+
plan_namespace (str): MTV Plan CR namespace.
|
|
13
|
+
cut_over (date): For Warm Migration Only.Cut Over Phase Start Date & Time.
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
api_group = NamespacedResource.ApiGroup.FORKLIFT_KONVEYOR_IO
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
name=None,
|
|
22
|
+
namespace=None,
|
|
23
|
+
plan_name=None,
|
|
24
|
+
plan_namespace=None,
|
|
25
|
+
cut_over=None,
|
|
26
|
+
client=None,
|
|
27
|
+
teardown=True,
|
|
28
|
+
yaml_file=None,
|
|
29
|
+
delete_timeout=TIMEOUT_4MINUTES,
|
|
30
|
+
**kwargs,
|
|
31
|
+
):
|
|
32
|
+
super().__init__(
|
|
33
|
+
name=name,
|
|
34
|
+
namespace=namespace,
|
|
35
|
+
client=client,
|
|
36
|
+
teardown=teardown,
|
|
37
|
+
yaml_file=yaml_file,
|
|
38
|
+
delete_timeout=delete_timeout,
|
|
39
|
+
**kwargs,
|
|
40
|
+
)
|
|
41
|
+
self.plan_name = plan_name
|
|
42
|
+
self.plan_namespace = plan_namespace
|
|
43
|
+
self.cut_over = cut_over
|
|
44
|
+
self.condition_message_succeeded = self.ConditionMessage.MIGRATION_SUCCEEDED
|
|
45
|
+
|
|
46
|
+
def to_dict(self):
|
|
47
|
+
super().to_dict()
|
|
48
|
+
if not self.yaml_file:
|
|
49
|
+
self.res.update(
|
|
50
|
+
{
|
|
51
|
+
"spec": {
|
|
52
|
+
"plan": {
|
|
53
|
+
"name": self.plan_name,
|
|
54
|
+
"namespace": self.plan_namespace,
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
if self.cut_over:
|
|
61
|
+
self.res["spec"]["cutover"] = self.cut_over.strftime(
|
|
62
|
+
format="%Y-%m-%dT%H:%M:%SZ"
|
|
63
|
+
)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from ocp_resources.resource import Resource
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class MigrationPolicy(Resource):
|
|
5
|
+
api_group = Resource.ApiGroup.MIGRATIONS_KUBEVIRT_IO
|
|
6
|
+
|
|
7
|
+
def __init__(
|
|
8
|
+
self,
|
|
9
|
+
name=None,
|
|
10
|
+
allow_auto_converge=None,
|
|
11
|
+
allow_post_copy=None,
|
|
12
|
+
bandwidth_per_migration=None,
|
|
13
|
+
completion_timeout_per_gb=None,
|
|
14
|
+
namespace_selector=None,
|
|
15
|
+
vmi_selector=None,
|
|
16
|
+
**kwargs,
|
|
17
|
+
):
|
|
18
|
+
"""
|
|
19
|
+
Create MigrationPolicy object.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
name (str): Migration Policy name
|
|
23
|
+
allow_auto_converge (bool, optional)
|
|
24
|
+
allow_post_copy (bool, optional)
|
|
25
|
+
bandwidth_per_migration (str, optional, i.e. "1Gi")
|
|
26
|
+
completion_timeout_per_gb (int, optional)
|
|
27
|
+
namespace_selector (dict, optional): Dict of Namespace labels to match (e.g. {"project-owner": "redhat"})
|
|
28
|
+
vmi_selector (dict, optional): Dict of VMI labels to match (e.g. {"best-vm": ""})
|
|
29
|
+
"""
|
|
30
|
+
super().__init__(
|
|
31
|
+
name=name,
|
|
32
|
+
**kwargs,
|
|
33
|
+
)
|
|
34
|
+
self.allow_auto_converge = allow_auto_converge
|
|
35
|
+
self.allow_post_copy = allow_post_copy
|
|
36
|
+
self.bandwidth_per_migration = bandwidth_per_migration
|
|
37
|
+
self.completion_timeout_per_gb = completion_timeout_per_gb
|
|
38
|
+
self.namespace_selector = namespace_selector or {}
|
|
39
|
+
self.vmi_selector = vmi_selector or {}
|
|
40
|
+
|
|
41
|
+
def to_dict(self):
|
|
42
|
+
super().to_dict()
|
|
43
|
+
if not self.yaml_file:
|
|
44
|
+
spec = self.res.setdefault("spec", {})
|
|
45
|
+
selectors = spec.setdefault("selectors", {})
|
|
46
|
+
|
|
47
|
+
if self.allow_auto_converge is not None:
|
|
48
|
+
self.res["spec"]["allowAutoConverge"] = self.allow_auto_converge
|
|
49
|
+
if self.allow_post_copy is not None:
|
|
50
|
+
self.res["spec"]["allowPostCopy"] = self.allow_post_copy
|
|
51
|
+
if self.bandwidth_per_migration:
|
|
52
|
+
self.res["spec"]["bandwidthPerMigration"] = self.bandwidth_per_migration
|
|
53
|
+
if self.completion_timeout_per_gb:
|
|
54
|
+
self.res["spec"][
|
|
55
|
+
"completionTimeoutPerGiB"
|
|
56
|
+
] = self.completion_timeout_per_gb
|
|
57
|
+
|
|
58
|
+
if self.namespace_selector:
|
|
59
|
+
selectors.setdefault("namespaceSelector", {}).setdefault(
|
|
60
|
+
"matchLabels", self.namespace_selector
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
if self.vmi_selector:
|
|
64
|
+
selectors.setdefault("virtualMachineInstanceSelector", {}).setdefault(
|
|
65
|
+
"matchLabels", self.vmi_selector
|
|
66
|
+
)
|
ocp_resources/mtv.py
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
from ocp_resources.utils import TimeoutExpiredError, TimeoutSampler
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _get_status_condition_log_message(**status_condition):
|
|
5
|
+
log_msg = "Waiting For: \n"
|
|
6
|
+
for status_condition_name, status_condition in status_condition.items():
|
|
7
|
+
log_msg += (
|
|
8
|
+
f"{status_condition_name}->{status_condition} \n"
|
|
9
|
+
if status_condition
|
|
10
|
+
else ""
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
return log_msg
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MTV:
|
|
17
|
+
"""
|
|
18
|
+
Abstract Class for all Migration ToolKit For Virtualization (MTV) Resources:
|
|
19
|
+
Provider
|
|
20
|
+
Plan
|
|
21
|
+
Migration
|
|
22
|
+
StorageMap
|
|
23
|
+
NetworkMap
|
|
24
|
+
Host
|
|
25
|
+
ForkliftController
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self):
|
|
29
|
+
self.api = None
|
|
30
|
+
self.name = None
|
|
31
|
+
self.namespace = None
|
|
32
|
+
self.kind = None
|
|
33
|
+
self.Condition = None
|
|
34
|
+
self.Status = None
|
|
35
|
+
|
|
36
|
+
self.condition_message_ready = None
|
|
37
|
+
self.condition_message_succeeded = None
|
|
38
|
+
self.mapping = None
|
|
39
|
+
self.source_provider_name = None
|
|
40
|
+
self.source_provider_namespace = None
|
|
41
|
+
self.destination_provider_name = None
|
|
42
|
+
self.destination_provider_namespace = None
|
|
43
|
+
|
|
44
|
+
if self.__class__.__name__ == "MTV":
|
|
45
|
+
raise TypeError("MTV is not a Resource. Please Use one of its successors.")
|
|
46
|
+
|
|
47
|
+
class ConditionMessage:
|
|
48
|
+
PROVIDER_READY = "The provider is ready."
|
|
49
|
+
NETWORK_MAP_READY = "The network map is ready."
|
|
50
|
+
STORAGE_MAP_READY = "The storage map is ready."
|
|
51
|
+
PLAN_READY = "The migration plan is ready."
|
|
52
|
+
PLAN_SUCCEEDED = "The plan execution has SUCCEEDED."
|
|
53
|
+
PLAN_FAILED = "The plan execution has FAILED."
|
|
54
|
+
MIGRATION_READY = "The migration is ready."
|
|
55
|
+
MIGRATION_RUNNING = "The migration is RUNNING"
|
|
56
|
+
MIGRATION_SUCCEEDED = "The migration has SUCCEEDED."
|
|
57
|
+
HOST_READY = "The host is ready."
|
|
58
|
+
|
|
59
|
+
class ConditionCategory:
|
|
60
|
+
CRITICAL = "Critical"
|
|
61
|
+
|
|
62
|
+
class ConditionType:
|
|
63
|
+
SUCCEEDED = "Succeeded"
|
|
64
|
+
FAILED = "Failed"
|
|
65
|
+
TARGET_NAME_NOT_VALID = "TargetNameNotValid"
|
|
66
|
+
VM_ALREADY_EXISTS = "VMAlreadyExists"
|
|
67
|
+
|
|
68
|
+
class ProviderType:
|
|
69
|
+
VSPHERE = "vsphere"
|
|
70
|
+
OPENSHIFT = "openshift"
|
|
71
|
+
RHV = "ovirt"
|
|
72
|
+
|
|
73
|
+
def wait_for_resource_status(
|
|
74
|
+
self,
|
|
75
|
+
condition_status,
|
|
76
|
+
condition_type,
|
|
77
|
+
condition_message=None,
|
|
78
|
+
condition_reason=None,
|
|
79
|
+
condition_category=None,
|
|
80
|
+
wait_timeout=600,
|
|
81
|
+
):
|
|
82
|
+
"""
|
|
83
|
+
Wait for MTV Resource Status Conditions.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
self.logger.info(
|
|
87
|
+
_get_status_condition_log_message(
|
|
88
|
+
condition_status=condition_status,
|
|
89
|
+
condition_type=condition_type,
|
|
90
|
+
condition_message=condition_message,
|
|
91
|
+
condition_reason=condition_reason,
|
|
92
|
+
condition_category=condition_category,
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
samples = TimeoutSampler(
|
|
97
|
+
wait_timeout=wait_timeout,
|
|
98
|
+
sleep=1,
|
|
99
|
+
func=self.api.get,
|
|
100
|
+
field_selector=f"metadata.name=={self.name}",
|
|
101
|
+
namespace=self.namespace,
|
|
102
|
+
)
|
|
103
|
+
last_condition = None
|
|
104
|
+
try:
|
|
105
|
+
for sample in samples:
|
|
106
|
+
current_conditions = (
|
|
107
|
+
sample.items[0].status.get("conditions")
|
|
108
|
+
if sample.items and sample.items[0].status
|
|
109
|
+
else []
|
|
110
|
+
)
|
|
111
|
+
for condition in current_conditions:
|
|
112
|
+
last_condition = condition
|
|
113
|
+
valid_status_type = (
|
|
114
|
+
condition_status == condition.status
|
|
115
|
+
and condition_type == condition.type
|
|
116
|
+
)
|
|
117
|
+
valid_message = (
|
|
118
|
+
condition_message == condition.message
|
|
119
|
+
or condition_message is None
|
|
120
|
+
)
|
|
121
|
+
valid_reason = (
|
|
122
|
+
condition_reason == condition.reason or condition_reason is None
|
|
123
|
+
)
|
|
124
|
+
valid_category = (
|
|
125
|
+
condition_category == condition.category
|
|
126
|
+
or condition_category is None
|
|
127
|
+
)
|
|
128
|
+
if all(
|
|
129
|
+
[valid_status_type, valid_message, valid_reason, valid_category]
|
|
130
|
+
):
|
|
131
|
+
return
|
|
132
|
+
|
|
133
|
+
except TimeoutExpiredError:
|
|
134
|
+
self.logger.error(
|
|
135
|
+
msg=f"Last Status Condition of {self.kind} {self.name} was: {last_condition}"
|
|
136
|
+
)
|
|
137
|
+
raise
|
|
138
|
+
|
|
139
|
+
def wait_for_condition_ready(self, wait_timeout=360):
|
|
140
|
+
self.wait_for_resource_status(
|
|
141
|
+
condition_message=self.condition_message_ready,
|
|
142
|
+
condition_status=self.Condition.Status.TRUE,
|
|
143
|
+
condition_type=self.Condition.READY,
|
|
144
|
+
wait_timeout=wait_timeout,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
def wait_for_condition_succeeded(self, wait_timeout=600):
|
|
148
|
+
self.wait_for_resource_status(
|
|
149
|
+
condition_type=self.Status.SUCCEEDED,
|
|
150
|
+
condition_message=self.condition_message_succeeded,
|
|
151
|
+
condition_status=self.Condition.Status.TRUE,
|
|
152
|
+
wait_timeout=wait_timeout,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def map_to_dict(self):
|
|
157
|
+
return {
|
|
158
|
+
"spec": {
|
|
159
|
+
"map": self.mapping,
|
|
160
|
+
"provider": {
|
|
161
|
+
"source": {
|
|
162
|
+
"name": self.source_provider_name,
|
|
163
|
+
"namespace": self.source_provider_namespace,
|
|
164
|
+
},
|
|
165
|
+
"destination": {
|
|
166
|
+
"name": self.destination_provider_name,
|
|
167
|
+
"namespace": self.destination_provider_namespace,
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from ocp_resources.constants import TIMEOUT_4MINUTES
|
|
2
|
+
from ocp_resources.resource import Resource
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Namespace(Resource):
|
|
6
|
+
"""
|
|
7
|
+
Namespace object, inherited from Resource.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
api_version = Resource.ApiVersion.V1
|
|
11
|
+
|
|
12
|
+
class Status(Resource.Status):
|
|
13
|
+
ACTIVE = "Active"
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
name=None,
|
|
18
|
+
client=None,
|
|
19
|
+
teardown=True,
|
|
20
|
+
label=None,
|
|
21
|
+
yaml_file=None,
|
|
22
|
+
delete_timeout=TIMEOUT_4MINUTES,
|
|
23
|
+
**kwargs,
|
|
24
|
+
):
|
|
25
|
+
super().__init__(
|
|
26
|
+
name=name,
|
|
27
|
+
client=client,
|
|
28
|
+
teardown=teardown,
|
|
29
|
+
yaml_file=yaml_file,
|
|
30
|
+
delete_timeout=delete_timeout,
|
|
31
|
+
**kwargs,
|
|
32
|
+
)
|
|
33
|
+
self.label = label
|
|
34
|
+
|
|
35
|
+
def to_dict(self):
|
|
36
|
+
super().to_dict()
|
|
37
|
+
if not self.yaml_file and self.label:
|
|
38
|
+
self.res.setdefault("metadata", {}).setdefault("labels", {}).update(
|
|
39
|
+
self.label
|
|
40
|
+
)
|
ocp_resources/network.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from ocp_resources.resource import NamespacedResource
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class NetworkAttachmentDefinition(NamespacedResource):
|
|
5
|
+
"""
|
|
6
|
+
NetworkAttachmentDefinition object.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
api_group = NamespacedResource.ApiGroup.K8S_CNI_CNCF_IO
|
|
10
|
+
resource_name = None
|
|
11
|
+
|
|
12
|
+
def wait_for_status(
|
|
13
|
+
self, status, timeout=None, label_selector=None, resource_version=None
|
|
14
|
+
):
|
|
15
|
+
raise NotImplementedError(f"{self.kind} does not have status")
|
|
16
|
+
|
|
17
|
+
def to_dict(self):
|
|
18
|
+
super().to_dict()
|
|
19
|
+
if not self.yaml_file:
|
|
20
|
+
if self.resource_name is not None:
|
|
21
|
+
self.res["metadata"]["annotations"] = {
|
|
22
|
+
f"{NamespacedResource.ApiGroup.K8S_V1_CNI_CNCF_IO}/resourceName": self.resource_name
|
|
23
|
+
}
|
|
24
|
+
self.res["spec"] = {}
|