Linux het baie gesigte: hoe om aan enige verspreiding te werk

Linux het baie gesigte: hoe om aan enige verspreiding te werk

Om 'n rugsteuntoepassing te skep wat op enige verspreiding werk, is geen maklike taak nie. Om te verseker dat Veeam Agent vir Linux werk op verspreidings vanaf Red Hat 6 en Debian 6, na OpenSUSE 15.1 en Ubuntu 19.04, moet jy 'n reeks probleme oplos, veral as in ag geneem word dat die sagtewareproduk 'n kernmodule insluit.

Die artikel is geskep op grond van materiaal van 'n toespraak by die konferensie Linux Peter 2019.

Linux is nie net een van die gewildste bedryfstelsels nie. In wese is dit 'n platform op grond waarvan jy iets uniek kan maak, iets van jou eie. Danksy dit het Linux baie verspreidings wat verskil in hul stel sagtewarekomponente. En hier ontstaan ​​'n probleem: om 'n sagtewareproduk op enige verspreiding te laat funksioneer, moet jy die kenmerke van elkeen in ag neem.

Pakketbestuurders. .deb teenoor .rpm

Kom ons begin met die ooglopende probleem om die produk oor verskillende verspreidings te versprei.
Die mees tipiese manier om sagtewareprodukte te versprei, is om die pakket op 'n bewaarplek te plaas sodat die pakketbestuurder wat in die stelsel ingebou is, dit van daar af kan installeer.
Ons het egter twee gewilde pakketformate: rpm и deb. Dit beteken almal sal moet ondersteun.

In die wêreld van deb-pakkette is die vlak van verenigbaarheid ongelooflik. Dieselfde pakket installeer en werk ewe goed op beide Debian 6 en Ubuntu 19.04. Die standaarde vir die proses om pakkette te bou en daarmee te werk, wat in ou Debian-verspreidings neergelê is, bly relevant in die nuwerwetse Linux Mint en elementêre bedryfstelsel. Daarom, in die geval van Veeam Agent vir Linux, is een deb-pakket vir elke hardewareplatform voldoende.

Maar in die wêreld van rpm-pakkette is die verskille groot. Eerstens, as gevolg van die feit dat daar twee heeltemal onafhanklike verspreiders is, Red Hat en SUSE, waarvoor versoenbaarheid heeltemal onnodig is. Tweedens, hierdie verspreiders het verspreidingsstelle van daardie. ondersteunend en eksperimenteel. Daar is ook geen behoefte aan verenigbaarheid tussen hulle nie. Dit het geblyk dat el6, el7 en el8 hul eie pakkette het. Afsonderlike pakket vir Fedora. Pakkette vir SLES11 en 12 en 'n aparte een vir openSUSE. Die grootste probleem is afhanklikhede en pakketname.

Afhanklikheidsprobleem

Ongelukkig beland dieselfde pakkette dikwels onder verskillende name in verskillende verspreidings. Hieronder is 'n gedeeltelike lys van veeam-pakketafhanklikhede.

Vir EL7:
Vir SLES 12:

  • libblkid
  • libgcc
  • libstdc++
  • ncurses-libs
  • lont-libs
  • lêer-libs
  • veeamsnap=3.0.2.1185
  • libblkid1
  • libgcc_s1
  • libstdc++6
  • libmagic1
  • libfuse2
  • veeamsnap-kmp=3.0.2.1185

As gevolg hiervan is die lys van afhanklikhede uniek vir die verspreiding.

Wat erger word, is wanneer 'n opgedateerde weergawe onder die ou pakketnaam begin skuil.

Voorbeeld:

Die pakket is opgedateer in Fedora 24 vloeke van weergawe 5 tot weergawe 6. Ons produk is met weergawe 5 gebou om verenigbaarheid met ouer verspreidings te verseker. Om die ou 5de weergawe van die biblioteek op Fedora 24 te gebruik, moes ek die pakket gebruik ncurses-compat-libs.

As gevolg hiervan is daar twee pakkette vir Fedora, met verskillende afhanklikhede.

Verder meer interessant. Na die volgende verspreidingsopdatering, die pakket ncurses-compat-libs met weergawe 5 van die biblioteek blyk dit nie beskikbaar te wees nie. Dit is duur vir 'n verspreider om ou biblioteke na 'n nuwe weergawe van die verspreiding in te sleep. Na 'n ruk het die probleem homself herhaal in SUSE-verspreidings.

Gevolglik moes sommige verspreidings hul eksplisiete afhanklikheid van ncurses-libs, en maak die produk reg sodat dit met enige weergawe van die biblioteek kan werk.

Terloops, in weergawe 8 van Red Hat is daar nie meer 'n metapakket nie python, wat na die goeie ou verwys het python 2.7... daar is python2 и python3.

Alternatief vir pakketbestuurders

Die probleem met afhanklikhede is oud en is lankal duidelik. Onthou net Afhanklikheid hel.
Om verskeie biblioteke en toepassings te kombineer sodat hulle almal stabiel werk en nie bots nie – dit is eintlik die taak wat enige Linux-verspreider probeer oplos.

Die pakketbestuurder probeer om hierdie probleem op 'n heeltemal ander manier op te los. Snappy van Canonical. Die hoofgedagte: die toepassing loop in 'n sandbox wat geïsoleer en beskerm is van die hoofstelsel. Indien 'n toepassing biblioteke benodig, word hulle saam met die toepassing self voorsien.

Flatpak laat jou ook toe om toepassings in 'n sandbox te laat loop deur Linux-houers te gebruik. Die sandbox-idee word ook gebruik AppImage.

Hierdie oplossings laat jou toe om een ​​pakket vir enige verspreiding te skep. In die geval van Flatpak installasie en bekendstelling van die toepassing is moontlik selfs sonder die administrateur se medewete.

Die grootste probleem is dat nie alle toepassings in 'n sandbox kan loop nie. Sommige mense benodig direkte toegang tot die platform. Ek praat nie eers van kernmodules nie, wat streng van die kern afhanklik is en nie by die sandbox-konsep inpas nie.

Die tweede probleem is dat verspreidings wat gewild is in die ondernemingsomgewing vanaf Red Hat en SUSE nog nie ondersteuning vir Snappy en Flatpak bevat nie.

In hierdie verband is Veeam Agent vir Linux nie beskikbaar nie snapcraft.io nie aan nie flathub.org.

Om die vraag oor pakketbestuurders af te sluit, wil ek daarop let dat daar 'n opsie is om pakketbestuurders heeltemal te laat vaar deur binêre lêers en 'n skrip te kombineer om dit in een pakket te installeer.

So 'n bundel laat jou toe om een ​​gemeenskaplike pakket vir verskillende verspreidings en platforms te skep, 'n interaktiewe installasieproses uit te voer, die nodige aanpassing uit te voer. Ek het net sulke pakkette vir Linux van VMware teëgekom.

Opdateer probleem

Linux het baie gesigte: hoe om aan enige verspreiding te werk
Selfs al is alle afhanklikheidskwessies opgelos, kan die program anders loop op dieselfde verspreiding. Dit is 'n kwessie van opdaterings.

Daar is 3 opdateringstrategieë:

  • Die eenvoudigste een is om nooit op te dateer nie. Ek het die bediener opgestel en daarvan vergeet. Waarom opdateer as alles werk? Probleme begin die eerste keer dat jy ondersteuning kontak. Die skepper van die verspreiding ondersteun slegs die opgedateerde vrystelling.
  • Jy kan die verspreider vertrou en outomatiese opdaterings opstel. In hierdie geval is 'n oproep na ondersteuning waarskynlik onmiddellik na 'n onsuksesvolle opdatering.
  • Die opsie van handmatige opdatering slegs nadat dit op 'n toetsinfrastruktuur uitgevoer is, is die betroubaarste, maar duur en tydrowend. Nie almal kan dit bekostig nie.

Aangesien verskillende gebruikers verskillende opdateringstrategieë gebruik, is dit nodig om beide die nuutste weergawe en alle voorheen vrygesteldes te ondersteun. Dit bemoeilik beide die ontwikkelings- en toetsproses en voeg hoofpyn by die ondersteuningspan.

Verskeidenheid hardeware platforms

Verskillende hardeware-platforms is 'n probleem wat grootliks spesifiek is vir inheemse kode. Op 'n minimum moet jy binaries vir elke ondersteunde platform insamel.

In die Veeam Agent for Linux-projek kan ons steeds niks soos hierdie RISC ondersteun nie.

Ek gaan nie in detail oor hierdie kwessie stilstaan ​​nie. Ek sal net die hoofprobleme uiteensit: platformafhanklike tipes, soos size_t, struktuurbelyning en greepvolgorde.

Statiese en/of dinamiese koppeling

Linux het baie gesigte: hoe om aan enige verspreiding te werk
Maar die vraag is "Hoe om met biblioteke te skakel - dinamies of staties?" die moeite werd om te bespreek.

As 'n reël gebruik C/C++-toepassings onder Linux dinamiese skakeling. Dit werk uitstekend as die toepassing spesifiek vir 'n spesifieke verspreiding gebou is.

As die taak is om verskeie verspreidings met een binêre lêer te dek, dan moet jy fokus op die oudste ondersteunde verspreiding. Vir ons is dit Red Hat 6. Dit bevat gcc 4.4, wat selfs die C++11-standaard nie ondersteun nie ten volle.

Ons bou ons projek met behulp van gcc 6.3, wat C++14 ten volle ondersteun. Natuurlik, in hierdie geval, op Red Hat 6 moet u die libstdc++ dra en biblioteke 'n hupstoot gee. Die maklikste manier is om staties na hulle te skakel.

Maar helaas, nie alle biblioteke kan staties gekoppel word nie.

Eerstens, stelselbiblioteke soos libfuse, libblkid dit is nodig om dinamies te koppel om hul verenigbaarheid met die kern en sy modules te verseker.

Tweedens is daar 'n subtiliteit met lisensies.

Die GPL-lisensie laat jou basies toe om biblioteke net met oopbronkode te koppel. MIT en BSD laat statiese koppeling toe en laat biblioteke toe om by 'n projek ingesluit te word. Maar dit lyk asof die LGPL nie statiese koppeling weerspreek nie, maar vereis dat die lêers wat nodig is vir koppeling gedeel word.

Oor die algemeen sal die gebruik van dinamiese skakeling verhoed dat jy enigiets hoef te verskaf.

Bou C/C++ toepassings

Om C/C++-toepassings vir verskillende platforms en verspreidings te bou, is dit genoeg om 'n geskikte weergawe van gcc te kies of te bou en kruissamestellers vir spesifieke argitekture te gebruik en die hele stel biblioteke saam te stel. Hierdie werk is redelik haalbaar, maar nogal lastig. En daar is geen waarborg dat die geselekteerde samesteller en biblioteke 'n werkbare weergawe sal verskaf nie.

'n Voor die hand liggende voordeel: die infrastruktuur is baie vereenvoudig, aangesien die hele bouproses op een masjien voltooi kan word. Daarbenewens is dit genoeg om een ​​stel binaries vir een argitektuur te versamel en jy kan dit in pakkette vir verskillende verspreidings verpak. Dit is hoe veeam-pakkette vir Veeam Agent vir Linux gebou word.

In teenstelling met hierdie opsie, kan jy eenvoudig 'n bouplaas voorberei, dit wil sê verskeie masjiene vir montering. Elke sodanige masjien sal toepassingsamestelling en pakketsamestelling vir 'n spesifieke verspreiding en 'n spesifieke argitektuur verskaf. In hierdie geval word samestelling uitgevoer met behulp van die middele wat deur die verspreider voorberei is. Dit wil sê, die stadium van die voorbereiding van die samesteller en die keuse van biblioteke word uitgeskakel. Daarbenewens kan die bouproses maklik geparalleliseer word.

Daar is egter 'n nadeel aan hierdie benadering: vir elke verspreiding binne dieselfde argitektuur, sal jy jou eie stel binêre lêers moet versamel. Nog 'n nadeel is dat so 'n groot aantal masjiene in stand gehou moet word en 'n groot hoeveelheid skyfspasie en RAM moet toegewys word.

Dit is hoe KMOD-pakkette van die veeamsnap kernmodule saamgestel word vir Red Hat-verspreidings.

Maak Boudiens oop

Kollegas van SUSE het probeer om 'n middelweg te implementeer in die vorm van 'n spesiale diens vir die samestelling van toepassings en die samestelling van pakkette - oopboudiens.

In wese is dit 'n hiperviseerder wat 'n virtuele masjien skep, al die nodige pakkette daarin installeer, die toepassing saamstel en die pakket in hierdie geïsoleerde omgewing bou, waarna die virtuele masjien vrygestel word.

Linux het baie gesigte: hoe om aan enige verspreiding te werk

Die skeduleerder wat in OpenBuildService geïmplementeer is, sal bepaal hoeveel virtuele masjiene dit kan begin vir optimale pakketbouspoed. Die ingeboude ondertekeningsmeganisme sal die pakkette onderteken en oplaai na die ingeboude bewaarplek. Die ingeboude weergawebeheerstelsel sal die geskiedenis van veranderinge en bouwerk stoor. Al wat oorbly is om eenvoudig jou bronne by hierdie stelsel te voeg. U hoef nie eers die bediener self op te stel nie; u kan 'n oop een gebruik.

Daar is egter 'n probleem: so 'n stroper is moeilik om in die bestaande infrastruktuur in te pas. Byvoorbeeld, weergawebeheer is nie nodig nie; ons het reeds ons eie vir bronkodes. Ons handtekeningmeganisme is anders: ons gebruik 'n spesiale bediener. 'n Bewaarplek is ook nie nodig nie.

Boonop word ondersteuning vir ander verspreidings - byvoorbeeld Red Hat - taamlik swak geïmplementeer, wat verstaanbaar is.

Die voordeel van so 'n diens is vinnige ondersteuning vir die volgende weergawe van die SUSE-verspreiding. Voor die amptelike aankondiging van die vrystelling, word die pakkette wat nodig is vir samestelling op 'n publieke bewaarplek geplaas. 'n Nuwe een verskyn in die lys van beskikbare verspreidings op OpenBuildService. Ons merk die blokkie en dit word by die bouplan gevoeg. Die byvoeging van 'n nuwe weergawe van die verspreiding word dus in amper een klik gedoen.

In ons infrastruktuur, met behulp van OpenBuildService, word die hele verskeidenheid KMP-pakkette van die veeamsnap-kernmodule vir SUSE-verspreidings saamgestel.

Vervolgens wil ek stilstaan ​​by kwessies wat spesifiek met kernmodules is.

kern ABI

Linux-kernmodules is histories in bronvorm versprei. Die feit is dat die skeppers van die kern hulself nie belas met die kommer om 'n stabiele API vir kernmodules te ondersteun nie, en veral op die binêre vlak, verder na verwys as kABI.

Om 'n module vir 'n vanieljekern te bou, het jy beslis die opskrifte van hierdie spesifieke kern nodig, en dit sal net op hierdie kern werk.

Met DKMS kan u die proses van die bou van modules outomatiseer wanneer u die kern bywerk. Gevolglik gebruik gebruikers van die Debian-bewaarplek (en sy baie familielede) kernmodules óf vanaf die verspreider se repository óf saamgestel vanaf bron met DKMS.

Hierdie situasie pas egter nie juis by die Enterprise-segment nie. Eiendomskodeverspreiders wil die produk as saamgestelde binaries versprei.

Administrateurs wil om veiligheidsredes nie ontwikkelingshulpmiddels op produksiebedieners hou nie. Enterprise Linux-verspreiders soos Red Hat en SUSE het besluit dat hulle stabiele kABI vir hul gebruikers kan ondersteun. Die resultaat was KMOD-pakkette vir Red Hat en KMP-pakkette vir SUSE.

Die kern van hierdie oplossing is redelik eenvoudig. Vir 'n spesifieke weergawe van die verspreiding word die kern-API gevries. Die verspreider meld dat hy die kern gebruik, byvoorbeeld, 3.10, en maak slegs regstellings en verbeterings wat nie die kern-koppelvlakke raak nie, en die modules wat vir die heel eerste kern ingesamel is, kan vir alle daaropvolgendes gebruik word sonder om te herkompileer.

Red Hat beweer kABI-versoenbaarheid vir die verspreiding deur sy hele lewensiklus. Dit wil sê, die saamgestelde module vir rhel 6.0 (vrystelling November 2010) behoort ook op weergawe 6.10 (vrystelling Junie 2018) te werk. En dit is amper 8 jaar. Natuurlik is hierdie taak nogal moeilik.
Ons het verskeie gevalle aangeteken waar die veeamsnap-module ophou werk het weens kABI-versoenbaarheidskwessies.

Nadat die veeamsnap-module, saamgestel vir RHEL 7.0, onversoenbaar met die kern van RHEL 7.5 geblyk het te wees, maar dit gelaai het en gewaarborg was om die bediener te laat crash, het ons die gebruik van kABI-versoenbaarheid vir RHEL 7 heeltemal laat vaar.

Tans bevat die KMOD-pakket vir RHEL 7 'n samestelling vir elke vrystellingweergawe en 'n skrif wat die module laai.

SUSE het die taak van kABI-versoenbaarheid noukeuriger benader. Hulle bied kABI-versoenbaarheid slegs binne een dienspakket.

Byvoorbeeld, die vrystelling van SLES 12 het in September 2014 plaasgevind. En SLES 12 SP1 was reeds in Desember 2015, dit wil sê, 'n bietjie meer as 'n jaar is verby. Alhoewel beide vrystellings die 3.12-kern gebruik, is hulle kABI-onversoenbaar. Dit is duidelik dat dit baie makliker is om kABI-versoenbaarheid vir net 'n jaar te handhaaf. Die jaarlikse kernmodule-opdateringsiklus behoort nie probleme vir moduleskeppers te veroorsaak nie.

As gevolg van hierdie SUSE-beleid het ons nie 'n enkele probleem met kABI-versoenbaarheid in ons veeamsnap-module aangeteken nie. Die aantal pakkette vir SUSE is weliswaar amper 'n orde van grootte groter.

Patches en backports

Alhoewel verspreiders probeer om kABI-versoenbaarheid en kernstabiliteit te verseker, probeer hulle ook om die werkverrigting te verbeter en defekte van hierdie stabiele kern uit te skakel.

Terselfdertyd monitor die ontwikkelaars van die onderneming Linux-kern, benewens hul eie "werk aan foute", veranderinge in die vanieljekern en dra dit oor na hul "stabiele" een.

Soms lei dit tot nuwes foute.

In die jongste weergawe van Red Hat 6 is 'n fout gemaak in een van die klein opdaterings. Dit het gelei tot die feit dat die veeamsnap-module gewaarborg was om die stelsel te laat crash wanneer die momentopname vrygestel is. Nadat ons die kernbronne voor en na die opdatering vergelyk het, het ons uitgevind dat die agterpoort die skuld was. 'n Soortgelyke oplossing is gemaak in die vanieljepitweergawe 4.19. Dit is net dat hierdie regstelling goed in die vanieljepit gewerk het, maar toe dit na die "stal" 2.6.32 oorgedra is, het 'n probleem met die spinlock ontstaan.

Almal het natuurlik altyd foute, maar was dit die moeite werd om die kode van 4.19 na 2.6.32 te sleep, om stabiliteit te waag? .. Ek is nie seker nie...

Die ergste is wanneer bemarking betrokke raak by die toutrekkery tussen “stabiliteit” en “modernisering”. Die bemarkingsafdeling moet die kern van die opgedateerde verspreiding aan die een kant stabiel wees en terselfdertyd beter in prestasie en nuwe kenmerke hê. Dit lei tot vreemde kompromieë.

Toe ek probeer om 'n module op kern 4.4 van SLES 12 SP3 te bou, was ek verbaas om funksionaliteit van vanilla 4.8 daarin te vind. Na my mening is die blok I/O-implementering van die 4.4-kern van SLES 12 SP3 meer soortgelyk aan die 4.8-kern as die vorige weergawe van die stabiele 4.4-kern van SLES12 SP2. Ek kan nie oordeel watter persentasie kode van kern 4.8 na SLES 4.4 vir SP3 oorgedra is nie, maar ek kan nie eers die kern dieselfde stabiele 4.4 noem nie.

Die onaangenaamste hiervan is dat wanneer jy 'n module skryf wat ewe goed op verskillende pitte sal werk, jy nie meer op die kernweergawe kan staatmaak nie. Jy moet ook die verspreiding in ag neem. Dit is goed dat jy soms betrokke kan raak by 'n definisie wat saam met nuwe funksionaliteit verskyn, maar hierdie geleentheid verskyn nie altyd nie.

As gevolg hiervan word die kode oorgroei met vreemde voorwaardelike samestelling-aanwysings.

Daar is ook pleisters wat die gedokumenteerde kern-API verander.
Ek het op die verspreiding afgekom KDE neon 5.16 en was baie verbaas om te sien dat die lookup_bdev-oproep in hierdie kernweergawe die lys van invoerparameters verander het.

Om dit bymekaar te kry, moes ek 'n skrif by die makefile voeg wat kyk of die lookup_bdev-funksie 'n maskerparameter het.

Ondertekening van kernmodules

Maar kom ons keer terug na die kwessie van pakketverspreiding.

Een van die voordele van stabiele kABI is dat kernmodules as 'n binêre lêer onderteken kan word. In hierdie geval kan die ontwikkelaar seker wees dat die module nie per ongeluk beskadig of opsetlik gewysig is nie. U kan dit kontroleer met die modinfo-opdrag.

Red Hat- en SUSE-verspreidings laat jou toe om die module se handtekening na te gaan en dit net te laai as die ooreenstemmende sertifikaat op die stelsel geregistreer is. Die sertifikaat is die publieke sleutel waarmee die module onderteken is. Ons versprei dit as 'n aparte pakket.

Die probleem hier is dat sertifikate óf in die kern ingebou kan word (verspreiders gebruik dit) óf geskryf moet word na EFI nie-vlugtige geheue met behulp van 'n program mokutil. Nut mokutil Wanneer 'n sertifikaat geïnstalleer word, vereis dit dat jy die stelsel herlaai en, selfs voor die laai van die bedryfstelselkern, vra die administrateur om die laai van 'n nuwe sertifikaat toe te laat.

Die byvoeging van 'n sertifikaat vereis dus fisiese administrateurtoegang tot die stelsel. As die masjien iewers in die wolk of bloot in 'n afgeleë bedienerkamer geleë is en toegang slegs via die netwerk is (byvoorbeeld via ssh), dan sal dit onmoontlik wees om 'n sertifikaat by te voeg.

EFI op virtuele masjiene

Ten spyte van die feit dat EFI lank reeds deur byna alle moederbordvervaardigers ondersteun word, kan die administrateur by die installering van 'n stelsel nie aan die behoefte aan EFI dink nie, en dit kan gedeaktiveer word.

Nie alle hiperviseerders ondersteun EFI nie. VMWare vSphere ondersteun EFI vanaf weergawe 5.
Microsoft Hyper-V het ook EFI-ondersteuning gekry, begin met Hyper-V vir Windows Server 2012R2.

In die verstekkonfigurasie is hierdie funksionaliteit egter vir Linux-masjiene gedeaktiveer, wat beteken dat die sertifikaat nie geïnstalleer kan word nie.

Stel die opsie in vSphere 6.5 Veilige opstart slegs moontlik in die ou weergawe van die webkoppelvlak, wat via Flash loop. Web-UI op HTML-5 is nog ver agter.

Eksperimentele verspreidings

En laastens, kom ons kyk na die kwessie van eksperimentele verspreidings en verspreidings sonder amptelike ondersteuning. Aan die een kant is dit onwaarskynlik dat sulke verspreidings op die bedieners van ernstige organisasies gevind sal word. Daar is geen amptelike ondersteuning vir sulke verspreidings nie. Verskaf dit dus. Die produk kan nie op so 'n verspreiding ondersteun word nie.

Sulke verspreidings word egter 'n gerieflike platform om nuwe eksperimentele oplossings uit te probeer. Byvoorbeeld, Fedora, OpenSUSE Tumbleweed of onstabiele weergawes van Debian. Hulle is redelik stabiel. Hulle het altyd nuwe weergawes van programme en altyd 'n nuwe kern. Oor 'n jaar kan hierdie eksperimentele funksionaliteit in 'n opgedateerde RHEL, SLES of Ubuntu beland.

So as iets nie op 'n eksperimentele verspreiding werk nie, is dit 'n rede om die probleem uit te vind en dit op te los. U moet daarop voorbereid wees dat hierdie funksionaliteit binnekort op gebruikers se produksiebedieners sal verskyn.

Jy kan die huidige lys van amptelik ondersteunde verspreidings vir weergawe 3.0 bestudeer hier. Maar die werklike lys van verspreidings waarop ons produk kan werk, is baie wyer.

Persoonlik was ek geïnteresseerd in die eksperiment met die Elbrus OS. Nadat die veeam-pakket gefinaliseer is, was ons produk geïnstalleer en werk. Ek het oor hierdie eksperiment op Habré geskryf in Artikel.

Wel, ondersteuning vir nuwe verspreidings gaan voort. Ons wag vir weergawe 4.0 om vrygestel te word. Beta is op die punt om te verskyn, so hou 'n ogie uit wat's nuut!

Bron: will.com

Voeg 'n opmerking