Planet Libre

Marthym : Hello OSGi World, Part 5, Fragment Bundles

Disons que cette partie est un bonus si vous n’avez pas encore saturé ! Depuis le vous devez bien avoir remarqué que l’on utilise log4j 2 et que les logs ne s’affichent pas. À la place on a un message d’erreur qui dit qu’il manque un fichier de configuration. Et malheureusement, l’ajouter dans le répertoire de conf ne suffit pas, ni dans le répertoire courant. Il doit se trouver dans le classpath de log4j2-core.

Fragment Bundle

Le problème est là, l’isolation des classpaths induite par OSGi interdit donc de rajouter un fichier dans le classpath d’un bundle. À moins de modifier le jar original de log4j, ce qui n’est pas vraiment génial.

C’est là qu’interviennent les Fragments Bundles. En effet, ce sont des genres d’ajout fait à des bundles existant. Les fichiers qu’ils contiennent vont être ajouté au bundle qui les abrite et vont donc partager le même classpath.

Création du module how-log4j2

Pour créer un Fragment Bundle, il faut ajouter dans le MANIFEST.MF la ligne :

Fragment-Host: org.apache.logging.log4j.core

Pour dire que le fragment est hébergé par log4j2-core.

Dans la configuration du maven-bundle-plugin on a précisé

combine.children="append"> <_include>-src/main/osgi/osgi.bnd

Cette configuration permet, via un fichier src/main/osgi/osgi.bnd, d’ajouter des instructions à BND. On ajoute le module how-log4j2 avec le fichier osgi.bnd contenant la ligne nécessaire. Et on ajoute au module le ficher de configuration log4j2.

On build et on re-teste :

START LEVEL 1 ID|State |Level|Name 16|Resolved | 1|how-log4j2 (1.0.0.SNAPSHOT)|1.0.0.SNAPSHOT

Dans la liste des bundle on voit le nouveau Fragment. Les Fragments s’activent par l’intermédiaire de leur hôte. C’est pour cela qu’il est noté Resolved au lieu de Active.

Les logs s’affichent maintenant correctement !

Conclusion

Si vous êtes arrivé là, merci de votre patience et indulgence. N’hésitez pas à me faire un retour dans les commentaires !

J’utilise OSGi depuis 4 ans sur un projet conséquent en production. Quand on a commencé, on a essuyé les mêmes plâtres que décrit dans ces articles et même plus ! Au final le projet fonctionne bien mais la maintenance en est souvent complexe. Nous n’avons pas abordé la question des tests mais c’est tout aussi compliqué. En outre, les ressources que ce soit documentation ou humaines sont difficiles à trouver. La multitude d’implémentations de chaque partie du framework crée en plus une fragmentation qui amplifie encore le phénomène. De plus, vous avez du le voir, malgré l’ajout de la dépendance Xnio dans le composant http-server il arrive que l’erreur XNIO se produise. C’est une question de timing. Pour la résoudre définitivement, en plus de demander à Felix de vider son cache sur chaque démarrage, il faut ajouter un niveau de chargement des bundles. Un répertoire core qui serait chargé avant application et qui contiendrait tout sauf les jars de notre application. Mais on constate que la gestion de l’ordre de chargement est aussi un élément compliqué d’OSGi qui vient s’ajouter aux autres.

Pour ces raisons, je ne choisirais pas d’utiliser OSGi en production sur les prochains projets. C’est un sujet intéressant à explorer mais le coût en est très élevé comparé au gain qu’on en retire.

Code source: Part 5, Fragment Bundles

Hello OSGi World, Part 5, Fragment Bundles écrit à l'origine par Marthym pour J'ai acheté un PC neuf cassé ... le September 23, 2017.

Gravatar de Marthym
Original post of Marthym.Votez pour ce billet sur Planet Libre.

®om : Gnirehtet réécrit en Rust

Il y a quelques mois, j’ai présenté Gnirehtet, un outil de reverse tethering pour Android que j’ai écrit en Java.

Depuis, je l’ai réécrit en Rust.

Et il est également open source ! Téléchargez-le, branchez un téléphone ou une tablette Android, et exécutez :

./gnirehtet run

(adb doit être installé)

Pourquoi Rust?

À Genymobile, nous voulions que Gnirehtet ne nécessite pas d’environnement d’exécution Java (JRE), donc le besoin principal était de compiler l’application vers un binaire exécutable natif.

Par conséquent, j’ai d’abord pensé la réécrire en C ou C++. Mais à ce moment-là (début mai), apprendre Rust m’intéressait, après avoir vaguement entendu parler de ses fonctionnalités:

Cependant, je n’avais jamais écrit une ligne de Rust ni entendu parler de son système de possession, d’emprunt ou de durées de vie.

Mais je suis convaincu que le meilleur moyen d’apprendre un langage de programmation est de travailler à plein temps sur un projet dans ce langage.

J’étais motivé, donc après avoir vérifié que ça pouvait convenir (en gros, j’ai écrit un exemple utilisant la bibliothèque d’I/O asynchrone mio, et je l’ai exécuté à la fois sur Linux et Windows), j’ai décidé de réécrire Gnirehtet en Rust.

Apprendre Rust

Pendant la réécriture, j’ai dévoré successivement le Rust book, Rust by example et le Rustonomicon. J’ai beaucoup appris, et j’aime énormément ce langage. Beaucoup de ses fonctionnalités me manquent maintenant quand je travaille sur un projet C++ :

À propos de l’apprentissage, Paul Graham a écrit:

Reading and experience train your model of the world. And even if you forget the experience or what you read, its effect on your model of the world persists. Your mind is like a compiled program you’ve lost the source of. It works, but you don’t know why.

Pour les non-anglophones, ma propre traduction :

La lecture et l’expérience entraînent votre modèle du monde. Et même si vous oubliez l’expérience ou ce que vous avez lu, son effet sur votre modèle du monde persiste. Votre esprit est comme un programme compilé dont vous auriez perdu le code source. Ça fonctionne, mais vous ne savez pas pourquoi.

Certains des concepts de Rust (comme les durées de vie ou la sémantique de mouvement par défaut) m’ont fourni un jeu de données significativement différent, qui a sans aucun doute affecté mon modèle du monde (de la programmation).

Je ne vais pas présenter toutes ces fonctionnaliés (cliquez sur les liens de la documentation si ça vous intéresse). À la place, je vais essayer d’expliquer où et pourquoi Rust a resisté au design que je voulais implémenter, et comment repenser les problèmes dans le périmètre des contraintes de Rust.

La partie suivant nécessite une certaine connaissance de Rust. Vous pourriez vouloir la passer pour aller directement aux stats.

Difficultés

Je trouvais la conception de l’application Java plutôt réussie, donc je voulais reproduire l’architecture globale dans la version Rust (avec d’éventuelles adaptations pour la rustifier).

Mais j’ai lutté sur les détails, en particulier pour satisfaire le borrow checker. Les règles sont simples:

First, any borrow must last for a scope no greater than that of the owner. Second, you may have one or the other of these two kinds of borrows, but not both at the same time:

  • one or more references (&T) to a resource,
  • exactly one mutable reference (&mut T).

En français :

Premièrement, aucun emprunt ne doit avoir une portée plus grande que celle de son propriétaire. Deuxièmement, vous pouvez avoir l’un ou l’autre de ces types d’emprunts, mais pas les deux à la fois:

  • une ou plusieurs références (&T) vers une ressource,
  • exactement une référence mutable (&mut T).

Cependant, il m’a fallu un peu de temps pour réaliser comment elles entrent en conflit avec certains principes ou modèles de conception.

Voici donc mes retours. J’ai sélectionné 4 sujets qui sont suffisamment généraux pour être indépendants de ce projet particulier :

Encapsulation

Les règles d’emprunt contraignent l’encapsulation. C’est la première conséquence que j’ai réalisée.

Voici un exemple canonique :

pub struct Data { header: [u8; 4], payload: [u8; 20], } impl Data { pub fn new() -> Self { Self { header: [0; 4], payload: [0; 20], } } pub fn header(&mut self) -> &mut [u8] { &mut self.header } pub fn payload(&mut self) -> &mut [u8] { &mut self.payload } } fn main() { let mut data = Data::new(); let header = data.header(); let payload = data.payload(); }

Nous créons juste une nouvelle instance de Data, puis associons à des variables locales des références mutables vers les tableaux header et payload, en passant par des accesseurs.

Cependant, cela ne compile pas :

$ rustc sample.rs error[E0499]: cannot borrow `data` as mutable more than once at a time --> sample.rs:21:19 | 25 | let header = data.header(); | ---- first mutable borrow occurs here 26 | let payload = data.payload(); | ^^^^ second mutable borrow occurs here 27 | } | - first borrow ends here

Le compilateur ne peut pas faire l’hypothèse que header() et payload() retournent des références vers des données disjointes dans la structure Data. Par conséquent, chacun emprunte la structure data entièrement. Vu que les règles d’emprunt interdisent d’obtenir deux références mutables vers la même ressource, il rejette le second appel.

Parfois, nous faisons face à des limitations temporaires parce que le compilateur n’est pas (encore) assez malin. Ce n’est pas le cas ici : l’implémentation de header() pourrait très bien retourner une référence vers payload, ou écrire dans le tableau payload, enfreignant ainsi les règles d’emprunt. Et la validité d’un appel d’une méthode ne peut pas dépendre de l’implementation de la méthode.

Pour corriger le problème, le compilateur doit être capable de savoir que les variables locales header et payload référencent des données disjointes, par exemple en accédant aux champs directement :

let header = &mut data.header; let payload = &mut data.payload;

ou en exposant une méthode fournissant les deux références simultanément :

struct Data { fn header_and_payload(&mut self) -> (&mut [u8], &mut [u8]) { (&mut self.header, &mut self.payload) } } fn main() { let mut data = Data::new(); let (header, payload) = data.header_and_payload(); }

De même, dans l’implémentation d’une structure, les règles d’emprunt empêchent de factoriser du code dans une méthode privée facilement. Prenons cet exemple (artificiel) :

pub struct Data { buf: [u8; 20], prefix_length: usize, sum: u32, port: u16, } impl Data { pub fn update_sum(&mut self) { let content = &self.buf[self.prefix_length..]; self.sum = content.iter().cloned().map(u32::from).sum(); } pub fn update_port(&mut self) { let content = &self.buf[self.prefix_length..]; self.port = (content[2] as u16) << 8 | content[3] as u16; } }

Ici, le champ buf est un tableau stockant un préfixe et un contenu de manière contiguë.

Nous voulons factoriser la manière dont nous récupérons la slice content, pour que les méthodes update_*() n’aient pas à se préoccuper des détails. Essayons :

impl Data { pub fn update_sum(&mut self) { - let content = &self.buf[self.prefix_length..]; + let content = self.content(); self.sum = content.iter().cloned().map(u32::from).sum(); } pub fn update_port(&mut self) { - let content = &self.buf[self.prefix_length..]; + let content = self.content(); self.port = (content[2] as u16) << 8 | content[3] as u16; } + + fn content(&mut self) -> &[u8] { + &self.buf[self.prefix_length..] + } }

Malheureusement, cela ne compile pas :

error[E0506]: cannot assign to `self.sum` because it is borrowed --> facto2.rs:11:9 | 10 | let content = self.content(); | ---- borrow of `self.sum` occurs here 11 | self.sum = content.iter().cloned().map(u32::from).sum(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.sum` occurs here error[E0506]: cannot assign to `self.port` because it is borrowed --> facto2.rs:16:9 | 15 | let content = self.content(); | ---- borrow of `self.port` occurs here 16 | self.port = (content[2] as u16) << 8 & content[3] as u16; |

Comme dans l’exemple précédent, récupérer une référence à travers une méthode emprunte la structure complète (ici, self).

Pour contourner le problème, nous pouvons expliquer au compilateur que les champs sont disjoints :

impl Data { pub fn update_sum(&mut self) { let content = Self::content(&self.buf, self.prefix_length); self.sum = content.iter().cloned().map(u32::from).sum(); } pub fn update_port(&mut self) { let content = Self::content(&self.buf, self.prefix_length); self.port = (content[2] as u16) << 8 | content[3] as u16; } fn content(buf: &[u8], prefix_length: usize) -> &[u8] { &buf[prefix_length..] } }

Ça compile, mais cela va totalement à l’encontre de la factorisation : l’appelant doit fournir les champs nécessaires.

Comme alternative, nous pouvons utiliser une macro pour inliner le code :

macro_rules! content { ($self:ident) => { &$self.buf[$self.prefix_length..] } } impl Data { pub fn update_sum(&mut self) { let content = content!(self); self.sum = content.iter().cloned().map(u32::from).sum(); } pub fn update_port(&mut self) { let content = content!(self); self.port = (content[2] as u16) << 8 | content[3] as u16; } }

Mais c’est loin d’être idéal.

Je pense que nous devons juste l’accepter : l’encapsulation entre parfois en conflit avec les règles d’emprunt. Après tout, ce n’est pas si surprenant : imposer les règles d’emprunt nécessite de suivre chaque accès concret aux ressources, alors que l’encapsulation vise à les abstraire.

Observateur

Le design pattern observateur est utile pour enregistrer des événements sur un objet.

Dans certains cas, ce pattern pose des difficultés d’implémentation en Rust.

Pour faire simple, considérons que les événements sont des valeurs u32. Voici une implémentation possible :

pub trait EventListener { fn on_event(&self, event: u32); } pub struct Notifier { listeners: Vec<Box<EventListener>>, } impl Notifier { pub fn new() -> Self { Self { listeners: Vec::new() } } pub fn register<T: EventListener + 'static>(&mut self, listener: T) { self.listeners.push(Box::new(listener)); } pub fn notify(&self, event: u32) { for listener in &self.listeners { listener.on_event(event); } } }

Par commodité, implémentons notre trait EventListener pour les closures :

impl<F: Fn(u32)> EventListener for F { fn on_event(&self, event: u32) { self(event); } }

Ainsi, son utilisation est simple :

let mut notifier = Notifier::new(); notifier.register(|event| println!("received [{}]", event)); println!("notifying..."); notifier.notify(42);

Cela affiche :

notifying... received [42]

Jusqu’ici, tout va bien.

Cependant, les choses se compliquent si nous voulons modifier un état sur la réception d’un événement. Par exemple, implémentons une structure pour stocker tous les événements reçus :

pub struct Storage { events: Vec<u32>, } impl Storage { pub fn new() -> Self { Self { events: Vec::new() } } pub fn store(&mut self, value: u32) { self.events.push(value); } pub fn events(&self) -> &Vec<u32> { &self.events } }

Pour pouvoir remplir ce Storage sur chaque événement reçu, nous devons d’une manière ou d’une autre le passer avec l’event listener, qui sera stocké dans le Notifier. Par conséquent, nous avons besoin qu’une instance de Storage soit partagée entre le code appelant et le Notifier.

Avoir deux références mutables vers le même objet enfreint évidemment les règles d’emprunt, donc nous avons besoin d’un pointeur à compteur de références.

Cependant, un tel pointeur est en lecture seul, donc nous avons également besoin d’un RefCell pour la mutabilité intérieure.

Ainsi, nous allons utiliser une instance de Rc>. Cela peut sembler trop verbeux, mais utiliser Rc> (ou Arc> pour la thread-safety) est très courant en Rust. Et il y a pire.

Voici ce que donne le code client :

use std::cell::RefCell; use std::rc::Rc; let mut notifier = Notifier::new(); // first Rc to the Storage let rc = Rc::new(RefCell::new(Storage::new())); // second Rc to the Storage let rc2 = rc.clone(); // register the listener saving all the received events to the Storage notifier.register(move |event| rc2.borrow_mut().store(event)); notifier.notify(3); notifier.notify(141); notifier.notify(59); assert_eq!(&vec![3, 141, 59], rc.borrow().events());

De cette manière, le Storage est correctement modifié à partir de l’event listener.

Tout n’est pas résolu pour autant. Dans cet exemple, c’était facile, nous avions accès à l’instance Rc>. Comment faire si nous avons seulement accès au Storage, par exemple si nous voulons que le Storage s’enregistre lui-même à partir de l’une de ses méthodes, sans que l’appelant n’ait à fournir l’instance Rc> ?

impl Storage { pub fn register_to(&self, notifier: &mut Notifier) { notifier.register(move |event| { /* how to retrieve a &mut Storage from here? */ }); } }

Nous devons trouver un moyen de récupérer le Rc> à partir du Storage.

Pour cela, l’idée consiste à rendre Storage conscient de son pointeur à compteur de références. Bien sûr, cela n’a du sens que si Storage est construit dans un Rc>.

C’est exactement ce que enable_shared_from_this fournit en C++, donc nous pouvons nous inspirer de son fonctionnement : juste stocker un Weak>, downgradé à partir du Rc>, dans la structure elle-même. De cette manière, nous pouvons l’utiliser pour récupérer une référence &mut Storage à partir de l’event listener :

use std::rc::{Rc, Weak}; use std::cell::RefCell; pub struct Storage { self_weak: Weak<RefCell<Storage>>, events: Vec<u32>, } impl Storage { pub fn new() -> Rc<RefCell<Self>> { let rc = Rc::new(RefCell::new(Self { self_weak: Weak::new(), // initialize empty events: Vec::new(), })); // set self_weak once we get the Rc instance rc.borrow_mut().self_weak = Rc::downgrade(&rc); rc } pub fn register_to(&self, notifier: &mut Notifier) { let rc = self.self_weak.upgrade().unwrap(); notifier.register(move |event| rc.borrow_mut().store(event)) } }

Voici comment l’utiliser :

let mut notifier = Notifier::new(); let rc = Storage::new(); rc.borrow().register_to(&mut notifier); notifier.notify(3); notifier.notify(141); notifier.notify(59); assert_eq!(&vec![3, 141, 59], rc.borrow().events());

Il est donc possible d’implémenter le design pattern observateur en Rust, mais c’est un peu plus difficile qu’en Java ;-)

Lorsque c’est possible, il est probablement préférable de l’éviter.

Partage de données mutables

Mutable references cannot be aliased.

En français :

Les références mutables ne peuvent pas être aliasées.

Comment partager des données mutables, alors ?

Nous avons vu que nous pouvions utiliser Rc> (ou Arc>), qui impose les règles d’emprunt à l’exécution. Cependant, ce n’est pas toujours désirable :

  • cela force une nouvelle allocation sur le tas,
  • chaque accès a un coût à l’exécution,
  • l’emprunt concerne toujours la ressource entière.

Au lieu de cela, nous pourrions utiliser des pointeurs bruts manuellement dans du code non-sûr, mais alors ce serait non-sûr.

Et il y a une autre solution, qui consiste à exposer des vues temporaires d’emprunt d’un objet. Laissez-moi expliquer.

Dans Gnirehtet, un paquet contient une référence vers les données brutes (stockées dans un buffer quelque part) ainsi que les valeur des champs des en-têtes IP et TCP/UDP (parsées à partir du tableau d’octets brut). Nous aurions pu utiliser une structure à plat pour tout stocker :

pub struct Packet<'a> { raw: &'a mut [u8], ipv4_source: u32, ipv4_destination: u32, ipv4_protocol: u8, // + other ipv4 fields transport_source: u16, transport_destination: u16, // + other transport fields }

Le Packet aurait fourni des setters pour tous les champs d’en-têtes (modifiant à la fois les champs du paquet et le tableau d’octets). Par exemple :

impl<'a> Packet<'a> { pub fn set_transport_source(&mut self, transport_source: u16) { self.transport_source = transport_source; let transport = &mut self.raw[20..]; BigEndian::write_u16(&mut transport[0..2], port); } }

Mais cette conception ne serait pas terrible (surtout que les champs d’en-têtes TCP et UDP sont différents).

À la place, nous voudrions extraire les en-têtes d’IP et de transport vers des structures séparées, gérant leur propre partie du tableau d’octets :

// violates the borrowing rules pub struct Packet<'a> { raw: &'a mut [u8], // the whole packet (including headers) ipv4_header: Ipv4Header<'a>, transport_header: TransportHeader<'a>, } pub struct Ipv4Header<'a> { raw: &'a mut [u8], // slice related to ipv4 headers source: u32, destination: u32, protocol: u8, // + other ipv4 fields } pub struct TransportHeader<'a> { raw: &'a mut [u8], // slice related to transport headers source: u16, destination: u16, // + other transport fields }

Vous avez immédiatement repéré le problème : il y a plusieurs références vers la même ressource, le tableau d’octets raw, en même temps.

Remarquez que diviser le tableau n’est pas une possibilité ici, vu que les slices de raw se chevauchent : nous avons besoin d’écrire le paquet complet en une seule fois vers la couche réseau, donc le tableau raw dans Packet doit inclure les headers.

Nous avons besoin d’une solution compatible avec les règles d’emprunt.

Voici celle à laquelle je suis parvenu :

  • stocker les données des en-têtes séparément, sans les slices de raw,
  • créer des structures de vues pour les en-têtes d’IP et de transport, liées à une durée de vie,
  • exposer des méthodes de Packet retournant des instances de vues.

Et voici une simplification de l’implémentation réelle :

pub struct Packet<'a> { raw: &'a mut [u8], ipv4_header: Ipv4HeaderData, transport_header: TransportHeaderData, } pub struct Ipv4HeaderData { source: u32, destination: u32, protocol: u8, // + other ipv4 fields } pub struct TransportHeaderData { source: u16, destination: u16, // + other transport fields } pub struct Ipv4Header<'a> { raw: &'a mut [u8], data: &'a mut Ipv4HeaderData, } pub struct TransportHeader<'a> { raw: &'a mut [u8], data: &'a mut TransportHeaderData, } impl<'a> Packet<'a> { pub fn ipv4_header(&mut self) -> Ipv4Header { Ipv4Header { raw: &mut self.raw[..20], data: &mut self.ipv4_header, } } pub fn transport_header(&mut self) -> TransportHeader { TransportHeader { raw: &mut self.raw[20..40], data: &mut self.transport_header, } } }

Les setters sont implémentés sur les vues, où ils détiennent une référence mutable vers le tableau brut :

impl<'a> TransportHeader<'a> { pub fn set_source(&mut self, source: u16) { self.data.source = source; BigEndian::write_u16(&mut raw[0..2], source); } pub fn set_destination(&mut self, destination: u16) { self.data.destination = destination; BigEndian::write_u16(&mut raw[2..4], destination); } }

De cette manière, les règles d’emprunt sont respectées, et l’API est élégante :

let mut packet = …; // "transport_header" borrows "packet" during its scope let mut transport_header = packet.transport_header(); transport_header.set_source(1234); transport_header.set_destination(1234);Limitations du compilateur

Rust est un langage jeune, et le compilateur a quelques problèmes ennuyeux.

Le pire, d’après moi, est lié aux durées de vie non-lexicales, qui provoque des erreurs inattendues :

struct Container { vec: Vec<i32>, } impl Container { fn find(&mut self, v: i32) -> Option<&mut i32> { None // we don't care the implementation } fn get(&mut self, v: i32) -> &mut i32 { if let Some(x) = self.find(v) { return x; } self.vec.push(v); self.vec.last_mut().unwrap() } }error[E0499]: cannot borrow `self.vec` as mutable more than once at a time --> sample.rs:14:9 | 11 | if let Some(x) = self.find(v) { | ---- first mutable borrow occurs here ... 14 | self.vec.push(v); | ^^^^^^^^ second mutable borrow occurs here 15 | self.vec.last_mut().unwrap() 16 | } | - first borrow ends here

Heureusement, cela devrait être corrigé prochainement.

La fonctionnalité d’Impl Trait, permettant aux fonctions de retourner des types abstraits non-boxés, devrait aussi améliorer l’expérience (il y a aussi une proposition étendue).

Le compilateur produit généralement des messages d’erreur très utiles. Mais quand ce n’est pas le cas, ils peuvent être très déroutants.

Sûreté et pièges

Le premier chapitre du Rustonomicon dit :

Safe Rust is For Reals Totally Safe.

[…]

Safe Rust is the true Rust programming language. If all you do is write Safe Rust, you will never have to worry about type-safety or memory-safety. You will never endure a null or dangling pointer, or any of that Undefined Behavior nonsense.

En français :

La partie Sûre de Rust est Réellement Totallement Sûre.

[…]

Le Rust Sûr est le vrai langage de programmation Rust. Si vous n’écrivez que du Rust Sûr, vous n’aurez jamais à vous inquiétez de la sûreté des types ou de la mémoire. Vous n’aurez jamais à supporter un pointeur null ou dangling, ou l’un de ces comportements indéfinis insensés.

C’est le but. Et c’est presque vrai.

Leakpocalypse

Dans le passé, il a été possible d’écrire du code Rust sûr accédant à de la mémoire libérée.

Cette “leakpocalypse” a conduit à la clarification des guaranties de sûreté : ne pas exécuter un destructeur est maintenant considéré sûr. En d’autres termes, la sûreté mémoire ne peut plus reposer sur RAII (en fait, elle n’a jamais pu, mais cela n’a été remarqué que tardivement).

En conséquence, std::mem::forget est maintenant sûr, et JoinGuard a été déprécié et supprimé de la bibliothèque standard (il a été déplacé vers un crate séparé).

Les autres outils s’appuyant sur RAII (comme Vec::drain()) doivent prendre des précautions particulières pour garantir que la mémoire ne sera pas corrompue.

Ouf, la sûreté mémoire est (maintenant) sauvée.

Infinité indéfinie

En C et C++, les boucles infinies sans effets de bords sont un cas d’undefined behavior. À cause de cela, il est possible d’écrire des programmes qui, de façon inattendue, réfutent le dernier théorème de Fermat.

En pratique, le compilateur Rust s’appuie sur LLVM, qui (actuellement) applique ses optimisations en faisant l’hypothèse que les boucles infinies sans effets de bords ont un comportement indéfini. En conséquence, de tels undefined behaviors se produisent également en Rust.

Voici un exemple minimal pour l’observer :

fn infinite() { loop {} } fn main() { infinite(); }

Quand on l’exécute sans optimisations, il se comporte comme “attendu” :

$ rustc ub.rs && ./ub ^C (infinite loop, interrupt it)

Mais activer les optimisations fait paniquer le programme :

$ rustc -O ub.rs && ./ub thread 'main' panicked at 'assertion failed: c.borrow().is_none()', /checkout/src/libstd/sys_common/thread_info.rs:51 note: Run with `RUST_BACKTRACE=1` for a backtrace.

Nous pouvons aussi produire des résultats inattendus sans plantage :

fn infinite(mut value: u32) { // infinite loop unless value initially equals 0 while value != 0 { if value != 1 { value -= 1; } } } fn main() { infinite(42); println!("end"); }$ rustc ub.rs && ./ub ^C (infinite loop, interrupt it)

Mais avec optimisations :

$ rustc -O ub.rs && ./ub end

C’est un cas particulier, qui sera probablement corrigé dans le futur. En pratique, les garanties de sûreté de Rust sont très fortes (au prix d’être contraignantes).

Stats

C’est tout pour mes retours sur le langage lui-même.

En supplément, comparons les versions Java et Rust du serveur relais.

Nombre de lignes $ cloc relay-{java,rust}/src ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- Rust 29 687 655 4506 Java 37 726 701 2931 -------------------------------------------------------------------------------

(tests included)

Le projet Rust est significativement plus gros, pour plusieurs raisons :

  • il y a beaucoup de classes de vues d’emprunt ;
  • la version Rust définit sa propre classe de selecteur d’I/O asynchrone, encapsulant Poll de plus bas niveau, alors que la version Java utilise le Selector standard ;
  • la gestion d’erreur pour l’analyse de la ligne de commande est plus verbeuse.

La version Java contient plus de fichiers car les tests unitaires sont séparés, alors qu’en Rust ils se trouvent dans le même fichier que les classes qu’ils testent.

Juste pour information, voici les résultats pour le client Android :

$ cloc app/src ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- Java 15 198 321 875 XML 6 7 2 76 ------------------------------------------------------------------------------- SUM: 21 205 323 951 ------------------------------------------------------------------------------- Taille des binaires -------------------------------------------- Java gnirehtet.jar 61K -------------------------------------------- Rust gnirehtet 3.0M after "strip -g gnirehtet" 747K after "strip gnirehtet" 588K --------------------------------------------

Le binaire Java lui-même est bien plus petit. La comparaison n’est pas juste cependant, vu qu’il nécessite l’environnement d’exécution Java :

$ du -sh /usr/lib/jvm/java-1.8.0-openjdk-amd64/ 156M /usr/lib/jvm/java-1.8.0-openjdk-amd64/ Utilisation mémoire

Avec une seule connection TCP ouvert, voici la consommation mémoire pour le serveur relais en Java :

$ sudo pmap -x $RELAY_JAVA_PID Kbytes RSS Dirty total kB 4364052 86148 69316

(résultat filtré)

Et pour le serveur relais en Rust :

$ sudo pmap -x $RELAY_RUST_PID Kbytes RSS Dirty total kB 19272 2736 640

Regardez la valeur RSS, qui indique la mémoire réellement utilisée.

Comment on pouvait s’y attendre, la version Java consomme plus de mémoire (86Mo) que la version Rust (moins de 3Mo). De plus, sa valeur est instable à cause de l’allocation de petits objets et leur garbage collection, qui génère aussi davantage de dirty pages. La valeur pour Rust, quant à elle, est très stable : une fois la connection créée, il n’y a plus d’allocations mémoire du tout.

Utilisation CPU

Pour comparer l’utilisation CPU, voici mon scénario : un fichier de 500Mo est hébergé par Apache sur mon ordinateur, je démarre le serveur relais avec perf stat, puis je télécharge le fichier à partir de Firefox sur Android. Dès que le fichier est téléchargé, je stoppe le serveur relais (Ctrl+C).

Voici les résultats pour la version Java :

$ perf stat -B java -jar gnirehtet.jar relay Performance counter stats for 'java -jar gnirehtet.jar relay': 11805,458302 task-clock:u (msec) # 0,088 CPUs utilized 0 context-switches:u # 0,000 K/sec 0 cpu-migrations:u # 0,000 K/sec 28 618 page-faults:u # 0,002 M/sec 17 908 360 446 cycles:u # 1,517 GHz 13 944 172 792 stalled-cycles-frontend:u # 77,86% frontend cycles idle 18 437 279 663 instructions:u # 1,03 insn per cycle # 0,76 stalled cycles per insn 3 088 215 431 branches:u # 261,592 M/sec 70 647 760 branch-misses:u # 2,29% of all branches 133,975117164 seconds time elapsed

Et pour la version Rust :

$ perf stat -B ./gnirehtet relay Performance counter stats for 'target/release/gnirehtet relay': 2707,479968 task-clock:u (msec) # 0,020 CPUs utilized 0 context-switches:u # 0,000 K/sec 0 cpu-migrations:u # 0,000 K/sec 1 001 page-faults:u # 0,370 K/sec 1 011 527 340 cycles:u # 0,374 GHz 2 033 810 378 stalled-cycles-frontend:u # 201,06% frontend cycles idle 981 103 003 instructions:u # 0,97 insn per cycle # 2,07 stalled cycles per insn 98 929 222 branches:u # 36,539 M/sec 3 220 527 branch-misses:u # 3,26% of all branches 133,766035253 seconds time elapsed

Je ne suis pas un expert pour analyser les résultats, mais de ce que je comprends de la valeur task-clock:u, la version Rust consomme 4× moins de temps CPU.

Conclusion

Réécrire Gnirehtet en Rust a été une formidable expérience, où j’ai appris un super langage et de nouveaux concepts de programmation. Et maintenant, nous avons une application native avec de meilleures performances.

Bon reverse tethering !

Gravatar de ®om
Original post of ®om.Votez pour ce billet sur Planet Libre.

Thuban : Bilan libre de septembre 2017 (n°10)

Un peu en avance ce mois-ci, mais je sais que la fin du mois ne sera pas très riche car l'emploi du temps est chargé. Voici donc un résumé de mes quelques contributions à des projets libres au cours du mois de septembre, en espérant vous donner envie d'en faire autant.

Manuel (auto)? hébergement
Concernant le manuel pour s'(auto?) héberger, j'ai bien avancé et je suis en mesure de le publier lorsqu'OpenBSD 6.2 le sera (d'ici un mois?). Les gains de la précédente version couvreront une publication simple (pas en librairie) et c'est très bien puisque de toutes façon il n'y a pas de ventes chez les libraires. Cependant, selon mes moyens, je voudrais accompagner le manuel d'un petit plus. À ce propos, ce sont vraiment vos remarques qui m'ont permi de le corriger/simplifier/améliorer. C'est en discutant avec des collègues néophytes que j'ai reçu une bonne claque :

- C'est super intéressant ce truc! Tu peux vraiment être tranquille au moins comme ça. C'est difficile?
- Ce n'est pas plus difficile que se mettre à jardiner. Il faut être soigneux surtout, et y aller étape par étape.
- Et ton bouquin là, il est long?
- Euh, environ 200 pages...
- Ah ouais quand même ! C'est pas si accessible que ça, s'il faut se taper 200 pages avant d'y arriver.

*VLAN.
C'est tellement vrai. Mis à part quelques êtres à parts, il faut être carrément motivé.
J'ai donc décidé d'accompagner le manuel complet par un e-book plus court qui contient des fiches pratiques. Vous y trouverez la recette pour avoir son serveur web, une autre pour avoir son serveur mail... Chaque chapitre ne dépasse pas les 4 pages (c'est le max) et va à l'essentiel.

Autres projets

  • J'ai configuré la prochaine session de l'iso permettant d'aborder OpenBSD, à savoir isotop. Elle se construit en -current et ma foi ça semble fonctionner comme prévu. J'attends la publication d'OpenBSD 6.2 pour approfondir les tests.
  • Pour obsd4a.net, j'ai bricolé des thèmes et je termine le partenariat avec notre hébergeur.
  • Avec l'aide de PengouinBSD, le miroir OpenBSD hébergé par obsd4a a maintenant une version https.
  • Un peu de traduction de la FAQ d'OpenBSD sur le wiki obsd4a.
  • Je suis de près le projet ldnscripts de 22decembre pour DNSSEC. Cet outil remplace les usines à gaz comme Opendnssec Quelques commits sont de moi, mais ce n'est rien comparé à son travail.
  • J'ai fait quelques commits à blogotext, le moteur de ce blog. Notamment, on peut retenir la séparation du javascript en fichier à part, la création de logos (qui n'ont pas été retenus par le vote de la communauté :) ), le passage de l'user-agent à une version plus à jour, la création d'un fichier robots.txt à l'installation.

Et voilà, ça sera tout :)

i'm out

Gravatar de Thuban
Original post of Thuban.Votez pour ce billet sur Planet Libre.

Carl Chenet : Déjà 100 abonnés au Courrier du hacker une semaine après son lancement

Une semaine après son lancement, le Courrier du hacker, une newsletter hebdomadaire publiée le vendredi qui propose les meilleurs liens du Logiciel Libre et Open Source francophones, vient de passer les 100 abonnés !

La première édition du Courrier du hacker a été publiée vendredi dernier à 80 abonnés. Le nombre d’abonnés avant la première édition a démontré l’intérêt d’une newsletter hebdomadaire récapitulative.

La source des liens du Courrier du hacker

En effet pour ceux qui ne peuvent pas se connecter régulièrement au Journal du hacker, il était dommage de passer à côté de nombres de liens très intéressants. D’où l’idée de rassembler au sein d’une newsletter arrivant directement dans vos e-mails le vendredi afin de la parcourir tranquillement pendant le week-end.

 

E-mail S'abonner

Si vous n’avez pas le temps de suivre l’évolution de l’actualité sur le Journal du hacker, n’hésitez pas à vous abonner via le formulaire ci-dessus ou directement sur le Courrier du hacker.

Gravatar de Carl Chenet
Original post of Carl Chenet.Votez pour ce billet sur Planet Libre.

Articles similaires

Miamondo : Le logiciel libre, késako?

Chères lectrices, chers lecteurs,

Je suis ravi d’accueillir le collectif Emmabuntüs en tant que nouvel auteur de Miamondo. Voici donc le tout premier article signé « Emmabuntüs » accompagné d’un beau dessin de Péhä. Cet article a également été publié aujourd’hui même dans le journal  l’âge de faire. Je vous souhaite une bonne lecture.

Benoît.

peha_logiciel_libre

 

Pour bien débuter cette nouvelle saison, revenons sur la définition du logiciel libre, que certains d’entre vous confondent avec un logiciel gratuit dénommé « Freeware » ou gratuiciel. Or, on va voir que la gratuité n’est pas la principale qualité d’un logiciel libre, et que les logiciels gratuits (gratuiciels) ne sont pas nécessairement libres… Cet amalgame vient du fait qu’il y a une ambiguïté en langue anglaise autour du mot « free » qui peut signifier libre aussi bien que gratuit. Donc dans notre contexte, « Free software » se traduit par « logiciel libre » et non pas « gratuit ». D’ailleurs, un certain nombre d’anglophones utilisent désormais le vocable « Software libre » pour bien marquer la différence.

Alors pourquoi parle-t-on de liberté pour un logiciel ? Cela a plus de sens pour les êtres vivants que pour du virtuel ! En fait, il s’agit d’une liberté d’usage pour vous, pour nous, qui est constituée de 4 libertés numérotées de 0 à 3 (humour typique des informaticiens, Ndlr) par la Free Software Foundation, permettant de définir le logiciel comme libre :

0. la liberté d’exécuter le programme par vous, pour tous vos usages.
1. la liberté d’étudier le fonctionnement du programme et de l’adapter à vos besoins.
2. la liberté de redistribuer des copies du programme -ce qui implique la possibilité de donner, aussi bien que de vendre des copies. Par exemple en France, le chiffre d’affaires du logiciel libre représentait 4,5 Milliards d’euros en 2016.
3. la liberté d’améliorer le programme et de distribuer vos améliorations au public, pour en faire profiter tout le monde.

Quand le logiciel ne remplit pas ces 4 libertés, il est qualifié de propriétaire (ou de privateur) même s’il est distribué gratuitement. En l’utilisant, vous acceptez implicitement la licence, qui vous interdit de l’étudier, de le modifier, de le céder à des tiers. Il ne vous appartient pas, vous avez simplement un droit d’usage très limité.

Pour compléter la présentation du logiciel libre, voici une réflexion le concernant, proposée par Richard Stallman, qui fonda il y a 30 ans ce mouvement libertaire, ainsi que la Free Software Foundation :

« Quand les utilisateurs ne contrôlent pas le programme, c’est le programme qui contrôle les utilisateurs. Le développeur contrôle le programme, et par ce biais, contrôle les utilisateurs. Ce programme non libre, ou « privateur », devient donc l’instrument d’un pouvoir injuste. »

A partir du principe du logiciel libre, sont nés de grands logiciels que vous utilisez tous les jours, comme Wikipédia, Linux (la base, entre autres, d’Android), Firefox, LibreOffice, VLC, etc. Preuve que la liberté est gage de qualité et d’utilisation pour tous !

Le concept de la licence du logiciel libre (GPL : GNU General Public License) a aussi permis la création des formats ouverts. Avec les formats, on ne fait pas référence au logiciel global, mais à la structure même des données du logiciel, qui est donc ouvertement publiée, ceci permettant à des développeurs de créer des logiciels pour traiter ces données dans le présent mais aussi dans le futur, comme la Pierre de Rosette a permis à Jean-François Champollion de déchiffrer les hiéroglyphes. Dans un format propriétaire, si l’éditeur arrête de développer son logiciel pour lire vos données, celles-ci deviennent de facto illisibles, car personne ne sait, et n’a souvent même pas le droit de savoir, comment elles sont codées 😦

Dans cet article, nous avons uniquement employé le terme logiciel libre, et non pas celui d’Open Source, que vous pouvez entendre ou lire dans les médias. Cela n’est pas une erreur de notre part, car ces deux concepts, bien que poursuivant un but similaire (celui de donner une plus grande liberté d’usage aux utilisateurs de logiciels) ont cependant une différence fondamentale qui réside dans leurs philosophies respectives. Selon Richard Stallman dont nous partageons complètement l’analyse,

«  L’open source est une méthodologie de développement; le logiciel libre est un mouvement social ».

Voici deux articles, qui vous permettrons de former votre propre opinion sur ce sujet :
Pourquoi l’expression « logiciel libre » est meilleure qu’« open source »
En quoi l’open source perd de vue l’éthique du logiciel libre

Le mois prochain dans L’âge de faire : comment trouver des ressources libres : musique, images, etc.

Collectif EmmabuntüsGPL V3
Dessin : Péhä CC-BY-SA 2017

 


Gravatar de Miamondo
Original post of Miamondo.Votez pour ce billet sur Planet Libre.

Articles similaires

Renault : Participez à la journée de test consacrée à l'internationalisation

Aujourd'hui, ce mardi 19 septembre, est une journée dédiée à un test précis : sur l'internationalisation de Fedora. En effet, durant le cycle de développement, l'équipe d'assurance qualité dédie quelques journées autours de certains composants ou nouveautés afin de remonter un maximum de problèmes sur le sujet.

Elle fournit en plus une liste de tests précis à effectuer. Il vous suffit de les suivre, comparer votre résultat au résultat attendu et le notifier.

En quoi consiste ce test ?

Comme chaque version de Fedora, la mise à jour de ses outils impliquent souvent l’apparition de nouvelles chaînes de caractères à traduire et de nouveaux outils liés à la prise en charge de langues (en particulier asiatiques).

Pour favoriser l'usage de Fedora dans l'ensemble des pays du monde, il est préférable de s'assurer que tout ce qui touche à l'internationalisation de Fedora soit testée et fonctionne. Notamment parce qu'une partie doit être fonctionnelle dès le LiveCD d'installation (donc sans mise à jour).

Les tests du jour couvrent :

  • Le bon fonctionnement d'ibus pour la gestion des entrées claviers ;
  • La personnalisation des polices de caractères ;
  • L'installation automatique des paquets de langues des logiciels installés suivant la langue du système ;
  • La traduction fonctionnelle par défaut des applications ;
  • Les polices Serif chinois par défaut (changement de Fedora 27) ;
  • Test de libpinyin 2.1 pour la saisie rapide du chinois Pinyin (changement de Fedora 27).

Bien entendu, étant donné les critères, à moins de savoir une langue chinoise, l'ensemble des tests n'est pas forcément réalisable. Mais en tant que francophones, de nombreuses problématiques nous concernent et remonter les problèmes est important. En effet, ce ne sont pas les autres communautés linguistiques qui identifieront les problèmes d'intégration de la langue française.

Comment y participer ?

Vous pouvez vous rendre sur la page des tests pour lister les tests disponibles et rapporter vos résultats. La page wiki récapitule les modalités de la journée.

Si vous avez besoin d'aide lors du déroulement des tests, n'hésitez pas de faire un tour sur IRC pour recevoir un coup de main sur les canaux #fedora-test-days et #fedora-fr (respectivement en anglais et en français) sur le serveur Freenode.

En cas de bogue, il est nécessaire de le rapporter sur le BugZilla. Si vous ne savez pas faire, n'hésitez pas à consulter la documentation correspondante.

De plus, si une journée est dédiée à ces tests, il reste possible de les effectuer quelques jours plus tard sans problème ! Les résultats seront globalement d'actualité.

Gravatar de Renault
Original post of Renault.Votez pour ce billet sur Planet Libre.

Articles similaires

alterlibriste : Pas toujours facile de promouvoir le libre quand on n'est pas convaincu

Encore un billet un peu sous forme de dépêche, mais il va falloir oublier quelque temps les longues réflexions, car je n’ai ni vraiment l’envie, ni vraiment le temps. Je préfère profiter du temps plutôt agréable pour aller faire du sport dehors. Même la lecture de mes flux rss est plus ou moins expédiée sans m’attarder sur les annonces de versions, les billets techniques ni les aspects sécurité.

Je n’en reste pas moins dans la mouvance libriste et continue d’écouter les podcasts traitant le sujet de près ou de loin. Je signale donc que l’émission canadienne (précédemment chroniquée) traitait ce week-end des logiciels libres. Bon, pour des addicts aux iPhone et aux réseaux sociaux de masse, ça sonnait un peu faux et il y a même eu une petite remarque assez désobligeante comme quoi les développeurs faisaient d’abord du libre pour se faire un CV avant d’intégrer les grosses boîtes privatrices.

La partie la plus intéressante était celle consacré à Purism avec ses machines libres : laptop et futur téléphone. Ce dernier fait pas mal parler de lui, à voir s’il fera mieux que la tentative ratée de Canonical ; ils en sont actuellement à 30 % de leur campagne de financement, 35 jours avant la fin. Il y a une demande mais à ce prix (600 $) et avec un tel délai (presque un an et demi), il faut être motivé !

La fin de l’émission a été consacrée aux CHATONS de Framasoft que l’on ne présente plus ici. Encore une fois, ça sentait un peu l’œuvre de charité, pourquoi quitter le monde Google quand on s’y sent si bien et que tout y est tellement mieux fait ?, avouent les différents intervenants.

Cela me fait penser que finalement, tous ceux qui relaient ce genre d’informations se donnent en quelque sorte bonne conscience en montrant qu’une alternative existe pour ceux qui se plaignent des géants du web. Encore faudrait-il avoir le courage de ses opinions et parfois accepter un peu moins de clinquant pour plus de liberté.

Gravatar de alterlibriste
Original post of alterlibriste.Votez pour ce billet sur Planet Libre.

Articles similaires

genma : Yunohost et les applications Framasoft

Comme je le disais dans mon billet et ma conférence De Framasoft à Yunohost, réapproprions nous le cloud un partenariat avait été mis en place entre Framasoft et Yunohost avec du temps d'un salarié de Framasoft consacré au packaging d'application Framasoft pour Yunohost.

Quelques mois après, où en est-on ?

L'idée n'est pas de parler au nom de Framasoft mais plus de remettre en avant cette collaboration et de faire un petit suivi de l'avancement. Une image valant mieux qu'un long discours :

On peut donc voir qu'il reste donc encore des applications à packagées, il faut maintenir les packages existant (en les faisant évoluer pour que les applications installées sur une instance Yunohost soient mises à jour ou qu'une installation fraîche installe la dernière version de l'application...)

Si vous souhaitez aider, si vous avez un peu de temps ou tout simplement des retours d'expérience à faire, il y a un topic dédié dans le forum Yunohost sur le sujet.

Contribuez à Yunohost

D'une façon plus générale, Yunohost a besoin de contributeurs pour tous les aspects du projet. A savoir :
- backend : python (simple), bash (lua)
- frontend : html/js (sammy.js)
- packging des apps : full bash, et des connaissance en sysadmin sont nécessaires (configuration nginx)
- sécurité : revue de code
- infrastructure du projet : debian, deb toolchain, ruby
- relation avec la communauté : communication, support via le forum, dans les issues de Git...
- aide à la traduction et à la documentation
- testing (les versions beta) avec rapport de bugs
- ...

Gravatar de genma
Original post of genma.Votez pour ce billet sur Planet Libre.

Journal du hacker : Liens intéressants Journal du hacker semaine #37

Pour la 37ème semaine de 2017, voici 10 liens intéressants que vous avez peut-être ratés, relayés par le Journal du hacker, votre source d’informations pour le Logiciel Libre francophone !

Pour ne plus rater aucun article de la communauté francophone, voici :

De plus le site web du Journal du hacker est « adaptatif (responsive) ». N’hésitez pas à le consulter depuis votre smartphone ou votre tablette !

Le Journal du hacker fonctionne de manière collaborative, grâce à la participation de ses membres. Rejoignez-nous pour proposer vos contenus à partager avec la communauté du Logiciel Libre francophone et faire connaître vos projets !

Et vous ? Qu’avez-vous pensé de ces articles ? N’hésitez pas à réagir directement dans les commentaires de l’article sur le Journal du hacker ou bien dans les commentaires de ce billet :)

Gravatar de Journal du hacker
Original post of Journal du hacker.Votez pour ce billet sur Planet Libre.

Articles similaires

Renault : Bilan mensuel de la documentation francophone de Fedora-fr.org, numéro 2

Pour rappel, vous pouvez consulter l'état du travail en cours sur la documentation.

À cause des vacances et d'autres histoires personnelles, j'ai loupé le bilan d'août et j'ai moins contribué que la période juin-juillet. En cette rentrée, faisons quand même un bilan du travail abattu depuis deux mois.

Les sujets traités ont changé quelque peu. C'est plus centré autours des thématiques :

  • Les dépôts externes ;
  • La création de médias personnels et leur exploitation ;
  • L'usage serveur.

Personnellement je me suis occupé plutôt des deux premiers thèmes. Par exemple le dépôt de RPMFusion et les paquets multimédia qu'il propose sont un incontournable auprès des utilisateurs de Fedora. Il était important de s'y atteler car de nombreux paquets ont évolué, que ce soit des nouveaux venus, des évolutions majeures comme plus de codecs accessibles via mplayer ou GStreamer.

Concernant le deuxième point, il était nécessaire de revoir les procédures pour exploiter kickstart qui a évolué (notamment depuis l'apparition des Spins et des produits Server, Workstation et Cloud). Les moyens de télécharger Fedora ont changé, le Live CD a peu à peu laissé place au Live USB qui a été particulièrement mis en avant avec l'outil Fedora Media Writer. D'ailleurs l'installation d'un dual Boot avec Windows a aussi beaucoup évolué, car GRUB a changé avec sa version 2 ce qui a simplifié la procédure et Windows est aussi plus conciliant sur ce genre de cohabitation.

J'ai également rafraîchi la page d'aide pour contribuer à Fedora, car depuis le temps les sujets ont évolué, de nouvelles ressources ou secteurs ce sont développés comme l'assurance qualité et l'ajout aussi de la documentation francophone jusqu'ici absente.

Le dernier point a été particulièrement étudié par Nicolas, car Fedora a bien entendu un usage serveur important dont le paysage a changé. Outre MySQL devenu MariaDB, de nombreuses commandes ont changé avec l’évolution des outils. Si l’environnement web LAMP est surtout concerné, cela touche également SELinux, le serveur de courriel Dovecot et Openldap. Un énorme travail a été accomplis, donc merci à lui !

Je remercie également les autres contributeurs, relecteurs ou toute autres personnes qui se sont impliquées dans ce processus comme Édouard, Nicolas Chauvet, et d'autres.

Aujourd'hui donc, nous sommes à 42 articles traités, contre 25 au précédent bilan. Je suis satisfait des progrès réalisés sur la documentation. Il y a beaucoup de travail à mener encore, mais il semble possible que la documentation soit dans un état très acceptable d'ici Fedora 27 ou la fin de l'année 2017. Ensuite il faudra veiller à maintenir la documentation à jour continuellement et ajouter des articles suivant les besoins du moment.

Je vous invite en tout cas à nous donner un coup de main, pour cela je vous conseille de suivre la procédure pour contribuer à la documentation et si possible de participer à nos ateliers hebdomadaires tous les lundi soir à partir de 21h (heure de Paris) sur le canal IRC #fedora-doc-fr du serveur Freenode. Rien ne vous empêche de contribuer en dehors du cadre des ateliers, toute l'aide est la bienvenue. Alors, n'hésitez pas !

Gravatar de Renault
Original post of Renault.Votez pour ce billet sur Planet Libre.

Articles similaires

Renault : Petit bilan de Rawhide, épisode 5, septembre 2017

Je n'ai pas écrit de bilan de Rawhide en juin, juillet et août, l'approche de la version finale de Fedora 26 a amené trop peu de changements visibles pour que ce soit pertinent de les noter au départ puis j'ai manqué de temps pour traiter les avancées de Fedora 27.

Fedora 26 étant disponible depuis le 11 juillet, mon ordinateur personnel est repassé aussi tôt sur Fedora Rawhide qui est devenu il y a un mois Fedora 27 en devenir.

Fedora 27 Beta va d'ailleurs bientôt arriver, d'ici quelques semaines. Ce sera une première sans version Alpha préliminaire.

Changements

Dès le début GNOME 3.26 a des changements assez visibles. Je vous invite à lire les notes de versions pour plus de détails (et les illustrations). L'utilitaire gnome-tweak-tool a été remanié, les options sont plus nombreuses et le style de sélection ressemble à l'interface de GNOME Builder. Le centre de contrôle de GNOME a été également très modifié, avec une nouvelle organisation via cette barre latérale permanente et la refonte de nombreuses pages comme ce qui touche à l'affichage ou au réseau.

Je ne sais pas pourquoi mais la police par défaut de GNOME Terminal (police à chasse fixe) est Monospace Regular ce qui change bien entendu le rendu.

Quand les fenêtres dans GNOME sont rétrécies ou agrandies, il y a un nouvel effet visuel. Rien de sensationnel, mais c'est plutôt agréable sans pertes de performance dans la foulée j'ai l'impression. La barre de GNOME devient également transparente s'il n'y a pas de fenêtres maximisées.

Pendant quelques semaines, Empathy a également bénéficié de la refonte de son interface pour être plus homogène avec les autres applications GNOME en adoptant une interface proche de Polari. Mais cela était expérimental et l'interface habituelle a repli place. En espérant qu'il reviendra bientôt.

Et bien d'autres que je n'ai sans doute pas remarqué ou qui sont plus insignifiants.

Problèmes

Rawhide comporte bien évidemment de bogues. Même si des procédures doivent être mises en place durant ce cycle pour améliorer la qualité globale de cette branche de Fedora, des bogues importants resteront probablement présents.

En premier lieu, mon système de fichier /home chiffré avec LUKS n'était plus monté automatiquement. C'est plutôt gênant, on doit le faire à la main mais heureusement sans autres conséquences notamment en terme de cohérence des données. Heureusement corrigé depuis.

Un autre bogue, assez pénible, le sélecteur de fichier de GTK crashe. Donc dès qu'il faut choisir / ajouter un fichier dans un programme, l'application plante. Cela a été corrigé avant que je n'en fasse un rapport.

Firefox 55 a été oublié des mises à jour des paquets, à la base suite à des soucis pour le compiler puis par oubli du mainteneur. :-)

Sinon GNOME est très instable. La session se ferme régulièrement (toutes les heures presque) voire à certains moment comme à l'ouverture d'une machine virtuelle. Beaucoup de rapports de bogues tournent autours de ce sujet. Il semble que le composant gjs soit le fautif et une correction semble en cours. C'est rare que GNOME soit autant en difficulté et étant donné l'importance du sujet Fedora bloque l'évolution du cycle de F27 le temps que cela se calme.

Gravatar de Renault
Original post of Renault.Votez pour ce billet sur Planet Libre.

Articles similaires

Cenwen : Remplacer avantageusement Shutter par HotShots

Fervent utilisateur de Shutter depuis de nombreuses années, je me suis retrouvé sans logiciel de capture d’écran il y a quelques mois. En effet, le projet n’ayant pas eu de maj depuis au moins 2 ans (cela a été fait récemment) et les bureaux et librairies graphiques ou pas évoluant durant ce laps de temps, il m’a été impossible de lancer le logiciel après une maj de Manjaro. Cela ne sentait pas bon pour l’avenir , vu que cette distribution en rolling-release est à la pointe des dernières versions en tout genre, que ce soit pour l’environnement ou bien pour les librairies. Bref, il fallait que je trouve une solution. Mon choix s’est alors porté sur HotShots, écrit en C++ et QT4 .

Hum HotShots. Est-ce que cela se mange ?

Traduit en 21 langues, Hotshots permet de réaliser des captures d’écrans dans différents formats et de leurs appliquer des modifications diverses, le plus facilement du monde.

Les caractéristiques principales de cet outil sont :

  • capturer tout l’écran, tous les écrans (si vous en avez plusieurs), une portion de l’écran, une fenêtre, une zone à main levée
  • exportation de l’image dans les formats png, tiff, tif, jpg, jpeg, gif, svg, pgm, ppm, ico, bmp, mng, pbm, svgz, xbm, xpm
  • définition du délai de la capture (pas ou selon votre choix)
  • définition de l’action à réaliser sur l’image capturée (sauvegarde automatique, sauvegarde de l’image à la demande de l’utilisateur, ouvrir directement l’éditeur, ne rien faire)
  • imprimer directement l’image que ce soit dans le logiciel ou bien dans l’éditeur
  • démarrer automatiquement ou non le logiciel au démarrage système
  • minimiser l’application dans le systray
  • application directe d’un filtre de type ombre portée simple, ombre portée avec bordures, opacité progressive, bords déchirés
  • mise à l’échelle de l’image
  • exportation automatique ou non de l’image vers un serveur FTP, un service d’hébergement d’images en ligne (FreeImageHosting.net, ImageShack.us, Imgur.com, CanardPC) ou bien sur votre disque dur avec ou pas de proxy

 

Comment l’installer ?

Comme d’habitude sous Linux, vous avez le choix pour installer et tester ce logiciel. Soit vous utilisez votre gestionnaire de paquets comme Octopi, Pacmac, Synaptic, Linux Mint Software Center, Ubuntu Software Center, …. , soit en ligne de commande.

Vu que pour Archlinux et dérivées dont Manjaro, le logiciel est disponible sur AUR, la ligne de commande sera :

yaourt -S hotshots

Si vous êtes sur Ubuntu et dérivés dont Linux Mint, la commande sera la suivante :

sudo apt-get install hotshots

 

Présentation rapide de l’interface

L’interface dispose de 3 zones principales.

Tout en haut, vous avez la barre d’outils qui permet un accès rapide aux principales fonctionnalités du logiciel, à savoir :

  • Quitter l’application
  • A propos de l’application elle-même (version, traductions, remerciements, actions faites pour cette version et les précédentes, licence, …)
  • Ouverture des préférences
  • Sauvegarder l’image (à la demande de l’utilisateur)
  • Télécharger l’image sur le web
  • Imprimer directement l’image
  • Copier vers le presse-papier
  • Ouvrir l’éditeur et annoter, modifier l’image
  • Capturer l’écran courant
  • Capturer tous les écrans
  • Capturer une fenêtre
  • Capturer une région
  • Capturer une région à main levée

Au centre se situe la deuxième zone, qui est en fait la zone d’affichage de l’image.

En bas, se trouve la troisième et dernière zone dans laquelle vous trouverez les paramètres principaux de l’image. Cette zone est elle-même découpée en deux parties. A gauche vous pouvez reprendre le même cliché (pratique quand vous capturer une région). Quant à celle de droite, vous pouvez définir le répertoire de sortie, le mode de capture, le délai de la capture, l’action à réaliser après la capture.

L’éditeur d’écran est quant à lui découpé en quatre zones.

On retrouve tout en haut la fameuse barre d’outils qui permet là aussi un accès rapide aux fonctions essentielles bien que celle-ci soit un peu plus étoffée en fonctionnalités que celle de l’interface principale. Nous retrouvons de gauche à droite :

  • Quitter l’éditeur
  • Ouvrir un fichier
  • Créer un nouveau document
  • Importer une image du presse papier
  • Sauvegarder l’édition actuelle
  • Sauvegarder sous l’édition actuelle
  • Copier vers le presse papier
  • Exporter l’image
  • Télécharger l’image sur le web
  • Imprimer l’image
  • Ajuster à la fenêtre
  • Réinitialiser l’échelle
  • Annuler la dernière action
  • Restaurer la dernière action
  • Ajouter un effet à l’image de fond
  • Retailler l’image de fond
  • Appliquer un alignement à un groupe d’images
  • Afficher/Cacher l’ombrage des éléments
  • Mettre les éléments sélectionnés au dessus
  • Mettre les éléments sélectionnés en haut
  • Mettre les éléments sélectionnés en dessous
  • Mettre les éléments sélectionnés en bas
  • Dupliquer l’élément courant
  • Effacer tous les éléments
  • Supprimer les éléments sélectionnés

Au centre, se trouve la seconde zone qui correspond à l’image ouverte.

A sa gauche, verticalement, nous retrouvons une autre barre d’outils fort intéressante. Celle-ci comporte des outils de dessin basiques qui sont les suivants:

  • Sélectionner
  • Écrire un texte
  • Tracer une ligne
  • Entourer
  • Tracer une polyligne
  • Tracer un polygone
  • Dessiner une courbe
  • Couper l’image de fond
  • Tracer un rectangle
  • Tracer une ellipse
  • Tracer une flèche
  • Tracer une balise
  • Mettre en évidence
  • Loupe
  • Ajouter une image
  • Mettre un flou
  • Décroître la taille de la police
  • Accroître la taille de la police
  • Réinitialiser les couleurs
  • Inverser les couleurs
  • Couleurs de premier et d’arrière plan
  • Une série de lignes de différentes tailles et styles

Enfin, la dernière zone interagit avec les deux derniers points de la précédente. D’un clic, vous modifier la couleur de celles-ci avec le choix que vous venez de sélectionner dans la quatrième zone.

Un dernier mot

Comme vous avez pu le constater tout au long de cet article, HotShots est un outil qui vaut le détour et qui a sa place au sein de votre bureau. Certes, j’ai pu noter quelques désagréments mineurs différents selon la distribution utilisée avec toutefois le même environnement. Sur Manjaro, les icônes des actions réalisables dans le systray ne sont pas affichées contrairement à Linux Mint. A l’inverse, l’icône de l’application ne s’affiche nulle part que ce soit dans le menu ou bien quand l’application est ouverte sur Mint. Ce sont cependant des remarques mineurs, n’empêchant nullement l’utilisation journalière de l’application avec une efficacité redoutable.

Un dernier mot avant de finir cet article, concerne l’éditeur de capture d’écran. Cet outil est à lui seul une application entière de dessin. Toutefois, il répond efficacement à l’essentiel et même plus. Une documentation expliquant les diverses fonctionnalités de ces outils serait le bienvenue car certains sont un peu obscurs à l’usage.


Classé dans:Découverte, Logiciels, News, Planet-Libre Tagged: C++, Dessin, Hotshots, Image, Linux, Logiciels

Gravatar de Cenwen
Original post of Cenwen.Votez pour ce billet sur Planet Libre.

Articles similaires

Full Circle Magazine FR : Pour la rentrée

Bonjour !

Aujourd'hui, à peine deux semaines après la sortie du numéro en anglais, l'équipe française est heureuse de vous présenter ce numéro 124,du mois d'août 2017, en français. Il peut être téléchargé ou visionné sur notre page NUMÉROS ou téléchargé directement en cliquant sur la photo de couverture ci-dessous.

issue124fr.png

Bien que les numéros deviennent de plus en plus courts, vous y trouverez notamment :

  • tous les tutoriels habituels PLUS un sur des sauvegardes avec les instantanés ZFS ;
  • le début d'une courte série par Charles McColm sur sa configuration KODI (dans la rubrique Le coin KODI) ;
  • et de nouveaux bureaux à admirer !

N'hésitez pas à envoyer vos propres articles, critiques, tutoriels, opinions ou histoires, etc., en anglais, à Ronnie@fullcirclemagazine.org, car sans les articles des lecteurs, la revue ne pourra pas exister. Au besoin, et si votre prose n'est pas trop long, on se fera un plaisir de le traduire du français en anglais (webmaster@fullcirclemag.fr).

En attendant, bonne lecture !

  • Bab, scribeur et relecteur
  • d52fr, traducteur et relecteur
  • AuntieE, traductrice et relectrice

Gravatar de Full Circle Magazine FR
Original post of Full Circle Magazine FR.Votez pour ce billet sur Planet Libre.

Articles similaires

OLPC France : Une plateforme de traduction pour Sugarizer

Et si Sugarizer  – un goût de Sugar sur n’importe quelle machine  – pouvait être disponible dans votre langue ?

Pour faciliter les efforts de traduction de la communauté, nous avons unifié tous les fichiers sources à traduire pour Sugarizer (Sugarizer core, le site web Sugarizer website, les activités incluses et le future  Sugarizer Server dashboard) dans une nouvelle plate-forme:

http://translate.sugarizer.org

Cliquez simplement sur cette URL et vous pourrez démarrer la traduction:

  • Suggérez une nouvelle traduction sans même avoir besoin de vous connecter
  • Enregistrez-vous pour démarrer la traduction sur une nouvelle langue ou valider des traductions

Grâce à Weblate l’outil utiliser pour cette plateforme, toutes les nouvelles traductions seront intégrés dans les dépôts correspondants sans autres actions de votre part.

N’hésitez pas à nous solliciter pour toutes questions ou problèmes.

Gravatar de OLPC France
Original post of OLPC France.Votez pour ce billet sur Planet Libre.

Articles similaires

Marthym : Hello OSGi World, Part 4, Injection de dépendances

Quelles sont donc les raisons d’utiliser OSGi ? On en a vu plusieurs jusqu’ici :

  • Isolation des classpath par bundle
  • Chargement et mise à jour des bundles à chaud

Mais OSGi c’est aussi et surtout un framework d’injection de dépendances. Comme pour tout dans l’univers OSGi, l’injection est une spécification et il existe plusieurs implémentations comme iPOJO ou Declarative Service. On ne verra pas iPOJO parce que je suis pas fan et j’ai plus l’habitude d’utiliser DS.

Declarative Service

DS permet de déclarer des composants et des services qui s’injectent les uns les autres. Initialement tout doit être déclaré dans des XML et dans le MANIFEST.MF, encore un truc bien fastidieux ! Heureusement, SCR vient à notre secours et permet de faire tout ça via des annotations ce qui rend la chose plus sympa et plus “actuelle”.

Ajoutons donc les dépendances nécessaires au projet:

org.apache.felix org.apache.felix.scr ${felix-scr.version} org.osgi osgi.cmpn ${osgi.core.version} provided
  • osgi.cmpn pour les annotations. C’est une dépendance de compilation uniquement, on ne la veut pas dans le package final. Si vous la laissé, au lancement vous aurez une erreur assez parlante. À déclarer dans how-rest.
  • org.apache.felix.scr c’est l’implémentation runtime uniquement qui gère les composants au runtime. À déclarer dans how-assembly
Création de composants

Voici à quoi ressemble un composant

import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component(name = "http-server", immediate = true) public final class HttpServerComponent { private static final Logger LOGGER = LoggerFactory.getLogger(HttpServerComponent.class); @Activate private void startHttpServer() { LOGGER.info("HTTP Server started on port {}", 8888); } }

C’est l’annotation @Component qui définit un composant. name détermine le nom du composant, l’information n’est pas obligatoire, si absente le composant aura le nom de la classe. immediate permet de dire que le composant doit être instancié dès que le bundle est activé, sans ça le composant ne sera instancié que quand il sera nécessaire. Comme aucun autre composant ne dépend du nôtre, si on ne le met pas immédiate, on ne verra rien.

L’annotation @Activate détermine la méthode qui sera exécutée lors de l’activation du composant. Ici on se limite à un log pour vérifier que cela fonctionne.

Et un coup de mvn clean package puis on lance l’application et …

____________________________ Welcome to Apache Felix Gogo g! 21:43:51.533 [fileinstall-application] INFO fr.ght1pc9kc.how.HowActivator - HOW is now Activated ! 21:43:51.554 [fileinstall-application] INFO fr.ght1pc9kc.how.HttpServerComponent - HTTP Server started on port 8888

On voit bien les deux messages. Et à ce moment vous vous dites “merde mais l’activateur ça sert du coup ?”. Ben en fait non, SCR instancie les composant et exécute les méthodes @Activate du coup c’est plus très utile. Après c’est quand même pas la même chose, l’activateur agit au niveau bundle alors que @Activate agit au niveau composant.

Bref on peut supprimer l’activateur et la toutes section du pom de how-rest qui devient elle aussi inutile. Dans le jar maintenant, au même niveau que META-INT on trouve OSGI-INF qui contient les déclarations XML des composants que le maven-bundle-plugin a généré pour nous.

Gogo gadgeto composant

Jetons un œil coté gogo shell, un coup de help montre une nouvelle série de commandes, les scr:. Essayez scr:list :

g! scr:list BundleId Component Name Default State Component Id State PIDs (Factory PID) [ 9] http-server enabled [ 0] [active ] g!

Pour chaque bundle, cette commande liste les composants et leur état. C’est très utile si un composant ne s’active pas, pour savoir ce qu’il lui manque, quelles dépendances ne sont pas satisfaites par exemple.

Dis Bonjour !

Ben oui on a fait plein de trucs mais on a toujours pas notre Hello World. Maintenant que la machinerie est en place on peut lancer un serveur HTTP à l’activation de notre composant http-server :

@Activate private void startHttpServer() { Undertow server = Undertow.builder() .addHttpListener(HTTP_PORT, "localhost") .setHandler(exchange -> { exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain"); exchange.getResponseSender().send("Hello OSGi World"); }).build(); server.start(); LOGGER.info("HTTP Server started on port {}", HTTP_PORT); }

J’ai pris un serveur Undertow parce qu’il est rapide simple, non-bloquant (killer feature dans notre cas !) et en prime il est compatible OSGi.

Je vous laisse voir les poms pour la liste des imports.

Il ne reste plus qu’à relancer l’application pour voir si ça fonctionne.

Ordre et dépendances ERROR: [http-server(0)] The startHttpServer method has thrown an exception java.lang.IllegalArgumentException: XNIO001001: No XNIO provider found at org.xnio.Xnio.doGetInstance(Xnio.java:270) at org.xnio.Xnio.getInstance(Xnio.java:187) at io.undertow.Undertow.start(Undertow.java:114) at fr.ght1pc9kc.how.HttpServerComponent.startHttpServer(HttpServerComponent.java:23) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.felix.scr.impl.inject.BaseMethod.invokeMethod(BaseMethod.java:229) at org.apache.felix.scr.impl.inject.BaseMethod.access$500(BaseMethod.java:39) at org.apache.felix.scr.impl.inject.BaseMethod$Resolved.invoke(BaseMethod.java:650) at org.apache.felix.scr.impl.inject.BaseMethod.invoke(BaseMethod.java:506) at org.apache.felix.scr.impl.inject.ActivateMethod.invoke(ActivateMethod.java:307) at org.apache.felix.scr.impl.inject.ActivateMethod.invoke(ActivateMethod.java:299)

Voilà un autre inconvénient d’OSGi, l’ordre de chargement des bundles compte. La plupart du temps, les bundles dépendent les uns des autres et le framwork les résous en chargeant les bundles dans l’ordre. Mais là on a un bundle xnio.nio qui est une implémentation, personne ne dépend de lui. Mais tant qu’il n’est pas là le serveur Undertow ne peut être lancé. Mais comme personne ne dépend ni de xnio.nio ni de how-rest les deux bundles sont chargés par ordre alphabétique et l’activation de how-rest est déclenché avant que xnio.nio ne soit disponible.

Solution:

En regardant dans le code d’Undertow ou dans la documentation, on voit que Undertow, pour être lancé, a besoin d’une instance de Xnio. Comme c’est souvent le cas dans les modules standard qui “supportent” OSGi, la façon dont Xnio génère son instance et la façon dont Undertow en dépend ne permet pas d’éviter ce souci. Du coup c’est à nous de le gérer. Le plus simple pour ça est d’expliquer à OSGi que le module http-server ne peut être activé tant qu’il n’existe pas une instance accessible de Xnio. On ajoute la dépendance comme suit :

@Reference private void waitForXnio(Xnio xnio) { LOGGER.debug("XNIO Implementation found: {}", xnio); }

C’est l’annotation @Reference qui indique à Felix que le composant à besoin d’une instance de Xnio.

On rebuild l’application et ça démarre correctement ! Rendez-vous sur la page http://localhost:8080/ pour y voir s’affiche le message de bienvenue.

Le felix-cache

Il reste cependant encore un souci, si l’on stoppe (CTRL^C) et que l’on relance, on prend à nouveau cette erreur. C’est lié au cache que Felix génère. J’ignore pourquoi mais un chargement depuis le cache provoque la même erreur. Pour palier ce souci, on demande à Felix de recharger son cache à chaque démarrage. Dans le fichier de configuration Felix on ajoute la ligne:

org.osgi.framework.storage.clean=onFirstInit Dépendances Multiples

Pour finir, modifions un peu l’application pour la rendre plus dynamique. L’idée de faire en sorte que le serveur découvre les nouvelles route dynamiquement.

Pour cela, on crée une interface Route comme suit :

public interface Route extends HttpHandler { String getRoute(); }

Et dans le composant HTTP on ajoute une dépendance MULTIPLE à Route

@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC) private void addHttpHandler(Route handler) { routingHandler.get(handler.getRoute(), handler); } private void removeHttpHandler(Route handler) { routingHandler.remove(handler.getRoute()); }

Ainsi chaque Route qui apparaîtra dans les bundles installé viendra s’ajouter à celle existantes. La présence d’une méthode removeHttpHandler est obligatoire pour packager le bundle. BND utilise le nom pour trouver la bonne méthode.

Une route ressemble à ça :

@Component public class HelloWorldRoute implements Route { @Override public void handleRequest(HttpServerExchange exchange) throws Exception { exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain"); exchange.getResponseSender().send("Hello OSGi World"); } @Override public String getRoute() { return "/hello"; } }

Si vous compilez les sources 4.0 il y a 2 routes, /hello et /bonjour.

C’est un exemple simple pour illustré les dépendances multiples, mais il est possible de faire beaucoup mieux, des Controllers avec l’API JAX-RS.

Next

Donc voilà, on a vu comment OSGi gère les dépendances. La prochaine fois on verra les Fragments Bundles, à quoi ça sert et comment on fait ça.

Hello OSGi World, Part 4, Injection de dépendances écrit à l'origine par Marthym pour J'ai acheté un PC neuf cassé ... le September 16, 2017.

Gravatar de Marthym
Original post of Marthym.Votez pour ce billet sur Planet Libre.

elementary OS : Les vacances sont terminées : elementary OS continue son évolution

Septembre sonne la fin des vacances d’été et la rentrée pour bon nombre d’entre nous, la team elementary OS n’a pour autant pas chômé : pendant les vacances d’été, l’équipe de Daniel a pu travailler de concert avec l’équipe de System76 pour faire évoluer l’Installateur d’elementary OS !

Le mois d’août a vu toutefois aussi de nombreuses mises à jour apparaître :

AppCenter

Cassidy a pu apporter quelques modifications graphiques sur la fenêtre de paiement de l’AppCenter, le titre ainsi que la description sont maintenant plus visibles :

 le titre d'une fenêtre est mis en valeur

 

Autre modification qui se voit greffer à AppCenter, l’ajout d’une liste noire qui intègre par exemple certains composants systèmes et outils hérités d’Ubuntu, mais qui ne fonctionnent pas sur elementary OS. Cette liste noire est accessible ici.

Un correctif a été aussi réalisé sur la gestion des URL de type appstream://,dans certaines conditions, vous pouviez être bloqués sur la fenêtre des mises à jour.

Look & Feel

Grâce à de nombreux retours faits sur GitHub, l’équipe de Daniel a pu augmenter le contraste des couleurs au niveau des sidebars de vos applications pour supporter les règles d’accessibilité des contenus web : le standard WCAG. Notre feuille de style intègre maintenant la classe .monospace pour le support des polices de caractères monospaced sur un widget. Autre point d’attention, lorsqu’une fenêtre est maintenant maximisée : les bords arrondis sont affichés en lieu et place de bord carré.

Coins arrondis

Si vous suivez de manière assidue le développement d’elementary OS depuis un autre système d’exploitation Open Source, vous serez ravis d’apprendre que la dernière version de notre feuille de style incorpore de nombreux correctifs de compatibilités pour Gtk+ ≥ 3.20. Ce travaille et ces correctifs seront intégrés dans la prochaine version majeure d’elementary OS. Cela inclut le changement de nombreux sélecteurs CSS vers de nouveaux noms(actionbarinstead en lieu et place de .action-bar ou GtkActionBar) ainsi que le support de nouvelles classes dont par exemple keycap.

L’indicateur Bluetooth se voit aussi mis à jour au travers d’un correctif qui corrige l’affichage en double les équipements Bluetooth. Un autre correctif s’est vu intégré qui corrige le comportement du séparateur de menu qui pouvait être déplacé avec la liste de périphériques.

Pour l’indicateur de Notification, la présence de texte long de notification se voit maintenant tronquée. Un autre fix s’est vu aussi intégré : celui-ci vient corriger le comportement de certaines fenêtres qui n’étaient pas minimisées lors d’un clic dans la zone de notification adéquate.

Un peu de nettoyage ainsi que quelques corrections d’ordre graphiques ont été apportés à l’indicateur de Session.

Mail

Mail se voit maintenant doter d’un bouton permettant l’ajout d’image directement dans le corps du mail ! Autre soucis maintenant corrigé, lors d’un clic sur un lien issu d’un lien dans un mail, il n’y aura plus de défilement involontaire.

FastMail a effectué un déplacement de leurs serveurs récemment, l’équipe a donc mis à jour le paramétrage des Comptes en ligne pour pointer vers leur nouvelle adresse.

Dans certains cas, lorsque Vidéo détecté la pression sur la barre d’espace, il pouvait interpréter cela comme une double pression sur cette même touche. La calculatrice se voit aussi mise à jour avec une amélioration de la gestion des décimales ainsi qu’un correctif qui empêche maintenant l’affiche du résultat -0.

Le billet Les vacances sont terminées : elementary OS continue son évolution a été publié sur le site de la elementary OS -

Gravatar de elementary OS
Original post of elementary OS.Votez pour ce billet sur Planet Libre.

Articles similaires

Morot : Puppet : automatiser la construction d’un volume GlusterFS répliqué

Puppet : automatiser la construction d’un volume GlusterFS répliqué

Je vais présenter rapidement comment créer le code Puppet adapté à la création d’un cluster à deux noeuds avec deux bricks répliqués. Pour la démonstration, j’aurais deux VM Ubuntu 16.04 et les bricks seront sur deux disques durs de 8 Go.

Préparation du Puppet Master

Installation des modules nécessaires :

# puppet module install puppetlabs-lvm Notice: Preparing to install into /etc/puppetlabs/code/environments/production/modules ... Notice: Downloading from https://forgeapi.puppet.com ... Notice: Installing -- do not interrupt ... /etc/puppetlabs/code/environments/production/modules └─┬ puppetlabs-lvm (v0.9.0) └── puppetlabs-stdlib (v4.20.0) # puppet module install puppet-gluster Notice: Preparing to install into /etc/puppetlabs/code/environments/production/modules ... Notice: Downloading from https://forgeapi.puppet.com ... Notice: Installing -- do not interrupt ... /etc/puppetlabs/code/environments/production/modules └─┬ puppet-gluster (v3.0.0) └─┬ puppetlabs-apt (v2.4.0) └── puppetlabs-stdlib (v4.20.0)

Notre arborescence pour le module se trouvera dans ce répertoire :

# mkdir -p /etc/puppetlabs/code/environments/production/modules/glustersrv/manifests   Préparation des disques Fichier /etc/puppetlabs/code/environments/production/modules/glustersrv/manifests/lvm.pp : class glustersrv::brick { # Dépendances : package { "xfsprogs": ensure=> present } package { "lvm2": ensure=> present } # On créé notre LVM : physical_volume { '/dev/sdb': ensure => present, } volume_group { 'vg-gluster': ensure => present, physical_volumes => '/dev/sdb', } logical_volume { 'lv-bricks': ensure => present, volume_group => 'vg-gluster', size => '7.9G', } filesystem { '/dev/vg-gluster/lv-bricks': ensure => present, fs_type => 'xfs', } # Le volume LVM est automatiquement monté mount { '/data/glusterfs/vol0': name => '/data/glusterfs/vol0', ensure => 'mounted', atboot => 'true', device => '/dev/vg-gluster/lv-bricks', fstype => 'xfs', options => 'defaults', dump => 1, pass => 0, } } Création du volume répliqué

Fichier /etc/puppetlabs/code/environments/production/modules/glustersrv/manifests/node.pp :

class glustersrv::node { file { '/data/glusterfs/vol0/brick0': ensure => 'directory', } package { "glusterfs-server": ensure => 'present' } service { 'glusterfs-server': ensure => running, enable => true, hasrestart => true, } gluster::volume { 'repl-vol': replica => 2, bricks => [ 'gluster0.morot.test:/data/glusterfs/vol0/brick0', 'gluster1.morot.test:/data/glusterfs/vol0/brick0', ], } } Affectation des classes

Fichier /etc/puppetlabs/code/environments/production/manifests/site.pp :

node 'gluster0' { include system include glustersrv::lvm gluster::peer { 'gluster1.morot.test': pool => 'production', } include glustersrv::node } node 'gluster1' { include system include glustersrv::lvm gluster::peer { 'gluster0.morot.test': pool => 'production', } include glustersrv::node } On vérifie root@gluster1:~# gluster volume status Status of volume: repl-vol Gluster process TCP Port RDMA Port Online Pid ------------------------------------------------------------------------------ Brick gluster0.morot.test:/data/glusterfs/v ol0/brick0 49152 0 Y 7037 Brick gluster1.morot.test:/data/glusterfs/v ol0/brick0 49152 0 Y 3817 NFS Server on localhost N/A N/A N N/A Self-heal Daemon on localhost N/A N/A Y 3844 NFS Server on 192.168.69.70 N/A N/A N N/A Self-heal Daemon on 192.168.69.70 N/A N/A Y 7063 Task Status of Volume repl-vol ------------------------------------------------------------------------------ There are no active volume tasks

Gravatar de Morot
Original post of Morot.Votez pour ce billet sur Planet Libre.

Articles similaires

blog-libre : sshrc, utiliser vos fichiers de configuration dans des sessions SSH

sshrc apporte une réponse à 2 problématiques :

  • Vous souhaitez pouvoir utiliser votre configuration locale aux petits oignons (alias, fonctions, variables d’environnement, bashrc, vimrc, inputrc, screenrc, etc.) lorsque vous êtes connectés sur les pc/serveurs que vous administrez. Cependant vous désirez ne pas toucher aux fichiers de configuration de ces pc/serveurs car vous ne pouvez pas (contexte professionnel) ou vous ne voulez pas. De plus plusieurs personnes se connectent au(x) même(s) compte(s), il faut respecter l’usage de chacun et ne pas imposer vos fichiers de configuration aux autres
  • Au contraire vous avez décidé d’utiliser vos fichiers de configuration (aussi appelés dotfiles) mais passer sur X pc/serveurs pour modifier un de vos fichiers de configuration ça vous gonfle et vous trouvez la gestion de configuration (Ansible, Puppet, Git + liens symboliques…) trop lourde pour si peu

Alors sshrc est fait pour vous. Sur votre poste vous allez créer un fichier ~/.sshrc dans lequel vous allez exporter/sourcer votre configuration personnalisée et un dossier ~./sshrc.d où vous allez placer vos fichiers de configuration (.bashrc, .vimrc, .inputrc, etc.). Au lieu de vous connecter sur ces pc/serveurs avec la commande ssh, vous allez vous connecter avec la commande sshrc (no stress c’est propre). Un dossier /tmp/.cascador.sshrc.XXXX unique (XXXX généré aléatoirement) sera créé sur l’hôte distant, votre configuration personnalisée sera envoyée dedans (avec openssl) puis chargée. A la déconnexion ce dossier sera supprimé.

sshrc est un script shell sous licence MIT aisément maintenable, compréhensible et lisible. Il nécessite comme prérequis openssl sur l’hôte local et distant. Il existe également moshrc pour Mosh. Voici le code source.

#!/usr/bin/env bash function sshrc() { local SSHHOME=${SSHHOME:=~} if [ -f $SSHHOME/.sshrc ]; then local files=.sshrc if [ -d $SSHHOME/.sshrc.d ]; then files="$files .sshrc.d" fi SIZE=$(tar cfz - -h -C $SSHHOME $files | wc -c) if [ $SIZE -gt 65536 ]; then echo >&2 $'.sshrc.d and .sshrc files must be less than 64kb\\ncurrent size: '$SIZE' bytes' exit 1 fi if [ -z "$CMDARG" -a ! -e ~/.sshrc.d/.hushlogin ]; then WELCOME_MSG=" if [ ! -e ~/.hushlogin ]; then if [ -e /etc/motd ]; then cat /etc/motd; fi if [ -e /etc/update-motd.d ]; then run-parts /etc/update-motd.d/ 2>/dev/null; fi last -F \\$USER 2>/dev/null | grep -v 'still logged in' | head -n1 | awk '{print \\"Last login:\\",\\$4,\\$5,\\$6,\\$7,\\$8,\\"from\\",\\$3;}' fi " else WELCOME_MSG="" fi ssh -t "$DOMAIN" $SSHARGS " command -v openssl >/dev/null 2>&1 || { echo >&2 \\"sshrc requires openssl to be installed on the server, but it's not. Aborting.\\"; exit 1; } $WELCOME_MSG export SSHHOME=\\$(mktemp -d -t .$(whoami).sshrc.XXXX) export SSHRCCLEANUP=\\$SSHHOME trap \\"rm -rf \\$SSHRCCLEANUP; exit\\" 0 echo $'"$(cat "$0" | openssl enc -base64)"' | tr -s ' ' $'\\n' | openssl enc -base64 -d > \\$SSHHOME/sshrc chmod +x \\$SSHHOME/sshrc echo $'"$( cat << 'EOF' | openssl enc -base64 if [ -r /etc/profile ]; then source /etc/profile; fi if [ -r ~/.bash_profile ]; then source ~/.bash_profile elif [ -r ~/.bash_login ]; then source ~/.bash_login elif [ -r ~/.profile ]; then source ~/.profile fi export PATH=$PATH:$SSHHOME source $SSHHOME/.sshrc; EOF )"' | tr -s ' ' $'\\n' | openssl enc -base64 -d > \\$SSHHOME/sshrc.bashrc echo $'"$( cat << 'EOF' | openssl enc -base64 #!/usr/bin/env bash exec bash --rcfile <(echo ' [ -r /etc/profile ] && source /etc/profile if [ -r ~/.bash_profile ]; then source ~/.bash_profile elif [ -r ~/.bash_login ]; then source ~/.bash_login elif [ -r ~/.profile ]; then source ~/.profile fi source '$SSHHOME'/.sshrc; export PATH=$PATH:'$SSHHOME' ') "$@" EOF )"' | tr -s ' ' $'\\n' | openssl enc -base64 -d > \\$SSHHOME/bashsshrc chmod +x \\$SSHHOME/bashsshrc echo $'"$(tar czf - -h -C $SSHHOME $files | openssl enc -base64)"' | tr -s ' ' $'\\n' | openssl enc -base64 -d | tar mxzf - -C \\$SSHHOME export SSHHOME=\\$SSHHOME echo \\"$CMDARG\\" >> \\$SSHHOME/sshrc.bashrc bash --rcfile \\$SSHHOME/sshrc.bashrc " else echo "No such file: $SSHHOME/.sshrc" >&2 exit 1 fi } function sshrc_parse() { while [[ -n $1 ]]; do case $1 in -b | -c | -D | -E | -e | -F | -I | -i | -L | -l | -m | -O | -o | -p | -Q | -R | -S | -W | -w ) SSHARGS="$SSHARGS $1 $2"; shift ;; -* ) SSHARGS="$SSHARGS $1" ;; *) if [ -z "$DOMAIN" ]; then DOMAIN="$1" else local SEMICOLON=$([[ "$@" = *[![:space:]]* ]] && echo '; ') CMDARG="$@$SEMICOLON exit" return; fi ;; esac shift done if [ -z $DOMAIN ]; then ssh $SSHARGS; exit 1; fi } command -v openssl >/dev/null 2>&1 || { echo >&2 "sshrc requires openssl to be installed locally, but it's not. Aborting."; exit 1; } sshrc_parse "$@" sshrc

Prise en main

On ne s’embête pas avec Git, on se contente de copier sshrc et le placer dans /usr/local/bin.

wget https://raw.githubusercontent.com/Russell91/sshrc/master/sshrc && chmod +x sshrc && sudo mv sshrc /usr/local/bin/ touch ~/.sshrc && mkdir -p ~/.sshrc.d

Voici mon fichier ~/.sshrc actuel. Dans le dossier ~/.sshrc.d j’ai mes .bashrc, .inputrc, .vimrc.

export EDITOR=vim export INPUTRC=$SSHHOME/.sshrc.d/.inputrc export LESS='-FRXi' export LESS_TERMCAP_mb=$'\\E[01;31m' export LESS_TERMCAP_md=$'\\E[01;31m' export LESS_TERMCAP_me=$'\\E[0m' export LESS_TERMCAP_so=$'\\E[01;44;33m' export LESS_TERMCAP_se=$'\\E[0m' export LESS_TERMCAP_us=$'\\E[01;32m' export LESS_TERMCAP_ue=$'\\E[0m' export VIMINIT="let \\$MYVIMRC='$SSHHOME/.sshrc.d/.vimrc' | source \\$MYVIMRC" source $SSHHOME/.sshrc.d/.bashrc if [[ -f ${SSHHOME}/.sshrc.d/.bash_aliases ]]; then source ${SSHHOME}/.sshrc.d/.bash_aliases ; fi if [[ -f ${SSHHOME}/.sshrc.d/.bash_functions ]]; then source ${SSHHOME}/.sshrc.d/.bash_functions ; fi

On se connecte ensuite à un serveur comme ceci sshrc root@blog-libre.org. Pour retrouver le répertoire sshrc echo $SSHHOME et s’y déplacer cd $SSHHOME; ls -a.

Je vous invite à taper « dotfile sshrc » dans votre moteur de recherche préféré pour avoir d’autres exemples : 1, 2, 3, 4, 5.

Deux points négatifs

Il n’est pas possible d’envoyer plus de 64 Ko de fichiers de configuration compressés avec sshrc. Première réaction la peur puis après quelques tests, j’arrive à passer 1 Mo sans problème, le mot important à retenir : compressés. Cependant ça reste un problème important pour certains, on peut citer les plugins Vim par exemple. Dans ce cas l’auteur conseille de copier les fichiers dans un obscur dossier sur le serveur et d’utiliser sshrc pour automatiquement sourcer ces configurations au login.

On a vu que sshrc était bien conçu et propre, il crée un dossier /tmp/.cascador.sshrc.XXXX unique qu’il supprime à la déconnexion. Cependant pour certains cas, vous serez obligés de « sortir » de ce dossier. Pour nano il n’est pas possible d’exporter un fichier de configuration, il lit seulement /etc/nanorc et ~/.nanorc, il ne possède pas d’option permettant de préciser où se situe (ailleurs) nanorc. On est donc obligé d’aller placer .nanorc dans ~/. Certains font une copie, d’autres créent un lien symbolique, c’est plus propre. Il faut gérer la suppression de ce fichier (on peut modifier trap \\"rm -rf \\$SSHRCCLEANUP; exit\\" 0 entre autres solutions) mais si une autre personne se connecte sous le même compte que vous, il va charger ce fichier de configuration… et puis vous touchez aux fichiers de configuration du pc/serveur (/root/.nanorc pourrait déjà exister par exemple).

Quelques conseils

N’oubliez pas que les fichiers de configuration de votre pc sont probablement différents de ceux de vos serveurs. Typiquement je suis sur Xubuntu et j’administre des serveurs Debian, les versions des paquets sont différentes, les fichiers de configuration également. Je vous invite à copier les fichiers de configuration à partir de vos serveurs dans ~/.sshrc.d puis les modifier.

N’hésitez pas à abuser de if [ "$(hostname)" == "jessie1" ]; then source ${SSHHOME}/.sshrc.d/.bashrc_jessie1 ; fi afin de gérer finement vos dotfiles par serveur.

Vous pouvez créer des liens symboliques au lieu de copier certains fichiers de configuration dans ~/.sshrc.d. Personnellement j’ai fait ln -s ~/.inputrc ~/.sshrc.d/.inputrc pour inputrc. Ça me permet ainsi d’avoir mes raccourcis claviers personnalisés en fonction du poste sur lequel je suis (touches utilisées différentes si je suis sur mon pc portable).

Je vous invite à lire ce fil sur Hacker News autour de sshrc, il y a des réflexions intéressantes. Je me demande notamment dans quelle mesure on peut charger des fichiers de configuration (rendus disponibles par un serveur web) avec wget/curl. A noter le reddit dotfiles, the unofficial guide to doing dotfiles on GitHub, awesome-shell et tant qu’à faire awesome.

Gravatar de blog-libre
Original post of blog-libre.Votez pour ce billet sur Planet Libre.

Articles similaires

Okki : Sortie de GNOME 3.26

Ça y est. Le tout nouveau GNOME 3.26 est disponible.

Et cette fois-ci, le bureau lui-même a droit à quelques nouveautés bienvenues. Dans la vue d’ensemble des activités, la taille des vignettes des fenêtres a été augmentée, ce qui rend leur sélection plus facile. Et lors d’une recherche, la mise en page a été retravaillée pour pouvoir afficher plus de résultats, tout en étant plus lisibles.

Réorganisation des résultats de recherche

Il est également possible d’effectuer des recherches sur les actions du système (déconnexion, redémarrage, mise hors tension, verrouillage de l’écran…). Lors de la minimisation ou de la maximisation d’une fenêtre, de nouvelles animations font leur apparition. Et lorsque aucune fenêtre n’est maximisée, la barre supérieure devient désormais transparente, donnant l’impression d’un bureau plus grand.

Autre nouveauté importante, l’interface du Centre de contrôle a été complètement refaite et affiche désormais un panneau latéral pour pouvoir naviguer entre les différents modules. Les paramètres concernant le réseau et l’affichage ont également été retravaillés.

Le nouveau Centre de contrôle

Le reste des applications n’est pas en reste. Fichiers peut désormais rechercher dans le contenu même de vos documents (fichiers texte, PDF, LibreOffice ou MS Office…). Les onglets fermés peuvent être restaurés à l’aide du raccourci clavier Ctrl + Shift + T. Les archives peuvent être décompressées sur des serveurs distants.

Le navigateur Web peut désormais synchroniser vos signets, mots de passe, historique de navigation… au travers du service Firefox Sync. Synchronisation qui fonctionne tout aussi bien entre les deux navigateurs que sont Web et Firefox.

Fin 2017, GNOME découvre enfin les émojis en couleur 😁 Et bonne nouvelle, ces derniers pourront désormais être insérés bien plus facilement dans vos messages et documents, à l’aide d’un sélecteur graphique. Certaines applications, comme le client IRC Polari, en tirent d’ores et déjà parti.

Les émojis sont désormais en couleur

Machines peut désormais partager des dossiers entre l’hôte et l’invité. On peut enfin ajouter des événements récurrents dans l’agenda. To Do prend désormais en charge le service Todoist. Le Visionneur de documents prend désormais en charge les documents Adobe Illustrator et CBR

Et bien évidemment, en plus des principales nouveautés, nous avons droit à de nombreuses petites améliorations bienvenues un peu partout, ainsi que d’innombrables corrections de bugs.

Mais je ne vais pas refaire les notes de version, qui n’ont malheureusement pas encore été traduites en français, mais que je vous invite tout de même à parcourir. On regrettera également l’absence de la vidéo de présentation au moment du lancement, qui aurait gagné à être retardé, le temps que tout le monde soit prêt.

Vous pouvez également jeter un œil au billet de blog de Georges Basile Stavracas Neto, qui donne quelques infos supplémentaires, tout en proposant diverses vidéos mettant en avant certaines nouveautés.

Cette nouvelle version est donc un très bon cru, mais qui comporte tout de même son lot de déceptions. Certaines fonctionnalités particulièrement attendues, comme la juxtaposition de quatre fenêtres ou la mise à l’échelle fractionnée nécessaire à la bonne prise en charge des écrans HiDPI n’étaient malheureusement pas prêtes à temps et seront donc repoussées à la prochaine version, prévue pour le mois de mars 2018.

Gravatar de Okki
Original post of Okki.Votez pour ce billet sur Planet Libre.

Okki : Sortie de Gradio 6.0

Gradio 6.0

Pour rappel, Gradio vous permet de découvrir et d’écouter des radios en ligne.

Au niveau des nouveautés, nous noterons :

  • la possibilité de regrouper nos stations en collections
  • la possibilité de pouvoir trier nos stations selon différents critères (nom, langue, pays, votes…)
  • l’ajout d’une recherche étendue (la petite flèche pointant vers le bas, à droite de la boîte de recherche) permettant de sélectionner un pays ou une langue
  • la possibilité d’ajouter de nouvelles stations ou d’éditer les informations de stations déjà existantes (la base de données étant en ligne, chaque ajout ou modification est visible par l’ensemble des utilisateurs)
  • la bibliothèque peut désormais être exportée et importée
  • une barre latérale proposant un certain nombre d’informations sur chaque station peut désormais être affichée
  • un nouveau système de sélection fait son apparition
  • l’état de la connexion est désormais affiché dans la barre d’outils
  • l’application se reconnecte automatiquement après une déconnexion et elle consomme beaucoup moins de mémoire

Par contre, les années ont beau passer, il n’existe malheureusement toujours aucune traduction en français.

Gravatar de Okki
Original post of Okki.Votez pour ce billet sur Planet Libre.

Articles similaires

Pages