Faru mem Nudmetalan Provizadon aŭ Aŭtomatan preparadon de serviloj de nulo

Saluton, mi estas Denis kaj unu el miaj agadkampoj estas la disvolviĝo de infrastrukturaj solvoj ĉe X5. Hodiaŭ mi ŝatus dividi kun vi kiel vi povas deploji aŭtomatan servilan preparsistemon bazitan sur publike disponeblaj iloj. Laŭ mi, ĉi tio estas interesa, simpla kaj fleksebla solvo.

Faru mem Nudmetalan Provizadon aŭ Aŭtomatan preparadon de serviloj de nulo

Per preparado ni volas diri: turni novan servilon el la skatolo en plene agordita servilo kun OS. Linukso aŭ kun la hiperviziero ESXi (la deplojo de Vindozaj serviloj ne estas diskutita en ĉi tiu artikolo).

Kondiĉoj:

  • serviloj - serviloj kiuj devas esti agorditaj.
  • instala servilo estas la ĉefa servilo kiu provizas la tutan preparprocezon tra la reto.

Kial necesas aŭtomatigo?

Ni diru, ke ekzistas tasko: amase prepari servilojn de nulo, ĉe pinto - 30 tage. Serviloj de malsamaj produktantoj kaj modeloj, malsamaj operaciumoj povas esti instalitaj sur ili, kaj povas aŭ eble ne havas hipervizion.

Kiaj operacioj estas inkluzivitaj en la agorda procezo (sen aŭtomatigo):

  • konekti klavaron, muson, monitoron al la servilo;
  • agordi BIOS, RAID, IPMI;
  • ĝisdatigi komponan firmware;
  • deploji dosiersisteman bildon (aŭ instali hiperviziilon kaj kopii virtualajn maŝinojn);

Notu. Alternative, OS-deplojo eblas per instalado kun aŭtomata responda dosiero. Sed ĉi tio ne estos diskutita en la artikolo. Kvankam vi vidos sube, ke aldoni ĉi tiun funkcion ne estas malfacila.

  • agordi OS-parametrojn (gastigantonomo, IP, ktp.).

Kun ĉi tiu aliro, la samaj agordoj estas faritaj sinsekve sur ĉiu servilo. La efikeco de tia laboro estas tre malalta.

La esenco de aŭtomatigo estas forigi homan partoprenon de la servila preparprocezo. Kiel eble plej multe.

Aŭtomatigo reduktas malfunkcion inter operacioj kaj ebligas provizi plurajn servilojn samtempe. La verŝajneco de eraroj pro homaj faktoroj ankaŭ estas tre reduktita.

Faru mem Nudmetalan Provizadon aŭ Aŭtomatan preparadon de serviloj de nulo

Kiel serviloj aŭtomate agordas?

Ni analizu ĉiujn stadiojn detale.

Vi havas Linuksan servilon, kiun vi uzas kiel PXE-instala servilo. Servoj estas instalitaj kaj agorditaj sur ĝi: DHCP, TFTP.

Do, ni ekfunkciigas la servilon (kiu devas esti agordita) per PXE. Ni memoru kiel ĝi funkcias:

  • Reta lanĉo estas elektita sur la servilo.
  • La servilo ŝarĝas la PXE-ROM de la retkarto kaj kontaktas la instalan servilon per DHCP por akiri retadreson.
  • La DHCP-instalservilo donas adreson, same kiel instrukciojn por plua elŝuto per PXE.
  • La servilo ŝarĝas la retan ekŝargilon de la instala servilo per PXE, plua ŝarĝo okazas laŭ la agorda dosiero de PXE.
  • La ekkuro okazas surbaze de la ricevitaj parametroj (kerno, initramfs, muntado-punktoj, squashfs-bildo, ktp.).

Notu. La artikolo priskribas lanĉadon per PXE per BIOS-reĝimo. Nuntempe, fabrikistoj aktive efektivigas UEFI-botreĝimon. Por PXE, la diferenco estos en la agordo de la DHCP-servilo kaj la ĉeesto de plia ekŝargilo.

Ni rigardu ekzemplon de agordo de PXE-servilo (pxelinux menuo).

Dosiero pxelinux.cfg/default:

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 // переход на следующее меню

Dosiero pxelinux.cfg/toolkit:

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=”…”

La kerno kaj initramfs en ĉi tiu etapo estas meza Linuksa bildo, per kies helpo okazos la ĉefa preparado kaj agordo de la servilo.

Kiel vi povas vidi, la ekŝargilo pasas multajn parametrojn al la kerno. Kelkaj el ĉi tiuj parametroj estas uzataj de la kerno mem. Kaj ni povas uzi iujn por niaj propraj celoj. Ĉi tio estos diskutita poste, sed nuntempe vi nur povas memori, ke ĉiuj preterpasitaj parametroj estos disponeblaj en la meza Linuksa bildo per /proc/cmdline.

Kie mi povas akiri ilin, kernon kaj initramfs?
Kiel bazo, vi povas elekti ajnan Linuksan distribuon. Kion ni atentas kiam ni elektas:

  • la ekbildo devas esti universala (havebleco de ŝoforoj, kapablo instali pliajn utilecojn);
  • Plej verŝajne, vi devos personecigi la initramfs.

Kiel tio estas farita en nia solvo por X5? Kiel bazo estis elektita CentOS 7. Ni provu la sekvan lertaĵon: preparu la estontan bildstrukturon, paku ĝin en arkivon kaj kreu initramfs, ene de kiu estos nia dosiersistemo-arkivo. Dum ŝarĝo de la bildo, la arkivo estos vastigita en la kreitan tmpfs-diskon. Tiel ni ricevos minimuman, tamen plenrajtan vivan linuksan bildon kun ĉiuj necesaj iloj, konsistante el nur du dosieroj: vmkernel kaj 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

Do ni specifis la kernon kaj initramfs kiuj devus esti ŝargitaj. Kiel rezulto, en ĉi tiu etapo, ŝarĝante la interan linuksan bildon per PXE, ni ricevos la OS-konzolon.

Bonege, sed nun ni devas transdoni kontrolon al nia "aŭtomatigo".

Ĝi povas esti farita tiel.

Ni supozu, ke post ŝarĝo de la bildo ni planas transdoni kontrolon al la skripto mount.sh.
Ni inkludu la skripton mount.sh en aŭtorun. Por fari tion, vi devos modifi la initramfs:

  • malpaki initramfs (se ni uzas la supran initramfs opcion, ĉi tio ne estas bezonata)
  • inkluzivi kodon en lanĉo, kiu analizos la parametrojn trapasitajn tra /proc/cmdline kaj transdonos kontrolon plu;
  • paki initramfs.

Notu. En la kazo de la ilaro X5, ŝarĝa kontrolo estas transdonita al la skripto /opt/x5/toolkit/bin/hook.sh с помощью override.conf в getty tty1 (ExecStart=…)

Do, la bildo estas ŝarĝita, en kiu la skripto mount.sh komenciĝas ĉe aŭtorun. Poste, la mount.sh-skripto analizas la preterpasitajn parametrojn (script_cmd=) dum ekzekuto kaj lanĉas la necesan programon/skripton.

etikedo ilaro-aŭto
kerno...
aldoni... nfs_toolkit_script=scripts/mount.sh script_cmd=master-install.sh

etikedo ilaro-ŝelo
kerno...
aldoni... nfs_toolkit_script=scripts/mount.sh script_cmd=/bin/bash

Faru mem Nudmetalan Provizadon aŭ Aŭtomatan preparadon de serviloj de nulo

Ĉi tie maldekstre estas la PXE-menuo, dekstre la diagramo de kontrolo de transdono.

Ni eltrovis la translokigon de kontrolo. Depende de la elekto de la PXE-menuo, aŭ la aŭtomata agorda skripto aŭ la sencimiga konzolo estas lanĉitaj.

En la kazo de aŭtomata agordo, la necesaj dosierujoj estas muntitaj de la instala servilo, kiuj enhavas:

  • skriptoj;
  • konservitaj BIOS/UEFI-ŝablonoj por diversaj serviloj;
  • firmvaro;
  • serviloj;
  • ŝtipoj

Poste, la skripto mount.sh transigas kontrolon al la skripto master-install.sh de la skripto-dosierujo.

La skripto-arbo (la ordo en kiu ili estas lanĉitaj) aspektas kiel ĉi tio:

  • majstro-instali
  • sharefunctions (kunhavaj funkcioj)
  • info (informa eligo)
  • modeloj (agordante instalajn parametrojn surbaze de la servila modelo)
  • prepare_utils (instalado de necesaj iloj)
  • fwupdate (firmware ĝisdatigo)
  • diag (elementa diagnozo)
  • biosconf (agordoj de BIOS/UEFI)
  • horloĝo (agordante la horon sur la baztabulo)
  • srmconf (fora interfaca agordo)
  • raidconf (agordado de logikaj volumoj)

unu el:

  • antaŭinstali (transdonante kontrolon al la OS aŭ hipervizila instalilo, kiel ESXi)
  • merged-install (tuja komenco de malpakado de la bildo)

Nun ni scias:

  • kiel ekbruligi servilon per PXE;
  • kiel transdoni kontrolon al via propra skripto.


Ni daŭrigu. La sekvaj demandoj iĝis gravaj:

  • Kiel identigi la servilon, kiun ni preparas?
  • Kiuj utilecoj kaj kiel agordi la servilon?
  • Kiel akiri agordojn por specifa servilo?

Kiel identigi la servilon, kiun ni preparas?

Ĝi estas simpla - DMI:

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

Ĉio, kion vi bezonas, estas ĉi tie: vendisto, modelo, seria numero. Se vi ne certas, ke ĉi tiuj informoj ĉeestas en ĉiuj serviloj, vi povas identigi ilin per ilia MAC-adreso. Aŭ ambaŭmaniere samtempe, se la servilaj vendistoj estas malsamaj kaj en iuj modeloj simple ne ekzistas informoj pri la seria numero.

Surbaze de la ricevitaj informoj, retaj dosierujoj estas muntitaj de la instala servilo kaj ĉio necesa estas ŝarĝita (utilaĵoj, firmware, ktp.).

Kiuj utilecoj kaj kiel agordi la servilon?

Mi provizos ilojn por Linukso por iuj fabrikantoj. Ĉiuj utilecoj haveblas en la oficialaj retejoj de vendistoj.

Faru mem Nudmetalan Provizadon aŭ Aŭtomatan preparadon de serviloj de nulo

Kun la firmware, mi pensas, ke ĉio estas klara. Ili kutime venas en la formo de pakitaj ruleblaj dosieroj. La rulebla dosiero kontrolas la procezon de ĝisdatigo de firmware kaj raportas la revenkodon.

BIOS kaj IPMI estas kutime agorditaj per ŝablonoj. Se necese, la ŝablono povas esti redaktita antaŭ elŝuto.

RAID-servaĵoj de kelkaj vendistoj ankaŭ povas esti agorditaj uzante ŝablonon. Se ĉi tio ne estas la kazo, tiam vi devos skribi agordan skripton.

La proceduro por agordi RAID plej ofte estas jena:

  • Ni petas la nunan agordon.
  • Se jam ekzistas logikaj tabeloj, ni forigas ilin.
  • Ni rigardu kiajn fizikajn diskojn ĉeestas kaj kiom da estas.
  • Kreu novan logikan tabelon. Ni interrompas la procezon en kazo de eraro.

Kiel akiri agordojn por specifa servilo?

Ni supozu, ke la agordoj de ĉiuj serviloj estos stokitaj sur la instala servilo. En ĉi tiu kazo, por respondi nian demandon, ni unue devas decidi kiel translokigi la agordojn al la instala servilo.

Komence, vi povas elteni tekstajn dosierojn. (Estonte, vi eble volas uzi tekstdosieron kiel rezervan metodon por transdoni agordojn.)

Vi povas "kunhavi" tekstdosieron sur la instala servilo. Kaj aldonu ĝian monton al la skripto mount.sh.

La linioj, ekzemple, aspektos jene:

<seria numero> <gastigantonomo> <subreto>

Ĉi tiuj linioj estos transdonitaj al la dosiero fare de la inĝeniero de sia labormaŝino. Kaj tiam, kiam oni agordas servilon, la parametroj por specifa servilo estos legitaj el la dosiero.

Sed, longtempe, estas pli bone uzi datumbazon por konservi agordojn, statojn kaj protokolojn de servilaj instalaĵoj.

Kompreneble, datumbazo sole ne sufiĉas, kaj vi devos krei klientan parton kun la helpo de kiuj agordoj estos translokigitaj al la datumbazo. Ĉi tio estas pli malfacile efektivigi kompare kun tekstdosiero, sed fakte ĉio ne estas tiel malfacila kiel ŝajnas. Estas tute eble verki minimuman version de kliento, kiu simple translokigos datumojn al la datumbazo mem. Kaj estonte eblos plibonigi la klientprogramon en senpaga reĝimo (raportoj, presado de etikedoj, sendado de sciigoj, ktp., kio venas al la menso).

Farante specifan peton al la datumbazo kaj specifante la servilon serian numeron, ni ricevos la necesajn parametrojn por agordi la servilon.

Krome, ni ne bezonos elpensi serurojn por samtempa aliro, kiel estas la kazo kun tekstdosiero.

Ni povas skribi la agordan protokolon al la datumbazo en ĉiuj etapoj kaj kontroli la instalan procezon per eventoj kaj flagoj de la preparaj etapoj.

Nun ni scias kiel:

  • lanĉu la servilon per PXE;
  • translokigi kontrolon al nia skripto;
  • identigu la servilon, kiun oni devas prepari per sia seria numero;
  • agordi la servilon uzante la taŭgajn ilojn;
  • translokigi agordojn al la instala servila datumbazo uzante la klientparton.

Ni eksciis kiel:

  • la instalita servilo ricevas la necesajn agordojn de la datumbazo;
  • ĉiu preparprogreso estas registrita en la datumbazo (protokoloj, eventoj, etapaj flagoj).

Kio pri la malsamaj specoj de programaro, kiun vi instalas? Kiel instali hiperviziilon, kopii VM kaj agordi ĉion?

En la kazo de deploji dosiersisteman bildon (Linukso) al aparataro, ĉio estas sufiĉe simpla:

  • Post agordo de ĉiuj servilaj komponantoj, ni deplojas la bildon.
  • Instalu la grub-ŝargilon.
  • Ni chroot kaj agordas ĉion, kio necesas.

Kiel transdoni kontrolon al la OS-instalilo (uzante ESXi kiel ekzemplon).

  • Ni organizas la translokigon de kontrolo de nia skripto al la instalilo de hiperviziero uzante la aŭtomatan responddosieron (kickstart):
  • Ni forigas la nunajn subdiskojn sur la disko.
  • Kreu sekcion kun grandeco de 500MB.
  • Ni markas ĝin kiel startebla.
  • Formatu al FAT32.
  • Kopiu la instalajn dosierojn de ESXi al la radiko de ĝi.
  • Instalante syslinux.
  • Kopiu syslinux.cfg al /syslinux/

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

  • Kopiu mboot.c32 al /syslinux.
  • Boot.cfg devus havi kernelopt=ks=ftp:// /ks_esxi.cfg
  • Ni rekomencas la servilon.

Post kiam la servilo rekomencas, la instalilo ESXi elŝutos el la malmola disko de la servilo. Ĉiuj necesaj instaliloj estos ŝarĝitaj en memoron kaj tiam la instalado de ESXi komenciĝos, laŭ la specifita aŭtoresponda dosiero.

Jen kelkaj linioj de la aŭtoresponda dosiero ks_esxi.cfg:

%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

En ĉi tiu etapo, la hiperviziero estas instalita kaj agordita, kaj virtualaj maŝinoj estas kopiitaj.

Kiel agordi virtualajn maŝinojn nun?

Ni trompis iomete: dum instalado ni starigis la parametron guestinfo.esxihost.id = "$SYSSN" en la dosiero VM1.vmx kaj indikis la serian numeron de la fizika servilo en ĝi.

Nun, post ekfunkciigo, la virtuala maŝino (kun la pako vmware-tools instalita) povas aliri ĉi tiun parametron:

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

Tio estas, la VM povos identigi sin (ĝi konas la serian numeron de la fizika gastiganto), fari peton al la instalaĵservila datumbazo kaj ricevi la parametrojn, kiujn oni devas agordi. Ĉio ĉi estas kompilita en skripton, kiu devus esti lanĉita aŭtomate kiam guestos vm komenciĝas (sed unufoje: RunOnce).

Nun ni scias kiel:

  • lanĉu la servilon per PXE;
  • translokigi kontrolon al nia skripto;
  • identigu la servilon, kiun oni devas prepari per sia seria numero;
  • agordi la servilon uzante la taŭgajn ilojn;
  • translokigi agordojn al la instala servila datumbazo uzante la klientparton;
  • agordi diversajn specojn de programaro, inkluzive de deplojado de la hiperviziero esxi kaj agordo de virtualaj maŝinoj (ĉiuj aŭtomate).

Ni eksciis kiel:

  • la instalita servilo ricevas la necesajn agordojn de la datumbazo;
  • ĉiu preparprogreso estas registrita en la datumbazo (protokoloj, eventoj, etapaj flagoj).


Funda linio:

Mi kredas, ke la unikeco de ĉi tiu solvo kuŝas en sia fleksebleco, simpleco, kapabloj kaj ĉiuflankeco.

Bonvolu skribi en la komentoj kion vi pensas.

fonto: www.habr.com

Aldoni komenton