Posts Tagged ‘работа’

2017-05-09 bias-и и дебъгване

Tuesday, May 9th, 2017

Нещо странично.

Тия дни в офиса около някакви занимания обсъждахме следната задача:

“Имаме банда пирати (N на брой, капитан и N-1 останали членове), които искат да си разделят съкровище от 100 пари. Пиратите имат строга линейна йерархия (знае се кой след кой е). Разделянето става по следния начин – текущият капитан предлага разпределение, гласува се и ако събере половината или повече от гласовете се приема, ако не – убиват го и следващия по веригата предлага разпределение. Въпросът е какво трябва да предложи капитанът, така че всички да се съгласят, ако приемем, че всички в екипажа са перфектни логици. Също така пиратите са кръвожадни и ако при гласуване против има шанс да спечели и същите пари, пак ще предпочете да убие капитана. Също така всички са алчни и целта е капитанът да запази най-много за себе си.”
(задачата не идва от икономиката, въпреки че и там всички са перфектни логици и за това толкова много им се дънят теориите)

Решението на задачата е интересно (за него – по-долу), но е доста по-интересно колко трудно се оказа да я реша. Първоначалната ми идея беше просто на горната половина от пиратите да се разделят намалящи суми, понеже това е стандартния начин, по който се случват нещата. Това се оказа неефективно. После ми напомниха (което сам трябваше да се сетя), че такива задачи се решават отзад-напред и по индукция, и като за начало започнахме с въпроса, какво става ако са само двама?

Първият ми отговор беше – ами другия член на екипажа ще иска винаги да убие капитана, щото така ще вземе всичко. Обаче се оказа, че и капитана има глас, т.е. ако останат само двама, капитанът взима всичко и разпределението е 100 за него и нищо за другия.

Какво следва, ако са трима? Казах – добре, тогава даваш на единия 1, на другия 2, и останалото за капитана, понеже ако останат само двама, последния няма да вземе нищо, капитанът гласува за себе си и втория и да е за и против, няма значение. Само че няма нужда да даваме нищо на средния, щото не ни пука за мнението му, така всъщност правилното разпределение идва 1, 0, 99. Тук пак си пролича bias-а, пак очаквах да има някаква пропорция.

Long story short, следващата итерация е 0, 1, 0, 99, понеже така ако не се съгласят, на следващия ход предпоследния ако не се съгласи няма да вземе нищо, и на другите двама мнението няма значение. Pattern-а мисля, че си личи :)

Лошото е колко много влияеше bias-а, който съм натрупал от четене за разпределения в реалния живот – какво са пиратите, как няма перфектни логици (и реално никой няма да смята по тоя начин, а ще се стремят към нещо, което им се вижда честно), как това тотално изключва политическата възможност N/2+1 от долната част да гласуват винаги против, докато не дойде всичкото до тях и после да си го разделят по равно и всякакви подобни варианти от реалния живот. Ако примерът беше с каквото и да е друго (например не включваше хора), вероятно щеше да е доста по-лесно да гледам абстрактно.

Което е още един довод в подкрепа на идеята ми, че много по-лесно се дебъгва нещо чуждо (често и което никога не си виждал), отколкото нещо, с което почти постоянно се занимаваш. Над 90% от проблемите (това не се базира на никаква статистика, а на усещане) са достатъчно прости, че да могат да се решат със стандартни методи и да не изискват много задълбочено познаване на системата (половината ми живот е минал в дебъгване на неща, които не разбирам, доста по-често успешно, отколкото не) и вероятно като/ако правя debug workshop-а (за който много хора ми натякват), ще е с проблеми, с които и аз не съм запознат, да е наистина забавно …

2017-04-10 splitpatch

Monday, April 10th, 2017

Нов ценен tool – splitpatch (има го в debian, нищо, че е на ruby).

Трябваше да вкараме едно парче код (на perl) в главното ни repo, и след code review имаше забележки като за 11 промени. Вкарахме ги, тествах го и открих, че не работи – output-а беше много много различен от този в началото (който си се знаеше, че е верен).

Един вариант беше някой да гледа промените ред по ред и да се разбере какво е объркано. Вместо да се стига до такива крайни мерки, намерих tool, който може да сцепи patch-а на hunk-ове, и след това направих следното:

for i in ptch/* ; do patch -o test TOOL $i ; ./test debug > $i.output ; done

и след това с един прост for и diff видях кои съвпадат и кои се различават, и проблемния commit лъсна…

Имаше и варианта вместо да patch-вам оригинала, да махам по един patch от финалния, докато не изчезне проблема. При зависещи един от друг hunk-ове пък може да се направи нещо още по-забавно – да се направят всичките комбинации от patch-ове (като са 11 не са толкова много), да се изтества и пак да се хване разликата сравнително лесно (ако например два са виновни).

Изводът е, че човек може да дебъгва код на нещо в много случаи и без да знае езика…

2017-04-05 интервюта за админи

Wednesday, April 5th, 2017

Смених работата, но се оказва, че от интервютата бягане няма. Тоя път са за системни администратори.

За всеки нов вид интервюта си трябва доста време, за да се свикне и измисли хубав метод. Например, нямам fizzbuzz, доста по-трудно е да кажеш “покажи какво си писал”, а срещането на NDA, заради което не може да се говори какво е вършено не е чак толкова рядък случай. Да разбереш дали някой разбира в дълбочина някоя технология не винаги може да стане с 2-3 въпроса. Да не говорим, че докато не видиш как работи човека, няма как да го прецениш дали става…
(най-добрия вариант го правят в automattic, просто един месец ти плащат да работиш с екипа и ти дават задачи и гледат как се справяш. За съжаление не е лесно да се направи на друго място.)

Като за начало съм си сглобил малък админски тест, който да пращам на хората. Има даже дребен състезателен елемент и се чудя дали не мога да го разпъна до нещо escape-room-о-подобно :)

(in other news, бях седнал да си си разписвам escape room за админи, ако се намери достатъчно интерес може да я сглобя в лаба, има всякакви странни неща вътре)

(p.s. ако някой тия задачи са му лесни и си търси работа, лесно се разбира де да си прати CV-то…)

2017-02-22 FizzBuzz 2

Wednesday, February 22nd, 2017

Понеже идеята ми се мотае в главата от месец-два и тая нощ ми хрумна финалната оптимизация, ето продължението на post-а за fizzbuzz:

int i=0,p;
static void *pos[4]= {&&digit, &&fizz, &&buzz, &&fizzbuzz};
static void *loop[2] = { &&loopst, &&loopend};
int s3[3]={1,0,0},s5[5]={2,0,0,0,0};
char buff[2048];
char dgts[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
int buffpos=0;

loopst:
	i++;
	p= s3[i%3] | s5[i%5]; 
	goto *pos[p];

fizz:
	memcpy(&buff[buffpos],"Fizz", 4);
	buffpos+=4;
	goto end;
buzz:
	memcpy(&buff[buffpos],"Buzz", 4);
	buffpos+=4;
	goto end;
fizzbuzz:
	memcpy(&buff[buffpos],"FizzBuzz", 8);
	buffpos+=8;
	goto end;
digit:
	buff[buffpos++]=dgts[i/16];
	buff[buffpos++]=dgts[i%16];
end:
	buff[buffpos++]='\n';
	goto *loop[i/100];
loopend:
write(1, buff, buffpos);

Известно време се чудех как може цялото нещо да стане без никакъв branch, т.е. и без проверката за край на цикъла. Първоначалната ми идея беше да я карам на асемблер и да използвам като в exploit-ите NOP sled, нещо от типа (извинете ме за калпавия асемблер):

	JMP loopst
	JMP loopend
loopst:
	NOP
	NOP
...
	NOP
	; fizzbuzz implementation
	; i is in RAX
...
	MOV RBX, 0
	SUB RBX, RAX
	SUB RBX, $LENGTH
	SUB EIP, RBX
loopend:

Или, накратко, колкото повече се увеличава i, толкова повече скачам назад с релативния JMP (който съм написал като вадене на нещо от EIP, което най-вероятно изобщо не е валидно), докато не ударя JMP, който ме изхвърля. Като оптимизация бях решил, че мога да shift-вам стойността с 4, така че sled-а да е само 25 броя.

В един момент ми хрумна, че мога да мина и без sled-а, като правя деление (което е отвратителна операция, но спестява кофа nop-ове). Така се получи по-горния вариант на C, който не е съвсем C, а просто някаква странна асемблероподобна гняс.

Иначе, важно е да се отбележи, че на какъвто и да е модерен процесор по-горния код е далеч по-неефективен от простото решение с if-ове, най-вече защото branch prediction и всички други екстри се справят много добре с всякаквите if-ове, но доста по-трудно могат да се сетят тия jmp-ове към таблици базирани на някакви стойности къде точно ще идат, за да се прави спекулативното изпълнение. Не съм си играл да benchmark-вам (въпреки, че имам желание), но като цяло горния код има шанс да се справя по-добре само на неща като 8086 и компания.

И като идея за следващата подобна мизерия, може би може да се оптимизира истински чрез ползване на някое от разширенията за работа с вектори/големи стойности и се unroll-не цикъла, например да се прави на стъпки от по 4 с някаква инструкция, която смята делители (кой-знае какви странни неща има вкарани вече в x86 instruction set-а).

2017-02-07 FOSDEM 2017

Tuesday, February 7th, 2017

И преживяхме FOSDEM 2017.

Бяхме там с Марио, Любо, Маги, neter и zeridon (а Мариян беше там да присъства на конференцията, но се включи към нас) да правим видео/аудио записите и streaming-а. Три дни се ставаше рано и цял ден се дебъгваше (и за доста от хората – тичаше напред-назад, Любо каза, че единия ден е направил 27000 крачки), имаше всякакви странни проблеми и като цяло беше голямо забавление, приключено със ставане в 6:30 в понеделник да си хванем самолета. Като се прибрах спах 12 часа. Справихме се със събитие от 24 зали, два дни, около 600 лекции и 8-9 хиляди посетители (и не знам колко точно дъжд).

Малко снимки има на /pics/201702fosdem/, като на една от тях може да се види колко съм щастлив (това е в петък още, после имах основно уморен вид).
(снимките са от Мариян и Любо, като ще се опитам да намеря и още)

Като статистики не съм събирал кой-знае колко, мога да кажа само че пиковият трафик на restreamer-ите беше 630mbps, далеч под очакванията (това, което бяхме подготвили можеше да издържи спокойно 4gbps и се разширяваше лесно). Някакъв status на видео записите може да се види в review системата, като мога да се похваля, че имахме готови видеа още в събота вечер, а като гледам днес вече са release-нати половината.

И най-интересната част, проблемите, в които се набих (като преди това може да искате да прочетете архитектурата и да видите схема с една зала):

Явно съм забравил какво значи best effort в IP/Ethernet мрежите. При 72та multicast stream-а и при 300pps на всеки в един момент се оказа, че по switch-овете има microburst-ове, които ни ядат пакетите от време на време. Това водеше до примигване на някои stream-ове, до ошашкване на ingest-ващия ffmpeg и вадене на картина с 1fps (като па аудиото си беше добре), артефакти и други гадости.

– Първият опит за решение беше включване на flow control-а. Това доведе до спиране на всичко за 5-10 минути (и липса на stream и видеа в review системата от тоя период, добре, че има записи по кутиите) и желание за по-внимателни fix-ове.
– Последва ровене по switch-овете, забелязване на едни броячи за твърде големи пакети и след това форсиране на 1000 байта горна граница на пакетите във ffmpeg. Не помогна;
– Вдигнахме за всеки случай и MTU-то на switch-овете, пак не помогна;
– Като вариант за pacing на портовете преместихме някакви неща на 100mbps да вкараме изкуствено забавяне, тотално омаза ситуацията;
– В един момент единия от мрежарите откри, че няма контрол в/у буферите на повечето switch-ове и реално ползваме 1/4 от буферите (щото всичкия ни трафик се набива в една опашка от 4те) и че няма свестен начин да използваме и 4те. Само на единия switch бяха пипнати и помогна, но малко;
– Смъкнах и bandwidth-а на входящите stream-ове от 4mbps на 2mbps, не помогна особено.

Решението за догодина е или Reliable Datagram Socket (Мариян обеща да напише support-а за ffmpeg и го държа отговорен), някакъв forward error correction (някакви хора са написали pro-mpeg поддръжка за ffmpeg, но не е merge-ната), или lossless мрежа и по-добри буфери (което казаха, че може и да може да се осигури за догодина). Шегувахме се, че мога да мина на infiniband за видеото.

Интересно е, че всъщност съм се сетил за проблема, но не ни се е видяло достатъчно важно да мислим решение.

Другите проблеми бяха по-малко интересни – утрепахме тока на сървърното (докато включвахме неща в съвсем друго място), хората не знаеха как да ползват микрофони, гърмя хардуер, валя дъжд (но не в залите), хората тичаха, врати се заключваха (автоматично), за малко neter и Мариян заседнаха в един асансьор и куп други неща, дето вече не помня.

(и за разлика от openfest, тук сървърите не бяха в/у тръбите на парното, а в стаята до него…)

Update: Току-що открих, че push-ването на видео извън мрежата е генерирало ~600GB, а системата, която генерира картинките за преглеждане на контролния интерфейс – ~7.1TB (постоянни 300mbps). Май съм бил най-големия генератор на изходящ трафик на FOSDEM 2017. Чудя се да се радвам ли или да се ужасявам.

2016-11-23 Интерком и телефони на OpenFest 2016

Wednesday, November 23rd, 2016

Интерком

Видео екипът има нужда от начин, по който да си комуникира между операторския пулт и камерите, в общи линии еднопосочно (т.е. режисьора да може да каже "камера 1, мръдни малко в ляво"). Предишни години за целта се употребяваха различни неща, най-често някаква част от комплектите безжични микрофони (един предавател и няколко приемника). Тази година микрофоните ни бяха кът, за това сглобих едно просто решение от ffmpeg и raspberry pi-та:

На контролния лаптоп закачахме какъвто-и-да-е-микрофон (в случая – едни jabra headset-и, които бяха под ръка) и с ffmpeg ги бълвахме по multicast по мрежата:

ffmpeg  \
    -fflags nobuffer \
    -f alsa -i hw:0,0 \
    -acodec aac -tune zerolatency -ac 1 -b:a 128k \
    -f mpegts 'udp://227.0.9.1:9000?pkt_size=128'

Скриптът взима звукът от alsa-та от микрофона (в случая hw:0,0) и ги пуска на 227.0.9.1 с малък размер на пакета, за по-ниска латентност. Ако трябва да се пусне под windows, ‘-f alsa -i hw:0,0’ се сменя с нещо като ‘-f dshow -i audio="Microphone"’ (като "Microphone" трябва да се погледне как точно се казва, понеже windows-а странно кръщава нещата, Любо беше намерил как точно).

На няколкото raspberry pi-та до камерите се пускаше следния скрипт:

while /bin/true; do
ffmpeg  \
    -fflags nobuffer -probesize 32 -i \
'udp://227.0.9.1:9000?timeout=1000000&fifo_size=100&overrun_nonfatal=0' \
    -f alsa hw:0,0
done

Това слуша на multicast-а и play-ва каквото му дойде, като има timeout от 1 секунда без никакви данни, за да гръмне и да се рестартира. Така може да издържи на всякакви мрежови проблеми и в общи линии гарантира възстановяване до 1 секунда, след като се оправи мрежата.

Това като цяло е доста хакаво и сглобено в последния момент. При мрежата, която имахме, за догодина спокойно ffmpeg-а може да бъде заменен с един asterisk с конференция и телефони, които се закачат в нея, така включително ще можем да смъкнем още латентността (на този беше около 300-400ms) и да направим двупосочен интеркома (въпреки че хората не звучаха много въодушевени). Другото, което сравнително лесно трябва да може да се добави е noise reduction, понеже доколкото знам имаше някакъв, или от микрофона и усилването му, или от самите pi-та (като за второто няма да се оправим само софтуерно).

Телефони

Кодът е качен в github, и е съвсем съвсем тривиален:

  • С един php модул (phirehose) се дърпат tweet-ове по признак и се пишат във файлове;
  • Друг скрипт проверява на какъв език са, с espeak ги обръща в говор и ги дава на asterisk-а чрез call file да ги изговори на някого.

Цялото нещо отне чисто час-два да се напише и тества. Изглежда бая грозно (и може да седна да го оправя), но върши доста прилична работа и може да се използва като основа за всякакви подобни неща.

На самия OpenFest реализацията беше, че имаше наслагани 3 стари черни телефона на различни места, които бяха вързани през grandstream ATA устройства (понеже бяха единствените, които поддържаха импулсно набиране) и когато дойдеше tweet с #openfest2016telefon, asterisk-а звънеше на трите едновременно и който пръв вдигнеше го чуваше.

Архив на всичките неща, дето са казани по телефона може да се намери тук.

2016-11-22 Мрежата на OpenFest 2016

Tuesday, November 22nd, 2016

Нямахме голяма промяна от миналата година. Разликите бяха следните:

  • Тази година повечето switch-ове в опорната мрежа бяха tplink SG3210, имахме само 2 cisco-та. tplink-овете са по-тихи, по-малки, (буквално) железни и стават за странни deployment-и. Ако имаха и PoE, щяха да са направо невероятни.
  • Имахме още един switch, за NOC-а в мазето (който беше и единствения leaf в мрежата). Тази година стаичката за VOC беше оставена само на видео екипа, а мрежовия се ширеше в едно мазе.
  • Понеже имахме две зали за workshop-и, имахме малко повече user-ски switch-ове, в общи линии от кол и въже;

Ето тазгодишната схема.

С техника ни услужиха пак Светла от netissat (нейния switch вече 3-4 години е в опорната ни мрежа), Стефан Леков (noc switch-а и резервния сървър) и digger (два microtik-а за workshop switch-ове). Останалото беше от мен и initLab.

Голяма част от мрежовия setup беше организирана през github-ски issue-та, та лесно може да видите какво ни се е случвало по време на подготовката.

Тази година имаше повече наши "клиенти" на мрежата – интеркомът на залите беше по IP и имаше пръснати разни странни телефони, които бяха из мрежата. Като цяло wired мрежата не изглежда да се ползва от посетителите, но все повече се оказва полезна за нас.

Пак използвахме за сървърно подстълбищното пространство от другата страна на залата, и съответно имаме снимки преди и след. Не е от най-подходящите – всичко наоколо е дървено, тясно е и отдолу минава тръбата за парното (т.е. сме може би едно от малкото сървърни, които вместо климатик имат парно), но е точно до ел. таблото, далеч е от потоците хора и на достатъчно централна позиция, че да можем да пускаме от него независими трасета.

Тази година преизползвахме кабелите от миналата година и взехме един резервен кашон кабел, та нямахме никакви проблеми с изграждането на мрежата.

За uplink тази година ползвахме същата оптика на NetX, но с гигабитови конвертори и 300mbps, та не усетихме никакъв проблем със свързаността.

Използвахме и същия DL380G5 за сървър/router, като тази година Леков пусна още един такъв като backup. Пак го използвахме да encode-ва 1080p stream-а от зала България, въпреки че май тая година нормалния ни encoder щеше да се справи (за една година софтуерът е понапреднал).

Тази година се наложи да променим номерата на VLAN-ите, понеже една част от AP-тата (едни големи linksys-и) не поддържаха VLAN tag-ове над 64. Съответно адресният ни план изглеждаше по следния начин:

IPv4

id  range           name
10  185.108.141.104/30  external
20  10.20.0.0/24        mgmt
21  10.21.0.0/22        wired
22  10.22.0.0/22        wireless
23  10.23.0.0/24        video
24  10.24.0.0/24        overflow

IPv6

10  2a01:b760:1:2::/120
21  2a01:b760:2:4::/62
22  2a01:b760:2:5::/62

По firewall-а и forced forwarding-а нямахме разлика – пак пуснахме proxy_arp_pvlan за потребителските VLAN-и, филтрирахме 25ти порт и не се допускаше трафик до management/video/overflow VLAN-ите от нормални потребители.

Имахме пълна IPv6 поддръжка в потребителските VLAN-и (wired и wireless), като тази година нямахме проблемът с изчезващият IPv6 за random хора – явно най-накрая странният bug е бил ремонтиран.

Изобщо мрежата беше максимално стабилна и при събрания опит може да планираме догодина повече вътрешно-екипна комуникация върху нея, и всякакви странни екстри (например стационарни телефони, повече монитори с информация, някакви сигнализации, работни станции на рецепции и всякакви весели неща). За сега най-големите потребители са wireless-а и видео екипа.

2016-11-21 VoctoMix на OpenFest

Monday, November 21st, 2016

Ситуация

За OpenFest имахме две кутии от тези от FOSDEM, които в общи линии ни даваха възможност да включим почти произволен източник на видео в тях и да го изкараме от мрежата. Те вървят в комплект от две – едната се използва, за да се включи в нея лектора, другата – за камерата. С тези две кутии и малко софтуерно видео миксиране може да се направи много лесно добър setup за видео запис на една зала.

Схемата на setup-а може да се види в github, като лесно може да се види, че е доста по-прост от другите, които използваме. Негов вариант мислим да използваме за FOSDEM 2017 (което може да се наблюдава в repo-тата в github – issue-та, wiki и всякакви работи).

VoctoMix

Липсващият компонент в цялата работа беше софтуерен миксер, който да ползваме. Пробвахме различни – първо един ffmpeg с малко patch-ове (чупи се твърде лесно), после OBS (който leak-ва памет като гламав и не е особено стабилен), и накрая се спряхме на voctomix, който е разработка на CCC и в общи линии е прекрасен хакерски инструмент, който работи по следния начин:

  • Има входове на TCP портове за следните неща:
    • Видео потоци (камери, лекторски лаптоп)
    • Поддържащи потоци (фон, какво да се пуска докато не сме live и т.н.)
    • Команди за разни действия (смяна на картина и т.н.)
  • Изходи, пак по TCP, за
    • Видео поток
    • Аудио поток
    • Копие на всеки входящ stream
    • preview на потоците и изходящата картина

Софтуерът в общи линии просто switch-ва между няколко неща (някоя картина на fullscreen, picture-in-picture в някакви варианти и т.н.) и вади поток, който може да се използва. Има отделно приложение (voctogui) което се закача към него и се използва като конзола – може да показва preview на потоците и да подава команди към основния процес (voctocore).

Как го използвахме

Излъчване от кутиите

Като за начало, изкарването на поток от кутиите става с ffmpeg/avconv, по UDP, по multicast. UDP, понеже е по-издръжливо на някакви random прекъсвания и няма да създаде десинхронизация, multicast, за да може да се гледа от повече от едно място (например за проверка какво точно излиза). Командата изглежда по следния начин:

# these are needed, because the default socket size is too small.
echo 81921024 > /proc/sys/net/core/wmem_max
echo 81921024 > /proc/sys/net/core/wmem_default

echo 81921024 > /proc/sys/net/core/rmem_max
echo 81921024 > /proc/sys/net/core/rmem_default

/usr/local/bin/bmd-streamer -f /usr/lib/firmware -k 1000 -S hdmi -F 0 | \
 ffmpeg -i - -c copy -f mpegts 'udp://227.0.0.1:9000&overrun_nonfatal=1&buffer_size=81921024&fifo_size=178481'

Интересното тук са параметрите на UDP stream-а – гигантски буфери (които и по-горе се казват на kernel-а), така че каквото и да се случва, да не се бави писането в буфера. Като цяло не е проблем да се губят пакети, но е доста лошо да се получава забавяне в целия stream, понеже води до десинхронизация. (да се губят пакети също е лошо, и за целта работя по нещо, което да вкарва forward error correction в тоя поток, един добър човек е написал patch за ffmpeg, реализиращ pro-mpeg, който има точно такава функционалност, надявам се да успеем да го ползваме на FOSDEM)

Приемане във voctomix

Самият voctocore приема потоците точно във видът, в който е конфигуриран (в нашия случай 1280×720, 30fps, audio в pcm_s16le на 44100hz), в MKV контейнер. За целта скриптовете, които го подават изглеждат ето така:

#/bin/sh
confdir="`dirname "$0"`/../"
. $confdir/default-config.sh
if [ -f $confdir/config.sh ]; then
    . $confdir/config.sh
fi


ffmpeg -y -nostdin \
    -i 'udp://227.0.0.1:9000&overrun_nonfatal=1&buffer_size=81921024&fifo_size=178481' \
    -ac 2 \
    -filter_complex "
        [0:v] scale=$WIDTH:$HEIGHT,fps=$FRAMERATE,setdar=16/9,setsar=1 [v] ;
        [0:a] aresample=$AUDIORATE [a]
    " \
    -map "[v]" -map "[a]" \
    -pix_fmt yuv420p \
    -c:v rawvideo \
    -c:a pcm_s16le \
    -f matroska \
    tcp://localhost:10000

Това в общи линии казва "вземи udp stream-а, scale-ни го до колкото искаме, сгъни пикселите и аспекта да са точно каквито ни трябват, и го прати като mkv на порт 10000". Сгъването на пикселите и аспекта (setsar, setdar) се налага основно когато не може да се промени изхода на камерата и идва в нещо странно като 1920×1088, което води до малко по-различна форма на пикселите.

За да работи цялото нещо, имаме два такива скрипта (по един за box), както и един подобен, който просто loop-ва едно PNG, което играе ролята на фон. В оригиналните скриптове хората са използвали видео за фон на picture-in-picture, но това е по-объркващо за гледащите и не го ползваме.

Излъчване и запис при voctomix

Излъчването и записът са в общи линии много подобни скриптове, като ще покажа само този, който праща до restreamer-а:

#/bin/sh
ffmpeg -y -nostdin \
    -i tcp://localhost:15000 \
    -threads:0 0 \
    -aspect 16:9 \
    -c:v libx264 \
    -maxrate:v:0 2000k -bufsize:v:0 8192k \
    -pix_fmt:0 yuv420p -profile:v:0 main -b:v 512k \
    -preset:v:0 ultrafast \
    \
    -ac 1 -c:a libfdk_aac -b:a 96k -ar 44100 \
    -map 0:v \
    -map 0:a -filter:a:0 pan=mono:c0=FL \
    -ac:a:2 2 \
    \
    -y -f flv rtmp://10.23.0.1:1935/st/STREAM

(скриптът е примерен, понеже доработвах след това нещата)

Като цяло, просто се взимат raw данните от порт 15000, encode-ват се до H.264 и се пращат до сървъра. По същият начин може да се обръщат във WEBM и засилват, но той иска много повече процесорно време и не сме стигнали до там, че да го ползваме.

Екстри за voctomix

Нещо, което не включихме на OpenFest, но ще има на FOSDEM е една дребна доработка, която позволява с много малко ресурси хора отдалечено да контролират voctomix-а. По принцип voctogui не е лек процес и има много сериозни мрежови изисквания, ако не се стартира локално (от порядъка на 1Gbps само за него), но позволява всякакви ужасяващи неща с малко дописване. С един прост скрипт, който прави screenshot веднъж в секунда, и съвсем прост друг, който подава команди ще имаме начин определени хора да имат контрол върху излъчването.

Също така нещо, което ползвахме донякъде на OpenFest за monitoring на stream-а е един друг скрипт с mpv, който взима списък URL-та и някакви имена към тях и ги пуска в отделни подредени един до друг прозорци на екрана, като за всеки overlay-ва един bar с нивото на звука, така че да може да се вижда дали е ок (понеже не е практически възможно да се слушат няколко зали едновременно). Проблемът му е, че се иска бая процесорно време, за да се декодират повечето потоци и един T420 с i7 процесор се озорваше с 6те потока от феста. Как изглеждаше екрана може да видите тук.

Опериране

Работата с voctomix не е сложна, но за момента пълна с неща, които имат да се свършат. Ето как изглежда (засега, работим по автоматизация) процесът на стартиране:

  • voctocore
  • voctogui
  • скриптове за приемане от камери (cam1.sh, grab.sh)
  • скрипт за генериране на фон
  • скрипт за stream-ване
  • запис (record.sh)

След което от voctogui при нужда се сменят различните картини. Като цяло е доста по-просто за разбиране от по-големите setup-и с конвертори и т.н., но и с по-малко функционалности.

Доколко добре работи?

Работи прекрасно, въпреки че се опитваме да открием един бъг с забавяне на audio-то, който се появява в някакъв момент. Започвам да си мисля, че има някакъв проблем със самия лаптоп, с който правим миксирането.

Какво още можем да искаме?

Хрумнаха ни няколко екстри, които да добавим, така че да стигнем функционалността на хардуерния setup:

  • Начин да излъчваме екрана за проектора от при нас. Това ще иска някаква доработка, за да смъкнем латентността на цялото нещо под 100ms, понеже иначе ще е доста забележимо (представете си как лектора прави нещо и проекторът се променя след 5 секунди). Единият от вариантите, който ни хрумна е проекторът да е вързан на едно pi и то директно да може да избира кой multicast да гледа (някоя камера, лаптопа на лектора или нещо трето).
  • Overlay надписи по време на лекцията – трябва да видим какво има да се пипне още, мисля, че има някаква такава функционалност (или може да ги сложим във фона).
  • По-добра синхронизация на различните потоци – ако работим с няколко камери, може да се окаже проблем, че едната върви с няколко кадъра след другата и трябва да си поиграем със забавяне.

Като цяло, аз съм много щастлив от voctomix и ако успея да убедя екипа, догодина можем много повече да ползваме него, отколкото чисто хардуерния setup (просто ще ни трябват мощни машини, за да се справят с encode-ването, че засега успяваме да работим само на 720p, без да подпалим лаптопа).

2016-08-17 java, unicode, emoji

Wednesday, August 17th, 2016

Чудех се дали да кръстя това “fuck you, Java”.

От някакво време гледаме проблеми с пращането на emoticon-и (ако не знаете, unicode стана пълен с всякакви лайна) – в някакви случаи се намазват, не пристигат вярно и т.н.. При нас през JNI стринговете се пращат до един C/C++ lib, от който всъщност излизат през мрежата от там, като по пътя има малко debug, който да каже какво излиза…

Седя аз и гледам как за намазващото се emoji по някаква причина получавам 6 байта от java-та, вместо 4 (което очаквам). 6-те байта ми изглеждат странно, не наподобяват UTF-8 (поне това, което аз знам), и след някакво четене откривам, че педе^Wпрекрасните хора от java под UTF-8 разбират modified UTF-8, или някакви неща като по-големите unicode символи се кодират така, че нищо друго не може да ги схване, освен друга java. Това обърква SMS центровете по пътя и всякакви други реализации и води до странни за дебъгване проблеми.

Разбира се, това се случва само с определени много много големи emoji-та, които ги има само на определени телефони в стандартните клавиатури, което па води до много фалшиви следи, като например “това са го строшили в android 5 при samsung”, “сървъра ги яде”, “космически излъчвания” и т.н..
(“клавиатурите” в android са софтуерни компоненти, дето явно всеки малоумен производител си пише сам)

Решението поне в нашия случай е в JNI-то да се превежда техния utf8 до нормалния. Ровейки се из интернета, намерих още подобни оплаквания, но явно не всички успяват да се ударят в това, понеже преди това се оказва, че например mysql-ската им база не ползва верния storage type, node.js-а им има само UCS2, който па хептен не може да ги събере и т.н..

Много хора просто казват “не ползвайте тия работи”. Сериозно ми се иска и за мен да беше опция…

2016-08-14

Sunday, August 14th, 2016

Ужасно ми се спи, та накратко.

Преместихме си офиса, което беше дълго и тежко преживяване и включваше бърникане от моя страна в ел. табло със закачане на жици. Никой не умря.

Случиха се БургасConf и ВарнаConf през седна седмица, като присъствах само на второто. На него се занимавах основно с FOSDEM-ския setup и откривам някакви неща, за които има да се пише сериозно код, който може да се окаже и донякъде в kernel-а, което изобщо не ме радва. Ще седна да си опиша по-подробно реализацията тия дни, може някой да може да даде интересни идеи.
(записи – тия дни)

Забравих да кажа, че има cfp за OpenFest 2016, submit-вайте, добри хора. Намирам за срамно, че още никой не е направил workshop за open source/hardware варене на ракия.

2016-07-18 httpoxy

Monday, July 18th, 2016

Накратко, ново vulnerability, ако имате web сървър, дето проксира/праща до php, python, go (или вероятно и други неща, дето ги лови Proxy: header-а), минете и си пипнете конфигурацията на web сървърите.

2016-06-24 радио-link

Friday, June 24th, 2016

(blog post за разсейване)

Пешо (който организира uzana.io) си взе няколко ubiquiti airmax-а, с които да си пусне net (като разстоянието, което има да покрие е около 12км). За да им направим истински тест, решихме да ги вържем от у нас (Лозенец, близо до водната кула) до у тях (Костинброд), което е около 18км.

Лъчът се оказа достатъчно широк, че да не трябва ултра-точно насочване, и резултатът може да се види в един smokeping, който пуснах да дебне. Има едно прекъсване при донастройване първия ден на вертикалата от Костинбродската страна. Като цяло нощно време загубите са малко, през деня обаче има бая зашумяване по пътя – например НДК е точно по правата линия и техния wifi се чува бая добре с тия антени…
(тия антени чуват наистина много добре, май мога да слушам wifi-та на няколко километра с тях)

Може да се види снимка на гледката от моя покрив. Да, знаем, че сме го закачили на гръмоотвода.

След упражнението се оказа, че аз имам root на router-а на Пешо, та първо най-накрая си подкарах bgp за моя ipv6 вкъщи, после подкарах при него, и накрая ги interconnect-нах през радиовръзката. Сега ако ми спре net-a вкъщи, ще имам поне ipv6 през Костинброд. Наливам пълна таблица и на двете места, сложил съм local preference на пътищата от него да е по-малък (и по същия начин на двата router-а от другата страна моя prefix през неговия link е с по-малък localpref), като цяло съвсем стандартен setup :)

Мога спокойно да кажа, че вкъщи свързаността ми вече е географски подсигурена.

Log-ове, дървета, бази данни

Sunday, May 29th, 2016

Около разни разговори за една нова система при нас и какви бази данни трябва да ползваме (и викове от някакви хора “ама то трябва да е задължително nosql” с идеята, че nosql == магически бързо) и обяснения, подкрепени с малко тухли, реших да драсна това – какви основни неща ползват базите данни, защо (и какво можем да очакваме с промените по хардуера), заедно с разни други наблюдения.

На всички, които това им е интересно препоръчвам “Transaction Processing” на Jim Gray като едно много добро начало.
(за хората, които предпочитат да четат код, двете малки и съвсем истински бази са BDB и SQLite (който е и пример за истински добре написан софтуер))

По принцип под “база данни” се разбира ACID база данни, вероятно с някакъв SQL интерфейс. В по-модерни времена се разбира някакъв вариант на това, без SQL, понякога просто бърз начин човек да съхранява (и губи) данни.

ACID значи следното:
Atomicity (атомарност) – всяко действие или се изпълнява изцяло, или не се изпълнява изобщо (т.е. ако кажем “искам да увелича с единица на тия две места”, или ще се увеличат и двете, или ще получите грешка, но никога няма да се промени само едното).
Consistency (консистентност) – има вътрешни правила, които винаги са в сила, (например ако сме казали, че стойностите в дадена колона са уникални, базата не трябва да ни позволи да вкараме две еднакви такива).
Isolation (изолираност) – никой няма да ни подмени данните, докато работим с тях.
Durability (издръжливост) – ако сме записали нещо в базата и тя е казала, че е записано – то няма да изчезне, т.е. записано е на физическия носител, който не се влияе от спиране на тока.

Като цяло това са свойства, произлезли от нуждите на счетоводството/банкирането. Една ACID база данни е перфектна за всякакви такива нужди, понеже позволява да се опишат всякакви сложни структури от данни и тя да се грижи за това да не се омазват и да може да се работи с тях.

Всички тези свойства имат негативно влияние в/у performance. Най-зле се отразява D-то, понеже в повечето случаи това значи по поне един fsync() на транзакция, което от своя страна води до поне една физическа дискова операция, а поне преди SSD-тата те бяха най-голямото ограничение. I (и донякъде зависещото от него A) пък започва да се проявява при достатъчно бързи дискови масиви и големи паралелни натоварвания, когато се налага да се взимат и изчакват много (и сложни) lock-ове.

Изобщо, ако искате да запомните нещо съвсем просто от цялото ми писание, TL;DR-то е: писането в базата ви е ограничено от това колко транзакции може да ви направи дискът, четенето (ако базата ви не се събира в паметта) – също. Ако не са ограничени от това, ще загубите данни.

Други бавещи неща в стандартните бази данни са огромните възможности на SQL-а – всякакви join-ове и други сложни заявки, които в един момент няма как да се оптимизират – и неща като trigger-и, foreign key-ове, views, които усложняват и вкарват навсякъде нови lock-ове, сметки и забавяния. Например може да е възможно една база да пише в transaction log-а си по 2000 транзакции в секунда, но голяма част от времето ѝ да отива да проверява дали данните отговарят на консистентността, да чака read lock-ове или просто да parse-ва сложния SQL, който ѝ се подава.

Структурите, които базите данни използват са ориентирани към това да може да се работи ефективно и сравнително бързо с бавни, но сигурно-записващи устройства (дискове), т.е. основното предположение на повечето бази данни е, че имаме процесор с много бързи регистри/кеш, 10тина пъти по-бавна памет, и около милион пъти по-бавен диск, от който може да се чете само на блокове (т.е. парчета с размер от 512 или 4096 байта, align-нати на такава граница), като линейните действия (с няколко предни блока) са по-бързи от random действията.

Основната структура, която базите използват се нарича B+ дърво. В “Transaction Processing” има страхотно описание и си личи колко гениална структура е, аз тук ще се спра само на основните неща от нея:
– представлява нормално дърво, с корен и листа на няколко нива;
– всеки node от дървото съдържа ключ, данни и масив от указатели, който казва за кой range от данни към кой друг node да се ходи;
– размерът на всеки един node се гледа да е колкото една страница, константен за дървото, кратен на block size на устройството, на което се записва. Варира от 512B (за много много отдавна), 4KiB (сравнително отдавна) до всякакви други стойности (веднъж като гледах кода на postgresql беше 64KiB);
– в B+ дървото (и каквото по принцип се използва) всеки node има указатели към левия и десния си такъв, за да направи лесно търсенията по интервал (range).

Така търсенето в дървото е в общи линии логаритмично при основа размерът на масива от указатели във всеки node, което много ускорява работата при блоково устройство.

(почти) всяка таблица в съществуващите бази данни е B+ дърво, подредено по primary key-а си. Допълнителните индекси са често B+ дърво или подобна структура по колоната, която индексират и със стойност primary key на търсения ред. Това води до следните няколко неща:

– Търсенето по primary key винаги е по-бързо от търсенето по вторичен индекс (освен в един специфичен случай по-долу);
– Индексирането не е магия. Виждал съм хора да слагат в заявка търсене по функция от дадено поле, и ако индексът не е построен по същата функция, базата няма как да го използва;
– Като цяло за блокови устройства няма по-ефективна структура – прави малко четения (които са бавни) за сметка на сравненията (които са сравнително бързи).
– Някои бази имат допълнителни типове индекси, които вършат работа в по-странни случаи. Примери са full-text индексите (GIN на някои места), R-дървета (за многомерни данни) и hash-овете.

Тук има един интересен hack, който се поддържа от повечето по-нови версии на базите данни. Ако имаме следната таблица:

create table pesho (
pesho_sid serial not null PRIMARY KEY,
field_a int not null,
field_b int not null,
field_t varchar(16) not null
);

и имаме да търсим по field_a и field_b, за да прочетем field_t (SELECT field_t FROM pesho WHERE field_a=1 AND field_b=2), по принцип бихме създали индекс по field_a и field_b. Тогава заявката ще прави първо търсене в индекса, ще намери pesho_sid за нужния ред, и ще потърси после в самото B+ дърво. По-хитро (ако базата го поддържа) е да направим индекса по field_a, field_b и field_t, като тогава базата ще намери стойността в индекса и ще има и нужните данни, за да върне директно отговор на заявката само с първото търсене.
(още по-подобрен вариант за конкретния случай е да се махне pesho_sid и да се направи primary key по field_a и field_b, доста хора се притесняват по принцип от композитните primary key-ове, а не трябва)

Другият компонент, който би трябвало да има във всяка база е т.нар. transaction log (или write-ahead log, binary log, journal или всякакви други имена). Идеята му е, че всяка транзакция/действие за писане се записва в него, след което той се sync-ва до диска (така се гарантира онова Durability), и чак като се напълни се насипва в/у реалните данни по диска. Всяко действие се записва така, че да е идемпотентно, т.е. да може логът да се приложи няколко пъти, без да повреди данните (което е нужно за спасяване от момента, в който ни спре тока докато flush-ваме log-а).Това помага за доста неща:

– Писането по диска е през повечето време линейно, което доста забързва действията по базата;
– Заявките естествено се сериализират и при спиране на тока или нещо такова после могат да се replay-нат от лога;
– Същия log може да се използва за репликиране на базата, или за възстановяване от backup заедно с dump от дадена дата, или дори за връщане назад.

Идеята всъщност не е ограничена до базите данни, и в един или друг вид се използва на много места (например файлови системи).

Този вид log се използва във всички бази данни и в почти всичко, което съхранява данни (изключение са in-memory storage-ите като memcache, на които не им трябва да се синхронизират с някои и не им пука за спирането на тока).

Ако човек се загледа какво ползват nosql базите, ще открие все същите неща. По-долу съм изброил няколко и причините да са по-бързи (за някои неща):

Apache Cassandra в общи линии използва in-memory transaction log-ове, които синхронизира с другите сървъри в клъстера (т.е. губят се данни, ако на всички им спре тока). Решава си проблемите със скоростта, като не поддържа нищо сложно (като join-ове) и като пише по диска само на големи burst-ове, когато напълни някоя таблица.

Apache CouchDB комбинира по хитър начин B+ дървото и transaction log-а, като винаги само добавя във файла. За да си помогне още малко, прави fsync() не на съвсем всеки документ, а гледа да batch-ва по някакви писания и да sync-ва веднъж в секунда, което пак може да доведе до загуба на данни.

MongoDB ползва transaction log, ползва B дървета за индекси, и се справя с многото писане като просто mmap-ва файловете от базата в паметта. Единственото, което fsync()-ва, е transaction log-а, на 100ms (pdf с презентация за mongodb internals).

Както и много други знайни и незнайни нещица. Голяма част от тях не биха се справили със стандартния ми тест за сериозна база данни ( да се пуснат транзакции спрямо нея и да и се рита тока, и да не загуби нито една от потвърдените), но пък имат приложение в много области, където или данните не са чак толкова важни, или има начин да се заобиколи загубването им. Един хубав пример има в Beautiful data, гл. 5, където facebook описват как, за да си съхраняват clickstream-а, са минали през Oracle, MySQL и са стигнали до cassandra, която просто може да се scale-ва ужасно много (и на тях изобщо не им пука за няколко изгубени click-а).

Ако събера сили, ще напиша приложение за дистрибутирането на базите данни, CAP теоремата (или защо господ ни мрази) и какво правят разни хора по въпроса.

2016-04-22

Friday, April 22nd, 2016

Трябва да пиша по-редовно, да не се получава миш-маш като тоя по-долу.

Както обикновено, ми върви на дебъгване. В последната седмица от по-странните неща се сещам за:
– build на android image (за нещо, правено и писано от (некадърни) китайци);
– Java/groovy;
– Python;
– И нормалното количество VoIP бози.
За да завърша картинката, обмислям да седна да подкарам VAX-а, който виси в initLab.

Тая вечер ходих на концерт на “band H.”, хора, които свирят Tool. Прилично се справиха, въпреки че им куцаше ритъма на моменти (което не е учудващо, Tool са учудващо гадни за свирене).
(по някаква причина в същия ден имаше 3 концерта – band H., Smallman и Irfan, не беше лесен избора)
(random човек ме разпозна на концерта и каза колко се радва на разните проекти като initLab, дето правим)

Седнах да подкарвам най-накрая сертификати от letsencrypt за нещата по marla, и успях да наслагам на половината, преди да ме удари resource limit-а при тях. Следващата седмица ще ги довърша. Разписах нещата с acme-tiny, базирано на нещо, което Петко беше драснал за лаба, оказва се сравнително просто (ако config-а е подреден както трябва) да се parse-ва apache config-а и да се смята какви точно сертификати да се генерират за кого.
(открих кофа неща, които вече не се host-ват при мен и ги почистих)

Събрал съм резултатите от теста на FOSDEM-ската техника (сравнение на запис на stream-а и encode-нат резултат, от нашия и от FOSDEM-ския setup), и като цяло с още малко пипване това може да се окаже достатъчно лесно за по-малки конференции (на които не си влачим 6-7-8 човека от екипа).

На opendata.government.bg тия дни пак качиха нещо интересно (тоя път – целия търговски регистър от 2008ма досега) и пак претовариха нещастната виртуалка (която е един debian в/у microsoft hyper-v). Обмислям някаква магия да може да преживява такива неща по-лесно, щото не се очаква да намалеят интересните данни.

За който се интересува, върви световното първенство по snooker, прилично забавно е. Тия дни пътувахме в метрото и tether-нати през телефона ми и с един таблет си гледахме вървящия мач…
(да живее технологията)

И не си спомням нещо друго да ми се е случвало.

Втория BGP workshop

Monday, April 4th, 2016

Направихме и втория BGP workshop, на който още хора откриха колко лесно се подкарва IPv6 :) При достатъчно желаещи ще направим и трети след около месец. Също така може да помислим по въпроса хората да имат отделно устройство за подкарване и да са си сами потребители, понеже една от най-гадните задачки се оказва да убедиш всичките ти приложения на операционната система да се bind-ват на определен ip адрес, когато излизат навън.
(а аз тотално се изложих, понеже мислех да се включа вместо един от участниците, който не дойде, ползвайки pine64, което ми пристигна наскоро, и някъде на средата открих, че kernel-а му няма 802.1q и че трябва да компилирам отнякъде нов… което ще свърша, като си подкарам някаква среда скоро).

От интересните неща, които (пре)открихме беше, че ICMP echo reply от 8.8.8.8 винаги е орязан до 64 байта payload, колкото и голям пакет да се прати. Това води до въпроса “абе, защо нещо някъде ми реже пакетите?”…

Ако има желаещи да организират такова нещо извън София, мога да услужа с малко тунели, скриптове и да измислим начин за нужния хардуер за провеждането.

(а вечерта бяхме на Jimmy Carr, от който лицето още ме боли от смях)

2016-03-31 въпроси за админско интервю

Wednesday, March 30th, 2016

Около едно интервю, което правих тия дни и понеже един приятел иска да изпитва някакви кандидати при него, реших да измисля малко въпроси като за интервю за админи. Ползвайте на воля :)
(историята показва, че никой от кандидатите за работа не ми чете блога, та няма страшно, че ги публикувам тук)
Въпросите са отворени, донякъде не-напълно зададени – това е полезно, понеже показва как кандидатът мисли и какви уточняващи въпроси задава.

Как бихте реализирали система за backup, на която сървъра не може да прочете данните на клиента (т.е. са криптирани подходящо) и compromise на клиента не води до възможност за декриптиране на backup-ите му?

Ако имате 12 диска, кое е по-reliable – 2 raid масива в raid5 от 6 диска или 1 масив от 12те диска в raid6? Кое е по-производително?
(изобщо, какво е raid6?)

Имате дърво с директории и (много) файлове в тях, как ще намерите кои файлове се повтарят?
(задължително трябва да се знае какво е -print0)

Какви са трите типа ssh тунели? Какво е socat?
(ssh трябва да го знаят всички, socat-а почти на всички някога е трябвал)

Пак към ssh-а, защо не трябва да се логваме на чужда машина с agent forwarding и как точно се exploit-ва?
(това е забавна задача за практическо упражнение)

Защо не трябва да се сверява часовникът на машина с ntpdate, който се пуска от cron-а веднъж на ден/час?

При смяна на DNS запис с TTL от 3600 секунди, колко време отнема да се научи от 90% от internet? 95% ? 99% ? 100% ?
(същия въпрос за 60-секунден TTL. Bonus points, ако споменат на БТК/vivacom малоумните resolver-и)

Защо на натоварен linux сървър не трябва да има swap?
(не мисля, че е само за linux, но трябват малко тестове още за останалите)

Какво е rollback plan и кога трябва да имаме такъв?
(bonus points за “винаги”)

Защо не трябва да се смесват различни модели/производители на дискове в един и същи raid масив?

Каква е разликата м/у strace и ltrace?

Какъв е основният протокол за контрол/комуникация с мрежови устройства?

Защо не трябва да се филтрира цялото ICMP?

Как можем да сменим root паролата на linux-ка машина, като имаме достъп до конзолата?
Как можем да направим това трудно/невъзможно?

Защо не се ходи с къси гащи в datacenter?

Предимства и недостатъци на hardware и software raid?

Инструменти за анализ на натоварването на машина, кои в кои случаи се ползват?

2016-01-25 интервюта

Monday, January 25th, 2016

Човек и добре да живее, трябва да прави интервюта.
(и после почва да живее зле)

Писал съм преди за интервютата, дето правих, но не очаквах нещата да станат по-зле… От известно време в securax си търсим php и js програмисти и QA, в чиито интервюта участвам, и идват всякакви интересни хора.

Процентът хора, кандидатстващи за програмисти и неспособни да напишат fizzbuzz се е увеличил. Освен стандартните грешки в самия код, имаше един-двама човека, които казаха, че “това без internet не могат да го напишат” и един случай, в който седнаха да пишат очаквания output вместо програмата, която да го прави.
(рекордът беше днес, когато след като дадох на един човек задачата, той просто си тръгна с някакво оправдание)

За QA и понякога за програмистите имаме един тривиален тест с няколко математически/логически задачи, да ги видим как/дали мислят и дали разбират английски (което си е доста важно при нас, понеже някаква част от фирмата не говори български). Откриват се всякакви странности, например:
– едната задача е да се сметне ако нещо с ДДС е 600 лв, колко е без (ДДС-то е 20%). Редовният отговор е 480, и имаше два куриоза – 400 и 576.
– друга задача гласи “One brick is one kilogram and half a brick heavy. How much does a brick weight?”. Повечето хора казват или един килограм, или килограм и половина, а много директно не могат да си преведат цялото изречение и си мислят, че им се казва “една тухла тежи един килограм”…
– има няколко глупави въпроса като от обща култура, които нямат голям смисъл, но водят до забавления. Единият е “Who was the first person in space”, на което двата ми любими отговора досега са “Louis Armstrong” и “Adam”.
(и сигурно ще сменя тия задачи, че вече са ми скучни)

В повечето случаи изобщо не се стига до по-сложни въпроси (алгоритми, сложности, някакви практически проблеми, fizzbuzz без if-ове), просто защото не са по силите на човека. Идея си нямам дали само при нас е така, или просто аз помня само ужасяващите случаи, някой има ли наблюдения по въпроса?

2016-01-05 разни около opendata.government.bg

Tuesday, January 5th, 2016

Едно от нещата, с които се занимавам, е да помагам на Общество.бг с разни админски дейности.

opendata.government.bg е един от техните проекти, който след доста мъки се deploy-на в държавната администрация, и има някакво количество проблеми с хостинга си там (например падаше около DDoS-овете около изборите). Днес в един момент видях някакви аларми на monitoring-а за машината и открих, че ми е доста трудно да се логна, и се зачудих дали няма някой нов DDoS, и на smokeping-а ситуацията изглеждаше зле.

Порових се малко и въпреки сериозното натоварване се оказа, че (учудващо) CKAN-а (който е писан на python) явно удържа на напора и сервира спокойно каквото му искат хората. В крайна сметка бяхме успели да претоварим shaper-а на виртуалката (или знам ли, целия host), което май има шанс да се оправи тия дни.

По-интересното обаче беше причината – за пръв път публикувана и систематизирана на едно място информацията за проверените агенти на ДС. Мен лично ме радва как интересът към това не спада, и че въпреки че се чуват гласове “какво от това”, че данните не са точни, не са пълни и т.н., те са добра стъпка към запомнянето на миналото и историята.

Надявам се да има още такива данни, които да предизвикат интереса на хората :)

Monitoring-а на OpenFest 2015

Tuesday, November 24th, 2015

Автор: Владимир Витков / zeridon
Дата: 2015.11.16
Контакт: vvitkov@linux-bg.org / jabber: zeridon@jaim.at / irc: zeridon @ marla.ludost.net

Тази година осъзнах, че OpenFest хич няма да е малко събитие. Имайки предвид количествата хардуер, количеството хора и новото място без почти никаква инфраструктура стана ясно, че ни трябва стабилен мониторинг. Тази година това беше моята основна задача, покрай другите неща.

Мониторинг системата имаше 2 цели:
* Събиране на данни за производителността на мрежата/хардуера който бяхме пръснали
* Наблюдение на ключови параметри и известяване за проблеми

Реализацията на системата започна доста рано и улесни работата (поне за мен). За събиране на данни за производителността използвахме комбинация от collectd и graphite. Данните бяха събирани на всеки 10 секунди. Машината, която играеше ролята на колектор беше наблюдавана доста по-сериозно.
Тъй като трябваше да събираме данни за производителността на мрежовото ни оборудване, collectd беше внимателно помолен да събира SNMP данни. Tова се оказа учудващо лесно. Данните събрани (или изпратени) към collectd след това бяха препращани към graphite. Избрахме graphite поради опита който имахме и поради факта, че размерът използвано пространство за съхранение на данните е лесно предвидим. Graphite използва whisper бази, които се преалокират в зависимост от времето за което ще пазите данните.
Данните от wi-fi устройствата бяха събирани локално на самите тях от collectd, който ги препращаше на централния колектор.

В допълнение към данните за производителност трябваше да осъществяваме и наблюдение за достъпност и състояние на услугите. За целта използвахме nagios3, който наблюдаваше суичовете (състояние на портове, натоварване, SNMP traps, телнет), wi-fi устройствата (достъпност, пинг, ssh), излъчването от залите (брой стриймове, състояние на всеки от стриймовете). Голямото “забавление” беше подкарването на SNMP трап-овете. Ако наистина, ама наистина не ви се налага да го правете – недейте. Ако все пак настоявате, погледнете https://github.com/OpenFest/openfest-2015-network/tree/master/monitoring/snmp.

За да представим нещата красиво използвахме tessera, като дори в един момент публично раздадохме линкове към някои от графиките. Конфигурацята на графиките беше от Петко, така че нека той сподели повече.

Бяха ни необходими и разни други дреболии, като arpwatch – за да знаем ако някой прави глупости, централизиран сислог за да не ровим по различните устройства, писане на стартъп скриптове за нещата (през systemd) което беше болезнено неприятно.

Като цяло забавлението беше на прилично ниво (за догодина – и автоматизирано). Ако някой се интересува от конфигурациите (иска да ми се кара как не се правят неща), може да ги намери на https://github.com/OpenFest/openfest-2015-network/tree/master/monitoring. Документирани са … бегло, но са четими като цяло.

Публикуваме архива на collect базата данни за всички заинтересувани.

2015-11-16 Мрежата на OpenFest

Monday, November 16th, 2015

Мрежата на тазгодишния openfest беше с един порядък по-сложна от миналогодишната. Как вървят кабелите и в общи линии си личи на плановете на партера (първия етаж) и първи балкон (втори етаж).
(ще говоря за core мрежата само, Петко ще разказва за wireless-а)

Понеже самата зала България няма никаква мрежова инфраструктура, направихме мрежа от няколко свързани кръга (в стила на ISP) с MSTP в/у тях, така че да можем да се спасим от поне един паднал кабел. Решихме, че един гигабит ни стига за backbone и не правихме някакви по-сложни неща, като балансиране м/у няколко връзки.

Самата core мрежа имаше следните “клиенти”:
– router и encoder, при core switch-а;
– wireless мрежата;
– Видео екипите в трите зали;
– Рецепцията;
– switch-овете за крайни потребители в workshop залата, и
– две специално донесени железа от e-card, на които хората се записваха за томбола.

Тази година пак няколко човека ни услужиха с техника – Светла от netissat, Иван Стамов, Стефан Леков донесе един switch, digger даде двата за workshop-ите, и останалото дойде от мен и initLab. Също така настройването не го правих сам – Леков и Петко участваха активно в дизайна (и направиха прилична част от него), а Стоил, Марги и Zeridon – голямата част от конфигурацията на switch-овете.

Имахме 8 core switch-а на различни места, като където се налагаше да има switch в залите, се слагаше нещо по-тихо. Целият core беше от изцяло гигабитови switch-ове (като изключим един, който имаше и 10gbps портове, но не влязоха в употреба, за съжаление). Така можахме да закачим всичко извън тази мрежа на гигабит, включително wireless AP-тата, които тази година бяха изцяло гигабитови. Нямаше грешката от миналата година да се ползват супер-различни switch-ове – бяха 3 TP-Link SG-3210 и останалото леко разнообразни Cisco-та, като STP конфигурация с тях в тоя вид беше тествана още на курса по системна администрация (ето тогавашната схема).

Router ни беше един HP DL380G5, който в общи линии си клатеше краката (до момента, в който пуснахме да encode-ва един stream и на него). Тук нямаше особено много промени от миналата година, просто един linux-ки router с NAT и DNS/DHCP. По-забавните неща там бяха многото monitoring и записвания на данни (за които ще карам да се пише нещо отделно), в общи линии setup с collectd и събиране на каквито данни може да се събират.

Нямам в момента някакви снимки от мрежата, но беше опъната по най-добрия възможен начин за обстоятелствата – кабелите бяха прибрани и увити с велкро, нямаше някакви, през които да минават хора и като цяло не се виждаха особено много. Местат, които не бяха посещавани от хора бяха малко плашещи (например core switch-а, router-а и encoder-а бяха под едни стълби до едно ел. табло и изглеждаха като мрежовия вариант на клошари), но за останалите успяхме да намерим по-скрити и подходящи места (в workshop area-та switch-ът с няколко други неща беше под един роял).

Internet-ът ни беше от Netx (които успяха да реагират в нормални срокове и да опънат оптика около месец преди събитието, за разлика от други, които ще останат неназовани), и тази година 100те mbps нещо почнаха да не ни стигат. Това са графиките от първия и втория ден, като прилична част от изходящия беше streaming-а. Проблемите се виждат на графиката на smokeping-а, и поне според мен за по-спокойно догодина трябва да сме на 200mbps.

Адресният план беше много близък до миналогодишния:
VLAN 50 – външната ни връзка, 46.233.38.137/28 и 2a01:b760:1::/127
VLAN 100 – нашата си management мрежа, 10.100.0.0/24
VLAN 101 – мрежата за хората, свързани на кабел, 10.101.0.0/22, 2a01:b760:abc:2::/64
VLAN 102 – мрежата за хората, свързани на wireless-а, 10.102.0.0/22, 2a01:b760:abc:3::/64
VLAN 103 – мрежата на видео-екипа, 10.103.0.0/24
VLAN 104 – мрежата на overflow телевизорите, 10.104.0.0/24

(нещо, което не трябва да пропускаме за догодина е да раздадем адреси на видео-оборудването предварително, сега те си ги измисляха в последния момент и аз просто разместих раздавания range от dhcp-то)

Firewall-ът беше тривиален, от типа на “тия всичките vlan-и не могат да си говорят помежду си, само с външния” и “25ти порт е забранен”. Не съм голям фен на stateful нещата за такива случаи, а тоя прост setup свърши прекрасна работа.

Пуснали бяхме и още нещо странно – освен филтрацията на broadcast трафика, бяхме включили за потребителските vlan-и (101, 102) proxy_arp_pvlan, което в общи линии е poor man’s forced forwarding – караше router-а да отговаря със себе си за всички arp заявки. Така се избягваше прилично количество broadcast, затрудняваше се arp spoofing-а (с няколкото други неща директно и се убиваше) и като цяло не направи някакъв проблем, освен че може би държеше пълен arp cache на windows машините.

Преди събитието имахме няколко проблема. Един от тяхбеше, че не бяхме предвидили вярно колко кабел ни трябва, и се наложи спешно да се купи още един кашон (300м), но като цяло мрежата изгря без проблеми, може би с една-две грешки по конфигурацията на портовете. Също така един от switch-овете (cisco ws-3550-12G) имаше проблеми с gbic-ите, понеже няколко от медните не работеха, та за това имахме 5м оптика – един от access point-ите беше свързан през single-mode gbic в switch-а и конвертор от другата страна. За дебъгване имаше един вечерта, като закачахме на e-card машините, за които се оказа, че един странно прекъснат кабел прави нещата да не работят, но имаше link (това се усети най-вече по това, че не щяха да закачат на гигабит).

По време на събитието пак имахме проблем с ipv6, този път обаче след нашия router, и понеже нямахме как да го debug-нем/решим, втория ден бяхме ipv4-only. Бяхме правили тестове предишната седмица с връзката, но явно някакви неща не сме успели да ги хванем (или нашия router пак е направил нещо странно). Също така по погрешка бяха извадили тока на един switch (което аз поне изобщо не съм усетил), и заради кофти удължител за малко е паднало едно AP (което е било хванато моментално на monitoring-а).

Като цяло, мрежата избута всичките си неща без никакъв сериозен проблем и потребителски оплаквания тая година нямаше.

Ще оставя статистиките и другите неща на хората, дето ги събираха :)