|
|
@ -1,21 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
from app.utils.authorization import token_required
|
|
|
|
from app.utils.authorization import token_required
|
|
|
|
from flask_restplus import Resource, Namespace, fields
|
|
|
|
from flask_restplus import Resource, Namespace, fields
|
|
|
|
from flask import request
|
|
|
|
from flask import request, jsonify
|
|
|
|
import requests
|
|
|
|
import requests
|
|
|
|
import time
|
|
|
|
import time
|
|
|
|
from flask_restx import fields
|
|
|
|
from flask_restx import fields
|
|
|
|
from functools import wraps
|
|
|
|
from functools import wraps
|
|
|
|
import os
|
|
|
|
import os
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
|
|
|
|
|
|
|
|
load_dotenv()
|
|
|
|
load_dotenv()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
api = Namespace('Container', description='Containers creation and manager')
|
|
|
|
api = Namespace('Container', description='Containers creation and manager')
|
|
|
|
|
|
|
|
|
|
|
|
API_BASE_URL = f'https://{os.getenv("PROXMOX_NODE_IP")}:8006/api2/json/nodes/{os.getenv("PROXMOX_NODE_NAME")}/lxc'
|
|
|
|
API_BASE_URL = f'https://{os.getenv("PROXMOX_NODE_IP")}:8006/api2/json/nodes/{os.getenv("PROXMOX_NODE_NAME")}/lxc'
|
|
|
|
|
|
|
|
API_AUTH = f'https://{os.getenv("PROXMOX_NODE_IP")}:8006/api2/json/access/ticket'
|
|
|
|
|
|
|
|
CREDENTIAL = {
|
|
|
|
|
|
|
|
"username": f"{os.getenv('API_USER')}@{os.getenv('PROXMOX_NODE_NAME')}", "password": os.getenv("API_USER_PASSWORD")}
|
|
|
|
|
|
|
|
|
|
|
|
# Use the API token directly
|
|
|
|
|
|
|
|
AUTH_TOKEN_PROXMOX = f'{os.getenv("PROXMOX_USER")}@pve!{os.getenv("PROXMOX_TOKEN_ID_SECRET")}'
|
|
|
|
def get_data(endpoint, data):
|
|
|
|
|
|
|
|
response = requests.post(endpoint, data=data, verify=False)
|
|
|
|
|
|
|
|
response.raise_for_status()
|
|
|
|
|
|
|
|
return response.json()["data"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get ticket and CSRFPreventionToken
|
|
|
|
|
|
|
|
ticket = get_data(API_AUTH, CREDENTIAL)["ticket"]
|
|
|
|
|
|
|
|
csrf_token = get_data(API_AUTH, CREDENTIAL)["CSRFPreventionToken"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Function to retrieve information about all containers
|
|
|
|
|
|
|
|
def list_all_containers():
|
|
|
|
|
|
|
|
endpoint = f"{API_BASE_URL}"
|
|
|
|
|
|
|
|
response = requests.get(
|
|
|
|
|
|
|
|
endpoint, cookies={"PVEAuthCookie": ticket}, verify=False)
|
|
|
|
|
|
|
|
response.raise_for_status()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
containers = response.json()["data"]
|
|
|
|
|
|
|
|
return containers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Function to retrieve information about a specific container by ID
|
|
|
|
|
|
|
|
def get_container_info(container_id):
|
|
|
|
|
|
|
|
endpoint = f"{API_BASE_URL}/{container_id}/config"
|
|
|
|
|
|
|
|
response = requests.get(
|
|
|
|
|
|
|
|
endpoint, cookies={"PVEAuthCookie": ticket}, verify=False)
|
|
|
|
|
|
|
|
response.raise_for_status()
|
|
|
|
|
|
|
|
is_container_locked(container_id)
|
|
|
|
|
|
|
|
container_info = response.json()["data"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return container_info
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Function to check if a container is locked
|
|
|
|
|
|
|
|
def is_container_locked(container_id):
|
|
|
|
|
|
|
|
endpoint = f"{API_BASE_URL}/{container_id}/status/current"
|
|
|
|
|
|
|
|
response = requests.get(
|
|
|
|
|
|
|
|
endpoint, cookies={"PVEAuthCookie": ticket}, verify=False)
|
|
|
|
|
|
|
|
response.raise_for_status()
|
|
|
|
|
|
|
|
if 'lock' in response.json()["data"]:
|
|
|
|
|
|
|
|
return {"locked": True}
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
return {"locked": False}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Decorator for handling exceptions in routes
|
|
|
|
# Decorator for handling exceptions in routes
|
|
|
@ -33,41 +80,6 @@ def handle_exceptions(func):
|
|
|
|
return decorated_function
|
|
|
|
return decorated_function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Function to retrieve information about all containers
|
|
|
|
|
|
|
|
def list_all_containers():
|
|
|
|
|
|
|
|
endpoint = f"{API_BASE_URL}"
|
|
|
|
|
|
|
|
response = requests.get(
|
|
|
|
|
|
|
|
endpoint, headers={"Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, verify=False)
|
|
|
|
|
|
|
|
response.raise_for_status()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
containers = response.json()["data"]
|
|
|
|
|
|
|
|
return containers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Function to retrieve information about a specific container by ID
|
|
|
|
|
|
|
|
def get_container_info(container_id):
|
|
|
|
|
|
|
|
endpoint = f"{API_BASE_URL}/{container_id}/config"
|
|
|
|
|
|
|
|
response = requests.get(
|
|
|
|
|
|
|
|
endpoint, headers={"Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, verify=False)
|
|
|
|
|
|
|
|
response.raise_for_status()
|
|
|
|
|
|
|
|
is_container_locked(container_id)
|
|
|
|
|
|
|
|
container_info = response.json()["data"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return container_info
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Function to check if a container is locked
|
|
|
|
|
|
|
|
def is_container_locked(container_id):
|
|
|
|
|
|
|
|
endpoint = f"{API_BASE_URL}/{container_id}/status/current"
|
|
|
|
|
|
|
|
response = requests.get(
|
|
|
|
|
|
|
|
endpoint, headers={"Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, verify=False)
|
|
|
|
|
|
|
|
response.raise_for_status()
|
|
|
|
|
|
|
|
if 'lock' in response.json()["data"]:
|
|
|
|
|
|
|
|
return {"locked": True}
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
return {"locked": False}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@api.route('/')
|
|
|
|
@api.route('/')
|
|
|
|
class ContainerListAll(Resource):
|
|
|
|
class ContainerListAll(Resource):
|
|
|
|
@api.response(200, "Success")
|
|
|
|
@api.response(200, "Success")
|
|
|
@ -95,25 +107,25 @@ class ContainerId(Resource):
|
|
|
|
@api.doc('some operation', security='apikey')
|
|
|
|
@api.doc('some operation', security='apikey')
|
|
|
|
@token_required
|
|
|
|
@token_required
|
|
|
|
@api.doc(params={'id': 'The container id'},)
|
|
|
|
@api.doc(params={'id': 'The container id'},)
|
|
|
|
@api.doc(params={'command': 'start, stop'},)
|
|
|
|
@api.doc(params={'command': 'start, stop, delete'},)
|
|
|
|
@handle_exceptions
|
|
|
|
@handle_exceptions
|
|
|
|
def get(self, id: int, command: str):
|
|
|
|
def get(self, id: int, command: str):
|
|
|
|
|
|
|
|
|
|
|
|
commands = ['start', 'stop', 'del_test']
|
|
|
|
commands = ['start', 'stop', 'delete']
|
|
|
|
|
|
|
|
|
|
|
|
if (command not in commands):
|
|
|
|
if (command not in commands):
|
|
|
|
return {"error": f"Bad Request: Invalid command passed in your route'{command}'. Valid commands are {', '.join(commands)}"}, 400
|
|
|
|
return {"error": f"Bad Request: Invalid command passed in your route'{command}'. Valid commands are {', '.join(commands)}"}, 400
|
|
|
|
|
|
|
|
|
|
|
|
if command in ["start", "stop"]:
|
|
|
|
if command in ["start", "stop"]:
|
|
|
|
endpoint = f"{API_BASE_URL}/{id}/status/{command}"
|
|
|
|
endpoint = f"{API_BASE_URL}/{id}/status/{command}"
|
|
|
|
response = requests.post(
|
|
|
|
response = requests.post(endpoint, cookies={"PVEAuthCookie": ticket}, headers={
|
|
|
|
endpoint, headers={"Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, verify=False)
|
|
|
|
"CSRFPreventionToken": csrf_token}, verify=False)
|
|
|
|
response.raise_for_status()
|
|
|
|
response.raise_for_status()
|
|
|
|
|
|
|
|
|
|
|
|
elif command == "del_test":
|
|
|
|
elif command == "delete":
|
|
|
|
endpoint = f"{API_BASE_URL}/{id}"
|
|
|
|
endpoint = f"{API_BASE_URL}/{id}"
|
|
|
|
response = requests.delete(endpoint, headers={
|
|
|
|
response = requests.delete(endpoint, cookies={"PVEAuthCookie": ticket}, headers={
|
|
|
|
"Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, verify=False)
|
|
|
|
"CSRFPreventionToken": csrf_token}, verify=False)
|
|
|
|
response.raise_for_status()
|
|
|
|
response.raise_for_status()
|
|
|
|
|
|
|
|
|
|
|
|
return {'message': 'success'}, 200
|
|
|
|
return {'message': 'success'}, 200
|
|
|
@ -123,7 +135,7 @@ class ContainerId(Resource):
|
|
|
|
class ContainerIdEdit(Resource):
|
|
|
|
class ContainerIdEdit(Resource):
|
|
|
|
|
|
|
|
|
|
|
|
payload_model = api.model('ContainerEditModel', {
|
|
|
|
payload_model = api.model('ContainerEditModel', {
|
|
|
|
"nameserver": fields.String(example="8.8.8.8,8.8.4.4"),
|
|
|
|
"nameserver": fields.String(example="8.8.8.8,4.4.4.4"),
|
|
|
|
"searchdomain": fields.String(example="hittelco.com.br"),
|
|
|
|
"searchdomain": fields.String(example="hittelco.com.br"),
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
@ -136,8 +148,8 @@ class ContainerIdEdit(Resource):
|
|
|
|
def put(self, id: int):
|
|
|
|
def put(self, id: int):
|
|
|
|
data = request.json
|
|
|
|
data = request.json
|
|
|
|
endpoint = f"{API_BASE_URL}/{id}/config"
|
|
|
|
endpoint = f"{API_BASE_URL}/{id}/config"
|
|
|
|
response = requests.put(endpoint, headers={
|
|
|
|
response = requests.put(endpoint, cookies={"PVEAuthCookie": ticket}, headers={
|
|
|
|
"Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, data=data, verify=False)
|
|
|
|
"CSRFPreventionToken": csrf_token}, data=data, verify=False)
|
|
|
|
response.raise_for_status()
|
|
|
|
response.raise_for_status()
|
|
|
|
|
|
|
|
|
|
|
|
return {'message': 'success'}, 200
|
|
|
|
return {'message': 'success'}, 200
|
|
|
@ -151,17 +163,17 @@ class ContainerCreateUp(Resource):
|
|
|
|
"ostemplate": fields.String(example="local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst"),
|
|
|
|
"ostemplate": fields.String(example="local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst"),
|
|
|
|
"storage": fields.String(example="local"),
|
|
|
|
"storage": fields.String(example="local"),
|
|
|
|
"cores": fields.String(example="1"),
|
|
|
|
"cores": fields.String(example="1"),
|
|
|
|
"pool": fields.String(example='desenvolvimento'),
|
|
|
|
|
|
|
|
"cpuunits": fields.String(example="512"),
|
|
|
|
"cpuunits": fields.String(example="512"),
|
|
|
|
"memory": fields.String(example="512"),
|
|
|
|
"memory": fields.String(example="512"),
|
|
|
|
"swap": fields.String(example="0"),
|
|
|
|
"swap": fields.String(example="0"),
|
|
|
|
"password": fields.String(example="88325936"),
|
|
|
|
"password": fields.String(example="91472432"),
|
|
|
|
"hostname": fields.String(example="ctnodeapi"),
|
|
|
|
"hostname": fields.String(example="ctnodeapi"),
|
|
|
|
"nameserver": fields.String(example="8.8.8.8,8.8.4.4"),
|
|
|
|
"nameserver": fields.String(example="8.8.8.8,4.4.4.4"),
|
|
|
|
"searchdomain": fields.String(example="hittelco.com.br"),
|
|
|
|
"searchdomain": fields.String(example="hittelco.com.br"),
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
@api.response(201, "Success")
|
|
|
|
@api.response(201, "Success")
|
|
|
|
|
|
|
|
|
|
|
|
@api.doc('some operation', security='apikey')
|
|
|
|
@api.doc('some operation', security='apikey')
|
|
|
|
@token_required
|
|
|
|
@token_required
|
|
|
|
@api.expect(payload_model, validate=True)
|
|
|
|
@api.expect(payload_model, validate=True)
|
|
|
@ -199,20 +211,20 @@ class ContainerCreateUp(Resource):
|
|
|
|
|
|
|
|
|
|
|
|
# Create container
|
|
|
|
# Create container
|
|
|
|
endpoint = f"{API_BASE_URL}"
|
|
|
|
endpoint = f"{API_BASE_URL}"
|
|
|
|
response = requests.post(endpoint, headers={
|
|
|
|
response = requests.post(endpoint, cookies={"PVEAuthCookie": ticket}, headers={
|
|
|
|
"Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, data=data, verify=False)
|
|
|
|
"CSRFPreventionToken": csrf_token}, data=data, verify=False)
|
|
|
|
response.raise_for_status()
|
|
|
|
response.raise_for_status()
|
|
|
|
print(f'Container id {vm_id} created!')
|
|
|
|
print(f'Container id {vm_id} created!')
|
|
|
|
|
|
|
|
|
|
|
|
# Check each 3 seconds if the container is locked before start
|
|
|
|
# Check each 3 seconds if the container is locked before start
|
|
|
|
while is_container_locked(vm_id)['locked']:
|
|
|
|
while is_container_locked(vm_id)['locked']:
|
|
|
|
print('*********** LOCKED ************')
|
|
|
|
print('*********** LOCKED ************')
|
|
|
|
time.sleep(8)
|
|
|
|
time.sleep(5)
|
|
|
|
|
|
|
|
|
|
|
|
# Start container
|
|
|
|
# Start container
|
|
|
|
endpoint = f"{API_BASE_URL}/{vm_id}/status/start"
|
|
|
|
endpoint = f"{API_BASE_URL}/{vm_id}/status/start"
|
|
|
|
response = requests.post(endpoint, headers={
|
|
|
|
response = requests.post(endpoint, cookies={"PVEAuthCookie": ticket}, headers={
|
|
|
|
"Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, verify=False)
|
|
|
|
"CSRFPreventionToken": csrf_token}, verify=False)
|
|
|
|
response.raise_for_status()
|
|
|
|
response.raise_for_status()
|
|
|
|
print(f'Container id {vm_id} started!')
|
|
|
|
print(f'Container id {vm_id} started!')
|
|
|
|
|
|
|
|
|
|
|
@ -227,14 +239,13 @@ class ContainerCreate(Resource):
|
|
|
|
"ostemplate": fields.String(example="local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst"),
|
|
|
|
"ostemplate": fields.String(example="local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst"),
|
|
|
|
"storage": fields.String(example="local"),
|
|
|
|
"storage": fields.String(example="local"),
|
|
|
|
"vmid": fields.String(example="538"),
|
|
|
|
"vmid": fields.String(example="538"),
|
|
|
|
"pool": fields.String(example='desenvolvimento'),
|
|
|
|
|
|
|
|
"cores": fields.String(example="1"),
|
|
|
|
"cores": fields.String(example="1"),
|
|
|
|
"cpuunits": fields.String(example="512"),
|
|
|
|
"cpuunits": fields.String(example="512"),
|
|
|
|
"memory": fields.String(example="512"),
|
|
|
|
"memory": fields.String(example="512"),
|
|
|
|
"swap": fields.String(example="0"),
|
|
|
|
"swap": fields.String(example="0"),
|
|
|
|
"password": fields.String(example="988325936"),
|
|
|
|
"password": fields.String(example="988325936"),
|
|
|
|
"hostname": fields.String(example="ctnodeapi538"),
|
|
|
|
"hostname": fields.String(example="ctnodeapi538"),
|
|
|
|
"nameserver": fields.String(example="8.8.8.8,8.8.4.4"),
|
|
|
|
"nameserver": fields.String(example="8.8.8.8,4.4.4.4"),
|
|
|
|
"searchdomain": fields.String(example="hittelco.com.br"),
|
|
|
|
"searchdomain": fields.String(example="hittelco.com.br"),
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
@ -251,7 +262,7 @@ class ContainerCreate(Resource):
|
|
|
|
data[key] = int(value)
|
|
|
|
data[key] = int(value)
|
|
|
|
|
|
|
|
|
|
|
|
endpoint = f"{API_BASE_URL}"
|
|
|
|
endpoint = f"{API_BASE_URL}"
|
|
|
|
response = requests.post(endpoint, headers={
|
|
|
|
response = requests.post(endpoint, cookies={"PVEAuthCookie": ticket}, headers={
|
|
|
|
"Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, data=data, verify=False)
|
|
|
|
"CSRFPreventionToken": csrf_token}, data=data, verify=False)
|
|
|
|
response.raise_for_status()
|
|
|
|
response.raise_for_status()
|
|
|
|
return {'message': 'success'}, 201
|
|
|
|
return {'message': 'success'}, 201
|
|
|
|