siteconf
This commit is contained in:
parent
cd4914ed55
commit
def708e271
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
__pycache__
|
||||
213
etalon
Executable file
213
etalon
Executable file
@ -0,0 +1,213 @@
|
||||
#!/usr/bin/perl
|
||||
use strict; use warnings; use utf8;
|
||||
use FindBin;
|
||||
use lib $FindBin::Bin;
|
||||
binmode STDOUT, ':utf8';
|
||||
binmode STDERR, ':utf8';
|
||||
use Getopt::Long qw(:config no_ignore_case bundling);
|
||||
use siteconf;
|
||||
|
||||
my %site_conf = siteconf::read;
|
||||
|
||||
my %opts = (
|
||||
tmpmask => 24,
|
||||
tmpip_skip => 0,
|
||||
nodeploy => 0,
|
||||
netmask => 24,
|
||||
nouzem => 0,
|
||||
noweb => 0,
|
||||
nomysql => 0,
|
||||
noreboot => 0
|
||||
);
|
||||
my $usage = <<EOT;
|
||||
usage: $0 [OPTIONS..]
|
||||
--site SITE vmware site (IP, DNS beállítások)
|
||||
--clone-ip IP friss klón IP címe, default site_conf szerint
|
||||
--tmpip IP ideiglenes IP cím az etalon készítés idejére
|
||||
--tmpmask NNN ideiglenes címhez prefix hossz, default: 24
|
||||
--tmpgw ideiglenes címhez default gw, default: .254
|
||||
--tmpip-skip egyből az ideiglenes címet használja, nem állítja be
|
||||
--nodeploy nincs hostnév és IP cím változtatás, vagy:
|
||||
--hostname HH
|
||||
--domain DOMAIN default site_conf szerint
|
||||
--dns DNS[+DNS] default site_conf szerint
|
||||
XXX--ntp NTPSERVER default site_conf szerint
|
||||
--ip IP
|
||||
--netmask NNN lehet prefix-length is (default: 24)
|
||||
--gw GW default: .254
|
||||
--datasize NNN /data mérete (`lvcreate -L` kapja) default: 50%FREE
|
||||
--nouzem
|
||||
--noweb
|
||||
--nomysql
|
||||
--mysql-root PWD mysql root jelszó, default: random
|
||||
--border PREFIX installálj BORDERt (web + db localhost)
|
||||
--border-db PREFIX .. de csak az adatbázisát
|
||||
--border-web PREFIX .. de csak a webes részét
|
||||
--border-dbpasswd PWD BORDER db jelszó, default: random
|
||||
--border-web-dbhost HH db szerver hostnév \\_ /etc/hosts-ba kerül
|
||||
--border-web-dbip HH db szerver IP cím /
|
||||
--noreboot
|
||||
EOT
|
||||
|
||||
GetOptions(
|
||||
"site=s" => \$opts{site},
|
||||
"clone-ip=s" => \$opts{clone_ip},
|
||||
"tmpip=s" => \$opts{tmpip},
|
||||
"tmpmask=s" => \$opts{tmpmask},
|
||||
"tmpgw=s" => \$opts{tmpgw},
|
||||
"tmpip-skip" => \$opts{tmpip_skip},
|
||||
"nodeploy" => \$opts{nodeploy},
|
||||
"hostname=s" => \$opts{hostname},
|
||||
"domain=s" => \$opts{domain},
|
||||
"dns=s" => \$opts{dns},
|
||||
"ntp=s" => \$opts{ntp},
|
||||
"ip=s" => \$opts{ip},
|
||||
"netmask=s" => \$opts{netmask},
|
||||
"gw=s" => \$opts{gw},
|
||||
"datasize=s" => \$opts{datasize},
|
||||
"nouzem" => \$opts{nouzem},
|
||||
"noweb" => \$opts{noweb},
|
||||
"nomysql" => \$opts{nomysql},
|
||||
"mysql-root=s" => \$opts{mysql_root},
|
||||
"border=s" => \$opts{border},
|
||||
"border-db=s" => \$opts{border_db},
|
||||
"border-web=s" => \$opts{border_web},
|
||||
"border-web-dbhost=s" => \$opts{border_web_dbhost},
|
||||
"border-web-dbip=s" => \$opts{border_web_dbip},
|
||||
"border-dbpasswd=s" => \$opts{border_dbpasswd},
|
||||
"noreboot" => \$opts{noreboot},
|
||||
"help|h" => sub {print $usage; exit 0}
|
||||
) or die $usage;
|
||||
|
||||
if (!defined $opts{site}) {
|
||||
die "Kell --site.\n";
|
||||
}
|
||||
if (!exists $site_conf{$opts{site}}) {
|
||||
die "site not found: $opts{site}\n";
|
||||
}
|
||||
for my $o (qw(dns ntp domain clone_ip mgmt_ssh_key postfix_relayhost)) {
|
||||
if (!defined $opts{$o}) {
|
||||
$opts{$o} = $site_conf{$opts{site}}->{$o};
|
||||
}
|
||||
}
|
||||
|
||||
chdir("$FindBin::Bin/..") or die "chdir() failed.\n";
|
||||
|
||||
my @vars;
|
||||
my @skip;
|
||||
|
||||
if ($site_conf{$opts{site}}->{aptproxy}) {
|
||||
push @vars, "aptproxy=$site_conf{$opts{site}}->{aptproxy}";
|
||||
}
|
||||
|
||||
my $border_opts = 0;
|
||||
for my $x ($opts{border}, $opts{border_web}, $opts{border_db}) {
|
||||
$border_opts++ if $x;
|
||||
}
|
||||
die "Csak egy --border... opciót lehet egyszerre megadni\n" if $border_opts > 1;
|
||||
|
||||
if ($opts{border}) {
|
||||
if ($opts{noweb} or $opts{nomysql}) {
|
||||
die "--border opcióhoz kell web és mysql.\n";
|
||||
}
|
||||
push @vars, "border_prefix=$opts{border}";
|
||||
} elsif ($opts{border_web}) {
|
||||
die "Kell web.\n" if $opts{noweb};
|
||||
die "Kell --mysql-root.\n" if !defined $opts{mysql_root};
|
||||
die "Kell dbhost.\n" if !defined $opts{border_web_dbhost};
|
||||
die "Kell dbip.\n" if !defined $opts{border_web_dbip};
|
||||
die "Kell dbpasswd.\n" if !defined $opts{border_dbpasswd};
|
||||
push @vars, "border_prefix=$opts{border_web}";
|
||||
push @vars, "border_install_webonly=1";
|
||||
push @vars, "border_dbhost=$opts{border_web_dbhost}";
|
||||
push @vars, "border_dbip=$opts{border_web_dbip}";
|
||||
} elsif ($opts{border_db}) {
|
||||
die "Kell mysql.\n" if $opts{nomysql};
|
||||
die "Kell --mysql-root.\n" if !defined $opts{mysql_root};
|
||||
die "Kell dbpasswd.\n" if !defined $opts{border_dbpasswd};
|
||||
push @vars, "border_prefix=$opts{border_db}";
|
||||
push @vars, "border_install_dbonly=1";
|
||||
} else {
|
||||
push @skip, 'border';
|
||||
}
|
||||
|
||||
if (!$opts{nodeploy}) {
|
||||
die "Missing --hostname.\n" if !defined $opts{hostname};
|
||||
die "Missing --ip.\n" if !defined $opts{ip};
|
||||
if (!defined $opts{gw}) {
|
||||
$opts{gw} = $opts{ip};
|
||||
$opts{gw} =~ s/\.\d+$/.254/;
|
||||
}
|
||||
for my $x (qw(hostname domain dns ntp ip netmask gw)) {
|
||||
push @vars, "$x=$opts{$x}";
|
||||
}
|
||||
}
|
||||
if ($opts{datasize}) {
|
||||
push @vars, "datasize=$opts{datasize}";
|
||||
}
|
||||
if ($opts{mysql_root}) {
|
||||
push @vars, "mysql_root=$opts{mysql_root}";
|
||||
}
|
||||
if ($opts{border_dbpasswd}) {
|
||||
push @vars, "border_dbpasswd=$opts{border_dbpasswd}";
|
||||
}
|
||||
if ($opts{postfix_relayhost}) {
|
||||
push @vars, "postfix_relayhost=$opts{postfix_relayhost}";
|
||||
}
|
||||
|
||||
if ($opts{tmpip}) {
|
||||
if (!$opts{tmpip_skip}) {
|
||||
if (!defined $opts{tmpgw}) {
|
||||
$opts{tmpgw} = $opts{tmpip};
|
||||
$opts{tmpgw} =~ s/\.\d+$/.254/;
|
||||
}
|
||||
my $cmd = "ansible -i etalon-debian, -e ansible_host=$opts{clone_ip} ".
|
||||
"-u root -B 30 -P 0 -m shell -a '".
|
||||
"sleep 3; DEV=\$(cd /sys/class/net; \\ls -1d e* | head -1);".
|
||||
"ip a flu dev \$DEV; ".
|
||||
"ip a add $opts{tmpip}/$opts{tmpmask} dev \$DEV; ".
|
||||
"ip r add default via $opts{tmpgw}; ".
|
||||
"ping -c 3 $opts{tmpgw}".
|
||||
"' etalon-debian";
|
||||
print "$cmd\n";
|
||||
system $cmd;
|
||||
exit 1 if $? > 0;
|
||||
print "New IP address: $opts{tmpip}.\n";
|
||||
sleep 5;
|
||||
}
|
||||
push @vars, "ansible_host=$opts{tmpip}";
|
||||
}
|
||||
|
||||
my $vars = '';
|
||||
for my $v (@vars) {
|
||||
if ($v =~ /[\s'"]/) {
|
||||
die "invalid character: '$v'.\n";
|
||||
}
|
||||
$vars .= " -e '$v'";
|
||||
}
|
||||
|
||||
if ($opts{mgmt_ssh_key}) {
|
||||
# szokoz van benne: -e 'aaa="bb cc"'
|
||||
$vars .= " -e 'mgmt_ssh_key=\"$opts{mgmt_ssh_key}\"'";
|
||||
}
|
||||
|
||||
|
||||
for my $x (qw(deploy uzem web mysql reboot)) {
|
||||
push @skip, $x if $opts{"no$x"};
|
||||
}
|
||||
my $skip = '';
|
||||
if (scalar @skip) {
|
||||
$skip = "--skip-tags=". join(',', @skip);
|
||||
}
|
||||
my $cmd = "ansible-playbook -i etalon-debian, -e ansible_host=$opts{clone_ip} $skip $vars etalon.yml";
|
||||
|
||||
print "$cmd\n";
|
||||
system $cmd;
|
||||
exit 1 if $? > 0;
|
||||
|
||||
if (!$opts{nodeploy}) {
|
||||
print "\nadd to inventory:\n\n".
|
||||
"echo '$opts{hostname} $opts{ip}' >> inventory\n\n";
|
||||
}
|
||||
|
||||
# vim: set tabstop=4 shiftwidth=4 expandtab smarttab:
|
||||
204
etalon_clone
Executable file
204
etalon_clone
Executable file
@ -0,0 +1,204 @@
|
||||
#!/usr/bin/env python3
|
||||
from pyVmomi import vim
|
||||
import pyVim.connect
|
||||
import atexit
|
||||
import argparse
|
||||
from pprint import pprint
|
||||
import siteconf
|
||||
|
||||
site_conf = siteconf.read()
|
||||
|
||||
def get_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Clone VM from template')
|
||||
|
||||
parser.add_argument('-s', '--site',
|
||||
required=True,
|
||||
action='store',
|
||||
help='Name of the site to create VM on')
|
||||
|
||||
parser.add_argument('-t', '--template',
|
||||
required=False,
|
||||
action='store',
|
||||
help='Name of the template you wish to clone')
|
||||
|
||||
parser.add_argument('-v', '--vm-name',
|
||||
required=True,
|
||||
action='store',
|
||||
help='Name of the VM you wish to make')
|
||||
|
||||
parser.add_argument('-c', '--cpu',
|
||||
required=False,
|
||||
type=int,
|
||||
action='store',
|
||||
default=1,
|
||||
help='Set number of CPUs')
|
||||
|
||||
parser.add_argument('-m', '--memory',
|
||||
required=False,
|
||||
type=int,
|
||||
action='store',
|
||||
default=2048,
|
||||
help='[MB] Set memory size')
|
||||
|
||||
parser.add_argument('-d', '--disk-size',
|
||||
required=False,
|
||||
type=int,
|
||||
action='store',
|
||||
default=0,
|
||||
help='[GB] Resize LVM disk to this size')
|
||||
|
||||
parser.add_argument('--datastore',
|
||||
required=False,
|
||||
action='store',
|
||||
default=None,
|
||||
help='target datastore')
|
||||
|
||||
args = parser.parse_args()
|
||||
args.disk_size = args.disk_size * 1024 * 1024
|
||||
return args
|
||||
|
||||
|
||||
def wait_for_task(task):
|
||||
""" wait for a vCenter task to finish """
|
||||
task_done = False
|
||||
while not task_done:
|
||||
if task.info.state == 'success':
|
||||
return task.info.result
|
||||
|
||||
if task.info.state == 'error':
|
||||
print("there was an error")
|
||||
task_done = True
|
||||
|
||||
|
||||
def get_obj(content, vimtype, name):
|
||||
"""
|
||||
Return an object by name, if name is None the
|
||||
first found object is returned
|
||||
"""
|
||||
obj = None
|
||||
container = content.viewManager.CreateContainerView(
|
||||
content.rootFolder, vimtype, True)
|
||||
for c in container.view:
|
||||
if name:
|
||||
if c.name == name:
|
||||
obj = c
|
||||
break
|
||||
else:
|
||||
obj = c
|
||||
break
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
def clone_vm(content, template, vm_name, datacenter_name, datastore_name,
|
||||
cluster_or_host):
|
||||
datacenter = get_obj(content, [vim.Datacenter], datacenter_name)
|
||||
destfolder = datacenter.vmFolder
|
||||
datastore = get_obj(content, [vim.Datastore], datastore_name)
|
||||
cluster = get_obj(content, [vim.ClusterComputeResource], cluster_or_host)
|
||||
if cluster:
|
||||
resource_pool = cluster.resourcePool
|
||||
else:
|
||||
host = get_obj(content, [vim.ComputeResource], cluster_or_host)
|
||||
resource_pool = host.resourcePool
|
||||
|
||||
relospec = vim.vm.RelocateSpec()
|
||||
relospec.datastore = datastore
|
||||
relospec.pool = resource_pool
|
||||
clonespec = vim.vm.CloneSpec()
|
||||
clonespec.location = relospec
|
||||
clonespec.powerOn = False
|
||||
|
||||
print("cloning VM...")
|
||||
task = template.Clone(folder=destfolder, name=vm_name, spec=clonespec)
|
||||
wait_for_task(task)
|
||||
|
||||
def extend_disk(content, vm_name, extend_to_kb):
|
||||
vm = get_obj(content, [vim.VirtualMachine], vm_name)
|
||||
for dev in vm.config.hardware.device:
|
||||
#print("dev "+ dev.deviceInfo.label)
|
||||
if hasattr(dev.backing, 'fileName'):
|
||||
size_kb = dev.capacityInKB
|
||||
if size_kb > 5 * 1024 * 1024: # lvm disk
|
||||
if extend_to_kb > size_kb:
|
||||
disk_spec = vim.vm.device.VirtualDeviceSpec()
|
||||
disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit
|
||||
disk_spec.device = vim.vm.device.VirtualDisk()
|
||||
disk_spec.device.key = dev.key
|
||||
disk_spec.device.backing = vim.vm.device.VirtualDisk.FlatVer2BackingInfo()
|
||||
disk_spec.device.backing.fileName = dev.backing.fileName
|
||||
disk_spec.device.backing.diskMode = dev.backing.diskMode
|
||||
disk_spec.device.controllerKey = dev.controllerKey
|
||||
disk_spec.device.unitNumber = dev.unitNumber
|
||||
disk_spec.device.capacityInKB = extend_to_kb
|
||||
dev_changes = []
|
||||
dev_changes.append(disk_spec)
|
||||
spec = vim.vm.ConfigSpec()
|
||||
spec.deviceChange = dev_changes
|
||||
print("extending disk '"+ dev.deviceInfo.label +"' to "+ str(extend_to_kb) +" kB")
|
||||
task = vm.ReconfigVM_Task(spec=spec)
|
||||
wait_for_task(task)
|
||||
|
||||
def set_cpu_mem(content, vm_name, cpu, mem_mb):
|
||||
vm = get_obj(content, [vim.VirtualMachine], vm_name)
|
||||
spec = vim.vm.ConfigSpec()
|
||||
spec.numCPUs = cpu
|
||||
spec.memoryMB = mem_mb
|
||||
print("Set cpu="+ str(cpu) +", memory="+ str(mem_mb) +" MB")
|
||||
task = vm.ReconfigVM_Task(spec=spec)
|
||||
wait_for_task(task)
|
||||
|
||||
def power_on(content, vm_name):
|
||||
vm = get_obj(content, [vim.VirtualMachine], vm_name)
|
||||
print("Powering on '"+ vm_name +"'")
|
||||
task = vm.PowerOn()
|
||||
wait_for_task(task)
|
||||
|
||||
def main():
|
||||
args = get_args()
|
||||
|
||||
if not args.site in site_conf:
|
||||
print(f"site not found: {args.site}")
|
||||
exit(1)
|
||||
site = site_conf[args.site];
|
||||
#pprint(site)
|
||||
|
||||
si = pyVim.connect.SmartConnect(
|
||||
host = site["vsphere"],
|
||||
user = site["user"],
|
||||
pwd = site["passwd"],
|
||||
disableSslCertValidation = True
|
||||
)
|
||||
|
||||
atexit.register(pyVim.connect.Disconnect, si)
|
||||
|
||||
content = si.RetrieveContent()
|
||||
template_name = site["template"]
|
||||
if args.template is not None:
|
||||
template_name = args.template
|
||||
template = get_obj(content, [vim.VirtualMachine], template_name)
|
||||
if not template:
|
||||
print("template not found")
|
||||
exit(1)
|
||||
|
||||
vm = get_obj(content, [vim.VirtualMachine], args.vm_name)
|
||||
if vm:
|
||||
print("VM '"+ args.vm_name +"' exists.")
|
||||
exit(1)
|
||||
|
||||
datastore = site["datastore"]
|
||||
if args.datastore is not None:
|
||||
datastore = args.datastore
|
||||
clone_vm(content, template, args.vm_name, site["datacenter"],
|
||||
datastore, site["cluster_or_host"])
|
||||
|
||||
set_cpu_mem(content, args.vm_name, args.cpu, args.memory)
|
||||
extend_disk(content, args.vm_name, args.disk_size)
|
||||
power_on(content, args.vm_name)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
# vim: set tabstop=4 shiftwidth=4 expandtab smarttab:
|
||||
11
gather_facts
11
gather_facts
@ -1,16 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
ANSIBLE_DIR=/etc/ansible
|
||||
ANSIBLE_CMDB=/usr/local/bin/ansible-cmdb
|
||||
OUTPUT=/var/www/def/public/facts.html
|
||||
|
||||
rm $ANSIBLE_DIR/gathered_facts/*
|
||||
ansible '!off,linux,windows' -m setup -f 5 --task-timeout 30 --tree $ANSIBLE_DIR/gathered_facts >/dev/null
|
||||
|
||||
INV=""
|
||||
if [[ -r $ANSIBLE_DIR/cmdb-inventory ]]; then
|
||||
if [[ -x $ANSIBLE_CMDB ]]; then
|
||||
INV=""
|
||||
if [[ -r $ANSIBLE_DIR/cmdb-inventory ]]; then
|
||||
INV="-i $ANSIBLE_DIR/cmdb-inventory"
|
||||
fi
|
||||
|
||||
$ANSIBLE_CMDB $INV -t html_fancy_split_overview $ANSIBLE_DIR/gathered_facts > $OUTPUT
|
||||
fi
|
||||
|
||||
/usr/local/bin/ansible-cmdb $INV -t html_fancy_split_overview $ANSIBLE_DIR/gathered_facts > $OUTPUT
|
||||
|
||||
# vim: set tabstop=4 shiftwidth=4 expandtab smarttab:
|
||||
|
||||
32
siteconf.pm
Executable file
32
siteconf.pm
Executable file
@ -0,0 +1,32 @@
|
||||
package siteconf;
|
||||
use strict; use warnings;
|
||||
use FindBin;
|
||||
|
||||
my $configuration = "$FindBin::Bin/../site.conf";
|
||||
if (!open(FH, '<', $configuration)) {
|
||||
die "Could not open configuration file: $configuration\n";
|
||||
}
|
||||
|
||||
my %site_conf;
|
||||
sub read {
|
||||
my $site;
|
||||
while (my $line = <FH>) {
|
||||
chomp $line;
|
||||
next if $line =~ /^#/;
|
||||
next if $line !~ /\S/;
|
||||
if ($line =~ /^\[([A-Za-z0-9_-]+)\]/) {
|
||||
$site = $1;
|
||||
$site_conf{$site} = {};
|
||||
} elsif ($line =~ /^([A-Za-z0-9_-]+)\s+(.+)/) {
|
||||
$site_conf{$site}->{$1} = $2;
|
||||
} else {
|
||||
die "invalid line in site_conf: $line\n";
|
||||
}
|
||||
}
|
||||
close(FH);
|
||||
return %site_conf;
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
# vim: set tabstop=4 shiftwidth=4 expandtab smarttab:
|
||||
29
siteconf.py
Executable file
29
siteconf.py
Executable file
@ -0,0 +1,29 @@
|
||||
import os
|
||||
import re
|
||||
#from pprint import pprint
|
||||
|
||||
configuration = "{}/../site.conf".format(os.path.dirname(__file__))
|
||||
site_conf = {}
|
||||
|
||||
def read():
|
||||
with open(configuration, "r") as cf:
|
||||
for line in cf:
|
||||
line = line.rstrip();
|
||||
if r := re.match('#', line):
|
||||
continue
|
||||
if r := re.match('\s*$', line):
|
||||
continue
|
||||
|
||||
if r := re.match('\[([A-Za-z0-9_-]+)\]', line):
|
||||
site = r[1]
|
||||
site_conf[site] = {}
|
||||
elif r := re.match('([A-Za-z0-9_-]+)\s+(.+)', line):
|
||||
site_conf[site][r[1]] = r[2]
|
||||
else:
|
||||
print(f"invalid line in site_conf: {line}")
|
||||
exit(1)
|
||||
|
||||
cf.close()
|
||||
return site_conf
|
||||
|
||||
# vim: set tabstop=4 shiftwidth=4 expandtab smarttab:
|
||||
Loading…
x
Reference in New Issue
Block a user