Csináld magad Bare-Metal ellátás, vagy a szerverek automatikus előkészítése a semmiből

Hello, Denis vagyok, és az egyik tevékenységi területem az X5 infrastrukturális megoldásainak fejlesztése. Ma szeretném megosztani veled, hogyan telepíthetsz nyilvánosan elérhető eszközökön alapuló automatikus szerver-előkészítő rendszert. Véleményem szerint ez egy érdekes, egyszerű és rugalmas megoldás.

Csináld magad Bare-Metal ellátás, vagy a szerverek automatikus előkészítése a semmiből

Az előkészítés alatt azt értjük, hogy egy új szervert alakítsunk ki egy teljesen konfigurált operációs rendszerrel rendelkező szerverré. Linux vagy az ESXi hipervizorral (a Windows-kiszolgálók telepítésével ebben a cikkben nem foglalkozunk).

feltételek:

  • szerverek – konfigurálandó szerverek.
  • A telepítőkiszolgáló a fő szerver, amely a teljes előkészítési folyamatot biztosítja a hálózaton keresztül.

Miért van szükség automatizálásra?

Tegyük fel, hogy van egy feladat: masszívan felkészíteni a szervereket a semmiből, csúcsidőben – napi 30. Különböző gyártók és modellek szerverei, különböző operációs rendszerek telepíthetők rájuk, és lehet, hogy rendelkeznek hypervisorral, vagy nem.

Milyen műveleteket tartalmaz a beállítási folyamat (automatizálás nélkül):

  • csatlakoztasson billentyűzetet, egeret, monitort a szerverhez;
  • BIOS, RAID, IPMI konfigurálása;
  • komponens firmware frissítése;
  • telepítsen egy fájlrendszer-képet (vagy telepítsen egy hypervisort és másoljon virtuális gépeket);

Jegyzet. Alternatív megoldásként az operációs rendszer üzembe helyezése lehetséges egy automatikus válaszfájllal történő telepítéssel. De erről a cikkben nem lesz szó. Bár alább látni fogja, hogy ennek a funkciónak a hozzáadása nem nehéz.

  • konfigurálja az operációs rendszer paramétereit (gazdanév, IP stb.).

Ezzel a megközelítéssel minden kiszolgálón egymás után ugyanazokat a beállításokat hajtják végre. Az ilyen munka hatékonysága nagyon alacsony.

Az automatizálás lényege, hogy kiküszöböljük az emberi részvételt a szerver előkészítési folyamatból. Amennyire csak lehetséges.

Az automatizálás csökkenti a műveletek közötti állásidőt, és lehetővé teszi több szerver egyidejű kiépítését. Az emberi tényezők miatti hibák valószínűsége is jelentősen csökken.

Csináld magad Bare-Metal ellátás, vagy a szerverek automatikus előkészítése a semmiből

Hogyan történik a szerverek automatikus beállítása?

Elemezzük részletesen az összes szakaszt.

Van egy Linux-kiszolgálója, amelyet PXE telepítőkiszolgálóként használ. A szolgáltatások telepítve és konfigurálva vannak rajta: DHCP, TFTP.

Tehát a szervert (melyet konfigurálni kell) PXE-n keresztül indítunk. Emlékezzünk, hogyan működik:

  • A hálózati rendszerindítás ki van választva a szerveren.
  • A szerver betölti a hálózati kártya PXE-ROM-ját, és DHCP-n keresztül kapcsolatba lép a telepítőkiszolgálóval, hogy megkapja a hálózati címet.
  • A DHCP telepítőkiszolgáló kiad egy címet, valamint utasításokat a PXE-n keresztüli további letöltéshez.
  • A szerver PXE-n keresztül tölti be a hálózati rendszerbetöltőt a telepítő szerverről, a további betöltés a PXE konfigurációs fájl szerint történik.
  • A rendszerindítás a kapott paraméterek (kernel, initramfs, mount point, squashfs image, stb.) alapján történik.

Jegyzet. A cikk a PXE-n keresztül történő indítást írja le BIOS módban. Jelenleg a gyártók aktívan implementálják az UEFI rendszerindítási módot. A PXE esetében a különbség a DHCP-kiszolgáló konfigurációjában és egy további rendszerbetöltő jelenlétében lesz.

Nézzünk egy példát a PXE szerver konfigurációjára (pxelinux menü).

pxelinux.cfg/default fájl:

default menu.c32
prompt 0
timeout 100
menu title X5 PXE Boot Menu
LABEL InstallServer Menu
	MENU LABEL InstallServer
	KERNEL menu.c32
	APPEND pxelinux.cfg/installserver
LABEL VMware Menu
	MENU LABEL VMware ESXi Install
	KERNEL menu.c32
	APPEND pxelinux.cfg/vmware
LABEL toolkit // меню по умолчанию
	MENU LABEL Linux Scripting Toolkits
	MENU default
	KERNEL menu.c32
	APPEND pxelinux.cfg/toolkit // переход на следующее меню

pxelinux.cfg/toolkit fájl:

prompt 0
timeout 100
menu title X5 PXE Boot Menu
label mainmenu
    menu label ^Return to Main Menu
    kernel menu.c32
    append pxelinux.cfg/default
label x5toolkit-auto // по умолчанию — автоматический режим
        menu label x5 toolkit autoinstall
        menu default
        kernel toolkit/tkcustom-kernel
        append initrd=toolkit/tk-initramfs.gz quiet net.ifnames=0 biosdevname=0 nfs_toolkit_ip=192.168.200.1 nfs_toolkit_path=tftpboot/toolkit nfs_toolkit_script=scripts/mount.sh script_cmd=master-install.sh CMDIS2=”…”
label x5toolkit-shell // для отладки - консоль
        menu label x5 toolkit shell
        kernel toolkit/tkcustom-kernel
        append initrd=toolkit/tkcustom-initramfs.gz quiet net.ifnames=0 biosdevname=0 nfs_toolkit_ip=192.168.200.1 nfs_toolkit_path=tftpboot/toolkit nfs_toolkit_script=scripts/mount.sh script_cmd=/bin/bash CMDIS2=”…”

A kernel és az initramfs ebben a szakaszban egy köztes Linux kép, amelynek segítségével a szerver fő előkészítése és konfigurálása történik.

Mint látható, a rendszerbetöltő sok paramétert továbbít a kernelnek. Ezen paraméterek egy részét maga a kernel is használja. És néhányat felhasználhatunk saját céljainkra. Erről később lesz szó, de egyelőre ne feledje, hogy az összes átadott paraméter elérhető lesz a köztes Linux lemezképben a /proc/cmdline-on keresztül.

Hol szerezhetem be őket, kernel és initramfs?
Alapként bármilyen Linux disztribúciót választhat. Mire figyelünk a választásnál:

  • a rendszerindító képnek univerzálisnak kell lennie (illesztőprogramok elérhetősége, további segédprogramok telepítésének lehetősége);
  • Valószínűleg testre kell szabnia az initramfs-t.

Hogyan történik ez az X5-ös megoldásunkban? A CentOS 7-et választottuk alapnak, próbáljuk ki a következő trükköt: készítsük elő a leendő képszerkezetet, csomagoljuk be egy archívumba, és hozzunk létre egy initramfs-t, amiben a fájlrendszer archívumunk lesz. A kép betöltésekor az archívum kibővül a létrehozott tmpfs partícióba. Így egy minimális, mégis teljes értékű live linux képet kapunk minden szükséges segédprogrammal, amely mindössze két fájlból áll: vmkernel és initramfs.

#создаем директории: 

mkdir -p /tftpboot/toolkit/CustomTK/rootfs /tftpboot/toolkit/CustomTK/initramfs/bin

#подготавливаем структуру:

yum groups -y install "Minimal Install" --installroot=/tftpboot/toolkit/CustomTK/rootfs/
yum -y install nfs-utils mariadb ntpdate mtools syslinux mdadm tbb libgomp efibootmgr dosfstools net-tools pciutils openssl make ipmitool OpenIPMI-modalias rng-tools --installroot=/tftpboot/toolkit/CustomTK/rootfs/
yum -y remove biosdevname --installroot=/tftpboot/toolkit/CustomTK/rootfs/

# подготавливаем initramfs:

wget https://busybox.net/downloads/binaries/1.31.0-defconfig-multiarch-musl/busybox-x86_64 -O /tftpboot/toolkit/CustomTK/initramfs/bin/busybox
chmod a+x /tftpboot/toolkit/CustomTK/initramfs/bin/busybox
cp /tftpboot/toolkit/CustomTK/rootfs/boot/vmlinuz-3.10.0-957.el7.x86_64 /tftpboot/toolkit/tkcustom-kernel

# создаем /tftpboot/toolkit/CustomTK/initramfs/init (ниже содержание скрипта):

#!/bin/busybox sh
/bin/busybox --install /bin
mkdir -p /dev /proc /sys /var/run /newroot
mount -t proc proc /proc
mount -o mode=0755 -t devtmpfs devtmpfs /dev
mkdir -p /dev/pts /dev/shm /dev/mapper /dev/vc
mount -t devpts -o gid=5,mode=620 devpts /dev/pts
mount -t sysfs sysfs /sys
mount -t tmpfs -o size=4000m tmpfs /newroot
echo -n "Extracting rootfs... "
xz -d -c -f rootfs.tar.xz | tar -x -f - -C /newroot
echo "done"
mkdir -p /newroot/dev /newroot/proc /newroot/sys
mount --move /sys  /newroot/sys
mount --move /proc /newroot/proc
mount --move /dev  /newroot/dev
exec switch_root /newroot /sbin/init

# упаковываем rootfs и initramfs:

cd /tftpboot/toolkit/CustomTK/rootfs
tar cJf /tftpboot/toolkit/CustomTK/initramfs/rootfs.tar.xz --exclude ./proc --exclude ./sys --exclude ./dev .
cd /tftpboot/toolkit/CustomTK/initramfs
find . -print0 | cpio --null -ov --format=newc | gzip -9 > /tftpboot/toolkit/tkcustom-initramfs-new.gz

Tehát megadtuk a betöltendő kernelt és initramfs-t. Ennek eredményeként ebben a szakaszban a köztes linux képfájl PXE-n keresztüli betöltésével megkapjuk az operációs rendszer konzolját.

Remek, de most át kell adnunk az irányítást az „automatizálásunkra”.

Ezt így is meg lehet csinálni.

Tegyük fel, hogy a kép betöltése után a vezérlést a mount.sh szkriptre tervezzük átvinni.
Tegyük bele a mount.sh szkriptet az automatikus futtatásba. Ehhez módosítania kell az initramfs-t:

  • csomagolja ki az initramfs-t (ha a fenti initramfs opciót használjuk, ez nem szükséges)
  • tartalmazzon kódot az indításkor, amely elemzi a /proc/cmdline-n keresztül átadott paramétereket, és továbbítja a vezérlést;
  • csomag initramfs.

Jegyzet. Az X5 toolkit esetében a betöltési vezérlés átkerül a szkriptre /opt/x5/toolkit/bin/hook.sh с помощью override.conf в getty tty1 (ExecStart=…)

Tehát a kép betöltődik, amelyben a mount.sh szkript az automatikus futtatáskor indul. Ezután a mount.sh szkript elemzi az átadott paramétereket (script_cmd=) a végrehajtás során, és elindítja a szükséges programot/szkriptet.

címke eszközkészlet-auto
kernel...
append... nfs_toolkit_script=scripts/mount.sh script_cmd=master-install.sh

címke eszközkészlet-héj
kernel...
append... nfs_toolkit_script=scripts/mount.sh script_cmd=/bin/bash

Csináld magad Bare-Metal ellátás, vagy a szerverek automatikus előkészítése a semmiből

Itt a bal oldalon a PXE menü, a jobb oldalon a vezérlés átviteli diagramja.

Kitaláltuk az irányítás átadását. A PXE menü választásától függően vagy az automatikus konfigurációs parancsfájl, vagy a hibakereső konzol indul el.

Automatikus konfigurálás esetén a telepítési szerverről felcsatolják a szükséges könyvtárakat, amelyek a következőket tartalmazzák:

  • forgatókönyvek;
  • mentett BIOS/UEFI sablonok különféle szerverekhez;
  • firmware;
  • szerver segédprogramok;
  • rönkök

Ezután a mount.sh szkript átadja a vezérlést a parancsfájlkönyvtárból a master-install.sh szkriptnek.

A szkriptfa (az indítási sorrendben) valahogy így néz ki:

  • master-install
  • sharefunctions (megosztott funkciók)
  • info (információs kimenet)
  • modellek (telepítési paraméterek beállítása a szerver modellje alapján)
  • ready_utils (a szükséges segédprogramok telepítése)
  • fwupdate (firmware frissítés)
  • diag (elemi diagnosztika)
  • biosconf (BIOS/UEFI beállítások)
  • órafix (az idő beállítása az alaplapon)
  • srmconf (távoli interfész konfigurálása)
  • raidconf (logikai kötetek beállítása)

az egyik:

  • előtelepítés (a vezérlés átvitele az operációs rendszerre vagy a hypervisor telepítőre, például az ESXi-re)
  • Merged-install (a kép kicsomagolásának azonnali kezdete)

Most már tudjuk:

  • hogyan indítsunk el egy szervert PXE-n keresztül;
  • hogyan viheti át a vezérlést a saját szkriptjére.


Folytassuk. A következő kérdések váltak aktuálissá:

  • Hogyan lehet azonosítani az éppen előkészített szervert?
  • Milyen segédprogramok és hogyan kell beállítani a szervert?
  • Hogyan szerezhetek be beállításokat egy adott szerverhez?

Hogyan lehet azonosítani az éppen előkészített szervert?

Egyszerű – DMI:

dmidecode –s system-product-name
dmidecode –s system-manufacturer
dmidecode –s system-serial-number

Itt minden megtalálható, amire szüksége van: gyártó, modell, sorozatszám. Ha nem biztos abban, hogy ez az információ minden kiszolgálón megtalálható, akkor a MAC-címük alapján azonosíthatja őket. Vagy mindkét irányban egyszerre, ha a szerver gyártók különbözőek, és egyes modelleken egyszerűen nincs információ a sorozatszámról.

A kapott információk alapján a hálózati mappák felcsatolódnak a telepítőkiszolgálóról, és minden szükséges betöltődik (segédprogramok, firmware stb.).

Milyen segédprogramok és hogyan kell beállítani a szervert?

Egyes gyártók számára biztosítok Linuxhoz segédprogramokat. Minden segédprogram elérhető a gyártók hivatalos weboldalain.

Csináld magad Bare-Metal ellátás, vagy a szerverek automatikus előkészítése a semmiből

A firmware-rel szerintem minden tiszta. Általában csomagolt futtatható fájlok formájában érkeznek. A végrehajtható fájl vezérli a firmware-frissítési folyamatot, és jelenti a visszatérési kódot.

A BIOS és az IPMI általában sablonokon keresztül konfigurálható. Szükség esetén a sablon szerkeszthető a letöltés előtt.

Egyes gyártók RAID-segédprogramjai sablon használatával is konfigurálhatók. Ha nem ez a helyzet, akkor meg kell írnia egy konfigurációs szkriptet.

A RAID beállításának folyamata leggyakrabban a következő:

  • Az aktuális konfigurációt kérjük.
  • Ha már vannak logikai tömbök, töröljük azokat.
  • Nézzük meg, milyen fizikai lemezek vannak jelen, és mennyi van.
  • Hozzon létre egy új logikai tömböt. Hiba esetén megszakítjuk a folyamatot.

Hogyan szerezhetek be beállításokat egy adott szerverhez?

Tegyük fel, hogy az összes szerver beállításai a telepítőkiszolgálón lesznek eltárolva. Ebben az esetben kérdésünk megválaszolásához először el kell döntenünk, hogyan vigyük át a beállításokat a telepítő szerverre.

Eleinte meg lehet boldogulni a szöveges fájlokkal. (A jövőben érdemes lehet szöveges fájlt használni tartalék módszerként a beállítások átviteléhez.)

A telepítőkiszolgálón „megoszthat” egy szöveges fájlt. És add hozzá a mount.sh szkripthez.

A sorok például így fognak kinézni:

<sorozatszám> <gépnév> <alhálózat>

Ezeket a sorokat a mérnök átviszi a fájlba a munkagépéről. Ezután a szerver beállításakor egy adott szerver paraméterei lesznek kiolvasva a fájlból.

De hosszú távon jobb, ha adatbázist használunk a beállítások, állapotok és a szervertelepítések naplóinak tárolására.

Természetesen egy adatbázis önmagában nem elég, hanem létre kell hozni egy kliens részt, aminek segítségével a beállítások átkerülnek az adatbázisba. Ezt nehezebb megvalósítani, mint egy szöveges fájlt, de valójában nem minden olyan nehéz, mint amilyennek látszik. Teljesen lehetséges egy olyan kliens minimális verzióját írni, amely egyszerűen átviszi az adatokat az adatbázisba. A jövőben pedig szabad módban is lehet majd fejleszteni a kliensprogramot (riportok, címkék nyomtatása, értesítések küldése stb., ami eszembe jut).

Az adatbázisnak adott konkrét kéréssel és a szerver sorozatszámának megadásával megkapjuk a szerver konfigurálásához szükséges paramétereket.

Ráadásul nem kell zárakat kitalálnunk az egyidejű hozzáféréshez, mint a szöveges fájl esetében.

A konfigurációs naplót minden szakaszban írhatjuk az adatbázisba, és irányíthatjuk a telepítési folyamatot eseményeken és az előkészítési szakaszok zászlóin keresztül.

Most már tudjuk, hogyan:

  • indítsa el a szervert PXE-n keresztül;
  • átviszi a vezérlést a szkriptünkre;
  • a sorozatszám alapján azonosítani kell az előkészítendő szervert;
  • konfigurálja a kiszolgálót a megfelelő segédprogramokkal;
  • a beállítások átvitele a telepítőkiszolgáló adatbázisába a kliens rész segítségével.

Megtudtuk, hogyan:

  • a telepített szerver megkapja a szükséges beállításokat az adatbázisból;
  • minden felkészülési folyamat rögzítve van az adatbázisban (naplók, események, szakaszjelzők).

Mi a helyzet a különböző típusú szoftverekkel, amelyeket telepít? Hogyan lehet hipervizort telepíteni, virtuális gépet másolni és mindezt beállítani?

Fájlrendszerkép (linux) hardverre történő telepítése esetén minden meglehetősen egyszerű:

  • Az összes szerverösszetevő beállítása után telepítjük a lemezképet.
  • Telepítse a grub rendszerbetöltőt.
  • Mindent chrootolunk és konfigurálunk, ami szükséges.

A vezérlés átadása az operációs rendszer telepítőjének (például az ESXi használatával).

  • Az automatikus válaszfájl (kickstart) segítségével megszervezzük az irányítás átadását a szkriptünkről a hypervisor telepítőre:
  • Töröljük a lemez aktuális partícióit.
  • Hozzon létre egy 500 MB méretű partíciót.
  • Bootolhatónak jelöljük.
  • Formázza FAT32-re.
  • Az ESXi telepítőfájlokat a gyökérbe másoljuk.
  • Syslinux telepítése.
  • Másolja a syslinux.cfg fájlt a /syslinux/ mappába

default esxi
prompt 1
timeout 50
label esxi
kernel mboot.c32
append -c boot.cfg

  • Másolja az mboot.c32 fájlt a /syslinux mappába.
  • A Boot.cfg fájlnak a következőnek kell lennie: kernelopt=ks=ftp:// /ks_esxi.cfg
  • Újraindítjuk a szervert.

A szerver újraindítása után az ESXi telepítő letöltődik a szerver merevlemezéről. Az összes szükséges telepítőfájl betöltődik a memóriába, majd megkezdődik az ESXi telepítése a megadott automatikus válaszfájlnak megfelelően.

Íme néhány sor a ks_esxi.cfg automatikus válaszfájlból:

%firstboot --interpreter=busybox
…
# получаем серийный номер

SYSSN=$(esxcli hardware platform get | grep Serial | awk -F " " '{print $3}')

# получаем IP

IPADDRT=$(esxcli network ip interface ipv4 get | grep vmk0 | awk -F " " '{print $2}')
LAST_OCTET=$(echo $IPADDRT | awk -F'.' '{print $4}')

# подключаем NFS инсталл-сервера

esxcli storage nfs add -H is -s /srv/nfs_share -v nfsshare1

# копируем временные настройки ssh, для использования ssh-клиента

mv /etc/ssh /etc/ssh.tmp
cp -R /vmfs/volumes/nfsshare1/ssh /etc/
chmod go-r /etc/ssh/ssh_host_rsa_key

# копируем ovftool, для развертывания ВМ сейчас, плюс возможно пригодится позже

cp -R /vmfs/volumes/nfsshare1/ovftool /vmfs/volumes/datastore1/

# развертываем ВМ

/vmfs/volumes/datastore1/ovftool/tools/ovftool --acceptAllEulas --noSSLVerify --datastore=datastore1 --name=VM1 /vmfs/volumes/nfsshare1/VM_T/VM1.ova vi://root:[email protected]
/vmfs/volumes/datastore1/ovftool/tools/ovftool --acceptAllEulas --noSSLVerify --datastore=datastore1 --name=VM2 /vmfs/volumes/nfsshare1/VM_T/VM2.ova vi://root:[email protected]

# получаем строку с настройками нашего сервера

ssh root@is "mysql -h'192.168.0.1' -D'servers' -u'user' -p'secretpassword' -e "SELECT ... WHERE servers.serial='$SYSSN'"" | grep -v ^$ | sed 's/NULL//g' > /tmp/servers
...
# генерируем скрипт настройки сети

echo '#!/bin/sh' > /vmfs/volumes/datastore1/netconf.sh
echo "esxcli network ip interface ipv4 set -i=vmk0 -t=static --ipv4=$IPADDR --netmask=$S_SUB || exit 1" >> /vmfs/volumes/datastore1/netconf.sh
echo "esxcli network ip route ipv4 add -g=$S_GW -n=default || exit 1" >> /vmfs/volumes/datastore1/netconf.sh
chmod a+x /vmfs/volumes/datastore1/netconf.sh

# задаем параметр guestinfo.esxihost.id, указываем в нем серийный номер

echo "guestinfo.esxihost.id = "$SYSSN"" >> /vmfs/volumes/datastore1/VM1/VM1.vmx
echo "guestinfo.esxihost.id = "$SYSSN"" >> /vmfs/volumes/datastore1/VM2/VM2.vmx
...
# обновляем информацию в базе

SYSNAME=$(esxcli hardware platform get | grep Product | sed 's/Product Name://' | sed 's/^ *//')
UUID=$(vim-cmd hostsvc/hostsummary | grep uuid | sed 's/ //g;s/,$//' | sed 's/^uuid="//;s/"$//')
ssh root@is "mysql -D'servers' -u'user' -p'secretpassword' -e "UPDATE servers ... SET ... WHERE servers.serial='$SYSSN'""
ssh root@is "mysql -D'servers' -u'user' -p'secretpassword' -e "INSERT INTO events ...""

# возвращаем настройки SSH

rm -rf /etc/ssh
mv /etc/ssh.tmp /etc/ssh

# настраиваем сеть и перезагружаемся

esxcli system hostname set --fqdn=esx-${G_NICK}.x5.ru
/vmfs/volumes/datastore1/netconf.sh
reboot

Ebben a szakaszban megtörténik a hypervisor telepítése és konfigurálása, valamint a virtuális gépek másolása.

Hogyan lehet most beállítani a virtuális gépeket?

Kicsit csaltunk: a telepítés során a VM1.vmx fájlban beállítottuk a guestinfo.esxihost.id = "$SYSSN" paramétert és feltüntettük benne a fizikai szerver sorozatszámát.

Most, az indítás után a virtuális gép (amelyben a vmware-tools csomag telepítve van) hozzáférhet ehhez a paraméterhez:

ESXI_SN=$(vmtoolsd --cmd "info-get guestinfo.esxihost.id")

Vagyis a virtuális gép képes lesz azonosítani magát (tudja a fizikai gazdagép sorozatszámát), kérést intézni a telepítőkiszolgáló adatbázisához és megkapni a konfigurálandó paramétereket. Mindez egy szkriptbe van fordítva, amelynek automatikusan el kell indulnia a guestos vm indításakor (de egyszer: RunOnce).

Most már tudjuk, hogyan:

  • indítsa el a szervert PXE-n keresztül;
  • átviszi a vezérlést a szkriptünkre;
  • a sorozatszám alapján azonosítani kell az előkészítendő szervert;
  • konfigurálja a kiszolgálót a megfelelő segédprogramokkal;
  • beállítások átvitele a telepítési szerver adatbázisba a kliens rész segítségével;
  • különféle típusú szoftverek konfigurálása, beleértve az esxi hypervisor telepítését és a virtuális gépek konfigurálását (mindezt automatikusan).

Megtudtuk, hogyan:

  • a telepített szerver megkapja a szükséges beállításokat az adatbázisból;
  • minden felkészülési folyamat rögzítve van az adatbázisban (naplók, események, szakaszjelzők).


Az alsó sor:

Úgy gondolom, hogy ennek a megoldásnak az egyedisége a rugalmasságában, egyszerűségében, képességeiben és sokoldalúságában rejlik.

Kérlek írd meg kommentben, hogy mit gondolsz.

Forrás: will.com

Hozzászólás