Digest of YaST Development Sprint 123
Both openSUSE Leap 15.3 and SUSE Enterprise Linux 15 SP3 are already in the oven and almost ready to be tasted. But although they smell delicious, the openSUSE volunteers and the great SUSE QA team never give up in challenging our beloved distributions to find the corner cases that need more polishing. Since we want to make sure each possible problem have a solution or a documented workaround at the release date, the YaST Team invested quite some time during the last sprint investigating and solving some problems related to AutoYaST, system migration, registration and other tricky areas.
But we also found time to work on more blog-friendly topics like:
- Improvements in the AutoYaST functionality to configure questions during the installation
- Better handling of path names in Arabic and other right-to-left languages
- Progress in the refactoring of YaST Users
- Possibility of installing with neither NetworkManager or
wicked
Let’s dive into the details.
One of the many features offered by AutoYaST is the possibility of specifying a so-called ask-list,
which lets the user decide the values of some parts of the AutoYaST profile during the installation.
That allows to fine-tune the level of flexibility and interactivity, with a process that is highly
automated but still customizable on the fly. During this sprint we basically rewrote the whole
feature to make it more robust and powerful, while still being fully backwards-compatible. See more
details in the corresponding pull request
including technical details, before-and-after screenshots and a link to the official documentation
that explains how to use this reworked feature.
And talking about before-and-after screenshots, let’s see if you can spot the differences in the following image.
Exactly. In the upper part, the right-to-left orientation of the Arabic writing mangles the mount
points and the device names, moving the initial slash of paths like /dev/vda to the end. This is
just one of the many interesting software development problems you don’t normally think about, but
that makes life as a YaST developer a constant learning experience. If you want to know more about
Unicode directional formatting characters and how we solved the problem, check this pull
request at the yast2-storage-ng repository.
And talking about challenges and learning, sure you remember we are in the middle of a whole rewrite of the YaST mechanisms to manage local users. We already have a new version of the installer that works perfectly using the new code, including the creation of brand new users and also importing them from a previous installation. We are now integrating that new code into AutoYaST and we will be ready soon to discuss the best procedure and timing to introduce the revamped yast2-users into openSUSE Tumbleweed in a way that it brings all the benefits of the rewrite to our users without any disruptive change in the surface.
Last but not least, we would like to mention a new feature we already submitted to the Tumbleweed
installer in search for feedback from you, our beloved users. :wink: In a nutshell, it offers the
possibility to install the distribution without NetworkManager or wicked, for those users that
want to manually configure an alternative network manager (like systemd-networkd) or that simply
want a network-less operating system. Please check the corresponding pull
request and reach out to us to tell us what do you
think. Remember you can do that at the yast-devel and factory mailing lists at
openSUSE, at the #yast channel at Freenode IRC or directly
commenting on GitHub.
While waiting for your input, we will keep working in polishing the upcoming releases and bringing new features into Tumbleweed. Stay safe and have a lot of fun!
Error handling in Go HTTP applications
Nate Finch had a nice blog post on error flags recently, and it caused me to think about error handling in my own greenfield Go project at work.
Much of the Go software I write follows a common pattern: an HTTP JSON API fronting some business logic, backed by a data store of some sort. When an error occurs, I typically want to present a context-aware HTTP status code and an a JSON payload containing an error message. I want to avoid 400 Bad Request and 500 Internal Server Errors whenever possible, and I also don’t want to expose internal implementation details or inadvertently leak information to API consumers.
I’d like to share the pattern I’ve settled on for this type of application.
An API-safe error interface
First, I define a new interface that will be used throughout the application for exposing “safe” errors through the API:
package app
type APIError interface {
// APIError returns an HTTP status code and an API-safe error message.
APIError() (int, string)
}
Common sentinel errors
In practice, most of the time there are a limited set of errors that I
want to return through the API. Things like a 401 Unauthorized for a
missing or invalid API token, or a 404 Not Found when referring to a
resource that doesn’t exist in the data store. For these I create a
create a private struct that implements APIError:
type sentinelAPIError struct {
status int
msg string
}
func (e sentinelAPIError) Error() string {
return e.msg
}
func (e sentinelAPIError) APIError() (int, string) {
return e.status, e.msg
}
And then I publicly define common sentinel errors:
var (
ErrAuth = &sentinelAPIError{status: http.StatusUnauthorized, msg: "invalid token"}
ErrNotFound = &sentinelAPIError{status: http.StatusNotFound, msg: "not found"}
ErrDuplicate = &sentinelAPIError{status: http.StatusBadRequest, msg: "duplicate"}
)
Wrapping sentinels
The sentinel errors provide a good foundation for reporting basic
information through the API, but how can I associate real errors with
them? ErrNoRows from the database/sql package is never going to
implement my APIError interface, but I can leverage the
error wrapping functionality introduced in Go 1.13.
One of the lesser-known features of error wrapping is the ability to
write a custom Is method on your own types. This is perhaps because
the implementation is privately hidden
within the errors package, and the package documentation
doesn’t give much information about why you’d want to use it. But it’s
a perfect fit for these sentinel errors.
First, I define a sentinel-wrapped error type:
type sentinelWrappedError struct {
error
sentinel *sentinelAPIError
}
func (e sentinelWrappedError) Is(err error) bool {
return e.sentinel == err
}
func (e sentinelWrappedError) APIError() (int, string) {
return e.sentinel.APIError()
}
This associates an error from elsewhere in the application with one of
my predefined sentinel errors. A key thing to note here is that
sentinelWrappedError embeds the original error, meaning its Error
method returns the original error’s message, while implementing
APIError with the sentinel’s API-safe message. The Is method allows
for comparisons of these wrapping errors with the sentinel errors using
errors.Is.
Then I need a public function to do the wrapping:
func WrapError(err error, sentinel *sentinelAPIError) error {
return sentinelWrappedError{error: err, sentinel: sentinel}
}
(If you wanted to include additional context in the APIError, such as a resource name, this would be a good place to add it.)
When other parts of the application encounter an error, they wrap the
error with one of the sentinel errors. For example, the database layer
might have its own wrapError function that looks something like this:
package db
import "example.com/app"
func wrapError(err error) error {
switch {
case errors.Is(err, sql.ErrNoRows):
return app.WrapError(err, app.ErrNotFound)
case isMySQLError(err, codeDuplicate):
return app.WrapError(err, app.ErrDuplicate)
default:
return err
}
}
Because the wrapper implements Is against the sentinel, you can
compare errors to sentinels regardless of what the original error is:
err := db.DoAThing()
switch {
case errors.Is(err, ErrNotFound):
// do something specific for Not Found errors
case errors.Is(err, ErrDuplicate):
// do something specific for Duplicate errors
}
Handling errors in the API
The final task is to handle these errors and send them safely back
through the API. In my api package, I define a helper function that
takes an error and serializes it to JSON:
package api
import "example.com/app"
func JSONHandleError(w http.ResponseWriter, err error) {
var apiErr app.APIError
if errors.As(err, &apiErr) {
status, msg := apiErr.APIError()
JSONError(w, status, msg)
} else {
JSONError(w, http.StatusInternalServerError, "internal error")
}
}
(The elided JSONError function is the one responsible for setting the
HTTP status code and serializing the JSON.)
Note that this function can take any error. If it’s not an
APIError, it falls back to returning a 500 Internal Server Error.
This makes it safe to pass unwrapped and unexpected errors without
additional care.
Because sentinelWrappedError embeds the original error, you can also
log any error you encounter and get the original error message. This
can aid debugging.
An example
Here’s an example HTTP handler function that generates an error, logs it, and returns it to a caller.
package api
func exampleHandler(w http.ResponseWriter, r *http.Request) {
// A contrived example that always throws an error. Imagine this
// is actually a function that calls into a data store.
err := app.WrapError(fmt.Errorf("user ID %q not found", "archer"), app.ErrNotFound)
if err != nil {
log.Printf("exampleHandler: error fetching user: %v", err)
JSONHandleError(w, err)
return
}
// Happy path elided...
}
Hitting this endpoint will give you this HTTP response:
HTTP/1.1 404 Not Found
Content-Type: application/json
{"error": "not found"}
And send to your logs:
exampleHandler: error fetching user: user ID "archer" not found
If I had forgotten to call app.WrapError, the response instead would
have been:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{"error": "internal error"}
But the message to the logs would have been the same.
Impact
Adopting this pattern for error handling has reduced the number of error types and scaffolding in my code – the same problems that Nate experienced before adopting his error flags scheme. It’s centralized the errors I expose to the user, reduced the work to expose appropriate and consistent error codes and messages to API consumers, and has an always-on safe fallback for unexpected errors or programming mistakes. I hope you can take inspiration to improve the error handling in your own code.
openSUSE Tumbleweed – Review of the week 2021/19
Dear Tumbleweed users and hackers,
First, I want to apologize to our Steam users for making their life harder this week than needed. I misjudged an openQA-reported issue as being a Steam packaging bug instead of realizing that it was in fact a Mesa packaging bug. This in turn made some of you receive scary messages from zypper. A bug for this had been filed in Bugzilla of course: https://bugzilla.opensuse.org/show_bug.cgi?id=1185933. A fixed Mesa package will be part of Snapshot 0514.
Other than that, I did not hear/read a lot of complaints regarding the six snapshots released during this week (0506, 0507, 0508, 0510, 0511, and 0512). The main changes included:
- GNOME 40.1
- KDE Plasma 5.21.5
- Mesa 21.1.0
- LibreOffice 7.1.3.2
- QEmu 6.0.0
- Virtualbox 6.1.22
- VLC 3.0.13
- icu 69.1
- Mozilla Firefox 88.0.1
- KDE Frameworks 5.82.0
- Linux kernel 5.12.2, kfence has been disabled. This allows the system to reach idle state easier again
- Python 3.8.10 (security and bug fixes)
The staging areas are currently filled with these major topics:
- NodeJS 15 will be removed
- Linux kernel 5.12.3
- KDE Gear 21.04.1
- Base filesystem layout changes: more base directories will change permission from 755 to 555
- Switch from go 1.15 to go 1.16: most packages fixed, the last failure in Staging:M is cilium
- GCC 11 as default compiler: Move from special-purpose Staging:Gcc7 to Staging:O (incl. openQA test coverage). There are a few more build failures to be addressed.
- UsrMerge: The current state is that we checked in all changes and are planning on actually doing the switch somewhen in the not too far future, likely together with the planned distro-rebuild for GCC 11
Mesa, KDE Frameworks, GlusterFS Update in Tumbleweed
There were three openSUSE Tumbleweed snapshots released so far this week.
The snapshots updated Mozilla Thunderbird, Mozilla Firefox, Mesa, KDE Frameworks, glusterfs, php and several other packages.
The most recently released snapshot, 20210511, updated a little more than a handful of packages. There was one package update from KDE Frameworks 5.82.0 with plotting framework kplotting. The 5.12.2 Linux Kernel updated in the snapshot and brought a thermal sensor correction to the x86 thinkpad_acpi module and some fixes for Advanced Linux Sound Architecture USB audio. Another package update in the snapshot was hivex 1.3.20, which is a system for extracting the contents of the Windows Registry; the hivex version fixed a Common Vulnerabilities and Exposures that would allow an attacker to read memory beyond normal bounds or cause the program to crash.
Mesa 21.1.0 and a majority of the KDE Frameworks 5.82.0 packages updated in snapshot 20210510. The Mesa update added some patches and dropped vulkan_intel.h in /usr/include/vulkan/ but a decision was made to keep the directory empty. The update of KDE Frameworks 5.82.0 added new sidebar show and hide Breeze Icons. The KDBusAddons file was relicensed to LGPL-2.0 or later. Many fixes were made in the frameworks update, including a KTextEditor memory corruption fix and a couple fixes for dragging. The update of Mozilla Thunderbird 78.10.1 restored some previous behavior found in the 78.9.0 version. The fetchmail 6.4.19 update now properly reports option parsing errors. Tumbleweed skipped an entire major version of the of cluster file-system capable of scaling to several peta-bytes in its update of glusterfs from version 7.1 to 9.1; the new major version upgrade added support for 5K volumes, improved the rebalance of sparse files and it is now compiled with Link Time Optimization enabled by default. The full-featured implementation of the DNS protocol bind9 9.16.15, fixed a few CVEs including one that could lead to a RUNTIME_CHECK assertion failure. Also updated in the snapshots were ceph 16.2.3.26, chat client pidgin 2.14.4 and terminal multiplexer tmux 3.2.
The 20210508 snapshot updated Mozilla Firefox 88.0.1, which fixed a corruption of videos playing on Twitter or WebRTC calls on some Gen6 Intel graphics chipsets. A CVE involving web render components was also fixed with the open-source browser. An update in php7 7.4.19 reverted a fix that treated everything as PARAM_STR. Google’s library for parsing, formatting and validating international phone numbers libphonenumber updated to version 8.12.22, which updated carrier data and the geocoding data for Germany’s +49 and Mexico’s +52 calling codes. Other packages updated in the snapshot were hwdata 0.347, perl-CGI 4.52 and ibus-table 1.13.0.
Shells, openSUSE Unite with Partnership
A startup bringing personal workspaces in the cloud for students, workers, coders, and creators along with a Linux project for developers, system administrators and users are teaming up to extend the use of a secure desktop from any device, anywhere.
Shells and openSUSE Project have entered into a partnership to expand the use of Shells with the availability of openSUSE distributions on Shells’ private virtual desktop environment powered by cloud computing.
“This is a great way to give an openSUSE distribution a spin - without downloading or installing anything locally,” said Gerald Pfeifer, chairperson of the openSUSE Project. “And it’s a completely new way to use a feature rich, full fledged open source-based environment from your tablet or other device.”
Shells’ CEO Alex Lee couldn’t agree more.
“We’re thrilled with the images that have been created that are now available for our customers to choose from when setting up their Shells virtual desktop,” Lee said. “It’s been a pleasure collaborating with the openSUSE team for the past few months. Both of the openSUSE and Shells tech teams have put in a lot of hard work to drive this project to completion, and it is clearly evident in the end products.
“We are honored by the fact that the group at openSUSE selected this project to work on during their SUSE HackWeek,” Lee added.
Shells has multiple use cases and openSUSE distributions are just one of many other operating systems offered by Shells. With the partnership, openSUSE will be a member of Shells Affiliate Program. The two organizations are working closely on a way to allow users to trial the distribution and its desktop environments. Further extending this partnership, Shells has become an Emerald Sponsor of this year’s openSUSE Conference and Lee will give a keynote on June 18.
Developers can rapidly spin up multiple secure environments that are automatically backed up. Music producers can access production grade programs across devices to collaborate on the next hit.
The use of Shells by educators allows for remote learning on any device, which becomes affordable, less complex for students and the accessibility and learning with the many operating systems and tools add synergy to the classroom. Students across the world can easily access openSUSE distributions on whatever device that is available to them, whether that be at school, the library or at home.
“The openSUSE leadership team has always expressed the fact that it is important to have the right tool for the right job,” Pfeifer said. “openSUSE has a lot of powerful tools. Securely accessing openSUSE and its toolset from anywhere extends the power of the distribution to the device in someone’s pocket, to a smart TV, or VR browser of a user in an instant.”
A key member of the Shells tech team involved with the collaboration is Debian developer and former Purism Chief Technical Officer Zlatan Todoric.
“The Shells and openSUSE collaboration is one of those that we all enjoy in the FLOSS community,” Todoric said, who is currently serving at Shells’ Vice President of Technology. “Sharing knowledge, ideas, and helping each other to benefit the entire community is obviously what it is all about. openSUSE is a well known integrator and has vast experience in desktop and cloud environments, and having them as an option for our Shells cloud computers is a win-win solution for everyone. The collaboration will continue to expand even further as time goes on and I can already tell you that the openSUSE experience on Shells is going to be loved.”
Disclaimer: The initial go-live images are Tumbleweed images that make it easier to adjust as the distro changes. The release team is working toward having an openSUSE Leap image.
Get your openSUSE virtual desktop here.
Media Contacts:
Alex Lee Shells.com alex@shells.com
Douglas DeMaio openSUSE ddemaio@opensuse.org
openSUSE Leap 15.3 Expands with armv7
Developers of the openSUSE community are looking to utilize armv7l efforts in the context of openSUSE Step to evolve how openSUSE Leap and SUSE Linux Enterprise are developed together.
The Step effort was announced in February to open up and expand architecture enablement for future SUSE Linux Enterprise (SLE) releases.
Step is a community effort to rebuild SLE from the released sources packages in the openSUSE instance of the Open Build Service (OBS) with the intention to stay as compatible as possible with SLE. Just recently the project established armv7l in OBS as a Leap port.
“As the survey’s results showed, Leap still has lots of armv7 users,” said Guillaume Gardet, an arm developer and community contributor. “We listened to that feedback to address the potential use cases of people with armv7 and found a solution.”
Leap ports provide Leap for architectures not supported by SLE, such as 32-bit architectures. Step armv7l together with Backports forms the Leap port for armv7l.
Images can be found at http://download.opensuse.org/ports/armv7hl/distribution/leap/15.3/.
openSUSE Tumbleweed – Review of the week 2021/18
Dear Tumbleweed users and hackers,
Week 18 was a regular one with almost daily snapshots being published. A total of six snapshots went out to the users (0429, 0430, 0502, 0503, 0504, and 0506).
The main changes in those snapshots included:
- GTK+ 3.24.29
- TeXLive 2021
- PHP 7.4.18
- Python 3.8.9
- We switched from openMPI2 to openMPI4
Changes currently being prepared in the staging areas:
- GNOME 40.1
- KDE Plasma 5.21.5
- icu 69.1: for the ring packages, nodejs15 seems to be the last blocker
- Switch from go 1.15 to go 1.16: most packages fixed, the last failure in Staging:M is cilium
- GCC 11 as default compiler: Move from special-purpose Staging:Gcc7 to Staging:O (incl. openQA test coverage). There are a few more build failures to be addressed.
- UsrMerge: The current state is that we checked in all changes and are planning on actually doing the switch somewhen in the not too far future, likely together with the planned distro-rebuild for GCC 11
Trying out Phosh shell on PinePhone and openSUSE Tumbleweed
During my time with Phosh on PinePhone and openSUSE Tumbleweed, I have stumbled on a couple of issues that made clear that the experience still needed some polish. This is not a critic against the Phosh or the GNOME project. I don’t envy the developers that need to ensure that their app works across many form factors.
However, I can see that the additional time that the KDE project has spend on polishing their experience has paid off. In this article, I will describe the issues that I encountered and how you can fix them. I like everyone to try out this GNOME based mobile experience. It’s awesome to see FOSS beyond the PC / Laptop.
Where is my keyboard?
Unlocking your phone and then your SIM card are the number 1 and 2 things to do when you boot up a smartphone. However, its hard to unlock your SIM card without a virtual keyboard. And that was exactly what I encountered.

How do you progress? Click on Cancel and go to the Settings.

There is a category for Accessibility and under Typing you find a toggle for the (on) Screen Keyboard. Hit the switch!

You will find a keyboard icon at the bottom of the phone. Touching this keyboard button automatically opens and closes the virtual keyboard.

Now it is time to unlock that Simcard. Go to the Mobile category and click on Unlock.

Enter your Pincode and now you can make phone calls. The sound quality is excellent.

The GNOME experience, but mobile
Phosh is GNOME. And that becomes very apparent when you go from the full-screen experience to the windowed experience. (Yes, you can do that.) Just drag the title-bar down and your windows are in plain sight.

In many ways you can see that most apps are plain desktop apps (up-scaled by 200%) on a mobile device screen. Take GNOME Software for instance, which is clearly not designed as a Mobile First app. However, it does everything that it needs to do.


The most funny example is when you open LibreOffice. (Yes, you can do that.) It is amazing that you can do this at all. I do recommend that you switch to a Dock and a FullHD monitor to work on your LibreOffice files. You won’t get very far on the PinePhone screen.

Phosh looks good!
The parts that are developed for Phosh are designed to be Mobile First. You can see that the experience is optimized for those parts. Scrolling is relatively smooth (the PinePhone is not the fastest device and hardware acceleration is not working). The general design direction is clean and functional. The Lock screen is a good example of that design esthetic.

When you unlock Phosh, you are greeted by the App grid.

The Phone app is clearly designed to be a Mobile First experience.

When you swipe up, you go back to the Overview, where your open windows (Yes, it does multitasking) are shown above the App grid.

GNOME already featured a very clean and functional look for its apps. That translates quite well to a mobile form factor. GNOME Maps for instance looks quite good. The buttons could be a bit bigger, but it works fine on the PinePhone.

GNOME Weather works as you expect.

And GNOME Web (or Epiphany) works very well as a mobile browser.

The Smartphone app is called Megapixels. That app is still a work in progress. In contrast to opening this app on KDE Plasma Mobile, I can now see colors. The user interface of Megapixels is easy to understand. But there are very few features to work with.

GNOME Clocks could also do better. Everything is very small and there is a lot of unused screen estate. Which is weird, because on my desktop PC the interface looks more mobile friendly. However, there is a minimum width for the window on my desktop PC. Maybe this is what happens, when you make the window even smaller.

Conclusion
I liked exploring Phosh on openSUSE Tumbleweed. I am not in love with the experience, but I do like the way it operates. It’s a very functional experience. For some people, that is all it needs to be. With some love and development from the GNOME community, I am certain that it will reach the same level as polish that the KDE community has.
What I really like about the PinePhone is that I can install any OS to the phone that I like to explore. It is a bit similar to using Virtualbox to explore the various Linux distributions and the various Desktop Environments. You can just wipe your phone and flash another Operating System on it and try it out. Every experience is unique. Although not every experience is right for me, it is fun poking around. And that is what FOSS is all about (for me).
Published on: 4 May 2021
How to edit stuff that you've already commited to git? (And squash as a bonus)
So, you’re in the middle of a review, and have couple of commits but one of the comments is asking you to modify a line that belongs to second to last, or even the first commit in your list, and you’re not willing to do:
git commit -m "Add fixes from the review" $file
Or you simply don’t know, and have no idea what squash or rebase means?, well I won’t explain squash today, but I
will explain rebase

See how I do it, and also how do I screw up!
It all boils down to making sure that you trust git, and hope that things are small enough so that if you lose the stash, you can always rewrite it.
So in the end, for me it was:
git fetch origin
git rebase -i origin/master # if your branch is not clean, git will complain and stop
git stash # because my branch was not clean, and my desired change was already done
git rebase -i origin/master # now, let's do a rebase
# edit desired commits, for this add the edit (or an e) before the commit
# save and quit vim ([esc]+[:][x] or [esc]+[:][w][q], or your editor, if you're using something else
git stash pop # because I already had my change
$HACK # if you get conflicts or if you want to modify more
# be careful here, if you rewrite history too much
# you will end up in Back to the Future II
# Luckly you can do git rebase --abort
git commit --amend $files #(alternatively, git add $files first then git commit --amend
git rebase --continue
git push -f # I think you will need to add remote+branch, git will remind you
# go on with your life
Note: A squash is gonna put all of the commits together, just make sure that there’s an order:
I lied, here’s a very quick and dirty squash guide
- pick COMMIT1
- pick COMMIT2
- squash COMMIT3 # (Git will combine this commit, with the one above iir, so COMMIT2+COMMIT3 and git will ask you for a new commit message)


