opendev: OpenStack Foundation failed to learn the lesson
Reminder: OpenStack Summit Sydney - CFP Deadline
Arduino Para Niños Parte II: Sensor de Movimiento
Arduino para Niños
Legacy Systems as Old Cities
I just realized that I only tweeted about this a couple of months ago, but never blogged about it. Shame on me!
I wrote an article, Legacy Systems as Old Cities, for The Recompiler magazine. Is GNOME, now at 20 years old, legacy software? Is it different from mainframe software because "everyone" can change it? Does long-lived software have the same patterns of change as cities and physical artifacts? Can we learn from the building trades and urbanism for maintaining software in the long term? Could we turn legacy software into a good legacy?
You can read the article here.
Also, let me take this opportunity to recommend The Recompiler magazine. It is the most enjoyable technical publication I read. Their podcast is also excellent!
Update 2017/06/10 - Spanish version of the article, Los Sistemas Heredados como Ciudades Viejas
openSUSE Conference 2017
В конце прошлого месяца разработчики openSUSE снова собрались в Нюрнберге, чтобы обсудить дальнейшее развитие дистрибутива и просто пообщаться и весело провести время вместе. В последние пару лет проект стал очень быстро меняться. К проекту присоединилось очень много новых людей. Новые идеи, которые они приносят, находят свое место в новых проектах, разрабатываемых для openSUSE. Даже используя все информационные каналы проекта openSUSE, тяжело уследить за всеми новшествами, включаемыми в проект, и просто меняющейся стратегией совета. Поэтому вопрос о посещении конференции, тем более, если вы мейнтейнер, долгого размышления не потребует 

Конференция была открыта докладом Матиаса о LiMux. Краткая история проекта, его взлет, надежды и его падение… Явный пример того, на сколько опасны могут быть политики, пользующиеся властью для удовлетворения собственных предпочтений, и закрывающие глаза на интересы и желания населения. В настоящий момент я как раз работаю над этим проектом в администриции Мюнхена.
На конференции я снова встретился с Дмитрием, занимающимся проектом invis и продвижением Free Software решений на базе 1C в Германии. Беседовали о русскоязычном сообществе openSUSE, и о причинах его столь плачевного состояния. Я очень надеюсь, что сообществу получится преодалеть существующие проблемы и оно снова возьмет курс на развитие, как было в 2008-2010 годах.
Познакомился с Денисом Кондратенко из Киева и его женой. Очень приятная пара. Денис рассказывал о Ceph и EKG в openSUSE, а также о методах обработки метаданных в Elasticsearch. Мой личный опыт использования Elasticsearch ограничивается только BigData/Hadoop, поэтому и тут удалось узнать что-то новое.
Много новых иновационных идей было услышано от Ричарда. Он уже давно стал openSUSE evangelist’ом; его доклады об OBS или openQA можно услышать практически на каждой европейской Free Software конференции, посвященной GNU/Linux. Я всем советую посмотреть его доклад о Containerised Application.

Одним из спонсоров конференции в этом году стал fedora project. Fedora уже не первый год использует нашу систему openQA для автоматического тестирования linux-систем, а сотрудники RedHat уже во второй раз читают свои доклады на openSUSE Conference. В этом году это был доклад How semantic analysis of C and C++ ELF binaries can be used to analyze ABI changes, в прошлом году это были Enforcement of a system-wide crypto policy и Testing complex software in CI.
В общем, как и обычно, конферениция оставила приятное впечатление (пару фоток можно найти тут). И хотя в этом году она длилась всего 3 дня вместо 5, как в прошлом, информации для размышления я пролучил придостаточно. Её посещение в этом году не стоило мне ничего. Спасибо за это TSP. В следующем году она пройдет в Праге, куда я планирую поехать с семьей. Возможно там я встречусь и с теми, кто читает сейчас эти стоки 
Setting Alt-Tab behavior in gnome-shell
After updating my distro a few months ago, I somehow lost my tweaks to the Alt-Tab behavior in gnome-shell.
The default is to have Alt-Tab switch you between applications in the
current workspace. One can use Alt-backtick (or whatever key you
have above Tab) to switch between windows in the current application.
I prefer a Windows-like setup, where Alt-Tab switches between
windows in the current workspace, regardless of the application to
which they belong.
Many moons ago there was a gnome-shell extension to change this behavior, but these days (GNOME 3.24) it can be done without extensions. It is a bit convoluted.
With the GUI
If you are using X instead of Wayland, this works:
-
Unset the Switch applications command. To do this, run
gnome-control-center, go to Keyboard, and find the Switch applications command. Click on it, and hitBackspacein the dialog that prompts you for the keyboard shortcut. Click on the Set button. -
Set the Switch windows command. While still in the Keyboard settings, find the Switch windows command. Click on it, and hit
Alt-Tab. Click Set.
That should be all you need, unless you are in Wayland. In that case, you need to do it on the command line.
With the command line, or in Wayland
The kind people on #gnome-hackers tell me that as of GNOME
3.24, changing Alt-Tab doesn't work on Wayland as in (2) above,
because the compositor captures the Alt-Tab key when you type it
inside the dialog that prompts you for a keyboard shortcut. In that
case, you have to change the configuration keys directly instead of
using the GUI:
gsettings set org.gnome.desktop.wm.keybindings switch-applications "[]"
gsettings set org.gnome.desktop.wm.keybindings switch-applications-backward "[]"
gsettings set org.gnome.desktop.wm.keybindings switch-windows "['<Alt>Tab', '<Super>Tab']"
gsettings set org.gnome.desktop.wm.keybindings switch-windows-backward "['<Alt><Shift>Tab', '<Super><Shift>Tab']"
Of course the above also works in X, too.
Changing windows across all workspaces
If you'd like to switch between windows in all workspaces, rather than
in the current workspace, find the org.gnome.shell.window-switcher
current-workspace-only GSettings key and change it. You can do this
in dconf-editor, or on the command line with
gsettings set org.gnome.shell.window-switcher current-workspace-only true
Packaging MediaWiki extensions
As part of the work for the openSUSE wiki upgrade and move, I had to package a bunch of MediaWiki extensions. We'll use the MediaWiki 1.27.x LTS release, which means the extensions need to work with this version.
When it comes to packaging, there are three categories of extensions:
The Good
These extensions are hosted on phabricator.wikimedia.org, and you can easily download a tarball matching your MediaWiki version using the "Download snapshot" link on the extension page.
Packaging these extensions is easy - just unpack the tarball and copy/package everything to the extension directory.
These extensions are standardized enough to use a spec file template - usually I only had to adjust the extension name, tarball name and version. Speaking of the version - most extensions don't have explicit version numbers, so I decided to use the tarball date instead.
An example for this category is Auth_remoteuser (extension page, package) which we use to keep the "nice" wiki login form.
The Bad
These extensions are hosted on GitHub and typically only have a "master" branch. They usually still work with MediaWiki 1.27.x, but there's a small risk that they require features added in newer MediaWiki versions, and this risk will grow over time.
On the packaging side, they are as easy as the "good" extensions.
An example is the ParamProcessor extension (extension page, package) which is needed by the Maps extension
The Ugly
These extensions can be hosted on phabricator.mediawiki.org or GitHub, so there are "god ugly" and "bad ugly" extensions ;-) The thing that makes packaging really ugly is that they don't include all the code they need. Instead, you have to download the missing parts with composer.
composer works fine in a "real" system, but makes packaging hard. Running it from the spec will obviously fail because OBS doesn't allow network connections while building a package (and even if it's annoying in this case, not having network access during build is a good thing[tm]).
My solution is a little script that unpacks the extension tarball and runs "composer install --no-dev" inside the extension directory. The most important part is the "--no-dev" parameter because that avoids lots of superfluous things. Afterwards, I build a tarball from the "vendor" directory and add it to the package.
Yeah, I know that's not nice - guess why I named this section "The Ugly" ;-)
One of the packages that need a "composer install" run is the GitHub extension (extension page, package including script to run composer).
Luckily, "ugly" only applies to packaging. The extensions and their maintainers are for sure not ugly - for example, the maintainer of the GitHub extension was very fast in fixing a bug :-)
golang range Tickers
Yesterday Praveen sent me an interesting piece of golang code. Read the following code and tell what the answer will be:
===
type LED struct {
state bool
ticker *time.Ticker
}
func toggle(led *LED) {
led.state = !led.state
}
func looper(led *LED) {
for range led.ticker.C {
toggle(led)
}
}
func main() {
fmt.Println("Initial number of GoRoutines: ", runtime.NumGoroutine())
led := &LED{state: true, ticker: time.NewTicker(time.Millisecond * 500)}
go looper(led)
fmt.Println("Number of GoRoutines after a call to looper: ", runtime.NumGoroutine())
time.Sleep(2 * time.Second)
led.ticker.Stop()
fmt.Println("Number of GoRoutines after stopping the ticker: ", runtime.NumGoroutine())
runtime.GC()
fmt.Println("Number of GoRoutines after gc: ", runtime.NumGoroutine())
}
===
Golang playground URL: https://play.golang.org/p/1as5QN1r2c
Gist URL: https://gist.github.com/psankar/8af76ba183b0203ec141bca8156f5955
I will explain roughly what the code is doing.
There is a LED struct which has a Ticker and a state variable. While creating an instance of the led struct, we initialise the state and the Ticker. There is a looper function will toggle the state, whenever the Ticker fires an event.
Now when the program is launched, there will be one goroutine (the initial main thread). After we call looper in a goroutine, the goroutineCount will be 2. Now, comes the tricky part. We stop the Ticker, after a particular amount of time. We even call the gc.
It was observed by Praveen that this piece of code was leaking go routines and the number of go routines was never going down, inspite of the Ticker getting stopped.
The reason why the leakage is happening is because, the "range" loop is never exiting. If the range loop was on a channel, you could "close" it. The ticker.C channel however is a receive only channel and you cannot close it.
How do we fix this, so that none of the goroutines are leaking ? If you have watched the talks, golang concurrency patterns by Rob Pike and Advanced golang concurrency patterns by Sameer Ajmani, then you will realise that it is quite easy to add another parameter to the looper function, which could just exit the loop. So the updated code will be:
===
type LED struct {
state bool
ticker *time.Ticker
}
func toggle(led *LED) {
led.state = !led.state
}
func looper(led *LED) {
for range led.ticker.C {
toggle(led)
}
}
func looper2(led *LED, q chan bool) {
for {
select {
case <-led.ticker.C:
toggle(led)
case <-q:
fmt.Println("Exiting the goroutine")
return
}
}
}
func main() {
fmt.Println("Initial number of GoRoutines: ", runtime.NumGoroutine())
led := &LED{state: true, ticker: time.NewTicker(time.Millisecond * 500)}
q := make(chan bool)
go looper2(led, q)
// go looper(led)
fmt.Println("Number of GoRoutines after a call to looper: ", runtime.NumGoroutine())
time.Sleep(2 * time.Second)
led.ticker.Stop()
fmt.Println("Number of GoRoutines after stopping the ticker: ", runtime.NumGoroutine())
q <- true
fmt.Println("Number of GoRoutines after sending a message on the quit channel: ", runtime.NumGoroutine())
}
===
Playground URL: https://play.golang.org/p/NlWbyHLHvA
Gist URL: https://gist.github.com/psankar/4e5b2e563038ce3e9c17eb208c76168a
Let me know if you have any comments.
Langkah Sederhana Upgrade Leap 42.1 ke 42.2
Pada kesempatan kali ini Saya mencoba untuk membuat langkah sederhana untuk memutakhirkan versi (upgrade) openSUSE Leap 42.1 menjadi 42.2. Untuk penjelasan lebih detail, Anda bisa mengunjungi panduan upgrade official dari openSUSE di link ini. Sedangkan pada tutorial ini, Saya hanya akan mencoba untuk menjelaskan langkah yang sangat sederhana untuk melakukan proses upgrade. Langkah ini telah saya lakukan dan berhasil. Berikut langkah – langkahnya.
- Pastikan sistem Anda telah dilakukan update, jika belum Anda bisa melakukannya dengan melalui Software Manager atau dengan menggunakan terminal (akses root) dengan mengetik zypper up.
- Lakukan backup repository sekarang dengan mengetik cp -Rv /etc/zypp/repos.d /etc/zypp/repos.d.old.
- Hapus repositori yang tidak diperlukan melalui aplikasi YaST2 kemudian pilih Software Repositories. Cara ini bisa dilakukan juga dengan melalui terminal, namun sebagaimana pada kesepakatan awal bahwa Saya hanya akan menjelaskan langkah yang sederhana dan mudah.

Agar lebih mudah ketika melakukan upgrade, berikut repositori yang tidak Saya hapus.
* OSS
* Non OSS
* OSS Updates
* Packman - Ubah angka versi rilis pada repositori yang ada menjadi 42.2 (sebelumnya 42.1)
- Kembali ke terminal, lakukan refresh dengan mengetik zypper ref.
- Unduh paket dari repositori terbaru dengan mengetik zypper dup –download-only.
- Setelah proses unduh selesai, logout dari sistem.
- Tekan Ctrl+Alt+F1 untuk masuk ke mode teks dan login sebagai root
- Ubah runlevel ke 3 dengan mengetik init 3.
- Terakhir ketik zypper –no-refresh dup untuk melakukan proses upgrade.
Proses upgrade membutuhkan beberapa menit. setelah proses upgrade selesai dan tidak terjadi kendala Anda bisa melakukan reboot pada sistem kemudian setelah login Anda bisa mengecek versi dari sistem dengan melalui terminal dengan mengetik lsb_release -a.
Keyword : openSUSE 42.1, openSUSE 42.2, Leap, Update, Upgrade, Instalasi

