rpyc-pve-cloud 0.0.21__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.
@@ -0,0 +1,169 @@
1
+ import asyncio, asyncssh
2
+ import grpc
3
+ import pve_cloud_rpc.protos.cloud_pb2 as cloud_pb2
4
+ import pve_cloud_rpc.protos.cloud_pb2_grpc as cloud_pb2_grpc
5
+ import pve_cloud_rpc.protos.health_pb2 as health_pb2
6
+ import pve_cloud_rpc.protos.health_pb2_grpc as health_pb2_grpc
7
+ from pve_cloud.lib.inventory import *
8
+ from pve_cloud.cli.pvclu import get_cluster_vars, get_ssh_master_kubeconfig
9
+ import yaml
10
+ import socket
11
+ import sys
12
+
13
+
14
+ class HealthServicer(health_pb2_grpc.HealthServicer):
15
+ def __init__(self):
16
+ self._statuses = {}
17
+
18
+ async def Check(self, request, context):
19
+ service_name = request.service or ""
20
+ status = self._statuses.get(service_name, health_pb2.HealthCheckResponse.UNKNOWN)
21
+ print(f"Health Check request for service '{service_name}', returning {status}")
22
+ return health_pb2.HealthCheckResponse(status=status)
23
+
24
+ def set_status(self, service_name: str, status: health_pb2.HealthCheckResponse.ServingStatus):
25
+ self._statuses[service_name] = status
26
+
27
+
28
+ class CloudServiceServicer(cloud_pb2_grpc.CloudServiceServicer):
29
+
30
+ async def GetMasterKubeconfig(self, request, context):
31
+ target_pve = request.target_pve
32
+ stack_name = request.stack_name
33
+
34
+ online_pve_host = get_online_pve_host(target_pve, skip_py_cloud_check=True)
35
+ cluster_vars = get_cluster_vars(online_pve_host)
36
+
37
+ return cloud_pb2.GetKubeconfigResponse(config=get_ssh_master_kubeconfig(cluster_vars, stack_name))
38
+
39
+
40
+ async def GetClusterVars(self, request, context):
41
+ target_pve = request.target_pve
42
+
43
+ online_pve_host = get_online_pve_host(target_pve, skip_py_cloud_check=True)
44
+ cluster_vars = get_cluster_vars(online_pve_host)
45
+
46
+ return cloud_pb2.GetClusterVarsResponse(vars=yaml.safe_dump(cluster_vars))
47
+
48
+
49
+ async def GetCloudSecret(self, request, context):
50
+ target_pve = request.target_pve
51
+ secret_name = request.secret_name
52
+
53
+ online_pve_host = get_online_pve_host(target_pve, skip_py_cloud_check=True)
54
+ async with asyncssh.connect(online_pve_host, username='root', known_hosts=None) as conn:
55
+ cmd = await conn.run(f"cat /etc/pve/cloud/secrets/{secret_name}", check=True)
56
+ catted_secret = cmd.stdout
57
+
58
+ return cloud_pb2.GetCloudSecretResponse(secret=catted_secret)
59
+
60
+
61
+ async def GetCephAccess(self, request, context):
62
+ target_pve = request.target_pve
63
+
64
+ online_pve_host = get_online_pve_host(target_pve, skip_py_cloud_check=True)
65
+ async with asyncssh.connect(online_pve_host, username='root', known_hosts=None) as conn:
66
+ cmd = await conn.run(f"cat /etc/ceph/ceph.conf", check=True)
67
+ catted_conf = cmd.stdout
68
+
69
+ cmd = await conn.run(f"cat /etc/pve/priv/ceph.client.admin.keyring", check=True)
70
+ catted_keyring = cmd.stdout
71
+
72
+
73
+ return cloud_pb2.GetCephAccessResponse(ceph_conf=catted_conf, admin_keyring=catted_keyring)
74
+
75
+
76
+ async def GetSshKey(self, request, context):
77
+ target_pve = request.target_pve
78
+
79
+ online_pve_host = get_online_pve_host(target_pve, skip_py_cloud_check=True)
80
+ async with asyncssh.connect(online_pve_host, username='root', known_hosts=None) as conn:
81
+ match request.key_type:
82
+ case cloud_pb2.GetSshKeyRequest.PVE_HOST_RSA:
83
+ cmd = await conn.run(f"cat /root/.ssh/id_rsa", check=True)
84
+ catted_key = cmd.stdout
85
+ case cloud_pb2.GetSshKeyRequest.AUTOMATION:
86
+ cmd = await conn.run(f"cat /etc/pve/cloud/automation_id_ed25519", check=True)
87
+ catted_key = cmd.stdout
88
+
89
+ return cloud_pb2.GetSshKeyResponse(key=catted_key)
90
+
91
+
92
+ async def GetProxmoxApi(self, request, context):
93
+ target_pve = request.target_pve
94
+
95
+ online_pve_host = get_online_pve_host(target_pve, skip_py_cloud_check=True)
96
+ async with asyncssh.connect(online_pve_host, username='root', known_hosts=None) as conn:
97
+ args_string = None
98
+ if request.get_args:
99
+ args_string = " ".join(f"{k} {v}" for k, v in request.get_args.items())
100
+
101
+ cmd = await conn.run(f"pvesh get {request.api_path} {args_string} --output-format json", check=True)
102
+ resp_json = cmd.stdout
103
+
104
+ return cloud_pb2.GetProxmoxApiResponse(json_resp=resp_json)
105
+
106
+
107
+ async def GetProxmoxHost(self, request, context):
108
+ target_pve = request.target_pve
109
+ online_pve_host = get_online_pve_host(target_pve, skip_py_cloud_check=True)
110
+
111
+ return cloud_pb2.GetProxmoxHostResponse(pve_host=online_pve_host)
112
+
113
+
114
+ async def GetPveInventory(self, request, context):
115
+ target_pve = request.target_pve
116
+
117
+ cloud_domain = get_cloud_domain(target_pve)
118
+ pve_inventory = get_pve_inventory(cloud_domain, skip_py_cloud_check=True)
119
+
120
+ return cloud_pb2.GetPveInventoryResponse(inventory=yaml.safe_dump(pve_inventory), cloud_domain=cloud_domain)
121
+
122
+
123
+ def is_port_bound(port, host="0.0.0.0"):
124
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
125
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
126
+ try:
127
+ s.bind((host, port))
128
+ return False # not bound
129
+ except OSError:
130
+ return True # bound
131
+
132
+
133
+ async def serve():
134
+ server = grpc.aio.server()
135
+ cloud_pb2_grpc.add_CloudServiceServicer_to_server(CloudServiceServicer(), server)
136
+
137
+ health_servicer = HealthServicer()
138
+ health_pb2_grpc.add_HealthServicer_to_server(health_servicer, server)
139
+
140
+ # if is_port_bound(50052): # google quirks nice
141
+ # raise RuntimeError("PCRPC Already running / unclean shutdown!")
142
+
143
+ socket_file = f"/tmp/pc-rpc-{sys.argv[1]}.sock"
144
+
145
+ # listen_addr = "[::]:50052"
146
+ server.add_insecure_port(f"unix://{socket_file}")
147
+ await server.start()
148
+
149
+ health_servicer.set_status(
150
+ "", # empty = overall server health
151
+ health_pb2.HealthCheckResponse.SERVING
152
+ )
153
+ # print(f"gRPC AsyncIO server running on {listen_addr}")
154
+ print(f"gRPC AsyncIO server running on {socket_file}")
155
+ try:
156
+ await server.wait_for_termination()
157
+ finally:
158
+ # Ensure cleanup
159
+ await server.stop(grace=0)
160
+ print("gRPC server stopped and port released.")
161
+
162
+ # delete unix socket file
163
+ if os.path.exists(socket_file):
164
+ os.remove(socket_file)
165
+
166
+
167
+
168
+ def main():
169
+ asyncio.run(serve())
@@ -0,0 +1,10 @@
1
+ Metadata-Version: 2.4
2
+ Name: rpyc-pve-cloud
3
+ Version: 0.0.21
4
+ Author-email: Tobias Huebner <tobias.huebner@vmzberlin.com>
5
+ License-Expression: GPL-3.0-or-later
6
+ License-File: LICENSE.md
7
+ Requires-Dist: py-pve-cloud<0.14.0,>=0.13.8
8
+ Requires-Dist: grpcio==1.76.0
9
+ Requires-Dist: asyncssh==2.21.0
10
+ Dynamic: license-file
@@ -0,0 +1,12 @@
1
+ pve_cloud_rpc/_version.py,sha256=PsqtE_T084MVsMv47JyTQ3DK2CRZJ3Kd9Q_vnw02oZk,23
2
+ pve_cloud_rpc/server.py,sha256=gupcL5VHLTJUfZPgBn04H6tpNdUykvSylbBXd4YPg2U,6439
3
+ pve_cloud_rpc/protos/cloud_pb2.py,sha256=WZyD6MaxEnEXHXDzLrkk1O0WvoRTmuS9wY2UXZm29JE,6153
4
+ pve_cloud_rpc/protos/cloud_pb2_grpc.py,sha256=FOC_MXEZkXe32dzxQua9zHBLWLjso1X-xqj0xTexfFg,15535
5
+ pve_cloud_rpc/protos/health_pb2.py,sha256=GuDLSR8jFZuEk4cNL0UMEkTerscanrgOFroe-gee-Nc,2238
6
+ pve_cloud_rpc/protos/health_pb2_grpc.py,sha256=XXT8lsH8YgKLqn07YfigSQ6TNW6s-P4V6S-X69fLfh0,3368
7
+ rpyc_pve_cloud-0.0.21.dist-info/licenses/LICENSE.md,sha256=ADUqsZhl4juwq34PRTMiBqumpm11s_PMli_dZQjWPqQ,34260
8
+ rpyc_pve_cloud-0.0.21.dist-info/METADATA,sha256=c016rbTMiSinbW4O7wa8P22pOWVuFy_z8o7mV4P4syw,309
9
+ rpyc_pve_cloud-0.0.21.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
10
+ rpyc_pve_cloud-0.0.21.dist-info/entry_points.txt,sha256=h4ytTryc_8IlySP_ICyy6srHzF71qrQ0noUhqI-3aGw,52
11
+ rpyc_pve_cloud-0.0.21.dist-info/top_level.txt,sha256=CTGM4RRp33khtroUiv-RiYXI4h6W6AaQQGIvsbwAetM,14
12
+ rpyc_pve_cloud-0.0.21.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pcrpc = pve_cloud_rpc.server:main