Kelle see artikkel on mõeldud
See artikkel võib huvi pakkuda süsteemiadministraatoritele, kelle ees seisis ülesanne luua "ühekordsed" tööjaamad.
Proloog
IT-osakonda noorest, dünaamiliselt arenevast ettevõttest, millest on väike regionaalne võrgustik, pöörduti palvega luua "iseenesest teenindamise jaamad" nende välishoone klientide kasutamiseks. Nendes jaamades on ette nähtud kasutada registreerimist ettevõtte välistel portaalidel, andmete üleslaadimist välistelt seadmetelt ja töötamist riiklike portaalidega.
Oluline aspekt oli see, et enamus tarkvarast on "suitsetatud" MS Windowsile (näiteks "Deklaratsioon"), ja hoolimata liikumisest avatud formaatide suunas, jääb MS Office domineerivaks standardiks elektrooniliste dokumentide vahetamisel. Seega ei saanud me selle ülesande lahendamisel MS Windowsist loobuda.
Peamine probleem nähti kasutajaseansside erinevate andmete kogunemise võimaluses, mis võiks viia nende lekkimiseni kolmandatele isikutele. . Kuid erinevalt kvasi-riigilisest (riiklikust autonoomsest asutusest) MFC-st, karistatakse mittetulunduslikke organisatsioone sarnaste puuduste eest palju rangemalt. Järgmise kriitilise probleemina oli nõudmine, et töötada koos välistelt andmekandjatelt, millel on kindlasti palju kurjategijate pahavara. Pahavara oht interneti kaudu toimetatakse, peeti vähem tõenäoliseks, kuna interneti juurdepääs on piiratud lubatud aadresside valiku kaudu. Nõuete väljatöötamisse kaasati teiste osakondade töötajad, kes esitasid oma nõudmisi ja soove, lõpp-nõuded nägid välja järgmised:
IB nõuded
- Pärast kasutamist peavad kõik kasutajaandmed (sealhulgas ajutised failid ja registrivõtmed) olema kustutatud.
- Kõik kasutaja poolt käivitatud protsessid peavad oma töö lõppedes lõpetama.
- Internetti pääs lubatud aadresside nimekirja kaudu.
- Piirangud kolmanda-poolse koodi käivitamiseks.
- Kui seanss seisab rohkem kui 5 minutit, peab seanss automaatselt lõpetama ja jaam peab teostama puhastuse.
Tellija nõuded
- Klientide jaamade arv harukontoris – mitte rohkem kui 4.
- Minimaalne ooteaeg süsteemi valmidusest, hetkest, mil sa istud toolile, kuni klienditarkvaraga töötamise algus.
- Perifeersete seadmete (skännerid, mälupulgad) ühendamise võimalus otse «ise teenindamise jaama» paigalduskohtade kaudu.
- Kliendi soovingud
- Reklaammaterjalide (piltide) demonstreerimine, kui kompleks on väljaspool kasutust.
Loomevaev
Pärast soovide rahuldamist Windowsi livecd-dega jõudsime ühisele järeldusele, et saadud lahendus ei rahulda vähemalt kolme kriitilist punkti. Nad kas laadivad pika aja või ei ole päris live, või nende kohandamine on seotud suurte kannatustega. Võib-olla ei otsinud me piisavalt ja saate soovitada mõnda tööriistade komplekti, oleksin tänulik.
Edasi hakkasime vaatama VDI suunas, kuid enamus lahendusi on selle ülesande jaoks kas liiga kallid või nõuavad suurt tähelepanu. Soovisime lihtsat tööriista, millel oleks minimaalne maagia, ja enamus probleeme saaks lahendada lihtsa taaskäivitamise / teenuse uuesti käivitamisega. Õnneks oli meil serverivarustus, madalama klassi aparaadid filiaalides, mis tulid välja kasutuselt eemaldatud teenusest, mida saime kasutada tehnoloogilise aluse jaoks.
Kuidas olukord lõppes? Kuidas lõppes? Kahjuks ei saa ma teile rääkida, sest NDA, kuid otsingute käigus töötasime välja huvitava skeemi, mis osutus laboratoorsetes katsetustes heaks, kuigi ei läinud seeriatootmisse.
Mõned disklaimerid: autor ei pretendeeri sellele, et pakutud lahendus lahendab täielikult kõik esitatud ülesanded ja teeb seda vabatahtlikult ja lauldes. Autor on eelnevalt nõus väitega, et Sein Englishe sprache is zehr schlecht. Kuna lahendus enam ei arene, ei tasu kukkuda bugide parandamise ega funktsionaalsuse muutmise lootustes, kõik on teie kätes. Autor arvab, et olete vähemalt veidi tuttav KVM-iga ja olete lugenud ülevaateartiklit Spice protokolli kohta ning töötanud veidi Centos või muu GNU Linuxi distributsiooniga.
Selles artiklis sooviksin käsitleda saadud lahenduse selgroogu, nimelt kliendi ja serveri vahelist suhtlemist ning virtuaalmasinate elutsükli protsesside olemust antud lahenduses. Kui artikkel osutub publikule huvitavaks, kirjeldan live-piltide rakendamise üksikasju, et luua õhukesed kliendid Fedora põhjal, ning räägin virtuaalmasinate seadistamise detailidest ja KVM serverid soorituse ja turvalisuse optimeerimiseks.
Kui võtta värvilist paberit,
Värvid, pintslid ja liim,
Ja veel natuke oskusi…
Saame 100 eurot!
Testseina skeem ja kirjeldus

Kõik seadmed asuvad filiaali sisevõrgus, ainult interneti kanal väljub. Proxiserver oli ajalooliselt olemas, midagi erakordset ta endas ei kanna. Kuid just seal, muu hulgas, toimub virtuaalmasinate (edaspidi lühendatult VMs) liikluse filtreerimine. Miski ei takista selle teenuse paigutamist KVM serverisse, ainus asi, millele tuleb tähelepanu pöörata, on see, kuidas koormus diskisüsteemile muutub.
Kliendi jaama – tegelikult «ise teenindavad jaamad», meie teenuse «frontend». Need on Lenovo IdeaCentre nettopid. Miks on see seade hea? Peaaegu kõigi omaduste tõttu, eriti rõõmustab suur USB-portide arv ja eesmine kaardilugeja. Meie skeemis on kaardilugejasse sisestatud SD kaart, millel on aktiivne kirjutamise kaitse ja millele on salvestatud modifitseeritud live-pilt Fedora 28-st. Loomulikult on nettopiga ühendatud monitor, klaviatuur ja hiir.
Lüliti – tavaline teise taseme riistvaralüliti, seisab serveriruumis ja vilgub tulesid. Ei ole ühendatud ühegi võrgu, välja arvatud «ise teenindavate jaamade» võrk.
KVM_Server – skeemi süda, labori katsedes Core 2 Quad Q9650 koos 8 GB mäluga tõmbas usaldusväärselt 3 virtuaalmasinat Windows 10-ga. Diskisüsteem - adaptec 3405, 2 ketast Raid 1 + SSD. Rikkalikes testides Xeon 1220 tõsisem LSI 9260 + SSD vedasid kergesti 5-6 VMs. Serverid saime eelmise teenuse jääkidest, kapitalikulusid pole palju. Selle(serveri) peale on üles seatud KVM virtualiseerimissüsteem koos virtuaalmasinate puuli pool_Vm.
Vm – virtuaalmasin, meie teenuse tagumisel küljel. Seal toimub kasutaja töö.
Enp5s0 – võrguliides, mis suunab iseemakeerimise jaama võrku, kus elavad dhcpd, ntpd, httpd ja xinetd kuulab „signal” sadamat.
Lo0 – pöördfaili pseudo-liides. Standardne.
Spice_console – väga huvitav asi, sest erinevalt klassikalisest RDP-st, KVM + Spice protokolli kasutamisel, tekib täiendav entiteet – virtuaalmasina konsooli port. Põhimõtteliselt, ühendades selle TCP pordi kaudu, saame VM konsooli, ilma et oleks vaja ühendust võtta VM-iga läbi selle võrguliidese. Kõik suhtlemine VM-iga signaalide edastamise osas toimub serveri kaudu. Kõige lähem analoog funktsiooni poolest on IPKVM. See tähendab, et sellele pordile edastatakse VM-i ekraanipilt, sellele kantakse ka hiire liikumise andmed ja (mis kõige tähtsam) interaktsioon Spice protokolli kaudu võimaldab sujuvalt suunata USB-seadmeid virtuaalmasinasse, justkui see seade oleks otse VM-iga ühendatud. Kontrollitud välkmälu, skannerite, veebikaamerate puhul.
Vnet0, virbr0 ja virtuaalsed VM-i võrgukaardid moodustavad virtuaalsete masinate võrgu.
Kuidas SEE töötab
Klientjaama poolt
Klientjaam käivitub graafilises režiimis muudetud Fedora 28 live-imažilt, saab dhcp kaudu IP-aadressi aadressiruumi 169.254.24.0/24. Käivitumise käigus luuakse tulemüürireeglid, mis võimaldavad ühendusi serveri „signal” ja „spice” sadamatega. Pärast käivitamist ootab jaam kasutaja „Client” autentimist. Pärast kasutaja autentimist käivitub töölaudade haldur „openbox” ja täidetakse autostardi skript autostart autenditud kasutaja nimel. Kõigi muu hulgas käivitab autostardi skript skripti remote.sh.
$HOME/.config/openbox/scripts/remote.sh
#!/bin/sh
server_ip=$(/usr/bin/cat /etc/client.conf |/usr/bin/grep "server_ip"
|/usr/bin/cut -d "=" -f2)
vdi_signal_port=$(/usr/bin/cat /etc/client.conf |/usr/bin/grep "vdi_signal_port"
|/usr/bin/cut -d "=" -f2)
vdi_spice_port=$(/usr/bin/cat /etc/client.conf |/usr/bin/grep "vdi_spice_port"
|/usr/bin/cut -d "=" -f2)
animation_folder=$(/usr/bin/cat /etc/client.conf |/usr/bin/grep "animation_folder"
|/usr/bin/cut -d "=" -f2)
process=/usr/bin/remote-viewer
while true
do
if [ -z `/usr/bin/pidof feh` ]
then
/usr/bin/echo $animation_folder
/usr/bin/feh -N -x -D1 $animation_folder &
else
/usr/bin/echo
fi
/usr/bin/nc -i 1 $server_ip $vdi_signal_port |while read line
do
if /usr/bin/echo "$line" |/usr/bin/grep "RULE ADDED, CONNECT NOW!"
then
/usr/bin/killall feh
pid_process=$($process "spice://$server_ip:$vdi_spice_port"
"--spice-disable-audio" "--spice-disable-effects=animation"
"--spice-preferred-compression=auto-glz" "-k"
"--kiosk-quit=on-disconnect" | /bin/echo $!)
/usr/bin/wait $pid_process
/usr/bin/killall -u $USER
exit
else
/usr/bin/echo $line >> /var/log/remote.log
fi
done
done
/etc/client.conf
server_ip=169.254.24.1
vdi_signal_port=5905
vdi_spice_port=5906
animation_folder=/usr/share/backgrounds/animation
background_folder=/usr/share/backgrounds2/fedora-workstation
client.conf faili muutuja kirjeldus
server_ip — KVM_Serveri aadress
vdi_signal_port — KVM_Serveri sadam, kus xinetd töötab
vdi_spice_port — KVM_Serveri võrgupord, mille kaudu edastatakse remote-viewer kliendi ühendumistaotlused virtuaalmaja spice porti (detailid allpool)
animation_folder — kaust, kust saadakse pildid bullshit animatsiooni näitamiseks
background_folder — kaust, kust saadakse pildid taustapiltide esitamiseks ooterežiimis. Rohkem animatsioonist artikli järgmises osas.
Skripti remote.sh võtab konfiguratsioonifailist /etc/client.conf seaded ja loodi nc abil ühendus KVM serveri "vdi_signal_port" porti, et saada serverist andmevoog, milles oodatakse rida "RULE ADDED, CONNECT NOW". Kui otsitud rida on saadud, käivitatakse kioskirežiimis remote-viewer, luues ühenduse serveri "vdi_spice_port" portiga. Skripti täitmine peatatakse, kuni remote-viewer protsess on lõppenud.
Remote-viewer, ühendudes "vdi_spice_port" portiga, jõuab serveri küljest redirectimise tõttu "spice_console" porti, mis on seotud liidese lo0, s.t. virtuaalmasina konsoolisse ning toimub, otseselt, kasutaja töö. Ühenduse ootamise protsessis kuvatakse kasutajale BS animatsioon, mis on jpeg-failide slaidiesitlus, kus pildi katalooge määrab konfiguratsioonifaili animation_folder muutuja väärtus.
Kui virtuaalmasina "spice_console" port kaob ühendus, mis signaalib virtuaalmasina väljalülitamist/taaskäivitamist (s.t. kasutaja sessiooni tegelikku lõppu), lõpetatakse kõik autoriseeritud kasutaja nimel käivitatud protsessid, mis põhjustab lightdm taaskäivitamise ja tagastamise autentimise ekraanile.
KVM serveri poolt
Enp5s0 võrguadapteri "signal" port ootab xinetd ühendust. Pärast "signal" porti ühendust käivitab xinetd skripti vm_manager.sh, edastamata sellele mingeid sisendparameetreid, ja suunab skripti täitmise tulemuse klientjaama nc sessioonile.
/etc/xinetd.d/test-server
teenus vdi_signal
{
port = 5905
socket_type = stream
protocol = tcp
wait = no
user = root
server = /home/admin/scripts_vdi_new/vm_manager.sh
}
/home/admin/scripts_vdi_new/vm_manager.sh
#!/usr/bin/sh
#<SET LOCAL VARIABLES FOR SCRIPT>#
SRV_SCRIPTS_DIR=$(/usr/bin/cat /etc/vm_manager.conf
|/usr/bin/grep "srv_scripts_dir" |/usr/bin/cut -d "=" -f2)
/usr/bin/echo "SRV_SCRIPTS_DIR=$SRV_SCRIPTS_DIR"
export SRV_SCRIPTS_DIR=$SRV_SCRIPTS_DIR
SRV_POOL_SIZE=$(/usr/bin/cat /etc/vm_manager.conf
|/usr/bin/grep "srv_pool_size" |/usr/bin/cut -d "=" -f2)
/usr/bin/echo "SRV_POOL_SIZE=$SRV_POOL_SIZE"
export "SRV_POOL_SIZE=$SRV_POOL_SIZE"
SRV_START_PORT_POOL=$(/usr/bin/cat /etc/vm_manager.conf
|/usr/bin/grep "srv_start_port_pool" |/usr/bin/cut -d "=" -f2)
/usr/bin/echo SRV_START_PORT_POOL=$SRV_START_PORT_POOL
export SRV_START_PORT_POOL=$SRV_START_PORT_POOL
SRV_TMP_DIR=$(/usr/bin/cat /etc/vm_manager.conf
|/usr/bin/grep "srv_tmp_dir" |/usr/bin/cut -d "=" -f2)
/usr/bin/echo "SRV_TMP_DIR=$SRV_TMP_DIR"
export SRV_TMP_DIR=$SRV_TMP_DIR
date=$(/usr/bin/date)
#</SET LOCAL VARIABLES FOR SCRIPT>#
/usr/bin/echo "# $date START EXECUTE VM_MANAGER.SH #"
make_connect_to_vm() {
#<READING CLEAR.LIST AND CHECK PORT FOR NETWORK STATE>#
/usr/bin/echo "READING CLEAN.LIST AND CHECK PORT STATE"
#<CHECK FOR NO ONE PORT IN CLEAR.LIST>#
if [ -z `/usr/bin/cat $SRV_TMP_DIR/clear.list` ]
then
/usr/bin/echo "NO AVALIBLE PORTS IN CLEAN.LIST FOUND"
/usr/bin/echo "Will try to make housekeeper, and create new vm"
make_housekeeper
else
#<MINIMUN ONE PORT IN CLEAR.LIST FOUND>#
/usr/bin/cat $SRV_TMP_DIR/clear.list |while read line
do
clear_vm_port=$(($line))
/bin/echo "FOUND PORT $clear_vm_port IN CLEAN.LIST. TRY NETSTAT"
"CHECK FOR PORT=$clear_vm_port"
#<NETSTAT LISTEN CHECK FOR PORT FROM CLEAN.LIST>#
if /usr/bin/netstat -lnt |/usr/bin/grep ":$clear_vm_port" > /dev/null
then
/bin/echo "$clear_vm_port IS LISTEN"
#<PORT IS LISTEN. CHECK FOR IS CONNECTED NOW>#
if /usr/bin/netstat -nt |/usr/bin/grep ":$clear_vm_port"
|/usr/bin/grep "ESTABLISHED" > /dev/null
then
#<PORT LISTEN AND ALREADY CONNECTED! MOVE PORT FROM CLEAR.LIST
# TO WASTE.LIST>#
/bin/echo "$clear_vm_port IS ALREADY CONNECTED, MOVE PORT TO WASTE.LIST"
/usr/bin/sed -i "/$clear_vm_port/d" $SRV_TMP_DIR/clear.list
/usr/bin/echo $clear_vm_port >> $SRV_TMP_DIR/waste.list
else
#<PORT LISTEN AND NO ONE CONNECT NOW. MOVE PORT FROM CLEAR.LIST TO
# CONN_WAIT.LIST AND CREATE IPTABLES RULES>##
/usr/bin/echo "OK, $clear_vm_port IS NOT ALREADY CONNECTED"
/usr/bin/sed -i "/$clear_vm_port/d" $SRV_TMP_DIR/clear.list
/usr/bin/echo $clear_vm_port >> $SRV_TMP_DIR/conn_wait.list
$SRV_SCRIPTS_DIR/vm_connect.sh $clear_vm_port
#<TRY TO CLEAN VM IN WASTE.LIST AND CREATE NEW WM>#
/bin/echo "TRY TO CLEAN VM IN WASTE.LIST AND CREATE NEW VM"
make_housekeeper
/usr/bin/echo "# $date STOP EXECUTE VM_MANAGER.SH#"
exit
fi
else
#<PORT IS NOT A LISTEN. MOVE PORT FROM CLEAR.LIST TO WASTE.LIST>#
/bin/echo " "$clear_vm_port" is NOT LISTEN. REMOVE PORT FROM CLEAR.LIST"
/usr/bin/sed -i "/$clear_vm_port/d" $SRV_TMP_DIR/clear.list
/usr/bin/echo $clear_vm_port >> $SRV_TMP_DIR/waste.list
make_housekeeper
fi
done
fi
}
make_housekeeper() {
/usr/bin/echo "=Execute housekeeper="
/usr/bin/cat $SRV_TMP_DIR/waste.list |while read line
do
/usr/bin/echo "$line"
if /usr/bin/netstat -lnt |/usr/bin/grep ":$line" > /dev/null
then
/bin/echo "port_alive, vm is running"
if /usr/bin/netstat -nt |/usr/bin/grep ":$line"
|/usr/bin/grep "ESTABLISHED" > /dev/null
then
/bin/echo "port_in_use can't delete vm!!!"
else
/bin/echo "port_not in use. Deleting vm"
/usr/bin/sed -i "/$line/d" $SRV_TMP_DIR/waste.list
/usr/bin/echo $line >> $SRV_TMP_DIR/recycle.list
$SRV_SCRIPTS_DIR/vm_delete.sh $line
fi
else
/usr/bin/echo "posible vm is already off. Deleting vm"
/usr/bin/echo "MOVE VM IN OFF STATE $line FROM WASTE.LIST TO"
"RECYCLE.LIST AND DELETE VM"
/usr/bin/sed -i "/$line/d" $SRV_TMP_DIR/waste.list
/usr/bin/echo $line >> $SRV_TMP_DIR/recycle.list
$SRV_SCRIPTS_DIR/vm_delete.sh "$line"
fi
done
create_clear_vm
}
create_clear_vm() {
/usr/bin/echo "=Create new VM="
while [ $SRV_POOL_SIZE -gt 0 ]
do
new_vm_port=$(($SRV_START_PORT_POOL+$SRV_POOL_SIZE))
/usr/bin/echo "new_vm_port=$new_vm_port"
if /usr/bin/grep "$new_vm_port" $SRV_TMP_DIR/clear.list > /dev/null
then
/usr/bin/echo "$new_vm_port port is already defined in clear.list"
else
if /usr/bin/grep "$new_vm_port" $SRV_TMP_DIR/waste.list > /dev/null
then
/usr/bin/echo "$new_vm_port port is already defined in waste.list"
else
if /usr/bin/grep "$new_vm_port" $SRV_TMP_DIR/recycle.list > /dev/null
then
/usr/bin/echo "$new_vm_port PORT IS ALREADY DEFINED IN RECYCLE LIST"
else
if /usr/bin/grep "$new_vm_port" $SRV_TMP_DIR/conn_wait.list > /dev/null
then
/usr/bin/echo "$new_vm_port PORT IS ALREADY DEFINED IN CONN_WAIT LIST"
else
/usr/bin/echo "PORT IN NOT DEFINED IN NO ONE LIST WILL CREATE"
"VM ON PORT $new_vm_port"
/usr/bin/echo $new_vm_port >> $SRV_TMP_DIR/recycle.list
$SRV_SCRIPTS_DIR/vm_create.sh $new_vm_port
fi
fi
fi
fi
SRV_POOL_SIZE=$(($SRV_POOL_SIZE-1))
done
/usr/bin/echo "# $date STOP EXECUTE VM_MANAGER.SH #"
}
make_connect_to_vm |/usr/bin/tee -a /var/log/vm_manager.log
/etc/vm_manager.confsrv_scripts_dir=/home/admin/scripts_vdi_new
srv_pool_size=4
srv_start_port_pool=5920
srv_tmp_dir=/tmp/vm_state
base_host=win10_2
input_iface=enp5s0
vdi_spice_port=5906
count_conn_tryes=10
vm_manager.conf konfiguratsioonifaili muutujate kirjeldus
srv_scripts_dir — vm_manager.sh, vm_connect.sh, vm_delete.sh, vm_create.sh, vm_clear.sh skriptide asukoha kaust
srv_pool_size — VM basseini suurus
srv_start_port_pool — algne port, kust alates hakkavad virtuaalmasina spice konsoolide portid paiknema
srv_tmp_dir — kaust ajutiste failide jaoks
base_host — baas VM (kuldpilt), millest tehakse VM koopiaid basseini
input_iface — serveri võrgu liides, mis vaatab Client Stations poole
vdi_spice_port — serveri võrgu port, kust toimub remote-vieweri kliendi ühendusküsimuse suunamine virtuaalmasina spice porti
count_conn_tryes — ooteaeg, pärast mille kulgu arvatakse, et ühendus Vm-iga ei ole toimunud (töö üksikasjade jaoks vaata vm_connect.sh)
Skript vm_manager.sh loeb konfiguratsioonifaili vm_manager.conf, hindab virtuaalmasinate olekut grupis mitme parameetri põhjal, nimelt: kui palju VM-e on kasutusele võetud, kas on vabu puhtaid VM-e. Selleks loeb ta faili clear.list, milles on «spice_console» portide numbrid «värskelt loodud» (vt allpool VM-i loomise tsüklit) virtuaalmasinate kohta ja kontrollib nende ühenduse olemasolu. Kui leitakse port, millel on kehtiv võrguühendus (mida ei peaks kindlasti olema), kuvatakse hoiatusteade ja port kantakse waste.listi. Kui leiate esimest porti failist clear.list, millega praegu ei ole ühendust, kutsub vm_manager.sh esile skripti vm_connect.sh ja edastab sellele määramisena selle porti numbri.
/home/admin/scripts_vdi_new/vm_connect.sh
#!/bin/sh
date=$(/usr/bin/date)
/usr/bin/echo "#" "$date" "START EXECUTE VM_CONNECT.SH#"
#<SET LOCAL VARIABLES FOR SCRIPT>#
free_port="$1"
input_iface=$(/usr/bin/cat /etc/vm_manager.conf |/usr/bin/grep "input_iface"
|/usr/bin/cut -d "=" -f2)
/usr/bin/echo "input_iface=$input_iface"
vdi_spice_port=$(/usr/bin/cat /etc/vm_manager.conf
|/usr/bin/grep "vdi_spice_port" |/usr/bin/cut -d "=" -f2)
/usr/bin/echo "vdi_spice_port=$vdi_spice_port"
count_conn_tryes=$(/usr/bin/cat /etc/vm_manager.conf
|/usr/bin/grep "count_conn_tryes" |/usr/bin/cut -d "=" -f2)
/usr/bin/echo "count_conn_tryes=$count_conn_tryes"
#</SET LOCAL VARIABLES FOR SCRIPT>#
#<CREATE IPTABLES RULES AND SEND SIGNAL TO CONNECT>#
/usr/bin/echo "create rule for port" $free_port
/usr/sbin/iptables -I INPUT -i $input_iface -p tcp -m tcp --dport
$free_port -j ACCEPT
/usr/sbin/iptables -I OUTPUT -o $input_iface -p tcp -m tcp --sport
$free_port -j ACCEPT
/usr/sbin/iptables -t nat -I PREROUTING -p tcp -i $input_iface --dport
$vdi_spice_port -j DNAT --to-destination 127.0.0.1:$free_port
/usr/bin/echo "RULE ADDED, CONNECT NOW!"
#</CREATE IPTABLES RULES AND SEND SIGNAL TO CONNECT>#
#<WAIT CONNECT ESTABLISHED AND ACTIVATE CONNECT TIMER>#
while [ $count_conn_tryes -gt 0 ]
do
if /usr/bin/netstat -nt |/usr/bin/grep ":$free_port"
|/usr/bin/grep "ESTABLISHED" > /dev/null
then
/bin/echo "$free_port NOW in use!!!"
/usr/bin/sleep 1s
/usr/sbin/iptables -t nat -D PREROUTING -p tcp -i $input_iface --dport
$vdi_spice_port -j DNAT --to-destination 127.0.0.1:$free_port
/usr/sbin/iptables -D INPUT -i $input_iface -p tcp -m tcp --dport
$free_port -j ACCEPT
/usr/sbin/iptables -D OUTPUT -o $input_iface -p tcp -m tcp --sport
$free_port -j ACCEPT
/usr/bin/sed -i "/$free_port/d" $SRV_TMP_DIR/conn_wait.list
/usr/bin/echo $free_port >> $SRV_TMP_DIR/waste.list
return
else
/usr/bin/echo "$free_port NOT IN USE"
/usr/bin/echo "RULE ADDED, CONNECT NOW!"
/usr/bin/sleep 1s
fi
count_conn_tryes=$((count_conn_tryes-1))
done
#</WAIT CONNECT ESTABLISED AND ACTIVATE CONNECT TIMER>#
#<IF COUNT HAS EXPIRED. REMOVE IPTABLES RULE AND REVERT
# VM TO CLEAR.LIST>#
/usr/bin/echo "REVERT IPTABLES RULE AND REVERT VM TO CLEAN
LIST $free_port"
/usr/sbin/iptables -t nat -D PREROUTING -p tcp -i $input_iface --dport
$vdi_spice_port -j DNAT --to-destination 127.0.0.1:$free_port
/usr/sbin/iptables -D INPUT -i $input_iface -p tcp -m tcp --dport $free_port
-j ACCEPT
/usr/sbin/iptables -D OUTPUT -o $input_iface -p tcp -m tcp --sport
$free_port -j ACCEPT
/usr/bin/sed -i "/$free_port/d" $SRV_TMP_DIR/conn_wait.list
/usr/bin/echo $free_port >> $SRV_TMP_DIR/clear.list
#</COUNT HAS EXPIRED. REMOVE IPTABLES RULE AND REVERT VM
#TO CLEAR.LIST>#
/usr/bin/echo "#" "$date" "END EXECUTE VM_CONNECT.SH#"
# Attention! Must Be! sysctl net.ipv4.conf.all.route_localnet=1
Skript vm_connect.sh lisab tulemüürireeglid, mis loovad „vdi_spice_port” serveri enp5s0 liidese portide suunamise VM-i „spice console” porti, mis asub serveri lo0 liideses ja mis edastatakse käivitamisel parameetrina. Port kantakse conn_wait.listi, VM loetakse ühenduse ootamiseks. Client Station'i seansis edastatakse serveris «signal» porti rida «RULE ADDED, CONNECT NOW», mida oodatakse käivitatud skriptist remote.sh. Algab ühenduse ootamise tsükkel, mille katsete arv on määratud konfiguratsioonifaili muutujaga «count_conn_tryes». Iga sekundi järel antakse nc seansis välja rida «RULE ADDED, CONNECT NOW» ja kontrollitakse, kas „spice_console” port on kehtiva ühendusega.
Kui määratud katsete arvu jooksul ühendust ei toimunud, kantakse „spice_console” port tagasi clear.listi. vm_connect.sh täitmine lõpeb, jätkatakse vm_manager.sh täitmist, mis käivitab puhastustsükli.
Kui Client Station ühendub lo0 liidese «spice_console» pordiga, eemaldatakse tulemüürireeglid, mis loovad ümbersuunamise «spice» serveri ja «spice_console» pordi vahel, ning edasine ühenduse säilitamine toimub tulemüüri oleku määramise mehhanismi kaudu. Ühenduse katkedes ei õnnestu «spice_console» pordiga uuesti ühendust luua. «spice_console» port kantakse waste.list faili, VM loetakse „räpaseks“ ja ta ei saa naasta „puhtate“ virtuaalmasinate punkti ilma puhastamiseta. vm_connect.sh skripti täitmine lõppeb, jätkab vm_manager.sh täitmine, mis käivitab puhastusprotsessi.
Puhastusprotsess algab waste.list faili vaatamisest, kuhu kantakse virtuaalmasinate «spice_console» portide numbrid, kellega ühendust loodi. Iga loendis oleva «spice_console» pordi puhul määratakse kindlaks, kas aktiivne ühendus on olemas. Kui ühendust pole, arvatakse, et virtuaalmasinat ei kasutata enam ja port kantakse recycle.list, alustatakse virtuaalmasina eemaldamise protsessi (vt allpool), millele see port kuulus. Kui pordil on aktiivne võrguühendus, arvatakse, et virtuaalmasinat kasutatakse ning tema suhtes ei tehta mingeid toiminguid. Kui porti ei kuulata, arvatakse, et VM on välja lülitatud ja enam ei vajata. Port kantakse recycle.list ja käivitatakse virtuaalmasina eemaldamise protsess. Selleks kutsutakse esile vm_delete.sh skript, millele edastatakse VM «spice_console» pordi number, mille soovitakse eemaldada.
/home/admin/scripts_vdi_new/vm_delete.sh
#!/bin/sh
#<Set local VARIABLES>#
port_to_delete="$1"
date=$(/usr/bin/date)
#</Set local VARIABLES>#
/usr/bin/echo "# $date START EXECUTE VM_DELETE.SH#"
/usr/bin/echo "TRY DELETE VM ON PORT: $vm_port"
#<VM NAME SETUP>#
vm_name_part1=$(/usr/bin/cat /etc/vm_manager.conf |/usr/bin/grep 'base_host'
|/usr/bin/cut -d'=' -f2)
vm_name=$(/usr/bin/echo "$vm_name_part1""-""$port_to_delete")
#</VM NAME SETUP>#
#<SHUTDOWN AND DELETE VM>#
/usr/bin/virsh destroy $vm_name
/usr/bin/virsh undefine $vm_name
/usr/bin/rm -f /var/lib/libvirt/images_write/$vm_name.qcow2
/usr/bin/sed -i "/$port_to_delete/d" $SRV_TMP_DIR/recycle.list
#</SHUTDOWN AND DELETE VM>#
/usr/bin/echo "VM ON PORT $vm_port HAS BEEN DELETE AND REMOVE"
"FROM RECYCLE.LIST. EXIT FROM VM_DELETE.SH"
/usr/bin/echo "# $date STOP EXECUTE VM_DELETE.SH#"
exit
Virtuaalmasina eemaldamine on piisavalt triviaalne operatsioon, skript vm_delete.sh määrab ära virtuaalmasina nime, mille port on edastatud käivitusparameetrina. VM sunnitakse peatuma, VM eemaldatakse hüperviisorist ning eemaldatakse selle VM virtuaalne kõvaketas. «spice_console» port kantakse recycle.list failist. vm_delete.sh skripti täitmine lõppeb, jätkub vm_manager.sh täitmine.
Skript vm_manager.sh, lõpetades üleliigsete virtuaalmasinate eemaldamise operatsioonid waste.list failist, alustab virtuaalmasinate loomise tsüklit puuli.
Protsess algab sellega, et määratakse kõik saadaval olevad "spice_console" sadamad. Selleks tehtakse konfiguratsioonifaili parameetri "srv_start_port_pool" põhjal, mis määrab algsadama "spice_console" virtuaalmasinate puule, ja parameetri "srv_pool_size", mis määrab virtuaalmasinate maksimaalse arvu, järjestikune ülekäik kõigist võimalikest sadamavalikutest. Iga kindla sadama jaoks otsitakse selle olemasolu clear.list, waste.list, conn_wait.list, recycle.list failides. Kui sadam tuvastatakse mõnes eespool nimetatud failis, peetakse seda hõivatud ja see jäetakse vahele. Kui sadamat nendest failidest ei leita, kantakse see recycle.list faili ja alustatakse uue virtuaalmasina loomise protsessi. Selleks käivitatakse skript vm_create.sh, millele antakse parameetrina "spice_console" sadama number, mille jaoks tuleb VM luua.
/home/admin/scripts_vdi_new/vm_create.sh
#!/bin/sh
/usr/bin/echo "#" "$date" "START RUNNING VM_CREATE.SH#"
new_vm_port=$1
date=$(/usr/bin/date)
a=0
/usr/bin/echo SRV_TMP_DIR=$SRV_TMP_DIR
#<SET LOCAL VARIABLES FOR SCRIPT>#
base_host=$(/usr/bin/cat /etc/vm_manager.conf |/usr/bin/grep "base_host"
|/usr/bin/cut -d "=" -f2)
/usr/bin/echo "base_host=$base_host"
#</SET LOCAL VARIABLES FOR SCRIPT>#
hdd_image_locate() {
/bin/echo "Run STEP 1 - hdd_image_locate"
hdd_base_image=$(/usr/bin/virsh dumpxml $base_host
|/usr/bin/grep "source file" |/usr/bin/grep "qcow2" |/usr/bin/head -n 1
|/usr/bin/cut -d "'" -f2)
if [ -z "$hdd_base_image" ]
then
/bin/echo "base hdd image not found!"
else
/usr/bin/echo "hdd_base_image found is a $hdd_base_image. Run next step 2"
#< CHECK FOR SNAPSHOT ON BASE HDD >#
if [ 0 -eq `/usr/bin/qemu-img info "$hdd_base_image" | /usr/bin/grep -c "Snapshot"` ]
then
/usr/bin/echo "base image haven't snapshot, run NEXT STEP 3"
else
/usr/bin/echo "base hdd image have a snapshot, can't use this image"
exit
fi
#</ CHECK FOR SNAPSHOT ON BASE HDD >#
#< CHECK FOR HDD IMAGE IS LINK CLONE >#
if [ 0 -eq `/usr/bin/qemu-img info "$hdd_base_image" |/usr/bin/grep -c "backing file"
then
/usr/bin/echo "base image is not a linked clone, NEXT STEP 4"
/usr/bin/echo "Base image check complete!"
else
/usr/bin/echo "base hdd image is a linked clone, can't use this image"
exit
fi
fi
#</ CHECK FOR HDD IMAGE IS LINK CLONE >#
cloning
}
cloning() {
# <Step_1 turn the base VM off >#
/usr/bin/virsh shutdown $base_host > /dev/null 2>&1
# </Step_1 turn the base VM off >#
#<Create_vm_config>#
/usr/bin/echo "Free port for Spice VM is $new_vm_port"
#<Setup_name_for_new_VM>#
new_vm_name=$(/bin/echo $base_host"-"$new_vm_port)
#</Setup_name_for_new_VM>#
#<Make_base_config_as_clone_base_VM>#
/usr/bin/virsh dumpxml $base_host > $SRV_TMP_DIR/$new_vm_name.xml
#<Make_base_config_as_clone_base_VM>#
##<Setup_New_VM_Name_in_config>##
/usr/bin/sed -i "s%<name>$base_host</name>%<name>$new_vm_name</name>%g" $SRV_TMP_DIR/$new_vm_name.xml
#</Setup_New_VM_Name_in_config>#
#<UUID Changing>#
old_uuid=$(/usr/bin/cat $SRV_TMP_DIR/$new_vm_name.xml |/usr/bin/grep "<uuid>")
/usr/bin/echo old UUID $old_uuid
new_uuid_part1=$(/usr/bin/echo "$old_uuid" |/usr/bin/cut -d "-" -f 1,2)
new_uuid_part2=$(/usr/bin/echo "$old_uuid" |/usr/bin/cut -d "-" -f 4,5)
new_uuid=$(/bin/echo $new_uuid_part1"-"$new_vm_port"-"$new_uuid_part2)
/usr/bin/echo $new_uuid
/usr/bin/sed -i "s%$old_uuid%$new_uuid%g" $SRV_TMP_DIR/$new_vm_name.xml
#</UUID Changing>#
#<Spice port replace>#
old_spice_port=$(/usr/bin/cat $SRV_TMP_DIR/$new_vm_name.xml
|/usr/bin/grep "graphics type='spice' port=")
/bin/echo old spice port $old_spice_port
new_spice_port=$(/usr/bin/echo "<graphics type='spice' port='$new_vm_port' autoport='no' listen='127.0.0.1'>")
/bin/echo $new_spice_port
/usr/bin/sed -i "s%$old_spice_port%$new_spice_port%g" $SRV_TMP_DIR/$new_vm_name.xml
#</Spice port replace>#
#<MAC_ADDR_GENERATE>#
mac_new=$(/usr/bin/hexdump -n6 -e '/1 ":%02X"' /dev/random|/usr/bin/sed s/^://g)
/usr/bin/echo New Mac is $mac_new
#</MAC_ADDR_GENERATE>#
#<GET OLD MAC AND REPLACE>#
mac_old=$(/usr/bin/cat $SRV_TMP_DIR/$new_vm_name.xml |/usr/bin/grep "mac address=")
/usr/bin/echo old mac is $mac_old
/usr/bin/sed -i "s%$mac_old%$mac_new%g" $SRV_TMP_DIR/$new_vm_name.xml
#<GET OLD MAC AND REPLACE>#
#<new_disk_create>#
/usr/bin/qemu-img create -f qcow2 -b $hdd_base_image /var/lib/libvirt/images_write/$new_vm_name.qcow2
#</new_disk_create>#
#<attach_new_disk_in_confiig>#
/usr/bin/echo hdd base image is $hdd_base_image
/usr/bin/sed -i "s%<source file='$hdd_base_image'/>%<source file='/var/lib/libvirt/images_write/$new_vm_name.qcow2'/>%g" $SRV_TMP_DIR/$new_vm_name.xml
#</attach_new_disk_in_confiig>#
starting_vm
#</Create_vm config>#
}
starting_vm() {
/usr/bin/virsh define $SRV_TMP_DIR/$new_vm_name.xml
/usr/bin/virsh start $new_vm_name
while [ $a -ne 1 ]
do
if /usr/bin/virsh list --all |/usr/bin/grep "$new_vm_name" |/usr/bin/grep "running" > /dev/null 2>&1
then
a=1
/usr/bin/sed -i "/$new_vm_port/d" $SRV_TMP_DIR/recycle.list
/usr/bin/echo $new_vm_port >> $SRV_TMP_DIR/clear.list
/usr/bin/echo "#" "$date" "VM $new_vm_name IS STARTED #"
else
/usr/bin/echo "#VM $new_vm_name is not ready#"
a=0
/usr/bin/sleep 2s
fi
done
/usr/bin/echo "#$date EXIT FROM VM_CREATE.SH#"
exit
}
hdd_image_locate
Uue virtuaalmasina loomise protsess
Skript vm_create.sh loeb konfiguratsioonifailist muutuja "base_host" väärtuse, mis määrab virtuaalmasina malli, mille põhjal luuakse kloon. See väljastab virtuaalmasina XML konfiguratsiooni hüperviisori andmebaasist, teostab rea kontrollimisi VM-i qcow ketta kujutise kohta ja eduka lõpetamise järel loob XML konfiguratsioonifaili uue VM-i jaoks ning "linked clone" ketta kujutise uue VM-i jaoks. Pärast seda laaditakse uue VM-i XML konfigureerimine hüperviisori andmebaasi, ja VM käivitatakse. "spice_console" port kantakse recycle.list failist clear.list faili. Skripti vm_create.sh täitmine lõpeb ja vm_manager.sh täitmine lõpetatakse.
Järgmise ühenduse korral algab kõik taas algusest.
Hädajuhtumite jaoks on kaasas skript vm_clear.sh, mis sunniviisiliselt käib läbi kõik VM-d puulus ja kustutab need, lähtestades nimekirjade väärtused. Selle väljakutsumine laadimisfaasis võimaldab (alustada) VDI tööd puhta lehena.
/home/admin/scripts_vdi_new/vm_clear.sh
#!/usr/bin/sh
#set VARIABLES#
SRV_SCRIPTS_DIR=$(/usr/bin/cat /etc/vm_manager.conf
|/usr/bin/grep "srv_scripts_dir" |/usr/bin/cut -d "=" -f2)
/usr/bin/echo "SRV_SCRIPTS_DIR=$SRV_SCRIPTS_DIR"
export SRV_SCRIPTS_DIR=$SRV_SCRIPTS_DIR
SRV_TMP_DIR=$(/usr/bin/cat /etc/vm_manager.conf
|/usr/bin/grep "srv_tmp_dir" |/usr/bin/cut -d "=" -f2)
/usr/bin/echo "SRV_TMP_DIR=$SRV_TMP_DIR"
export SRV_TMP_DIR=$SRV_TMP_DIR
SRV_POOL_SIZE=$(/usr/bin/cat /etc/vm_manager.conf
|/usr/bin/grep "srv_pool_size" |/usr/bin/cut -d "=" -f2)
/usr/bin/echo "SRV_POOL_SIZE=$SRV_POOL_SIZE"
SRV_START_PORT_POOL=$(/usr/bin/cat /etc/vm_manager.conf
|/usr/bin/grep "srv_start_port_pool" |/usr/bin/cut -d "=" -f2)
/usr/bin/echo SRV_START_PORT_POOL=$SRV_START_PORT_POOL
#Set VARIABLES#
/usr/bin/echo "= Cleanup ALL VM="
/usr/bin/mkdir $SRV_TMP_DIR
/usr/sbin/service iptables restart
/usr/bin/cat /dev/null > $SRV_TMP_DIR/clear.list
/usr/bin/cat /dev/null > $SRV_TMP_DIR/waste.list
/usr/bin/cat /dev/null > $SRV_TMP_DIR/recycle.list
/usr/bin/cat /dev/null > $SRV_TMP_DIR/conn_wait.list
port_to_delete=$(($SRV_START_PORT_POOL+$SRV_POOL_SIZE))
while [ "$port_to_delete" -gt "$SRV_START_PORT_POOL" ]
do
$SRV_SCRIPTS_DIR/vm_delete.sh $port_to_delete
port_to_delete=$(($port_to_delete-1))
done
/usr/bin/echo "= EXIT FROM VM_CLEAR.SH="
Sellega soovin lõpetada oma jutustuse esimese osa. Esitatud teave peaks olema piisav süsteemiadministraatoritele, et proovida VDI-d tegutsemas. Kui kogukond peab selle teema huvitavaks, räägin teises osas Fedora livecd modifitseerimisest ja selle muutmisest kioskiks.
Allikas: habr.com
