Compare commits

...

5 Commits

4 changed files with 67 additions and 77 deletions

View File

@ -1,5 +1,5 @@
PROXMOX_NODE_IP=192.168.0.186 PROXMOX_NODE_IP=192.168.0.186
PROXMOX_NODE_NAME=pve PROXMOX_NODE_NAME=pve
API_USER=api PROXMOX_USER=api
API_USER_PASSWORD= PROXMOX_TOKEN_ID_SECRET=tokenUserAPI=c95fd56a-c915-49b5-86d2-a0c99e11f167
TOKEN= TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxx

1
.gitignore vendored
View File

@ -109,6 +109,7 @@ venv/
ENV/ ENV/
env.bak/ env.bak/
venv.bak/ venv.bak/
env_proxmox_api/
# Spyder project settings # Spyder project settings
.spyderproject .spyderproject

View File

@ -20,7 +20,7 @@ authorizations = {
api = Api(app, api = Api(app,
title='Proxmox container rest API', title='Proxmox container rest API',
version='1.0', version='1.0',
description='The Proxmox Container Management API allows users to interact with Proxmox using its REST API for container management. Key functionalities include creating, updating, editing, deleting, and retrieving information about containers.', description='The Proxmox Container Management API allows users to interact with Proxmox using its REST API for container management. Key functionalities include creating, updating, editing and retrieving information about containers.',
prefix='/api', prefix='/api',
authorizations=authorizations, authorizations=authorizations,
security='apiKey') security='apiKey')

View File

@ -1,68 +1,21 @@
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, jsonify from flask import request
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
def get_data(endpoint, data): AUTH_TOKEN_PROXMOX = f'{os.getenv("PROXMOX_USER")}@pve!{os.getenv("PROXMOX_TOKEN_ID_SECRET")}'
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
@ -80,6 +33,41 @@ 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")
@ -107,25 +95,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, delete'},) @api.doc(params={'command': 'start, stop'},)
@handle_exceptions @handle_exceptions
def get(self, id: int, command: str): def get(self, id: int, command: str):
commands = ['start', 'stop', 'delete'] commands = ['start', 'stop', 'del_test']
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(endpoint, cookies={"PVEAuthCookie": ticket}, headers={ response = requests.post(
"CSRFPreventionToken": csrf_token}, verify=False) endpoint, headers={"Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, verify=False)
response.raise_for_status() response.raise_for_status()
elif command == "delete": elif command == "del_test":
endpoint = f"{API_BASE_URL}/{id}" endpoint = f"{API_BASE_URL}/{id}"
response = requests.delete(endpoint, cookies={"PVEAuthCookie": ticket}, headers={ response = requests.delete(endpoint, headers={
"CSRFPreventionToken": csrf_token}, verify=False) "Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, verify=False)
response.raise_for_status() response.raise_for_status()
return {'message': 'success'}, 200 return {'message': 'success'}, 200
@ -135,7 +123,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,4.4.4.4"), "nameserver": fields.String(example="8.8.8.8,8.8.4.4"),
"searchdomain": fields.String(example="hittelco.com.br"), "searchdomain": fields.String(example="hittelco.com.br"),
}) })
@ -148,8 +136,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, cookies={"PVEAuthCookie": ticket}, headers={ response = requests.put(endpoint, headers={
"CSRFPreventionToken": csrf_token}, data=data, verify=False) "Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, data=data, verify=False)
response.raise_for_status() response.raise_for_status()
return {'message': 'success'}, 200 return {'message': 'success'}, 200
@ -163,17 +151,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="91472432"), "password": fields.String(example="88325936"),
"hostname": fields.String(example="ctnodeapi"), "hostname": fields.String(example="ctnodeapi"),
"nameserver": fields.String(example="8.8.8.8,4.4.4.4"), "nameserver": fields.String(example="8.8.8.8,8.8.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)
@ -211,20 +199,20 @@ class ContainerCreateUp(Resource):
# Create container # Create container
endpoint = f"{API_BASE_URL}" endpoint = f"{API_BASE_URL}"
response = requests.post(endpoint, cookies={"PVEAuthCookie": ticket}, headers={ response = requests.post(endpoint, headers={
"CSRFPreventionToken": csrf_token}, data=data, verify=False) "Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, 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(5) time.sleep(8)
# 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, cookies={"PVEAuthCookie": ticket}, headers={ response = requests.post(endpoint, headers={
"CSRFPreventionToken": csrf_token}, verify=False) "Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, verify=False)
response.raise_for_status() response.raise_for_status()
print(f'Container id {vm_id} started!') print(f'Container id {vm_id} started!')
@ -239,13 +227,14 @@ 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,4.4.4.4"), "nameserver": fields.String(example="8.8.8.8,8.8.4.4"),
"searchdomain": fields.String(example="hittelco.com.br"), "searchdomain": fields.String(example="hittelco.com.br"),
}) })
@ -262,7 +251,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, cookies={"PVEAuthCookie": ticket}, headers={ response = requests.post(endpoint, headers={
"CSRFPreventionToken": csrf_token}, data=data, verify=False) "Authorization": f"PVEAPIToken={AUTH_TOKEN_PROXMOX}"}, data=data, verify=False)
response.raise_for_status() response.raise_for_status()
return {'message': 'success'}, 201 return {'message': 'success'}, 201