py-pve-cloud 0.0.4__tar.gz → 0.1.0__tar.gz

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.

Potentially problematic release.


This version of py-pve-cloud might be problematic. Click here for more details.

Files changed (25) hide show
  1. {py_pve_cloud-0.0.4/src/py_pve_cloud.egg-info → py_pve_cloud-0.1.0}/PKG-INFO +3 -1
  2. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/pyproject.toml +4 -2
  3. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/pve_cloud/cli/pvcli.py +1 -1
  4. py_pve_cloud-0.1.0/src/pve_cloud/cli/pvclu.py +134 -0
  5. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0/src/py_pve_cloud.egg-info}/PKG-INFO +3 -1
  6. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/py_pve_cloud.egg-info/requires.txt +2 -0
  7. py_pve_cloud-0.0.4/src/pve_cloud/cli/pvclu.py +0 -68
  8. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/LICENSE +0 -0
  9. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/README.md +0 -0
  10. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/setup.cfg +0 -0
  11. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/pve_cloud/lib/inventory.py +0 -0
  12. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/pve_cloud/orm/alchemy.py +0 -0
  13. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/pve_cloud/orm/alembic.ini +0 -0
  14. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/pve_cloud/orm/migrations/env.py +0 -0
  15. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/pve_cloud/orm/migrations/versions/24a548bfce3e_len_rules_enforcements.py +0 -0
  16. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/pve_cloud/orm/migrations/versions/27724e407e2b_proxy_fqdn.py +0 -0
  17. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/pve_cloud/orm/migrations/versions/3c95509a5de9_fix.py +0 -0
  18. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/pve_cloud/orm/migrations/versions/7868bcd05006_migrate_old.py +0 -0
  19. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/pve_cloud/orm/migrations/versions/7dea8c4ee39f_init.py +0 -0
  20. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/pve_cloud/orm/migrations/versions/944a8fd5d5bc_ext_ctrl_plns.py +0 -0
  21. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/pve_cloud/orm/migrations/versions/d9b711555be8_ext_control_plane.py +0 -0
  22. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/py_pve_cloud.egg-info/SOURCES.txt +0 -0
  23. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/py_pve_cloud.egg-info/dependency_links.txt +0 -0
  24. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/py_pve_cloud.egg-info/entry_points.txt +0 -0
  25. {py_pve_cloud-0.0.4 → py_pve_cloud-0.1.0}/src/py_pve_cloud.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py-pve-cloud
3
- Version: 0.0.4
3
+ Version: 0.1.0
4
4
  Author-email: Tobias Huebner <tobias.huebner@vmzberlin.com>
5
5
  License-Expression: GPL-3.0-or-later
6
6
  License-File: LICENSE
@@ -8,5 +8,7 @@ Requires-Dist: PyYAML==6.0.2
8
8
  Requires-Dist: psycopg2-binary==2.9.10
9
9
  Requires-Dist: SQLAlchemy==2.0.43
10
10
  Requires-Dist: alembic==1.16.5
11
+ Requires-Dist: paramiko==4.0.0
11
12
  Requires-Dist: proxmoxer==2.2.0
13
+ Requires-Dist: dnspython==2.7.0
12
14
  Dynamic: license-file
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "py-pve-cloud"
7
- version = "0.0.4"
7
+ version = "0.1.0"
8
8
  authors = [{ name = "Tobias Huebner", email = "tobias.huebner@vmzberlin.com" }]
9
9
  license = "GPL-3.0-or-later"
10
10
  license-files = ["LICENSE"]
@@ -13,7 +13,9 @@ dependencies = [
13
13
  "psycopg2-binary==2.9.10",
14
14
  "SQLAlchemy==2.0.43",
15
15
  "alembic==1.16.5",
16
- "proxmoxer==2.2.0"
16
+ "paramiko==4.0.0",
17
+ "proxmoxer==2.2.0",
18
+ "dnspython==2.7.0"
17
19
  ]
18
20
 
19
21
  [tool.setuptools.package-data]
@@ -2,7 +2,7 @@ import argparse
2
2
  import yaml
3
3
  from proxmoxer import ProxmoxAPI
4
4
  import os
5
- import paramiko
5
+
6
6
 
7
7
 
8
8
  def connect_cluster(args):
@@ -0,0 +1,134 @@
1
+ import argparse
2
+ import yaml
3
+ import os
4
+ import socket
5
+ import paramiko
6
+ import dns.resolver
7
+ import base64
8
+
9
+
10
+ def get_cloud_domain(target_pve):
11
+ with open(os.path.expanduser("~/.pve-cloud-dyn-inv.yaml"), "r") as f:
12
+ pve_inventory = yaml.safe_load(f)
13
+
14
+ for pve_cloud in pve_inventory:
15
+ for pve_cluster in pve_inventory[pve_cloud]:
16
+ if pve_cluster + "." + pve_cloud == target_pve:
17
+ return pve_cloud
18
+
19
+ raise Exception(f"Could not identify cloud domain for {target_pve}")
20
+
21
+
22
+ def get_cld_domain_prsr(args):
23
+ print(f"export PVE_CLOUD_DOMAIN='{get_cloud_domain(args.target_pve)}'")
24
+
25
+
26
+ def get_online_pve_host(target_pve):
27
+ with open(os.path.expanduser("~/.pve-cloud-dyn-inv.yaml"), "r") as f:
28
+ pve_inventory = yaml.safe_load(f)
29
+
30
+ for pve_cloud in pve_inventory:
31
+ for pve_cluster in pve_inventory[pve_cloud]:
32
+ if pve_cluster + "." + pve_cloud == target_pve:
33
+ for pve_host in pve_inventory[pve_cloud][pve_cluster]:
34
+ # check if host is available
35
+ pve_host_ip = pve_inventory[pve_cloud][pve_cluster][pve_host]["ansible_host"]
36
+ try:
37
+ with socket.create_connection((pve_host_ip, 22), timeout=3):
38
+ return pve_host_ip
39
+ except Exception as e:
40
+ # debug
41
+ print(e, type(e))
42
+ pass
43
+
44
+ raise Exception(f"Could not find online pve host for {target_pve}")
45
+
46
+
47
+ def get_cloud_env(pve_host):
48
+ ssh = paramiko.SSHClient()
49
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
50
+
51
+ ssh.connect(pve_host, username="root")
52
+
53
+ # since we need root we cant use sftp and root via ssh is disabled
54
+ _, stdout, _ = ssh.exec_command("cat /etc/pve/cloud/cluster_vars.yaml")
55
+
56
+ cluster_vars = yaml.safe_load(stdout.read().decode('utf-8'))
57
+
58
+ _, stdout, _ = ssh.exec_command("cat /etc/pve/cloud/secrets/patroni.pass")
59
+
60
+ patroni_pass = stdout.read().decode('utf-8')
61
+
62
+ return cluster_vars, patroni_pass
63
+
64
+
65
+ def get_online_pve_host_prsr(args):
66
+ print(f"export PVE_ANSIBLE_HOST='{get_online_pve_host(args.target_pve)}'")
67
+
68
+
69
+ def get_ssh_master_kubeconfig(cluster_vars, stack_name):
70
+ resolver = dns.resolver.Resolver()
71
+ resolver.nameservers = [cluster_vars['bind_master_ip'], cluster_vars['bind_slave_ip']]
72
+
73
+ ddns_answer = resolver.resolve(f"masters-{stack_name}.{cluster_vars['pve_cloud_domain']}")
74
+ ddns_ips = [rdata.to_text() for rdata in ddns_answer]
75
+
76
+ if not ddns_ips:
77
+ raise Exception("No master could be found via DNS!")
78
+
79
+ print(ddns_ips)
80
+
81
+ ssh = paramiko.SSHClient()
82
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
83
+
84
+ ssh.connect(ddns_ips[0], username="admin")
85
+
86
+ # since we need root we cant use sftp and root via ssh is disabled
87
+ _, stdout, _ = ssh.exec_command("sudo cat /etc/kubernetes/admin.conf")
88
+
89
+ return base64.b64encode(stdout.read().decode('utf-8').replace("https://127.0.0.1:6443", f"https://{ddns_ips[0]}:6443").encode('utf-8')).decode('utf-8')
90
+
91
+
92
+ def export_envr(args):
93
+ ansible_host = get_online_pve_host(args.target_pve)
94
+ cloud_domain = get_cloud_domain(args.target_pve)
95
+ cluster_vars, patroni_pass = get_cloud_env(ansible_host)
96
+ print(f"export PVE_ANSIBLE_HOST='{ansible_host}'")
97
+ print(f"export PVE_CLOUD_DOMAIN='{cloud_domain}'")
98
+
99
+ # tf vars
100
+ print(f"export PG_CONN_STR=\"postgres://postgres:{patroni_pass}@{cluster_vars["pve_haproxy_floating_ip_internal"]}:5000/tf_states?sslmode=disable\"")
101
+ print(f"export TF_VAR_pve_cloud_domain='{cloud_domain}'")
102
+ print(f"export TF_VAR_pve_host='{ansible_host}'")
103
+ print(f"export TF_VAR_cluster_proxy_ip='{cluster_vars["pve_haproxy_floating_ip_internal"]}'")
104
+ print(f"export TF_VAR_pve_cloud_pg_cstr=\"postgresql+psycopg2://postgres:{patroni_pass}@{cluster_vars["pve_haproxy_floating_ip_internal"]}:5000/pve_cloud?sslmode=disable\"")
105
+ print(f"export TF_VAR_master_b64_kubeconf='{get_ssh_master_kubeconfig(cluster_vars, args.stack_name)}'")
106
+
107
+
108
+
109
+ def main():
110
+ parser = argparse.ArgumentParser(description="PVE Cloud utility cli. Should be called with bash eval.")
111
+
112
+ base_parser = argparse.ArgumentParser(add_help=False)
113
+
114
+ subparsers = parser.add_subparsers(dest="command", required=True)
115
+
116
+ get_cld_domain_parser = subparsers.add_parser("get-cloud-domain", help="Get the cloud domain of a pve cluster.", parents=[base_parser])
117
+ get_cld_domain_parser.add_argument("--target-pve", type=str, help="The target pve cluster to get the cloud domain of.", required=True)
118
+ get_cld_domain_parser .set_defaults(func=get_cld_domain_prsr)
119
+
120
+ export_envr_parser = subparsers.add_parser("export-envrc", help="Export variables for k8s .envrc", parents=[base_parser])
121
+ export_envr_parser.add_argument("--target-pve", type=str, help="The target pve cluster.", required=True)
122
+ export_envr_parser.add_argument("--stack-name", type=str, help="Stack name of the deployment.", required=True)
123
+ export_envr_parser.set_defaults(func=export_envr)
124
+
125
+ get_online_pve_host_parser = subparsers.add_parser("get-online-host", help="Gets the ip for the first online proxmox host in the cluster.", parents=[base_parser])
126
+ get_online_pve_host_parser.add_argument("--target-pve", type=str, help="The target pve cluster to get the first online ip of.", required=True)
127
+ get_online_pve_host_parser.set_defaults(func=get_online_pve_host_prsr)
128
+
129
+ args = parser.parse_args()
130
+ args.func(args)
131
+
132
+
133
+ if __name__ == "__main__":
134
+ main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py-pve-cloud
3
- Version: 0.0.4
3
+ Version: 0.1.0
4
4
  Author-email: Tobias Huebner <tobias.huebner@vmzberlin.com>
5
5
  License-Expression: GPL-3.0-or-later
6
6
  License-File: LICENSE
@@ -8,5 +8,7 @@ Requires-Dist: PyYAML==6.0.2
8
8
  Requires-Dist: psycopg2-binary==2.9.10
9
9
  Requires-Dist: SQLAlchemy==2.0.43
10
10
  Requires-Dist: alembic==1.16.5
11
+ Requires-Dist: paramiko==4.0.0
11
12
  Requires-Dist: proxmoxer==2.2.0
13
+ Requires-Dist: dnspython==2.7.0
12
14
  Dynamic: license-file
@@ -2,4 +2,6 @@ PyYAML==6.0.2
2
2
  psycopg2-binary==2.9.10
3
3
  SQLAlchemy==2.0.43
4
4
  alembic==1.16.5
5
+ paramiko==4.0.0
5
6
  proxmoxer==2.2.0
7
+ dnspython==2.7.0
@@ -1,68 +0,0 @@
1
- import argparse
2
- import yaml
3
- import os
4
- import socket
5
-
6
-
7
- def get_cloud_domain(target_pve):
8
- with open(os.path.expanduser("~/.pve-cloud-dyn-inv.yaml"), "r") as f:
9
- pve_inventory = yaml.safe_load(f)
10
-
11
- for pve_cloud in pve_inventory:
12
- for pve_cluster in pve_inventory[pve_cloud]:
13
- if pve_cluster + "." + pve_cloud == target_pve:
14
- return pve_cloud
15
-
16
- raise Exception(f"Could not identify cloud domain for {target_pve}")
17
-
18
-
19
- def get_cld_domain_prsr(args):
20
- print(f"export PVE_CLOUD_DOMAIN='{get_cloud_domain(args.target_pve)}'")
21
-
22
-
23
- def get_online_pve_host(target_pve):
24
- with open(os.path.expanduser("~/.pve-cloud-dyn-inv.yaml"), "r") as f:
25
- pve_inventory = yaml.safe_load(f)
26
-
27
- for pve_cloud in pve_inventory:
28
- for pve_cluster in pve_inventory[pve_cloud]:
29
- if pve_cluster + "." + pve_cloud == target_pve:
30
- for pve_host in pve_inventory[pve_cloud][pve_cluster]:
31
- # check if host is available
32
- pve_host_ip = pve_inventory[pve_cloud][pve_cluster][pve_host]["ansible_host"]
33
- try:
34
- with socket.create_connection((pve_host_ip, 22), timeout=3):
35
- return pve_host_ip
36
- except Exception as e:
37
- # debug
38
- print(e, type(e))
39
- pass
40
-
41
- raise Exception(f"Could not find online pve host for {target_pve}")
42
-
43
-
44
- def get_online_pve_host_prsr(args):
45
- print(f"export PVE_ANSIBLE_HOST='{get_online_pve_host(args.target_pve)}'")
46
-
47
-
48
- def main():
49
- parser = argparse.ArgumentParser(description="PVE Cloud utility cli. Should be called with bash eval.")
50
-
51
- base_parser = argparse.ArgumentParser(add_help=False)
52
-
53
- subparsers = parser.add_subparsers(dest="command", required=True)
54
-
55
- get_cld_domain_parser = subparsers.add_parser("get-cloud-domain", help="Get the cloud domain of a pve cluster.", parents=[base_parser])
56
- get_cld_domain_parser.add_argument("--target-pve", type=str, help="The target pve cluster to get the cloud domain of.", required=True)
57
- get_cld_domain_parser .set_defaults(func=get_cld_domain_prsr)
58
-
59
- get_online_pve_host_parser = subparsers.add_parser("get-online-host", help="Gets the ip for the first online proxmox host in the cluster.", parents=[base_parser])
60
- get_online_pve_host_parser.add_argument("--target-pve", type=str, help="The target pve cluster to get the first online ip of.", required=True)
61
- get_online_pve_host_parser.set_defaults(func=get_online_pve_host_prsr)
62
-
63
- args = parser.parse_args()
64
- args.func(args)
65
-
66
-
67
- if __name__ == "__main__":
68
- main()
File without changes
File without changes
File without changes