Posted on Leave a comment

FedoraShareYourScreen week (F35)

The Fedora Project, through the Marketing team, is happy to announce the first FedoraShareYourScreen week!

We know that even though the stock look of Fedora Linux is awesome, most people love to tweak and adapt their systems to their own workflow. We want to see how your Fedora Linux desktop looks.

FedoraShareYourScreen week

  • Share your screen with us! Take a screenshot of your desktop and share it. Use the hashtag #FedoraShareYourScreen and mention @fedora on Twitter or @thefedoraproject on Instagram. For Mastodon, just use the hashtag. Avoid showing personal and private info.
  • If you use a full Desktop Environment, just a Window Manager, or just the command line, we want to see how it looks! Share your favorite apps, configs, plugins, widgets and everything on your desktop (including your favorite wallpapers if they are SFW 😉).
  • At the end of the week we will be publishing a slide show on YouTube with all the screens collected during the week! Keep it Family Friendly, inappropriate content won’t be included in the video.

Feel proud of your customization and show it to us! From January 31st to February 6th we will be looking, commenting and sharing feedback on the screenshots shared with the hashtag #FedoraShareYourScreen on Twitter, Instagram and Mastodon!

When is this week?

It will start this on January 31st and it will end on February 6th. We will collect all the screenshots on February 7th and the slide show will be published on February 10th.

Will this happen again?

Of course! We want to see everyone’s ideas with all the new stuff that Fedora Linux adds each release. We will be doing this in the middle of each Fedora Linux release. This will give everyone time to customize the desktop and show it in all it’s shininess!

Posted on Leave a comment

Sharing the computer screen in Gnome

You do not want someone else to be able to monitor or even control your computer and you usually work hard to cut off any such attempts using various security mechanisms. However, sometimes a situation occurs when you desperately need a friend, or an expert, to help you with a computer problem, but they are not at the same location at the same time. How do you show them? Should you take your mobile phone, take pictures of your screen, and send it to them? Should you record a video? Certainly not. You can share your screen with them and possibly let them control your computer remotely for a while. In this article, I will describe how to allow sharing the computer screen in Gnome.

Setting up the server to share its screen

A server is a computer that provides (serves) some content that other computers (clients) will consume. In this article the server runs Fedora Workstation with the standard Gnome desktop.

Switching on Gnome Screen Sharing

By default, the ability to share the computer screen in Gnome is off. In order to use it, you need to switch it on:

  1. Start Gnome Control Center.
  2. Click on the Sharing tab.

    Sharing switched off

  3. Switch on sharing with the slider in the upper right corner.
  4. Click on Screen sharing.

    Sharing switched on

  5. Switch on screen sharing using the slider in the upper left corner of the window.
  6. Check the Allow connections to control the screen if you want to be able to control the screen from the client. Leaving this button unchecked will only allow view-only access to the shared screen.
  7. If you want to manually confirm all incoming connections, select New connections must ask for access.
  8. If you want to allow connections to people who know a password (you will not be notified), select Require a password and fill in the password. The password can only be 8 characters long.
  9. Check Show password to see what the current password is. For a little more protection, do not use your login password here, but choose a different one.
  10. If you have more networks available, you can choose on which one the screen will be accessible.

Setting up the client to display a remote screen

A client is a computer that connects to a service (or content) provided by a server. This demo will also run Fedora Workstation on the client, but the operating system actually should not matter too much, if it runs a decent VNC client.

Check for visibility

Sharing the computer screen in Gnome between the server and the client requires a working network connection and a visible “route” between them. If you cannot make such a connection, you will not be able to view or control the shared screen of the server anyway and the whole process described here will not work.

To make sure a connection exists

Find out the IP address of the server.

Start Gnome Control Center, a.k.a Settings. Use the Menu in the upper right corner, or the Activities mode. When in Activities, type

settings

and click on the corresponding icon.

Select the Network tab.

Click on the Settings button (cogwheel) to display your network profile’s parameters.

Open the Details tab to see the IP address of your computer.

Go to your client’s terminal (the computer from which you want to connect) and find out if there is a connection between the client and the server using the ping command.

$ ping -c 5 192.168.122.225

Examine the command’s output. If it is similar to the example below, the connection between the computers exists.

PING 192.168.122.225 (192.168.122.225) 56(84) bytes of data. 64 bytes from 192.168.122.225: icmp_seq=1 ttl=64 time=0.383 ms 64 bytes from 192.168.122.225: icmp_seq=2 ttl=64 time=0.357 ms 64 bytes from 192.168.122.225: icmp_seq=3 ttl=64 time=0.322 ms 64 bytes from 192.168.122.225: icmp_seq=4 ttl=64 time=0.371 ms 64 bytes from 192.168.122.225: icmp_seq=5 ttl=64 time=0.319 ms --- 192.168.122.225 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4083ms rtt min/avg/max/mdev = 0.319/0.350/0.383/0.025 ms

You will probably experience no problems if both computers live on the same subnet, such as in your home or at the office, but problems might occur, when your server does not have a public IP address and cannot be seen from the external Internet. Unless you are the only administrator of your Internet access point, you will probably need to consult about your situation with your administrator or with your ISP. Note, that exposing your computer to the external Internet is always a risky strategy and you must pay enough attention to protecting your computer from unwanted access.

Install the VNC client (Remmina)

Remmina is a graphical remote desktop client that can you can use to connect to a remote server using several protocols, such as VNC, Spice, or RDP. Remmina is available from the Fedora repositories, so you can installed it with both the dnf command or the Software, whichever you prefer. With dnf, the following command will install the package and several dependencies.

$ sudo dnf install remmina

Connect to the server

If there is a connection between the server and the client, make sure the following is true:

  1. The computer is running.
  2. The Gnome session is running.
  3. The user with screen sharing enabled is logged in.
  4. The session is not locked, i.e. the user can work with the session.

Then you can attempt to connect to the session from the client:

  1. Start Remmina.
  2. Select the VNC protocol in the dropdown menu on the left side of the address bar.
  3. Type the IP address of the server into the address bar and hit Enter.

    Remmina Window

  4. When the connection starts, another connection window opens. Depending on the server settings, you may need to wait until the server user allows the connection, or you may have to provide the password.
  5. Type in the password and press OK.

    Remmina Connected to Server

  6. Press Align with resolution button to resize the connection window to match the server resolution, or press Full Screen Button to resize the connection window over your entire desktop. When in fullscreen mode, notice the narrow white bar at the upper edge of the screen. That is the Remmina menu and you can access it by moving the mouse to it when you need to leave the fullscreen mode or change some of the settings.

When you return back to the server, you will notice that there is now a yellow icon in the upper bar which indicates that you are sharing the computer screen in Gnome. If you no longer wish to share the screen, you can enter the menu and click on Screen is being shared and then on select Turn off to stop sharing the screen immediately.

Turn off menu item

Terminating the screen sharing when session locks.

By default, the connection will always terminate when the session locks. A new connection cannot be established until the session is unlocked.

On one hand, this sounds logical. If you want to share your screen with someone, you might not want them to use your computer when you are not around. On the other hand, the same approach is not very useful, if you want to control your own computer from a remote location, be it your bed in another room or your mother-in-law’s place. There are two options available to deal with this problem. You can either disable locking the screen entirely or you can use a Gnome extension that supports unlocking the session via the VNC connection.

Disable screen lock

In order to disable the screen lock:

  1. Open the Gnome Control Center.
  2. Click on the Privacy tab.
  3. Select the Screen Lock settings.
  4. Switch off Automatic Screen Lock.

Now, the session will never lock (unless you lock it manually), so it will be possible to start a VNC connection to it.

Use a Gnome extension to allow unlocking the session remotely.

If you do not want to switch off locking the screen or you want to have an option to unlock the session remotely even when it is locked, you will need to install an extension that provides this functionality as such behavior is not allowed by default.

To install the extension:

  1. Open the Firefox browser and point it to the Gnome extension page.

    Gnome Extensions Page

  2. In the upper part of the page, find an info block that tells you to install GNOME Shell integration for Firefox.
  3. Install the Firefox extension by clicking on Click here to install browser extension.
  4. After the installation, notice the Gnome logo in the menu part of Firefox.
  5. Click on the Gnome logo to navigate back to the extension page.
  6. Search for allow locked remote desktop.
  7. Click on the displayed item to go to the extension’s page.
  8. Switch the extension ON by using the on/off button on the right.

    Extension selected

Now, it will be possible to start a VNC connection any time. Note, that you will need to know the session password to unlock the session. If your VNC password differs from the session password, your session is still protected a little.

Conclusion

This article, described the way to enable sharing the computer screen in Gnome. It mentioned the difference between the limited (view-only) access or not limited (full) access. This solution, however, should in no case be considered a correct approach to enable a remote access for serious tasks, such as administering a production server. Why?

  1. The server will always keep its control mode. Anyone working with the server session will be able to control the mouse and keyboard.
  2. If the session is locked, unlocking it from the client will also unlock it on the server. It will also wake up the display from the stand-by mode. Anybody who can see your server screen will be able to watch what you are doing at the moment.
  3. The VNC protocol per se is not encrypted or protected so anything you send over this can be compromised.

There are several ways, you can set up a protected VNC connection. You could tunnel it via the SSH protocol for better security, for example. However, these are beyond the scope of this article.

Disclaimer: The above workflow worked without problems on Fedora 35 using several virtual machines. If it does not work for you, then you might have hit a bug. Please, report it.

Posted on Leave a comment

Quarkus and Mutiny

Quarkus is a foundation for building Java based applications; whether for the desktop, server or cloud. An excellent write up on usage can be found at https://fedoramagazine.org/using-the-quarkus-framework-on-fedora-silverblue-just-a-quick-look/. This article is primer for coding asynchronous processes using Quarkus and Mutiny.

So what is Mutiny? Mutiny allows streaming of objects in an event driven flow. The stream might originate from a local process or something remote like a database. Mutiny streaming is accomplished by either a Uni or a Multi object. We are using the Uni to stream one object — a List containing many integers. A subscribe pattern initiates the stream.

A traditional program is executed and results are returned before continuing. Mutiny can easily support non-blocking code to run processes concurrently. RxJava, ReactiveX and even native Java are alternatives. Mutiny is easy to use (the exposed API is minimal) and it is the default in many of the Quarkus extensions. The two extensions used are quarkus-mutiny and quarkus-vertx. Vert.x is the underlying framework wrapped by Quarkus. The Promise classes are supplied by quarkus-vertx. A promise returns a Uni stream when the process is complete. To get started, install a Java JDK and Maven.

Bootstrap

The minimum requirement is either Java-11 or Java-17 with Maven.

With Java-11:

$ sudo dnf install -y java-11-openjdk-devel maven

With Java-17:

$ sudo dnf install -y java-17-openjdk-devel maven

Bootstrap Quarkus and Mutiny with the Maven call below. The extension quarkus-vertx is not included to demonstrate how to add additional extensions. Locate an appropriate directory before executing. The directory mutiny-demo will be created with the initial application.

$ mvn io.quarkus.platform:quarkus-maven-plugin:2.6.2.Final:create \ -DprojectGroupId=fedoramag \ -DprojectArtifactId=mutiny-demo \ -DprojectVersion=1.0.0 \ -DclassName="org.demo.mag.Startup" \ -Dextensions="mutiny" \ -DbuildTool=gradle

Now that Gradle is bootstrapped, other extensions can be added. In the mutiny-demo directory execute:

$ ./gradlew addExtension --extensions='quarkus-vertx'

To view all available extensions execute:

$ ./gradlew listExtensions

To get all of the defined Gradle tasks execute:

$ ./gradlew tasks

Mutiny Code

The className entry on the Quarkus bootstrap is org.demo.mag.Startup which creates the file src/main/java/org/demo/map/Startup.java. Replace the contents with the following code:

package org.demo.mag; import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.function.IntSupplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream; import io.quarkus.runtime.Quarkus;
import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.annotations.QuarkusMain;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.tuples.Tuple2;
import io.vertx.mutiny.core.Promise; @QuarkusMain
public class Startup implements QuarkusApplication { public static void main(String... args) { Quarkus.run(Startup.class, args); } @Override public int run(String... args) throws InterruptedException, ExecutionException { final Promise<String> finalMessage = Promise.promise(); final String elapsedTime = "Elapsed time for asynchronous method: %d milliseconds"; final int[] syncResults = {0}; Application.runTraditionalMethod(); final Long millis = System.currentTimeMillis(); Promise<List<Integer>> promiseRange = Application.getRange(115000); Promise<Tuple2<Promise<List<Integer>>, Promise<List<Integer>>>> promiseCombined = Application.getCombined(10000, 15000); Promise<List<Integer>> promiseReverse = Application.getReverse(24000); /* * Retrieve the Uni stream and on the complete event obtain the List<Integer> */ promiseRange.future().onItem().invoke(list -> { System.out.println("Primes Range: " + list.size()); if(syncResults[0] == 1) { finalMessage.complete(String.format(elapsedTime, System.currentTimeMillis() - millis)); } { syncResults[0] = 2; } return; }).subscribeAsCompletionStage(); promiseReverse.future().onItem().invoke(list -> { System.out.println("Primes Reverse: " + list.size()); return; }).subscribeAsCompletionStage(); /* * Notice that this finishes before the other two prime generators(smaller lists). */ promiseCombined.future().onItem().invoke(p -> { /* * Notice that "Combined Range" displays first */ p.getItem2().future().invoke(reverse -> { System.out.println("Combined Reverse: " + reverse.size()); return; }).subscribeAsCompletionStage(); p.getItem1().future().invoke(range -> { System.out.println("Combined Range: " + range.size()); /* * Nesting promises to get multple results together */ p.getItem2().future().invoke(reverse -> { System.out.println(String.format("Asserting that expected primes are equal: %d -- %d", range.get(0), reverse.get(reverse.size() - 1))); assert range.get(0) == reverse.get(reverse.size() - 1) : "Generated primes incorrect"; if(syncResults[0] == 2) { finalMessage.complete(String.format(elapsedTime, System.currentTimeMillis() - millis)); } else { syncResults[0] = 1; } return; }).subscribeAsCompletionStage(); return; }).subscribeAsCompletionStage(); return; }).subscribeAsCompletionStage(); // Note: on very fast machines this may not display first. System.out.println("This should display first - indicating asynchronous code."); // blocking for final message String elapsedMessage = finalMessage.futureAndAwait(); System.out.println(elapsedMessage); return 0; } public static class Application { public static Promise<List<Integer>> getRange(int n) { final Promise<List<Integer>> promise = Promise.promise(); // non-blocking - this is only for demonstration(emulating some remote call) new Thread(() -> { try { /* * RangeGeneratedPrimes.primes is blocking, only returns when done */ promise.complete(RangeGeneratedPrimes.primes(n)); } catch (Exception exception) { Thread.currentThread().interrupt(); } }).start(); return promise; } public static Promise<List<Integer>> getReverse(int n) { final Promise<List<Integer>> promise = Promise.promise(); new Thread(() -> { try { // Generating a new object stream promise.complete(ReverseGeneratedPrimes.primes(n)); } catch (Exception exception) { Thread.currentThread().interrupt(); } }).start(); return promise; } public static Promise<Tuple2<Promise<List<Integer>>, Promise<List<Integer>>>> getCombined(int ran, int rev) { final Promise<Tuple2<Promise<List<Integer>>, Promise<List<Integer>>>> promise = Promise.promise(); new Thread(() -> { try { Uni.combine().all() /* * Notice that these are running concurrently */ .unis(Uni.createFrom().item(Application.getRange(ran)), Uni.createFrom().item(Application.getReverse(rev))) .asTuple().onItem().call(tuple -> { promise.complete(tuple); return Uni.createFrom().nullItem(); }) .onFailure().invoke(Throwable::printStackTrace) .subscribeAsCompletionStage(); } catch (Exception exception) { Thread.currentThread().interrupt(); } }).start(); return promise; } public static void runTraditionalMethod() { Long millis = System.currentTimeMillis(); System.out.println("Traditiona1-1: " + RangeGeneratedPrimes.primes(115000).size()); System.out.println("Traditiona1-2: " + RangeGeneratedPrimes.primes(10000).size()); System.out.println("Traditiona1-3: " + ReverseGeneratedPrimes.primes(15000).size()); System.out.println("Traditiona1-4: " + ReverseGeneratedPrimes.primes(24000).size()); System.out.println(String.format("Elapsed time for traditional method: %d milliseconds\n", System.currentTimeMillis() - millis)); } } public interface Primes { static List<Integer> primes(int n) { return null; }; } public abstract static class PrimeBase { static boolean isPrime(int number) { return IntStream.rangeClosed(2, (int) (Math.sqrt(number))) .allMatch(n -> number % n != 0); } } public static class RangeGeneratedPrimes extends PrimeBase implements Primes { public static List<Integer> primes(int n) { return IntStream.rangeClosed(2, n) .filter(x -> isPrime(x)).boxed() .collect(Collectors.toList()); } } public static class ReverseGeneratedPrimes extends PrimeBase implements Primes { public static List<Integer> primes(int n) { List<Integer> list = IntStream.generate(getReverseList(n)).limit(n - 1) .filter(x -> isPrime(x)).boxed() .collect(Collectors.toList()); return list; } private static IntSupplier getReverseList(int startValue) { IntSupplier reverse = new IntSupplier() { private int start = startValue; public int getAsInt() { return this.start--; } }; return reverse; } }
}

Testing

The Quarkus install showcases the quarkus-resteasy extension by default. We are not using it, replace the contents of src/test/java/org/demo/mag/StartupTest.java with:

package org.demo.mag; import io.quarkus.test.junit.QuarkusTest;
import io.vertx.mutiny.core.Promise; import java.util.List; import org.demo.mag.Startup;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test; @QuarkusTest
public class StartupTest { Promise<List<Integer>> promise = Promise.promise(); Promise<Void> promiseAndAwait = Promise.promise(); List<Integer> testValue; @Tag("DEV") @Test public void testVerifyAsync() { Assertions.assertEquals( null , testValue); promise.future().onItem().invoke(list -> { testValue = list; promiseAndAwait.complete(); }).subscribeAsCompletionStage(); Assertions.assertEquals(null, testValue); promise.complete(Startup.ReverseGeneratedPrimes.primes(100)); promiseAndAwait.futureAndAwait(); Assertions.assertNotNull(testValue); Assertions.assertEquals(2, testValue.get(testValue.size()-1)); }
}

Optional

To reduce download volume, remove the following entries from the build.gradle file.

	implementation 'io.quarkus:quarkus-resteasy' testImplementation 'io.rest-assured:rest-assured'

Installation and Execution

The next step is to build the project. This includes downloading all dependencies as well as compiling and executing the Startup.java program. Everything is included in one file for brevity.

$ ./gradlew quarkusDev

The above command produces a banner and console output from Quarkus and the program.

This is development mode. Notice the prompt: “Press [space] to restart”. To review edits hit the space-bar and enter-key to re-compile and execute. Enter q to quit.

To build an Uber jar (all dependencies included) execute:

$ ./gradlew quarkusBuild -Dquarkus.package.type=uber-jar

This creates a jar in the build directory named mutiny-demo-1.0.0-runner.jar. To run the jar file, enter the following command.

$ java -jar ./build/mutiny-demo-1.0.0-runner.jar

To remove the banner and console logs, add the following lines to the src/main/resources/application.properties file.

%prod.quarkus.log.console.enable=false
%prod.quarkus.banner.enabled=false

The output might look similar to the following.

	Traditional-1: 9592 Traditional-2: 1229 Traditional-3: 2262 Traditional-4: 2762 Elapsed time for traditional method: 67 milliseconds Combined Range: 1229 This should display first - indicating asynchronous code. Combined Reverse: 2262 Primes Reverse: 2762 Asserting that expected primes are equal: 2 -- 2 Primes Range: 9592 Elapsed time for asynchronous method: 52 milliseconds

You will still get the banner and logs in development mode.

To go one step further, Quarkus can generate an executable out of the box using GraalVM.

$ ./gradlew build -Dquarkus.package.type=native

The executable generated by the above command will be ./build/mutiny-demo-1.0.0-runner.

The default GraalVM is a downloaded container. To override this, set the environment variable GRAALVM_HOME to your local install. Don’t forget to install the native-image with the following command.

$ ${GRAALVM_HOME}/bin/gu install native-image

The Code

The code, generates prime numbers for a range, reversed on a limit and a combination of the two. For example, consider the range: “Promise<List<Integer>> promiseRange = Application.getRange(115000);”.

This generates all primes between 1 and 115000 and displays the number of primes in the range. It is executed first but displays its results last. The code near the end of the main method — System.out.println (“This should display first – indicating asynchronous code.”); — displays first. This is an example of asynchronous code. We can run multiple processes concurrently. However, the order of completion is unpredictable. The traditional calls are orderly and the results can be collected when completed.

Execution can be blocked until a result is returned. The code does exactly that to display the asynchronous elapsed time message. At the end of the main method we have: “String elapsedMessage = finalMessage.futureAndAwait();”. The message arrives from either promiseRange or promiseCombined — the two longest running processes. But even this is not guaranteed. The state of the underling OS is unknown. One of the other processes might finish last. Normally, asynchronous calls are nested to co-ordinate results. This is demonstrated in the promiseCombined promise to evaluate the results of range and reversed primes.

Conclusion

The comparison between the traditional method and asynchronous method suggests that the asynchronous method can be up to 25% faster on a modern computer. An older CPU that does not have the resources and computing power produces results faster with the traditional method. If a computer has many cores, why not use them‽

More documentation can be found on the following web sites.

Posted on Leave a comment

JetBrains Investigated by FBI in SolarWinds Hack Probe

JetBrains, maker of popular development software including the likes of IntelliJ IDEA, WebStorm, Project Rider, the Kotlin language and even the Mono font, are being investigated by the FBI as part of the SolarWinds hack probe according to the New York Times. The product in question targeted in this investigation is their build management solution TeamCity. Please keep in mind, this is just an investigation at this point, there is no guilt established and no indication JetBrains products have been compromised.

From the New York Times article, JetBrains deny any knowledge of a compromise in their software:

JetBrains said on Wednesday that it had not been contacted by government officials and was not aware of any compromise. The exact software that investigators are examining is a JetBrains product called TeamCity, which allows developers to test and exchange software code before its release. By compromising TeamCity, or exploiting gaps in how customers use the tool, cybersecurity experts say the Russian hackers could have invisibly planted back doors in an untold number of JetBrain’s clients.

Government officials are not certain how the compromise of the JetBrains software relates to the larger SolarWinds hacking. They are seeking to learn if it was a parallel way for Russia’s main intelligence agency to enter government and private systems, or whether it was the original pathway for Russian operatives to first infiltrate SolarWinds.

Information on the JetBrains investigation are limited, there is also an extremely short article on Reuters. The extent of the SolarWinds hack continue to grow daily. After the video was published, JetBrains have issued a response to the New York Times article, included in full:

The New York Times has published a story in which they point to JetBrains being under investigation and somehow related to the SolarWinds breach that recently took place.

First and foremost, JetBrains has not taken part or been involved in this attack in any way. SolarWinds is one of our customers and uses TeamCity, which is a Continuous Integration and Deployment System, used as part of building software. SolarWinds has not contacted us with any details regarding the breach and the only information we have is what has been made publicly available. It’s important to stress that TeamCity is a complex product that requires proper configuration. If TeamCity has somehow been used in this process, it could very well be due to misconfiguration, and not a specific vulnerability. Furthermore, security is our top concern and we notify and manage updates transparently in our Security Bulletin.

Secondly, we have not been contacted by any government or security agency regarding this matter, nor are we aware of being under any investigation. If such an investigation is undertaken, the authorities can count on our full cooperation.

We remain open to answering any and all questions regarding this matter and as always are committed to delivering the best possible products and services to our customers.

Thank you
Maxim Shafirov
Chief Executive Officer

Posted on Leave a comment

AI Powered Art Tools

Today we are going to look at two vastly different AI powered art generation tools, Luminar and NVIDIA GauGAN Beta. Luminar is a powerful art processing tool, a cross between Photoshop and Lightroom, but AI assisted. We recently covered Luminar hands-on including how to use it with Affinity Photo here and it is currently (2021-01-05) in the final 24 hours of a Humble Bundle sale.

NVIDIA GauGAN on the other-hand is a web based application that is part of the NVIDIA AI Playground. GauGAN is described as:

GauGAN, named after post-Impressionist painter Paul Gauguin, creates photorealistic images from segmentation maps, which are labeled sketches that depict the layout of a scene.

Artists can use paintbrush and paint bucket tools to design their own landscapes with labels like river, rock and cloud. A style transfer algorithm allows creators to apply filters — changing a daytime scene to sunset, or a photorealistic image to a painting. Users can even upload their own filters to layer onto their masterpieces, or upload custom segmentation maps and landscape images as a foundation for their artwork

You can learn more about GauGAN here, while technical details of the algorithm in the open source implementation hosted on GitHub. You can try an already trained version of the algorithm in action here in your browser.

These are not unique examples in terms of machine learning or AI enhanced art creation tools. In early 2020 Unity acquired Artomatix, the creator of ArtEngine, an AI driven material creation tool. Another project that was recently featured on this site is Cascadeur, a physics based animation tool that uses machine learning to help with animations. DeepMotion Animate 3D is another recently featured machine learning based application, that takes simple 2D footage and makes a 3D rig and animation from the results.

The key thing in all of these tools thus far is they don’t seek to replace the artist, but augment them using deep or machine learning algorithms. You can check out NVIDIA GauGAN and Luminar in action in the video below. For a VERY limited time you can get Luminar on Humble Bundle here. [Expires 01/06! — GFS can receive a commission on Humble purchases]. So what do you say, are AI powered art tools the future?

[youtube https://www.youtube.com/watch?v=SIUdUPjeatg?feature=oembed&w=1500&h=844]
Posted on Leave a comment

Scatter for Godot

Today we are looking at Scatter for the Godot Game Engine. Scatter is a Godot add-on that makes it incredibly easy to instance mesh objects in your game level. This makes level design tasks like placing grass, paths, fences, etc incredibly simple. Additionally Scatter supports instancing multiple meshes (think different tree meshes to make a forest) in the same scatter, excluding splines or points from being scatter targets and more.

Scatter is an open source project with the source code hosted on GitHub under the MIT open source license. The project is implemented as a simple Godot add-on, so simply clone the repository into your projects Addons folder (or create one if you don’t have one already). Next load your project, go to Project Settings, then Plugins and make sure Scatter is enabled.

Once scattered is enabled, you create a Scatter object. This is a spline path that defines the boundaries of the scatter object. You need to add a ScatterItem child to your Scatter, then add a MeshInstance to the ScatterItem. This mesh instance is the 3D model that will be “scattered” around the boundary defined by the Scatter path.

The creator of the Scatter add-on also created Concept Graph for Godot, an excellent procedural generation extension we previously covered here. You can learn more about Scatter for Godot and see it in action in the video below.

[youtube https://www.youtube.com/watch?v=MB3Vz6JFAOA?feature=oembed&w=1500&h=844]
Posted on Leave a comment

Network address translation part 1 – packet tracing

The first post in a series about network address translation (NAT). Part 1 shows how to use the iptables/nftables packet tracing feature to find the source of NAT related connectivity problems.

Introduction

Network address translation is one way to expose containers or virtual machines to the wider internet. Incoming connection requests have their destination address rewritten to a different one. Packets are then routed to a container or virtual machine instead. The same technique can be used for load-balancing where incoming connections get distributed among a pool of machines.

Connection requests fail when network address translation is not working as expected. The wrong service is exposed, connections end up in the wrong container, request time out, and so on. One way to debug such problems is to check that the incoming request matches the expected or configured translation.

Connection tracking

NAT involves more than just changing the ip addresses or port numbers. For instance, when mapping address X to Y, there is no need to add a rule to do the reverse translation. A netfilter system called “conntrack” recognizes packets that are replies to an existing connection. Each connection has its own NAT state attached to it. Reverse translation is done automatically.

Ruleset evaluation tracing

The utility nftables (and, to a lesser extent, iptables) allow for examining how a packet is evaluated and which rules in the ruleset were matched by it. To use this special feature “trace rules” are inserted at a suitable location. These rules select the packet(s) that should be traced. Lets assume that a host coming from IP address C is trying to reach the service on address S and port P. We want to know which NAT transformation is picked up, which rules get checked and if the packet gets dropped somewhere.

Because we are dealing with incoming connections, add a rule to the prerouting hook point. Prerouting means that the kernel has not yet made a decision on where the packet will be sent to. A change to the destination address often results in packets to get forwarded rather than being handled by the host itself.

Initial setup

 
# nft 'add table inet trace_debug'
# nft 'add chain inet trace_debug trace_pre { type filter hook prerouting priority -200000; }'
# nft "insert rule inet trace_debug trace_pre ip saddr $C ip daddr $S tcp dport $P tcp flags syn limit rate 1/second meta nftrace set 1"

The first rule adds a new table This allows easier removal of the trace and debug rules later. A single “nft delete table inet trace_debug” will be enough to undo all rules and chains added to the temporary table during debugging.

The second rule creates a base hook before routing decisions have been made (prerouting) and with a negative priority value to make sure it will be evaluated before connection tracking and the NAT rules.

The only important part, however, is the last fragment of the third rule: “meta nftrace set 1″. This enables tracing events for all packets that match the rule. Be as specific as possible to get a good signal-to-noise ratio. Consider adding a rate limit to keep the number of trace events at a manageable level. A limit of one packet per second or per minute is a good choice. The provided example traces all syn and syn/ack packets coming from host $C and going to destination port $P on the destination host $S. The limit clause prevents event flooding. In most cases a trace of a single packet is enough.

The procedure is similar for iptables users. An equivalent trace rule looks like this:

 
# iptables -t raw -I PREROUTING -s $C -d $S -p tcp --tcp-flags SYN SYN  --dport $P  -m limit --limit 1/s -j TRACE

Obtaining trace events

Users of the native nft tool can just run the nft trace mode:

 
# nft monitor trace

This prints out the received packet and all rules that match the packet (use CTRL-C to stop it):

 
trace id f0f627 ip raw prerouting  packet: iif "veth0" ether saddr ..

We will examine this in more detail in the next section. If you use iptables, first check the installed version via the “iptables –version” command. Example:

 
# iptables --version
iptables v1.8.5 (legacy)

(legacy) means that trace events are logged to the kernel ring buffer. You will need to check dmesg or journalctl. The debug output lacks some information but is conceptually similar to the one provided by the new tools. You will need to check the rule line numbers that are logged and correlate those to the active iptables ruleset yourself. If the output shows (nf_tables), you can use the xtables-monitor tool:

 
# xtables-monitor --trace

If the command only shows the version, you will also need to look at dmesg/journalctl instead. xtables-monitor uses the same kernel interface as the nft monitor trace tool. Their only difference is that it will print events in iptables syntax and that, if you use a mix of both iptables-nft and nft, it will be unable to print rules that use maps/sets and other nftables-only features.

Example

Lets assume you’d like to debug a non-working port forward to a virtual machine or container. The command “ssh -p 1222 10.1.2.3” should provide remote access to a container running on the machine with that address, but the connection attempt times out.

You have access to the host running the container image. Log in and add a trace rule. See the earlier example on how to add a temporary debug table. The trace rule looks like this:

 
nft "insert rule inet trace_debug trace_pre ip daddr 10.1.2.3 tcp dport 1222 tcp flags syn limit rate 6/minute meta nftrace set 1"

After the rule has been added, start nft in trace mode: nft monitor trace, then retry the failed ssh command. This will generate a lot of output if the ruleset is large. Do not worry about the large example output below – the next section will do a line-by-line walkthrough.

 
trace id 9c01f8 inet trace_debug trace_pre packet: iif "enp0" ether saddr .. ip saddr 10.2.1.2 ip daddr 10.1.2.3 ip protocol tcp tcp dport 1222 tcp flags == syn
trace id 9c01f8 inet trace_debug trace_pre rule ip daddr 10.2.1.2 tcp dport 1222 tcp flags syn limit rate 6/minute meta nftrace set 1 (verdict continue)
trace id 9c01f8 inet trace_debug trace_pre verdict continue
trace id 9c01f8 inet trace_debug trace_pre policy accept
trace id 9c01f8 inet nat prerouting packet: iif "enp0" ether saddr .. ip saddr 10.2.1.2 ip daddr 10.1.2.3 ip protocol tcp  tcp dport 1222 tcp flags == syn
trace id 9c01f8 inet nat prerouting rule ip daddr 10.1.2.3  tcp dport 1222 dnat ip to 192.168.70.10:22 (verdict accept)
trace id 9c01f8 inet filter forward packet: iif "enp0" oif "veth21" ether saddr .. ip daddr 192.168.70.10 .. tcp dport 22 tcp flags == syn tcp window 29200
trace id 9c01f8 inet filter forward rule ct status dnat jump allowed_dnats (verdict jump allowed_dnats)
trace id 9c01f8 inet filter allowed_dnats rule drop (verdict drop)
trace id 20a4ef inet trace_debug trace_pre packet: iif "enp0" ether saddr .. ip saddr 10.2.1.2 ip daddr 10.1.2.3 ip protocol tcp tcp dport 1222 tcp flags == syn

Line-by-line trace walkthrough

The first line generated is the packet id that triggered the subsequent trace output. Even though this is in the same grammar as the nft rule syntax, it contains header fields of the packet that was just received. You will find the name of the receiving network interface (here named “enp0”) the source and destination mac addresses of the packet, the source ip address (can be important – maybe the reporter is connecting from a wrong/unexpected host) and the tcp source and destination ports. You will also see a “trace id” at the very beginning. This identification tells which incoming packet matched a rule. The second line contains the first rule matched by the packet:

 
trace id 9c01f8 inet trace_debug trace_pre rule ip daddr 10.2.1.2 tcp dport 1222 tcp flags syn limit rate 6/minute meta nftrace set 1 (verdict continue)

This is the just-added trace rule. The first rule is always one that activates packet tracing. If there would be other rules before this, we would not see them. If there is no trace output at all, the trace rule itself is never reached or does not match. The next two lines tell that there are no further rules and that the “trace_pre” hook allows the packet to continue (verdict accept).

The next matching rule is

 
trace id 9c01f8 inet nat prerouting rule ip daddr 10.1.2.3  tcp dport 1222 dnat ip to 192.168.70.10:22 (verdict accept)

This rule sets up a mapping to a different address and port. Provided 192.168.70.10 really is the address of the desired VM, there is no problem so far. If its not the correct VM address, the address was either mistyped or the wrong NAT rule was matched.

IP forwarding

Next we can see that the IP routing engine told the IP stack that the packet needs to be forwarded to another host:

trace id 9c01f8 inet filter forward packet: iif "enp0" oif "veth21" ether saddr .. ip daddr 192.168.70.10 .. tcp dport 22 tcp flags == syn tcp window 29200

This is another dump of the packet that was received, but there are a couple of interesting changes. There is now an output interface set. This did not exist previously because the previous rules are located before the routing decision (the prerouting hook). The id is the same as before, so this is still the same packet, but the address and port has already been altered. In case there are rules that match “tcp dport 1222” they will have no effect anymore on this packet.

If the line contains no output interface (oif), the routing decision steered the packet to the local host. Route debugging is a different topic and not covered here.

trace id 9c01f8 inet filter forward rule ct status dnat jump allowed_dnats (verdict jump allowed_dnats)

This tells that the packet matched a rule that jumps to a chain named “allowed_dnats”. The next line shows the source of the connection failure:

 
trace id 9c01f8 inet filter allowed_dnats rule drop (verdict drop)

The rule unconditionally drops the packet, so no further log output for the packet exists. The next output line is the result of a different packet:

trace id 20a4ef inet trace_debug trace_pre packet: iif "enp0" ether saddr .. ip saddr 10.2.1.2 ip daddr 10.1.2.3 ip protocol tcp tcp dport 1222 tcp flags == syn

The trace id is different, the packet however has the same content. This is a retransmit attempt: The first packet was dropped, so TCP re-tries. Ignore the remaining output, it does not contain new information. Time to inspect that chain.

Ruleset investigation

The previous section found that the packet is dropped in a chain named “allowed_dnats” in the inet filter table. Time to look at it:

 
# nft list chain inet filter allowed_dnats
table inet filter {
 chain allowed_dnats {
  meta nfproto ipv4 ip daddr . tcp dport @allow_in accept
  drop
   }
}

The rule that accepts packets in the @allow_in set did not show up in the trace log. Double-check that the address is in the @allow_set by listing the element:

 
# nft "get element inet filter allow_in { 192.168.70.10 . 22 }"
Error: Could not process rule: No such file or directory

As expected, the address-service pair is not in the set. We add it now.

 
# nft "add element inet filter allow_in { 192.168.70.10 . 22 }"

Run the query command now, it will return the newly added element.

# nft "get element inet filter allow_in { 192.168.70.10 . 22 }"
table inet filter { set allow_in { type ipv4_addr . inet_service elements = { 192.168.70.10 . 22 } }
}

The ssh command should now work and the trace output reflects the change:

trace id 497abf58 inet filter forward rule ct status dnat jump allowed_dnats (verdict jump allowed_dnats)
trace id 497abf58 inet filter allowed_dnats rule meta nfproto ipv4 ip daddr . tcp dport @allow_in accept (verdict accept)
trace id 497abf58 ip postrouting packet: iif "enp0" oif "veth21" ether .. trace id 497abf58 ip postrouting policy accept

This shows the packet passes the last hook in the forwarding path – postrouting.

In case the connect is still not working, the problem is somewhere later in the packet pipeline and outside of the nftables ruleset.

Summary

This Article gave an introduction on how to check for packet drops and other sources of connectivity problems with the nftables trace mechanism. A later post in the series shows how to inspect the connection tracking subsystem and the NAT information that may be attached to tracked flows.

Posted on Leave a comment

Blender in 2021

The Blender Foundation have just announced their “Big Projects” list for Blender in 2021. It is hard to argue that 2020 wasn’t a banner year for Blender development, with three major releases as well as the first ever LTS release. Through 2020 we saw improvements to the Blender UI/UX, sculpting tools, modeling, EEVEE, Cycles and so much more. We also saw a record number of massive companies coming on board the Blender development fund. With the release today of the projects list, we get insight into the Blender priorities in 2021, including priorities such as:

  • launch of a new open movie called Sprite Fight
  • the everything nodes project, where everything in Blender will be able to be driven procedurally using nodes (see Geometry Nodes in action here)
  • all new Asset Browsers editor window for better content management
  • massive improvements to the VSE or Video Sequence Editor
  • EEVEE real-time rendering improvements including Vulkan support, motion blur, depth of field and possibly raytracing
  • VR improvements including the ability to use VR controllers and author content in virtual reality
  • Cycles rendering improvements especially related to perfromance
  • Animation 22 (previously Animation 2020), an effort to improve animation tools in Blender, sponsored by AWS
  • improved pipeline and USD support, Pixar’s open interchange format

You can learn more about the Blender’s accomplishments in 2020, as well as the new projects in 2021 in the video below.

[youtube https://www.youtube.com/watch?v=mU387jw8UNU?feature=oembed&w=1500&h=844]
Posted on Leave a comment

A 2020 love letter to the Fedora community

[This message comes directly from the desk of Matthew Miller, the Fedora Project Leader. — Ed.]

When I wrote about COVID-19 and the Fedora community all the way back on March 16, it was very unclear how 2020 was going to turn out. I hoped that we’d have everything under control and return to normal soon—we didn’t take our Flock to Fedora in-person conference off the table for another month. Back then, I naively hoped that this would be a short event and that life would return to normal soon. But of course, things got worse, and we had to reimagine Flock as a virtual event on short notice. We weren’t even sure if we’d be able to make our regular Fedora Linux releases on schedule.

Even without the pandemic, 2020 was already destined to be an interesting year. Because Red Hat moved the datacenter where most of Fedora’s servers live, our infrastructure team had to move our servers across the continent. Fedora 33 had the largest planned change set of any Fedora Linux release—and not small things either. We changed the default filesystem for desktop variants to BTRFS and promoted Fedora IoT to an Edition. We also began Fedora ELN—a new process which does a nightly build of Fedora’s development branch in the same configuration Red Hat would use to compose Red Hat Enterprise Linux. And Fedora’s popularity keeps growing, which means more users to support and more new community members to onboard. It’s great to be successful, but we also need to keep up with ourselves!

So, it was already busy. And then the pandemic came along. In many ways, we’re fortunate: we’re already a global community used to distributed work, and we already use chat-based meetings and video calls to collaborate. But it made the datacenter move more difficult. The closure of Red Hat offices meant that some of the QA hardware was inaccessible. We couldn’t gather together in person like we’re used to doing. And of course, we all worried about the safety of our friends and family. Isolation and disruption just plain make everything harder.

I’m always proud of the Fedora community, but this year, even more so. In a time of great stress and uncertainty, we came together and did our best work. Flock to Fedora became Nest With Fedora. Thanks to the heroic effort of Marie Nordin and many others, it was a resounding success. We had way more attendees than we’ve ever had at an in-person Flock, which made our community more accessible to contributors who can’t always join us. And we followed up with our first-ever virtual release party and an online Fedora Women’s Day, both also resounding successes.

And then, we shipped both Fedora 32 and Fedora 33 on time, extending our streak to six releases—three straight years of hitting our targets.

The work we all did has not gone unnoticed. You already know that Lenovo is shipping Fedora Workstation on select laptop models. I’m happy to share that two of the top Linux podcasts have recognized our work—particularly Fedora 33—in their year-end awards. LINUX Unplugged listeners voted Fedora Linux their favorite Linux desktop distribution. Three out of the four Destination Linux hosts chose Fedora as the best distro of the year, specifically citing the exciting work we’ve done on Fedora 33 and the strength of our community. In addition, OMG! Ubuntu! included Fedora 33 in its “5 best Linux distribution releases of 2020” and TechRepublic called Fedora 33 “absolutely fantastic“.

Like everyone, I’m looking ahead to 2021. The next few months are still going to be hard, but the amazing work on mRNA and other new vaccine technology means we have clear reasons to be optimistic. Through this trying year, the Fedora community is stronger than ever, and we have some great things to carry forward into better times: a Nest-like virtual event to compliment Flock, online release parties, our weekly Fedora Social Hour, and of course the CPE team’s great trivia events.

In 2021, we’ll keep doing the great work to push the state of the art forward. We’ll be bold in bringing new features into Fedora Linux. We’ll try new things even when we’re worried that they might not work, and we’ll learn from failures and try again. And we’ll keep working to make our community and our platform inclusive, welcoming, and accessible to all.

To everyone who has contributed to Fedora in any way, thank you. Packagers, blog writers, doc writers, testers, designers, artists, developers, meeting chairs, sysadmins, Ask Fedora answerers, D&I team, and more—you kicked ass this year and it shows. Stay safe and healthy, and we’ll meet again in person soon.Oh, one more thing! Join us for a Fedora Social Hour New Year’s Eve Special. We’ll meet at 23:30 UTC today in Hopin (the platform we used for Nest and other events). Hope to see you there!

Posted on Leave a comment

Blender Network Being Shutdown

Blender have announced that Blender Network is being shutdown. The Blender Network shutdown is occurring in just a few months according to the post on the Blender press site:

On March 31st 2021, Blender Network will terminate its operations. All ongoing memberships will be cancelled and have their last payment refunded. The Blender Foundation Certified Trainer program (BFCT), which was already on hold, will also stop. The blendernetwork.org domain (and all URLs) will redirect to blender.org. No data will be preserved on the blendernetwork.org server, which will be discontinued.

Originally presented by Ton Roosendaal as a whitepaper in 2010, Blender Network’s mission was to facilitate the provisioning of services and support, connect users and promote professional Blender businesses. This mission has been carried out by the blendernetwork.org platform, providing visibility and business opportunities to several hundred individuals and organizations.

However, the incredible growth of the Blender community and the rise of social media have greatly reduced the need for a Blender-backed platform to provide legitimacy and visibility to professionals. For this reason, after almost a decade of operation, it is time to retire the platform.

Fortunately, out of the ashes rise a new phoenix, with Pablo Vazquez making the following announcement on Twitter.

Followed by the follow Tweet with more details:

Unfortunately there is no successor planned for the Blender Certification Program, that was already put on hold due to a lack of focus. You can learn more about the Blender Network sun-setting in the video below.

[youtube https://www.youtube.com/watch?v=P8Du83qumwc?feature=oembed&w=1500&h=844]