init
commit
3f19cfc745
|
@ -0,0 +1 @@
|
|||
/venv/
|
|
@ -0,0 +1,92 @@
|
|||
from proxmoxer import ProxmoxAPI
|
||||
import yaml
|
||||
import os.path
|
||||
import urllib.request
|
||||
|
||||
|
||||
with open('vars.yaml') as data:
|
||||
vars_dict = yaml.safe_load(data)
|
||||
|
||||
# параметры хоста Proxmox
|
||||
proxmox_node = vars_dict['proxmox_node']['name']
|
||||
pve_host = vars_dict['proxmox_node']['host']
|
||||
pve_port = vars_dict['proxmox_node']['port']
|
||||
pve_admin = vars_dict['proxmox_node']['username']
|
||||
pve_passwd = vars_dict['proxmox_node']['password']
|
||||
pve_storage = vars_dict['proxmox_node']['storage']
|
||||
pve_net = vars_dict['proxmox_node']['net']
|
||||
|
||||
# параметры создаваемого шаблона
|
||||
tmpl_id = vars_dict['template']['id']
|
||||
tmpl_name = vars_dict['template']['name']
|
||||
tmpl_cores = vars_dict['template']['cores']
|
||||
tmpl_memory = vars_dict['template']['memory']
|
||||
tmpl_user = vars_dict['template']['username']
|
||||
tmpl_passwd = vars_dict['template']['password']
|
||||
|
||||
# ссылка на образ
|
||||
img_url = vars_dict['img']['url']
|
||||
img_name = vars_dict['img']['name']
|
||||
|
||||
|
||||
def download_img(name, url):
|
||||
"""
|
||||
Проверка наличия образа в текущей директории.
|
||||
Если образа нет, он скачивается.
|
||||
|
||||
Params:
|
||||
name - (str), имя образа;
|
||||
url - (str), url-ссылка на директорию с образом.
|
||||
|
||||
Return:
|
||||
None
|
||||
"""
|
||||
if os.path.isfile(name):
|
||||
print(f'Файл с именем "{name}" присутствует в текущей директории')
|
||||
else:
|
||||
print(f'Образа "{name}" нет в текущей директории, скачиваю..')
|
||||
urllib.request.urlretrieve(f'{url}/{name}', name)
|
||||
print('Скачивание завершено.')
|
||||
|
||||
|
||||
def create_vm(node, **kwargs):
|
||||
"""
|
||||
Создание шаблона ВМ из ранее скачанного образа.
|
||||
|
||||
Params:
|
||||
node - (class 'proxmoxer.core.ProxmoxResource'), хост Proxmox,
|
||||
на котором создаётся шаблон.
|
||||
|
||||
Return:
|
||||
None
|
||||
"""
|
||||
node.qemu.create(
|
||||
vmid=tmpl_id, name=tmpl_name, cores=tmpl_cores, memory=tmpl_memory,
|
||||
net0=f'virtio,bridge={pve_net}', bootdisk='scsi0',
|
||||
ide0=f'{pve_storage}:cloudinit', ide2='none,media=cdrom', vga='qxl',
|
||||
ciuser=tmpl_user, cipassword=tmpl_passwd, agent=1)
|
||||
|
||||
|
||||
def importdisk(node, img, stor, **kwargs):
|
||||
"""
|
||||
Импорт образа в ВМ.
|
||||
|
||||
Params:
|
||||
node - (class 'proxmoxer.core.ProxmoxResource'), хост Proxmox,
|
||||
на котором создаётся шаблон.
|
||||
|
||||
Return:
|
||||
None
|
||||
"""
|
||||
node.qemu.importdisk(img, stor)
|
||||
|
||||
|
||||
proxmox = ProxmoxAPI(host=pve_host, user=pve_admin, password=pve_passwd, port=pve_port, verify_ssl=True)
|
||||
pve_node = proxmox.nodes(proxmox_node)
|
||||
|
||||
|
||||
# download_img(name=img_name, url=img_url)
|
||||
# create_vm(node=pve_node)
|
||||
# importdisk(node=pve_node, img=img_name, stor=pve_storage)
|
||||
|
||||
pve_node.qemu(f'disk import {tmpl_id} {img_name} {pve_storage},format=qcow2')
|
|
@ -0,0 +1,70 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
from pprint import pprint
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
with open('vars.yaml') as data:
|
||||
vars_dict = yaml.safe_load(data)
|
||||
|
||||
|
||||
def shell_run(cmd):
|
||||
"""
|
||||
Выполнение shell команды.
|
||||
|
||||
:param cmd: (str), команда.
|
||||
:return: proc.stdout: (subprocess object), вывод команды
|
||||
proc.stderr: (subprocess object), код завершения.
|
||||
"""
|
||||
proc = subprocess.run(
|
||||
cmd.split(), capture_output=True, text=True, timeout=60)
|
||||
if proc.stderr:
|
||||
print(f'Команда - "{cmd}"')
|
||||
print(proc.stderr)
|
||||
exit(1)
|
||||
return proc.stdout, proc.stderr
|
||||
|
||||
|
||||
def gen_vm_commands(all_dict):
|
||||
"""
|
||||
Генерация списка команд для создания группировки ВМ ALD Pro.
|
||||
:param all_dict: (dict), словарь с переменными для генерации.
|
||||
:return: (dict), словарь списков команд.
|
||||
"""
|
||||
tmpl_id = all_dict['template']['id']
|
||||
gw = all_dict['proxmox_node']['vmbr_gw']
|
||||
commands = {}
|
||||
for vm in vars_dict['vms']:
|
||||
vm_cmds = [f'qm clone {tmpl_id} {vm["id"]} --name {vm["name"]} --full',
|
||||
f'qm set {vm["id"]} --ipconfig0 ip={vm["ip"]}/24,gw={gw}',
|
||||
f'qm resize {vm["id"]} scsi0 32G']
|
||||
if vm["name"] == 'dc01' or vm["name"] == 'dc02':
|
||||
vm_cmds.append(f'qm set {vm["id"]} --cores 4 --memory 8192')
|
||||
vm_cmds.remove(f'qm resize {vm["id"]} scsi0 32G')
|
||||
vm_cmds.append(f'qm resize {vm["id"]} scsi0 64G')
|
||||
elif vm["name"] == 'repo':
|
||||
vm_cmds.remove(f'qm resize {vm["id"]} scsi0 32G')
|
||||
vm_cmds.append(f'qm resize {vm["id"]} scsi0 64G')
|
||||
commands.update({vm["name"]: vm_cmds})
|
||||
return commands
|
||||
|
||||
|
||||
def create_vms(commands_dict):
|
||||
"""
|
||||
Создание группировки ВМ ALD Pro.
|
||||
|
||||
:param commands_dict: (dict), словарь списков команд для создания ВМ.
|
||||
:return: None
|
||||
"""
|
||||
for role in commands_dict.items():
|
||||
print(f'Создаётся ВМ - {role[0]}')
|
||||
for cmd in role[1]:
|
||||
shell_run(cmd)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cmds = gen_vm_commands(vars_dict)
|
||||
create_vms(cmds)
|
||||
# pprint(cmds)
|
|
@ -0,0 +1,105 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
import urllib.request
|
||||
|
||||
|
||||
with open('vars.yaml') as data:
|
||||
vars_dict = yaml.safe_load(data)
|
||||
|
||||
# параметры хоста Proxmox
|
||||
proxmox_node = vars_dict['proxmox_node']['name']
|
||||
pve_host = vars_dict['proxmox_node']['host']
|
||||
pve_port = vars_dict['proxmox_node']['port']
|
||||
pve_admin = vars_dict['proxmox_node']['username']
|
||||
pve_passwd = vars_dict['proxmox_node']['password']
|
||||
pve_storage = vars_dict['proxmox_node']['storage']
|
||||
pve_vmbr = vars_dict['proxmox_node']['vmbr']
|
||||
|
||||
# параметры создаваемого шаблона
|
||||
tmpl_id = vars_dict['template']['id']
|
||||
tmpl_name = vars_dict['template']['name']
|
||||
tmpl_cores = vars_dict['template']['cores']
|
||||
tmpl_memory = vars_dict['template']['memory']
|
||||
tmpl_user = vars_dict['template']['username']
|
||||
tmpl_passwd = vars_dict['template']['password']
|
||||
|
||||
# ссылка на образ
|
||||
img_url = vars_dict['img']['url']
|
||||
img_name = vars_dict['img']['name']
|
||||
|
||||
|
||||
def download_img(name, url):
|
||||
"""
|
||||
Проверка наличия образа в текущей директории.
|
||||
Если образа нет, он скачивается.
|
||||
|
||||
:param name: (str), имя образа;
|
||||
:param url: (str), url-ссылка на директорию с образом.
|
||||
:return: None.
|
||||
"""
|
||||
if Path(name).is_file():
|
||||
print(f'Файл с именем "{name}" присутствует в текущей директории')
|
||||
else:
|
||||
print(f'Образа "{name}" нет в текущей директории, скачиваю..')
|
||||
urllib.request.urlretrieve(f'{url}/{name}', name)
|
||||
print('Скачивание завершено.')
|
||||
|
||||
|
||||
def del_img(name):
|
||||
"""
|
||||
Удаление образа из текущей директории.
|
||||
|
||||
:param name: (str), имя образа.
|
||||
:return: None
|
||||
"""
|
||||
if Path(name).is_file():
|
||||
proc = subprocess.run(f'rm -rf {name}'.split(), capture_output=True, text=True)
|
||||
print(f'Образ "{name}" удалён из текущей директории')
|
||||
if proc.stderr:
|
||||
print(f'Команда - "rm -rf {name}"')
|
||||
print(proc.stderr)
|
||||
exit(1)
|
||||
else:
|
||||
print(f'Образа "{name}" нет в текущей директории, скачиваю..')
|
||||
|
||||
|
||||
def deploy_template(list_commands):
|
||||
"""
|
||||
Функция поочерёдно выполняет shell команды, переданные списком.
|
||||
|
||||
:param list_commands: (list), список команд, которые необходимо выполнить.
|
||||
:return: None
|
||||
"""
|
||||
print(f'Создаю шаблон ВМ из образа')
|
||||
for com in list_commands:
|
||||
proc = subprocess.run(com.split(), capture_output=True, text=True)
|
||||
if proc.stderr:
|
||||
print(f'Команда - "{com}"')
|
||||
print(proc.stderr)
|
||||
exit(1)
|
||||
# else:
|
||||
# print(proc.stdout)
|
||||
print('Шаблон создан.')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# в зависимости от типа и нахождения хранилища
|
||||
# путь к создаваемому в процессе импорта диску указывается по-разному
|
||||
# см. в WEB-интерфейсе примеры с других ВМ
|
||||
commands = [f'qm create {tmpl_id} --name {tmpl_name}',
|
||||
f'qm set {tmpl_id} --memory {tmpl_memory} --cores {tmpl_cores}',
|
||||
f'qm set {tmpl_id} --net0 virtio,bridge={pve_vmbr} --scsihw virtio-scsi-pci',
|
||||
f'qm disk import {tmpl_id} {img_name} {pve_storage} --format qcow2',
|
||||
f'qm set {tmpl_id} --scsi0 {pve_storage}:{tmpl_id}/vm-{tmpl_id}-disk-0.qcow2',
|
||||
f'qm set {tmpl_id} --bootdisk scsi0',
|
||||
f'qm set {tmpl_id} --ide0 {pve_storage}:cloudinit --ide2 none,media=cdrom',
|
||||
f'qm set {tmpl_id} --vga qxl --agent 1',
|
||||
f'qm set {tmpl_id} --ciuser={tmpl_user} --cipassword={tmpl_passwd}',
|
||||
f'qm template {tmpl_id}']
|
||||
|
||||
download_img(img_name, img_url)
|
||||
deploy_template(commands)
|
||||
del_img(img_name)
|
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
proxmox_node:
|
||||
name: pve
|
||||
ip: 192.168.13.19
|
||||
host: pve.da2001.ru
|
||||
port: 443
|
||||
username: root@pam
|
||||
password: KatIrina1
|
||||
storage: testvms
|
||||
vmbr: vmbr1
|
||||
vmbr_gw: 10.1.1.9
|
||||
|
||||
template:
|
||||
name: alse-1703-cloudinit-template
|
||||
id: 400
|
||||
cores: 2
|
||||
memory: 2048
|
||||
username: sysadmin
|
||||
password: KatIrina1
|
||||
|
||||
img:
|
||||
name: alse-vanilla-1.7.3-cloud-max-mg9.1.2.qcow2
|
||||
url: https://vault.astralinux.ru/images/alse/cloud
|
||||
|
||||
vms:
|
||||
- name: dc01
|
||||
id: 401
|
||||
ip: 10.1.1.11
|
||||
- name: dc02
|
||||
id: 402
|
||||
ip: 10.1.1.12
|
||||
- name: repo
|
||||
id: 403
|
||||
ip: 10.1.1.13
|
||||
- name: dhcp
|
||||
id: 404
|
||||
ip: 10.1.1.14
|
||||
- name: pxe
|
||||
id: 405
|
||||
ip: 10.1.1.15
|
||||
- name: nas
|
||||
id: 406
|
||||
ip: 10.1.1.16
|
||||
- name: monitoring
|
||||
id: 407
|
||||
ip: 10.1.1.17
|
||||
- name: printserver
|
||||
id: 408
|
||||
ip: 10.1.1.18
|
Loading…
Reference in New Issue