py-pve-cloud 0.0.2__tar.gz → 0.0.4__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.
- {py_pve_cloud-0.0.2/src/py_pve_cloud.egg-info → py_pve_cloud-0.0.4}/PKG-INFO +2 -1
- py_pve_cloud-0.0.4/README.md +21 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/pyproject.toml +4 -2
- py_pve_cloud-0.0.4/src/pve_cloud/cli/pvcli.py +97 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/pve_cloud/cli/pvclu.py +4 -4
- py_pve_cloud-0.0.4/src/pve_cloud/lib/inventory.py +3 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4/src/py_pve_cloud.egg-info}/PKG-INFO +2 -1
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/py_pve_cloud.egg-info/SOURCES.txt +2 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/py_pve_cloud.egg-info/entry_points.txt +1 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/py_pve_cloud.egg-info/requires.txt +1 -0
- py_pve_cloud-0.0.2/README.md +0 -4
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/LICENSE +0 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/setup.cfg +0 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/pve_cloud/orm/alchemy.py +0 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/pve_cloud/orm/alembic.ini +0 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/pve_cloud/orm/migrations/env.py +0 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/pve_cloud/orm/migrations/versions/24a548bfce3e_len_rules_enforcements.py +0 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/pve_cloud/orm/migrations/versions/27724e407e2b_proxy_fqdn.py +0 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/pve_cloud/orm/migrations/versions/3c95509a5de9_fix.py +0 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/pve_cloud/orm/migrations/versions/7868bcd05006_migrate_old.py +0 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/pve_cloud/orm/migrations/versions/7dea8c4ee39f_init.py +0 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/pve_cloud/orm/migrations/versions/944a8fd5d5bc_ext_ctrl_plns.py +0 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/pve_cloud/orm/migrations/versions/d9b711555be8_ext_control_plane.py +0 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/py_pve_cloud.egg-info/dependency_links.txt +0 -0
- {py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/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.
|
|
3
|
+
Version: 0.0.4
|
|
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,4 +8,5 @@ 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: proxmoxer==2.2.0
|
|
11
12
|
Dynamic: license-file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# py-pve-cloud
|
|
2
|
+
|
|
3
|
+
this is the core python library package that serves as a foundation for pve cloud.
|
|
4
|
+
|
|
5
|
+
## alembic orm
|
|
6
|
+
|
|
7
|
+
this project uses sqlalchemy + alembic integrated into the collection for management of the patroni database schema.
|
|
8
|
+
|
|
9
|
+
edit `src/orm/alchemy.py` database classes and run `alembic revision --auto-enerate -m "revision description"` from the orm folder, to commit your changes into the general migrations. before you need to do a `pip install .` to get the needed orm pypi packages.
|
|
10
|
+
|
|
11
|
+
you also need to `export PG_CONN_STR=postgresql+psycopg2://postgres:{{ patroni_postgres_pw }}@{{ proxy or master ip }}:{{ 5000 / 5432 }}/pve_cloud?sslmode=disable` env variable first with a testing database for alembic to work against. to create a new migration the database needs to be on the latest version, run `alembic upgrade head` to upgrade it.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## Releasing to pypi
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install build twine
|
|
18
|
+
rm -rf dist
|
|
19
|
+
python3 -m build
|
|
20
|
+
python3 -m twine upload dist/*
|
|
21
|
+
```
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "py-pve-cloud"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.4"
|
|
8
8
|
authors = [{ name = "Tobias Huebner", email = "tobias.huebner@vmzberlin.com" }]
|
|
9
9
|
license = "GPL-3.0-or-later"
|
|
10
10
|
license-files = ["LICENSE"]
|
|
@@ -12,7 +12,8 @@ dependencies = [
|
|
|
12
12
|
"PyYAML==6.0.2",
|
|
13
13
|
"psycopg2-binary==2.9.10",
|
|
14
14
|
"SQLAlchemy==2.0.43",
|
|
15
|
-
"alembic==1.16.5"
|
|
15
|
+
"alembic==1.16.5",
|
|
16
|
+
"proxmoxer==2.2.0"
|
|
16
17
|
]
|
|
17
18
|
|
|
18
19
|
[tool.setuptools.package-data]
|
|
@@ -20,4 +21,5 @@ dependencies = [
|
|
|
20
21
|
|
|
21
22
|
[project.scripts]
|
|
22
23
|
pvclu = "pve_cloud.cli.pvclu:main"
|
|
24
|
+
pvcli = "pve_cloud.cli.pvcli:main"
|
|
23
25
|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import yaml
|
|
3
|
+
from proxmoxer import ProxmoxAPI
|
|
4
|
+
import os
|
|
5
|
+
import paramiko
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def connect_cluster(args):
|
|
9
|
+
# try load current dynamic inventory
|
|
10
|
+
inv_path = os.path.expanduser("~/.pve-cloud-dyn-inv.yaml")
|
|
11
|
+
if os.path.exists(inv_path):
|
|
12
|
+
with open(inv_path, "r") as file:
|
|
13
|
+
dynamic_inventory = yaml.safe_load(file)
|
|
14
|
+
else:
|
|
15
|
+
# initialize empty
|
|
16
|
+
dynamic_inventory = {}
|
|
17
|
+
|
|
18
|
+
# init cloud domain if not there
|
|
19
|
+
if args.pve_cloud_domain not in dynamic_inventory:
|
|
20
|
+
dynamic_inventory[args.pve_cloud_domain] = {}
|
|
21
|
+
|
|
22
|
+
# connect to the passed host
|
|
23
|
+
proxmox = ProxmoxAPI(
|
|
24
|
+
args.pve_host, user="root", backend='ssh_paramiko'
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
# try get the cluster name
|
|
28
|
+
cluster_name = None
|
|
29
|
+
status_resp = proxmox.cluster.status.get()
|
|
30
|
+
for entry in status_resp:
|
|
31
|
+
if entry['id'] == "cluster":
|
|
32
|
+
cluster_name = entry['name']
|
|
33
|
+
break
|
|
34
|
+
|
|
35
|
+
if cluster_name is None:
|
|
36
|
+
raise Exception("Could not get cluster name")
|
|
37
|
+
|
|
38
|
+
if cluster_name in dynamic_inventory[args.pve_cloud_domain] and not args.force:
|
|
39
|
+
print(f"cluster {cluster_name} already in dynamic inventory")
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
# overwrite on force / create fresh
|
|
43
|
+
dynamic_inventory[args.pve_cloud_domain][cluster_name] = {}
|
|
44
|
+
|
|
45
|
+
# not present => add and safe the dynamic inventory
|
|
46
|
+
cluster_hosts = proxmox.nodes.get()
|
|
47
|
+
|
|
48
|
+
for node in cluster_hosts:
|
|
49
|
+
node_name = node["node"]
|
|
50
|
+
|
|
51
|
+
if node["status"] == "offline":
|
|
52
|
+
print(f"skipping offline node {node_name}")
|
|
53
|
+
continue
|
|
54
|
+
|
|
55
|
+
# get the main ip
|
|
56
|
+
ifaces = proxmox.nodes(node_name).network.get()
|
|
57
|
+
node_ip_address = None
|
|
58
|
+
for iface in ifaces:
|
|
59
|
+
if 'gateway' in iface:
|
|
60
|
+
if node_ip_address is not None:
|
|
61
|
+
raise Exception(f"found multiple ifaces with gateways for node {node_name}")
|
|
62
|
+
node_ip_address = iface.get("address")
|
|
63
|
+
|
|
64
|
+
if node_ip_address is None:
|
|
65
|
+
raise Exception(f"Could not find ip for node {node_name}")
|
|
66
|
+
|
|
67
|
+
dynamic_inventory[args.pve_cloud_domain][cluster_name][node_name] = {
|
|
68
|
+
"ansible_user": "root",
|
|
69
|
+
"ansible_host": node_ip_address
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
with open(inv_path, "w") as file:
|
|
73
|
+
yaml.dump(dynamic_inventory, file)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def main():
|
|
78
|
+
parser = argparse.ArgumentParser(description="PVE general purpose cli for setting up.")
|
|
79
|
+
|
|
80
|
+
base_parser = argparse.ArgumentParser(add_help=False)
|
|
81
|
+
|
|
82
|
+
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
83
|
+
|
|
84
|
+
connect_cluster_parser = subparsers.add_parser("connect-cluster", help="Add an entire pve cluster to this machine for use.", parents=[base_parser])
|
|
85
|
+
connect_cluster_parser.add_argument("--pve-host", type=str, help="PVE Host to connect to and add the entire cluster for the local machine.", required=True)
|
|
86
|
+
# todo: try and get the pve cloud domain from the cluster in case it is already initialized.
|
|
87
|
+
connect_cluster_parser.add_argument("--pve-cloud-domain", type=str, help="PVE Cloud domain the hosts are part of / should be initialized under.", required=True)
|
|
88
|
+
connect_cluster_parser.add_argument("--force", action="store_true", help="Will readd the cluster if set.")
|
|
89
|
+
connect_cluster_parser.set_defaults(func=connect_cluster)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
args = parser.parse_args()
|
|
93
|
+
args.func(args)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
if __name__ == "__main__":
|
|
97
|
+
main()
|
|
@@ -5,12 +5,12 @@ import socket
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def get_cloud_domain(target_pve):
|
|
8
|
-
with open(os.path.expanduser("~/.pve-
|
|
8
|
+
with open(os.path.expanduser("~/.pve-cloud-dyn-inv.yaml"), "r") as f:
|
|
9
9
|
pve_inventory = yaml.safe_load(f)
|
|
10
10
|
|
|
11
11
|
for pve_cloud in pve_inventory:
|
|
12
12
|
for pve_cluster in pve_inventory[pve_cloud]:
|
|
13
|
-
if pve_cluster == target_pve:
|
|
13
|
+
if pve_cluster + "." + pve_cloud == target_pve:
|
|
14
14
|
return pve_cloud
|
|
15
15
|
|
|
16
16
|
raise Exception(f"Could not identify cloud domain for {target_pve}")
|
|
@@ -21,12 +21,12 @@ def get_cld_domain_prsr(args):
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def get_online_pve_host(target_pve):
|
|
24
|
-
with open(os.path.expanduser("~/.pve-
|
|
24
|
+
with open(os.path.expanduser("~/.pve-cloud-dyn-inv.yaml"), "r") as f:
|
|
25
25
|
pve_inventory = yaml.safe_load(f)
|
|
26
26
|
|
|
27
27
|
for pve_cloud in pve_inventory:
|
|
28
28
|
for pve_cluster in pve_inventory[pve_cloud]:
|
|
29
|
-
if pve_cluster == target_pve:
|
|
29
|
+
if pve_cluster + "." + pve_cloud == target_pve:
|
|
30
30
|
for pve_host in pve_inventory[pve_cloud][pve_cluster]:
|
|
31
31
|
# check if host is available
|
|
32
32
|
pve_host_ip = pve_inventory[pve_cloud][pve_cluster][pve_host]["ansible_host"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: py-pve-cloud
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
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,4 +8,5 @@ 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: proxmoxer==2.2.0
|
|
11
12
|
Dynamic: license-file
|
py_pve_cloud-0.0.2/README.md
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/pve_cloud/orm/migrations/versions/3c95509a5de9_fix.py
RENAMED
|
File without changes
|
|
File without changes
|
{py_pve_cloud-0.0.2 → py_pve_cloud-0.0.4}/src/pve_cloud/orm/migrations/versions/7dea8c4ee39f_init.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|