[{"content":" Note: This article was partly generated with AI while I was learning Kotlin. It started as personal notes but turned into something readable enough to share. Also, Hugo renders it better than my text editor.\nYou’ve seen Kotlin mentioned in passing.\n“Modern Java,” they said. “Null-safe,” they promised. “Works on the JVM, Android, browser, fridge, whatever,” they muttered. Here’s the deal: we’ll learn Kotlin quickly and directly. No corporate slides, no Android Studio screenshots, no JetBrains marketing. Just the language, the essentials, and a bit of personality to keep you interested.\nThe quick pitch Kotlin is:\ncompiled, statically typed, boring in a good way, plays nicely with Java (you can literally call .javaClass on anything), and makes NullPointerException feel like a relic from 2004. You can use it for Android, backend, CLI tools, or even write multiplatform code that also runs on iOS.\nInteresting fact: Kotlin was created at JetBrains in 2011 and named after Kotlin Island near St. Petersburg, following the same naming style as Java (from Java Island). It officially became a first-class language for Android development in 2017.\nThe very basics You’ve seen var and val before, but let’s be formal:\nval immutable = 42 // can’t reassign var mutable = 0 // can change mutable += 1 Type inference? Yes. Explicit types? Also yes. You’ll end up mixing both like everyone else.\nTip: Prefer val unless you really need var. Immutability makes your code safer and easier to reason about.\nStrings val who = \u0026#34;world\u0026#34; println(\u0026#34;Hello, $who! 2 + 2 = ${2 + 2}\u0026#34;) String templates make interpolation simple. Just don’t forget the {} when mixing expressions, or Kotlin will print them literally.\nDid you know? Kotlin strings are immutable, but you can use StringBuilder for efficient concatenation in loops.\nNull safety val name: String? = getMaybe() val len = name?.length ?: 0 That ?. operator means “don’t fail if it’s null.” The ?: means “use something else instead.” And if you really want to crash:\nval sure = name!!.length // not recommended Kotlin makes null handling explicit. It’s a habit worth learning.\nTip: Use nullable types sparingly. If a value can be null, question why before adding ?.\nFunctions fun add(a: Int, b: Int) = a + b fun greet(name: String = \u0026#34;world\u0026#34;) { println(\u0026#34;Hi $name\u0026#34;) } You can omit the return type if it’s obvious. Kotlin will infer it.\nInteresting fact: Kotlin supports top-level functions—you don’t need a class to wrap everything like in Java.\nif and when val mood = if (hour \u0026lt; 12) \u0026#34;☕\u0026#34; else \u0026#34;🔥\u0026#34; if is an expression that returns a value. You’ll also find yourself using when instead of switch:\nval response = when (status) { 200 -\u0026gt; \u0026#34;OK\u0026#34; in 300..399 -\u0026gt; \u0026#34;Redirect\u0026#34; else -\u0026gt; \u0026#34;Error\u0026#34; } Tip: when can match types, ranges, or even multiple conditions per branch.\nLoops for (i in 0 until 10) println(i) for (i in 10 downTo 1 step 2) println(i) And if you need both index and value:\nlistOf(\u0026#34;a\u0026#34;, \u0026#34;b\u0026#34;, \u0026#34;c\u0026#34;).forEachIndexed { i, v -\u0026gt; println(\u0026#34;$i -\u0026gt; $v\u0026#34;) } Fun fact: Kotlin doesn’t have a traditional while(true) + break pattern as often as Java—most looping is handled through functional operators like map, filter, or forEach.\nCollections val nums = listOf(1, 2, 3, 4) val evens = nums.filter { it % 2 == 0 } val squares = nums.map { it * it } val sum = nums.reduce { acc, n -\u0026gt; acc + n } Immutable by default. Mutable versions exist (mutableListOf, mutableMapOf), but use them when needed.\nTip: Prefer functional operations (map, filter, fold) instead of manual loops whenever possible. They’re concise and expressive.\nData classes data class User(val id: Int, val name: String) val u1 = User(1, \u0026#34;Sam\u0026#34;) val u2 = u1.copy(name = \u0026#34;Samuel\u0026#34;) Data classes give you equals, hashCode, toString, copy, and destructuring—all generated automatically.\nDid you know? You can use componentN() functions for destructuring: val (id, name) = user.\nObjects and companions object Log { fun d(msg: String) = println(msg) } class C { companion object { fun make() = C() } } object creates a singleton. companion object is a singleton inside a class.\nTip: You can annotate companion methods with @JvmStatic for Java interop.\nExtensions fun String.title(): String = split(\u0026#34; \u0026#34;).joinToString(\u0026#34; \u0026#34;) { it.replaceFirstChar(Char::titlecase) } \u0026#34;hello kotlin\u0026#34;.title() // \u0026#34;Hello Kotlin\u0026#34; Extension functions let you add functionality without modifying classes.\nFact: Extensions are statically resolved. They don’t actually modify the class—they’re just syntactic sugar.\nOperator overloading data class Vec(val x: Int, val y: Int) operator fun Vec.plus(o: Vec) = Vec(x + o.x, y + o.y) val v = Vec(1,2) + Vec(3,4) Readable and controlled operator behavior.\nTip: Only overload operators when they make sense semantically.\nSealed hierarchies sealed interface Result\u0026lt;out T\u0026gt; data class Ok\u0026lt;T\u0026gt;(val value: T): Result\u0026lt;T\u0026gt; data class Err(val error: Throwable): Result\u0026lt;Nothing\u0026gt; Sealed types give you exhaustive when statements. Handle all cases explicitly.\nFact: Kotlin’s sealed types are a great way to model state machines or error handling without exceptions.\nCoroutines Coroutines bring structured concurrency and suspendable functions to Kotlin.\nimport kotlinx.coroutines.* suspend fun fetch(id: Int): String = withContext(Dispatchers.IO) { delay(100) \u0026#34;item-$id\u0026#34; } suspend fun parallel(): List\u0026lt;String\u0026gt; = coroutineScope { (1..3).map { async { fetch(it) } }.awaitAll() } fun main() = runBlocking { println(parallel()) } Readable concurrency with proper cancellation and scope management.\nTip: Prefer withContext for switching threads, not for every suspend call.\nInteresting fact: Coroutines compile into state machines under the hood—lightweight and efficient.\nrunCatching val res = runCatching { risky() } .getOrElse { println(\u0026#34;nope\u0026#34;); -1 } Kotlin treats exceptions as values, allowing cleaner error handling.\nTip: Combine runCatching with extension functions like .onFailure {} for clearer recovery flows.\nBuilders and DSLs fun html(init: Html.() -\u0026gt; Unit) = Html().apply(init) class Html { private val out = StringBuilder() fun div(init: Html.() -\u0026gt; Unit) { out.append(\u0026#34;\u0026lt;div\u0026gt;\u0026#34;); init(); out.append(\u0026#34;\u0026lt;/div\u0026gt;\u0026#34;) } fun text(s: String) { out.append(s) } override fun toString() = out.toString() } val h = html { div { text(\u0026#34;Hello DSL\u0026#34;) } } Kotlin’s syntax makes small domain-specific languages easy to build.\nExample: Gradle’s Kotlin DSL and Jetpack Compose both rely heavily on this pattern.\nThings Kotlin does better than Java Null safety. Default arguments. Smart casts (if (x is String) → x.length). Simpler lambdas. Coroutines instead of callback pyramids. Less boilerplate. Extra tip: Kotlin’s data class + copy() pattern is an excellent substitute for builders.\nThings Kotlin does worse than Rust No manual memory control (GC only). Slower at times due to JVM overhead. Longer compile times. Gradle still has its moods. Fact: Kotlin Native compiles to native binaries, but interoperability and performance still trail Rust.\nExample: pulling it together import kotlinx.coroutines.* import kotlinx.coroutines.Dispatchers.IO sealed interface Fetch\u0026lt;out T\u0026gt; { data class Ok\u0026lt;T\u0026gt;(val v: T): Fetch\u0026lt;T\u0026gt; data class Err(val msg: String): Fetch\u0026lt;Nothing\u0026gt; } data class Post(val id: Int, val title: String) suspend fun fetchPost(id: Int): Fetch\u0026lt;Post\u0026gt; = withContext(IO) { runCatching { delay(50) Post(id, \u0026#34;Hello Kotlin\u0026#34;) }.fold( onSuccess = { Fetch.Ok(it) }, onFailure = { Fetch.Err(it.message ?: \u0026#34;unknown\u0026#34;) } ) } suspend fun fetchAll(ids: List\u0026lt;Int\u0026gt;): List\u0026lt;Post\u0026gt; = coroutineScope { ids.map { async { fetchPost(it) } }.awaitAll().mapNotNull { when (it) { is Fetch.Ok -\u0026gt; it.v is Fetch.Err -\u0026gt; null } } } fun main() = runBlocking { println(fetchAll((1..3).toList())) } A concise, real-world pattern: parallel fetching with safe error handling.\nExtra Kotlin tips Use apply for configuration, let for transformation, also for side effects, run for scoping. Avoid overusing extension functions—they’re best for domain helpers, not full APIs. Prefer sealed class over enums when variants hold data. When writing libraries, expose interfaces instead of classes for easier testing. Remember: Kotlin compiles down to JVM bytecode, so any performance tips for Java often apply. Inline functions with reified types let you keep generic type info at runtime. Where to go next Search for:\n“Kotlin coroutines structured concurrency” “Ktor client/server” “Kotlin sealed classes vs enums” “Arrow-kt” for FP-style programming Or simply start coding. Kotlin rewards experimentation and practical use.\nThanks for reading. If this helped you or made Kotlin a bit clearer, feel free to share it or reuse parts of it for your own notes.\n","permalink":"https://blog.chmouel.com/posts/kotlin-primer/","summary":"\u003cblockquote\u003e\n\u003cp\u003e\u003cem\u003eNote:\u003c/em\u003e This article was partly generated with AI while I was learning Kotlin.\nIt started as personal notes but turned into something readable enough to share.\nAlso, Hugo renders it better than my text editor.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eYou’ve seen Kotlin mentioned in passing.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e“Modern Java,” they said.\u003c/li\u003e\n\u003cli\u003e“Null-safe,” they promised.\u003c/li\u003e\n\u003cli\u003e“Works on the JVM, Android, browser, fridge, whatever,” they muttered.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eHere’s the deal: we’ll learn Kotlin quickly and directly. No corporate slides, no Android Studio screenshots, no JetBrains marketing.  Just the language, the essentials, and a bit of personality to keep you interested.\u003c/p\u003e","title":"Kotlin in a hurry (and why you might actually like it)"},{"content":"GitHub\u0026rsquo;s pull_request_target event presents a significant security challenge due to its access to the pull request within the target repository\u0026rsquo;s context. This can expose sensitive secrets to untrusted users submitting pull requests.\nFor projects like Pipelines-as-Code (PAC), where interaction with multiple upstream providers (Bitbucket, GitLab, GitHub) is essential, this risk is amplified. Access to repository secrets is vital for E2E testing across these platforms, yet arbitrary pull requests triggering secret-laden workflows is unacceptable.\nRestricting pull requests to originate solely from repository branches would mitigate this risk, but it would also severely limit external contributions—a trade-off we aimed to avoid.\nExploring Alternatives: GitHub Environments and Workflow Dispatch Initially, GitHub Environments were considered. Configuring workflows to run only within specific environments allows for leveraging GitHub\u0026rsquo;s built-in approval mechanism. This offers a user-friendly approval button in the UI. However, it necessitates manual approval for every workflow execution, including automated nightly runs, which becomes cumbersome.\nNext, the workflow_dispatch event was explored. This involved a PAC PipelineRun that triggers the workflow dispatch API and monitors its completion. The appeal lies in utilizing PAC\u0026rsquo;s robust permission control features. Approved users can trigger E2E tests by commenting /ok-to-test on pull requests, while non-approved users have the workflow automatically initiated.\nHowever, several challenges arose. While the GitHub Actions workflow was triggered with the correct SHA and input arguments, it failed to accurately target the specified SHA during execution. This resulted in inaccurate status updates in the UI. Additionally, reliably retrieving the run ID of a newly created workflow dispatch proved difficult.\nUltimately, this approach proved overly complex and challenging to debug, prompting a search for a simpler, more transparent solution.\nThe Solution: Automating with GitHub Labels and PAC The solution involved leveraging GitHub labels, specifically the e2e label, to trigger our E2E testing workflow. This approach offers several advantages:\nExplicit Triggering: Workflows are triggered only when the e2e label is added. Transparency: The label\u0026rsquo;s presence is clearly visible in the pull request UI. Simplicity: This method avoids the complexities of API-based triggering and run ID management. To automate the label application, we utilize a Pipelines-as-Code (PAC) PipelineRun. This PipelineRun is triggered on pull requests targeting the main branch and involving changes to specific files (e.g., Go files, workflow configurations).\napiVersion: tekton.dev/v1beta1 kind: PipelineRun metadata: name: e2e-label.yaml annotations: pipelinesascode.tekton.dev/on-event: \u0026#34;pull_request\u0026#34; pipelinesascode.tekton.dev/on-target-branch: \u0026#34;main\u0026#34; pipelinesascode.tekton.dev/on-path-change: \u0026#34;[***/*.go, .github/workflows/*l]\u0026#34; spec: pipelineSpec: tasks: - name: label-pr taskSpec: steps: - name: label-pr image: registry.access.redhat.com/ubi9/ubi env: - name: HUB_TOKEN valueFrom: secretKeyRef: name: \u0026#34;nightly-ci-github-hub-token\u0026#34; key: \u0026#34;hub-token\u0026#34; script: | #!/usr/bin/env python3 # ... Python script to add the \u0026#39;e2e\u0026#39; label ... This PipelineRun runs within the context of PAC\u0026rsquo;s Access Control List (ACL) authorization, which is highly flexible. This allows us to define specific rules for when the e2e label should be applied. For example, we can restrict label application to pull requests originating from trusted users or those meeting specific criteria.\nBy configuring the GitHub workflow to trigger both when the label is added and when it already exists, we ensure that the workflow is executed for all relevant pull requests. This automation, driven by PAC\u0026rsquo;s flexible ACL, significantly streamlines the E2E testing process.\nAnother benefit of this approach is that if the automatic labeling fails to apply—such as when the Pull Request doesn’t involve any Go files but still requires testing—a GitHub repository admin can manually add the e2e label. This manual addition will trigger the workflow. Previously, the workflow would not have been triggered at all unless it specifically targeted changes in Go files.\nname: E2E Tests on: pull_request_target: types: - labeled - opened - reopened - synchronize jobs: e2e-tests: if: \u0026gt; github.event_name == \u0026#39;pull_request_target\u0026#39; \u0026amp;\u0026amp; (github.event.label.name == \u0026#39;e2e\u0026#39; || contains(github.event.pull_request.labels.*.name, \u0026#39;e2e\u0026#39;)) # ... rest of the workflow configuration Conclusion The pull_request_target event in GitHub Actions presents inherent security risks. By exploring alternative solutions and ultimately adopting a label-based triggering mechanism, coupled with PAC\u0026rsquo;s automated labeling and flexible authorization, a more secure, transparent, and manageable E2E testing workflow is established. This approach allows for maintaining a balance between security and the ability to accept contributions from external developers, while automating the triggering process.\nLinks Our E2E testing workflow: e2e.yaml Our Pipelines-as-Code PipelineRun that automates labeling: e2e-label.yaml Understanding pull_request vs pull_request_target GitHub Actions Documentation on pull_request_target Pipelines as Code Documentation ","permalink":"https://blog.chmouel.com/posts/github-workflows-pull_request_target/","summary":"\u003cp\u003eGitHub\u0026rsquo;s \u003ca href=\"https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target\"\u003e\u003ccode\u003epull_request_target\u003c/code\u003e\u003c/a\u003e\nevent presents a significant security challenge due to its access to the pull\nrequest within the \u003cem\u003etarget\u003c/em\u003e repository\u0026rsquo;s context. This can expose sensitive\nsecrets to untrusted users submitting pull requests.\u003c/p\u003e\n\u003cp\u003eFor projects like Pipelines-as-Code (PAC), where interaction with multiple\nupstream providers (Bitbucket, GitLab, GitHub) is essential, this risk is\namplified. Access to repository secrets is vital for E2E testing across these\nplatforms, yet arbitrary pull requests triggering secret-laden workflows is\nunacceptable.\u003c/p\u003e","title":"Trying to workaround the pull_request_target issue in GitHub Actions with Pipelines as Code"},{"content":"I haven’t fully jumped on the AI hype train, but I’ve kept an eye on the evolving technologies of the past two decades. It used to be that Cloud was the buzzword, then Containers, and maybe blockchain (never got into this one), and now AI.\nAt first, AI felt like a nice gimmick—discussing things with a chatbot felt a bit like doing a Google search but with a conversational twist. The problem with chatbots was that funny feeling you’d get when it seemed like they were just making things up.\nBut so much has changed since the first release of ChatGPT. Things have gotten way, way better.\nIt’s nice to have Copilot occasionally enabled for my open-source work to learn and get advanced code completions. It’s nice to have a chatbot that can answer questions about my code. It’s even nice to have one that helps with my writing. It is, indeed, useful.\nBut so far I wanted to go beyond that and play around with the AI APIs out there and see if I could go a bit beyond these use cases.\nGitHub offers a playground with a variety of APIs, making it easier to tinker with small ideas and use cases.\nA Couple of Personal Use Cases One thing I wanted was a way to generate those easy, trivial commit messages for my code. I started writing a tool for this until I discovered that the copilot-chat.el mode integrates nicely with Magit, so I didn’t need to do much there except some configurationhttps://gitlab.com/chmouel/emacs-config/-/blob/main/lisp/init-copilot.el?ref_type=heads#L31 for it.\nYour browser does not support the video tag. Another thing that’s always annoyed me is writing French accents on my English keyboard. On Linux, I need to use Right-ALT and do mental gymnastics to type them. I have a custom keyboard with macros that make it easier, but I still don’t like writing them—and to be honest, I’m not even sure where to properly place them half the time. So, when I write to family or friends in French from my computer, it always looks weird.\nTo address this, I built a little tool called aichmou to help. It plugs into Sway on Linux and also works with Alfred on macOS.\nHow It Works Aichmou supports a bunch of models using the GitHub model marketplace free API for those with access. It also works with Google Gemini and Groq, which have free APIs.\nHere’s how I use it:\nI select my text, press a key combo (Super+X for me), Sway intercepts it with this configuration: bindsym $super+x exec copyq selection | $HOME/go/src/github.com/chmouel/aichmou/.venv/bin/python3 $HOME/go/src/github.com/chmouel/aichmou/ai -N spell \u0026amp;\u0026amp; wtype -M ctrl -M shift v Launching CopyQ to grab the current selection. (If you don’t use CopyQ as your clipboard manager, you can probably use something else.). The text is sent to Aichmou, which queries an available and non-rate-limited LLM for the correction to make. The result is copied back to the clipboard and typed into the frontmost application using wtype tool. The Results Here is a little demo of it in action:\nYour browser does not support the video tag. Conclusion It\u0026rsquo;s simple and save me a lot of time, and I’m happy with it. And I can easily built on this for some other use cases on that tool if needed in the future.\nHere is the link to the tool:\nAIChmou - https://github.com/chmouel/aichmou My Emacs and Copilot config - https://gitlab.com/chmouel/emacs-config/-/blob/main/lisp/init-copilot.el?ref_type=heads#L31 My Emacs and LLM config - https://gitlab.com/chmouel/emacs-config/-/blob/main/lisp/init-llm.el?ref_type=heads ","permalink":"https://blog.chmouel.com/posts/making-ai-useful/","summary":"\u003cp\u003eI haven’t fully jumped on the AI hype train, but I’ve kept an eye on the\nevolving technologies of the past two decades. It used to be that Cloud was the\nbuzzword, then Containers, and maybe blockchain (never got into this one), and\nnow AI.\u003c/p\u003e\n\u003cp\u003eAt first, AI felt like a nice gimmick—discussing things with a chatbot felt a\nbit like doing a Google search but with a conversational twist. The problem with\nchatbots was that funny feeling you’d get when it seemed like they were just\nmaking things up.\u003c/p\u003e","title":"Making AI useful to me with an AI spellchecker"},{"content":"Introduction It has been a long time since I have blogged about Emacs. I still enjoy using it as when I started from day one (around 1998). I did made some changes I have now moved out of the Emacs keybindings toward using the evil keybinding and have become proficient using Neovim (for terminal editing) or Vscode (for the debugger) but Emacs is where my \u0026ldquo;home\u0026rdquo; is.\nToday I\u0026rsquo;d like to talk about Isearch, I don\u0026rsquo;t think we realise how powerful isearch is compared to other editors, the experience out of the box is very intuitive and powerful and as anything with Emacs you can customize it exactly the way you want.\nThe basic of Isearch is to search incrementally for something in your current buffer. You press C-s you press a string and it incrementally search for it. If you press Enter then the search finishes.\nThere is multiple keys you can press to do more after that search, for example if you press C-s again and you don\u0026rsquo;t have any inputs it will search for the next occurrences of the string of the previous search, you can read about all the basics in the manual:\nhttps://www.gnu.org/software/emacs/manual/html_node/emacs/Search.html\nI have made some customizations to isearch which I find really nice and have them listed in this blog post.\nDirectly jump into occur from a search When you search a buffer with a word it may become tedious to jump around with C-s, you can use the key combo M-s o in isearch to automatically have an overview of all the occurrences in the occur buffer.\nI like to keep that buffer and have the isearch mode exited. To be able to do this I have a little function that does it, which I have added via use-package:\n(use-package isearch :ensure nil :defer t :config (defun my-occur-from-isearch () (interactive) (let ((query (if isearch-regexp isearch-string (regexp-quote isearch-string)))) (isearch-update-ring isearch-string isearch-regexp) (let (search-nonincremental-instead) (ignore-errors (isearch-done t t))) (occur query))) :bind (:map isearch-mode-map (\u0026#34;C-o\u0026#34; . my-occur-from-isearch))) With this configuration I simply press C-s to start a search, type something I want to find and then press C-o to get a nice window of all occurrences of that search in the current buffer.\nSince I have configured my display-buffer-alist variable, the occur window automatically get focused and I can just press a n, p to go to the next or previous occurrence and q to discard the window.\nHere is a snippet of my configuration for display-buffer-alist:\n(defun my-select-window (window \u0026amp;rest _) \u0026#34;Select WINDOW for display-buffer-alist\u0026#34; (select-window window)) (setq display-buffer-alist \u0026#39;(((or . ((derived-mode . occur-mode))) (display-buffer-reuse-mode-window display-buffer-at-bottom) (body-function . my-select-window) (dedicated . t) (preserve-size . (t . t))))) As a side note, I never really understood how display-buffer-alist worked before watching prot excellent video and blog post about it which is available here:\nhttps://protesilaos.com/codelog/2024-02-08-emacs-window-rules-display-buffer-alist/\nDo a project search from a search term Now that little function which I used for occur could be generalised and extended for other type of search.\nFor example, you can do a project search out of the current search word instead of limiting ourselves to the current buffer:\n(use-package isearch :ensure nil :defer t :config (defun my-project-search-from-isearch () (interactive) (let ((query (if isearch-regexp isearch-string (regexp-quote isearch-string)))) (isearch-update-ring isearch-string isearch-regexp) (let (search-nonincremental-instead) (ignore-errors (isearch-done t t))) (project-find-regexp query))) :bind (:map isearch-mode-map (\u0026#34;C-f\u0026#34; . my-project-search-from-isearch))) you search a term and you press the C-f keys and it will instead do a search across your current project with the project-find-regexp function.\nNote that not much as changed between those functions, and you can easily generalise this with a macro or a function, but i\u0026rsquo;ll keep this obvious to make it easy to copy and paste in your configuration.\nUse the current selection for the initial search (if set) This comes from an idea of a rather old reddit post:\nhttps://www.reddit.com/r/emacs/comments/2amn1v/isearch_selected_text/cixq7zx/\nThis uses the current selection for the initial selection. I do a selection via for example an evil operator or via the easy-mark function from the easy-kill library and then press C-s to use that selection for the initial search input:\n;; use selection to search (defadvice isearch-mode (around isearch-mode-default-string (forward \u0026amp;optional regexp op-fun recursive-edit word-p) activate) (if (and transient-mark-mode mark-active (not (eq (mark) (point)))) (progn (isearch-update-ring (buffer-substring-no-properties (mark) (point))) (deactivate-mark) ad-do-it (if (not forward) (isearch-repeat-backward) (goto-char (mark)) (isearch-repeat-forward))) ad-do-it)) I may need to edit that search term, the best way to do edit is to go to the edit mode using the M-e key which is bound to the isearch-edit-string function and let you edit the search term with a cursor (ie: not incrementally).\nSelect the current symbol at point easily for the search Many times you want to select the current symbol to start the search, there is multiple way to do this. In evil I can do a selection with vio to select the current symbol and thanks to the defadvice in the previous tip it would automatically select that symbol for search.\nEmacs has a builtin way to do this using M-s . or since Emacs 28 you can use the function isearch-forward-thing-at-point to directly start a search with the current symbol.\nI find it easier for me to remap the C-d key in isearch mode since I find it easier being close to C-s on a qwerty keyboard. I can then just do C-s C-d and I\u0026rsquo;ll get that symbol filled, here is the snippet of my config:\n(use-package isearch :ensure nil :defer t :bind (:map isearch-mode-map (\u0026#34;C-d\u0026#34; . isearch-forward-symbol-at-point))) Use consult to jump onto the search occurrence Sometime I want to have a interactive way to jump into the current search word, you can use consult-line from the consult package to jump interactively. But if you want to jump from the current isearch term you can just use that same simple function from earlier and instead consult-line like this:\n(use-package consult (:map isearch-mode-map (\u0026#34;C-l\u0026#34; . my-isearch-consult-line-from-isearch)) (defun my-isearch-consult-line-from-isearch () \u0026#34;Invoke `consult-line\u0026#39; from isearch.\u0026#34; (interactive) (let ((query (if isearch-regexp isearch-string (regexp-quote isearch-string)))) (isearch-update-ring isearch-string isearch-regexp) (let (search-nonincremental-instead) (ignore-errors (isearch-done t t))) (consult-line query)))) I start a search and press C-l and it jumps directly to consult-line which I can further do things with it with preview.\nUse avy to jump to the search results on screen Avy let you jump to words and other things via labels, I use for all sort of things (my favourite way is combined with evil with evil-avy package). You can do this from isearch with avy:\n(use-package avy :bind (:map isearch-mode-map (\u0026#34;C-j\u0026#34; . avy-isearch)) I start a search term, press C-j when there is multiple occurrences on screen, and then select the label to directly jump to it instead of having to do multiples C-s.\nUse anzu to replace the current search term across the buffer anzu is a pretty nice library to do interactive replacement in Emacs. I combine it with isearch, replacing the builtin isearch-query-replace:\n(use-package anzu :bind (:map isearch-mode-map ([remap isearch-query-replace] . anzu-isearch-query-replace) ([remap isearch-query-replace-regexp] . anzu-isearch-query-replace-regexp) (\u0026#34;C-h\u0026#34; . anzu-isearch-query-replace))) I can then start from a search hit the C-h key combo and it will ask me for a new name to replace the searched word to something else.\nOn the left is the old word being changed and on the right the new word, it\u0026rsquo;s pretty simple but pretty neat to be able to do this visually.\nConclusion There is other ways to supercharge the Emacs Search and it\u0026rsquo;s probably just a tiny glimpsee of what I know or what I need for my Emacs searching.\nThere is as well the fantastic deadgrep package which I use often with the deadgrep-edit-mode function to do quick replacement over a project.\n","permalink":"https://blog.chmouel.com/posts/emacs-isearch/","summary":"\u003ch2 id=\"introduction\"\u003eIntroduction\u003c/h2\u003e\n\u003cp\u003eIt has been a long time since I have blogged about Emacs. I still enjoy using it\nas when I started from day one (around 1998). I did made some changes I have now\nmoved out of the Emacs keybindings toward using the evil keybinding and have\nbecome proficient using Neovim (for terminal editing) or Vscode (for the\ndebugger) but Emacs is where my \u0026ldquo;home\u0026rdquo; is.\u003c/p\u003e\n\u003cp\u003eToday I\u0026rsquo;d like to talk about Isearch, I don\u0026rsquo;t think we realise how powerful\nisearch is compared to other editors, the experience out of the box is very\nintuitive and powerful and as anything with Emacs you can customize it exactly\nthe way you want.\u003c/p\u003e","title":"Advanced usage of Emacs isearch"},{"content":"I have a very complicated development environment, which spins up a local Kubernetes cluster on Kind and then deploys a bunch of services to it.\nSome of the services gets accessed by the browser and until late I was deploying everything on localhost which so far did not cause any issues, since the browser are good at trusting localhost.\nBut since my laptop was getting slower and slower and I had a new raspberry pi 5 unused with a SSD, I decided to made it my local Kubernetes cluster.\nDeploying Kubernetes on a Raspberry Pi 5 running the raspbian distribution with nix is probably a post on its own, but let\u0026rsquo;s assume it\u0026rsquo;s already deployed. Now I have a new issue, since we are not running on localhost the browser don\u0026rsquo;t trust it anymore and everytime I redeploy I need to click again on those pesky \u0026ldquo;Trust me bro, I know what I\u0026rsquo;m doing\u0026rdquo; (or something along those lines) scary box.\nI spent a bit of time reading this LetsEncrypt blog post https://letsencrypt.org/docs/certificates-for-localhost/ which had a link to this fantastic tool called minica. It\u0026rsquo;s pretty straightforward it create a CA root and then create domains out of it.\nIn your browsers you only trust the CA root and everytime you generate domains, they are being trusted.\nGenerating a certificate and deploying an Ingress To plug this with ingress-nginx I do something like this:\nFirst generate a domain for $domain with minica: mkdir -p minica;cd minica/ minica -domains $domain (if it is already generated then the minica command will fail then make sure it\u0026rsquo;s not)\nUsing the generated secret from minica you can now create a Kubernetes secret out of it, we can call it $sec_name nd install it on the $namespace namespace. key_file=minica/${domain}/key.pem cert_file=minica/${domain}/cert.pem kubectl create secret tls ${sec_name} --key ${key_file} --cert ${cert_file} -n ${namespace} And then we create a Ingress out of it for a component on targetPort expose as ${host} (for example for a docker registry, I use docker-registry as component, 5000 as targetPort and host as registry.local which resolve via my local DNS but you can use a /etc/host entry too) cat \u0026lt;\u0026lt;EOF | kubectl apply -f - --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: \u0026#34;${component}\u0026#34; namespace: \u0026#34;${namespace}\u0026#34; spec: ingressClassName: nginx tls: - hosts: - \u0026#34;${host}\u0026#34; secretName: \u0026#34;${sec_name}\u0026#34; rules: - host: \u0026#34;${host}\u0026#34; http: paths: - pathType: ImplementationSpecific backend: service: name: \u0026#34;${component}\u0026#34; port: number: ${targetPort} EOF For the docker registries you actually need some other annotations to give to ingress nginx to let know that large blobs are OK, here is what I do to actually set those, you don\u0026rsquo;t need to set them if your service don\u0026rsquo;t need to increase the read/send timeout nginx settings.\nfor annotations in \u0026#34;nginx.ingress.kubernetes.io/proxy-body-size=0\u0026#34; \\ \u0026#34;nginx.ingress.kubernetes.io/proxy-read-timeout=600\u0026#34; \\ \u0026#34;nginx.ingress.kubernetes.io/proxy-send-timeout=600\u0026#34; \\ \u0026#34;kubernetes.io/tls-acme=true\u0026#34;; do kubectl -v=0 annotate ingress -n ${namespace} ${component} \u0026#34;${annotations}\u0026#34; done Using the certificate Linux (generic) On Linux you can install the certificate system wise by issuing this command:\nsudo trust anchor -v --store minica/minica.pem NixOS If you are using Nix you can simply use the option security.pki.cert and include the certificate in your configuration.\nMacOS On MacOS you can use this guide from Broadcom here to install your minica/minica.pem onto your keychain: https://techdocs.broadcom.com/us/en/symantec-security-software/web-and-network-security/web-isolation/1-16/Installing-the-STIP/Installing-the-STIP-Overview/Installing-the-CA-Certificate/Installing-the-CA-Certificate-Mac.html\nWhen you trust it, it will be available to all CLI tools as well as your browsers.\nCurl If you can\u0026rsquo;t (or don\u0026rsquo;t want to) install certificate system wise use curl with the custom certificate by specifying the --cacert flag to curl:\ncurl --cacert minica/minica.pem https://${host} Firefox As for Firefox you have to go to the settings and search for view certificates in the search box, go to the Authorities tab click on Import use the minica.pem file as generated in the minica/ directory and trust it as root domain by checking the checkbox. Now if you go to the https://${host} it should not bring any scary messages.\nChrome browsers Almost the same thing with chrome browser, I use Brave but that should apply to others. Go to this URL in your browser to see the certificates (it\u0026rsquo;s in the security section if you look for it from the home settings)\nbrave://settings/certificates\nGo to the authorities tab and import your minica.pem from the minica/ directory and you should be good to go.\nPython request Just for completeness using python requests you can simply specify the root certificates by using the non obvious keyword verify:\nr = requests.get( f\u0026#34;https://{domain}/\u0026#34;, verify=\u0026#34;minica/minica.pem\u0026#34;, ) Conclusion There is no reason to don\u0026rsquo;t use SSL domains for your local services on your cluster and you won\u0026rsquo;t need to spend your precious time clicking on those \u0026ldquo;trust me\u0026rdquo; button anymore.\n","permalink":"https://blog.chmouel.com/posts/self-signed-certs/","summary":"\u003cp\u003eI have a very complicated development environment, which spins up a local\nKubernetes cluster on Kind and then deploys a bunch of services to it.\u003c/p\u003e\n\u003cp\u003eSome of the services gets accessed by the browser and until late I was deploying\neverything on localhost which so far did not cause any issues, since the browser\nare good at trusting localhost.\u003c/p\u003e\n\u003cp\u003eBut since my laptop was getting slower and slower and I had a new raspberry pi 5\nunused with a SSD, I decided to made it my local Kubernetes cluster.\u003c/p\u003e","title":"Trusting self signed certificates with Kubernetes Ingress Controller"},{"content":"I use \u0026ldquo;Webhook\u0026rdquo; every day; it\u0026rsquo;s a simple mechanism used by most web applications to send payloads on events. It\u0026rsquo;s great and all, but since it needs to send you data, it has to be exposed to the internet. And that\u0026rsquo;s where it gets tricky. If you are in development mode and want to test the webhook, you can\u0026rsquo;t just expose your local machine to the internet; you need some sort of solution for that.\nThere are a lot of solutions for that, but most of them are either paid or require some pre-setup. At work, our Security team is very pedantic about things that can go in when you have things behind the VPN; the only service that is allowed is: https://smee.io\nsmee.io Service smee.io is a great service! It lets you expose a local port to the internet as simply as that. It\u0026rsquo;s all open source, but you can use their instance on https://smee.io for free. They have this client called smee-client which you can run locally to fetch the events from the server and replay them on a local service.\nI encountered some issues with the client (not being able to set the Host header behind a proxy) and found it challenging to deploy the Node.js version. So, I quickly went looking for alternatives and discovered pysmee, which worked for me for a while. However, I later faced some issues with chunked transfer due to a Python update, which broke it.\nThe project didn\u0026rsquo;t seem to be updated, and since our CI depended on this, I had to figure out a proper solution for this.\nCreating Gosmee Since it seemed to be a perfect fit for go, I looked on how to do my own implementation.\nUsing the r3labs/sse Go library, I made a quick implementation that connects to smee.io and replays events on another server.\nThis was quite straightforward, and since it was in Go, it makes it easy to distribute and run in the cloud, which is a perfect fit for when running on Kubernetes to expose a local Deployment/Service to the internet.\nIt\u0026rsquo;s available here:\nhttps://github.com/chmouel/gosmee\nand if my word don\u0026rsquo;t make that much sense here is a handy diagram showing how it works:\nDebugging Webhook with the Saved Script I added a feature that I find crucial to my workflow: the ability to replay a webhook without having to resend a commit. When you add the flag --saveDir and point it to a directory, it saves the full payload to a JSON file and creates a handy shell script with the correct headers, as seen from the server, for curl to send over to your local service. This allows you to \u0026ldquo;Re-run\u0026rdquo; the request easily, and furthermore, if you plug a debugger into it, it makes debugging a bug easy.\nThese days, when someone reports a bug on pipelines-as-code and I need to debug the query, I ask them to:\nChange the webhook URL to a smee.io URL. Provide me with the kubeconfig of their test cluster. Replay the action that wasn\u0026rsquo;t working. I plug gosmee --saveDir into that smee.io URL, connect with their kubeconfig, and run a debugger while replaying the action via the shell script and can easily reproduce (and hopefully fix) the bug.\nGosmee server All this things was great until smee.io wasn\u0026rsquo;t available anymore, it was down for a few weeks due of some abuse and our CI was broken again\u0026hellip;\nYou can run the smee.io server easily and I should have probably have done that and go on with my day but instead since I did find it interesting I implemented a server into gosmee available as gosmee server with the ideas of adding more features like authentication in the feature (spoiler: I didn\u0026rsquo;t do it since webhook is not really designed for that).\nI wasn\u0026rsquo;t sure if it was going to scale but since I have started running it on https://hook.pipelinesascode.com behind a caddy server on the smallest Amazon public VM I could find, I never had issues with it and happily run this for everyone who wants an alternative to smee.io.\nGosmee Replay via GitHub API I could probably have been done with this and called it a day, but then I stumbled onto the GitHub API documentation and saw that they have started to have the ability to list deliveries I thought this would be an interesting fit for gosmee.\nThis has the advantage of being able to replay any webhook deliveries even if the server or client was down, but it has the disadvantage of being specific to GitHub (unless there are other services offering that API that I don\u0026rsquo;t know about). Furthermore you don\u0026rsquo;t have to trust a external service or deploy your own.\nSo, the gosmee replay feature is born. It only supports repository webhook for now, but I am planning to have organization webhook or even GitHub Apps webhook replaying.\nThere is more things I want to add to the gosmee replay feature, like being able to see the payload and replay a specific one directly in a interactive way, so hopefully there is even more to do here\u0026hellip;\n","permalink":"https://blog.chmouel.com/posts/gosmee-webhook-forwarder-relayer/","summary":"\u003cp\u003eI use \u0026ldquo;Webhook\u0026rdquo; every day; it\u0026rsquo;s a simple mechanism used by most web\napplications to send payloads on events. It\u0026rsquo;s great and all, but since it needs to\nsend you data, it has to be exposed to the internet. And that\u0026rsquo;s where it gets\ntricky. If you are in development mode and want to test the webhook, you can\u0026rsquo;t\njust expose your local machine to the internet; you need some sort of\nsolution for that.\u003c/p\u003e","title":"Gosmee Webhook Forwarder and Relayer"},{"content":"GitHub workflow is great but can be a bit of a black box when things go wrong.\nWhen the YAML cannot be validated, GitHub offers a handy feature to debug the workflow with additional logging.\nBut sometimes your deployment or tests, or whatever you are doing in your workflow, fail when running on CI but not locally, and you are bound to end up in the git push/commit Outer-Loop hell:\n📝 vi file/to/add/debug.sh 🎹 git commit -a \u0026#34;debug ignore\u0026#34; 🫸 git push 👀 [watch logs failures] ♻️ [repeat] 🔞 [swear] 🤦 [hope that things start to work but no it\u0026#39;s just another random timeout] 😭 [distress] I hate this loop; it’s time-consuming, stupid, and wastes resources and energy for the planet and everyone.\nUsing tmate, your best mate ever Somebody made \u0026lt;tmate.io\u0026gt;, and that’s an incredible public service! It lets you SSH with a unique URL (via SSH public/private keys) to the VM running on GitHub actions and allows you debug your running VM.\nI probably would not use that for sensitive repositories, but if you are just running Open Source projects, then it’s probably fine.\nYou can enable it on your workflow on demand via the workflow_dispatch. First, add at the top of your workflow in your on section:\non: workflow_dispatch: inputs: debug_enabled: type: boolean description: \u0026#39;Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)\u0026#39; required: false default: false Then, add somewhere in your steps (after doing some pre-setup, for example) and before running your actual test:\n- name: Setup tmate session uses: mxschmitt/action-tmate@v3 if: ${{ github.event_name == \u0026#39;workflow_dispatch\u0026#39; \u0026amp;\u0026amp; inputs.debug_enabled }} with: limit-access-to-actor: true When you need to debug your Workflow, you simply can use the gh CLI to run the workflow_dispatch with the debug variable enabled.\n$ gh workflow run -f debug_enabled=true .github/workflows/my_workflow.yaml It will stop at the tmate step in your workflow and show you an SSH URL which you can connect to with your SSH private key and happily debug your tests or deployment in there.\nThere are multiple other options for the workflow; head over to the tmate action repository to see what other options you can pass.\n","permalink":"https://blog.chmouel.com/posts/debugging-github-workflow/","summary":"\u003cp\u003eGitHub workflow is great but can be a bit of a black box when things go wrong.\u003c/p\u003e\n\u003cp\u003eWhen the YAML cannot be validated, GitHub offers a handy feature to debug the\nworkflow with \u003ca href=\"https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging\"\u003eadditional logging\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eBut sometimes your deployment or tests, or whatever you are doing in your\nworkflow, fail when running on CI but not locally, and you are bound to end up\nin the git push/commit Outer-Loop hell:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e📝 vi file/to/add/debug.sh\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e🎹 git commit -a \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;debug ignore\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e🫸 git push\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e👀 \u003cspan style=\"color:#ff79c6\"\u003e[\u003c/span\u003ewatch logs failures\u003cspan style=\"color:#ff79c6\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e♻️ \u003cspan style=\"color:#ff79c6\"\u003e[\u003c/span\u003erepeat\u003cspan style=\"color:#ff79c6\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e🔞 \u003cspan style=\"color:#ff79c6\"\u003e[\u003c/span\u003eswear\u003cspan style=\"color:#ff79c6\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e🤦 \u003cspan style=\"color:#ff79c6\"\u003e[\u003c/span\u003ehope that things start to work but no it\u0026#39;s just another random timeout\u003cspan style=\"color:#ff79c6\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e😭 \u003cspan style=\"color:#ff79c6\"\u003e[\u003c/span\u003edistress\u003cspan style=\"color:#ff79c6\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eI \u003cstrong\u003ehate\u003c/strong\u003e this loop; it’s time-consuming, stupid, and wastes resources and energy\nfor the planet and everyone.\u003c/p\u003e","title":"How to debug GitHub Workflow with Tmate"},{"content":"I enjoy the space cadet feature of QMK :\nhttps://docs.qmk.fm/#/feature_space_cadet\nThe feature is simple but yet powerful, when you hit one press you send a parenthese open or close form the other side and if you hold it you have shift.\nI am not sure what happened to my config, but I could not get it to work with the default macros offered SC_LSPO and SC_RSPO.\nI dug into the process_record_user() function hook to replicate the feature and add one other \u0026rsquo;thing\u0026rsquo; where if you press another shift at the same time of the keypress it will do a right bracket.\nFor example, right shift held and left shift will print { and left shift held with right shift will print me }.\nAt the same time i have a combo setup when I press both shifts quickly, it will print me both ().\nThe code to add in process_record_user is this:\n#define SC_LSFT OSM(MOD_LSFT) #define SC_RSFT OSM(MOD_RSFT) bool process_record_user(uint16_t keycode, keyrecord_t *record) { bool ls = (get_mods() | get_weak_mods()) \u0026amp; MOD_BIT(KC_LSFT); bool rs = (get_mods() | get_weak_mods()) \u0026amp; MOD_BIT(KC_RSFT); switch (keycode) { case SC_LSFT: if (record-\u0026gt;tap.count \u0026amp;\u0026amp; rs \u0026amp;\u0026amp; record-\u0026gt;event.pressed) { unregister_code(KC_RSFT); tap_code16(KC_LCBR); return false; } else if (record-\u0026gt;tap.count \u0026amp;\u0026amp; record-\u0026gt;event.pressed) { tap_code16(KC_LPRN); return false; // Return false to ignore further processing of key } return true; case SC_RSFT: if (record-\u0026gt;tap.count == 1 \u0026amp;\u0026amp; ls) { unregister_code(KC_LSFT); tap_code16(KC_RCBR); return false; } else if (record-\u0026gt;tap.count == 1 \u0026amp;\u0026amp; record-\u0026gt;event.pressed) { tap_code16(KC_RPRN); return false; // Return false to ignore further processing of key } return true; } } now the hard part is to get used to it and effectively used it :)\n","permalink":"https://blog.chmouel.com/posts/qmk-space-cadet-plus-plus/","summary":"\u003cp\u003eI enjoy the space cadet feature of \u003ca href=\"https://docs.qmk.fm/\"\u003eQMK\u003c/a\u003e :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://docs.qmk.fm/#/feature_space_cadet\"\u003ehttps://docs.qmk.fm/#/feature_space_cadet\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eThe feature is simple but yet powerful, when you hit one press you send a\nparenthese open or close form the other side and if you hold it you have shift.\u003c/p\u003e\n\u003cp\u003eI am not sure what happened to my config, but I could not get it to work with\nthe default macros offered \u003ccode\u003eSC_LSPO\u003c/code\u003e and \u003ccode\u003eSC_RSPO\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eI dug into the \u003ccode\u003eprocess_record_user()\u003c/code\u003e function hook to replicate the feature and\nadd one other \u0026rsquo;thing\u0026rsquo; where if you press another shift at the same time of the\nkeypress it will do a right bracket.\u003c/p\u003e","title":"qmk space cadet plus"},{"content":"Sometime the tiniest optimization makes a huge difference. When I am not using Emacs and dired I usually just use the shell with zsh to do all my file management.\nThis is fine and great but sometime when I need to select multiple files with different names, I would have to do a lot of tabs and selection or copy and paste to select properly the list of files I want to do operations on.\nI could use a terminal file manager like ranger or nnn but I never got into getting used to use them and even if I have it installed and configured I always forget to launch them.\nThere is a fantastic plug-in for zsh called zsh-fzf-history-search it let you plug fzf onto any zsh selection.\nI don\u0026rsquo;t need as much fzf in my shell but I want only sometime for selecting some not so easy to get files.\nI made the fzf-select-file plug-in for that :\nhttps://github.com/chmouel/fzf-select-file\nYou just hit the keys C-x C-f (ie: control-x followed by control-f) and it will spin up a fzf windows with the list of files provided by exa sorted by file modification time. A nice preview window of it file will be showed as well on the right with bat.\nIt automatically quote the files with space into it show it on your command line.\nFeel free to go on the github project to see how you can install it! There should have been a video here but your browser does not seem to support it. ","permalink":"https://blog.chmouel.com/posts/selecting-files-in-zsh-with-fzf/","summary":"\u003cp\u003eSometime the tiniest optimization makes a huge difference. When I am not using\nEmacs and dired I usually just use the shell with zsh to do all my file\nmanagement.\u003c/p\u003e\n\u003cp\u003eThis is fine and great but sometime when I need to select multiple\nfiles with different names, I would have to do a lot of tabs and selection or\ncopy and paste to select properly the list of files I want to do operations on.\u003c/p\u003e","title":"Selecting files in ZSH With fzf and exa"},{"content":"Every time I press the [TAB] key in my shell, it bothers me that nothing happens.\nI\u0026rsquo;m not very smart, so I often press the [TAB] key multiple times, hoping that maybe the seventh time will magically produce the completion that I expect.\nHowever, magic is not a computer function, and if a user or command line interface (CLI) author has not provided a completion function, nothing will ever happen.\nThis used to be a manual task, Users has contributed a huge collection of completion functions for multiple binaries. Here is some completions for ZSH (zsh has a large number of builtins completion too) and here is some for Bash.\nAll these functions are a good way to get nice completions for most popular Unix binaries.\nProviding shell completion when you are not an expert in shell scripting, can be a frustrating and difficult process. For example, I previously created zsh completions manually for the openshift client, but it was a tedious and time-consuming task. Just the process of having to keep it updated with the new flags and arguments could get very frustrating.\nAdvanced shell scripting can be difficult to learn, especially when you have to work with multiple shell environments, such as bash, zsh, powershell, and fish. This can greatly increase the complexity and difficulty of the task.\nThankfully, most modern CLI libraries now offer built-in shell completion mechanisms, which make it easier for developers to provide completion functionality for their programs.\nFor the purposes of this article, we will focus on the Go programming language and one of its most popular libraries for command line interface (CLI) parsing, Cobra.\nBasics you simply define a new command called completion and output the snippet used for the specific shell directly from the binary like this (full example here):\nfunc Command() *cobra.Command { cmd := \u0026amp;cobra.Command{ Use: \u0026#34;completion [SHELL]\u0026#34;, Short: \u0026#34;Prints shell completion scripts\u0026#34;, Long: desc, ValidArgs: []string{\u0026#34;bash\u0026#34;, \u0026#34;zsh\u0026#34;, \u0026#34;fish\u0026#34;, \u0026#34;powershell\u0026#34;}, Example: eg, Annotations: map[string]string{ \u0026#34;commandType\u0026#34;: \u0026#34;main\u0026#34;, }, Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), RunE: func(cmd *cobra.Command, args []string) error { switch args[0] { case \u0026#34;bash\u0026#34;: _ = cmd.Root().GenBashCompletion(cmd.OutOrStdout()) case \u0026#34;zsh\u0026#34;: _ = cmd.Root().GenZshCompletion(cmd.OutOrStdout()) case \u0026#34;fish\u0026#34;: _ = cmd.Root().GenFishCompletion(cmd.OutOrStdout(), true) case \u0026#34;powershell\u0026#34;: _ = cmd.Root().GenPowerShellCompletion(cmd.OutOrStdout()) } return nil }, } return cmd } This will define a new command called completion with the first argument being the target shell and the command will use the cobra library to output the specific completion snippet for that shell.\nHow it works cobra completion is most of the time smart enough to analyze your commands and output the right completion to it.\nWhen for example your cobra command has :\nValidArgs: []string{\u0026#34;bash\u0026#34;, \u0026#34;zsh\u0026#34;, \u0026#34;fish\u0026#34;, \u0026#34;powershell\u0026#34;}, It will suggest the args after the completion.\nIt will as well suggest all flags and subcommands to the right command.\nThis will get most of the time the job done for most user who are craving (like myself) for completion.\nAnd for the CLI author, this is easy and simple and no need to do any maintenance, you can simply forget it.\nThe way it works when the user press [TAB] the completion functions as generated for the target shell will ask the binary to complete the command with the hidden command __complete command argument to the binary and the binary itself will output then the completion using cobra library.\nDebugging If you want to debug the completion on how it works you can set the variable BASH_COMP_DEBUG_FILE to a filename and the completion function will output (even on zsh) any query it does to that filename.\nCustom completion Sometime you want to offer your own completion to a specific command.\nTo do so you need to define in your Command a ValidArgsFunction with this signature:\nValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { outputs := []{\u0026#34;hello\u0026#34;, \u0026#34;moto\u0026#34;} return outputs, cobra.ShellCompDirectiveNoFileComp }, the outputs can be anything dynamics you want. args is the arguments the user provides for example :\ncommand argument he\u0026lt;TAB\u0026gt;\nyou may want to be smart and provides completion on those arguments (I don\u0026rsquo;t because it was too annoying)\ncobra.ShellCompDirective return here is a cobra.ShellCompDirectiveNoFileComp but there is other type to mix your argument with for file completions on globing, but there is plenty of other ones, you can see all the definitions in the cobra source here.\nInstallation The best way to tell user to install the completion isn\u0026rsquo;t to say the much advised :\nsource \u0026lt;(binary completion bash/zsh)\nbecause that command can get quite slow.\nBut instead to actually put it in the completion path, for example on bash while using the bash-completions framework you tell the use to create the directory ~/.local/share/bash-completion and dump the completion there :\n${BINARY_NAME} completion bash \u0026gt; \u0026#34;${HOME}/.local/share/bash-completion/${BINARY_NAME}\u0026#34; on ZSH you need to make the user load the completion mechanism in its ~/.zshrc :\nautoload -U compinit; compinit mkdir -p ~/.zsh_completions/ fpath+=(~/.zsh_completions/) and dump the completion in that directory:\n${BINARY_NAME} completion zsh \u0026gt; \u0026#34;${HOME}/.zsh_completions/_${BINARY_NAME}\u0026#34; There is many ways to do this differently to different path and for the different shell, I\u0026rsquo;ll encourage you to do some digging for your target shell and shelll framework.\nPackaging All theses steps can get pretty tedious, the easiest way to consumes your project is to consumes packages. goreleaser makes it very easy.\nHere is some snippet of the yaml to generate the completion with cobra from the aur and brews recipe, I have as well a full and live example here:\nbrews: # homebrew packages - name: ${BINARY_NAME} install: | (bash_completion/\u0026#34;${BINARY_NAME}\u0026#34;).write output output = Utils.popen_read(\u0026#34;SHELL=zsh #{bin}/${BINARY_NAME} completion zsh\u0026#34;) (zsh_completion/\u0026#34;_${BINARY_NAME}\u0026#34;).write output prefix.install_metafiles aurs: # arch package - name: ${BINARY_NAME} [....] package: |- # completions mkdir -p \u0026#34;${pkgdir}/usr/share/bash-completion/completions/\u0026#34; mkdir -p \u0026#34;${pkgdir}/usr/share/zsh/site-functions/\u0026#34; ./${BINARY_NAME} completion zsh \u0026gt; ${BINARY_NAME}.zsh ./${BINARY_NAME} completion bash \u0026gt; ${BINARY_NAME}.bash install -Dm644 \u0026#34;${BINARY_NAME}.bash\u0026#34; \u0026#34;${pkgdir}/usr/share/bash-completion/completions/${BINARY_NAME}\u0026#34; install -Dm644 \u0026#34;${BINARY_NAME}.zsh\u0026#34; \u0026#34;${pkgdir}/usr/share/zsh/site-functions/_${BINARY_NAME}\u0026#34; Other libraries I have successfully added completion to other CLIs using other library.\nwith the urfave/cli library on the gosmee binary. I have defined a completion command here which output this embedded static completion and made sure to enable it at the top level. Installation is about the same as how it works on Cobra. on Rust, using the ubiquitous clap-rs I have snazy using the derive api , it define a completion command using the clap_complete crate and then use the generator to output the snippet Hack the completion by providing your own. A nice hack I figured was to be able to provide extra completion to a binary using the cobra library. For example I wanted to be able to get the pull request number and title when I press tab to the gh binary. The way I did this is to wrap the binary around with a shell script and output the completion I wanted.\nThe shell script on how I did that is available here: https://github.com/chmouel/chmouzies/blob/main/git/gh-completer you simply need to install it in your path as an executable called gh before in the PATH where you real gh is located. There should have been a video here but your browser does not seem to support it. ","permalink":"https://blog.chmouel.com/posts/cobra-completions/","summary":"\u003cp\u003eEvery time I press the \u003ccode\u003e[TAB]\u003c/code\u003e key in my shell, it bothers me that nothing happens.\u003c/p\u003e\n\u003cp\u003eI\u0026rsquo;m not very smart, so I often press the \u003ccode\u003e[TAB]\u003c/code\u003e key multiple times, hoping that\nmaybe the seventh time will magically produce the completion that I expect.\u003c/p\u003e\n\u003cp\u003eHowever, magic is not a computer function, and if a user or command line\ninterface (CLI) author has not provided a completion function, nothing will ever\nhappen.\u003c/p\u003e","title":"shell completions with go cobra library"},{"content":"I have been meaning to write an article about tools that I have developed lately to make it easier for my day to day life work.\nBeing a so called \u0026ldquo;Kubernetes cloud native developer\u0026rdquo; (don\u0026rsquo;t laugh at the title because I do) I have to watch a log of controller logs. Most controller logs output in JSON format which is a nice tool for computers but not straightforward to parse to the eyes of the mere mortals.\nAs I was getting more annoyed trying to spot my errors in my controller, I wrote a python script in a haste called it sugarjazy.\nWhat it did is to make the log output from this :\nto this :\nI was happy with it and it did job (maybe a bit slow), python makes it easy to iterate, the cheer nature of the language being all dynamic and flexible in all kind of way made it easy to parse any sorts of json log. I think I spent 30 minutes to write it, 30 minutes to package it and be finished and happy with it.\nI was at the same time trying to find a pet project to learn rust and I thought it would be a good idea to rewrite it in rust.\nand boy I was in for a ride…\nI read tons and tons of materials on rust, I read the book, I read blog articles, I read stackoverflow obscure answer to anything, I abused github\u0026rsquo;s codeassist. I didn\u0026rsquo;t actually understand what I was doing but after a few days I was able to write a basic version of it in rust.\nAfter that I improved and tried to iterate and improve it, trying to figure out the best practice and the best way to do things.\nIt still IMHO pretty bad and probably yet another rewrite to make it proper Rust, but the good thing with Rust is when it compiles you are pretty confident it\u0026rsquo;s not going to crash and burn.\nThe naming of the tool is random called snazy (because I was lazy to find a better name) and it does what the python version is doing but in rust (in a much faster way) with a lot more features.\nHere is a list of them :\nWhen you use the -r flags (and you can have many of them) you tell snazy to highlight a regexp in the logs to get to highlight the words you need when it appears. It would colour the word differently for each regexp you use : You can skip some lines you don\u0026rsquo;t want to see with the -S flag.\nYou can filter the log levels you want to see with the -f flag (many -f can be specified for multiple levels)\nYou can have an action when some word appears. This is pretty useful for example to be able to get notified when something was successful or failed. For example on OSX you can do something like this :\nsnazy --action-regexp \u0026#34;script(s)?\\s*.*has successfully ran\u0026#34; --action-command \u0026#34;osascript -e \u0026#39;display notification \\\u0026#34;{}\\\u0026#34;\u0026#39;\u0026#34; and whenever we\u0026rsquo;ve the regexp \u0026ldquo;script has successfully ran\u0026rdquo; in the logs, you will get a notification on your mac. (see notify-send for how to do that on Linux)\nIf you want some fancy emojis instead of just boring messages, you can use the --level-symbols flag (or set the environment variable SNAZY_LEVEL_SYMBOLS in your shell) : One other feature that\u0026rsquo;s most useful for us \u0026ldquo;cloud native developers\u0026rdquo; having to watch multiple containers at the same time is the integration with kail which let you to do that and many more. Whenever snazy detects that you are piping the output of kail it will automatically show it.\nThis will get the output from kail like this:\nto this :\nThe blue string is the namespace/pod[container] format, if that\u0026rsquo;s a bit too verbose you can use the flag --kail-prefix-format or SNAZY_KAIL_PREFIX_FORMAT to change it to something else. For example me, I am only interested with pods so I have this set :\nexport SNAZY_KAIL_PREFIX_FORMAT=\u0026#34;{pod}\u0026#34; and I get this :\nI probably should write about my ongoing experience learning Rust and figuring release and packaging and all that stuff but I think I will do that in another article.\nUntil then feel free to grab snazy from here: https://github.com/chmouel/snazy and happy log viewing (if that\u0026rsquo;s a thing you can be happy with :))\n","permalink":"https://blog.chmouel.com/posts/snazy-log-viewer/","summary":"\u003cp\u003eI have been meaning to write an article about tools that I have developed\nlately to make it easier for my day to day life work.\u003c/p\u003e\n\u003cp\u003eBeing a so called \u0026ldquo;Kubernetes cloud native developer\u0026rdquo; (don\u0026rsquo;t laugh at the title\nbecause I do) I have to watch a log of controller logs. Most controller logs\noutput in JSON format which is a nice tool for computers but not straightforward to\nparse to the eyes of the mere mortals.\u003c/p\u003e","title":"Snazy - a snazzy json log viewer"},{"content":"I was talking with a colleague about Rust and we were wondering (since we are both learning the language) how error handling compares to Go.\nChaining error in Go Go\u0026rsquo;s best practice when you want to chain multiple errors is to \u0026ldquo;wrap\u0026rdquo; them.\nFor example let\u0026rsquo;s say you have this function returning an error:\nfunc do_something() err { value := \u0026#34;value\u0026#34; if value != \u0026#34;expected\u0026#34; { return fmt.Errorf(\u0026#34;this was not expected\u0026#34;) } } when we call the function do_something() from another function, we want to add context to it and to do so we will wrap it around it with the \u0026ldquo;%w\u0026rdquo; directive:\nfn start_doing_something() err { err := do_something() if err != nil { return fmt.Errorf(\u0026#34;I got an error while trying to do something: %w\u0026#34;, err) } } Error chaining in Rust So now how do we do this in Rust?\nIt does not seems there is any built-in way to do this but you can use the vastly popular crates called anyhow for it.\nIn this case it\u0026rsquo;s not called wrapping but context (which is a confusing overused term imho) and here is an example :\nuse anyhow::Context; #[derive(thiserror::Error, Debug)] pub enum MyErr { #[error(\u0026#34;This is the first error\u0026#34;)] FirstError, #[error(\u0026#34;This is the middle error\u0026#34;)] MidError, #[error(\u0026#34;This is the final error\u0026#34;)] FinalError, } fn first() -\u0026gt; anyhow::Result\u0026lt;(), MyErr\u0026gt; { Err(MyErr::FirstError) } fn second() -\u0026gt; anyhow::Result\u0026lt;(), anyhow::Error\u0026gt; { first().context(MyErr::MidError) } fn finally() -\u0026gt; anyhow::Result\u0026lt;(), anyhow::Error\u0026gt; { second().context(MyErr::FinalError) } fn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; { finally()?; Ok(()) } We first make our own enum of custom errors. The enum has a derive on another crates called thiserror. This crates allows you to have human friendly error message without having to do too much work for it.\nstarting from the bottom on the main function we return and \u0026ldquo;Box\u0026rdquo; all our errors with anyhow::Results this will get all error to it.\nWe call the finally function with the \u0026ldquo;?\u0026rdquo; operator at the end. It\u0026rsquo;s a shorthand to say :\nif it\u0026rsquo;s Ok, then yeah please go on and continue do your work. if it\u0026rsquo;s not then return the error. from the finally function we call another function called second, they are both adding a context to the error to let the user know where this comes from. This only happen if we are erroring. If we were Ok() we would not get any error. The final output will looks like this:\n% cargo run -q Error: This is the final error Caused by: 0: This is the middle error 1: This is the first error with the help of anyhow and thiserror we are nicely showing the chain of errors and what caused it.\nMy humble comparaison between Go and Rust error chaining The go way is definitely more idiomatic and much easier to write and understand than the the rust way. However the Rust way is more elegant and I feel in the long term will be more robust if we have to do some refactoring.\n","permalink":"https://blog.chmouel.com/posts/rust-errorhandling/","summary":"\u003cp\u003eI was talking with a \u003ca href=\"https://www.sebastien-han.fr/blog/\"\u003ecolleague\u003c/a\u003e about Rust\nand we were wondering (since we are both learning the language) how error\nhandling compares to Go.\u003c/p\u003e\n\u003ch2 id=\"chaining-error-in-go\"\u003eChaining error in Go\u003c/h2\u003e\n\u003cp\u003eGo\u0026rsquo;s best practice when you want to chain multiple errors is to \u0026ldquo;wrap\u0026rdquo; them.\u003c/p\u003e\n\u003cp\u003eFor example let\u0026rsquo;s say you have this function returning an error:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#50fa7b\"\u003edo_something\u003c/span\u003e() err {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e value \u003cspan style=\"color:#ff79c6\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;value\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ff79c6\"\u003eif\u003c/span\u003e value \u003cspan style=\"color:#ff79c6\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;expected\u0026#34;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ff79c6\"\u003ereturn\u003c/span\u003e fmt.\u003cspan style=\"color:#50fa7b\"\u003eErrorf\u003c/span\u003e(\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;this was not expected\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003ewhen we call the function \u003ccode\u003edo_something()\u003c/code\u003e from another function, we want to\nadd context to it and to do so we will wrap it around it with the \u0026ldquo;%w\u0026rdquo;\ndirective:\u003c/p\u003e","title":"Error chaining with Rust and Go"},{"content":"On Pipelines as Code we started to get a nice documentation website on :\nhttps://pipelinesascode.com\nThe website is statically generated with Hugo and hosted on CloudFares Pages using the markdown files from the repository.\nSo far that\u0026rsquo;s a pretty standard stack, but what we wanted is to be able to get preview URLS like on Netlify or other CIs\nThere is a nice check box, that says \u0026ldquo;Generate Preview URL on Pull Request\u0026rdquo; which seems to do what we want but it doesn\u0026rsquo;t. So far it seems that Pull Request coming from forks are not processed only the one from branch coming from the same repository where the pull request is.\nSince we do our own dogfood and we want anyway to use Pipelines as Code and Tekton as much as possible, I started to implement a preview environement mechanism to get a link with the changes from the pull request if the doc/ folder is modified inside the PR.\nI have again used my toy webserver, go-simple-uploader (which we have been used previously for artifacts caching) to serve the static HTML generate with hugo, but first I had to make a few changes to it:\nAdded an OpenShift Route to directly expose it to the internet. It previously was only accessible via the local kubernetes service across pods.\nI added a capability to be able to send a tarball when uploading, so we can upload a tarball of a folder and stream directly to go-simple-uploader which will uncompress it on the fly.\nI modified the server to add authentication to the /upload endpoint via a username and password. Just to make sure nobody abuse from it.\nSo far so good and after having the new image deployed on our cluster, I modified our Pipelines as Code/Tekton template in the .tekton directory to get those preview URLS generated.\nThe whole bits added is here :\n- name: build-doc runAfter: - fetchit taskSpec: workspaces: - name: source steps: - name: hugo-gen image: quay.io/thegeeklab/hugo workingDir: $(workspaces.source.path) script: | git fetch origin main \u0026amp;\u0026amp; \\ git diff --name-only FETCH_HEAD | grep -q \u0026#39;^docs/\u0026#39; || exit 0 cd docs sed -i \u0026#39;1acanonifyURLs = true\u0026#39; config.toml hugo --gc --minify -d {{ revision }} -b https://preview-pipelines-as-code-ci.apps.paac.devcluster.openshift.com/docs/{{ revision }} echo \u0026#34;Preview URL: https://preview-pipelines-as-code-ci.apps.paac.devcluster.openshift.com/docs/{{ revision }}\u0026#34; - name: upload-to-static-server # it has curl and we already pulled it image: registry.redhat.io/rhel8/go-toolset:1.16.12-7 workingDir: $(workspaces.source.path) env: - name: HUB_TOKEN valueFrom: secretKeyRef: name: \u0026#34;nightly-ci-github-hub-token\u0026#34; key: \u0026#34;hub-token\u0026#34; - name: UPLOADER_UPLOAD_CREDENTIALS valueFrom: secretKeyRef: name: \u0026#34;uploader-upload-credentials\u0026#34; key: \u0026#34;credentials\u0026#34; script: | cd docs [[ -d {{ revision }} ]] || exit 0 tar czf - {{ revision }} | curl -u ${UPLOADER_UPLOAD_CREDENTIALS} -F path=docs -F targz=true -X POST -F file=@- http://uploader:8080/upload # Post as status set +x curl -H \u0026#34;Authorization: Bearer ${HUB_TOKEN}\u0026#34; -H \u0026#39;Accept: application/vnd.github.v3+json\u0026#39; -X POST https://api.github.com/repos/{{repo_owner}}/{{repo_name}}/statuses/{{revision}} -d \u0026#39;{\u0026#34;state\u0026#34;: \u0026#34;success\u0026#34;, \u0026#34;target_url\u0026#34;: \u0026#34;https://preview-pipelines-as-code-ci.apps.paac.devcluster.openshift.com/docs/{{ revision }}\u0026#34;, \u0026#34;description\u0026#34;: \u0026#34;Generated with brio.\u0026#34;, \u0026#34;context\u0026#34;: \u0026#34;Pipelines as Code Preview URL\u0026#34;}\u0026#39; On the first step we start detecting if we had any changes in the doc/ folder using some git trickery with FETCH_HEAD, if we didn\u0026rsquo;t have any we will just exit 0 and skip it.\nIf we have some changes, we add a setting to the hugo config.toml file to set cannonifyURLs=true so we get canon urls instead of relative.\nWe are then generating the documentation using hugo and we add the new base which goes to our public route URL and the commit sha (via Pipelines as Code variable expansion).\nWe have another step just after, that would use the username and password from a secret on a cluster and tar gz the new docs/ folder on the file to go-simple-uploader which will upload it and uncompress it on the service.\nAt the end to be able to preview URL, I wasn\u0026rsquo;t sure which place to put it, we could do slack or as a comment of the pull request but this quickly become ignore and spammy. Instead, I used the GitHub statuses API to post the link inside the pull request in the CI status place of GitHub, just a click away to be previewed.\nLinks Pipelines as Code Pipelines as Code pull request template Go Simple Uploader Screenshot ","permalink":"https://blog.chmouel.com/posts/generating-preview-environment-with-tekton/","summary":"\u003cp\u003eOn \u003ca href=\"htps://github.com/openshift-pipelines/pipelines-as-code\"\u003ePipelines as\nCode\u003c/a\u003e we started to\nget a nice documentation website on :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://pipelinesascode.com\"\u003ehttps://pipelinesascode.com\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eThe website is statically generated with\n\u003ca href=\"https://gohugo.io/\"\u003eHugo\u003c/a\u003e and hosted on \u003ca href=\"https://pages.cloudfare.com\"\u003eCloudFares\nPages\u003c/a\u003e using the markdown files from the\nrepository.\u003c/p\u003e\n\u003cp\u003eSo far that\u0026rsquo;s a pretty standard stack, but what we wanted is to be able to get\npreview URLS like on \u003ca href=\"https://docs.netlify.com/site-deploys/deploy-previews/\"\u003eNetlify\u003c/a\u003e\nor other \u003ca href=\"https://docs.gitlab.com/ee/ci/review_apps/\"\u003eCI\u003c/a\u003es\u003c/p\u003e\n\u003cp\u003eThere is a nice check box, that says \u0026ldquo;Generate Preview URL on Pull Request\u0026rdquo;\nwhich seems to do what we want but it doesn\u0026rsquo;t. So far it seems that \u003ccode\u003ePull Request\u003c/code\u003e coming from forks are not processed only the one from branch coming\nfrom the same repository where the pull request is.\u003c/p\u003e","title":"Generating Preview Environments with Tekton"},{"content":"There is a lot of zsh plugin manager around :\nhttps://github.com/unixorn/awesome-zsh-plugins#frameworks\nThey all allow you to add cool new features to your shell easily and for authors to easily share their plugin with users and frameworks.\nWhile a lot of people are probably using frameworks like oh-my-zsh which does everything for them with minimal setup.\nBut since I have been using zsh since much before than those frameworks existed, I always ran my custom config.\nHistorically, I went for the \u0026ldquo;default\u0026rdquo; one (or it seemed that way at the time) called zplug. It allows you to specify the plugins you want and manage them easily. But zplug is a lot more things, it offers many more features like installing binary from the internet manage some configuration edge cases and other things. And it slowwws, I didn\u0026rsquo;t realize it at first but more I used it and more I realized that opening a shell would take me a second or two sometime. Moreover, last release was 5 years ago.\nI looked a bit more into it and figured it was actually pretty simple to dumb it down and write my own. So I wrote one and called it \u0026quot;vtplug\u0026quot; for \u0026ldquo;very tiny plugin manager\u0026rdquo; and since it\u0026rsquo;s so small it can be installed directly by copying it in your config as function from here :\nhttps://gitlab.com/chmouel/zsh-config/blob/master/functions/vtplug\nto use it you first need to copy the function in your config and then have a variable that has all the plugins you want to install, which for me is :\nZSH_PLUGINS=( agkozak/zsh-z zsh-users/zsh-autosuggestions chmouel/chmoujump chmouel/kubectl-config-switcher b4b4r07/emoji-cli::emoji-cli.zsh joshskidmore/zsh-fzf-history-search ) It currently only support public GitHub based plugins so effectively add the https://github.com/ to the repo/owner specified in ZSHZ_PLUGINS variable.\nYou then may want to add some configuration of the plugin right after, like this, I have those by you may want to have a look at each plugin READMEs to see which settings you may want to set :\nZSH_TAB_TITLE_ONLY_FOLDER=true ZSH_TAB_TITLE_DEFAULT_DISABLE_PREFIX=true ZSHZ_DATA=${HOME}/.cache/zsh-cache-z EMOJI_CLI_USE_EMOJI=true ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE=\u0026#34;fg=#9400d3\u0026#34; ZSH_FZF_HISTORY_SEARCH_BIND=\u0026#34;^S\u0026#34; EMOJI_CLI_KEYBIND=\u0026#34;^X^S\u0026#34; and then simply execute vtplug after that :\n-$ vtplug vtplug would then load all plugins and check them out in ~/.cache/zsh/repos/ if it wasn\u0026rsquo;t checked out before.\nIf you need to update the plugin you just do a :\nvtplug -u and it will run a git pull in those repos.\nIt\u0026rsquo;s simple as that, and load in milliseconds.\nMy whole zsh config is located here if you want to have a look:\nhttps://gitlab.com/chmouel/zsh-config\nIf you really want a plugin manger that does much more and probably more flexible, perhaps look at antidote which seems to be pretty fast and feature full.\n","permalink":"https://blog.chmouel.com/2022/03/18/vtplug-a-very-dumb-and-tiny-zsh-plugin-manager/","summary":"\u003cp\u003eThere is a lot of zsh plugin manager around :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/unixorn/awesome-zsh-plugins#frameworks\"\u003ehttps://github.com/unixorn/awesome-zsh-plugins#frameworks\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eThey all allow you to add cool new features to your shell easily and for authors to\neasily share their plugin with users and frameworks.\u003c/p\u003e\n\u003cp\u003eWhile a lot of people are probably using frameworks like \u003ccode\u003eoh-my-zsh\u003c/code\u003e which does\neverything for them with minimal setup.\u003c/p\u003e\n\u003cp\u003eBut since I have been using zsh since \u003ca href=\"https://zsh.sourceforge.io/Etc/changelog-4.0.html\"\u003emuch before\u003c/a\u003e than those frameworks\nexisted, I always ran my custom config.\u003c/p\u003e","title":"vtplug a very dumb and tiny zsh plugin manager"},{"content":"With the TektonCD CLI we have a system of \u0026ldquo;plugins\u0026rdquo;, it\u0026rsquo;s the same very simple CLI plugin system you have with git or kubectl, if you do a :\nkubectl blah foo --bar\nsince kubectl knows it doesn\u0026rsquo;t have the blah command will try to go over the filesystem paths in your $PATH environment and sees if there is a binary called kubectl-blah and if it finds it will pass the arguments to the binary which effectively become :\nkubectl-blah foo --bar\nall very transparent and easy to install and use.\nThe problem with this is that the user doesn\u0026rsquo;t really knows about it and discovery is limited unless the user knows about the command already.\nkubectl added a plugin list argument to list easily all plugins available (or in kubectl case you can just use krew to manage kubectl plugins).\nFor tektoncd-cli we wanted to shows it directly in the Root commands help. So when the user type tkn help it will shows the plugin list.\nSince tektoncd-cli is using the spf13/cobra library, and the lib being very extensible, it wasn\u0026rsquo;t hard to extend the help system.\nYou first need to define a custom \u0026ldquo;usage template\u0026rdquo;, the template we have is this one :\nhttps://github.com/chmouel/tektoncd-cli/blob/add-available-plugins-from-path/pkg/cmd/root.go#L46\nIt adds this snippet to the default template :\n{{if gt (len pluginList) 0}} Available Plugins: {{- range pluginList}} {{.}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} The pluginList template variable is a slice of plugins which is discovered in this function :\nfunc addPluginsToHelp() { pluginlist := []string{} paths := strings.Split(os.Getenv(\u0026#34;PATH\u0026#34;), \u0026#34;:\u0026#34;) // go over all paths in the PATH environment // and add them to the completion command for _, path := range paths { // list all files in path files, err := ioutil.ReadDir(path) if err != nil { continue } // add all files that start with tkn- for _, file := range files { if strings.HasPrefix(file.Name(), \u0026#34;tkn-\u0026#34;) { basep := strings.ReplaceAll(file.Name(), \u0026#34;tkn-\u0026#34;, \u0026#34;\u0026#34;) fpath := filepath.Join(path, file.Name()) info, err := os.Stat(fpath) if err != nil { continue } if info.Mode()\u0026amp;0o111 != 0 { pluginlist = append(pluginlist, basep) } } } } cobra.AddTemplateFunc(\u0026#34;pluginList\u0026#34;, func() []string { return pluginlist }) } what it does is, go over the environement variable PATH gets all directories from there, check all executable binaries that starts with the \u0026ldquo;tkn-\u0026rdquo; prefix and add it to the template variable pluginList inside a slice of strings.\nThe plugin command will show then nicely when doing tkn help. for example with the Pipelines as Code CLI installed, I will get this :\n$ tkn help CLI for tekton pipelines Usage: tkn [flags] tkn [command] Available Commands: bundle Manage Tekton Bundles chain Manage Chains clustertask Manage ClusterTasks condition Manage Conditions eventlistener Manage EventListeners hub Interact with tekton hub pipeline Manage pipelines pipelinerun Manage PipelineRuns resource Manage pipeline resources task Manage Tasks taskrun Manage TaskRuns triggerbinding Manage TriggerBindings triggertemplate Manage TriggerTemplates Other Commands: completion Prints shell completion scripts version Prints version information Available Plugins: pac Flags: -h, --help help for tkn Use \u0026quot;tkn [command] --help\u0026quot; for more information about a command. There is maybe area for improvement to be able to get a small snippet of what the plugin is actually doing in the future but so far having it in the root help is a great boost for CLI discoverability.\nThe full PR on tektoncd cli is here if you wanted to look at the full code and tests :\nhttps://github.com/tektoncd/cli/pull/1535\n","permalink":"https://blog.chmouel.com/2022/03/18/show-plugins-list-to-a-cli-when-using-gos-cobra-library/","summary":"\u003cp\u003eWith the TektonCD CLI we have a system of \u0026ldquo;plugins\u0026rdquo;, it\u0026rsquo;s the same very simple CLI plugin system you have with git or kubectl, if you do a :\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ekubectl blah foo --bar\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003esince kubectl knows it doesn\u0026rsquo;t have the blah command will try to go over the\nfilesystem paths in your \u003ccode\u003e$PATH\u003c/code\u003e environment and sees if there is a binary\ncalled \u003ccode\u003ekubectl-blah\u003c/code\u003e and if it finds it will pass the arguments to the binary\nwhich effectively become :\u003c/p\u003e","title":"Show plugins list to a CLI when using go’s cobra library"},{"content":"Expanding on my previous blog post on getting buildah to run with user namespaces or as rootless. There is another important security topic to talk about is how to run everything on OpenShift Pipeline as non root and not just the buildah task.\nOn OpenShift Pipelines we made the conscious decision to run all the TaskRuns and Pipelinerun by default under a custom ServiceAccount called pipelines.\nThat\u0026rsquo;s it, unless overridden by the user in its pipelinerun or taskrun, it will use the pipelines ServiceAccount which has a few elevated privileges..\nThe ServiceAccount has a custom SecurityContext (SCC) called pipelines-scc bound to it which allows running an image as any UUID.\nWe added this service account because building and pushing images to a registry is a very common use case on OpenShift Pipelines and to get buildah working under OpenShift Pipelines root was previously the only solution to run buildah.\nOne side effect of this SCC is that any images running on Openshift Cluster, unless the container image has a “USER $user” in its dockerfile will run as root. So even standard tasks like the “git-clone” tasks end up checking out code as root when it really doesn’t need to.\nIf you want to run all your pipelines as non root (and you probably want it) and the images you are using have the ability to do it, you can make the pipelines-scc running everything by default as the user 1000 by modifying it.\nSimply edit the scc as cluster-admin with oc edit scc pipelines-scc and modify the runAsUser section with :\nrunAsUser: type: MustRunAs uid: 1000 The ClusterTask shipped with openshift-pipelines needs to have a slight modification when running as uid 1000, to get the volumeMount path corrected, you can grab the modified buildah task from here :\nhttps://gist.github.com/chmouel/8242806100ffa7164bb63d7d5b0a593d#file-buildah-task-yaml\nExample Here is an example pipeline :\nhttps://github.com/chmouel/scratchmyback/blob/f6a0329832ee55a339a7acec8095aba276d651a5/.tekton/pipeline.yaml\nIt has three tasks.\nA git repository clone using the (modified) git-clone cluster task A simple task as taskspec which tests if we can write to the workspace where we have the source code checkout. A buildah task building a container and pushing it to the internal openshift registry. When you run this pipeline you can see that everything with run as non root as user 1000 :\n% tkn pr logs -Lf [clone : clone] ++ id [clone : clone] + echo \u0026#39; Running as uid=1000 gid=0(root) ps=0(root),1000670000\u0026#39; [clone : clone] Running as uid=1000 gid=0(root) groups=0(root),1000670000 [....] [task-spec : task-spec] ++ id [task-spec : task-spec] + echo \u0026#39; I can write here I am uid=1000(1000) 0(root) groups=0(root),1000670000\u0026#39; [task-spec : task-spec] + ls -l . [task-spec : task-spec] total 52 [....] userns-buildah : build] ++ id [userns-buildah : build] Running as USER ID uid=1000(build) gid=1000(build) ps=1000(build),1000670000 [userns-buildah : build] + echo \u0026#39; Running as USER ID uid=1000(build) 1000(build) groups=1000(build),1000670000\u0026#39; [userns-buildah : build] + buildah --storage-driver=vfs bud --format=oci --tls-fy=true --no-cache -f ./Dockerfile -t image-registry.openshift-image-stry.svc:5000/test/userns:latest . [userns-buildah : build] STEP 1: FROM registry.access.redhat.com/ubi8/ubi-mal:8.5 [...] [userns-buildah : build] Storing signatures [userns-buildah : build] STEP 2: RUN id [userns-buildah : build] uid=0(root) gid=0(root) groups=0(root) [userns-buildah : build] STEP 3: COMMIT image-registry.openshift-image-stry.svc:5000/test/userns:latest [userns-buildah : build] --\u0026gt; 3637c099315 [userns-buildah : build] c0993158a555352c26ca9f8ed6406f916a708511b95f6135a8ba02432b96 [userns-buildah : push] ++ id [userns-buildah : push] + echo \u0026#39; Running as USER ID uid=1000(build) 1000(build) groups=1000(build),1000670000\u0026#39; [userns-buildah : push] Running as USER ID uid=1000(build) gid=1000(build) ps=1000(build),1000670000 [userns-buildah : push] + buildah --storage-driver=vfs push --tls-verify=true --stfile /workspace/source/image-digest image-registry.openshift-image-stry.svc:5000/test/userns:latest docker://image-registry.openshift-image-stry.svc:5000/test/userns:latest [...] [userns-buildah : push] Writing manifest to image destination [userns-buildah : push] Storing signatures [...] Mixing it with some tasks with root requirement In some situation you will need to be able to mix it with some tasks in your pipeline that mayb needs the root access.\nYou can do this by createing a new ServiceAccount with elevated rights as needed (ie: like cluster-admin but you may want to lower this).\nIn your PipelineRun you can use a taskRunSpecs to force it to use that serviceaccount instead of the normal one :\ntaskRunSpecs: - pipelineTaskName: task-that-needs-root-access taskServiceAccountName: elevated-right-sa and the task task-that-needs-root-access will be run with the elevated-right-sa all other tasks will be run with the default SA pipelines\nConclusion There may be some restrictions when running rootless buildah where some images may not work but for most use cases this it should not need elevated priviliges to run your Tasks.\nWe are still exploring different solutions to make this more flexible and hopefully make this easier to set-up\n","permalink":"https://blog.chmouel.com/2022/03/07/running-tasks-as-non-root-on-openshift-pipelines/","summary":"\u003cp\u003eExpanding on my \u003ca href=\"https://blog.chmouel.com/2022/01/25/user-namespaces-with-buildah-and-openshift-pipelines/\" title=\" previous blog post\"\u003eprevious blog post\u003c/a\u003e on getting buildah to run with user namespaces or as rootless. There is another important security topic to talk about is how to run everything on OpenShift Pipeline as non root and not just the buildah task.\u003c/p\u003e\n\u003cp\u003eOn OpenShift Pipelines we made the conscious decision to run all the TaskRuns and Pipelinerun by default under a custom ServiceAccount called \u003ccode\u003epipelines\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eThat\u0026rsquo;s it, unless overridden by the user in its pipelinerun or taskrun, it will use the \u003ccode\u003epipelines\u003c/code\u003e ServiceAccount which has a few elevated privileges..\u003c/p\u003e","title":"Running tasks as non root on OpenShift Pipelines"},{"content":"In 2022 one of the hottest topic around CI is how to secure it every steps along the way.\nThe so-called supply chain attacks have been more and more an attack vector for bad actor whereas providers need to make sure every piece of the Integration is secure.\nOne area that was identified as something we can improve with Openshift and containers in general is when running as root on the container may expose the host and process in that container may be able to mingle with other resources.\nAnd this is a problem for us at the OpenShift pipelines team since this is what our shipped buildah ClusterTask does by default.\nIdeally we would like to run everything rootless with a randomized user id, like what Openshift does by default. But there are some use-cases needing to run as root on the container but still be secure on the host.\nIn this article we will focus on Buildah but some of those techniques can be reused for different workloads, bear in mind that some of those technologies can be pretty bleeding edge, and you may encounter some unexpected side effects, but for the sake of a secure pipeline I would encourage you to try this out and see how it works out for you.\nRunning as root in a user namespace Running in a user namespace is when you are running the container as root (user id 0) but as user on the host.\nOpenShift is using CRI-O as its container engine. And CRI-O has now a workload feature to be able to let the pod know it wants to run “user namespaced”.\nUser namespaces is not a new feature; it has been here for a while, see for example this 2013 article from the lwn introducing it. But it took some time to be included in RHEL (from RHEL8) and integrated into OpenShift (support was added in Openshift 4.10). If you want to try this feature manually you can refer to this article explaining how it works .\nTo run as a user in a namespace with Openshift Pipelines you need to be able to pass the annotations expected by CRIO to get the pods running user namespaced.\nYou can directly edit the buildah ClusterTask with “oc edit clustertask buildah” to add this to all users, or export the clustertask as a task to a specific Namespace.\nWith the latest tkn create from feature you can easily automate it :\noc new-project test $ tkn task create --from=buildah $ oc edit task buildah And add the annotations to the task :\nannotations: io.kubernetes.cri-o.userns-mode: \u0026#34;auto\u0026#34; io.openshift.builder: \u0026#34;true\u0026#34; Now if you are running the (currently unreleased) latest Openshift Pipelines 1.7 on OpenShift 4.10, you will see your buildah container running like before as root.\nBut if you adventure yourself behind the scene on the host of the pod :\n# get the nodename where the buildah pod is with \u0026#34;oc get pod -o wide\u0026#34; $ oc debug nodes/nodename $ chroot /host $ lsns -t user OpenShift and CRIO did their magic and ran your pod in a “user namespace”.\nRunning as rootless in container To be able to run as rootless inside a container; where you run as a user inside the container, you need your container to do some setup to add the subuid and subgid provided from the latest shadow-utils package.\nThankfully the public image based on Red Hat UBI has everything already setup for us in its Containerfile\nYou have an extra step to take tho, you need to “force” running the container as the “build” user, because if we start to leave it to the default it will be “randomed” and would not have the setup needed to run as non-root.\nEdit directly or export to a specific namespace the buildah clustertask as described in the previous section. Add this securityContext to each build and push steps :\nsecurityContext: runAsUser: 1000 Since we are now going to be building as user, buildah will keep its image caching in /home/build/.local/cache so instead of volume mounting /var/lib/containers we are going to change the mountPath on build and push steps to the user one :\nvolumeMounts: - name: varlibcontainers mountPath: /home/build/.local/share/containers And for demo purpose I have added this line at the beginning of the script task :\necho \u0026quot;Running as USER ID id\u0026quot;\nI have then created a ConfigMap workspace with a sample dockerfile and a sample taskrun to be able to test it.\nWhen running it, I can see my image is running as user :\n% tkn tr logs -Lf buildah-run [build] ++ id [build] Running as USER ID uid=1000(build) gid=1000(build) groups=1000(build),1000690000 [build] + echo \u0026#39;Running as USER ID uid=1000(build) gid=1000(build) groups=1000(build),1000690000\u0026#39; [build] + buildah --storage-driver=vfs bud --format=oci --tls-verify=true --no-cache -f ./Dockerfile -t image-registry.openshift-image-registry.svc:5000/test/buildahuser . [build] STEP 1: FROM registry.access.redhat.com/ubi8/ubi AS buildah-runner [build] Getting image source signatures [build] Checking if image destination supports signatures [build] Copying blob sha256:adffa69631469a649556cee5b8456f184928818064aac82106bd08bd62e51d4e [build] Copying blob sha256:26f1167feaf74177f9054bf26ac8775a4b188f25914e23bda9574ef2a759cce4 [build] Copying config sha256:fca12da1dc30ed8e7d03afb84b287fc695673fff9c04bfcb2ff404b558670a36 [build] Writing manifest to image destination [build] Storing signatures [build] STEP 2: RUN dnf -y update \u0026amp;\u0026amp; dnf -y install git \u0026amp;\u0026amp; dnf clean all [build] Updating Subscription Management repositories. […] More security with a custom SCC Now these steps are working because currently on Openshift Pipelines we make all taskrun/pipelinerun running automatically as the pipelines serviceAccount which has the pipelines SecurityContext that allows running as any user.\nWe have added those rights to have it easy to to migrate pipelines that needs to be run or build as root, but if you like to further lock down your installation you can only allow running container as the user 1000 if the pod is asking (or the container image forces it) for it and don’t let the container running as root by default.\nTo do so you need to edit the pipelines-scc and modify the runAsUser and seLinuxContext section to MustRunAs to uid 1000 :\nrunAsUser: type: MustRunAs uid: 1000 seLinuxContext: type: MustRunAs The pipeline serviceaccount will only allow running images as user 1000 and not as root anymore, if the images are not running as 1000 they will berandomed out as user id.\nTemplates examples This gist reference all the files I am mentioned int his article\nBuildah.yaml force running as user build : https://gist.github.com/chmouel/8242806100ffa7164bb63d7d5b0a593d#file-buildah-task-yaml\nTaskrun and Dockerfile configmap workspace: https://gist.github.com/chmouel/8242806100ffa7164bb63d7d5b0a593d#file-buildah-taskrun-configmap-yaml\nModified scc only allow running as user 1000: https://gist.github.com/chmouel/8242806100ffa7164bb63d7d5b0a593d#file-scc-runasuser-drop-anyuid-yaml\n","permalink":"https://blog.chmouel.com/2022/01/25/user-namespaces-with-buildah-and-openshift-pipelines/","summary":"\u003cp\u003eIn 2022 one of the hottest topic around CI is how to secure it every steps along the way.\u003c/p\u003e\n\u003cp\u003eThe so-called supply chain attacks have been more and more an attack vector for bad actor whereas providers need to make sure every piece of the Integration is secure.\u003c/p\u003e\n\u003cp\u003eOne area that was identified as something we can improve with Openshift and containers in general is when running as root on the container \u003cem\u003emay\u003c/em\u003e expose the host and process in that container may be able to mingle with other resources.\u003c/p\u003e","title":"User namespaces with Buildah and OpenShift Pipelines"},{"content":"Feels weird or great or stupid or pretty smart or whatever to be wrong. Just when I wrote that previous blog post : https://blog.chmouel.com/2021/11/14/for-the-love-of-centered-windows/ that I realize that shell script doesn\u0026rsquo;t work great on wayland.\nI didn\u0026rsquo;t really understood how Wayland works and just assumed that my tiny scripts just works. But experiencing not working on a native Wayland application and understanding how wayland works: https://wayland.freedesktop.org/docs/html/ch05.html it obviously needed a better way to do that if I have to keep up with the modern world of a linux desktop.\nSo I spent a few hours to trying to understand how to make a gnome shell extension to replicate this. Since with the wayland architecture I don\u0026rsquo;t think there is other way around to replicate this feature.\nI got inspired by the tactile. And when I say inspired I pretty much copied a lot of code from there (my javascript and gtk dev skills are near to zero so I truly needed help).\nThe results is a nice extension that does exactly the same thing as my script and work exactly as wanted.\nI even got a nice gif to show for it : If you are interested it feel free to grab it from the gnome extensions website : https://extensions.gnome.org/extension/4615/one-third-window/\nJust start pressing the Super (or windows) + C keys to center the current window or Super/Win+Shift C to rotate the window around.\n","permalink":"https://blog.chmouel.com/2021/11/19/for-the-love-of-centered-windows-gnome-extension-edition/","summary":"\u003cp\u003eFeels weird or great or stupid or pretty smart or whatever to be wrong. Just\nwhen I wrote that previous blog post :\n\u003ca href=\"https://blog.chmouel.com/2021/11/14/for-the-love-of-centered-windows/\"\u003ehttps://blog.chmouel.com/2021/11/14/for-the-love-of-centered-windows/\u003c/a\u003e that I\nrealize that shell script doesn\u0026rsquo;t work great on wayland.\u003c/p\u003e\n\u003cp\u003eI didn\u0026rsquo;t really understood how Wayland works and just assumed that my tiny scripts just works. But experiencing not working on a native Wayland application and understanding how wayland works: \u003ca href=\"https://wayland.freedesktop.org/docs/html/ch05.html\"\u003ehttps://wayland.freedesktop.org/docs/html/ch05.html\u003c/a\u003e it obviously needed a better way to do that if I have to keep up with the modern world of a linux desktop.\u003c/p\u003e","title":"For the love of centered windows gnome extension edition"},{"content":"Sometime over a 2020 confinement my work decided to give us some money to buy some work from home office items.\nI didn\u0026rsquo;t need much at that time since I was already settled with everything I needed in a work from home office but decided to go for a fancy new screen since well why not and the other one (a standard 24\u0026quot; display) could find some good use for my teenage gamer son.\nThe chosen screen is a Samsung Ultra Wide display with a beautiful model name called S34J550WQU.\nAt first I was thrilled, the display looks nice and it seems I have much more estate for more to look at than before.\nBut in practice it\u0026rsquo;s not like this, this screen is too wide because, if I start having to d some work on the windows located on the right and on the left, I actually need to look at those windows by turning my neck or to actually move my head left to right. After a while it became quite irritating and gave me serious neckache and stiffness.\nAfter experimenting for a short while, I decided that centered window was the way to go, so I was painfully resizing windows and moved them around manually as needed. There was other tools I have found trying to automate those taskss but they never helped much.\nFast forward 3 months later, I was happily switched back onto Linux with the promises of those titling windows manager where windows gets titled and rearranged exactly the way I would wanted it.\nBut I never got into titling windows manager and never understood it really. Before that ultra wide screen display, I was mostly a one large window person with fast Alt- fingers. I would have my Emacs (or browser/terminal) in full screen which was just right to look at without moving my head since the screen was smaller where I can focus on the task at hand, without having five of them at the same time.\nIn titling windows manager you can customize it a lot but no matter what layout I tried I never could get it right.\nI gave up trying to adjust my workflow with i3/monad since part it is because I am definitively comfortable with desktop Gnome and I actually quite enjoying its simplicity\nI kinda for a while was thinking to sell that ultra wide monitor and get a smaller screen but like a lot of things life I was able to adjust my workflow with a set of keybinding and a shell script.\nI got inspired by this unix.stackexchange answer and with the help of xwininfo and wmctrl. my script would identify the current window and rotate them one them on the left of the scrren or the right, or my preferred placement for working on center.\nSo essentially when I have my editor (Emacs) a browser and a terminal, I can move the windows around and center the one I want and move the non active one easily on the sides.\nI realize now I kinda replicated a (extremely simplified) titling windows manager with the only feature I want . The advantage of my method is that I can have it exactly the way I want. The thing is that I don\u0026rsquo;t want a perfect 1/3 of the screen window, the window in the center is a few pixel more in the center and cover over the side windows and that makes it trivial in a screen, compared to try to figure it out how to do that in i3.\nAnother win for perfect aligned windows desktop.\n(I am quite new to wayland but to my surprise the script still work on wayland too).\n","permalink":"https://blog.chmouel.com/2021/11/14/for-the-love-of-centered-windows/","summary":"\u003cp\u003eSometime over a 2020 confinement my work decided to give us some money to buy some work from home office items.\u003c/p\u003e\n\u003cp\u003eI didn\u0026rsquo;t need much at that time since I was already settled with everything I needed in a work from home office but decided to go for a fancy new screen since well why not and the other one (a standard 24\u0026quot; display) could find some good use for my teenage gamer son.\u003c/p\u003e","title":"For the love of centered windows"},{"content":"One of the early goals of Pipelines as Code on Tekton was to ensure the project’s CI could run using itself.\nThe common use case of validating pull requests was quickly implemented, and you can find more information about it in this walkthrough video:\nFor slightly more advanced use cases, here is how we created a release pipeline for the project.\nThe goal is that when we tag a release and push the tags to the GitHub repository, it will:\nGenerate the release.yaml file for that version, allowing users to automatically run _kubectl apply -f-_. Upload the release.yaml to a release-${version} branch. Generate the tkn-pac binaries for different operating systems. Create the GitHub release. Repository Configuration To achieve this, I created a Repository Custom Resource (CR) in the pipelines-as-code-ci namespace:\napiVersion: pipelinesascode.tekton.dev/v1alpha1 kind: Repository metadata: name: pipelines-as-code spec: url: https://github.com/openshift-pipelines/pipelines-as-code The key part is the branch and event_type fields, which specify that all pushed tags should be handled and run in the pipelines-as-code-ci namespace.\nPipelineRun Configuration Next, I created a release-pipeline.yaml PipelineRun in the .tekton directory, adding the necessary annotations:\npipelinesascode.tekton.dev/on-event: \u0026#34;[push]\u0026#34; pipelinesascode.tekton.dev/on-target-branch: \u0026#34;[refs/tags/*]\u0026#34; This configuration ensures the PipelineRun handles all push tag events.\nTasks In the tasks, I included the git-clone task and a custom version of the goreleaser task, located in the repository at .tekton/task/goreleaser.yaml.\nThe annotation for these tasks looks like this:\npipelinesascode.tekton.dev/task: \u0026#34;[git-clone, .tekton/tasks/goreleaser.yaml]\u0026#34; Goreleaser simplifies many tasks for us. It compiles binaries, creates a GitHub release, and can generate a Homebrew release in the openshift-pipelines/homebrew-pipelines-as-code repository. This allows users on macOS or LinuxBrew to easily install it:\nbrew install openshift-pipelines/pipelines-as-code/tektoncd-pac Uploading the Release Uploading the release.yaml is handled by a Python script I wrote:\nhttps://github.com/openshift-pipelines/pipelines-as-code/blob/main/hack/upload-file-to-github.py\nThe script fetches the tag SHA, creates a release-${tagversion} branch, and pushes the file into it. This provides a stable branch with all artifacts specific to that version.\nFinal Steps After everything is in place, I edit the GitHub release, update a few fields for a nicer presentation, and set it as a release (by default, Goreleaser creates a prerelease).\nUseful Links Here are links to all the related files:\n.goreleaser.yaml - The configuration file for Goreleaser. upload-file-to-github.py - The Python script to upload files directly to GitHub. .tekton/release-pipeline.yaml - The Tekton release pipeline. ","permalink":"https://blog.chmouel.com/2021/07/01/how-to-make-a-release-pipeline-with-pipelines-as-code/","summary":"\u003cp\u003eOne of the early goals of \u003ca href=\"https://github.com/openshift-pipelines/pipelines-as-code/\"\u003ePipelines as Code\u003c/a\u003e on Tekton was to ensure the project’s CI could run using itself.\u003c/p\u003e\n\u003cp\u003eThe common use case of validating pull requests was quickly implemented, and you can find more information about it in this walkthrough video:\u003c/p\u003e\n\u003cdiv style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\"\u003e\n\t\t\t\u003ciframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https://www.youtube-nocookie.com/embed/cNOqPgpRXQY?autoplay=0\u0026amp;controls=1\u0026amp;end=0\u0026amp;loop=0\u0026amp;mute=0\u0026amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"\u003e\u003c/iframe\u003e\n\t\t\u003c/div\u003e\n\n\u003cp\u003eFor slightly more advanced use cases, here is how we created a release pipeline for the project.\u003c/p\u003e","title":"How to Make a Release Pipeline with Pipelines as Code"},{"content":"There is one thing that can get your wind up when you try to iterate quickly in a PR is to have a slow CI.\nWhile working on a go project with a comprehensive test suite it was usually taking over 20 to 30 minutes to run and being as patient as a kid waiting for her candy floss to be ready I am eagerly waiting that my pipeline is Green or not.\nMy pipeline wasn\u0026rsquo;t that complicated, it\u0026rsquo;s a typical go project one, it has only a few steps which can be described like this :\nCheckout the git repo in a Tekton workspace (PVC) to the commit SHA we want to be tested. Run my functional/unit tests (I don\u0026rsquo;t have e2e tests yet :) but that should be step three when it\u0026rsquo;s done) Run some linting on my code with golangci-lint Run some other linters like yamllint. As a good cloud native citizen Tekton spins up a new pod and attaches our pvc/workspace to it, and in each pods where a step is using go, the go compiler recompiles my dependencies I have vendored in my vendor directory.\nI am vendoring inside my repository so at least I don\u0026rsquo;t have `go mod` downloading again and again, but the go compilation can get very slow.\nAt first, I made a large container with a large image that had all the tools (which is Tekton upstream test-runner image) to speeds by a good time albeit it was still relatively slow compared to running it on my laptop to run the testsuite.\nI decided to go the \u0026ldquo;hacky way\u0026rdquo;, I would save the cache as often as possible to help the go compiler as much as possible.\nThis would use a toy project of mine called go-simple-uploader which is a simple go http server to upload and serve files to \u0026ldquo;cache my cache\u0026rdquo;.\nAt first I deployed the go-simple-uploader binary inside a kubernetes Deployment in front of a \u0026ldquo;Service\u0026rdquo;. The service will be accessible to every pod inside that same namespace, to its service name \u0026ldquo;http://uploader:8080\u0026rdquo;.\nI modified my pipeline so at first step I would check if there is a cache file and uncompress it :\n- image: mirror.gcr.io/library/golang:latest name: get-cache workingDir: $(workspaces.source.path) script: | #!/usr/bin/env bash set -ex mkdir -p go-build-cache;cd go-build-cache curl -fsI http://uploader:8080/golang-cache.tar || { echo \u0026#34;no cache found\u0026#34; exit 0 } echo \u0026#34;Getting cache\u0026#34; curl http://uploader:8080/golang-cache.tar|tar -x -f- This step does a few things :\nIt uses the golang official image because I know it will be used later on in my pipeline so I don\u0026rsquo;t care as much to have a small image and I can use a bash/curl in there. It uses the source workspaces where I have my code checked out in from the git-clone task and create the go-build-cache directory If it finds the file called golang-cache.tar It uncompressed it as quickly as possible. Later on in my pipeline, I have another task with multiple steps. I have moved away from using multiple tasks because PVC attachment can get quite slow. While a tekton task is a single pod where each steps are a container the steps looks like this :\n- name: unitlint runAfter: - get-cache taskSpec: steps: - name: unittest image: mirror.gcr.io/library/golang:latest workingDir: $(workspaces.source.path) script: | mkdir -p $HOME/.cache/ \u0026amp;\u0026amp; ln -vs $(workspaces.source.path)/go-build-cache $HOME/.cache/go-build make test - name: lint image: quay.io/app-sre/golangci-lint workingDir: $(workspaces.source.path) script: | mkdir -p $HOME/.cache/ \u0026amp;\u0026amp; ln -vfs $(workspaces.source.path)/go-build-cache $HOME/.cache/go-build mkdir -p $HOME/.cache/ \u0026amp;\u0026amp; ln -vfs $(workspaces.source.path)/go-build-cache $HOME/.cache/golangci-lint make lint-go This task run after `get-cache` the key part is where I symlink the go-build-cache directory to $HOME/.cache/go-build directory\nSames goes for golangci-lint I symlink its cache directory to $HOME/cache/golangci-lint\nLater on I have another task that save this cache :\n- name: save-cache workingDir: $(workspaces.source.path) script: | #!/usr/bin/env bash curl -o/dev/null -s -f -X POST -F path=test -F file=@/etc/motd http://uploader:8080/upload || { echo \u0026#34;No cache server found\u0026#34; exit 0 } lm=\u0026#34;$(curl -fsI http://uploader:8080/golang-cache.tar|sed -n \u0026#39;/Last-Modified/ { s/Last-Modified: //;s/\\r//; p}\u0026#39;)\u0026#34; if [[ -n ${lm} ]];then expired=$(python -c \u0026#34;import datetime, sys;print(datetime.datetime.now() \u0026gt; datetime.datetime.strptime(sys.argv[1], \u0026#39;%a, %d %b %Y %X %Z\u0026#39;) + datetime.timedelta(days=1))\u0026#34; \u0026#34;${lm}\u0026#34;) [[ ${expired} == \u0026#34;False\u0026#34; ]] \u0026amp;\u0026amp; { echo \u0026#34;Cache is younger than a day\u0026#34; exit } fi cd $(workspaces.source.path)/go-build-cache tar cf - . |curl -# -L -f -F path=golang-cache.tar -X POST -F \u0026#34;file=@-\u0026#34; http://uploader:8080/upload The task starts by checking if you have a cache server and then with the help of some shell and python magic checking with the \u0026ldquo;Last-Modified\u0026rdquo; http header if you have a cache file that has already been generated since over a day.\nI am doing this because at first I was using a uploading server in another environment which could get quite slow to upload on every run, since we run in the same namespace the upload is very fast so this is probably not needed, but keeping it here if someone else needs it.\nIt then uploads the cache file where it would be available for the subsequent runs using the first get-cache task.\nThings got much faster, starting with my pipeline going over 10/12 minute at first run, it will get down to 2mn on the next runs. It gets as slow as your infra, the time for kubernetes to spin up the pods really, it could get under 1mn if I am running my pipeline under Kind.\nThis is pretty KISS and may actually work on any pipelines that needs caching (I am looking at you java maven and nodejs npm).\nNow the best way probably to address this in a generic way is to have a task in the tektoncd/catalog that behaves like the Github Action cache where the user can specify a parameter for the cache key, a TTL and a directory and maybe the storage type (ie: like an object storage or a simple http uploader or even another PVC) and the task automatically do everything at the start of your pipeline and by the end with in a finally task.\nHopefully we can get this done in the near future.\n","permalink":"https://blog.chmouel.com/2021/05/25/speed-up-your-tekton-pipeline-caching-the-hacky-way/","summary":"\u003cp\u003eThere is one thing that can get your wind up when you try to iterate quickly in a PR is to have a slow CI.\u003c/p\u003e\n\u003cp\u003eWhile working on a go project with a comprehensive test suite it was usually taking over 20 to 30 minutes to run and being as patient as a kid waiting for her candy floss to be ready I am eagerly waiting that my pipeline is Green or not.\u003c/p\u003e","title":"Speed up your tekton pipeline caching the hacky way"},{"content":"Took me a little bit a while to figure out so here is some documentation,\nMy router from my ISP which is generally pretty good, doesn\u0026rsquo;t support local dns names which is annoying in itself. Combined with NextDNS, I have no way to identify the devices on my network.\nSo there I went configured dnsmasq on my tiny raspbery-pi :\nport=5353 no-resolv interface=eth0 except-interface=lo listen-address=::1,192.168.0.3 no-dhcp-interface= bind-interfaces cache-size=10000 local-ttl=2 log-async log-queries bogus-priv server=192.168.0.3 add-mac add-subnet=32,128 This would have the dnsmasq service listening on 192.168.0.3:5353 and forward everything to 192.168.0.3.\nI continued and set my DHCP server :\ndhcp-authoritative dhcp-range=192.168.0.20,192.168.0.251,24h dhcp-option=option:router,192.168.0.254 dhcp-name-match=set:wpad-ignore,wpad dhcp-name-match=set:hostname-ignore,localhost dhcp-ignore-names=tag:wpad-ignore dhcp-mac=set:client_is_a_pi,B8:27:EB:*:*:* dhcp-reply-delay=tag:client_is_a_pi,2 dhcp-option=option:dns-server,192.168.0.3 dhcp-option=option:domain-name,lan domain=lan dhcp-option=option6:dns-server] dhcp-range=::100,::1ff,constructor:eth0,ra-names,slaac,24h ra-param=*,0,0 Standard DHCP really just make sure you setup the router to your local router, here it\u0026rsquo;s 0.254 in my config.\nI then configured the nextdns client on 192.168.0.3 default DNS port 53 :\ncache-size 0 report-client-info true setup-router false log-queries true config CONFIG_ID_FROM_NEXTDNS_GET_IT_FROM_THERE cache-max-age 0s timeout 5s control /var/run/nextdns.sock forwarder .lan.=192.168.0.3:5353 max-ttl 5s discovery-dns 192.168.0.3:5353 hardened-privacy false bogus-priv true auto-activate false listen 192.168.0.3:53 use-hosts true detect-captive-portals false The key setings is the discovery-dns setting, it means it would try to discover the local names to display on the nextdns web UI and resolve all lan domain to the local dnsmasq server.\nAnd that\u0026rsquo;s it\u0026hellip;. Hope this helps.\n","permalink":"https://blog.chmouel.com/2021/04/19/nextdns-dnsmasq-dhcp-and-local-names/","summary":"\u003cp\u003eTook me a little bit a while to figure out so here is some documentation,\u003c/p\u003e\n\u003cp\u003eMy \u003ca href=\"https://en.wikipedia.org/wiki/Freebox\"\u003erouter from my ISP\u003c/a\u003e which is generally pretty good, doesn\u0026rsquo;t support local dns names which is annoying in itself. Combined with NextDNS, I have no way to identify the devices on my network.\u003c/p\u003e\n\u003cp\u003eSo there I went configured dnsmasq on my tiny raspbery-pi :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eport=5353\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eno-resolv\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003einterface=eth0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexcept-interface=lo\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elisten-address=::1,192.168.0.3\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eno-dhcp-interface=\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebind-interfaces\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecache-size=10000\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elocal-ttl=2\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elog-async\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elog-queries\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebogus-priv\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eserver=192.168.0.3\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadd-mac\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadd-subnet=32,128\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThis would have the dnsmasq service listening on 192.168.0.3:5353 and forward everything to 192.168.0.3.\u003c/p\u003e","title":"NextDNS + DNSMasq DHCP and local names"},{"content":"I write a lot of scripts to automate my day to day workflow, some of them I just wrote for 3h to save me 5mn only once and some others I write for about 5mn but save me hours of boreness and repetitive task.\nThe script showed today, that I am proud of because of its usefulness and probably not of its code, is called \u0026ldquo;batzconverter\u0026rdquo; available on https://github.com/chmouel/batzconverter. What the script is trying to solve is when you work with your team spread around 3/4 timezones, how do you schedule a meeting easily.\nIt\u0026rsquo;s a ~200 lines simple shell script that leverage onto the very powerful GNU date\nIn its most simple form when you type the command batz you are getting this :\nThis is showing all timezones (which you can configure) at current time, with some easily identified emojis. The 🏠 emoji on the right is to show the location of the user.\nBut you can do way more, let\u0026rsquo;s say you want to show all timezone for tomorrow 13h00 meeting : It will just do that and show it.\nSame goes for a specific date : You can do some extra stuff, like adding quickly another timezone that isn\u0026rsquo;t configured : Or give another timezone as the base for conversion, the airplane emoji ✈️ here is to let know that you showing another target timezone : easy peasy to use, no frills, no bells just usefulness\u0026hellip;\nThere is another flag called \u0026ldquo;-j\u0026rdquo; to allow you to output to json, it was implemented for being able to plug into the awesome alfredapps on osx as a workflow :\nBut it doesn\u0026rsquo;t have to be for Alfred, the json outut can be used for any other integrations.\nConfiguration is pretty simple you just need to configure the timezone you would like to have in a file located ~/.config and the emojis associated with it (cause visuals are important! insert rolled eyes emoji here).\nHead up on github chmouel/batzconverter to learn how to install and configure it, and feel free to let me know about suggestions or issues you have using it.\n","permalink":"https://blog.chmouel.com/2021/01/31/batzconverter-a-multiple-timezone-converter/","summary":"\u003cp\u003eI write a lot of scripts to automate my day to day workflow, some of them I just wrote for 3h to save me 5mn only once and some others I write for about 5mn but save me hours of boreness and repetitive task.\u003c/p\u003e\n\u003cp\u003eThe script showed today, that I am proud of because of its usefulness and probably not of its code, is called \u003cstrong\u003e\u0026ldquo;batzconverter\u0026rdquo;\u003c/strong\u003e available on \u003ca href=\"https://github.com/chmouel/batzconverter\"\u003ehttps://github.com/chmouel/batzconverter\u003c/a\u003e. What the script is trying to solve is when you work with your team spread around 3/4 timezones, how do you schedule a meeting easily.\u003c/p\u003e","title":"batzconverter – A multiple timezone converter"},{"content":"I have been trying to build some packages for the ubuntu distros for a new program I have released, gnome-next-meeting-applet\nIn short, it what quite painful! if you are quite new to the launchpad and debian packaging ways (which I wasn\u0026rsquo;t and yet It took me some time to figure out) you can get quite lost. I got to say that the fedora copr experience is much smoother. After a couple of frustrated google and stackoverflow searches and multiple tries I finally figured out a script that builds and upload properly to launchpad via docker to make it available to my users.\nThe first rule of uploading to launchpad it\u0026rsquo;s to properly setup your GPG key on your account making sure it match what you have locally. The second rule is making sure the new upload you make increase onto the precedent uloaded version or it will be rejected. The third rule is to be patient or work on week-end, because the queue can be quite slow. Now the magic is happening in this script :\nhttps://github.com/chmouel/gnome-next-meeting-applet/blob/742dbe48795c0151411db69065fdd773762100e1/debian/build.sh#L20-L41\nWe have a Dockerfile with all the dependencies we need for building the package in this file :\nhttps://github.com/chmouel/gnome-next-meeting-applet/blob/a2785314365c51200935ad63c38f490c597989c9/debian/Dockerfile\nWhen we launch the script in the main loop we modify the FROM to go to the distro docker tag targeted (here I have LTS and ROLLING) and we start the container build.\nWhen it\u0026rsquo;s done we mount our current source as a volume inside the container and mount our ~/.gnupg to the build user gnupg inside the container.\nWith dch we increase the targeted distro version and we add as well after the release number the distro target after the \u0026quot;~\u0026quot; like this \u0026ldquo;0.1.0-1~focal1\u0026rdquo;.\nWe finish the upload with dput and launchpad *should* then send you an email it was accepted.\nAfter waiting a bit your package should be built for the multiple distribution.\n","permalink":"https://blog.chmouel.com/2021/01/31/building-packages-for-multiple-distros-on-launchpad-with-docker/","summary":"\u003cp\u003eI have been trying to build some packages for the ubuntu distros for a new program I have released, \u003ca href=\"https://github.com/chmouel/gnome-next-meeting-applet\"\u003egnome-next-meeting-applet\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eIn short, it what quite painful! if you are quite new to the launchpad and debian packaging ways (which I wasn\u0026rsquo;t and yet It took me some time to figure out) you can get quite lost. I got to say that the \u003ca href=\"https://copr.fedorainfracloud.org/\"\u003efedora copr\u003c/a\u003e experience is much smoother. After a couple of frustrated google and stackoverflow searches and multiple tries I finally figured out a script that builds and upload properly to \u003ca href=\"http://launchpad.net\"\u003elaunchpad\u003c/a\u003e via docker to make it available to my users.\u003c/p\u003e","title":"Building packages for multiple distros on launchpad with docker"},{"content":"Don\u0026rsquo;t you love \u0026ldquo;yaml\u0026rdquo;, yes you do ! or at least that\u0026rsquo;s what the industry told you to love!\nWhen you were in school your teacher told you about \u0026ldquo;XML\u0026rdquo; and how it will solve all the industry problems (and there was many in the late 90s). But you learned that you hate reaching to your \u0026quot;\u0026lt;\u0026quot; and\u0026quot; \u0026quot;\u0026gt;\u0026quot; keys and rather have something else. So then the industry came up with \u0026ldquo;json\u0026rdquo; so computer or yourself can talk to each others, that\u0026rsquo;s nice for computers but actually not so nice for yourself it was actually a lie and was not made for yourself to read and write but only for comptures. So then the \u0026ldquo;industry\u0026rdquo; came up with yaml, indentation based? you get it and that\u0026rsquo;s humm all about it, now you are stuck counting whitespaces in a 3000 lines file trying to figure out where goes where\u0026hellip;.\nAnywoo ranting about computer history is not the purpose of this blog post, like every other cloud native (sigh) component out there tekton is using yaml to let the user describe its operative executions. There is a very nice feature in there (no sarcasm it is really nice!) allowing you to embed \u0026ldquo;scripts\u0026rdquo; directly in tasks. Instead of like before where you had to build a container image with your script and run it from tekton, you can now just specify the script embedded directly in your \u0026ldquo;Task\u0026rdquo; or \u0026ldquo;Pipeline\u0026rdquo;.\nAll good, all good, that\u0026rsquo;s very nice and dandy but when you start writing a script that goes over 5 lines you are getting into the territory where you have mixed a ~1000 lines script embedded in a 2000 lines of yaml (double sigh).\nYou can come back to the old way, and start to go over the development workflow of :\n\u0026ldquo;write\u0026rdquo; -\u0026gt; commit -\u0026gt; \u0026ldquo;push\u0026rdquo; -\u0026gt; \u0026ldquo;build image\u0026rdquo; =\u0026gt; \u0026ldquo;push\u0026rdquo; -\u0026gt; \u0026ldquo;update tag\u0026rdquo; -\u0026gt; \u0026ldquo;start task\u0026rdquo;\nand realize that you are loosing approximately 40 years of your soul into some boring and repetitive tasks.\nSo now that i am over talking to myself with this way too long preamble here is the real piece of information in this post, a script that like everything in your life workaround the real issue.\nIt\u0026rsquo;s available here :\nhttps://gitlab.com/chmouel/chmouzies/blob/master/work/tekton-script-template.sh\nThe idea is if you have in your template a tag saying #INSERT filename, it would be replaced by the content of the file, it\u0026rsquo;s dumb and stupid but make devloping your yaml much more pleasing\u0026hellip; so if you have something like :\nimage: foo script: | #INSERT script.py the script with see this and insert the file script.py in your template. It will respect the previous line indentation and add four spaces extra to indent the script and you can have as many INSERT as you want in your template\u0026hellip;.\nNow you can edit your code in script.py and your yaml template in the yaml template.. win win, separation of concerns, sanity win happy dance and emoji and all\u0026hellip;\n","permalink":"https://blog.chmouel.com/2020/07/28/tekton-yaml-templates-and-script-feature/","summary":"\u003cp\u003eDon\u0026rsquo;t you love \u0026ldquo;yaml\u0026rdquo;, yes you do ! or at least that\u0026rsquo;s what the industry told you to love!\u003c/p\u003e\n\u003cp\u003eWhen you were in school your teacher told you about \u0026ldquo;XML\u0026rdquo; and how it will solve all the industry problems (and there was many in the late 90s). But you learned that you hate reaching to your \u003cstrong\u003e\u0026quot;\u0026lt;\u0026quot;\u003c/strong\u003e and\u0026quot; \u003cstrong\u003e\u0026quot;\u0026gt;\u0026quot;\u003c/strong\u003e keys and rather have something else. So then the industry came up with \u0026ldquo;json\u0026rdquo; so computer or yourself can talk to each others, that\u0026rsquo;s nice for computers but actually not so nice for yourself it was actually a lie and was not made for yourself to read and write but only for comptures. So then the \u0026ldquo;industry\u0026rdquo; came up with \u003cstrong\u003eyaml\u003c/strong\u003e, indentation based? you get it and that\u0026rsquo;s humm all about it, now you are stuck counting whitespaces in a 3000 lines file trying to figure out where goes where\u0026hellip;.\u003c/p\u003e","title":"Tekton yaml templates and script feature"},{"content":"Part of my new job working with Fabric8 is to having it deployed via minishift.\nEverything is nice and working (try it it\u0026rsquo;s awesome https://fabric8.io/guide/getStarted/gofabric8.html) as long you deploy it on your local workstation.\nThe thing is that my desktop macosx laptop has only 8GB of RAM and is not very well up to the task to get all the services being deployed when I have my web browser and other stuff hogging the memory. I would not do on a remote VM since I want to avoid the nested virtualisationt part that may slow down things even more.\nThanksfully I have another linux laptop with 8GB of RAM which I use for my testing and wanted to deploy minishift on it and access it from my desktop laptop.\nThis is not as trivial as it sounds but thanks to minishift flexibility there is way to set this up.\nSo here is the magic command line :\nminishift start --public-hostname localhost --routing-suffix 127.0.0.1.nip.io\nWhat do we do here? We bind everyting to localhost and 127.0.0.1, what for you may ask? Cause we then are going to use it via SSH. First you need to get the minishift IP :\n$ minishift ip 192.168.42.209 and now since in my case it\u0026rsquo;s the 192.168.42.209 IP I am going to forward SSH it :\nsudo ssh -L 443:192.168.42.209:443 -L 8443:192.168.42.209:8443 username@host\u0026lt;br /\u0026gt; Change the username@host and the 192.168.42.209 to your IP. I use sudo here since to be able to forward the privileged 443 port need root access,\nWhen this is done if the stars was aligned in the right direction when you typed those commands you should be able to see the fabric8 login page :\n","permalink":"https://blog.chmouel.com/2017/06/09/deploying-minishift-on-a-remote-laptop/","summary":"\u003cp\u003ePart of my new job working with Fabric8 is to having it deployed via minishift.\u003cbr\u003e\nEverything is nice and working (try it it\u0026rsquo;s awesome \u003ca href=\"https://fabric8.io/guide/getStarted/gofabric8.html\"\u003ehttps://fabric8.io/guide/getStarted/gofabric8.html\u003c/a\u003e) as long you deploy it on your local workstation.\u003c/p\u003e\n\u003cp\u003eThe thing is that my desktop macosx laptop has only 8GB of RAM and is not very well up to the task to get all the services being deployed when I have my web browser and other stuff hogging the memory. I would not do on a remote VM since I want to avoid the nested virtualisationt part that may slow down things even more.\u003c/p\u003e","title":"Deploying minishift on a remote laptop."},{"content":"By default when you install an OpenShift install it would automatically generate its own certificates.\nIt uses those certificates for communication between nodes and as well to automatically auth the admin account. By default those same certificates are the one provided for the OpenShift console and API.\nSince it is auto generated you will when connecting to the website with you webbrowser get an ugly error message :\nand as the error message says that\u0026rsquo;s not very secure #sadpanda.\nThere is an easy way to generate certificate these days and it is to use letsencrypt, so let\u0026rsquo;s see how to connect it to the openshift console.\nThere is something to understand first here, when you want to use an alternate SSL certificates for your console and API you can\u0026rsquo;t do that on your default (master) URL, it has to be another url. Phrased in another way here is a quote from the official documentation :\nwith that in mind let\u0026rsquo;s assume you have setup a domain being a CNAME to your default domain. For myself here since this is a test install I went to use the easy way and I will use the xp.io service as I have documented in an earlier post. This give me easily a domain which would look like this :\nSo now that you have defined it, you need first to generate the letsencrypt certificate usually you would use certbotfrom RHEL EPEL to generate them but unfortunately at the time of writing this blog post the package was uninstallable for me which probably would get fixed soon. In the meantime I have used letsencrypt from git directly as like this:\nbefore you do anything, you need to understand the letsencrypt process, usually you would have an apache or nginx (etc\u0026hellip;) serving the generated files for verifications (the /.well-known/ thing) since we can\u0026rsquo;t do that for us in openshift you can use the letsencrypt builtin webserver for that.\nBut to start the builtin webserver you need to be able to do it to bind it on port 80 but for us on master there is the router running which bind to it (and 443), so you would need to make sure it\u0026rsquo;s down and the most elegant way to do that with openshift is like this :\nnow that you have nothing on port 80 you can tell letsencrypt to do its magic with this command line :\nchange the lb.198.154.189.125.xip.io here to your own domain as the email address, if everything goes well you should get something like this :\nnow you should have all the certificates needed in /etc/letsencrypt/live/${domain}\nSo there is a little caveat here, there is a bug in openshift-ansible currently with symlinks and certificates and the way it operates. I have filled the bug here and it has already been fixed in GIT so hopefully by the time you will read this article this would be fixed in the openshift-ansible rpm if it\u0026rsquo;s not you can directly use the GIT openshift-ansible instead of the package.mber (3) here is going to change so you would have to adjust.\nnow you just need to some configuration in your /etc/ansible/hosts file :\nopenshift_master_cluster_public_hostname=lb.198.154.189.125.xip.io openshift_master_named_certificates=[{\u0026#34;certfile\u0026#34;: \u0026#34;/etc/letsencrypt/live/lb.198.154.189.125.xip.io/full.pem\u0026#34;, \u0026#34;keyfile\u0026#34;: \u0026#34;/etc/letsencrypt/live/lb.198.154.189.125.xip.io/privkey.pem\u0026#34;, \u0026#34;names\u0026#34;:[\u0026#34;lb.198.154.189.125.xip.io\u0026#34;]}] openshift_master_overwrite_named_certificates=true after you run your playbook (with ansible-playbook /usr/share/ansible/openshift-ansible/playbooks/byo/config.yml) you should have it running properly and now when accessing by the console you should the reassuring secure lock :\nNB:\nIf you need to renew the certs just do the steps where you oc scale the router quickly and renew the certificate with the letsencrypt auto command line mentioned earlier. There is probably a way more elegant way to do that with a container and a route. I saw this on dockerhub but this seems to be tailored to apps (and kube) and I don\u0026rsquo;t think this could be used for the OpenShift console. Don\u0026rsquo;t forget to oc scale \u0026ndash;replicas=1 dc/router(even tho the ansible rerun should have done for you. ","permalink":"https://blog.chmouel.com/2016/09/29/getting-a-letsencrypt-ssl-certificate-for-the-openshift-console-and-api/","summary":"\u003cp\u003eBy default when you install an OpenShift install it would automatically generate its own certificates.\u003c/p\u003e\n\u003cp\u003eIt uses those certificates for communication between nodes and as well to automatically auth the admin account. By default those same certificates are the one provided for the OpenShift console and API.\u003c/p\u003e\n\u003cp\u003eSince it is auto generated you will when connecting  to the website with you webbrowser get an ugly error message :\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2016/09/2016-09-28__23-40-01-20126.png\"\u003e\u003c/p\u003e\n\u003cp\u003eand as the error message says that\u0026rsquo;s not very secure #sadpanda.\u003c/p\u003e","title":"Getting a letsencrypt SSL certificate for the OpenShift console and API"},{"content":"OpenShift integrate1 a router based on HAproxy to expose your services to the outside world. Whenever your do a :\nit would expose by default the servicename this URL :\nThe defaultSubdomain is usually a wildcard DNS record that you have configured in your domain server by your system administrator. Now for your openshift testing if you don\u0026rsquo;t want to ask your system administrator to configure a new CNAME going to your testing environement you can just use the free service xp.io\nThe XP.IO service is a special DNS service which would take a an IP address and xp.io and report back the IP of this IP address to itself and to all subdomain so that the IP:\nwill go to 1.2.3.4 same goes for foo.1.2.3.4, bar.1.2.3.4 etc\u0026hellip;\nYou just then need to configure it in OpenShift by editing the value (assuming 1.2.3.4 is your public IP which come back to your router) :\nroutingConfig: subdomain: \u0026#34;1.2.3.4.xip.io\u0026#34; Or if you use the openshift-ansible scripts to add this your /etc/ansible/hosts\nand then you get all your route exposed properly without bother your always busy system admin.\n1 Which lately got merged into kubernetes as the \u0026ldquo;ingress\u0026rdquo; feature\n","permalink":"https://blog.chmouel.com/2016/09/28/easily-test-your-openshift-applications-exposed-by-the-router/","summary":"\u003cp\u003eOpenShift integrate\u003ca href=\"http://xp.io\"\u003e1\u003c/a\u003e a router based on HAproxy to expose your services to the outside world. Whenever your do a :\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003cp\u003eit would expose by default the servicename this URL :\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003eThe defaultSubdomain is usually a \u003c!-- raw HTML omitted --\u003ewildcard DNS record\u003c!-- raw HTML omitted --\u003e that you have configured in your domain server by your system administrator. \u003c!-- raw HTML omitted --\u003e\u003c/p\u003e","title":"Easily test your OpenShift applications exposed by the router"},{"content":"After you have installed your fancy openshift install and that it kicked the haproxy router automatically after install you may want to see the stats of the router.\nThe HAproxy stats are exposed on the port 1936 where the router is located (usually on the master node) so first you need a way to access it. You can open it via your firewall (not ideal) or you can just port forward the port to your workstation via SSH :\nssh -L 1936:localhost:1936 master.openshift Now that it\u0026rsquo;s done and you have 1936 tunelled you need to figure out the password of the haproxy stats. It\u0026rsquo;s stored in its environment variables so you just do a oc describe to see it for example :\nNow that you have the password (uo5LtC6mac in my case), you just point your workstation web browser to :\nhttp://admin:password@localhost:1936\njust make sure to replace the password with your own password and you should be all set.\n","permalink":"https://blog.chmouel.com/2016/09/27/how-to-view-openshift-haproxy-stats/","summary":"\u003cp\u003eAfter you have installed your fancy openshift install and that it kicked the haproxy router automatically after install you may want to see the stats of the router.\u003c/p\u003e\n\u003cp\u003eThe HAproxy stats are exposed on the port 1936 where the router is located (usually on the master node) so first you need a way to access it. You can open it via your firewall (not ideal) or you can just port forward the port to your workstation via SSH :\u003c/p\u003e","title":"How to view openshift router (haproxy) stats"},{"content":"At home I have been using a Yamaha AV RX-A380, it\u0026rsquo;s an home teather audio video solution where you can plug about everything you need (like 7 hdmi channel, spoiler alert there is something wrong with you if you have that many devices) and output to two other hdmi channel (like a tv and a projector).\nIt has integration for spotify, airplay, netradio and billions of connection to everything, just look at the damn back of this device :\nSince I wanted to control it from the command line to automate it for home automation, I firebugged the web interface and reversed some of the REST calls in a nice bash script.\nHere it is at your convenience to using or hack it :\nThis doesn\u0026rsquo;t support multi-zone and assume the web interface is resolvable to http://yamaha.local/ (it should be by default) so be aware. This may support other Yamaha AV devices but since I don\u0026rsquo;t have it I can\u0026rsquo;t say and you may have try, if it does kindly add a comment here soother would know :)\n","permalink":"https://blog.chmouel.com/2016/09/23/controlling-yamaha-av-rx-a830-from-command-line/","summary":"\u003cp\u003eAt home I have been using a \u003ca href=\"https://www.amazon.com/Yamaha-RX-A830-7-2-Channel-AVENTAGE-Receiver/dp/B00BQHCCQQ\"\u003eYamaha AV RX-A380\u003c/a\u003e, it\u0026rsquo;s an home teather audio video solution where you can plug about everything you need (like 7 hdmi channel, spoiler alert there is something wrong with you if you have that many devices) and output to two other hdmi channel (like a tv and a projector).\u003c/p\u003e\n\u003cp\u003eIt has integration for spotify, airplay, netradio and billions of connection to everything, just look at the damn back of this device :\u003c/p\u003e","title":"Controlling Yamaha AV RX-A830 from command line"},{"content":"I have been meaning to get this blog SSL protected for a while and since solution like letsencrypt makes it easy I have generated some SSL keys for my domain and configured it in apache.\nSo far so good, but the thing is my VM at my hosting provider is pretty small and I have been using varnish for quite some time or I would get out of memory quickly some the kernel OOM killer kicking1 it.\nVarnish don\u0026rsquo;t do SSL so you have to do something else, I went ahead and used Nginx to provide my SSL endpoint which then would look like this :\nI could have done it with apache virtualhosts which look like this :\nI went finally for nginx since most people seems to say that it was more lean and quick for those kick of ssl accelerator job.\nSo far so good for the configuration, you can find those informations all over the internet, the nginx ssl configuration was a bit special so I can have the higher secure end of SSL encryption :\nNow the thing didn\u0026rsquo;t work very well when accessing the website, I could not see any of th medias including JS and SSL since they were served on the old non ssl url. I tried to force the wordpress configuration to serve SSL but I would end up in a http redirect loop.\nFinally I stumbled on this guy blog and looked at a hack to put in the wp-config.php file. I streamlined it to :\nif ( (!empty( $_SERVER[\u0026#39;HTTP_X_FORWARDED_HOST\u0026#39;])) || (!empty( $_SERVER[\u0026#39;HTTP_X_FORWARDED_FOR\u0026#39;])) ) { $_SERVER[\u0026#39;HTTPS\u0026#39;] = \u0026#39;on\u0026#39;; } and that\u0026rsquo;s it, wordpress would then understand it would serve as HTTPS and would add its https url properly.\nHope this helps\n1 I had even a cron sometime ago to mysqlping my mysql server and restart it automatically if it was down since I was so sick of it\n","permalink":"https://blog.chmouel.com/2016/09/22/the-trick-to-get-your-wordpress-behind-a-reverse-proxy/","summary":"\u003cp\u003eI have been meaning to get this blog SSL protected for a while and since solution like \u003ca href=\"https://letsencrypt.org\"\u003eletsencrypt\u003c/a\u003e makes it easy I have generated some SSL keys for my domain  and configured it in apache.\u003c/p\u003e\n\u003cp\u003eSo far so good, but the thing is my VM at my hosting provider is pretty small and I have been using \u003ca href=\"https://varnish-cache.org/\"\u003evarnish\u003c/a\u003e for quite some time or I would get out of memory quickly some the kernel OOM killer kicking\u003ca href=\"https://letsencrypt.org\"\u003e1\u003c/a\u003e it.\u003c/p\u003e","title":"The trick to get your wordpress behind a reverse proxy"},{"content":"I have been meaning to automate my deployment directly from my small python application without having to use the openshift client (oc) directly.\nOpenShift use a REST API and the oc client uses it to communicate with the server, you can actually see all the REST operation the oc client is doing if you specify the \u0026ndash;loglevel=7 (it goes to 10 to get even more debug info) :\n$ oc --loglevel=7 get pod 2\u0026gt;\u0026amp;1 |head -10 I0919 09:59:20.047350 77328 loader.go:329] Config loaded from file /Users/chmouel/.kube/config I0919 09:59:20.048149 77328 round_trippers.go:296] GET https://openshift:8443/oapi I0919 09:59:20.048158 77328 round_trippers.go:303] Request Headers: I0919 09:59:20.048162 77328 round_trippers.go:306] User-Agent: oc/v1.4.0 (darwin/amd64) openshift/85eb37b I0919 09:59:20.048175 77328 round_trippers.go:306] Authorization: Bearer FOOBAR I0919 09:59:20.048180 77328 round_trippers.go:306] Accept: application/json, */* I0919 09:59:20.095239 77328 round_trippers.go:321] Response Status: 200 OK in 47 milliseconds I0919 09:59:20.096056 77328 round_trippers.go:296] GET https://openshift:8443/version I0919 09:59:20.096078 77328 round_trippers.go:303] Request Headers: I0919 09:59:20.096084 77328 round_trippers.go:306] User-Agent: oc/v1.4.0 (darwin/amd64) openshift/85eb37b I was thinking to come up with my own python rest wrapper since a google quick search didn\u0026rsquo;t come up with any binding. But since openshift is build on kubernetes and fully compatible with it (i.e: no fork or changes that make it incompatible) it was as easy as using the tools provided for kube.\nThe first project coming up on the google search is pykube and it\u0026rsquo;s easily installable with pip.\nYou need to provide a kubeconfig that was already setup (with username/passwd) or already identified if it\u0026rsquo;s token based (i.e: oauth, oid etc) and you can use this example like this :\nimport pykube api = pykube.HTTPClient(pykube.KubeConfig.from_file(\u0026#34;/Users/chmouel/.kube/config\u0026#34;)) pods = pykube.Pod.objects(api).filter(namespace=\u0026#34;test\u0026#34;) for x in pods: print(x) see the documentation of pykub on its website\n","permalink":"https://blog.chmouel.com/2016/09/19/using-python-to-drive-openshift-rest-api/","summary":"\u003cp\u003eI have been meaning to automate my deployment directly from my small python application without having to use the openshift client (oc) directly.\u003c/p\u003e\n\u003cp\u003eOpenShift use a REST API and the oc client uses it to communicate with the server, you can actually see all the REST operation the oc client is doing if you specify the \u0026ndash;loglevel=7 (it goes to 10 to get even more debug info) :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e$\u003c/span\u003e oc \u003cspan style=\"color:#ff79c6\"\u003e--\u003c/span\u003eloglevel\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#bd93f9\"\u003e7\u003c/span\u003e get pod \u003cspan style=\"color:#bd93f9\"\u003e2\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e\u0026gt;\u0026amp;\u003c/span\u003e\u003cspan style=\"color:#bd93f9\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e|\u003c/span\u003ehead \u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#bd93f9\"\u003e10\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eI0919 \u003cspan style=\"color:#bd93f9\"\u003e09\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e59\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e20.047350\u003c/span\u003e   \u003cspan style=\"color:#bd93f9\"\u003e77328\u003c/span\u003e loader\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ego:\u003cspan style=\"color:#bd93f9\"\u003e329\u003c/span\u003e] Config loaded from file \u003cspan style=\"color:#ff79c6\"\u003e/\u003c/span\u003eUsers\u003cspan style=\"color:#ff79c6\"\u003e/\u003c/span\u003echmouel\u003cspan style=\"color:#ff79c6\"\u003e/.\u003c/span\u003ekube\u003cspan style=\"color:#ff79c6\"\u003e/\u003c/span\u003econfig\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eI0919 \u003cspan style=\"color:#bd93f9\"\u003e09\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e59\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e20.048149\u003c/span\u003e   \u003cspan style=\"color:#bd93f9\"\u003e77328\u003c/span\u003e round_trippers\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ego:\u003cspan style=\"color:#bd93f9\"\u003e296\u003c/span\u003e] GET https:\u003cspan style=\"color:#ff79c6\"\u003e//\u003c/span\u003eopenshift:\u003cspan style=\"color:#bd93f9\"\u003e8443\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e/\u003c/span\u003eoapi\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eI0919 \u003cspan style=\"color:#bd93f9\"\u003e09\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e59\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e20.048158\u003c/span\u003e   \u003cspan style=\"color:#bd93f9\"\u003e77328\u003c/span\u003e round_trippers\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ego:\u003cspan style=\"color:#bd93f9\"\u003e303\u003c/span\u003e] Request Headers:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eI0919 \u003cspan style=\"color:#bd93f9\"\u003e09\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e59\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e20.048162\u003c/span\u003e   \u003cspan style=\"color:#bd93f9\"\u003e77328\u003c/span\u003e round_trippers\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ego:\u003cspan style=\"color:#bd93f9\"\u003e306\u003c/span\u003e]     User\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003eAgent: oc\u003cspan style=\"color:#ff79c6\"\u003e/\u003c/span\u003ev1\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003e\u003cspan style=\"color:#bd93f9\"\u003e4.0\u003c/span\u003e (darwin\u003cspan style=\"color:#ff79c6\"\u003e/\u003c/span\u003eamd64) openshift\u003cspan style=\"color:#ff79c6\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#bd93f9\"\u003e85\u003c/span\u003eeb37b\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eI0919 \u003cspan style=\"color:#bd93f9\"\u003e09\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e59\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e20.048175\u003c/span\u003e   \u003cspan style=\"color:#bd93f9\"\u003e77328\u003c/span\u003e round_trippers\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ego:\u003cspan style=\"color:#bd93f9\"\u003e306\u003c/span\u003e]     Authorization: Bearer FOOBAR\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eI0919 \u003cspan style=\"color:#bd93f9\"\u003e09\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e59\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e20.048180\u003c/span\u003e   \u003cspan style=\"color:#bd93f9\"\u003e77328\u003c/span\u003e round_trippers\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ego:\u003cspan style=\"color:#bd93f9\"\u003e306\u003c/span\u003e]     Accept: application\u003cspan style=\"color:#ff79c6\"\u003e/\u003c/span\u003ejson, \u003cspan style=\"color:#ff79c6\"\u003e*/*\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eI0919 \u003cspan style=\"color:#bd93f9\"\u003e09\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e59\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e20.095239\u003c/span\u003e   \u003cspan style=\"color:#bd93f9\"\u003e77328\u003c/span\u003e round_trippers\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ego:\u003cspan style=\"color:#bd93f9\"\u003e321\u003c/span\u003e] Response Status: \u003cspan style=\"color:#bd93f9\"\u003e200\u003c/span\u003e OK \u003cspan style=\"color:#ff79c6\"\u003ein\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e47\u003c/span\u003e milliseconds\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eI0919 \u003cspan style=\"color:#bd93f9\"\u003e09\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e59\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e20.096056\u003c/span\u003e   \u003cspan style=\"color:#bd93f9\"\u003e77328\u003c/span\u003e round_trippers\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ego:\u003cspan style=\"color:#bd93f9\"\u003e296\u003c/span\u003e] GET https:\u003cspan style=\"color:#ff79c6\"\u003e//\u003c/span\u003eopenshift:\u003cspan style=\"color:#bd93f9\"\u003e8443\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e/\u003c/span\u003eversion\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eI0919 \u003cspan style=\"color:#bd93f9\"\u003e09\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e59\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e20.096078\u003c/span\u003e   \u003cspan style=\"color:#bd93f9\"\u003e77328\u003c/span\u003e round_trippers\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ego:\u003cspan style=\"color:#bd93f9\"\u003e303\u003c/span\u003e] Request Headers:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eI0919 \u003cspan style=\"color:#bd93f9\"\u003e09\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e59\u003c/span\u003e:\u003cspan style=\"color:#bd93f9\"\u003e20.096084\u003c/span\u003e   \u003cspan style=\"color:#bd93f9\"\u003e77328\u003c/span\u003e round_trippers\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ego:\u003cspan style=\"color:#bd93f9\"\u003e306\u003c/span\u003e]     User\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003eAgent: oc\u003cspan style=\"color:#ff79c6\"\u003e/\u003c/span\u003ev1\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003e\u003cspan style=\"color:#bd93f9\"\u003e4.0\u003c/span\u003e (darwin\u003cspan style=\"color:#ff79c6\"\u003e/\u003c/span\u003eamd64) openshift\u003cspan style=\"color:#ff79c6\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#bd93f9\"\u003e85\u003c/span\u003eeb37b\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eI was thinking to come up with my own python rest wrapper since a google quick search didn\u0026rsquo;t come up with any binding. But since openshift is build on kubernetes and fully compatible with it (i.e: no fork or changes that make it incompatible) it was as easy as using the tools provided for kube.\u003c/p\u003e","title":"Using python to drive OpenShift REST API"},{"content":"In latest openshift client (oc) there is a nifty (relatively) new feature to get you a OpenShift cluster starting (very) quickly. It\u0026rsquo;s a pretty nice way to get you a new openshift origin environment on your laptop without the hassle.\nOn macosx there is a (as well relatively) new lightweight virtualization solution called xhyve it\u0026rsquo;s a bit like KVM in the sense of being lightweight and does not need like virtualbox or vmware to get a UI running. It seemed to be a perfect fit to try those two together.\nxhyve docker machine driver needed to be installed first so I just went on its website here :\nhttps://github.com/zchee/docker-machine-driver-xhyve\nand followed the installation instruction from the README which I could see everything was working :\nI then fired up the \u0026ldquo;oc cluster up \u0026ndash;create-machine\u0026rdquo; command and to my disappointment it was starting by default the virtualbox and I could not see anything in the options how to specify the \u0026ldquo;\u0026ndash;driver xhyve\u0026rdquo; option to docker-machine which is what the oc cluster feature is using on the backend to bootstrap a docker environment.\nDigging into the code it seems that the oc cluster has those feature set in static as virtualbox :\nhttps://github.com/openshift/origin/blob/85eb37b34f0657631592356d020cef5a58470f8e/pkg/bootstrap/docker/dockermachine/helper.go#L56-L79\nsince there was no way to pass other options I first looked in the github issues to see if there was nothing reported about it and sent a feature request here,\nI started to think a little bit more about a workaround going from modifying to my liking and recompiling the oc client or to just give up on xhyve but in fact the solution is actually much simplier.\nSince there is the ability to specify to \u0026ldquo;oc cluster up\u0026rdquo; an already configured docker-machine environment with the \u0026quot; \u0026ndash;docker-machine\u0026quot; option. We just had to configured previously properly first (which is with the option \u0026ndash;engine-insecure-registry 172.30.0.0/16) :\nand after a bit the new docker should be setup which can be easily used with the command eval $(docker-machine env xhyve)\nI then just have to start my oc cluster up with the option \u0026ndash;docker-machine=\u0026ldquo;xhyve\u0026rdquo; and I would get my nicely setuped openshift origin cluster to play with in mere seconds :\n","permalink":"https://blog.chmouel.com/2016/09/19/getting-openshift-origin-cluster-up-working-with-xhyve/","summary":"\u003cp\u003eIn latest openshift client (oc) there is a nifty (relatively) new feature to get you a OpenShift cluster starting (very) quickly. It\u0026rsquo;s a pretty nice way to get you a new openshift origin environment on your laptop  without the hassle.\u003c/p\u003e\n\u003cp\u003eOn macosx there is a (as well relatively) new lightweight virtualization solution called \u003ca href=\"https://github.com/mist64/xhyve\"\u003exhyve\u003c/a\u003e it\u0026rsquo;s a bit like KVM in the sense of being lightweight and does not need like virtualbox or vmware to get a UI running. It seemed to be a perfect fit to try those two together.\u003c/p\u003e","title":"Getting openshift origin “cluster up” working with xhyve"},{"content":"Sometime ago or at least when I started doing programming in the late 90s XML was all the rage, it promised to be the panacea for everything from data to storage to data presentation and processing. People realized that it was just complexity as Joel Spolski points out an attempt to make the complex seem accessible to ordinary people.. Really people were annoyed to write all those tags as those \u0026lsquo;\u0026lt;\u0026rsquo; and \u0026lsquo;\u0026gt;\u0026rsquo; are hard to reach on a qwerty keyboard.\nBeginning the new millennia in 2000 the web started to get very popular and things like \u0026ldquo;web services\u0026rdquo; popped up everywhere, people realised that actually XML is not that great so started to get a format called Json to get computers talking to each others in a sane manner.\nBut people realise that json was actually not that great to chat between web services as it was actually designed to serialize objects between programming languages. And really down the line it\u0026rsquo;s more about the programmers being annoyed by all those { } [ ] brackets\nSo here came yaml the latest \u0026ldquo;fashion format\u0026rdquo; based on the popularity of tab based programming languages.\nMost new software lately have been using it, all the containers software ecosystem configure things in yaml so you have to deal with it when you work with them.\nI don\u0026rsquo;t know if I like yaml or not, the only thing i know is that when I have a big ass large yaml file it become quickly unreadable. You have no idea which blocks belong to which one and not sure how many indents you need to add to that block to align to that other one that started 800 lines ago.\nThis has been driving me crazy as I need to write some large kubernetes/OpenShift yaml files and sometime end up for hours trying to detect where I have my tab alignment.\nSome may argue, but you do python and python is tab based. Yeah i have been doing python for the last 10 years and this has never been issue cause first I don\u0026rsquo;t write kick ass 5000 lines python functions and second the python mode of my editor Emacs is properly configured.\nAh there I say it, the editor needs to be configured properly to have a good workflow so here is Emacs to the rescue to make it bearable (and make that post more productive that another rant from the interweb)\nSo without further ado and with much fanfare, here is the emacs extension i found to make writing yaml bearable :\nHighlight Indentation for Emacs\nThis mode would give you a visual representation of the current indentation with a bar showing the indentation.\nSmart Shift\nThis mode doesn\u0026rsquo;t give you a visual but allow you to indent blocks of texts easily. Usually in emacs you would use the Control-x Tab command to indent and prefix it with a number for the number of indent. For example C-u 4 Control-x Tab would indent the text for 4 spaces. Smart shift make things much easier to move around.\nFlycheck-mode\nThis is a generics mode you should really configure for all your programming needs, it supports yaml files and will try to validate (with ruby-yaml library) your yaml file and see where you have an error.\naj-toggle-fold\nThis is a function I found in a post on stackoverflow (by the author of Highlight-Indentation-for-Emacs) it allow you to folds all code on an indentation level greater than the current line. A great way to show you the current outline of the file.\n","permalink":"https://blog.chmouel.com/2016/09/07/dealing-with-yaml-in-emacs/","summary":"\u003cp\u003eSometime ago or at least when I started doing programming in the late 90s \u003cstrong\u003eXML\u003c/strong\u003e was all the rage, it promised to be the panacea for everything from data to storage to data presentation and processing. People \u003ca href=\"http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show\u0026amp;ixPost=953\"\u003erealized\u003c/a\u003e that it was just complexity as Joel Spolski points out \u003cem\u003ean attempt to make the complex seem accessible to ordinary people.\u003c/em\u003e. Really people were annoyed to write all those tags as those \u0026lsquo;\u0026lt;\u0026rsquo; and \u0026lsquo;\u0026gt;\u0026rsquo; are hard to reach on a qwerty keyboard.\u003c/p\u003e","title":"The best ways to work with yaml files in Emacs"},{"content":"I am lucky enough to have a cloud available to me for free it obviously runs OpenStack and I can kick VM like I want.\nSince I am playing with OpenShift a lot lately I have seen issues in that cloud where pushing an image to the internal registry was just randomly failing.\nNetworking is definitely not my pedigree but I could definitely sense it was a networking issue. Since I could nost just blame the underlying cloud (hey it\u0026rsquo;s free!) I had to investigate a bit.\nUsing the \u0026ldquo;access to internal docker registry\u0026rdquo; feature of OpenShift, I could definitively push from the master (where the registry was) in 2s but not from the node where it was completely stucks at the end while it could only push some bits at first and after waiting forever there.\nI came back to our internal mailing list and the local experts there pointed me to the file :\n/etc/sysconfig/openshift-node and the interesting part is this :\n# The $DOCKER_NETWORK_OPTIONS variable is used by sdn plugins to set # $DOCKER_NETWORK_OPTIONS variable in the /etc/sysconfig/docker-network # Most plugins include their own defaults within the scripts # TODO: More elegant solution like this # https://github.com/coreos/flannel/blob/master/dist/mk-docker-opts.sh # DOCKER_NETWORK_OPTIONS=\u0026#39;-b=lbr0 --mtu=1450\u0026#39; I uncommented and adjusted my MTU to 1400 since 1450 wasn\u0026rsquo;t working for me and after a reboot I could push properly my images from the nodes to the internal registry.\nThanks to sdodson and Erik for pointing me to this\n","permalink":"https://blog.chmouel.com/2015/09/25/openshift-sdn-with-openstack-sdn-and-mtu/","summary":"\u003cp\u003eI am lucky enough to have a cloud available to me for free it obviously runs OpenStack and I can kick VM like I want.\u003c/p\u003e\n\u003cp\u003eSince I am playing with OpenShift a lot lately I have seen issues in that cloud where pushing an image to the internal registry was just randomly failing.\u003c/p\u003e\n\u003cp\u003eNetworking is definitely not my pedigree but I could definitely sense it was a networking issue. Since I could nost just blame the underlying cloud (hey it\u0026rsquo;s free!) I had to investigate a bit.\u003c/p\u003e","title":"openshift-sdn with OpenStack SDN and MTU"},{"content":"Something that has come up when using OpenShift and that was tricky enough to be shared on a blog post.\nOn OpenShift you have this routers and registry which by default are on the master nodes and that\u0026rsquo;s fine. Things get tricky if you don\u0026rsquo;t want anything else in there.\nI finally figured this out after digging in some internal mailing lists and this is actually not too difficult. The key thing is to have this on the \u0026lsquo;default\u0026rsquo; namespace annotations :\nopenshift.io/node-selector: region=infra The default namespace is an internal namespace used for openshift infrastructure services.\nLet me describe this a little bit further, here is my node labels configuration :\nroot@master:~$ oc get node NAME LABELS STATUS AGE master.local.openshift.chmouel.com kubernetes.io/hostname=master.local.openshift.chmouel.com,region=infra,zone=default Ready 2d node1.local.openshift.chmouel.com kubernetes.io/hostname=node1.local.openshift.chmouel.com,region=primary,zone=west Ready 2d node2.local.openshift.chmouel.com kubernetes.io/hostname=node2.local.openshift.chmouel.com,region=primary,zone=east Ready 2d I had already a router running fine on my master by forcing (this was generated by the oadm router command) it with a nodeSelector on the deploymentConfig :\nroot@master:~$ oc get pod router-1-q3am8 -o yaml [..] nodeName: master.local.openshift.chmouel.com nodeSelector: region: infra [..] Now I am going to edit my /etc/origin/master/master-config.yaml and add :\nprojectConfig: defaultNodeSelector: \u0026#34;region=primary\u0026#34; which force all new nodes to get on the primary region.\nAs expected if I delete my router and redeploy it :\nroot@master:~$ oc delete pod router-1-q3am8 root@master:~$ oc deploy router --latest The router was not able to be deployed since getting since we explicitely told the scheduler that we want pods only on infra :\nSep 23 09:45:52 master.local.openshift.chmouel.com origin-master[2879]: I0923 09:45:52.203596 2879 event.go:203] Event(api.ObjectReference{Kind:\u0026#34;ReplicationController\u0026#34;, Namespace:\u0026#34;default\u0026#34;, Name:\u0026#34;router-1\u0026#34;, UID:\u0026#34;454f46b0-5fbc-11e5-9c22-fa163e93ac32\u0026#34;, APIVersion:\u0026#34;v1\u0026#34;, ResourceVersion:\u0026#34;99201\u0026#34;, FieldPath:\u0026#34;\u0026#34;}): reason: \u0026#39;failedCreate\u0026#39; Error creating: pods \u0026#34;\u0026#34; is forbidden: pod node label selector conflicts with its project node label selector So what I had to do now is to edit the default namespace (not project but namespace that\u0026rsquo;s a critical point) and add in the metadata/annotations section :\napiVersion: v1 kind: Namespace metadata: annotations: openshift.io/node-selector: region=infra which to say that the default project can be indeed deployed on region=infra.\nNow let\u0026rsquo;s try again :\nroot@master:~$ oc deploy router --latest and check the log :\nSep 23 09:47:25 master.local.openshift.chmouel.com origin-master[2879]: I0923 09:47:25.341257 2879 event.go:203] Event(api.ObjectReference{Kind:\u0026#34;ReplicationController\u0026#34;, Namespace:\u0026#34;default\u0026#34;, Name:\u0026#34;router-1\u0026#34;, UID:\u0026#34;454f46b0-5fbc-11e5-9c22-fa163e93ac32\u0026#34;, APIVersion:\u0026#34;v1\u0026#34;, ResourceVersion:\u0026#34;99201\u0026#34;, FieldPath:\u0026#34;\u0026#34;}): reason: \u0026#39;successfulCreate\u0026#39; Created pod: router-1-l5r0e which seems to work fine and deployed on infra :\nroot@master:~$ oc get pod|grep router router-1-ed6dk 1/1 Running 0 1h root@master:~$ ","permalink":"https://blog.chmouel.com/2015/09/23/openshift-default-router-on-master-nodes-but-no-others/","summary":"\u003cp\u003eSomething that has come up when using OpenShift and that was tricky enough to be shared on a blog post.\u003c/p\u003e\n\u003cp\u003eOn OpenShift you have this routers  and registry which by default are on the master nodes and that\u0026rsquo;s fine. Things get tricky if you don\u0026rsquo;t want \u003cem\u003eanything else\u003c/em\u003e in there.\u003c/p\u003e\n\u003cp\u003eI finally figured this out after digging in some internal mailing lists and this is actually not too difficult. The key thing is to have this on the \u0026lsquo;\u003cstrong\u003edefault\u003c/strong\u003e\u0026rsquo; namespace annotations :\u003c/p\u003e","title":"Deploy openshift router and registry only on a master nodes with no others"},{"content":"I have been experimenting a lot with OpenShift v3 and love how everything work well together plugging Kubernetes and Docker with a PAAS workflow.\nOne of the thing that I don\u0026rsquo;t get is to have to write manually verbose json templates, it\u0026rsquo;s wonderful for machines and to parse but writing it can get as painful as (dear I said it) XML.\nOpenShift natively support very nicely yaml files and it\u0026rsquo;s a straight conversion of what you would have in json format.\nSince at this time most of the examples are in json I wrote a script to quickly convert them to yaml and came up with this command line using python and bash :\nfor i in $(find . -name '*.json');do python -c 'import sys,json,yaml;print(yaml.safe_dump(json.loads(sys.stdin.read()), default_flow_style=False))' \u0026lt; $i \u0026gt; ${i/json/yaml};done Happy Yameling (I just made this word up and I am not even drunk)\n","permalink":"https://blog.chmouel.com/2015/03/24/using-yaml-for-openshift-v3-templates/","summary":"\u003cp\u003eI have been experimenting a lot with \u003ca href=\"github.com/openshift/origin\"\u003eOpenShift v3\u003c/a\u003e and love how everything work well together plugging Kubernetes and Docker with a \u003ca href=\"http://openshiftv3-cmorgancloud.rhcloud.com/\"\u003ePAAS workflow.\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eOne of the thing that I don\u0026rsquo;t get is to have to write manually verbose json templates, it\u0026rsquo;s wonderful for machines and to parse but writing it can get as painful as (dear I said it) XML.\u003c/p\u003e\n\u003cp\u003eOpenShift natively support very nicely yaml files and it\u0026rsquo;s a straight conversion of what you would have in json format.\u003c/p\u003e","title":"Using yaml for OpenShift v3 templates"},{"content":"\nFor an internal project at work I have been thinking about more how to generate RPMs out of our CI. I wanted to have them produced as artifacts of the build so I can test how if they can be installed and properly working with some smoketests.\nSince we are using Docker for most of the things in our CI, I have been thinking about more about how to do that with docker images and RPM.\nIdeally what I would love to have from RPM is to be able to integrate with Docker so when you build your RPM you are building in a docker images. Basically the %prep section will be spined-up in a special docker images and the rpm output would be back to the host.\nThe advantages outside of making sure you are building your RPMs in a confined and reproducible enthronement is that you would be able to say from the same rpm build that I want to build the RPMs for centos/fedora/rhel/etc.. in whatever flavours.\nI am sure there is some workaround way to do that with chroot and such but it would be nice if this mechanism is built-in inside RPM (be it an abstracted system to do that as chroot/docker or whatever container technology).\nSince we are not there yet, I have ended-up just the straightforward way of constructing an image with my build dependences.\nIt\u0026rsquo;s a python project which use PBR for generating the version so I have to generate first a tarball in my build directory and get the generated version.\nI modify the spec file with that version and start to build the image with the new tarball and new spec file.\nI run the image and mount a volume to a local directory on the host and start running the image which run the start.sh script in the container.\nThe start.sh script is pretty straightforward, it builds the rpm and copy them to the volume directory as root (since there is no other way) so they can be copied from the host to the artifact output directory.\nI could have not copying and uploading to a object storage system (like Swift obviously) but since I needed to be available in the CI I ended-up up with the local file copy system.\nHere is my scripts, in SPECS/project.spec and SOURCES/* there is the spec and sources/patches as a standard rpm, the only thing is to make sure to use a %define _version VERSION and use that macro for Version in your spec file.\nThe main build.sh which get run from the CI\nThe DockerFile which try to be optimised a bit for Docker caching :\nand the script start.sh that gets run inside the container :\nIt probably would not fit straight to your environement but at least that may get you the idea.\n","permalink":"https://blog.chmouel.com/2014/12/31/building-rpm-with-docker-images/","summary":"\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2014/12/dockerrpm-175x300.jpg\"\u003e\u003c/p\u003e\n\u003cp\u003eFor an internal project at work I have been thinking about more how to generate RPMs out of our CI. I wanted to have them produced as artifacts of the build so I can test how if they can be installed and properly working with some smoketests.\u003c/p\u003e\n\u003cp\u003eSince we are using Docker for most of the things in our CI, I have been thinking about more about how to do that with docker images and RPM.\u003c/p\u003e","title":"Building RPM with Docker images"},{"content":"So the trend these days is to talk about container all the things that usually involve Docker, it even has a now its own verb, people are now using the word \u0026lsquo;containerizing\u0026rsquo; to describe packaging their application with Docker.\nA lot of the things happening lately in the Docker world is to solve how to get those containers in real production environments, there is people working on taking the \u0026lsquo;containerization\u0026rsquo; philosophy to storage, networking or getting orchestration right\nWhile getting docker in production is an important thing to have that would be hopefully getting solved and stable sometime soon, there is the use case for docker that can be used as of right now which is the developer use case.\nI briefly mentioned this in another blog post and wanted to expand my thoughts here after chatting with some of my colleagues that don\u0026rsquo;t seem to get how that would help and consider the docker trending not much more than a marketing trend.\nTake functional Testing to an another level.\nI am not going to go over of what functional testing is and all the different type of Software testing. There is a lot of them that are very well documented andexcept the unittests they usually need to have the real services properly up and running first\nThe testing driven development for unittests is a very well known process to develop application, it usually tightens to unittest. You start to write your unittests and write your code and fix your code/tests in an iterative way.\nWhen the code is working usually it gets committed to a CI environment which run the unittests and maybe some other functional tests before it gets reviewed and merged.\nThe functional tests for that feature doesn\u0026rsquo;t get committed at the same time, because usually running functional tests is painful and can takes a lot of time. You have to setup all the things properly, the initial setup of your DB and how it communicate to your service in the right context of how you want to do your testing.\nAnd even if you go by that path and get it done, most people would just do it in a single VM easy to share among your colleagues and you wont\u0026rsquo; go by the process of properly setup bunch of vm that communicate together like a DB a APP and perhaps a WEB server. You won\u0026rsquo;t even try to test how your application scales and behave cause that\u0026rsquo;s even more costly.\nHave your functional testing done by multiple services not just a single VM.\nAnd that\u0026rsquo;s where testing with docker with an orchestrator like fig can shine. You can specify different scenarios that are really quick to deploy. You can run different runs and targets directly from your CI and more importantly\nyou can easily share those to your colleagues/contributors and that\u0026rsquo;s usually very fast cause if there is one thing docker is good is that it does a lot of smart caching to build the images and run those images in a blink of a second.\nShow your users how your app should be deploy.\nWhen you build your Dockerfiles you show the way how your apps is building and how the configuration is setup. You are able to give ideas to your users how it would work. It may not going to be optimal and perfect since you probably not going to have the same experience and tweaking of someone who deploys complicated software for a living but at least you can give a guideline how things works without having the user pulling his hair how things works.\nEven your unittesting can get more robust!\nThis is to follow up on my blog post on the tool dox I have introduced, since in OpenStack we have some very complicated tests to do that are very much dependent of a system it gets very complicated to run our unittests in a portable. But that\u0026rsquo;s not just OpenStack take for example an app that needs Sqlalchemy to run, you can sure run it with sqlite backend to run your unittests but you may going to end up in weird cases with your foreign keys not working properly and other SQL features not implemented. With containers you can have a container that gets setup with your DB of your choice to do your testing against easily. There is more use cases where you depend of the binary (or your dependences) depend of the system that you want to be controlled and contained.\nI hope those points would help you to get convinced into containers in your development workflow. Hopefully in the future all those workflow would generalised more and we would have even more powerful tools to get our development (almost) perfectly done â„¢\n","permalink":"https://blog.chmouel.com/2014/11/10/use-cases-for-docker-driven-development/","summary":"\u003cp\u003eSo the trend these days is to talk about container all the things that usually involve Docker, it even has a now its own verb, people are now using the word \u0026lsquo;containerizing\u0026rsquo; to describe packaging their application with Docker.\u003c/p\u003e\n\u003cp\u003eA lot of the things happening lately in the Docker world is to solve how to get those containers in real \u003ca href=\"http://www.projectatomic.io/\"\u003eproduction environments,\u003c/a\u003e there is people working on taking the \u0026lsquo;containerization\u0026rsquo; philosophy to \u003ca href=\"https://clusterhq.com/\"\u003estorage,\u003c/a\u003e \u003ca href=\"https://github.com/zettio/weave\"\u003enetworking\u003c/a\u003e or getting \u003ca href=\"https://github.com/GoogleCloudPlatform/kubernetes\"\u003eorchestration\u003c/a\u003e right\u003c/p\u003e","title":"Use cases for Docker driven development."},{"content":"\nI have been playing with docker quite a lot lately. The advantage for me is to be able to run functional tests easily and be able to document how deployment should be done of my software as a developer for my endusers (i.e: operators/admins).\nThe advantage of this method is probably an article of its own which I won\u0026rsquo;t dig into today but just to give a tip for the existing users of fig/docker\nIt\u0026rsquo;s easy to get race conditions with fig and docker. Take for example, if you have a common pattern when you have a web and a DB, the DB will start before the Web server as orchestrated by fig and link to each others; but since the DB server didn\u0026rsquo;t have time to configure itself and web has already started it would just fail connecting for it.\nIn an ideal world the app should wait for DB to be up and setup before starting to connect to it but that\u0026rsquo;s not something easy all the time.\nPeople of docker and fig have noticed that and there is some proposal for that from a fig dev :\nhttps://github.com/docker/docker/issues/7445\nThe idea there is to have docker waiting that the exposed port is open and listening to be able to set that said container as started. This is not something easy to do since docker would have an hard time to figure out if (and how) that port is open.\nUntil there is a resolution that comes up you can always resort to the shell script to get it done. There is multiple tool that can check if a port is open\nfrom ping to netcat or curl etc. It really depend of what you are allowing to have into your base container.\nSince most of my devs involved Python, I do always have them in my containers so\nI came up with some built-in python solution, that looks like this :\nand in my start.sh of my app server I use it like this before starting my app server:\ncheck_up \u0026quot;DB Server\u0026quot; ${DB_PORT_3306_TCP_ADDR} 3306 the advantage of this method is that it\u0026rsquo;s pretty fast to just look over the\nopening the socket until it\u0026rsquo;s getting open and fail fast.\nHope this helps.\n","permalink":"https://blog.chmouel.com/2014/11/04/avoiding-race-conditions-between-containers-with-docker-and-fig/","summary":"\u003cp\u003e\u003ca href=\"/wp-content/uploads/2014/11/figs.jpg\"\u003e\u003c!-- raw HTML omitted --\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eI have been playing with docker quite a lot lately. The advantage for me is to be able to run functional tests easily and be able to document how deployment should be done of my software as a developer for my endusers (i.e: operators/admins).\u003c/p\u003e\n\u003cp\u003eThe advantage of this method is probably an article of its own which I won\u0026rsquo;t dig into today but just to give a tip for the existing users of \u003c!-- raw HTML omitted --\u003efig\u003c!-- raw HTML omitted --\u003e/docker\u003c/p\u003e","title":"Avoiding race conditions between containers with docker and fig"},{"content":"\nSometime there is some ideas that are just obvious that they are good ideas. When Monty started to mention on the OpenStack development mailing list about a tool he was hacking on allowing to integrate docker containers to do the testing it was obvious it was those ideas that everybody was thinking about that it would be awesome if it was implemented and started to get used.\nThe idea of dox is like the name imply is to slightly behave like the tox tool but instead of running virtualenvs you are using docker containers.\nThe testing in the OpenStack world is a bit different than the other unit testing. Since OpenStack is inherently working with the local system components we have to get abstracted from the local developer box to match exactly the system components. In other words if we run our testing against a zookeeper daemon of a specific version we want to make it sure and easy that this version has been installed.\nAnd that\u0026rsquo;s where docker can help, since you can easily specify different images and how to build them making sure we have those tools installed when we run our testing targets.\nThere are other issues with tox that we have encountered in our extensive use of it in the OpenStack world we are hoping to solve here. virtualenv has been slow for us and we have come up with all sorts of hacks to get around it. And as monty mention in his mailing list post docker itself does an EXCELLENT job at handling caching and reuse where we easily see in the future those standard image built by the openstack-infra folks that we know works and validated in upstream\nopenstack-ci published on dockerhub that everyone else (and dox) can use to run tests.\nThe tool is available here in stackforge here :\nhttps://git.openstack.org/cgit/stackforge/dox\nwith an handy README that would get you started :\nhttps://git.openstack.org/cgit/stackforge/dox/tree/README.rst\nIts not quite ready yet but you can start running tests using it. If you want a fun project to work on that can help the whole Python development community (and not just OpenStack) come hack with us. We are as well on Freenode servers in IRC on channel #dox.\nIf you are not familiar with the contribution process of Stackforge/OpenStack see this wiki page which should guide through it :\nhttp://wiki.openstack.org/HowToContribute\n","permalink":"https://blog.chmouel.com/2014/09/08/dox-a-tool-that-run-python-or-others-tests-in-a-docker-container/","summary":"\u003cp\u003e\u003ca href=\"/wp-content/uploads/2014/09/dox-diagram-fix.png\"\u003e\u003c!-- raw HTML omitted --\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eSometime there is some ideas that are just obvious that they are good ideas. When \u003c!-- raw HTML omitted --\u003eMonty\u003c!-- raw HTML omitted --\u003e \u003c!-- raw HTML omitted --\u003estarted to mention\u003c!-- raw HTML omitted --\u003e on the OpenStack development mailing list about a tool he was hacking on allowing to integrate docker containers to do the testing it was obvious it was those ideas that everybody was thinking about that it would be awesome if it was implemented and started to get used.\u003c/p\u003e","title":"Dox a tool that run python (or others) tests in a docker container"},{"content":"I am lucky to sit in front of Julien Danjou at work and as the sole Emacs users on the side of our office it was come to our attention that we needed as emacsian to unite ourselves to preach the good parole of the church of Emacs and sexy mens.\nIt was quite obvious that the only way to convince those in the unkown was to find an excuse for drinks good food between good people and set-up a meetup.\nAnd since eNovance have now a very new fancy office with a large room to organise geeky (or not) oriented meetups, it was just a perfect time.\nWithin three clicks, three steps of dancing and after 10 minutes trying to do that straight from Emacs before coming back to a modern web browser (Emacs users are pragmatic) the Parisian OpenStack User Group\nopened.\nThis is with great success, In less than 5 days we had already 50 members and an informal drink-up organised for thursday.\nSo if you are based in Paris and you have a love for Emacs or just want to discover what\u0026rsquo;s that all about come join the group.\n","permalink":"https://blog.chmouel.com/2014/03/31/paris-emacs-meetup-group/","summary":"\u003cp\u003eI am lucky to sit in front of \u003ca href=\"http://julien.danjou.info/\"\u003eJulien Danjou\u003c/a\u003e at work and as the sole Emacs users on the side of our office it was come to our attention that we needed as emacsian to unite ourselves to preach the good parole of the \u003ca href=\"http://churchofemacs.org/\"\u003echurch of Emacs\u003c/a\u003e and \u003ca href=\"http://rms.sexy\"\u003esexy mens.\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eIt was quite obvious that the only way to convince those in the unkown was to find an excuse for drinks good food between good people and set-up a meetup.\u003c/p\u003e","title":"Announcing the (Paris (Emacs) Meetup) Group"},{"content":"My day to day being work or personal is to create OpenSource code. As an habit I have taken lately I am adding licenses to all new files I am creating.\nI have historically used the `auto-insert-mode with a default template. For example for my newly created python files I would have this for configration :\n;AutoInsert (auto-insert-mode \u0026#39;t) (setq auto-insert-alist \u0026#39;((python-mode . \u0026#34;python.py\u0026#34;))) and in my `auto-insert-directory directory there would be a python.py template with my license files.\nBut that\u0026rsquo;s not so smart, since I wanted to find a mechanism to switch between work email and personal emails for my copyright I needed those templates to be more dynamic.\nThings with auto-insert templates taken from a directory they are not so dynamics and reading through the always excellent emacswiki page it seems that you need to `define-auto-insert the templates to get dynamic variables.\nI didn\u0026rsquo;t want to go to the define-auto-insert because I am always using the yasnippet package for my snippets which has a great expansion support and a nice templating language.\nAs it\u0026rsquo;s mostly always the case if you have a problem you can be sure it\u0026rsquo;s already resolved by others, so a quick search on the internet leaded me to a gist file written by a guy three years ago that does exactly what I wanted :\nSo now that I had my header loaded from yasnippet I could add some smartness into it. I have first written this function :\n(defun yas--magit-email-or-default () \u0026#34;Get email from GIT or use default\u0026#34; (if (magit-get-top-dir \u0026#34;.\u0026#34;) (magit-get \u0026#34;user.email\u0026#34;) user-mail-address)) this function would check if we are in a git directory and get the user.email git configuration, if we are not it would just reply by the standard emacs variable `user-mail-address.\nI have just to plug that in my template like this :\n# -*- mode: snippet -*- # name: header # -- # -*- coding: utf-8 -*- # Author: Chmouel Boudjnah \u0026lt; `(yas--magit-email-or-default)`\u0026gt; and depending of my local configuration of my git repo it will add my license email according to that.\nIf I really needed to override the user-mail-address without using git I could always just drop a .dir-locals.el with something like this :\n((nil . ((user-mail-address . \u0026#34;chmouel@othercompany.com\u0026#34;)))) which would override the default user-mail-address to whatever I want.\n","permalink":"https://blog.chmouel.com/2014/03/14/how-do-i-manage-my-copyright-headers-in-emacs/","summary":"\u003cp\u003eMy day to day being work or personal is to create \u003ca href=\"http://openstack.org\"\u003eOpenSource\u003c/a\u003e code. As an habit I have taken lately I am adding licenses to all new files I am creating.\u003c/p\u003e\n\u003cp\u003eI have historically used the \u003ca href=\"https://www.gnu.org/software/emacs/manual/html_node/autotype/Autoinserting.html\"\u003e`auto-insert-mode\u003c/a\u003e with a default template. For example for my newly created python files I would have this for configration :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-lisp\" data-lang=\"lisp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#6272a4\"\u003e;AutoInsert\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eauto-insert-mode\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;t\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#ff79c6\"\u003esetq\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eauto-insert-alist\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e\u0026#39;\u003c/span\u003e((\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003epython-mode\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;python.py\u0026#34;\u003c/span\u003e)))\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eand in my \u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e`auto-insert-directory\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e directory there would be a python.py template with my license files.\u003c/p\u003e","title":"How do I manage my copyright headers in Emacs"},{"content":"We have all been there, we are committing a two character change in a project and send our review all happy and dandy with the review tool full of hope that our change is rock solid :\nYou now that a two character change cannot fail. This is a tiny change in some arcane part of the Swift code that can never get passed by the tests launched in Jenkins and should just be a straightforward commit.\nYou are still anxious to see how it goes, so we fire our web browser and go to that beautiful page setup by our infra team and like that guy watching the tiny greeen progress bar hoping, well.. that it\u0026rsquo;s stay green :\nYou\u0026rsquo;d think to don\u0026rsquo;t have to stress and you that you can just let it go do its job.\nBut after a couple of minutes (and that\u0026rsquo;s if you are lucky) you are receiving an email from jenkins stating that the \u0026ldquo;Build has failed\u0026rdquo;? And this is where you start to feel like this guy thinking WHAT HAVE I DONE :\nThere is a handy link near the failure giving you the full log in the console.html file there. But digging into that log is like looking for a needle in a haystack, you are spending at least at most 5 minutes looking for a FAIL until if you are lucky it finally popping up in front of your face :\nSo now that you went by that effort you need to match the FAILURE to a real bug. Armed with your web browser you get into the recheck page http://status.openstack.org/rechecks/ where you start hitting furiously your âŒ˜-F or Control-F key shortcut hoping to match to an existing bug report.\nTo be honest, it doesn\u0026rsquo;t have to be so tedious. Since I like to save my time for stuff like browsing the internet for OpenStack reactions gifs, I just automate the thing.\nI start to curl the console output of the failed job :\nand just use my trusty grep to grep the FAIL :\nI can just now go to the launchpad bug search page on https://bugs.launchpad.net/ and just type the failed test in the search box to look for that bug :\nand just hit the recheck bug bugnumber in the review box :\nPS: Go watch Sean Dague excellent summit talk: Jenkins Failed My Patch, What Do I Do.\n","permalink":"https://blog.chmouel.com/2013/12/24/life-of-openstack-contributor-jenkins-failure/","summary":"\u003cp\u003eWe have all been there, we are committing a two character change in a project and send our review all happy and dandy with the review tool full of hope that our change is rock solid :\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2013/12/Screenshot-2013-12-24-20.33.54.png\"\u003e\u003c/p\u003e\n\u003cp\u003eYou now that a two character change cannot fail. This is a tiny change in some arcane part of the \u003ca href=\"http://swift.openstack.org/\"\u003eSwift\u003c/a\u003e code that can never get passed by the tests launched in Jenkins and should just be a straightforward commit.\u003c/p\u003e","title":"The life of an OpenStack contributor checking for Jenkins failures"},{"content":"I spent too much time trying to figure out how to use the latest swiftclient/novaclient with Rackspace Cloud that I thought I would have to document it somewhere to avoid the pain for others.\nAssuming you don\u0026rsquo;t want to use pyrax and no OS_AUTH_SYSTEM plugin but just pure OpenStack python-novaclient/swiftclient on Rackspace cloud then you just need to export those variables in your shell :\nexport OS_REGION_NAME=ORD export OS_USERNAME=username export OS_TENANT_NAME=\u0026#34; \u0026#34; export OS_PASSWORD=password export OS_AUTH_URL=https://identity.api.rackspacecloud.com/v2.0/ so now the region is ORD here (Chicago) but this can be SYD/IAD/DFW or whatever new datacenter/region from Rackspace. If you wanted to use the UK region you would need another username/password which is tighted to the LON datacenter (yes that\u0026rsquo;s an another legacy weirdness).\nIn your username and password set your real username and password the one you use to log into the control panel not the API Keys since the API key is a RAX extension of their Keystone implementation.\nAnd for the real trick of the day here is to set export OS_TENANT_NAME=\u0026quot; \u0026quot; (yes that\u0026rsquo;s a space inside) because the behaviour of the identity on Rackspace Cloud is a bit weird (from what I understand username is the first class citizen and tenant_name is binded to a service) you don\u0026rsquo;t want to set a TENANT_NAME so we set a space (just empty does not work) and the service would just strip it and not set it to get our full service catalog and happily use our pure OpenStack nova or swift client\n","permalink":"https://blog.chmouel.com/2013/09/27/how-to-access-rackspace-cloud-with-latest-swiftclient-novaclient/","summary":"\u003cp\u003eI spent too much time trying to figure out how to use the latest swiftclient/novaclient with Rackspace Cloud that I thought I would have to document it somewhere to avoid the pain for others.\u003c/p\u003e\n\u003cp\u003eAssuming you don\u0026rsquo;t want to use \u003ca href=\"https://github.com/rackspace/pyrax\"\u003epyrax\u003c/a\u003e and no \u003ca href=\"https://blog.chmouel.com/2012/08/17/using-python-novaclient-against-rackspace-cloud-next-generation-powered-by-openstack/\"\u003eOS_AUTH_SYSTEM\u003c/a\u003e plugin but just pure OpenStack python-novaclient/swiftclient on Rackspace cloud then you just need to export those variables in your shell :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eOS_REGION_NAME\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003eORD\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eOS_USERNAME\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003eusername\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eOS_TENANT_NAME\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34; \u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eOS_PASSWORD\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003epassword\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eOS_AUTH_URL\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003ehttps://identity.api.rackspacecloud.com/v2.0/\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eso now the region is ORD here (Chicago) but this can be SYD/IAD/DFW or whatever new datacenter/region from Rackspace. If you wanted to use the UK region you would need \u003cstrong\u003eanother\u003c/strong\u003e username/password which is tighted to the LON datacenter (yes that\u0026rsquo;s an another legacy weirdness).\u003c/p\u003e","title":"How to access Rackspace Cloud with latest novaclient/swiftclient"},{"content":"curl is obviously an extremely popular way to experiment a REST API. Unfortunately one of its shortcoming is not able to remove a custom header but just to modify or add it. In swift if you prefix your Meta header with X-remove it would then just do that and remove the header.\nFor example when I wanted to remove the account quota header from an account with a reseller admin token I had just to do that :\ncurl -X POST -H 'X-Remove-Account-Meta-Quota-Bytes: 0' -H \u0026quot;x-auth-token: ${RESELLER_TOKEN}\u0026quot; http://localhost:8080/v1/AUTH_accountId\nand the X-Account-Meta-Quota-Bytes header was removed.\n","permalink":"https://blog.chmouel.com/2013/07/17/quick-swift-tip-how-to-remove-a-header-with-curl/","summary":"\u003cp\u003ecurl is obviously an extremely popular way to experiment a REST API. Unfortunately one of its shortcoming is not able to remove a custom header but just to modify or add it. In swift if you prefix your Meta header with \u003cstrong\u003eX-remove\u003c/strong\u003e it would then just do that and remove the header.\u003c/p\u003e\n\u003cp\u003eFor example when I wanted to remove the \u003ca href=\"https://blog.chmouel.com/2013/03/08/swift-and-quotas-in-upcoming-1-8-0-grizzly-release/\"\u003eaccount quota\u003c/a\u003e header from an account with a reseller admin token I had just to do that :\u003c/p\u003e","title":"Quick Swift Tip: How to remove a header with Curl"},{"content":"It is easy to launch the swift functional tests with v2 auth (Keystone).\nAssuming you have a recent version of python-swiftclient, python-keystoneclient and swift you need to first add a few users which is easily done with this script :\nAssuming you have already your OS_* variables configured with an admin, you can just launch it and it will :\nadd a tenant/user named test/tester. add a tenant/user name test2/tester2. add a user tester3 belonging to test2 but not operator on that tenant. and it will create a /etc/swift/swift.conf for testing. You can adjust the keystone host in auth_host there (default to 127.0.0.1)\nYou can now just go to your swift directory and launch the script :\n$ ./.functests and the functional tests will run against a keystone server (or a auth v2 api compatible server).\n","permalink":"https://blog.chmouel.com/2013/06/14/how-to-launch-the-swift-functional-test-suite-with-keystone/","summary":"\u003cp\u003eIt is easy to launch the swift functional tests with v2 auth (Keystone).\u003c/p\u003e\n\u003cp\u003eAssuming you have a recent version of python-swiftclient, python-keystoneclient and swift you need to first add a few users which is easily done with this script :\u003c/p\u003e\n\u003cp\u003eAssuming you have already your OS_* variables configured with an admin, you can just launch it and it will :\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eadd a tenant/user named test/tester.\u003c/li\u003e\n\u003cli\u003eadd a tenant/user name test2/tester2.\u003c/li\u003e\n\u003cli\u003eadd a user tester3 belonging to test2 but not operator on that tenant.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eand it will create a /etc/swift/swift.conf for testing. You can adjust the keystone host in auth_host there (default to 127.0.0.1)\u003c/p\u003e","title":"How to launch the Swift functional test suite with Keystone"},{"content":"PKI tokens has been implemented in keystone by [Adam Young][1] and others and was shipped for the OpenStack grizlly release. It is available since the version 2.0 API of keystone.\nPKI is a beautiful acronym to [Public-key infrastructure][2] which according to wikipedia defines it like this :\nPublic-key cryptography is a cryptographic technique that enables users to securely communicate on an insecure public network, and reliably verify the identity of a user via digital signatures.\nAs described more lengthy on this IBM [blog post][3] keystone will start to generate a public and a private key and store it locally.\nWhen getting the first request the service (i.e: [Swift][4]) will go get the public certificate from keystone and store it locally for later use.\nWhen the user is authenticated and a PKI token needs to be generated, keystone will take the private key and encrypt the token and the metadata (i.e: roles, endpoints, services).\nThe service by the mean of the auth_token middleware will decrypt the token with the public key and get the info to pass on to the service it set the *keystone.identity* WSGI environement variable to be used by the other middleware of the service in the paste pipeline.\nThe PKI tokens are then much more secure since the service can trust where the token is coming from and much more efficient since it doesn\u0026rsquo;t have to validate it on every request like done for UUID token.\nAuth token This bring us to the auth_token middleware. The auth token middleware is a central piece of software of keystone to provide a generic middleware for other python WSGI services to integrate with keystone.\nThe auth_token middleware was moved in grizzly to the python-keystoneclient package, this allows us to don\u0026rsquo;t have to install a full keystone server package to use it (remember this is supposed to be integrated directly in services).\nYou usually would add the auth_token middleware in your paste pipeline at the begining of it (there may be other middlewares before like logging, catch_errors and stuff so not quite the first one).\n","permalink":"https://blog.chmouel.com/2013/05/02/keystone-pki-tokens-overview/","summary":"\u003cp\u003ePKI tokens has been implemented in keystone by [Adam Young][1] and others and was shipped for the OpenStack grizlly release. It is available since the version 2.0 API of keystone.\u003c/p\u003e\n\u003cp\u003ePKI is a beautiful acronym to [Public-key infrastructure][2] which according to wikipedia defines it like this :\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003ePublic-key cryptography is a cryptographic technique that enables users to securely communicate on an insecure public network, and reliably verify the identity of a user via digital signatures.\u003c/p\u003e","title":"Keystone and PKI tokens overview"},{"content":"This is something I have been asked and I was at first under impression it was only available in v3, digging a bit more into the code there is actually a way to do that in v2 when you are using PKI tokens. Since I could not find much documentation online here is a description of the steps how to do it.\nLet first get a PKI token, you can do it the hard way by sending a json blob to the keystone url and parse the json results like this :\n$ curl -s -d \u0026#39;{\u0026#34;auth\u0026#34;: {\u0026#34;tenantName\u0026#34;: \u0026#34;tenant\u0026#34;, \u0026#34;passwordCredentials\u0026#34;: {\u0026#34;username\u0026#34;: \u0026#34;user\u0026#34;, \u0026#34;password\u0026#34;: \u0026#34;password\u0026#34;}}}\u0026#39; -H \u0026#39;Content-type: application/json\u0026#39; http://localhost:5000/v2.0/tokens or do the easy way by gettting my script available here :\nhttp://p.chmouel.com/ks\nand use it like that :\neval $(bash ks -s localhost tenant:user password) it will give you a variable $TOKEN and a variable $STORAGE_URL that you can use further down.\nnow let\u0026rsquo;s try to use it with our swift :\n$ curl -i -H \u0026#34;X-Auth-Token: $TOKEN\u0026#34; ${STORAGE_URL} HTTP/1.1 204 No Content Content-Length: 0 Accept-Ranges: bytes X-Timestamp: 1366666887.01151 X-Account-Bytes-Used: 0 X-Account-Container-Count: 0 Content-Type: text/html; charset=UTF-8 X-Account-Object-Count: 0 X-Trans-Id: tx5b50dc6d01d04923a40a1486c13dd94d Date: Mon, 22 Apr 2013 22:01:00 GMT all good here,\nso now go inside your keystone.conf and get your admin/service token or use that friendly copy and paste command line :\n$ ADMIN_TOKEN=$(sed -n \u0026#39;/^admin_token/ { s/.*=[ ]*//;p }\u0026#39; /etc/keystone/keystone.conf) and use it to DELETE the token we do that request directly to our keystone which is localhost here point it wherever you want:\n$ curl -X DELETE -i -H \u0026#34;X-Auth-Token: $ADMIN_TOKEN\u0026#34; http://localhost:5000/v2.0/tokens/$TOKEN HTTP/1.1 204 No Content Vary: X-Auth-Token Content-Length: 0 Date: Mon, 22 Apr 2013 22:01:08 GMT We can still use it because the token is still in the cache. By default tokens are cached in memcache as good as 5 minutes but the\nrevocation list is fetched every seconds or so.\n$ curl -i -H \u0026#34;X-Auth-Token: $TOKEN\u0026#34; ${STORAGE_URL} 204 No Content Content-Length: 0 Accept-Ranges: bytes X-Timestamp: 1366666887.01151 X-Account-Bytes-Used: 0 X-Account-Container-Count: 0 Content-Type: text/html; charset=UTF-8 X-Account-Object-Count: 0 X-Trans-Id: tx9018045ce1324203a91e882ec6d27ac3 Date: Mon, 22 Apr 2013 22:01:12 GMT but after a bit (like over a minute or so) we are getting a proper denied:\n$ curl -i -H \u0026#34;X-Auth-Token: $TOKEN\u0026#34; ${STORAGE_URL} HTTP/1.1 401 Unauthorized Content-Length: 131 Content-Type: text/html; charset=UTF-8 X-Trans-Id: tx9133daf949204f0facf45152a43836bb Date: Mon, 22 Apr 2013 22:27:23 GMT \u0026gt;h1\u0026lt;Unauthorized\u0026lt; \u0026lt;p\u0026gt; This server could not verify that you are authorized to access the document you requested.\u0026lt;/html\u0026gt; proxy-server Token 49d94a8ca068013b6efe79e3463627c8 is marked as having been revoked proxy-server Token validation failure.#012Traceback (most recent call last):#012 File \u0026#34;/opt/stack/python-keystoneclient/keystoneclient/middleware/auth_token.py\u0026#34;, line 689, in _validate_user_token#012 verified = self.verify_signed_token(user_token)#012 File \u0026#34;/opt/stack/python-keystoneclient/keystoneclient/middleware/auth_token.py\u0026#34;, line 1045, in verify_signed_token#012 raise InvalidUserToken(\u0026#39;Token has been revoked\u0026#39;)#012InvalidUserToken: Token has been revoked [..] proxy-server Marking token MIIGogYJK...... as unauthorized in memcache ","permalink":"https://blog.chmouel.com/2013/04/22/howto-revoke-a-token-with-keystone-and-pki-v2-0-api/","summary":"\u003cp\u003eThis is something I have been asked and I was at first under impression it was only available in v3, digging a bit more into the code there is actually a way to do that in v2 when you are using PKI tokens. Since I could not find much documentation online here is a description of the steps how to do it.\u003c/p\u003e\n\u003cp\u003eLet first get a PKI token, you can do it the hard way by sending a json blob to the keystone url and parse the json results like this :\u003c/p\u003e","title":"Howto revoke a token with keystone and PKI (v2.0 API)"},{"content":"How I feel when I try to address all pylint warning/errors:\nAdapted from http://devopsreactions.tumblr.com/post/47690154351/trying-to-code-to-w3c-standards\n","permalink":"https://blog.chmouel.com/2013/04/11/trying-to-be-pylint-compatible/","summary":"\u003cp\u003eHow I feel when I try to address all pylint warning/errors:\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"/wp-content/uploads/2013/04/tumblr_inline_mk6xomQvzf1qz4rgp.gif\"\u003e\u003c!-- raw HTML omitted --\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eAdapted from \u003ca href=\"http://devopsreactions.tumblr.com/post/47690154351/trying-to-code-to-w3c-standards\"\u003ehttp://devopsreactions.tumblr.com/post/47690154351/trying-to-code-to-w3c-standards\u003c/a\u003e\u003c/em\u003e\u003c/p\u003e","title":"On trying to be pylint compatible"},{"content":"There is two new nifty middlewares for doing quotas in upcoming Swift release 1.8.0 called container_quotas and account_quotas.\nThose are two different middlewares because they are actually addressing different use cases.\ncontainer_quotas is typically used by end users the use case here is to let user to specify a limit on one of their container.\nWhy would you want to restrict yourself you may ask ? This is because when you allow a public upload to a container for example with tempurl or/and formpost you want to make sure people are not uploading a unlimited amount of datas.\nThe headers to configure for the container quota are :\nX-Container-Meta-Quota-Bytes - The Maximum size of the container, in bytes.\nX-Container-Meta-Quota-Count - Maximum object count of the\nThe account_quotas is more the typical quota implementation. A \u0026ldquo;super\nuser\u0026rdquo; with the reselleradmin group/role can set a byte limit for\nan account and the account will not be able to have new\nobjects/containers until someone cleanups his account to get under the\nlimited quotas.\nThe headers to configure the account quotas are :\nX-Account-Meta-Quota-Bytes - The Maximum size of the account in bytes.\nThe commit for the container quotas is here :\nBasic container quotas\nand account quotas commit :\nAccount quotas\nEnjoy.\n","permalink":"https://blog.chmouel.com/2013/03/08/swift-and-quotas-in-upcoming-1-8-0-grizzly-release/","summary":"\u003cp\u003eThere is two new nifty middlewares for doing quotas in upcoming Swift release 1.8.0 called container_quotas and account_quotas.\u003c/p\u003e\n\u003cp\u003eThose are two different middlewares because they are actually addressing different use cases.\u003c/p\u003e\n\u003cp\u003econtainer_quotas is typically used by end users the use case here is to let user to specify a limit on one of their container.\u003c/p\u003e\n\u003cp\u003eWhy would you want to restrict yourself you may ask ? This is because when you allow a public upload to a container for example with tempurl or/and formpost you want to make sure people are not uploading a unlimited amount of datas.\u003c/p\u003e","title":"Swift and quotas in upcoming 1.8.0 (Grizzly) release."},{"content":"I have been using quite a bit the anything-mode for Emacs, it\u0026rsquo;s basically a Quicksilver/Alfred or Gnome-do for Emacs and allow to configure a lot of different sources to complete some chosen \u0026lsquo;source\u0026rsquo;with different actions.\nWith my work on OpenStack I have found myself jumping a lot between git directories and due configured the variable \u0026lsquo;magit-repo-dirs for easy access to most of them easily.\nPlugging those two just seemed natural I had already this in my emacs to quickly open those magit repository directories :\n(global-set-key (read-kbd-macro \u0026#34;C-S-o\u0026#34;) \u0026#39;(lambda ()(interactive) (dired (magit-read-top-dir nil)))) But going with anything is much nicer and I can add another action for openning the source to magit so I quickly came up with this magit source :\n[gist id=\u0026ldquo;4751125\u0026rdquo; file=\u0026ldquo;anything-magit.el\u0026rdquo;]\nso now I open my different OpenStack Swift projects quickly with only a few keyboard touch (I bind my custom anything function to C-z) which shows graphically like this :\nas always my full emacs config is available here:\nhttp://github.com/chmouel/emacs-config\n","permalink":"https://blog.chmouel.com/2013/02/10/emacs-anything-with-magit/","summary":"\u003cp\u003eI have been using quite a bit the \u003ca href=\"http://www.emacswiki.org/emacs/Anything\"\u003eanything-mode\u003c/a\u003e for Emacs, it\u0026rsquo;s basically a \u003ca href=\"http://qsapp.com/\" title=\"Quicksilver\"\u003eQuicksilver\u003c/a\u003e/\u003ca href=\"www.alfredapp.com\"\u003eAlfred\u003c/a\u003e or \u003ca href=\"http://do.cooperteam.net/\" title=\"Gnome-do\"\u003eGnome-do\u003c/a\u003e for Emacs and allow to configure a lot of different sources to complete some chosen \u0026lsquo;source\u0026rsquo;with different actions.\u003c/p\u003e\n\u003cp\u003eWith my work on \u003ca href=\"http://openstack.org\"\u003eOpenStack\u003c/a\u003e I have found myself jumping a lot between git directories and due configured the variable \u003cstrong\u003e\u0026lsquo;magit-repo-dirs\u003c/strong\u003e for easy access to most of them easily.\u003c/p\u003e\n\u003cp\u003ePlugging those two just seemed natural I had already this in my emacs to quickly open those magit repository directories :\u003c/p\u003e","title":"emacs anything with magit"},{"content":"One of our client at eNovance had a need to be able to upload to Swift directly from a web browser without going via a PHP proxy.\nThings in browser-land are not exactly the same as what we have in user-land, it is a bit more restricted to ensure the end-user security and there is a few hoops to jump through to get it working.\nTo be able to do a xmlrpc upload to another server (swift in this case) there is a \u0026lsquo;standard/recommendation\u0026rsquo; document made by W3C about it located here :\nhttp://www.w3.org/TR/2013/CR-cors-20130129/\nBasically what happen when in Javascript we do :\nrequest.open(\u0026#34;POST\u0026#34;, \u0026#34;http://swift/AUTH_account/container/\u0026#34;); request.setRequestHeader(\u0026#39;X-Auth-Token\u0026#39;, myToken); request.send(); The browser just before the request will send an OPTIONS request to check with the server if the request is allowed by the server. This look like this when uploading to Swift :\nThe Options request that the browser does is literally asking for the server (swift) to know if this domain where it\u0026rsquo;s uploading from is allowed to upload directly via xmlrpc. The request looks like this :\nThanks to the work of Adrian Smith this is supported since Swift version 1.7.5 (and improved in 1.7.6), you can do at server level config or with headers on container easily see the full detailled documentation here:\nhttp://docs.openstack.org/developer/swift/cors.html\nWhile working on this I could not find a clear example to test it, I only found a great article on this page :\nhttp://www.ioncannon.net/programming/1539/direct-browser-uploading-amazon-s3-cors-fileapi-xhr2-and-signed-puts/\nthat was targetted to amazon s3 and I adapted it to use with OpenStack Swift.\nYou can find it here and use it as an example for your application :\nhttps://github.com/chmouel/cors-swift-example\n","permalink":"https://blog.chmouel.com/2013/02/01/swift-with-cors-request/","summary":"\u003cp\u003eOne of our client at \u003ca href=\"http://enovance.com\"\u003eeNovance\u003c/a\u003e had a need to be able to upload to Swift directly from a web browser without going via a PHP proxy.\u003c/p\u003e\n\u003cp\u003eThings in browser-land are not exactly the same as what we have in user-land, it is a bit more restricted to ensure the end-user security and there is a few hoops to jump through to get it working.\u003c/p\u003e\n\u003cp\u003eTo be able to do a xmlrpc upload to another server (swift in this case) there is a \u0026lsquo;standard/recommendation\u0026rsquo; document made by W3C about it located here :\u003c/p\u003e","title":"Upload to OpenStack Swift via CORS/HTML5 request."},{"content":"With a team of colleagues from enovance we are going to be this week-end (2/3 Feb 2013) in Brussels for Fosdem.\nFeel free to catch me if you want to have a chat about Swift or OpenStack in general. I will be wearing a enovance woodie/t-shirt.\nSee you there!\n","permalink":"https://blog.chmouel.com/2013/01/31/in-belgium-for-fosdem-this-weekend/","summary":"\u003cp\u003eWith a team of colleagues from \u003ca href=\"http://enovance.com\"\u003eenovance\u003c/a\u003e we are going to be this week-end (2/3 Feb 2013) in Brussels for Fosdem.\u003c/p\u003e\n\u003cp\u003eFeel free to catch me if you want to have a chat about Swift or OpenStack in general. I will be wearing a enovance woodie/t-shirt.\u003c/p\u003e\n\u003cp\u003eSee you there!\u003c/p\u003e","title":"In belgium for Fosdem this weekend."},{"content":"And here is another year finishing and I am looking back how did I do with my fitness.\nI have instead did much more cycling finishing a easy sportive in wales of 130km and a pretty hard one in south of france of 160km with a lot of mountains climbed. I made it to 5000Km (for my racing bike not counting my city bike which has around 500km on it) :\nI would have done much more if I didn\u0026rsquo;t have a bad upper shine when I was in australia where I was going to do a month of cycling.\nThis year looks promising with the Madrid Marathon in april (going for around 3h20) and probably some pretty good cycling trips during the summer if shin/ankle get sorted, I am looking forward to 2013.\n","permalink":"https://blog.chmouel.com/2012/12/31/my-running-and-cycling-stats-2012/","summary":"\u003cp\u003eAnd here is another year finishing and I am looking back how did I do with my fitness.\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003cp\u003e  \u003ca href=\"/wp-content/uploads/2012/12/Screen-Shot-2012-12-31-at-18.12.22.png\"\u003e\u003c!-- raw HTML omitted --\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eI have instead did much more cycling finishing a easy sportive in wales of 130km and a pretty hard one in south of france of 160km with a lot of mountains climbed. I made it to 5000Km (for my racing bike not counting my city bike which has around 500km on it) :\u003c/p\u003e","title":"My running and cycling stats of 2012"},{"content":"After almost five years at Rackspace UK I have now decided to move on and come back for good to Paris I will be now at eNovance working as before on OpenStack projects.\n","permalink":"https://blog.chmouel.com/2012/12/12/moving-on-from-rackspace-and-joining-enovance/","summary":"\u003cp\u003eAfter almost five years at Rackspace UK I have now decided to move on and come back for good to Paris I will be now at \u003ca href=\"http://enovance.com/\" title=\"eNovance\"\u003eeNovance\u003c/a\u003e working as before on OpenStack projects.\u003c/p\u003e","title":"Moving on from Rackspace and joining eNovance."},{"content":"Sometime you just need a long trans atlantic flight and a stupidly long stop-over in a random city to do some of those task that can improve your day to day but you never take some time to do it.\nWhen using emacs I wanted a simple way to launch a nosetests on the current function my cursor is in Emacs. The syntax on nosetests is a bit tricky and I actually always have to look at my shell history to know the proper syntax (nosetests directory/filename.py:Class.function).\nI created a simple wrapper for emacs for that which allow to just hit a key to copy the nosetests command to feed to your shell or to use it for the compile buffer.\nIt\u0026rsquo;s available from here :\nhttps://github.com/chmouel/emacs-config/blob/master/modes/nosetests.el\nI have binded those keys for my python mode hook :\n(local-set-key (kbd \u0026#34;C-S-t\u0026#34;) \u0026#39;nosetests-copy-shell-comand) (local-set-key (kbd \u0026#34;C-S-r\u0026#34;) \u0026#39;nosetests-compile) Happy TDD!!!!\nUPDATE: There was an another nose mode already that does much more available here : https://bitbucket.org/durin42/nosemacs/\n","permalink":"https://blog.chmouel.com/2012/10/14/emacs-and-nosetests/","summary":"\u003cp\u003eSometime you just need a long trans atlantic flight and a stupidly long stop-over in a random city to do some of those task that can improve your day to day but you never take some time to do it.\u003c/p\u003e\n\u003cp\u003eWhen using emacs I wanted a simple way to launch a nosetests on the current function my cursor is in Emacs. The syntax on nosetests is a bit tricky and I actually always have to look at my shell history to know the proper syntax (nosetests directory/filename.py:Class.function).\u003c/p\u003e","title":"Emacs and nosetests"},{"content":"With the modular auth plugin system merged into python-novaclient it is now very easy to use nova CLI against the Rackspace Public Cloud powered by OpenStack.\nwe even have a metapackage that would install all the needed bits. This should be easy as doing this :\nand all dependencies and extensions will be installed. To actually use the CLI you just need to specify the right arguments (or via env variable see nova \u0026ndash;help) like this :\non RAX cloud, usually the username is the tenant name so this should match.\nFor the UK Cloud you just need to change the auth_system to rackspace_uk like this :\n","permalink":"https://blog.chmouel.com/2012/08/17/using-python-novaclient-against-rackspace-cloud-next-generation-powered-by-openstack/","summary":"\u003cp\u003eWith the \u003ca href=\"https://github.com/openstack/python-novaclient/commit/86c713b17ac8984b54ff767d83ab41037e7a7833\"\u003emodular auth plugin system\u003c/a\u003e merged into python-novaclient it is now very easy to use nova CLI against the Rackspace Public Cloud powered by OpenStack.\u003c/p\u003e\n\u003cp\u003ewe even have a metapackage that would install all the needed bits. This should be easy as doing this :\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003cp\u003eand all dependencies and extensions will be installed. To actually use the CLI you just need to specify the right arguments (or via env variable see nova \u0026ndash;help) like this :\u003c/p\u003e","title":"Using python-novaclient against Rackspace Cloud next generation (powered by OpenStack)"},{"content":"Historically if you wanted to write software in python against OpenStack swift, people would have use the python-cloudfiles library or swift.common.client shipped with Swift.\npython-cloudfiles was made mostly for Rackspace CloudFiles before even Swift existed and does a lot of extra stuff not needed for OpenStack Swift (i.e: CDN).\nswift.common.client was designed for OpenStack Swift from the ground up but is included with Swift which made people having to download the full Swift repository if they wanted to use or tests against it. (i.e: OpenStack glance).\nAs yesterday we have now removed swift.common.client wth the bin/swift CLI and moved it to its own repository available here :\nhttps://github.com/openstack/python-swiftclient\nThis should be compatible with swift.common.client with only difference being to import swiftclient instead of importing swift.common.client\nAt this time we are using the same launchpad project as swift so feel free to send bugs/feature request under the swift project in launchpad :\nhttps://bugs.launchpad.net/swift/+filebug\nand add the tag python-swiftclient there.\n","permalink":"https://blog.chmouel.com/2012/06/13/swift-common-client-library-and-swift-cli-has-moved-to-its-own-project/","summary":"\u003cp\u003eHistorically if you wanted to write software in python against OpenStack swift, people would have use the python-cloudfiles library or swift.common.client shipped with Swift.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/rackspace/python-cloudfiles\"\u003epython-cloudfiles\u003c/a\u003e was made mostly for Rackspace CloudFiles before even Swift existed and does a lot of extra stuff not needed for OpenStack Swift (i.e: CDN).\u003c/p\u003e\n\u003cp\u003eswift.common.client was designed for OpenStack Swift from the ground up but is included with Swift which made people having to download the full Swift repository if they wanted to use or tests against it. (i.e: OpenStack glance).\u003c/p\u003e","title":"swift.common.client library and swift CLI has moved to its own project"},{"content":"A little note about swift3 the S3 emulation layer to OpenStack Swift\nAs from this review we have removed it from Swift since the decision1 was made that only the official OpenStack API would be supported in Swift. The development will be continued in fujita\u0026rsquo;s repository on github at this URL :\nhttps://github.com/fujita/swift3\nFeel free to grab the middle-ware or report issue from fujita\u0026rsquo;s repository.\n1 Globally for OpenStack not just for Swift.\n","permalink":"https://blog.chmouel.com/2012/05/24/s3-emulation-to-openstack-swift-has-moved/","summary":"\u003cp\u003eA little note about swift3 the S3 emulation layer to OpenStack Swift\u003c/p\u003e\n\u003cp\u003eAs from this \u003ca href=\"https://review.openstack.org/#/c/7628/\"\u003ereview\u003c/a\u003e we have removed it from Swift since the decision\u003ca href=\"https://review.openstack.org/#/c/7628/\"\u003e1\u003c/a\u003e was made that only the official OpenStack API would be supported in Swift. The development will be continued in fujita\u0026rsquo;s repository on github at this URL :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/fujita/swift3\"\u003ehttps://github.com/fujita/swift3\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eFeel free to grab the middle-ware or report issue from fujita\u0026rsquo;s repository.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://review.openstack.org/#/c/7628/\"\u003e1\u003c/a\u003e Globally for OpenStack not just for Swift.\u003c/p\u003e","title":"S3 emulation to OpenStack Swift has moved"},{"content":"During the development for OpenStack Essex a lot of work has been done to make Swift working well with the other OpenStack components, this is a list of the work that has been done.\nMIDDLEWARE To make Swift behaving well in the \u0026lsquo;stack\u0026rsquo; we had to get a rock solid keystone middleware and make sure most of the features provided by Swift would be supported by the middleware.\nThe middleware is currently located in the keystone essex repository and was entirely rewritten from the Diablo release to allow support these Swift features :\nACL via keystone roles : Anonymous access via ACL referrer. Container syncing : Different reseller prefix : Special reseller admin account : S3 emulation : One thing missing in the middleware is to allow auth overriding, basically it means that when an another middleware wants to take care of the authentication for some request the auth middleware will just let it go and allow the request to continue. Such feature is used for example in the temp_url middleware to allow temporary access/upload to an object. This is projected to be supported in the future.\nAn important thing to keep in mind when you configure your roles is to have a user in a tenant (or account like called in Swift world) acting as an operator. This is controlled by the setting :\nswift_operator_roles\nand by default have the roles swiftoperator and admin. A user needs to have this role to be able to do something in a tenant.\nGLANCE Glance has been updated as well to be able to store images in swift which have a auth server using the 2.0 identity auth.\nNOVA\nNova have the ability to access an objectstore to store images in a store which has been uploaded with the euca-upload-bundle command. Historically nova have shipped with a service called nova-objectstore but the service was buggy and had some security issues. Swift combined with keystone\u0026rsquo;s s3_token and swift3 middleware now can act as a more reliable and secure objectstore for Nova.\nDEVSTACK support Swift if you add the swift service to the ENABLED_SERVICE variable in your localrc. This is where you want to poke around to see how the configuration is made to have everything playing well together. The only bit that didn\u0026rsquo;t made for the devstack essex release is to have glance storing images directly in Swift.\nCLI / Client Library Swift CLI and client library (called swift.common.client) has been updated to support auth v2.0 the CLI support now the common OpenStack CLI arguments and environment to operate against auth server that has 2.0 identity auth.\nWe unfortunately were not in time to add the support for OS_AUTH_TENANT and use the Swift auth v1 syntax where if the user has the form of tenant:user OS_AUTH_TENANT will become tenant and OS_AUTH_USER the user.\nAside of a couple of bit missing we believe Swift should be rock solid to use with your other OpenStack components. There is no excuse to not use Swift as your central object storage component in OpenStack ;-).\n","permalink":"https://blog.chmouel.com/2012/04/25/swift-integration-with-other-openstack-components-in-essex/","summary":"\u003cp\u003eDuring the development for OpenStack Essex a lot of work has been done to make Swift working well with the other OpenStack components, this is a list of the work that has been done.\u003c/p\u003e\n\u003ch4 id=\"middleware\"\u003e\u003cstrong\u003eMIDDLEWARE\u003c/strong\u003e\u003c/h4\u003e\n\u003cp\u003eTo make Swift behaving well in the \u0026lsquo;stack\u0026rsquo; we had to get a rock solid keystone middleware and make sure most of the features provided by Swift would be supported by the middleware.\u003c/p\u003e\n\u003cp\u003eThe middleware is currently \u003c!-- raw HTML omitted --\u003elocated\u003c!-- raw HTML omitted --\u003e in the keystone essex repository and was entirely rewritten from the Diablo release to allow support these Swift features :\u003c/p\u003e","title":"Swift integration with other OpenStack components in Essex."},{"content":"I have been trying lately to get a better understanding of the Swift code base, and I found the best way to know it was to read it from top to bottom and document it along the way. Here is some of my notes, hopefully more will come.\nI am starting with an object PUT when the request is coming from the proxy server. The request in the log-file will look like this :\n\u0026ldquo;PUT /sdb1/2/AUTH_dcbeb7f1271d4374b951954a4f1be15f/foo/file.txt\u0026rdquo; 201 - \u0026ldquo;-\u0026rdquo; \u0026ldquo;txdw08eca2842e344bb8e11b5869c81cb52\u0026rdquo; \u0026ldquo;-\u0026rdquo; 0.0308\nThe WSGI controller send the request to the method swift.obj.server.ObjectController-\u0026gt;PUT and start to do the following :\nsplits the request.path to : Make sure that partition is mounted. (there is a mount_check option that can toggle this).\nEnsure that there is a X-Timestamp header which should be set by the proxy server.\nStart the check method check_object_creation which does the following :\nMake sure the content_length is not greater than the MAX_FILE_SIZE.\nMake sure there is a content_length header (except if the transfer has been chunked).\nMake sure that there is no content_length (ie: zero byte body) when doing a X-Copy-From.\nMake sure the object_name is not greater than MAX_OBJECT_NAME_LENGTH (1024 bytes by default).\nMaking sure we have a Content-Type in the headers passed (this could be set by the user or auto-guessed via mimetypes.guess_type on the proxy server).\nWhen we have an header of x-object-manifest (for large files support) it makes sure the value is a container/object style and not contain chars like ? \u0026amp; / in the referenced objects names.\nChecks metadata, make sure at first that the metadata name are not empty.\nThe metadata name length are not greater than MAX_META_NAME_LENGTH (default: 128).\nThe metadata value is not greater than MAX_META_VALUE_LENGTH (default: 256).\nWe don\u0026rsquo;t have a greater amount of metadatas than MAX_META_COUNT (default: 90).\nThe size of the headers combined (name+value) is not over MAX_META_OVERALL_SIZE (default: 4096).\nIf we have \u0026lsquo;X-Delete-At\u0026rsquo; (for the object expiration feature) we are making sure this is not happening in the past or we will exit with an HTTPBadRequest.\nThe class swift.obj.server.DiskFile will be the class that takes care to actually write the file locally. It gets instantiated and do the following in the constructor method:\nIt will hash the following value (account, container, obj) which will become hashed for our example into :\nIt will get the path where this is going to be store which going to be : /srv/node is the devices path which is the configuration directive [proxy]-\u0026gt;devices (default to /srv/node). sdb1 being the mounted device name. add the datadir type, \u0026lsquo;\u0026rsquo;objects\u0026rsquo;\u0026rsquo; for us. and the partition power (2) last three chars of the hashed name (fe1) the hash itself 46acec4563797178df9ec79b28146fe1 It will get the temporary directory which become in our case to: /srv/node/sdb1/tmp it is basically the devices dir, the device and /tmp If the directory didn\u0026rsquo;t exists before then it just return. If the directory was existing (already uploaded) then it will parse all files in there and would looks if we have : Files ending up with .ts which will be the tombstone (a deleted file). NB: Replication process will take care to os.unlink() the file properly later. In case of a POST and if we have fast post setting enabled (see config object_post_as_copy in proxy_server) we will detect it and only do a copy of metadata. It calculates the expiration time which is from now + the max_upload_time setting. It start the etag hashing to gradually calculate the md5 of the object. Using the method mkstemp of DiskFile it will start to write to tmpdir, which does the creation of the file like that : Make sure to create the tmpdir. make a secure temporary file (using mkstemp(3)) and yield the file descriptor back to PUT. If there is a content-length in the headers (assigned by the client) it will use the posix function fallocate(2) to pre-allocate that disk space to the file descriptor. It will then iterate over chunk of data size defined by the configuration variable network_chunk_size (default: 64m) reading that chunk from the request wsgi.input : It will update the upload_size value. It will make sure we are not going over our upload expiration time (or get back HTTPRequestTimeout HTTP Error). It will update the calculated md5 with that chunk. It will write the chunk using python os.write For large file sync which is over the configuration variable bytes_per_sync it will do a fdatasync(2) and drop the kernel buffer caches (s_o we are not filling up too much the kernel memory_). if we have a content-length in the client headers that doesn\u0026rsquo;t match the calculated upload_size we return a 499 Client Disconnected as it means we had a problem somewhere during the upload. It will bail out if we have a etag in the client headers that doesn\u0026rsquo;t match the calculated etag. And now we are starting defining our metadatas that we are going to store with the file :\nmetadata = {\n_ \u0026lsquo;X-Timestamp\u0026rsquo;:_ timestamp generated from the proxy_server_._\n_ \u0026lsquo;Content-Type\u0026rsquo;: d_efined by the user or \u0026lsquo;guessed\u0026rsquo; by the proxy server\n_ \u0026lsquo;ETag\u0026rsquo;:_ calculated value from the request.\n_ \u0026lsquo;Content-Length\u0026rsquo;:_ an fstat(2) on the file to get the proper value of what is stored on the disk.\n}\nIt will add to the metadata every headers starting by \u0026lsquo;x-object-meta-\u0026rsquo;. It will add to the metadata the allowed headers to be stored which is defined in the config variable allowed_headers (default: allowed_headers = Content-Disposition, Content-Encoding, X-Delete-At, X-Object-Manifest). It will write the file using the put method of the DiskFile class, which finalise the writing on the file on disk and renames it from the temp file to the real location: It will write the metadata using the xattr(1) feature which is stored directly with the file. If there is a Content-Length with the metada it will drop the kernel cache of that metadata length. It will invalidate the hashes of the datadir directory using the function swift.obj.replicator.invalidate_hashes It will set the hash of the dir as None, which would hint the replication process to have something to do with that dir (and that hash will be generated). This file is stored by partition as python pickle which is in our case: /srv/node/sdb1/objects/2/hashes.pkl Move the file from the tmp dir to go to the datadir. It will use the method unlinkold from DiskFile to remove any older versions of the object file which is any files that has older timestamp. It will start construct the request to make to a containers by going passing the following: account, container, obj as request path. the original headers. the headers Content-Length, Content-Type, X-Timestamp, Etag, X-trans-ID. It will get the headers X-Container-{Host,Partition,Device} from the original headers which is defined by the proxy to know on which container server it going to update. Every different PUT will have assigned a different container to each their own. It will use the async_update method (by self since it\u0026rsquo;s part of the same class) to make an asynchronous request: Passing the aforementioned build headers and req.path. If the request success (between 200 to 300) it will return to the main (PUT) method. the request didn\u0026rsquo;t succeed it will create a async_pending file locally in the tmp dir which is going to be picked-up by the replication process to update the container listing when the container is not too busy. When finish it will respond by a HTTPCreated ","permalink":"https://blog.chmouel.com/2012/02/06/anatomy-of-a-swift-put-query-to-object-server/","summary":"\u003cp\u003eI have been trying lately to get a better understanding of the Swift code base, and I found the best way to know it was to read it from top to bottom and document it along the way. Here is some of my notes, hopefully more will come.\u003c/p\u003e\n\u003cp\u003eI am starting with an object \u003cstrong\u003ePUT\u003c/strong\u003e when the request is coming from the proxy server. The request in the log-file will look like this :\u003c/p\u003e","title":"How does a PUT to a swift object server look like."},{"content":"Swift integrity tools.\nThere is quite a bit of tools shipped with Swift to ensure you have the right object on your cluster.\nAt first there is the basic :\nswift-object-info\nIt will take a swift object stored on the filesystem and print some infos about it, like this :\nswift@storage01:0/016/0b221bab535ac1b8f0d91e394f225016$ swift-object-info 1327991417.01411.data\nPath: /AUTH_root/foobar/file.txt\nAccount: AUTH_root\nContainer: foobar\nObject: file.txt\nObject hash: 0b221bab535ac1b8f0d91e394f225016\nRing locations:\n192.168.254.12:6000 - /srv/node/sdb1/objects/0/016/0b221bab535ac1b8f0d91e394f225016/1327991417.01411.data\nContent-Type: text/plain\nTimestamp: 2012-01-31 06:30:17.014110 (1327991417.01411)\nETag: 053a0f8516a5023b9af76c49ca917d3e (valid)\nContent-Length: 24 (valid)\nUser Metadata: {\u0026lsquo;X-Object-Meta-Mtime\u0026rsquo;: \u0026lsquo;1327968327.21\u0026rsquo;}\nPS: If you don\u0026rsquo;t know where is your object on which node, you can you use swift-get-nodes\nFor auditing, the Etag value is important because swift-object-info will compare the object recorded etag in the metadata with what we have on the disks. Let\u0026rsquo;s try to see if that works :\nswift@storage01:0/016/0b221bab535ac1b8f0d91e394f225016$ cp 1327991417.01411.data /tmp\nswift@storage01:0/016/0b221bab535ac1b8f0d91e394f225016$ echo \u0026ldquo;foo\u0026rdquo; \u0026raquo; 1327991417.01411.data\nswift@storage01:0/016/0b221bab535ac1b8f0d91e394f225016$ swift-object-info 1327991417.01411.data|grep \u0026lsquo;^Etag\u0026rsquo;\nEtag: 053a0f8516a5023b9af76c49ca917d3e doesn\u0026rsquo;t match file hash of 9ff871e5ce5dcb5d3f2680a80a88ff38!\nswift-object-info has detected that this file is not the one we have uploaded.\nThere is an other tool called swift-drive-audit which as explained in the admin guide will parse the /var/log/kern.log and have predefined regexp to detect disk failure notified by the kernel. It is usually run periodically by cron and there is a config file for it called /etc/swift/drive-audit.conf. If the script find any errors for a certain drive it will unmount it and comment it in /etc/fstab(5). Afterwards the replication process will pick it up from other replicas and put the object on that drive in handover.\nSwift provide as well different type of auditor daemons for account/container/object :\nswift-account-auditor swift-container-auditor swift-object-auditor swift-account-auditor will open all sqlite db of an account server and launch a SQL query to make sure all the dbs are valid.\nswift-container-auditor will do the same but for containers.\nswift-object-auditor will open all object of an object server and make sure of :\nMetadata are correct. We have the proper size. We have the proper MD5. Those auditors needs to be set in each type-server.conf, for example for account server you will add something like this to /etc/swift/account-server.conf :\n[account-auditor]\n# You can override the default log routing for this app here (don\u0026rsquo;t use set!):\n# log_name = account-auditor\n# log_facility = LOG_LOCAL0\n# log_level = INFO\n# Will audit, at most, 1 account per device per interval\ninterval = 1800\n# log_facility = LOG_LOCAL0\n# log_level = INFO\nFor container this is about the same options but for object-server does are the options :\n[object-auditor]\n# You can override the default log routing for this app here (don\u0026rsquo;t use set!):\n# log_name = object-auditor\n# log_facility = LOG_LOCAL0\n# log_level = INFO\n# files_per_second = 20\n# bytes_per_second = 10000000\n# log_time = 3600\n# zero_byte_files_per_second = 50\nAnother tool shipped with swift is swift-account-audit which will audit a full account and report if there is missing replicas or incorrect object in that account.\n","permalink":"https://blog.chmouel.com/2012/02/01/audit-a-swift-cluster/","summary":"\u003cp\u003eSwift integrity tools.\u003c/p\u003e\n\u003cp\u003eThere is quite a bit of tools shipped with Swift to ensure you have the right object on your cluster.\u003c/p\u003e\n\u003cp\u003eAt first there is the basic :\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eswift-object-info\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eIt will take a swift object stored on the filesystem and print some infos about it, like this :\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eswift@storage01:0/016/0b221bab535ac1b8f0d91e394f225016$ swift-object-info 1327991417.01411.data\u003cbr\u003e\nPath: /AUTH_root/foobar/file.txt\u003cbr\u003e\nAccount: AUTH_root\u003cbr\u003e\nContainer: foobar\u003cbr\u003e\nObject: file.txt\u003cbr\u003e\nObject hash: 0b221bab535ac1b8f0d91e394f225016\u003cbr\u003e\nRing locations:\u003cbr\u003e\n192.168.254.12:6000 - /srv/node/sdb1/objects/0/016/0b221bab535ac1b8f0d91e394f225016/1327991417.01411.data\u003cbr\u003e\nContent-Type: text/plain\u003cbr\u003e\nTimestamp: 2012-01-31 06:30:17.014110 (1327991417.01411)\u003cbr\u003e\nETag: 053a0f8516a5023b9af76c49ca917d3e (valid)\u003cbr\u003e\nContent-Length: 24 (valid)\u003cbr\u003e\nUser Metadata: {\u0026lsquo;X-Object-Meta-Mtime\u0026rsquo;: \u0026lsquo;1327968327.21\u0026rsquo;}\u003c/p\u003e","title":"Audit a swift cluster"},{"content":"Running 1,266 km (786 miles):\nCycling 3865 km (2401 miles):\nLet\u0026rsquo;s see if I can improve for next year\n","permalink":"https://blog.chmouel.com/2011/12/28/my-training-year-cycling-and-running/","summary":"\u003cp\u003eRunning 1,266 km  (786 miles):\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"/wp-content/uploads/2011/12/Screen-Shot-2011-12-28-at-19.44.05.png\"\u003e\u003c!-- raw HTML omitted --\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eCycling 3865 km (2401 miles):\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"/wp-content/uploads/2011/12/Screen-Shot-2011-12-28-at-19.44.20.png\"\u003e\u003c!-- raw HTML omitted --\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eLet\u0026rsquo;s see if I can improve for next year\u003c/p\u003e","title":"My stats for this year running and cycling"},{"content":"[NB: Much things has changed since I have written this article but keeping it here for info]\nIt seems that integrating Swift and Keystone together present some challenges to people and this is absolutely normal as there is a lot of changes going on. This is my attempt to document how everything is plugged together.\nI am not going to explain how a middleware is supposed to work as this is nicely documented on Wikipedia :\nhttp://en.wikipedia.org/wiki/Middleware\nor how the auth middlewares works on Swift :\nhttp://swift.openstack.org/development_auth.html or even how this is plugged inside Keystone :\nhttp://keystone.openstack.org/middleware_architecture.html At first let\u0026rsquo;s get some of the wordings right :\nA tenant in keystone is an account in swift. A user in keystone is also a user in swift. A role in keystone is a group in swift. Now that you keep this in mind let\u0026rsquo;s walk-though how a request will\nlook like.\nAt first your user connect to keystone and says this is my username for this\ntenant and here is the secret/api key, give me the endpoints for the\nservices and add a token to it. This will look like this in curl :\ncurl -s -d \u0026#39;{\u0026#34;auth\u0026#34;: {\u0026#34;tenantName\u0026#34;: \u0026#34;demo\u0026#34;, \u0026#34;passwordCredentials\u0026#34;: {\u0026#34;username\u0026#34;: \u0026#34;demo\u0026#34;, \u0026#34;password\u0026#34;: \u0026#34;password\u0026#34;}}}\u0026#39; -H \u0026#39;Content-type: application/json\u0026#39; http://localhost:5000/v2.0/tokens If successfully authenticated you get back in Json those public/internal urls\nfor swift so you are able to connect, here is some part of the replied request :\n{ \u0026#34;endpoints\u0026#34;: [ { \u0026#34;adminURL\u0026#34;: \u0026#34;http://localhost:8080/\u0026#34;, \u0026#34;internalURL\u0026#34;: \u0026#34;http://localhost:8080/v1/AUTH_2\u0026#34;, \u0026#34;publicURL\u0026#34;: \u0026#34;http://localhost:8080/v1/AUTH_2\u0026#34;, \u0026#34;region\u0026#34;: \u0026#34;RegionOne\u0026#34; } ], \u0026#34;name\u0026#34;: \u0026#34;swift\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;object-store\u0026#34; } [...] \u0026#34;token\u0026#34;: { \u0026#34;expires\u0026#34;: \u0026#34;2011-11-24T12:35:56\u0026#34;, \u0026#34;id\u0026#34;: \u0026#34;ea29dae7-4c54-4e80-98e1-9f886acb389a\u0026#34;, \u0026#34;tenant\u0026#34;: { \u0026#34;id\u0026#34;: \u0026#34;2\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;demo\u0026#34; } }, So now the clients is going to get the publicURL (or can be internal) with the token and able to give request to swift with it. Let\u0026rsquo;s take the simple request which list the container, this is a basic GET on the account :\ncurl -v -H \u0026#39;X-Auth-Token: ea29dae7-4c54-4e80-98e1-9f886acb389a\u0026#39; http://localhost:8080/v1/AUTH_2 which should come back by a 20* http code if that work.\nWhat\u0026rsquo;s happening here is that when you connect to swift it will pass it to the middleware to make sure we are able to have access with that token.\nThe middleware will take that token connect to keystone admin url with the admin token and pass that user token to be validated. The query looks like this in curl :\ncurl -H \u0026#39;X-Auth-Token: 7XX\u0026#39; http://localhost:35357/v2.0/tokens/ea29dae7-4c54-4e80-98e1-9f886acb389a note: localhost:35357 is the keystone admin url and 7XX is the admin token set in the configuration of the middleware.\nif successful keystone will come back with a reply that look like this :\n{ \u0026#34;access\u0026#34;: { \u0026#34;token\u0026#34;: { \u0026#34;expires\u0026#34;: \u0026#34;2011-11-24T12:35:56\u0026#34;, \u0026#34;id\u0026#34;: \u0026#34;ea29dae7-4c54-4e80-98e1-9f886acb389a\u0026#34;, \u0026#34;tenant\u0026#34;: { \u0026#34;id\u0026#34;: \u0026#34;2\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;demo\u0026#34; } }, \u0026#34;user\u0026#34;: { \u0026#34;id\u0026#34;: \u0026#34;2\u0026#34;, \u0026#34;roles\u0026#34;: [ { \u0026#34;id\u0026#34;: \u0026#34;2\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;Member\u0026#34;, \u0026#34;tenantId\u0026#34;: \u0026#34;2\u0026#34; }, { \u0026#34;id\u0026#34;: \u0026#34;5\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;SwiftOperator\u0026#34;, \u0026#34;tenantId\u0026#34;: \u0026#34;2\u0026#34; }, ], \u0026#34;username\u0026#34;: \u0026#34;demo\u0026#34; } } } Let\u0026rsquo;s step back before more Curl command and understand a thing about Swift, a user of an account in Swift by default don\u0026rsquo;t have any rights at all but there is one user in that account whose able to give ACL on containers for other users. In swift keystone middleware we call it an Operator.\nThe way the middleware knows which user is able to be admin on an account is by using the roles matching to whatever configuration we have on the middleware setting called :\nkeystone_swift_operator_roles = Admin, SwiftOperator since this user is part the SwiftOperator then it has access and he\u0026rsquo;s allowed to do whatever he wants for that account like creating containers or giving ACL to other users.\nSo let\u0026rsquo;s say we have a user called demo2 which is part of the demo account and have only the role Member to it and not SwiftOperator by default as we say before he will not be able to do much.\nBut if demo user give access to the group/role Memeber to a container via acl then demo2 will be able to do stuff on it.\nWe can all have fun with bunch of curl commands but since swift 1.4.7 the swift CLI tool have support for the auth server version 2.0 and allow you to connect to keystone for auth so we are going to use that instead.\nLet first create a testcontainer and upload a file into it with our \u0026lsquo;operator\u0026rsquo; user :\nswift --auth-version 2 -A http://localhost:5000/v2.0 -U demo:demo -K password post testcontainer now let\u0026rsquo;s give access to the Member group for that container on reading :\nswift --auth-version 2 -A http://localhost:5000/v2.0 -U demo:demo -K password post testcontainer -r Member and now if we try to read that file directly with demo2 it will be allowed :\nswift --auth-version 2 -A http://localhost:5000/v2.0 -U demo:demo2 -K password download testcontainer etc/issue -o- Hope this make things a bit more clears how everything works, in the next part I am going to explain how the config files and packages will look like for installing keystone and swift.\n","permalink":"https://blog.chmouel.com/2011/11/24/swift-and-keystone-middleware-part1/","summary":"\u003cp\u003e\u003c!-- raw HTML omitted --\u003e[NB: Much things has changed since I have written this article but keeping it here for info]\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003cp\u003eIt seems that integrating \u003c!-- raw HTML omitted --\u003eSwift\u003c!-- raw HTML omitted --\u003e and \u003c!-- raw HTML omitted --\u003eKeystone\u003c!-- raw HTML omitted --\u003e together present some challenges to people and this is absolutely normal as there is a lot of changes going on. This is my attempt to document how everything is plugged together.\u003c/p\u003e","title":"Swift and Keystone middleware"},{"content":"I have done lately quite a bit of work with python-novaclient the (nova/keystone) openstack client. I often experiment it with ipython in the console.\nThere is a nice debugging facility in novaclient which you can see while using \u0026ndash;debug argument on the command line and if you wanted to use it with ipython you could have that at the beginning of your session :\nThis would give you the details of the session showing you the REST requests and responses including the headers. It even show you the curl commands that you can use on the command line to experiment with it.\n","permalink":"https://blog.chmouel.com/2011/09/02/debugging-python-novaclient-on-the-command-line/","summary":"\u003cp\u003eI have done lately quite a bit of work with \u003c!-- raw HTML omitted --\u003epython-novaclient\u003c!-- raw HTML omitted --\u003e the (nova/keystone) openstack client. I often experiment it with \u003c!-- raw HTML omitted --\u003eipython\u003c!-- raw HTML omitted --\u003e in the console.\u003c/p\u003e\n\u003cp\u003eThere is a nice debugging facility in novaclient which you can see while using \u0026ndash;debug argument on the command line and if you wanted to use it with ipython you could have that at the beginning of your session :\u003c/p\u003e","title":"Debugging python-novaclient on the command line."},{"content":"I have released a python binding to Rackspace CloudDNS here which allow you to create/update/delete domains and records. It\u0026rsquo;s available on github\nhttps://github.com/rackspace/python-clouddns/\nThe binding is pretty simple and have unfortunately no documentation (or even tests) but you can figure out most of it from here :\nhttps://github.com/rackspace/python-clouddns/blob/master/tests/t.py\nI will be very welcoming pull request that add a bit of documentation.\n","permalink":"https://blog.chmouel.com/2011/07/17/rackspace-clouddns-python-binding/","summary":"\u003cp\u003eI have released a python binding to \u003c!-- raw HTML omitted --\u003eRackspace CloudDNS\u003c!-- raw HTML omitted --\u003e here which allow you to create/update/delete domains and records. It\u0026rsquo;s available on github\u003c/p\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003ca href=\"https://github.com/rackspace/python-clouddns/\"\u003ehttps://github.com/rackspace/python-clouddns/\u003c/a\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003cp\u003eThe binding is pretty simple and have unfortunately no documentation (or even tests) but you can figure out most of it from here :\u003c/p\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003ca href=\"https://github.com/rackspace/python-clouddns/blob/master/tests/t.py\"\u003ehttps://github.com/rackspace/python-clouddns/blob/master/tests/t.py\u003c/a\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e","title":"Rackspace CloudDNS python binding"},{"content":"A lot of our customers in Rackspace cloud has been asking how to mass edit firewalls of servers when you have multiple servers without doing it manually.\nPart of my cloudservers-api-demo I have written a simple firewall scripts abstracting the Operating System firewall software to allow/enable/disable the firewall and ports/networks.\nThe script has been kept very simple by design and currently allow only to :\n\u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt; enable the firewall \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt; \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt; disable the firewall \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt; \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt; allow or disallow a port or a network \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt; \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt; see firewall status \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;/ul\u0026gt; \u0026lt;h3\u0026gt; PREREQUISITES \u0026lt;/h3\u0026gt; \u0026lt;ul\u0026gt; \u0026lt;li\u0026gt; \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt; A management server under Ubuntu maverick. \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt; \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt; A supported Operating System for clients which includes : \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt; \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt; Debian. \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt; \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt; Ubuntu. \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt; \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt; RHEL. \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt; \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt; Fedora \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt; \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt; My patched python-cloudservers library (see below for installs). \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt; \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt; Your SSH key installed on all VM for root users. \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;/ul\u0026gt; \u0026lt;h3\u0026gt; Install \u0026lt;/h3\u0026gt; \u0026lt;ul\u0026gt; \u0026lt;li\u0026gt; \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt; After you have kicked a VM with a Ubuntu maverick and connected to it as root you want first execute intall some prereq packages : \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;/ul\u0026gt; apt-get update \u0026amp;\u0026amp; apt-get -y install python-stdeb git \u0026lt;p\u0026gt; checkout my python-cloudservers library : \u0026lt;/p\u0026gt; git clone git://github.com/chmouel/python-cloudservers.git \u0026lt;p\u0026gt; after being checked-out you will go into the python-cloudservers directory which has just been created and do this : \u0026lt;/p\u0026gt; cd python-cloudservers/ python setup.py install \u0026lt;p\u0026gt; this should automatically install all the dependences. \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; Now you can install my api-demo which include the firewall script : \u0026lt;/p\u0026gt; cd ../ git clone git://github.com/chmouel/cloudservers-api-demo \u0026lt;p\u0026gt; You need to configure some environemnt variable first which keep information about your rackspace account. \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; edit your ~/.bashrc (or /etc/environement if you want to make it global) and configure those variable : \u0026lt;/p\u0026gt; export RCLOUD_DATACENTER=UK export UK_RCLOUD_USER=\u0026#34;MY_USERNAME\u0026#34; export UK_RCLOUD_KEY=\u0026#34;MY_API_KEY\u0026#34; export UK_RCLOUD_AURL=\u0026#34;https://lon.auth.api.rackspacecloud.com/v1.0\u0026#34; \u0026lt;p\u0026gt; or for the US you would have : \u0026lt;/p\u0026gt; export RCLOUD_DATACENTER=US export UK_RCLOUD_USER=\u0026#34;MY_USERNAME\u0026#34; export UK_RCLOUD_KEY=\u0026#34;MY_API_KEY\u0026#34; export UK_RCLOUD_AURL=\u0026#34;https://auth.api.rackspacecloud.com/v1.0\u0026#34; \u0026lt;p\u0026gt; source the ~/.bashrc or relog into your account to have those accounts set-up you can test it to see if that works by going to : \u0026lt;/p\u0026gt; ~/cloudservers-api-demo/python \u0026lt;p\u0026gt; and launch the command : \u0026lt;/p\u0026gt; ./list-servers.py \u0026lt;p\u0026gt; to test if this is working properly (it should list your servers for your DATACENTER) \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; you are now basically ready to mass update firewall on all servers. \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; Let's say you have two web servers named web1 and web2 and two db servers named db1 and db2 and you would like to allow the 80 port on the web servers and 3306 port on the db servers. \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; You would have to go to this directory : \u0026lt;/p\u0026gt; ~/cloudservers-api-demo/firewall/ \u0026lt;p\u0026gt; and first execute this command to see the help/usages : \u0026lt;/p\u0026gt; ./fw-control.py --help \u0026lt;p\u0026gt; so let's say to enable the firewall on all the web and db server first you can do : \u0026lt;/p\u0026gt; ./fw-control.py -s \u0026#34;web db\u0026#34; enable \u0026lt;p\u0026gt; it will connect and enable the firewall on all the servers which match the name web and db. \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; now let's say we want to enable port 80 on the web : \u0026lt;/p\u0026gt; ./fw-control.py -s \u0026#34;web\u0026#34; allow port 80 \u0026lt;p\u0026gt; if you log into the servers you can check with \u0026lt;/p\u0026gt; iptables -L -n \u0026lt;p\u0026gt; that it it has been enabled properly. \u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; This is simple enough for you to modify the script to your liking to make it more modular for your specific environement. \u0026lt;/p\u0026gt; ","permalink":"https://blog.chmouel.com/2011/05/05/mass-editing-firewall-on-rackspace-cloud/","summary":"\u003cp\u003eA lot of our customers in Rackspace cloud has been asking how to mass edit firewalls of servers when you have multiple servers without doing it manually.\u003c/p\u003e\n\u003cp\u003ePart of my \u003ca href=\"https://github.com/chmouel/cloudservers-api-demo\"\u003ecloudservers-api-dem\u003c/a\u003eo I have written a simple firewall scripts abstracting the Operating System firewall software to allow/enable/disable the firewall and ports/networks.\u003c/p\u003e\n\u003cp\u003eThe script has been kept very simple by design and currently allow only to :\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003cpre\u003e\u003ccode\u003e\u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt;\n  enable the firewall\n\u0026lt;/p\u0026gt;\n\n\u0026lt;p\u0026gt;\n  \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \n  \n  \u0026lt;li\u0026gt;\n    \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \n    \n    \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt;\n      disable the firewall\n    \u0026lt;/p\u0026gt;\n    \n    \u0026lt;p\u0026gt;\n      \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \n      \n      \u0026lt;li\u0026gt;\n        \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \n        \n        \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt;\n          allow or disallow a port or a network\n        \u0026lt;/p\u0026gt;\n        \n        \u0026lt;p\u0026gt;\n          \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \n          \n          \u0026lt;li\u0026gt;\n            \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \n            \n            \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt;\n              see firewall status\n            \u0026lt;/p\u0026gt;\n            \n            \u0026lt;p\u0026gt;\n              \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;/ul\u0026gt; \n              \n              \u0026lt;h3\u0026gt;\n                PREREQUISITES\n              \u0026lt;/h3\u0026gt;\n              \n              \u0026lt;ul\u0026gt;\n                \u0026lt;li\u0026gt;\n                  \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \n                  \n                  \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt;\n                    A management server under Ubuntu maverick.\n                  \u0026lt;/p\u0026gt;\n                  \n                  \u0026lt;p\u0026gt;\n                    \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \n                    \n                    \u0026lt;li\u0026gt;\n                      \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \n                      \n                      \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt;\n                        A supported Operating System for clients which includes :\n                      \u0026lt;/p\u0026gt;\n                      \n                      \u0026lt;p\u0026gt;\n                        \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \n                        \n                        \u0026lt;li\u0026gt;\n                          \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \n                          \n                          \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt;\n                            Debian.\n                          \u0026lt;/p\u0026gt;\n                          \n                          \u0026lt;p\u0026gt;\n                            \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \n                            \n                            \u0026lt;li\u0026gt;\n                              \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \n                              \n                              \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt;\n                                Ubuntu.\n                              \u0026lt;/p\u0026gt;\n                              \n                              \u0026lt;p\u0026gt;\n                                \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \n                                \n                                \u0026lt;li\u0026gt;\n                                  \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \n                                  \n                                  \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt;\n                                    RHEL.\n                                  \u0026lt;/p\u0026gt;\n                                  \n                                  \u0026lt;p\u0026gt;\n                                    \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \n                                    \n                                    \u0026lt;li\u0026gt;\n                                      \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \n                                      \n                                      \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt;\n                                        Fedora\n                                      \u0026lt;/p\u0026gt;\n                                      \n                                      \u0026lt;p\u0026gt;\n                                        \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \n                                        \n                                        \u0026lt;li\u0026gt;\n                                          \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \n                                          \n                                          \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt;\n                                            My patched python-cloudservers library (see below for installs).\n                                          \u0026lt;/p\u0026gt;\n                                          \n                                          \u0026lt;p\u0026gt;\n                                            \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \n                                            \n                                            \u0026lt;li\u0026gt;\n                                              \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \n                                              \n                                              \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt;\n                                                Your SSH key installed on all VM for root users.\n                                              \u0026lt;/p\u0026gt;\n                                              \n                                              \u0026lt;p\u0026gt;\n                                                \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;/ul\u0026gt; \n                                                \n                                                \u0026lt;h3\u0026gt;\n                                                  Install\n                                                \u0026lt;/h3\u0026gt;\n                                                \n                                                \u0026lt;ul\u0026gt;\n                                                  \u0026lt;li\u0026gt;\n                                                    \u0026lt;span style=\u0026quot;font-size: medium;\u0026quot;\u0026gt; \n                                                    \n                                                    \u0026lt;p style=\u0026quot;display: inline !important;\u0026quot;\u0026gt;\n                                                      After you have kicked a VM with a Ubuntu maverick and connected to it as root you want first execute intall some prereq packages :\n                                                    \u0026lt;/p\u0026gt;\n                                                    \n                                                    \u0026lt;p\u0026gt;\n                                                      \u0026lt;/span\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;/ul\u0026gt; \n\u003c/code\u003e\u003c/pre\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt-get update \u003cspan style=\"color:#ff79c6\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e apt-get -y install python-stdeb git\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cpre\u003e\u003ccode\u003e                                                      \u0026lt;p\u0026gt;\n                                                        checkout my python-cloudservers library :\n                                                      \u0026lt;/p\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone git://github.com/chmouel/python-cloudservers.git\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cpre\u003e\u003ccode\u003e                                                      \u0026lt;p\u0026gt;\n                                                        after being checked-out you will go into the python-cloudservers directory which has just been created and do this :\n                                                      \u0026lt;/p\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ecd\u003c/span\u003e python-cloudservers/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython setup.py install\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cpre\u003e\u003ccode\u003e                                                      \u0026lt;p\u0026gt;\n                                                        this should automatically install all the dependences.\n                                                      \u0026lt;/p\u0026gt;\n                                                      \n                                                      \u0026lt;p\u0026gt;\n                                                        Now you can install my api-demo which include the firewall script :\n                                                      \u0026lt;/p\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ecd\u003c/span\u003e ../\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone git://github.com/chmouel/cloudservers-api-demo\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cpre\u003e\u003ccode\u003e                                                      \u0026lt;p\u0026gt;\n                                                        You need to configure some environemnt variable first which keep information about your rackspace account.\n                                                      \u0026lt;/p\u0026gt;\n                                                      \n                                                      \u0026lt;p\u0026gt;\n                                                        edit your ~/.bashrc (or /etc/environement if you want to make it global) and configure those variable :\n                                                      \u0026lt;/p\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eexport\u003c/span\u003e RCLOUD_DATACENTER\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003eUK\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eexport\u003c/span\u003e UK_RCLOUD_USER\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;MY_USERNAME\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eexport\u003c/span\u003e UK_RCLOUD_KEY\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;MY_API_KEY\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eexport\u003c/span\u003e UK_RCLOUD_AURL\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;https://lon.auth.api.rackspacecloud.com/v1.0\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cpre\u003e\u003ccode\u003e                                                      \u0026lt;p\u0026gt;\n                                                        or for the US you would have :\n                                                      \u0026lt;/p\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eexport\u003c/span\u003e RCLOUD_DATACENTER\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003eUS\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eexport\u003c/span\u003e UK_RCLOUD_USER\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;MY_USERNAME\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eexport\u003c/span\u003e UK_RCLOUD_KEY\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;MY_API_KEY\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eexport\u003c/span\u003e UK_RCLOUD_AURL\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;https://auth.api.rackspacecloud.com/v1.0\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cpre\u003e\u003ccode\u003e                                                      \u0026lt;p\u0026gt;\n                                                        source the ~/.bashrc or relog into your account to have those accounts set-up you can test it to see if that works by going to :\n                                                      \u0026lt;/p\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/cloudservers-api-demo/python\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cpre\u003e\u003ccode\u003e                                                      \u0026lt;p\u0026gt;\n                                                        and launch the command :\n                                                      \u0026lt;/p\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e./list-servers.py\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cpre\u003e\u003ccode\u003e                                                      \u0026lt;p\u0026gt;\n                                                        to test if this is working properly (it should list your servers for your DATACENTER)\n                                                      \u0026lt;/p\u0026gt;\n                                                      \n                                                      \u0026lt;p\u0026gt;\n                                                        you are now basically ready to mass update firewall on all servers.\n                                                      \u0026lt;/p\u0026gt;\n                                                      \n                                                      \u0026lt;p\u0026gt;\n                                                        Let's say you have two web servers named web1 and web2 and two db servers named db1 and db2 and you would like to allow the 80 port on the web servers and 3306 port on the db servers.\n                                                      \u0026lt;/p\u0026gt;\n                                                      \n                                                      \u0026lt;p\u0026gt;\n                                                        You would have to go to this directory :\n                                                      \u0026lt;/p\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/cloudservers-api-demo/firewall/\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cpre\u003e\u003ccode\u003e                                                      \u0026lt;p\u0026gt;\n                                                        and first execute this command to see the help/usages :\n                                                      \u0026lt;/p\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e./fw-control.py --help\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cpre\u003e\u003ccode\u003e                                                      \u0026lt;p\u0026gt;\n                                                        so let's say to enable the firewall on all the web and db server first you can do :\n                                                      \u0026lt;/p\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e./fw-control.py -s \u0026#34;web db\u0026#34; enable\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cpre\u003e\u003ccode\u003e                                                      \u0026lt;p\u0026gt;\n                                                        it will connect and enable the firewall on all the servers which match the name web and db.\n                                                      \u0026lt;/p\u0026gt;\n                                                      \n                                                      \u0026lt;p\u0026gt;\n                                                        now let's say we want to enable port 80 on the web :\n                                                      \u0026lt;/p\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e./fw-control.py -s \u0026#34;web\u0026#34; allow port 80\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cpre\u003e\u003ccode\u003e                                                      \u0026lt;p\u0026gt;\n                                                        if you log into the servers you can check with\n                                                      \u0026lt;/p\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eiptables -L -n\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cpre\u003e\u003ccode\u003e                                                      \u0026lt;p\u0026gt;\n                                                        that it it has been enabled properly.\n                                                      \u0026lt;/p\u0026gt;\n                                                      \n                                                      \u0026lt;p\u0026gt;\n                                                        This is simple enough for you to modify the script to your liking to make it more modular for your specific environement.\n                                                      \u0026lt;/p\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e","title":"Mass editing firewall on Rackspace Cloud."},{"content":"Currently in Rackspace-Cloud when you are shutting-down your Cloud Servers you are still paying for it.\nThe reason is that when the Cloud Server is shut-down your CloudServer is still sitting on the hyper-visor and still use resources on the Cloud and then get you billed for it.\nThere is a way to get around it by having the CloudServer stored as an image into CloudFiles.\nThe caveat with this solution is that every-time you are creating a server out of the stored image you are getting a new IP and in certain cases you would need to make a change in your application with the new IP.\nIf you only use domain names instead of IP in your application you are not dependent of the IP change, to update the domain with the new IP after creating the VM you can either :\nHave a dynamic DNS or \u0026lsquo;Cloud DNS\u0026rsquo; updated just after you created your server out of the image.\nHave a script going into your server and update the IP directly in /etc/hosts.\nIn programming words this is the steps you would do. I am using the python-nova binding which allow you to connect to RackSpace Cloud.\nAt first I am going to create an object which we are going to authenticate\nimport novaclient cx = novaclient.OpenStack(USERNAME, API_KEY) or for the UK :\nimport novaclient cx = novaclient.OpenStack(\u0026#34;USERNAME\u0026#34;, \u0026#34;API_KEY\u0026#34;, \u0026#39;https://lon.auth.api.rackspacecloud.com/v1.0\u0026#39;) cx is going to be the object from where we can do things on it. Let\u0026rsquo;s first find the server server that we want, assuming your server is called test you would get the server like this :\nserver = cx.servers.find(name=\u0026#39;test\u0026#39;) The variable \u0026lsquo;server\u0026rsquo; contain our server \u0026lsquo;object\u0026rsquo; and we can get its ID out of it :\nserver_id = server.id We got the function cx.images.create to create an image from a server which accept as first argument the image name and the second the server id we just got. this would start the creation of the image :\ncx.images.create(\u0026#34;backup_server\u0026#34;, server_id) The server has started to get backed-up into your Cloud Files account, you can see it directly into the \u0026ldquo;My Server Images\u0026rdquo; tab of Hosting =\u0026gt; Cloud Servers section :\nYou can now delete the server since it\u0026rsquo;s \u0026lsquo;backuped\u0026rsquo; into cloud files ;\nserver.delete() At this time you are not billed for your Cloud Servers anymore and only for the storage usage in Cloud Files.\nWhen you want to restore the image as a server, you would first get the id of your image :\nimage = cx.images.find(name=\u0026#39;backup-test\u0026#39;) image_id = image.id and create the server out of this image :\nCNX.servers.create(image=image_id, flavor=1, name=\u0026#34;test\u0026#34;, ) The flavor argument is the type of image you want, 1 the minimal 256M flavor. The full list is :\nIn [14]: for x in cx.flavors.list(): ....: print x.id, \u0026#39;-\u0026#39;, x.name ....: ....: 1 - 256 server 2 - 512 server 3 - 1GB server 4 - 2GB server 5 - 4GB server 6 - 8GB server 7 - 15.5GB server When the server has created it should be exactly the same as what you have before created in image. You can now run a script using SSH with SSH keys to log into servers and do adjustment with the new IP.\n","permalink":"https://blog.chmouel.com/2011/04/07/howto-shutdown-your-cloud-server-and-not-getting-billed-for-it/","summary":"\u003cp\u003eCurrently in Rackspace-Cloud when you are shutting-down your Cloud Servers you are still paying for it.\u003c/p\u003e\n\u003cp\u003eThe reason is that when the Cloud Server is shut-down your CloudServer is still sitting on the hyper-visor and still use resources on the Cloud and then get you billed for it.\u003c/p\u003e\n\u003cp\u003eThere is a way to get around it by having the CloudServer stored as an image into CloudFiles.\u003c/p\u003e\n\u003cp\u003eThe caveat with this solution is that every-time you are creating a server out of the stored image you are getting a new IP and in certain cases you would need to make a change in your application with the new IP.\u003c/p\u003e","title":"Howto shutdown your Cloud Server and not getting billed for it."},{"content":"Sometime ago I wrote a FTP proxy to RackSpace Cloud Files which expose Rackspace Cloud Files as a FTP server acting as a proxy.\nThanks to the OpenSource community a user on github took it and add support OpenStack and all the latest features available in Cloud Files.\nIt is now pretty robust and works pretty well via nautilus even with the pseudo hierarchical folder feature. The fun part here is that it allow you to effectively have a Cloud Drive where you can easily store your files/backup from your Linux desktop via nautilus built-in ftp support.\nI have made a video that show how it works :\nUpload to the Cloud via FTP from Chmouel Boudjnah on Vimeo.\n","permalink":"https://blog.chmouel.com/2011/04/06/uploading-to-rackspace-cloud-files-via-ftp/","summary":"\u003cp\u003e\u003ca href=\"https://blog.chmouel.com/2009/10/29/ftp-server-for-cloud-files/\"\u003eSometime ago\u003c/a\u003e I wrote a \u003ca href=\"https://github.com/chmouel/ftp-cloudfs/\"\u003eFTP proxy\u003c/a\u003e to RackSpace Cloud Files which expose Rackspace Cloud Files as a FTP server acting as a proxy.\u003c/p\u003e\n\u003cp\u003eThanks to the OpenSource community a user on github took it and add support \u003ca href=\"http://www.openstack.org/\"\u003eOpenStack\u003c/a\u003e and all the latest features available in Cloud Files.\u003c/p\u003e\n\u003cp\u003eIt is now pretty robust and works pretty well via nautilus even with the \u003ca href=\"http://docs.openstack.org/openstack-object-storage/developer/content/ch03s02.html#d5e527\"\u003epseudo hierarchical folder feature\u003c/a\u003e. The fun part here is that it allow you to effectively have a Cloud Drive where you can easily store your files/backup from your Linux desktop via nautilus built-in ftp support.\u003c/p\u003e","title":"Uploading to Rackspace Cloud Files via FTP"},{"content":"I have just uploaded python-cloudfiles to pypi available here\nThis make things easy to add as a dependence of your project like you can have something like this in your setup.py :\nrequirements = ['python-cloudfiles']\nand it will automatically download it as part of the dependence with easy_install or pip.\ncool kids on latest debian/ubuntu can do stuff like this (from python-stdeb package) :\npypi-install python-cloudfiles\nwhich would automatically download the tarball from pypi and install it as a packages (like the way it should be for prod machine!)\nIf you have a virtualenv environment you can easily do a (needs python-pip package) :\npip -E /usr/local/myvirtualenvroot install python-cloudfiles\u0026lt;br /\u0026gt; and magic would be done to get you on latest python-cloudfiles.\nAs a bonus side you can browse online the python-cloudfiles library :\nhttp://packages.python.org/python-cloudfiles/\n**\n[Update] This has been renamed back to python-cloudfiles please update your setup.py or scripts.**\n","permalink":"https://blog.chmouel.com/2011/02/16/installing-python-cloudfiles-from-pypi/","summary":"\u003cp\u003eI have just uploaded \u003ca href=\"https://github.com/rackspace/python-cloudfiles\"\u003epython-cloudfiles\u003c/a\u003e to pypi available \u003ca href=\"http://pypi.python.org/pypi/python-cloudfiles/\"\u003ehere\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eThis make things easy to add as a dependence of your project like you can have something like this in your setup.py :\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003erequirements = ['python-cloudfiles']\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eand it will automatically download it as part of the dependence with easy_install or pip.\u003c/p\u003e\n\u003cp\u003ecool kids on latest debian/ubuntu can do stuff like this (from \u003ca href=\"http://packages.debian.org/sid/python-stdeb\"\u003epython-stdeb\u003c/a\u003e package) :\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003epypi-install python-cloudfiles\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003ewhich would automatically download the tarball from pypi and install it as a packages (like the way it should be for prod machine!)\u003c/p\u003e","title":"Installing python-cloudfiles from pypi"},{"content":"Fireuploader is a Firefox addon that gives you a nice GUI to upload files via your firefox browser.\nI have made a special version of the extensions to make it works with the RackSpace Cloud UK.\nInstall the addon from here :\nhttp://www.chmouel.com/pub/firefox_universal_uploader__fireuploader_-0.4.5-fx+mz+ukcf.xpi\nAllow the website by clicking Allow in the yellow bar on the top as seen in this screenshot :\nClick on Install Now and restart Firefox.\nAfter the Firefox browser is restarted you can go in Tools =\u0026gt; Fireuploader and choose Rackspace Cloud UK in the dropdown list :\nand click on Manage Account :\nenter your UK username and UK API Key and \u0026ldquo;Save Password\u0026rdquo; if you like and it should log you into your UK Cloud :\n","permalink":"https://blog.chmouel.com/2011/02/07/how-to-use-fireuploader-with-the-rackspace-cloud-uk/","summary":"\u003cp\u003eFireuploader is a Firefox addon that gives you a nice GUI to upload files via your firefox browser.\u003c/p\u003e\n\u003cp\u003eI have made a special version of the extensions to make it works with the RackSpace Cloud UK.\u003c/p\u003e\n\u003cp\u003eInstall the addon from here :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://www.chmouel.com/pub/firefox_universal_uploader__fireuploader_-0.4.5-fx+mz+ukcf.xpi\"\u003ehttp://www.chmouel.com/pub/firefox_universal_uploader__fireuploader_-0.4.5-fx+mz+ukcf.xpi\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eAllow the website by clicking Allow in the yellow bar on the top as seen in this screenshot :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"/wp-content/uploads/2011/02/Click-Allow-on-the-top.png\"\u003e\u003c!-- raw HTML omitted --\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eClick on Install Now and restart Firefox.\u003c/p\u003e","title":"How to use fireuploader with the Rackspace Cloud UK"},{"content":"One of the last library I didn\u0026rsquo;t documented in my earlier post was php-cloudfiles. You need to have at least the version 1.7.6 released to have support to different auth_server and when you have that you can do it like this to get access to cloud files via the library :\n\u0026lt;?php require_once(\u0026#34;cloudfiles.php\u0026#34;); # Allow override by environment variable $USER = \u0026#34;MY_API_USERNAME\u0026#34;; $API_KEY = \u0026#34;MY_API_KEY\u0026#34;; $auth = new CF_Authentication($USER, $API_KEY, NULL, UK_AUTHURL); $auth-\u0026gt;authenticate(); ?\u0026gt; ","permalink":"https://blog.chmouel.com/2011/01/12/howto-access-the-uk-rackspace-cloud-with-the-php-binding/","summary":"\u003cp\u003eOne of the last library I didn\u0026rsquo;t documented in my \u003ca href=\"https://blog.chmouel.com/2011/01/04/how-to-use-the-rackspace-cloud-uk-api/\"\u003eearlier post\u003c/a\u003e was php-cloudfiles. You need to have at least the \u003ca href=\"https://github.com/rackspace/php-cloudfiles/archives/1.7.6\"\u003eversion 1.7.6\u003c/a\u003e released to have support to different auth_server and when you have that you can do it like this to get access to cloud files via the library :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e\u0026lt;?\u003c/span\u003ephp\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003erequire_once\u003c/span\u003e(\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;cloudfiles.php\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#6272a4\"\u003e# Allow override by environment variable\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$USER\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;MY_API_USERNAME\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$API_KEY\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;MY_API_KEY\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$auth\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003enew\u003c/span\u003e CF_Authentication(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$USER\u003c/span\u003e, \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$API_KEY\u003c/span\u003e, \u003cspan style=\"color:#ff79c6\"\u003eNULL\u003c/span\u003e, UK_AUTHURL);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$auth\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#50fa7b\"\u003eauthenticate\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e?\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Howto access the UK Rackspace Cloud with the PHP Binding"},{"content":"It seems that my post about using duplicity to backup your data on Rackspace CloudFiles got popular and people may be interested to use with the newly (Beta) released Rackspace Cloud UK. You would just need to have a environnement exported at the top of your backup script like this :\nexport CLOUDFILES_AUTHURL=https://lon.auth.api.rackspacecloud.com/v1.0\nand it will use the UK auth server (the same goes for OpenStack auth server if you have your own Swift install).\nTo make things easier I have taken this script from :\nhttp://damontimm.com/code/dt-s3-backup\nand adapted it to make it work with Rackspace Cloud Files.\nThis is available here :\nhttps://github.com/chmouel/dt-cf-backup\nYou need to make sure that you have python-cloudfiles installed, on a Debian or Ubuntu system you can do it like this :\nsudo apt-get -y install python-stdeb sudo pypi-install python-cloudfiles Check the documentation of your Operating System to install python-cloudfiles, usually it is very easy to do it via pip (pip install python-cloudfiles)\nWhen you have installed duplicity and checkout the script (see the github page for documentation how to do it) you can start configuring it.\nAt the top there is a detailled explanation of the different variables that need to be configured. You can change it in the script or you can have them configured in an external configuration file in your home directory called ~/.dt-cf-backup.conf, this is an example :\nexport CLOUDFILES_USERNAME=\u0026#34;MY_USERNAME\u0026#34; export CLOUDFILES_APIKEY=\u0026#34;MY_APIKEY\u0026#34; export PASSPHRASE=\u0026#34;MY_PASSPHRASE\u0026#34; GPG_KEY=\u0026#34;8D643162\u0026#34; ROOT=\u0026#34;/home/chmouel\u0026#34; export DEST=\u0026#34;cf+http://duplicity_backup\u0026#34; INCLIST=( /home/chmouel/ ) EXCLIST=( \u0026#34;/home/chmouel/tmp\u0026#34; \u0026#34;/**.DS_Store\u0026#34; \u0026#34;/**Icon?\u0026#34; \u0026#34;/**.AppleDouble\u0026#34; ) LOGDIR=\u0026#34;/tmp/\u0026#34; LOG_FILE_OWNER=\u0026#34;chmouel:\u0026#34; You can then just run :\n./dt-cf-backup.sh --backup to do your backup.\nThere is much more documentation in the README.txt.\nI just would like to thanks again the author of dt-s3-backup for this script. I have just made a few modifications for Rackspace Cloud Files.\n","permalink":"https://blog.chmouel.com/2011/01/06/backup-with-duplicity-on-rackspace-cloudfiles-including-uk-script/","summary":"\u003cp\u003eIt seems that my post about using duplicity to backup your data on Rackspace CloudFiles got popular and people may be interested to use with the newly (Beta) released Rackspace Cloud UK. You would just need to have a environnement exported at the top of your backup script like this :\u003c/p\u003e\n\u003cp\u003eexport CLOUDFILES_AUTHURL=https://lon.auth.api.rackspacecloud.com/v1.0\u003c/p\u003e\n\u003cp\u003eand it will use the UK auth server (the same goes for OpenStack auth server if you have your own Swift install).\u003c/p\u003e","title":"Backup with duplicity on Rackspace CloudFiles (including UK) script."},{"content":"If you are wondering howto use a graphical client like Cyberduck to access the Rackspace Cloud UK this is how you do it. We are going to use the Swift OpenStack support in Cyberduck to access the UK CloudFiles instance.\nYou first Open Cyberduck and Click on open connection :\nIn the Menu choose Swift (OpenStack Object Storage) and in Server field you specify :\nlon.auth.api.rackspacecloud.com\nand enter your Username and Api Key (in Password field) :\nYou should just be able to press connect to get going, if it is asking for a Password again in the next screen (which is to store in your Apple Keychain) just specify your API Key again in there.\n","permalink":"https://blog.chmouel.com/2011/01/04/howto-use-cyberduck-with-rackspace-cloud-uk/","summary":"\u003cp\u003eIf you are wondering howto use a graphical client like Cyberduck to access the Rackspace Cloud UK this is how you do it. We are going to use the Swift OpenStack support in Cyberduck to access the UK CloudFiles instance.\u003c/p\u003e\n\u003cp\u003eYou first Open Cyberduck and Click on open connection :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"/wp-content/uploads/2011/01/Open-Window.png\"\u003e\u003c!-- raw HTML omitted --\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eIn the Menu choose Swift (OpenStack Object Storage) and in Server field you specify :\u003c/p\u003e\n\u003cp\u003elon.auth.api.rackspacecloud.com\u003c/p\u003e\n\u003cp\u003eand enter your Username and Api Key (in Password field) :\u003c/p\u003e","title":"Howto use Cyberduck with Rackspace Cloud UK"},{"content":"Rackspace just released the public beta for the UK version of Rackspace Cloud. The UK Rackspace Cloud doesn\u0026rsquo;t have the same auth server as the US Cloud so there is a few change you need to do to support the UK Rackspace Cloud. This is the same way Amazon has different zone for EC2 we have now different geographical zone between the US and now the UK.\nIf you access directly, you just need to adjust the Auth URL in your code to go to :\nhttps://lon.auth.api.rackspacecloud.com\ninstead of :\nhttps://auth.api.rackspacecloud.com\nThe language binding provided by Rackspace has all been updated and available from github :\nFor Python CloudFiles :\ncnx = cloudfiles.Connection(api_username, api_key, authurl=\u0026#34;https://lon.auth.api.rackspacecloud.com/v1.0) For Python CloudServers :\ncloudservers.CloudServers(\u0026#34;USERNAME\u0026#34;, \u0026#34;API_KEY\u0026#34;, auth_url=\u0026#34;https://lon.auth.api.rackspacecloud.com/v1.0\u0026#34;) For Ruby CloudFiles :\nrequire \u0026#39;cloudfiles\u0026#39; # Log into the Cloud Files system cf = CloudFiles::Connection.new( :username =\u0026gt; \u0026#34;USERNAME\u0026#34;, :api_key =\u0026gt; \u0026#34;API_KEY\u0026#34;, :authurl =\u0026gt; \u0026#34;https://lon.auth.api.rackspacecloud.com/v1.0\u0026#34; ) For C# CloudFiles :\nUserCredentials userCreds = new UserCredentials(new Uri(\u0026#34;https://lon.auth.api.rackspacecloud.com/v1.0\u0026#34;), username, api_key, null, null); Connection connection = new com.mosso.cloudfiles.Connection(userCreds); For Java CloudFIles add a cloudfiles.properties file in your classpath with this content :\nusername=username password=apikey auth_url=https://lon.auth.api.rackspacecloud.com/v1.0 connection_timeout=15000 and you would be able to access it like this without any argument to the constructor :\nFilesClient client = new FilesClient(); client.login(); For non rackspace binding I have sent a patch for Apache libcloud :\nhttps://issues.apache.org/jira/browse/LIBCLOUD-66\nwhich when integrated would allow to do something like this :\nfor jclouds you can just pass the auth server like this for cloudfiles :\nand like this for cloudservers :\nfor Ruby Fog :\nrequire \u0026#39;rubygems\u0026#39; require \u0026#39;fog\u0026#39; rackspace = Fog::Rackspace::Storage.new( :rackspace_api_key =\u0026gt; \u0026#34;\u0026#34;, :rackspace_username =\u0026gt; \u0026#34;\u0026#34;, :rackspace_auth_url =\u0026gt; \u0026#34;lon.auth.api.rackspacecloud.com\u0026#34; ) ","permalink":"https://blog.chmouel.com/2011/01/04/how-to-use-the-rackspace-cloud-uk-api/","summary":"\u003cp\u003eRackspace just released the public beta for the UK version of Rackspace Cloud. The UK Rackspace Cloud doesn\u0026rsquo;t have the same auth server as the US Cloud so there is a few change you need to do to support the UK Rackspace Cloud. This is the same way Amazon has different zone for EC2 we have now different geographical zone between the US and now the UK.\u003c/p\u003e\n\u003cp\u003eIf you access directly, you just need to adjust the Auth URL in your code to go to :\u003c/p\u003e","title":"How-to use the Rackspace Cloud UK API"},{"content":"Lately I had to spawn some cloud servers and automatically customise them.\nI have used the python-cloudservers library and installed it automatically with pypi (works for Debian/Ubuntu you may want to check for other distros):\npypi-install python-cloudservers From there writing the script was pretty straight forward, I needed to know what type of CloudServers I wanted which in my case the smallest was good enough which is number 1 for me.\nIf you want to see all flavours you can do something like that from python command prompt\n:\nimport cloudservers cs = cloudservers.CloudServers(\u0026#34;API_USERNAME\u0026#34;, \u0026#34;API_PASSWORD\u0026#34;) for i in cs.flavors.list(): print \u0026#34;ID: %s = %s\u0026#34; % (i.id, i.name) which should output something like this at the time this article has\nbeen written :\nID: 1 - 256 server ID: 2 - 512 server ID: 3 - 1GB server ID: 4 - 2GB server ID: 5 - 4GB server ID: 6 - 8GB server ID: 7 - 15.5GB server You need to figure out the image type as well which is basically the Operating System, in this case I wanted Ubuntu Maverick which is 69. If you want to see all image type you can do :\nimport cloudservers cs = cloudservers.CloudServers(\u0026#34;API_USERNAME\u0026#34;, \u0026#34;API_PASSWORD\u0026#34;) for i in cs.images.list(): print \u0026#34;ID: %s = %s\u0026#34; % (i.id, i.name) which print something like this for me at this time :\nID: 29 = Windows Server 2003 R2 SP2 x86 ID: 69 = Ubuntu 10.10 (maverick) ID: 41 = Oracle EL JeOS Release 5 Update 3 ID: 40 = Oracle EL Server Release 5 Update 4 ID: 187811 = CentOS 5.4 ID: 4 = Debian 5.0 (lenny) ID: 10 = Ubuntu 8.04.2 LTS (hardy) ID: 23 = Windows Server 2003 R2 SP2 x64 ID: 24 = Windows Server 2008 SP2 x64 ID: 49 = Ubuntu 10.04 LTS (lucid) ID: 14362 = Ubuntu 9.10 (karmic) ID: 62 = Red Hat Enterprise Linux 5.5 ID: 53 = Fedora 13 ID: 17 = Fedora 12 ID: 71 = Fedora 14 ID: 31 = Windows Server 2008 SP2 x86 ID: 51 = CentOS 5.5 ID: 14 = Red Hat Enterprise Linux 5.4 ID: 19 = Gentoo 10.1 ID: 28 = Windows Server 2008 R2 x64 ID: 55 = Arch 2010.05 ID: 6719676 = Backup-Image Now to make stuff going automatic we send our ~/.ssh/id_rsa to \u0026lsquo;/root/.ssh/authorized_keys\u0026rsquo; and assuming you have a properly\nconfigured ssh-agent which was already identified you have a passwordless access and you can launch command.\nI have a script that does basic customisations at :\nhttp://chmouel.com/pub/bootstrap.sh\nbut you get the idea from there to launch the command the way you want, you can as well scp and ssh it after if you wanted to have some non public stuff in the script.\nHere is the full script you need to adjust a few variable at the top of the file and customize it the way you want but that should get you started :\n","permalink":"https://blog.chmouel.com/2010/11/23/automatically-spawn-rackspace-cloud-servers-and-customise-it/","summary":"\u003cp\u003eLately I had to spawn some cloud servers and automatically customise them.\u003c/p\u003e\n\u003cp\u003eI have used the  \u003ca href=\"https://github.com/jacobian/python-cloudservers\"\u003epython-cloudservers\u003c/a\u003e library and installed it automatically with pypi (works for Debian/Ubuntu you may want to check for other distros):\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epypi-install python-cloudservers\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eFrom there writing the script was pretty straight forward, I needed to know what type of CloudServers I wanted which in my case the smallest was good enough which is number 1 for me.\u003c/p\u003e","title":"Automatically spawn Rackspace Cloud Servers and customise it."},{"content":"I don\u0026rsquo;t have to use much of the Windows Operating System except when I have to synchronize my Garmin GPS to use the excellent SportsTrack software for my fitness training.\nI wanted to get safe and backup my SportsTrack \u0026rsquo;logbook\u0026rsquo; directly to Rackspace Cloud Files; while this is easy to do from Linux using some other script I made but I haven\u0026rsquo;t had anything at hand for Windows without having to install bunch of Unix tools.\nSo I made a quick C# CLI binary to allow just do that and do my backups via a \u0026lsquo;Scheduler Task\u0026rsquo; (or whatever cron is called on Windows).\nIt\u0026rsquo;s available here :\nhttp://github.com/chmouel/upload-to-cf-cs\nand note that you will need nant to compile it.\n","permalink":"https://blog.chmouel.com/2010/10/11/upload-a-file-to-rackspace-cloud-files-from-windows/","summary":"\u003cp\u003eI don\u0026rsquo;t have to use much of the Windows Operating System except when I have to  synchronize my Garmin GPS to use the excellent \u003ca href=\"http://www.zonefivesoftware.com/sporttracks/\"\u003eSportsTrack\u003c/a\u003e software for my fitness training.\u003c/p\u003e\n\u003cp\u003eI wanted to get safe and backup my SportsTrack \u0026rsquo;logbook\u0026rsquo; directly to Rackspace Cloud Files; while this is easy to do from Linux using some other \u003ca href=\"http://gist.github.com/440304\"\u003escript\u003c/a\u003e I made but I haven\u0026rsquo;t had anything at hand for Windows without having to install bunch of Unix tools.\u003c/p\u003e","title":"Upload a file to Rackspace Cloud Files from Windows"},{"content":"All my music players (Spotify, XBMC, Rythmbox etc\u0026hellip;) are scrobbling over lastfm but not all of them display song lyrics properly so I came up with a quick Google AppEngine app that grab the latest or current song scrobbled over last.fm and display its lyrics. No fancy HTML or javascript just the lyrics displayed for your enjoyment.\nThis is available here :\nhttp://getlastlastfmlyrics.appspot.com/\nfor the scripter around you can just get (via curl or other) :\nhttp://getlastlastfmlyrics.appspot.com/?u=username\nand it will automatically display it for that username.\n","permalink":"https://blog.chmouel.com/2010/10/09/get-latest-lyrics-of-a-scrobbled-lastfm-song/","summary":"\u003cp\u003eAll my music players (Spotify, XBMC, Rythmbox etc\u0026hellip;) are \u003ca href=\"http://www.last.fm/help/faq?category=Scrobbling\"\u003escrobbling\u003c/a\u003e over \u003ca href=\"http://www.last.fm\"\u003elastfm\u003c/a\u003e but not all of them display song lyrics properly so I came up with a quick Google AppEngine app that grab the latest or current song scrobbled over  last.fm and display its lyrics. No fancy HTML or javascript just the lyrics displayed for your enjoyment.\u003c/p\u003e\n\u003cp\u003eThis is available here :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://getlastlastfmlyrics.appspot.com/\"\u003ehttp://getlastlastfmlyrics.appspot.com/\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003efor the scripter around you can just get (via curl or other) :\u003c/p\u003e","title":"Get latest lyrics of a scrobbled LastFM song"},{"content":"This post is literally to test the embedding track feature from Garmin Connect \u0026hellip;..\nThis is a easy bike ride, it start from Ealing to to Decathlon in Canada water and stop in Parsons-Green on my way back to watch Liverpool-Arsenal at mates place before coming back home, my pace was kind of slow since I have a broken thumb and I am trying to respect London traffic now and stop at traffic lights ;-)\nGarmin Forerunner 305 is awesome device by the way if you are doing a lot of outdoor Running / Cycling, I have just ordered the footpod accessory to track my workout when I play football or on a treadmill.\n","permalink":"https://blog.chmouel.com/2010/08/16/sunday-bike-ride-in-london/","summary":"\u003cp\u003eThis post is literally to test the embedding track feature from Garmin Connect \u0026hellip;..\u003c/p\u003e\n\u003cp\u003eThis is a easy bike ride, it start from Ealing to to Decathlon in Canada water and stop in Parsons-Green on my way back to watch Liverpool-Arsenal at mates place before coming back home, my pace was kind of slow since I have a broken thumb and I am trying to respect London traffic now and stop at traffic lights ;-)\u003c/p\u003e","title":"Sunday bike ride in London"},{"content":"I am sure there is billions or more people who already done that but I needed this quickly for my project and was not feeling googling around :\n","permalink":"https://blog.chmouel.com/2010/07/29/python-decorator-to-argument-checking/","summary":"\u003cp\u003eI am sure there is billions or more people who already done that but I needed this quickly for my project and was not feeling googling around :\u003c/p\u003e","title":"Python decorator to argument checking"},{"content":"If you are using Ctrl+Shift+T in Eclipse and have .git or .svn directory showing up it is easy to fix it without having to use another plugin for eclipse like subeclipse or egit.\nOpen the Properties of your project go to Resource=\u0026gt;Resource Filters and click on Add to add a new filter.\nNow just do like this ScreenShot :\nChange the *.git* to *.svn* if you like for subversion.\n","permalink":"https://blog.chmouel.com/2010/06/17/exclude-git-or-svn-directories-in-eclipse-helios/","summary":"\u003cp\u003eIf  you are using Ctrl+Shift+T in Eclipse and have .git or .svn directory showing up it is easy to fix it without having to use another plugin for eclipse like subeclipse or egit.\u003c/p\u003e\n\u003cp\u003eOpen the Properties of your project go to \u003cem\u003eResource\u003c/em\u003e=\u0026gt;\u003cem\u003eResource Filters\u003c/em\u003e and click on Add to add a new filter.\u003c/p\u003e\n\u003cp\u003eNow just do like this ScreenShot :\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003cp\u003eChange the *.git* to *.svn* if you like for subversion.\u003c/p\u003e","title":"Exclude .git or .svn directories in Eclipse (Helios)"},{"content":"I don\u0026rsquo;t really use much the GUI and always the command line so I don\u0026rsquo;t really use the Cloud File plugin I created for nautilus.\nSo here is a shell script to upload to Rackspace Cloud Files and give you back a shortened URL of the public URL file. Great for quick sharing\u0026hellip; You have to install the zenity binary first..\n[Update: this is now available here https://github.com/chmouel/upcs]\n","permalink":"https://blog.chmouel.com/2010/06/09/upload-to-rackspace-cloud-files-in-a-shell-script/","summary":"\u003cp\u003eI don\u0026rsquo;t really use much the GUI and always the command line so I don\u0026rsquo;t really use the Cloud File plugin I created for nautilus.\u003c/p\u003e\n\u003cp\u003eSo here is a shell script to upload to Rackspace Cloud Files and give you back a shortened URL of the public URL file. Great for quick sharing\u0026hellip; You have to install the zenity binary first..\u003c/p\u003e\n\u003cp\u003e[Update: this is now available here \u003ca href=\"https://github.com/chmouel/upcs\"\u003ehttps://github.com/chmouel/upcs\u003c/a\u003e]\u003c/p\u003e","title":"Upload to Rackspace Cloud Files in a shell script"},{"content":"Quick conversion from shell :\n","permalink":"https://blog.chmouel.com/2010/06/06/unit-conversion-from-zsh/","summary":"\u003cp\u003eQuick conversion from shell :\u003c/p\u003e","title":"Unit conversion from zsh"},{"content":"You want to connect to self signed SSL certificate from Java using the standard HttpsURLConnection and you are getting this error, because the self signed certificate is obviously not recognized by Java :\nSEVERE: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1639) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:215) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:209) it seems that there is a lot of \u0026lsquo;solutions\u0026rsquo; (read hack) or workaround around the web which is resumed well on this stack overflow article.\nThere is actually a very easy (and secure) way on Debian based systems.\nGo to your https url with Firefox Right Click to \u0026lsquo;View Page Info\u0026rsquo; In \u0026lsquo;Security\u0026rsquo; tab you will see a button saying \u0026lsquo;View Certificate\u0026rsquo; Click now on the \u0026lsquo;Details\u0026rsquo; tab Finally click on the \u0026lsquo;Export\u0026rsquo; button which offer you to save the PEM certifcate of the website somewhere on your filesystem. Call it my.self.signed.domain.name.pem or whatever my.self.signed.domain.name should be and put the file in /etc/ssl/certs now you just have to run the command :\nsudo update-ca-certificates and it should add your certificate to the java keystore, you can check it with the command (Enter for Password) :\nkeytool -list -v -keystore /etc/ssl/certs/java/cacerts ","permalink":"https://blog.chmouel.com/2010/06/03/connecting-to-self-signed-ssl-certificate-from-java-on-debian-ubuntu/","summary":"\u003cp\u003eYou want to connect to self signed SSL certificate from Java using the standard \u003ca href=\"http://java.sun.com/j2se/1.4.2/docs/api/javax/net/ssl/HttpsURLConnection.html\"\u003eHttpsURLConnection\u003c/a\u003e and you are getting this error, because the self signed certificate is obviously not recognized by Java :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSEVERE: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ejavax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tat sun.security.ssl.Alerts.getSSLException(Alerts.java:192)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tat sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1639)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tat sun.security.ssl.Handshaker.fatalSE(Handshaker.java:215)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tat sun.security.ssl.Handshaker.fatalSE(Handshaker.java:209)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eit seems that there is a lot of \u0026lsquo;solutions\u0026rsquo; (read hack) or workaround around the web which is resumed well on \u003ca href=\"http://stackoverflow.com/questions/875467/java-client-certificates-over-https-ssl\"\u003ethis\u003c/a\u003e stack overflow article.\u003c/p\u003e","title":"connecting to self signed SSL certificate from Java on Debian/Ubuntu"},{"content":"Latest Froyo for Android have a nice feature for pushing messages to a Android phone, it\u0026rsquo;s called Android Cloud to Device Messaging Framework.\nSomeone at google has developped a nice extensions/apps for sending URL directly from google chrome web browser to your phone, it is called chrometophone and available here.\nI often use cyrket for browsing and installing new apps. I thought it could be nice to add support to chrome2phone when sending a cyrknet URL to my Nexus one to popup a market link to install the app sent.\nSo here is a patch against the android APP or directly the APK to install manually.\n","permalink":"https://blog.chmouel.com/2010/05/25/chrometophone-and-cyrket/","summary":"\u003cp\u003eLatest Froyo for Android have a nice feature for pushing messages to a Android phone, it\u0026rsquo;s called Android Cloud to \u003ca href=\"http://code.google.com/android/c2dm/\"\u003eDevice Messaging Framework\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eSomeone at google has developped a nice extensions/apps for sending URL directly from google chrome web browser to your phone, it is called chrometophone and available \u003ca href=\"http://code.google.com/p/chrometophone/\"\u003ehere\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eI often use \u003ca href=\"http://www.cyrket.com/p/android/\"\u003ecyrket\u003c/a\u003e for browsing and installing new apps. I thought it could be nice to add support to chrome2phone when sending a cyrknet URL to my Nexus one to popup a market link to install the app sent.\u003c/p\u003e","title":"chrometophone and cyrket"},{"content":"Lately I had to do a lot of works with the VMware VCloud product and since the python API did not seem available and I did not have the courage to use the PHP API I had to do most of the API works with Java. I never did any Java before and while I have found Eclipse+Java development surprisingly pleasant and easy to use/learn my favourite are still Emacs+Python.\nI have then started to look over Jython to see if I can interact easily with Java via Python and this was actually pretty easy, it took me less than 10mn to convert a Login/Listing-VAPPS script in Jython.\nThe script is attached at the end of this post (or on github gist here). Don\u0026rsquo;t forget to adjust the classpath variable mine are defined like that :\ncommons-codec-1.3.jar commons-httpclient-3.1.jar commons-logging-1.1.1.jar rest-api-schemas-1.0.0.jar vcloud-java-sdk-0.9.jar vCloudJavaSDK-samples.jar\n#!/usr/bin/jython import sys from org.apache.commons.httpclient.protocol import Protocol from com.vmware.vcloud.sdk import VcloudClient, Organization, Vdc from com.vmware.vcloud.sdk.samples import FakeSSLSocketFactory class VcloudLogin(object): \u0026#34;\u0026#34;\u0026#34; VcloudLogin: Login to vcloud class \u0026#34;\u0026#34;\u0026#34; vcloudClient = None api_version = None vcloud_url = None def __init__(self, vcloud_url, api_version): # This is needed if you have a self certified certificate # remove it if you have a proper SSL certs. self.setup_fake_ssl() self.vcloud_url = vcloud_url self.api_version = api_version def setup_fake_ssl(self): https = Protocol(\u0026#34;https\u0026#34;, FakeSSLSocketFactory(), 443) Protocol.registerProtocol(\u0026#34;https\u0026#34;, https) def login(self, username, password): versions = VcloudClient.getSupportedVersions(self.vcloud_url + \u0026#34;/api/versions\u0026#34;) self.vcloudClient = VcloudClient(versions.get(self.api_version)) return self.vcloudClient.login(username, password) if __name__ == \u0026#39;__main__\u0026#39;: URL=\u0026#34;https://URL\u0026#34; API_VERSION=\u0026#34;0.9\u0026#34; USERNAME=\u0026#34;user@organization\u0026#34; PASSWORD=\u0026#34;password\u0026#34; vcl = VcloudLogin(URL, API_VERSION) organizations_list = vcl.login(USERNAME, PASSWORD) for org in organizations_list.values(): for vdcLink in \\ Organization.getOrganizationByReference(vcl.vcloudClient, org).getVdcLinks(): vdc = Vdc.getVdc(vcl.vcloudClient, vdcLink) print \u0026#34;VDC Href: %s\\n\u0026#34; % (vdcLink.getHref()) for vapps in vdc.getVappRefs(): print \u0026#34;Name: %s URL: %s\u0026#34; % (vapps.getName(), vapps.getHref()) ","permalink":"https://blog.chmouel.com/2010/05/17/using-jython-with-the-vcloud-api/","summary":"\u003cp\u003eLately I had to do a lot of works with the \u003c!-- raw HTML omitted --\u003eVMware VCloud\u003c!-- raw HTML omitted --\u003e product and since the python API did not seem available and I did not have the courage to use the PHP API I had to do most of the API works with Java. I never did any Java before and while I have found Eclipse+Java development surprisingly pleasant and easy to use/learn my favourite are still Emacs+Python.\u003c/p\u003e","title":"Using Jython with the vCloud API"},{"content":"If like me you are surprised by the fact that dbstart or dbshut does not do anything when launching it, just make sure to edit the /etc/oratab and have the last char as Y and not N. Like if it is like this :\nchange it to this :\n","permalink":"https://blog.chmouel.com/2010/04/23/when-oracle-dbstartdbshut-does-not-do-anything/","summary":"\u003cp\u003eIf like me you are surprised by the fact that dbstart or dbshut does not do anything when launching it, just make sure to edit the /etc/oratab and have the last char as Y and not N. Like if it is like this :\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003cp\u003echange it to this :\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e","title":"When Oracle dbstart/dbshut does not do anything"},{"content":"If you want to boot backtrack4 from time to time on your Linux desktop/laptop but don\u0026rsquo;t want to carry it on a USB drive (or CDROM) on you then this guide may help.\nI am using Debian unstable on my laptop but I am sure you can adapt it to anything you want. I am using another partition (/dev/sda6) as my backtrack partition but it\u0026rsquo;s possible to copy the full thing in / as well on your main partition.\nDownload backtrack4 from backtrack website :\nhttp://www.backtrack-linux.org/downloads/\nmount the iso image locally : sudo mount -o loop bt4-final.iso /mnt\ncopy the content of the iso to the root of the chosen partition (mounted in /media/part6 for me) : cd /mnt;sudo rsync \u0026ndash;progress -avu * /media/part6/\nConfigure grub : sudo su -\ncat \u0026lt; /etc/grub.d/50_Backtrack\n#!/bin/sh\nexec tail -n +3 $0\nmenuentry \u0026ldquo;Backtrack\u0026rdquo; {\nlinux (hd0,6)/boot/vmlinuz BOOT=casper boot=casper nopersistent rw quiet vga=0x317\ninitrd (hd0,6)/boot/initrd.gz\n}\nEOF\nchmod +x /etc/grub.d/50_Backtrack\nUpdate grub sudo update-grub\nAnd you should be able to boot the Backtrack menu, make sure this point to the right partition for me it\u0026rsquo;s (hd0,6) because my backtrack copied CD is on /dev/sda6 but your mileage may differ.\n","permalink":"https://blog.chmouel.com/2010/03/08/howto-use-backtrack4-from-hard-disk-with-grub2/","summary":"\u003cp\u003eIf you want to boot backtrack4 from time to time on your Linux desktop/laptop but don\u0026rsquo;t want to carry it on a USB drive (or CDROM) on you then this guide may help.\u003c/p\u003e\n\u003cp\u003eI am using Debian unstable on my laptop but I am sure you can adapt it to anything you want. I am using another partition (/dev/sda6) as my backtrack partition but it\u0026rsquo;s possible to copy the full thing in / as well on your main partition.\u003c/p\u003e","title":"Howto use backtrack4 from hard disk with Grub2"},{"content":"Since I haven\u0026rsquo;t see much script like this around the web here is a quick script to suck bunch of albums from facebooks (your own) nothing fancy just something to get you started with pyfacebook.\n#!/usr/bin/python import os import urllib from facebook import Facebook # see http://developers.facebook.com/get_started.php # Your API key API_KEY=\u0026#34;YOUR_API_KEY\u0026#34; # Application secret key SECRET_KEY=\u0026#34;YOUR_SECRET_KEY\u0026#34; cnx = Facebook(API_KEY, SECRET_KEY) cnx.auth.createToken() cnx.login() cnx.auth.getSession() def choose_albums(cnx): cnt = 1 ret={} bigthing=cnx.photos.getAlbums(cnx.uid) for row in bigthing: ret[cnt] = row[\u0026#39;name\u0026#39;], row[\u0026#39;aid\u0026#39;], row[\u0026#39;link\u0026#39;] print \u0026#34;%d) %s - %s\u0026#34; % (cnt, row[\u0026#39;name\u0026#39;], row[\u0026#39;link\u0026#39;]) cnt += 1 ans = raw_input(\u0026#34;Choose albums (separated by ,): \u0026#34;) return [ret[int(row)] for row in ans.split(\u0026#39;, \u0026#39;) ] chosen_albums = choose_albums(cnx) for album in chosen_albums: name, aid, _ = album print \u0026#34;Album: \u0026#34;, (name) ddir = \u0026#34;fbgallery/%s\u0026#34; % name if not os.path.exists(ddir): os.makedirs(ddir) for photo in cnx.photos.get(aid=aid): url = photo[\u0026#39;src_big\u0026#39;] dest=\u0026#34;%s/%s.jpg\u0026#34; % (ddir, photo[\u0026#39;pid\u0026#39;]) if not os.path.exists(dest): print \u0026#34;Getting: \u0026#34;, url urllib.urlretrieve(url, dest) ","permalink":"https://blog.chmouel.com/2010/01/09/get-facebook-albums-with-python/","summary":"\u003cp\u003eSince I haven\u0026rsquo;t see much script like this around the web here is a quick script to suck bunch of albums from facebooks (your own) nothing fancy just something to get you started with pyfacebook.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#6272a4\"\u003e#!/usr/bin/python\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eimport\u003c/span\u003e os\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eimport\u003c/span\u003e urllib\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003efrom\u003c/span\u003e facebook \u003cspan style=\"color:#ff79c6\"\u003eimport\u003c/span\u003e Facebook\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#6272a4\"\u003e# see http://developers.facebook.com/get_started.php\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#6272a4\"\u003e# Your API key\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAPI_KEY\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;YOUR_API_KEY\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#6272a4\"\u003e# Application secret key\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSECRET_KEY\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;YOUR_SECRET_KEY\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecnx \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e Facebook(API_KEY, SECRET_KEY)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecnx\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003eauth\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ecreateToken()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecnx\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003elogin()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecnx\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003eauth\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003egetSession()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#50fa7b\"\u003echoose_albums\u003c/span\u003e(cnx):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    cnt \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ret\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e{}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    bigthing\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003ecnx\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ephotos\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003egetAlbums(cnx\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003euid)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ff79c6\"\u003efor\u003c/span\u003e row \u003cspan style=\"color:#ff79c6\"\u003ein\u003c/span\u003e bigthing:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ret[cnt] \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e row[\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;name\u0026#39;\u003c/span\u003e], row[\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;aid\u0026#39;\u003c/span\u003e], row[\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;link\u0026#39;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eprint\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e%d\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e) \u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e%s\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e - \u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e%s\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e%\u003c/span\u003e (cnt, row[\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;name\u0026#39;\u003c/span\u003e], row[\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;link\u0026#39;\u003c/span\u003e])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        cnt \u003cspan style=\"color:#ff79c6\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ans \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e raw_input(\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;Choose albums (separated by ,): \u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ff79c6\"\u003ereturn\u003c/span\u003e [ret[\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eint\u003c/span\u003e(row)] \u003cspan style=\"color:#ff79c6\"\u003efor\u003c/span\u003e row \u003cspan style=\"color:#ff79c6\"\u003ein\u003c/span\u003e ans\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003esplit(\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;, \u0026#39;\u003c/span\u003e) ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003echosen_albums \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e choose_albums(cnx)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003efor\u003c/span\u003e album \u003cspan style=\"color:#ff79c6\"\u003ein\u003c/span\u003e chosen_albums:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    name, aid, _ \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e  album\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eprint\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;Album: \u0026#34;\u003c/span\u003e, (name)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ddir \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;fbgallery/\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e%s\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e%\u003c/span\u003e name\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ff79c6\"\u003eif\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003enot\u003c/span\u003e os\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003epath\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003eexists(ddir):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        os\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003emakedirs(ddir)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ff79c6\"\u003efor\u003c/span\u003e photo \u003cspan style=\"color:#ff79c6\"\u003ein\u003c/span\u003e cnx\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ephotos\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003eget(aid\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003eaid):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        url \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e photo[\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;src_big\u0026#39;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        dest\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e%s\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e%s\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e.jpg\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e%\u003c/span\u003e (ddir, photo[\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;pid\u0026#39;\u003c/span\u003e])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#ff79c6\"\u003eif\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003enot\u003c/span\u003e os\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003epath\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003eexists(dest):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eprint\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;Getting: \u0026#34;\u003c/span\u003e, url\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            urllib\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003eurlretrieve(url, dest)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Get Facebook albums with python"},{"content":"I don\u0026rsquo;t check very often my twitter to know when someone replies and I find it hard to figure out what\u0026rsquo;s going on when i check a couple of days after even using a client showing only the reply (my client of choice lately is the Emacs twittering mode client)\nI have made a script who\u0026rsquo;s checking your direct reply and email it to you. This is to setup via a cron on a server who has a mail server configured locally. You can get it from here :\nhttp://github.com/chmouel/twitter-reply-notification\n","permalink":"https://blog.chmouel.com/2010/01/07/twitter-notification-of-replies-by-email/","summary":"\u003cp\u003eI don\u0026rsquo;t check very often my twitter to know when someone replies and I find it hard to figure out what\u0026rsquo;s going on when i check a couple of days after even using a client showing only the reply (my client of choice lately is the \u003ca href=\"http://www.emacswiki.org/emacs/TwitteringMode\"\u003eEmacs twittering\u003c/a\u003e mode client)\u003c/p\u003e\n\u003cp\u003eI have made a script who\u0026rsquo;s checking your direct reply and email it to you. This is to setup via a cron on a server who has a mail server configured locally. You can get it from here :\u003c/p\u003e","title":"Twitter notification of replies by Email"},{"content":"\nIt\u0026rsquo;s probably interesting only for the hardcore Emacs users but the last CVS version of emacs (2009-12-17) get a nifty new improvement if you need to customize a face property.\nIf you point on the text where you want to customize it will detect it automatically which face point you are on and ask you if this is what you want to customize (after launching the command M-x customize-face). No guessing around with list-face-displays anymore.\nI am just mentioning that because it does not seems to me mentioned in the CHANGES file.\n","permalink":"https://blog.chmouel.com/2009/12/22/customize-face-at-point-in-emacs/","summary":"\u003cp\u003e\u003ca href=\"/wp-content/uploads/2009/12/Screenshot-1.png\"\u003e\u003c!-- raw HTML omitted --\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eIt\u0026rsquo;s probably interesting only for the hardcore Emacs users but the last CVS version of emacs (2009-12-17) get a nifty new improvement if you need to customize a face property.\u003c/p\u003e\n\u003cp\u003eIf you point on the text where you want to customize it will detect it automatically which face point you are on and ask you if this is what you want to customize (after launching the command M-x customize-face). No guessing around with list-face-displays anymore.\u003c/p\u003e","title":"Customize face at point in Emacs"},{"content":"\nSometime ago I made a shell script to upload directly to Rackspace CF using the script capability of nautilus. While working well it did not offer the progress bar and was hard to update. I have made now as a proper python nautilus plugin which offer these features.\nThe code is available here :\nhttp://github.com/chmouel/nautilus-cloud-files-plugin\nThe old version is here, which is still a good example for uploading to Rackspace CF via the shell :\nhttp://github.com/chmouel/nautilus-shell-script-rackspace-cloud-files\nTo make it easier for people to install all the tools I have made for Rackspace Cloud Files I have made available a PPA repository for ubuntu karmic which should work in debian unstable :\nhttps://launchpad.net/~chmouel/+archive/rackspace-cloud-files\nit contains as well the API packaged until they are going to be uploaded to the official debian/ubuntu repositories.\n","permalink":"https://blog.chmouel.com/2009/12/21/new-gnome-plugin-for-uploading-to-rackspace-cloud-files-and-aptppa-repo-for-cf-tools/","summary":"\u003cp\u003e\u003ca href=\"/wp-content/uploads/2009/12/Screenshot.png\"\u003e\u003c!-- raw HTML omitted --\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eSometime ago I made a shell script to upload directly to Rackspace CF using the script capability of nautilus. While working well it did not offer the progress bar and was hard to update. I have made now as a proper python nautilus plugin which offer these features.\u003c/p\u003e\n\u003cp\u003eThe code is available here :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://github.com/chmouel/nautilus-cloud-files-plugin\"\u003ehttp://github.com/chmouel/nautilus-cloud-files-plugin\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eThe old version is here, which is still a good example for uploading to Rackspace CF via the shell :\u003c/p\u003e","title":"New GNOME plugin for uploading to Rackspace Cloud Files and APT/PPA repo for CF tools."},{"content":"Like a lot of people I have my irssi on a server in a screen. This has\nbeen working great so far but my only concerns are the notifications\non the desktop when something happening.\nOver the time I have found some different solution with mitigated\nresults for me :\nUse fanotify script with the libnotify-bin and SSH like mentioned here.\nSetup your irssi (or other) as irc proxy bouncer and connect with\nyour desktop client (like xchat) to get notification.\nThe fanotify is kind of very hacky on a laptop with intermittent\nconnection and having a cron doing a ssh every minutes or so is not\nideal, not talking about no passphrase ssh key or having to snoop the\nSSH_AGENT variable to connect without password.\nThe via proxy method is not my thing and I don\u0026rsquo;t feel like having\nxchat open all the time just for it and I anyway usually forget to\nlaunch it.\nMy solution is to have a plugin for irssi notify me via XMPP if there\nis a direct message addressed to me. I usually get my pidgin or gmail\nalway open and if i don\u0026rsquo;t since it goes to a gmail account I got gmail\nsending me an email about it.\nYou can find all the information about the install and configuration\nhere :\nhttp://github.com/chmouel/irssi-xmpp-notify\n","permalink":"https://blog.chmouel.com/2009/12/20/xmpp-notification-for-irssi-running-in-a-screen-on-a-remote-host/","summary":"\u003cp\u003eLike a lot of people I have my irssi on a server in a screen. This has\u003cbr\u003e\nbeen working great so far but my only concerns are the notifications\u003cbr\u003e\non the desktop when something happening.\u003c/p\u003e\n\u003cp\u003eOver the time I have found some different solution with mitigated\u003cbr\u003e\nresults for me :\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eUse fanotify script with the libnotify-bin and SSH like mentioned \u003ca href=\"http://thorstenl.blogspot.com/2007/01/thls-irssi-notification-script.html\"\u003ehere\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eSetup your irssi (or other) as irc proxy bouncer and connect with\u003cbr\u003e\nyour desktop client (like xchat) to get notification.\u003c/p\u003e","title":"XMPP notification for irssi running in a screen on a remote host"},{"content":"So you have a shiny new linux-2.6.32 kernel installed but your VMPlayer does not work anymore since the vmnet module does not compile by throwing this error :\nCC [M] /tmp/vmware-root/modules/vmnet-only/vnetEvent.o\nCC [M] /tmp/vmware-root/modules/vmnet-only/vnetUserListener.o\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c: In function â€˜VNetUserListenerEventHandlerâ€™:\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c:240: error: â€˜TASK_INTERRUPTIBLEâ€™ undeclared (first use in this function)\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c:240: error: (Each undeclared identifier is reported only once\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c:240: error: for each function it appears in.)\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c: In function â€˜VNetUserListenerReadâ€™:\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c:282: error: â€˜TASK_INTERRUPTIBLEâ€™ undeclared (first use in this function)\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c:282: error: implicit declaration of function â€˜signal_pendingâ€™\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c:282: error: implicit declaration of function â€˜scheduleâ€™\nmake[2]: *** [/tmp/vmware-root/modules/vmnet-only/vnetUserListener.o] Error 1\nmake[1]: *** [_module_/tmp/vmware-root/modules/vmnet-only] Error 2\nmake[1]: Leaving directory `/opt/temp/linux-2.6.32\u0026rsquo;\nmake: *** [vmnet.ko] Error 2\nJust do the following to fix it :\nmake sure first you have installed the latest vmplayer (VMware-Player-3.0.0-203739.i386.bundle) at this time for me.\ncd /tmp\ntar xf /usr/lib/vmware/modules/source/vmnet.tar\ncd vmnet-only\nvim vnetUserListener.c\ngo to line 37 (after the last include)\nadd this line #include \u0026ldquo;compat_sched.h\u0026rdquo;\nexit your editor\ncd /tmp\nsudo tar cf /usr/lib/vmware/modules/source/vmnet.tar vmnet-only\nrestart vmplayer\nWhen recompiling the kernel module it should get it built properly and working it seems\u0026hellip;..\n","permalink":"https://blog.chmouel.com/2009/12/05/vmware-vmplayer-and-kernel-2-6-32/","summary":"\u003cp\u003eSo you have a shiny new linux-2.6.32 kernel installed but your VMPlayer does not work anymore since the vmnet module does not compile by throwing this error :\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eCC [M] /tmp/vmware-root/modules/vmnet-only/vnetEvent.o\u003cbr\u003e\nCC [M] /tmp/vmware-root/modules/vmnet-only/vnetUserListener.o\u003cbr\u003e\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c: In function â€˜VNetUserListenerEventHandlerâ€™:\u003cbr\u003e\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c:240: error: â€˜TASK_INTERRUPTIBLEâ€™ undeclared (first use in this function)\u003cbr\u003e\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c:240: error: (Each undeclared identifier is reported only once\u003cbr\u003e\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c:240: error: for each function it appears in.)\u003cbr\u003e\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c: In function â€˜VNetUserListenerReadâ€™:\u003cbr\u003e\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c:282: error: â€˜TASK_INTERRUPTIBLEâ€™ undeclared (first use in this function)\u003cbr\u003e\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c:282: error: implicit declaration of function â€˜signal_pendingâ€™\u003cbr\u003e\n/tmp/vmware-root/modules/vmnet-only/vnetUserListener.c:282: error: implicit declaration of function â€˜scheduleâ€™\u003cbr\u003e\nmake[2]: *** [/tmp/vmware-root/modules/vmnet-only/vnetUserListener.o] Error 1\u003cbr\u003e\nmake[1]: *** [_module_/tmp/vmware-root/modules/vmnet-only] Error 2\u003cbr\u003e\nmake[1]: Leaving directory `/opt/temp/linux-2.6.32\u0026rsquo;\u003cbr\u003e\nmake: *** [vmnet.ko] Error 2\u003c/p\u003e","title":"Vmware vmplayer and kernel 2.6.32"},{"content":"I have this nice Toshiba TV which is connected to a small Linux box which act as a media player. I have been some issue lately the things works fine under the 1920x1800 resolution most of the time. But once in a while I get a blank screen and the nvidia driver telling me this :\n(II) Dec 03 17:00:19 NVIDIA(0): \u0026ldquo;nvidia-auto-select\u0026rdquo;\n(II) Dec 03 17:00:19 NVIDIA(0): Virtual screen size determined to be 640 x 480\n(WW) Dec 03 17:00:19 NVIDIA(0): Unable to get display device CRT-0\u0026rsquo;s EDID; cannot compute DPI\n(WW) Dec 03 17:00:19 NVIDIA(0): from CRT-0\u0026rsquo;s EDID.\n(==) Dec 03 17:00:19 NVIDIA(0): DPI set to (75, 75); computed from built-in default\n(==) Dec 03 17:00:19 NVIDIA(0): Enabling 32-bit ARGB GLX visuals.\n(\u0026ndash;) Depth 24 pixmap format is 32 bpp\nSpend a long time trying to debug the thing by the software but it seems that the TV has some kind of trouble and if I switch it to another HDMI connection it does detect fine which I do at about every week\u0026hellip; not a biggie but still annoying.\n","permalink":"https://blog.chmouel.com/2009/12/03/toshiba-regza-32av615db-blank-screen-hdmi-linux/","summary":"\u003cp\u003eI have this nice Toshiba TV which is connected to a small Linux box which act as a media player. I have been some issue lately the things works fine under the 1920x1800 resolution most of the time. But once in a while I get a blank screen and the nvidia driver telling me this :\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e(II) Dec 03 17:00:19 NVIDIA(0): \u0026ldquo;nvidia-auto-select\u0026rdquo;\u003cbr\u003e\n(II) Dec 03 17:00:19 NVIDIA(0): Virtual screen size determined to be 640 x 480\u003cbr\u003e\n(WW) Dec 03 17:00:19 NVIDIA(0): Unable to get display device CRT-0\u0026rsquo;s EDID; cannot compute DPI\u003cbr\u003e\n(WW) Dec 03 17:00:19 NVIDIA(0): from CRT-0\u0026rsquo;s EDID.\u003cbr\u003e\n(==) Dec 03 17:00:19 NVIDIA(0): DPI set to (75, 75); computed from built-in default\u003cbr\u003e\n(==) Dec 03 17:00:19 NVIDIA(0): Enabling 32-bit ARGB GLX visuals.\u003cbr\u003e\n(\u0026ndash;) Depth 24 pixmap format is 32 bpp\u003c/p\u003e","title":"Toshiba Regza 32AV615DB blank screen HDMI Linux"},{"content":"Spent a bit of time to configure my Nokia mobile to teethering wih my Linux and T-Mobile. Here is some steps that may help the others :\nIf you don\u0026rsquo;t have that blue bluetooth led switched on on your Dell Latitude D630 Laptop you have to enable it. I haven\u0026rsquo;t find any way to do that via the Linux Kernel module but with Windows under Vmware Player (3.0) enabling Bluetooth and installing the driver (manually not via the setup.exe) enabled bluetooth. Switched on bluetooth on the Phone and attached to the laptop via gnome bluetooth applet thingy. Get my phone device number from hcitool scan. And did this (as root) : cat \u0026lt;/etc/bluetooth/rfcomm.conf\n# RFCOMM configuration file.\nrfcomm0 {\n# Automatically bind the device at startup\nbind yes;\n# Bluetooth address of the device\ndevice YOUR:PHONE:DEVICE:NUMBER;\n# RFCOMM channel for the connection\nchannel 4;\n# Description of the connection\ncomment \u0026ldquo;Nokia N95\u0026rdquo;;\n}\nEOF\n/etc/init.d/bluetooth restart\ncat \u0026lt;/etc/ppp/chat-tmobile\nABORT BUSY\nABORT \u0026lsquo;NO CARRIER\u0026rsquo;\nABORT \u0026lsquo;NO ANSWER\u0026rsquo;\nABORT ERROR\nREPORT CONNECT\nSAY \u0026lsquo;Calling t-mobile\u0026hellip;\\n\u0026rsquo;\n\u0026quot;\u0026quot; \u0026lsquo;ATZ\u0026rsquo;\nOK \u0026lsquo;ATE0V1\u0026amp;D2\u0026amp;C1S0=0+IFC=2,2\u0026rsquo;\nSAY \u0026lsquo;Modem reset.\\n\u0026rsquo;\nSAY \u0026lsquo;Setting APN\u0026hellip;\u0026rsquo;\nOK \u0026lsquo;AT+cgdcont=1,\u0026ldquo;IP\u0026rdquo;,\u0026ldquo;general.t-mobile.uk\u0026rdquo;\u0026rsquo;\nSAY \u0026lsquo;APN set\\n\u0026rsquo;\nSAY \u0026lsquo;Dialling\u0026hellip;\\n\u0026rsquo;\nOK \u0026lsquo;ATDT*99#\u0026rsquo;\nTIMEOUT 30\nCONNECT \u0026quot;\u0026quot;\nEOF\ncat \u0026lt;/etc/ppp/peers/t-mobile\n/dev/rfcomm0\n460800\nidle 7200\nmodem\nnoauth\nlock\ncrtscts\ndefaultroute\nuser \u0026ldquo;user\u0026rdquo;\npassword \u0026ldquo;pass\u0026rdquo;\nnoipdefault\nusepeerdns\nupdetach\nnoccp\nnobsdcomp\n#novj\nipcp-restart 10\nipcp-accept-local\nipcp-accept-remote\nlcp-echo-interval 65535\nlcp-echo-failure 10\nlcp-max-configure 10\nconnect \u0026ldquo;/usr/sbin/chat -v -f /etc/ppp/chat-tmobile\u0026rdquo;\nEOF\nUnder Debian distros you can enable the connection with the command \u0026lsquo;pon t-mobile\u0026rsquo; or you for the others can do via the manual way with the command \u0026lsquo;pppd call t-mobile\u0026rsquo;.\n","permalink":"https://blog.chmouel.com/2009/10/30/nokia-n95-bluetooth-teethering-with-t-mobile-under-linux-and-delll-latitude-d630/","summary":"\u003cp\u003eSpent a bit of time to configure my Nokia mobile to teethering wih my Linux and T-Mobile. Here is some steps that may help the others :\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIf you don\u0026rsquo;t have that blue bluetooth led switched on on your Dell Latitude D630 Laptop you have to enable it. I haven\u0026rsquo;t find any way to do that via the Linux Kernel module but with Windows under Vmware Player (3.0) enabling Bluetooth and installing the \u003ca href=\"http://support.dell.com/support/downloads/download.aspx?c=ca\u0026amp;l=en\u0026amp;s=gen\u0026amp;releaseid=R155172\u0026amp;SystemID=LATITUDE%20D630\u0026amp;servicetag=\u0026amp;os=WW1\u0026amp;osl=en\u0026amp;deviceid=13911\u0026amp;devlib=0\u0026amp;typecnt=0\u0026amp;vercnt=1\u0026amp;catid=-1\u0026amp;impid=-1\u0026amp;formatcnt=1\u0026amp;libid=5\u0026amp;fileid=206919\" title=\"Dell Latitude Driver\"\u003edriver\u003c/a\u003e (manually not via the setup.exe) enabled bluetooth.\u003c/li\u003e\n\u003cli\u003eSwitched on bluetooth on the Phone and attached to the laptop via gnome bluetooth applet thingy.\u003c/li\u003e\n\u003cli\u003eGet my phone device number from hcitool scan.\u003c/li\u003e\n\u003cli\u003eAnd did this (as root) :\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003cp\u003ecat \u0026lt;/etc/bluetooth/rfcomm.conf\u003c/p\u003e","title":"Nokia N95 bluetooth teethering with T-Mobile under Linux and Delll Latitude D630"},{"content":"I have just committed an experiment of a FTP Server answering to Cloud Files. It act completely transparently to be able to use any FTP Client to connect to cloud-files.\nThere is probably a couple of bugs there but the basis of it seems to be working, please let me know if you find any problems with it.\nUsage\nBy default it will bind to port 2021 and localhost to be able to be launched by user which can be changed via the command line option -p. The username password are your API Username and key.\nManual Install\nFTP-Cloudfs require the pyftpdlib which can be installed from here :\nhttp://code.google.com/p/pyftpdlib/\nand python-cloudfiles :\nhttp://github.com/rackspace/python-cloudfiles\nyou can then checkout FTP-Cloudfs from here :\nhttp://github.com/chmouel/ftp-cloudfs\nThe way to install python package is pretty simple, simply do a python\nsetup.py install after uncompressing the tarball downloaded.\nAutomatic Install:\nYou can generate a debian package directly from the source if you have\ndpkg-buildpackage installed on your system. It will give you a nice\ninitscripts as well to start automatically the ftp cloudfs process.\nSupport\nAlbeit I am working for Rackspace Cloud this is not supported by\nRackspace but please feel free to send a comment here if you have any\nproblems.\n","permalink":"https://blog.chmouel.com/2009/10/29/ftp-server-for-cloud-files/","summary":"\u003cp\u003eI have just committed an experiment of a FTP Server answering to Cloud Files. It act completely transparently to be able to use any FTP Client to connect to cloud-files.\u003c/p\u003e\n\u003cp\u003eThere is probably a couple of bugs there but the basis of it seems to be working, please let me know if you find any problems with it.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eUsage\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eBy default it will bind to port 2021 and localhost to be able to be launched by user which can be changed via the command line option -p. The username password are your API Username and key.\u003c/p\u003e","title":"FTP server for Cloud Files"},{"content":"Last week I have posted an article explaining how to connect to Rackspace Cloud Files via Rackspace ServiceNET but I actually got it wrong as pointed by my great colleague exlt so I had to take it down until figured out how to fix it.\nI have add that feature properly to the PHP and Python API in version 1.5.0 to add a \u0026lsquo;servicenet\u0026rsquo; argument to the connection and updated the blog post here :\nhttps://blog.chmouel.com/2009/10/14/how-to-connect-to-rackspace-cloud-files-via-servicenet/\nIt should give you all the information for the howto use that feature.\nI have released as well a minor update in 1.5.1 to allow you to define the environment variable RACKSPACE_SERVICENET to force the use of the Rackspace ServiceNET this allow you to don\u0026rsquo;t have to modify the tools and have a clean code between prod and testing.\n","permalink":"https://blog.chmouel.com/2009/10/20/accessing-to-rackspace-cloud-files-via-servicenet-update/","summary":"\u003cp\u003eLast week I have posted an article explaining how to connect to Rackspace Cloud Files via Rackspace ServiceNET but I actually got it wrong as pointed by my great colleague \u003ca href=\"http://12.am/\"\u003eexlt\u003c/a\u003e so I had to take it down until figured out how to fix it.\u003c/p\u003e\n\u003cp\u003eI have add that feature properly to the PHP and Python API in version 1.5.0 to add a \u0026lsquo;servicenet\u0026rsquo; argument to the connection and updated the blog post here :\u003c/p\u003e","title":"Accessing to Rackspace Cloud Files via servicenet (update)"},{"content":"If you are a Rackspace customer and you are are planning to use Rackspace Cloud Files via it\u0026rsquo;s internal network (ServiceNet) so you don\u0026rsquo;t get billed for the bandwidth going over Cloud Files this is how you can do.\nThe first thing is to make sure with your support team if your servers are connected to ServiceNet and if you have that connection then there is a small change to do in your code.\nThe second thing is to use the just released 1.5.0 version on GitHUB for PHP :\nhttp://github.com/rackspace/php-cloudfiles/tree/1.5.0\nand for python :\nhttp://github.com/rackspace/python-cloudfiles/tree/1.5.0\n(you need to click on the download link at the top to download the tarball of the release).\nAfer this is just a matter to set the argument servicenet=True, for example in PHP :\n$user=\u0026#39;username\u0026#39;; $api_key=\u0026#39;theapi_key\u0026#39;; $auth = new CF_Authentication($user, $api_key); $auth-\u0026gt;authenticate(); $conn = new CF_Connection($auth, $servicenet=true); In Python you can do like this :\nusername=\u0026#39;username\u0026#39; api_key=\u0026#39;api_key\u0026#39; cnx = cloudfiles.get_connection(username, api_key, servicenet=True) ","permalink":"https://blog.chmouel.com/2009/10/14/how-to-connect-to-rackspace-cloud-files-via-servicenet/","summary":"\u003cp\u003e\u003c!-- raw HTML omitted --\u003eIf you are a Rackspace customer and you are are planning to use Rackspace Cloud Files via it\u0026rsquo;s internal network (ServiceNet) so you don\u0026rsquo;t get billed for the bandwidth going over Cloud Files this is how you can do.\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003cp\u003eThe first thing is to make sure with your support team if your servers are connected to ServiceNet and if you have that connection then there is a small change to do in your code.\u003c/p\u003e","title":"How to connect to Rackspace Cloud Files via ServiceNET"},{"content":" It\u0026rsquo;s really a collection of quickly written stuff put in the same file\nbut at least if not useful for you it would give you an idea how the\npython-cloudfiles works. It is all available here :\nhttp://github.com/chmouel/cloud-files-helper\n","permalink":"https://blog.chmouel.com/2009/09/24/rackspace-cloud-files-helper-scripts/","summary":"\u003c!-- raw HTML omitted --\u003e\n\u003cp\u003eIt\u0026rsquo;s really a collection of quickly written stuff put in the same file\u003cbr\u003e\nbut at least if not useful for you it would give you an idea how the\u003cbr\u003e\npython-cloudfiles works. It is all available here :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://github.com/chmouel/cloud-files-helper\"\u003ehttp://github.com/chmouel/cloud-files-helper\u003c/a\u003e\u003c/p\u003e","title":"Rackspace Cloud Files helper scripts"},{"content":"Emacs is playing fancy on the latest version (since emacs 23) it has now support for transparency at least on Linux when you have a composited Windows Manager.\nAs explained on the Emacs wiki here everything is controlled by this frame parameter like this :\n(set-frame-parameter (selected-frame) \u0026#39;alpha \u0026#39;(85 50)) I have automated the thing to allow the transparency to increase or decrease when combined with the alt key just put this code somewhere in your $HOME/.emacs or $HOME/.emacs.d/init.el :\n(defun my-increase-opacity() (interactive) (let ((increase (+ 10 (car (frame-parameter nil \u0026#39;alpha))))) (if (\u0026gt; increase 99)(setq increase 99)) (set-frame-parameter (selected-frame) \u0026#39;alpha (values increase 75))) ) (defun my-decrease-opacity() (interactive) (let ((decrease (- (car (frame-parameter nil \u0026#39;alpha)) 10))) (if (\u0026lt; decrease 20)(setq decrease 20)) (set-frame-parameter (selected-frame) \u0026#39;alpha (values decrease 75))) ) (global-set-key (kbd \u0026#34;M-\u0026lt;mouse-4\u0026gt;\u0026#34;) \u0026#39;my-increase-opacity) (global-set-key (kbd \u0026#34;M-\u0026lt;mouse -5\u0026gt;\u0026#34;) \u0026#39;my-decrease-opacity) \u0026lt;/mouse\u0026gt; ","permalink":"https://blog.chmouel.com/2009/09/16/emacs-and-transparency-mouse-wheel/","summary":"\u003cp\u003eEmacs is playing fancy on the latest version (since emacs 23) it has now support for transparency at least on Linux when you have a \u003ca href=\"http://en.wikipedia.org/wiki/Compositing_window_manager\"\u003ecomposited Windows Manager.\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eAs explained on the Emacs wiki \u003ca href=\"http://www.emacswiki.org/emacs/TransparentEmacs\"\u003ehere\u003c/a\u003e everything is controlled by this frame parameter like this :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-lisp\" data-lang=\"lisp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eset-frame-parameter\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eselected-frame\u003c/span\u003e) \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;alpha\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e\u0026#39;\u003c/span\u003e(\u003cspan style=\"color:#bd93f9\"\u003e85\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e50\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eI have automated the thing to allow the transparency to increase or decrease when combined with the alt key just put this code somewhere in your $HOME/.emacs or $HOME/.emacs.d/init.el :\u003c/p\u003e","title":"Emacs transparency with mouse wheel"},{"content":"It seems that there is no much documentation about how to do rsync like backup with duplicty so here it is :\nInstall python-cloudfiles from here http://github.com/rackspace/python-cloudfiles #!/bin/bash UPLOAD_TO_CONTAINER=\u0026#34;backup\u0026#34; #adjust it as you like export CLOUDFILES_USERNAME=Your Username export CLOUDFILES_APIKEY=API_KEY_YOU_GOT export PASSPHRASE=The Passphrase for your encrypted backup duplicity /full/path cf+http://${UPLOAD_TO_CONTAINER} This should take care to upload the backup files to the backup container. It does that incrementally and detect the changes to your file system to upload. There is much more option for duplicity look at the manpage for more info.\n","permalink":"https://blog.chmouel.com/2009/09/02/rsync-like-backup-to-rackspace-cloud-file-with-duplicity/","summary":"\u003cp\u003eIt seems that there is no much documentation about how to do rsync like backup with \u003c!-- raw HTML omitted --\u003eduplicty\u003c!-- raw HTML omitted --\u003e so here it is :\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eInstall python-cloudfiles from here \u003c!-- raw HTML omitted --\u003e\u003ca href=\"http://github.com/rackspace/python-cloudfiles\"\u003ehttp://github.com/rackspace/python-cloudfiles\u003c/a\u003e\u003c!-- raw HTML omitted --\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e#!/bin/bash\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eUPLOAD_TO_CONTAINER\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;backup\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#6272a4\"\u003e#adjust it as you like\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eCLOUDFILES_USERNAME\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003eYour Username\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eCLOUDFILES_APIKEY\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003eAPI_KEY_YOU_GOT\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ePASSPHRASE\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003eThe Passphrase \u003cspan style=\"color:#ff79c6\"\u003efor\u003c/span\u003e your encrypted backup\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eduplicity /full/path cf+http://\u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eUPLOAD_TO_CONTAINER\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThis should take care to upload the backup files to the backup container. It does that incrementally and detect the changes to your file system to upload. There is much more option for duplicity look at the manpage for more info.\u003c/p\u003e","title":"rsync like backup to Rackspace Cloud File with duplicity"},{"content":"After seeing this script http://overhrd.com/?p=106 which allow to upload files with the file manager (finder) of MacosX to Rackspace Cloud Files, I have made a nautilus script that doe the same for us Gnome/Unix users.\nAvailable here :\nhttp://github.com/chmouel/nautilus-rackspace-cloud-file/tree/master\n","permalink":"https://blog.chmouel.com/2009/09/02/upload-to-rackspace-cloud-files-from-gnome-nautilus/","summary":"\u003cp\u003eAfter seeing this script \u003ca href=\"http://overhrd.com/?p=106\"\u003ehttp://overhrd.com/?p=106\u003c/a\u003e which allow to upload files with the file manager (finder) of MacosX to Rackspace Cloud Files, I have made a nautilus script that doe the same for us Gnome/Unix users.\u003c/p\u003e\n\u003cp\u003eAvailable here :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://github.com/chmouel/nautilus-rackspace-cloud-file/tree/master\"\u003ehttp://github.com/chmouel/nautilus-rackspace-cloud-file/tree/master\u003c/a\u003e\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e","title":"Upload to Rackspace Cloud files from GNOME nautilus"},{"content":"One of the best feature to have with Emacs when doing python development is to have a real time syntax error/warning check highlighted in your code to avoid many errors or superfluous code.\nThis code is taken from the brillant Emacswiki python page.\nYou need to install pyflakes first which should be available on your linux distro by default in a package or for the other OS you may follow the procedure from the pyflakes webpage.\nand add this configuration to your .emacs :\n(when (load \u0026#34;flymake\u0026#34; t) (defun flymake-pyflakes-init () (let* ((temp-file (flymake-init-create-temp-buffer-copy \u0026#39;flymake-create-temp-inplace)) (local-file (file-relative-name temp-file (file-name-directory buffer-file-name)))) (list \u0026#34;pyflakes\u0026#34; (list local-file)))) (add-to-list \u0026#39;flymake-allowed-file-name-masks \u0026#39;(\u0026#34;\\\\.py\\\\\u0026#39;\u0026#34; flymake-pyflakes-init))) make sure pyflakes is in your path and enable flymake-mode by default if you like for all python mode :\n\u0026lt;br /\u0026gt; (add-hook 'python-mode-hook 'my-python-mode-hook)\ngo by M-x customize flymake as well if you like to customise some variables.\n","permalink":"https://blog.chmouel.com/2009/08/31/python-syntax-warning-in-emacs/","summary":"\u003cp\u003eOne of the best feature to have with Emacs when doing python development is to have a real time syntax error/warning check highlighted in your code to avoid many errors or superfluous code.\u003c/p\u003e\n\u003cp\u003eThis code is taken from the brillant Emacswiki \u003ca href=\"http://www.emacswiki.org/cgi-bin/wiki/PythonMode\"\u003epython page\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eYou need to install pyflakes first which should be available on your linux distro by default in a package or for the other OS you may follow the procedure from the \u003ca href=\"http://www.divmod.org/trac/wiki/DivmodPyflakes\"\u003epyflakes webpage\u003c/a\u003e.\u003c/p\u003e","title":"python syntax warning in emacs"},{"content":"It does not seems that emacs started with \u0026ndash;daemon read the .Xdefauls resource it seems that the only way setting it is by the default-frame-alist variable.\nI have my setup like this :\n(setq default-frame-alist \u0026#39;((font-backend . \u0026#34;xft\u0026#34;) (font . \u0026#34;Inconsolata-14\u0026#34;) (vertical-scroll-bars) (left-fringe . -1) (right-fringe . -1) (fullscreen . fullboth) (menu-bar-lines . 0) (tool-bar-lines . 0) )) PS: inconsolata font can be installed from the package ttf-inconsolata\n","permalink":"https://blog.chmouel.com/2009/08/11/emacs-daemon-and-xdefaults/","summary":"\u003cp\u003eIt does not seems that emacs started with \u0026ndash;daemon read the .Xdefauls resource it seems that the only way setting it is by the \u003cem\u003edefault-frame-alist\u003c/em\u003e variable.\u003c/p\u003e\n\u003cp\u003eI have my setup like this :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-lisp\" data-lang=\"lisp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#ff79c6\"\u003esetq\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003edefault-frame-alist\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e\u0026#39;\u003c/span\u003e((\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003efont-backend\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;xft\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003efont\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;Inconsolata-14\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003evertical-scroll-bars\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eleft-fringe\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e-1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eright-fringe\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e-1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003efullscreen\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003efullboth\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003emenu-bar-lines\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003etool-bar-lines\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            ))\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003ePS: inconsolata font can be installed from the package ttf-inconsolata\u003c/p\u003e","title":"emacs daemon and Xdefaults"},{"content":"So if you have network-manager not detecting wireless networks it is probably because lately the driver need to be set as up to get the thing going.\nOn my Debian I have added this to make it works :\necho \u0026quot;/sbin/ip link set wlan0 up\u0026quot;|sudo tee /etc/default/NetworkManager\n","permalink":"https://blog.chmouel.com/2009/08/10/network-manager-and-iwl3945-not-showing-network/","summary":"\u003cp\u003eSo if you have network-manager not detecting wireless networks it is probably because lately the driver need to be set as up to get the thing going.\u003c/p\u003e\n\u003cp\u003eOn my Debian I have added this to make it works :\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eecho \u0026quot;/sbin/ip link set wlan0 up\u0026quot;|sudo tee /etc/default/NetworkManager\u003c/code\u003e\u003c/p\u003e","title":"Network manager and iwl3945 not showing network"},{"content":"That weird output from sqlite3 command line is annoying you as well ? Just set this up to get something better :\ncat \u0026lt; \u0026lt;EOF\u0026gt;~/.sqliterc .mode \u0026#34;column\u0026#34; .headers on .explain on EOF ","permalink":"https://blog.chmouel.com/2009/07/16/better-output-from-sqlite3-command-line/","summary":"\u003cp\u003eThat weird output from sqlite3 command line is annoying you as well ? Just set this up to get something better :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecat \u0026lt; \u0026lt;EOF\u0026gt;~/.sqliterc\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e.mode \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;column\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e.headers on\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e.explain on\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eEOF\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Better output from sqlite3 command line"},{"content":"When you use the tags interface for Emacs or with VIM you have to generate your tag file everytime you have a new class or things get changed. Would not be cool to have inotify monitoring your project directory and run the etags command to generate it.\nWith incron you have cron that can watch some portion of the filesystem and generate an action if certain event appears. So after installed (aptitude/urpmi) it I have configured this incrontab entry :\n/home/chmouel/git/myproject IN_CLOSE_WRITE /home/chmouel/update-ctags.sh py $@ $@/$# The script update-ctags.sh takes 3 argument one is the type of file to update when it\u0026rsquo;s changed it accept multipe of them if you delimit with a pipe ie: py|inc|php|c and the two others are identifier from incron to give the base directory and the full path which is something you should not have to change.\nThe update-ctags is simple as follow which could be hacked for your convenience :\n#!/bin/bash ACCEPTED_EXTENSION=\u0026#34;$(echo $1|sed \u0026#39;s/|/ /g\u0026#39;)\u0026#34; BASE_DIR=$2 FILE_EXT=${3##*.} [[ -z ${FILE_EXT} ]] \u0026amp;\u0026amp; exit processing= for extension in $ACCEPTED_EXTENSION;do [[ $extension == $FILE_EXT ]] \u0026amp;\u0026amp; processing=true done find ${BASE_DIR} ! -wholename \u0026#39;./.git/*\u0026#39; -a ! -wholename \u0026#39;./.svn/*\u0026#39; -a ! -name \u0026#39;*.pyc\u0026#39; -a ! -name \u0026#39;*~\u0026#39; -a ! -name \u0026#39;*#\u0026#39; -print0| xargs -0 etags -o ${BASE_DIR}/TAGS 2\u0026gt;/dev/null \u0026gt;/dev/null ","permalink":"https://blog.chmouel.com/2009/07/03/update-emacsvim-tags-with-inotify/","summary":"\u003cp\u003eWhen you use the tags interface for \u003ca href=\"http://www.emacswiki.org/emacs/EmacsTags\"\u003eEmacs\u003c/a\u003e or with \u003ca href=\"http://www.vim.org/htmldoc/tagsrch.html#tags\"\u003eVIM\u003c/a\u003e you have to generate your tag file everytime you have a new class or things get changed.  Would not be cool to have inotify monitoring your project directory and run the etags command to generate it.\u003c/p\u003e\n\u003cp\u003eWith \u003ca href=\"http://inotify.aiken.cz/?section=incron\u0026amp;page=doc\u0026amp;lang=en\"\u003eincron\u003c/a\u003e you have cron that can watch some portion of the filesystem and generate an action if certain event appears.  So after installed (aptitude/urpmi) it I have configured this incrontab entry :\u003c/p\u003e","title":"Update Emacs/VIM tags with inotify"},{"content":"So if you get that shiny new Dell desktop and ACPI spit bunch of message at the install time and the network driver does not get detected you can follow these steps to have it working.\nContinue the install without the network until you reboot to grub.\nAdd hpet=disable at the end of the boot kernel parameter and get into the system.\nDownload the latest kernel for your architecture on :\nhttp://kernel-archive.buildserver.net/debian-kernel/pool/main/l/linux-2.6/\nTransfer it on a USB key and dpkg -i it.\nMake sure you add the hpet=disable at the kopt option of /boot/grub/menu.lst and launch a update-grub.\nOn reboot you should now have the network you can do the standard tasksel to install a Desktop etc\u0026hellip;.\n","permalink":"https://blog.chmouel.com/2009/06/16/debian-lenny-on-dell-optiflex-760/","summary":"\u003cp\u003eSo if you get that shiny new Dell desktop and ACPI spit bunch of message at the install time and the network driver does not get detected you can follow these steps to have it working.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eContinue the install without the network until you reboot to grub.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eAdd hpet=disable at the end of the boot kernel parameter and get into the system.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDownload the latest kernel for your architecture on :\u003c/p\u003e","title":"Debian Lenny on Dell Optiplex 760"},{"content":"Since I always forget stuff like this. This is the SQL query to detect mysql table schemas type (thanks to Darren.B) :\nSELECT table_name, table_schema, table_type, engine FROM information_schema.tables where table_schema not in (\u0026#39;information_schema\u0026#39;, \u0026#39;mysql\u0026#39;); ","permalink":"https://blog.chmouel.com/2009/05/11/what-type-of-mysql-table-schemas/","summary":"\u003cp\u003eSince I always forget stuff like this. This is the SQL query to detect mysql table schemas type (thanks to Darren.B) :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eSELECT\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003etable_name\u003c/span\u003e, table_schema, table_type, engine \u003cspan style=\"color:#ff79c6\"\u003eFROM\u003c/span\u003e information_schema.tables \u003cspan style=\"color:#ff79c6\"\u003ewhere\u003c/span\u003e table_schema \u003cspan style=\"color:#ff79c6\"\u003enot\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003ein\u003c/span\u003e (\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;information_schema\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;mysql\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"What type of MySQL table schemas"},{"content":"So at work we have to use a bastion host for all our connections to servers to be able to get called PCI compliant. This kind of stuff could be a pain to use when you have to use another host to do RSYNC/SCP or other stuff that need direct transfer to workstation.\nThankfully OpenSSH is very flexible and have multiple options to easy the pain. If you add this to your ~/.ssh/config :\nHost bastion\nHostname IP_ADDRESS_OF_BASTION_SERVER\nUser YOUR_USERNAME\nProxyCommand none\nControlMaster auto\nControlPath ~/.ssh/master-%r@%h:%p\nHost *\nProxyCommand ssh -qax bastion \u0026rsquo;nc -w 600 %h %p'\nThis will allow you to pass all SSH requests to the bastion server.\nI have experimented with different options and this seems to be most efficient way. The ControlMaster ControlPath is to speed up the connections by not reopening a tcp socket all the time to the bastion server. This seems to cause problems with the OpenSSH version shipped with some distros (ie: Fedora) so you may want to remove it if you experience problems. For the ProxyCommand there is way to use cat like this :\nProxyCommand ssh bastion \u0026rsquo;exec 3\u0026lt;\u0026gt;/dev/tcp/%h/22;(cat \u0026lt;\u0026amp;3 \u0026amp; );cat \u0026gt;\u0026amp;3'\nbut the cat processes seems to hang in memory on the bastion server so netcat seems a better option. I heard that tcpconnect from the tcputils package should make things smoother but I haven\u0026rsquo;t tried that.\nI have other options in my SSH configuration to allow to be less verbose see ssh_config(5) manpage for detailed description of each of these options :\nHost *\nForwardAgent yes\nGSSAPIAuthentication no\nVerifyHostKeyDNS no\nStrictHostKeyChecking no\nHashKnownHosts no\nTCPKeepAlive yes\nServerAliveInterval 600\nBy the way forgot to mention you would need to have SSH key exchange configured with the bastion server with a SSH agent runing (these days all distros should do that by default) to don\u0026rsquo;t have to type the password of your username on bastion server.\nI have heard there is way to do that on Windows with putty and plink but I haven\u0026rsquo;t tried that see this post here about it.\n","permalink":"https://blog.chmouel.com/2009/02/08/proxycommand-ssh-bastion-proxy/","summary":"\u003cp\u003eSo at work we have to use a \u003c!-- raw HTML omitted --\u003ebastion host\u003c!-- raw HTML omitted --\u003e for all our connections to servers to be able to get called \u003ca href=\"http://www.pcicomplianceguide.org/\"\u003ePCI\u003c/a\u003e compliant. This kind of stuff could be a pain to use when you have to use another host to do RSYNC/SCP or other stuff that need direct transfer to workstation.\u003c/p\u003e\n\u003cp\u003eThankfully OpenSSH is very flexible and have multiple options to easy the pain. If you add this to your ~/.ssh/config :\u003c/p\u003e","title":"Using ProxyCommand with OpenSSH and a Bastion server."},{"content":"If you want to bookmark a quick mozilla search from your house to another postcode you can use this URI :\nhttp://journeyplanner.tfl.gov.uk/user/XSLT_TRIP_REQUEST2?language=en\u0026amp;sessionID=0\u0026amp;type_destination=locator\u0026amp;name_destination=DESTINATION_POSTCODE\u0026amp;type_origin=locator\u0026amp;name_origin=ORIGIN_POSTCODE\u0026amp;place_origin=London\u0026amp;place_destination=London\njust change the DESTINATION and ORIGIN_POSTCODE to %s if you like or make it as static bookmark.\n","permalink":"https://blog.chmouel.com/2008/07/29/tflgovuk-and-mozilla-quick-search/","summary":"\u003cp\u003eIf you want to bookmark a  quick mozilla search from your house to another postcode you can use this URI :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://journeyplanner.tfl.gov.uk/user/XSLT\"\u003ehttp://journeyplanner.tfl.gov.uk/user/XSLT\u003c/a\u003e_TRIP_REQUEST2?language=en\u0026amp;sessionID=0\u0026amp;type_destination=locator\u0026amp;name_destination=DESTINATION_POSTCODE\u0026amp;type_origin=locator\u0026amp;name_origin=ORIGIN_POSTCODE\u0026amp;place_origin=London\u0026amp;place_destination=London\u003c/p\u003e\n\u003cp\u003ejust change the DESTINATION and ORIGIN_POSTCODE to %s if you like or make it as static bookmark.\u003c/p\u003e","title":"TFL.GOV.UK and mozilla quick search"},{"content":"If you want to use FFAP (find-file-at-point) in ruby-mode you can add this to your .emacs\n(defvar ruby-program-name \u0026#34;ruby\u0026#34;) (defun ruby-module-path(module) (shell-command-to-string (concat ruby-program-name \u0026#34; -e \u0026#34; \u0026#34;\\\u0026#34;ret=\u0026#39;()\u0026#39;;$LOAD_PATH.each{|p| \u0026#34; \u0026#34;x=p+\u0026#39;/\u0026#39;+ARGV[0].gsub(\u0026#39;.rb\u0026#39;, \u0026#39;\u0026#39;)+\u0026#39;.rb\u0026#39;;\u0026#34; \u0026#34;ret=File.expand_path(x)\u0026#34; \u0026#34;if(File.exist?(x))};printf ret\\\u0026#34; \u0026#34; module))) (eval-after-load \u0026#34;ffap\u0026#34; \u0026#39;(push \u0026#39;(ruby-mode . ruby-module-path) ffap-alist)) When you do ffap (i bind it to C-x f) near a require \u0026lsquo;PP\u0026rsquo; for example it will find it in your ruby path.\n","permalink":"https://blog.chmouel.com/2008/05/04/ffap-and-ruby-in-emacs/","summary":"\u003cp\u003eIf you want to use FFAP (find-file-at-point) in ruby-mode you can add this to your .emacs\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-ruby\" data-lang=\"ruby\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(defvar ruby\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003eprogram\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ename\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;ruby\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(defun ruby\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003emodule\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003epath(module)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    (shell\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003ecommand\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003eto\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003estring\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     (concat\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      ruby\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003eprogram\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ename\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34; -e \u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\\\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003eret=\u0026#39;()\u0026#39;;$LOAD_PATH.each{|p| \u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;x=p+\u0026#39;/\u0026#39;+ARGV[0].gsub(\u0026#39;.rb\u0026#39;, \u0026#39;\u0026#39;)+\u0026#39;.rb\u0026#39;;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;ret=File.expand_path(x)\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;if(File.exist?(x))};printf ret\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\\\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e \u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      module)))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eeval\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003eafter\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eload\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;ffap\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;(push \u0026#39;\u003c/span\u003e(ruby\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003emode \u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003e ruby\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003emodule\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003epath) ffap\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003ealist))\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eWhen you do ffap (i bind it to C-x f) near a require \u0026lsquo;PP\u0026rsquo; for example it will find it in your ruby path.\u003c/p\u003e","title":"FFAP and Ruby in Emacs"},{"content":"If you use the XMLRPC client in ruby over a self certified SSL you have this warning :\nwarning: peer certificate won\u0026rsquo;t be verified in this SSL session\nYou can get override that warning cleanly (i have seen some people who just comment the message in the standard library) like that :\nrequire \u0026#39;xmlrpc/client\u0026#39; require \u0026#39;net/https\u0026#39; require \u0026#39;openssl\u0026#39; require \u0026#39;pp\u0026#39; module SELF_SSL class Net_HTTP \u0026lt; Net::HTTP def initialize(*args) super @ssl_context = OpenSSL::SSL::SSLContext.new @ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE end end class XMLRPC_Client \u0026lt; XMLRPC::Client def initialize(*args) super @http = SELF_SSL::Net_HTTP.new( @host, @port, @proxy_host,@proxy_port ) @http.use_ssl = @use_ssl if @use_ssl @http.read_timeout = @timeout @http.open_timeout = @timeout end end end if __FILE__ == $0 f = SELF_SSL::XMLRPC_Client.new2(\u0026#34;https://url\u0026#34;) puts f.call(\u0026#34;method\u0026#34;, \u0026#39;arg\u0026#39;) end ","permalink":"https://blog.chmouel.com/2008/03/21/ruby-xmlrpc-over-a-self-certified-ssl-with-a-warning/","summary":"\u003cp\u003eIf you use the XMLRPC client in ruby over a self certified SSL you have this warning :\u003c/p\u003e\n\u003cp\u003e\u003cem\u003ewarning: peer certificate won\u0026rsquo;t be verified in this SSL session\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eYou can get override that warning cleanly (i have seen some people who just comment the message in the standard library) like that :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-ruby\" data-lang=\"ruby\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003erequire\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;xmlrpc/client\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003erequire\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;net/https\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003erequire\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;openssl\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003erequire\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;pp\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003emodule\u003c/span\u003e SELF_SSL\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ff79c6\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#50fa7b\"\u003eNet_HTTP\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e\u0026lt;\u003c/span\u003e Net\u003cspan style=\"color:#ff79c6\"\u003e::\u003c/span\u003eHTTP\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ff79c6\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#50fa7b\"\u003einitialize\u003c/span\u003e(\u003cspan style=\"color:#ff79c6\"\u003e*\u003c/span\u003eargs)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#ff79c6\"\u003esuper\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@ssl_context\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e OpenSSL\u003cspan style=\"color:#ff79c6\"\u003e::\u003c/span\u003eSSL\u003cspan style=\"color:#ff79c6\"\u003e::\u003c/span\u003eSSLContext\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003enew\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@ssl_context\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003everify_mode \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e OpenSSL\u003cspan style=\"color:#ff79c6\"\u003e::\u003c/span\u003eSSL\u003cspan style=\"color:#ff79c6\"\u003e::\u003c/span\u003eVERIFY_NONE\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ff79c6\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ff79c6\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ff79c6\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#50fa7b\"\u003eXMLRPC_Client\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e\u0026lt;\u003c/span\u003e XMLRPC\u003cspan style=\"color:#ff79c6\"\u003e::\u003c/span\u003eClient\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ff79c6\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#50fa7b\"\u003einitialize\u003c/span\u003e(\u003cspan style=\"color:#ff79c6\"\u003e*\u003c/span\u003eargs)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#ff79c6\"\u003esuper\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@http\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e SELF_SSL\u003cspan style=\"color:#ff79c6\"\u003e::\u003c/span\u003eNet_HTTP\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003enew( \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@host\u003c/span\u003e, \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@port\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                      \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@proxy_host\u003c/span\u003e,\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@proxy_port\u003c/span\u003e )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@http\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003euse_ssl \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@use_ssl\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003eif\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@use_ssl\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@http\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003eread_timeout \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@timeout\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@http\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003eopen_timeout \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e@timeout\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ff79c6\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#ff79c6\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eif\u003c/span\u003e \u003cspan style=\"font-style:italic\"\u003e__FILE__\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  f \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e SELF_SSL\u003cspan style=\"color:#ff79c6\"\u003e::\u003c/span\u003eXMLRPC_Client\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003enew2(\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;https://url\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eputs\u003c/span\u003e f\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003ecall(\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;method\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;arg\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Ruby XMLRPC over a Self Certified SSL with a warning"},{"content":"While talking with my fellow colleague Darren Birkett about what seems a design limitation\nof yum to not be able to force listing the excludes from yum. I had a\nshoot to make a yum plugin to force listing the excludes.\nHere is how it works :\nroot@centos5:\u0026gt; grep exclude /etc/yum.conf\nexclude=rpm*\nroot@centos5:\u0026gt; yum install rpm-devel\nLoading \u0026ldquo;installonlyn\u0026rdquo; plugin\nLoading \u0026ldquo;changelog\u0026rdquo; plugin\nLoading \u0026ldquo;chmouel\u0026rdquo; plugin\nLoading \u0026ldquo;priorities\u0026rdquo; plugin\nSetting up Install Process\nSetting up repositories\nReading repository metadata in from local files\nExcluding Packages in global exclude list\nFinished\n0 packages excluded due to repository priority protections\nParsing package install arguments\nNothing to do\nrpm* is excluded, but if we use the environment variable FORCE_EXCLUDE\nit will force it.\nroot@centos5:~\u0026gt; FORCE_EXCLUDE=true yum install rpm-devel\nLoading \u0026ldquo;installonlyn\u0026rdquo; plugin\nLoading \u0026ldquo;changelog\u0026rdquo; plugin\nLoading \u0026ldquo;chmouel\u0026rdquo; plugin\nLoading \u0026ldquo;priorities\u0026rdquo; plugin\nSetting up Install Process\nSetting up repositories\nReading repository metadata in from local files\n0 packages excluded due to repository priority protections\nParsing package install arguments\nResolving Dependencies\n\u0026ndash;\u0026gt; Populating transaction set with selected packages. Please wait.\n-\u0026ndash;\u0026gt; Downloading header for rpm-devel to pack into transaction set.\nrpm-devel-4.4.2-47.el5.i3 100% |=========================| 17 kB 00:00\n-\u0026ndash;\u0026gt; Package rpm-devel.i386 0:4.4.2-47.el5 set to be updated\n\u0026ndash;\u0026gt; Running transaction check\n[\u0026hellip;..]\nIt will allow you to list the excluded rpm as well :\nroot@centos5:\u0026gt; FORCE_EXCLUDE=true yum list|grep rpm\nrpm.i386 4.4.2-47.el5 installed\nrpm-libs.i386 4.4.2-47.el5 installed\nrpm-python.i386 4.4.2-47.el5 installed\nredhat-rpm-config.noarch 8.0.45-22.el5.centos base\nrpm-build.i386 4.4.2-47.el5 base\nrpm-devel.i386 4.4.2-47.el5 base\nroot@centos5:\u0026gt; yum list|grep rpm\nrpm.i386 4.4.2-47.el5 installed\nrpm-libs.i386 4.4.2-47.el5 installed\nrpm-python.i386 4.4.2-47.el5 installed\nredhat-rpm-config.noarch 8.0.45-22.el5.centos base\nSee the README.txt in the rpm file to see how to use/install it.\nYou can download the rpm here and the src.rpm here\n","permalink":"https://blog.chmouel.com/2008/03/20/yum-force-exclude-list/","summary":"\u003cp\u003eWhile talking with my fellow colleague Darren Birkett about what seems a design limitation\u003cbr\u003e\nof yum to not be able to force listing the excludes from yum. I had a\u003cbr\u003e\nshoot to make a yum plugin to force listing the excludes.\u003c/p\u003e\n\u003cp\u003eHere is how it works :\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eroot@centos5:\u003cdel\u003e\u0026gt; grep exclude /etc/yum.conf\u003cbr\u003e\nexclude=rpm*\u003cbr\u003e\nroot@centos5:\u003c/del\u003e\u0026gt; yum install rpm-devel\u003cbr\u003e\nLoading \u0026ldquo;installonlyn\u0026rdquo; plugin\u003cbr\u003e\nLoading \u0026ldquo;changelog\u0026rdquo; plugin\u003cbr\u003e\nLoading \u0026ldquo;chmouel\u0026rdquo; plugin\u003cbr\u003e\nLoading \u0026ldquo;priorities\u0026rdquo; plugin\u003cbr\u003e\nSetting up Install Process\u003cbr\u003e\nSetting up repositories\u003cbr\u003e\nReading repository metadata in from local files\u003cbr\u003e\nExcluding Packages in global exclude list\u003cbr\u003e\nFinished\u003cbr\u003e\n0 packages excluded due to repository priority protections\u003cbr\u003e\nParsing package install arguments\u003cbr\u003e\nNothing to do\u003c/p\u003e","title":"Yum Force Exclude List"},{"content":"To anyone interested my extensive Emacs configuration is available here :\nhttp://code.google.com/p/chmouel/source\nAnd here is the usual screen shot :\n","permalink":"https://blog.chmouel.com/2007/09/07/emacs-config/","summary":"\u003cp\u003eTo anyone interested my extensive Emacs configuration is available here :\u003c/p\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003ca href=\"http://code.google.com/p/chmouel/source\"\u003ehttp://code.google.com/p/chmouel/source\u003c/a\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003cp\u003eAnd here is the usual screen shot :\u003c/p\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e","title":"Emacs config"},{"content":"This is fun, theses two CEO of theses big companies are dog fighting each others :\nDave post:\nhttp://blogs.netapp.com/dave/2007/09/netapp-sues-sun.html\nJohanthan answer:\nhttp://blogs.sun.com/jonathan/entry/on_patent_trolling\nbut the real (fake) truth about that post is here :\nhttp://fakeschwartz.blogspot.com/2007/09/bring-it-cowboy.html\nI tend to believe more NetAPP in this case, just because i don\u0026rsquo;t know how many time i have sweared on that bloody ps -aux that does not work on solaris.\n","permalink":"https://blog.chmouel.com/2007/09/07/netapp-sue-sun/","summary":"\u003cp\u003eThis is fun, theses two CEO of theses big companies are dog fighting each others :\u003c/p\u003e\n\u003cp\u003eDave post:\u003c/p\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003ca href=\"http://blogs.netapp.com/dave/2007/09/netapp-sues-sun.html\"\u003ehttp://blogs.netapp.com/dave/2007/09/netapp-sues-sun.html\u003c/a\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003cp\u003eJohanthan answer:\u003c/p\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003e\u003ca href=\"http://blogs.sun.com/jonathan/entry/on_patent_trolling\"\u003ehttp://blogs.sun.com/jonathan/entry/on_patent_trolling\u003c/a\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003cp\u003ebut the real (fake) truth about that post is here :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://fakeschwartz.blogspot.com/2007/09/bring-it-cowboy.html\" title=\"http://fakeschwartz.blogspot.com/2007/09/bring-it-cowboy.html\"\u003ehttp://fakeschwartz.blogspot.com/2007/09/bring-it-cowboy.html\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eI tend to believe more NetAPP in this case, just because i don\u0026rsquo;t know how many time i have sweared on that bloody ps -aux that does not work on solaris.\u003c/p\u003e","title":"Netapp sue Sun"},{"content":"If you want to generate properly encrypted password to feed to chpasswd, the most easier and proper way is to do that from command line :\n[code lang=\u0026ldquo;bash\u0026rdquo;]\necho \u0026ldquo;encryptedpassword\u0026rdquo;|openssl passwd -1 -stdin\n[/code]\nIf you want to generate in pure python you can do it like that :\n[code lang=\u0026ldquo;python\u0026rdquo;]\ndef md5crypt(password, salt, magic=\u0026rsquo;$1$\u0026rsquo;):\nimport md5\nm = md5.new()\nm.update(password + magic + salt)\n# /* Then just as many characters of the MD5(pw,salt,pw) */\nmixin = md5.md5(password + salt + password).digest()\nfor i in range(0, len(password)):\nm.update(mixin[i % 16])\n# /* Then something really weird\u0026hellip; */\n# Also really broken, as far as I can tell. -m\ni = len(password)\nwhile i:\nif i \u0026amp; 1:\nm.update(\u0026lsquo;x00\u0026rsquo;)\nelse:\nm.update(password[0])\ni \u0026raquo;= 1\nfinal = m.digest()\n# /* and now, just to make sure things don\u0026rsquo;t run too fast */\nfor i in range(1000):\nm2 = md5.md5()\nif i \u0026amp; 1:\nm2.update(password)\nelse:\nm2.update(final)\nif i % 3:\nm2.update(salt)\nif i % 7:\nm2.update(password)\nif i \u0026amp; 1:\nm2.update(final)\nelse:\nm2.update(password)\nfinal = m2.digest()\n# This is the bit that uses to64() in the original code.\nitoa64 = \u0026lsquo;./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\u0026rsquo;\nrearranged = \u0026rsquo;\u0026rsquo;\nfor a, b, c in ((0, 6, 12), (1, 7, 13), (2, 8, 14), (3, 9, 15), (4, 10, 5)):\nv = ord(final[a]) \u0026lt; \u0026lt; 16 | ord(final[b]) \u0026laquo; 8 | ord(final[c]) for i in range(4): rearranged += itoa64[v \u0026amp; 0x3f]; v \u0026raquo;= 6\nv = ord(final[11])\nfor i in range(2):\nrearranged += itoa64[v \u0026amp; 0x3f]; v \u0026raquo;= 6\nreturn magic + salt + \u0026lsquo;$\u0026rsquo; + rearranged\n[/code]\nYou need to feed it up with a salt, like this :\n[code lang=\u0026ldquo;python\u0026rdquo;]\ndef generate_salt(count):\nimport random, string\nchar = string.ascii_letters + string.digits + string.punctuation.replace(\u0026rsquo;:\u0026rsquo;, \u0026lsquo;\u0026rsquo;)\nreturn string.join(map(lambda x,v=char: random.choice(v), range(count)), \u0026lsquo;\u0026rsquo;)\n[/code]\n","permalink":"https://blog.chmouel.com/2007/08/17/generating-md5-encrypted-password-for-chpasswd/","summary":"\u003cp\u003eIf you want to generate properly encrypted password to feed to chpasswd, the most easier and proper way is to do that from command line :\u003cbr\u003e\n[code lang=\u0026ldquo;bash\u0026rdquo;]\u003cbr\u003e\necho \u0026ldquo;encryptedpassword\u0026rdquo;|openssl passwd -1 -stdin\u003cbr\u003e\n[/code]\u003cbr\u003e\nIf you want to generate in pure python you can do it like that :\u003cbr\u003e\n[code lang=\u0026ldquo;python\u0026rdquo;]\u003cbr\u003e\ndef md5crypt(password, salt, magic=\u0026rsquo;$1$\u0026rsquo;):\u003cbr\u003e\nimport md5\u003cbr\u003e\nm = md5.new()\u003cbr\u003e\nm.update(password + magic + salt)\u003c/p\u003e\n\u003cp\u003e# /* Then just as many characters of the MD5(pw,salt,pw) */\u003cbr\u003e\nmixin = md5.md5(password + salt + password).digest()\u003cbr\u003e\nfor i in range(0, len(password)):\u003cbr\u003e\nm.update(mixin[i % 16])\u003c/p\u003e","title":"Generating md5 encrypted password for chpasswd"},{"content":"If you like me you have a big screen with your laptop and wants to automate when your X session start to get the best resolution, you can use that script :\n[code lang=\u0026ldquo;bash\u0026rdquo;]\n#!/bin/bash\nfunction get_resolutions() {\nxrandr|while read -a line;do\nRES=\u0026quot;${line[1]}x${line[3]} \u0026quot;\n[[ ${RES} != [0-9]* ]] \u0026amp;\u0026amp; continue\necho ${RES}\ndone\n}\n_BEST_RES=0\nBEST_RES=\nfor res in $(get_resolutions);do\n_res=${res/x/}\n[[ $_res -ge ${_BEST_RES} ]] \u0026amp;\u0026amp; {\nBEST_RES=${res}\n_BEST_RES=${_res}\n}\ndone\nxrandr -s ${BEST_RES}\n[/code]\n","permalink":"https://blog.chmouel.com/2007/07/31/automatic-best-resolution-with-xrandr/","summary":"\u003cp\u003eIf you like me you have a big screen with your laptop and wants to automate when your X session start to get the best resolution, you can use that script :\u003c/p\u003e\n\u003cp\u003e[code lang=\u0026ldquo;bash\u0026rdquo;]\u003cbr\u003e\n#!/bin/bash\u003c/p\u003e\n\u003cp\u003efunction get_resolutions() {\u003cbr\u003e\nxrandr|while read -a line;do\u003cbr\u003e\nRES=\u0026quot;${line[1]}x${line[3]} \u0026quot;\u003cbr\u003e\n[[ ${RES} != [0-9]* ]] \u0026amp;\u0026amp; continue\u003cbr\u003e\necho ${RES}\u003cbr\u003e\ndone\u003cbr\u003e\n}\u003c/p\u003e\n\u003cp\u003e_BEST_RES=0\u003cbr\u003e\nBEST_RES=\u003cbr\u003e\nfor res in $(get_resolutions);do\u003cbr\u003e\n_res=${res/x/}\u003cbr\u003e\n[[ $_res -ge ${_BEST_RES} ]] \u0026amp;\u0026amp; {\u003cbr\u003e\nBEST_RES=${res}\u003cbr\u003e\n_BEST_RES=${_res}\u003cbr\u003e\n}\u003cbr\u003e\ndone\u003cbr\u003e\nxrandr -s ${BEST_RES}\u003cbr\u003e\n[/code]\u003c/p\u003e","title":"Automatic best resolution with xrandr"},{"content":"If you like me, you have to do a lot of installs1 of the same test machine with the same IP and have to ssh it you will notice this annoying message :\nIT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that the RSA host key has just been changed. The fingerprint for the RSA key sent by the remote host is 54:9d:c0:37:3a:80:48:6c:82:ec:d1:84:93:61:24. Please contact your system administrator. Add correct host key in /home/cboudjnah/.ssh/known_hosts to get rid of this message. Offending key in /home/cboudjnah/.ssh/known_hosts:595 Password authentication is disabled to avoid man-in-the-middle attacks. Keyboard-interactive authentication is disabled to avoid man-in-the-middle attacks. Agent forwarding is disabled to avoid man-in-the-middle attacks. I have automated the cleanup by a script :\n[code lang=\u0026ldquo;bash\u0026rdquo;]\n#!/bin/bash\nH=$1\n[[ -z ${H} ]] \u0026amp;\u0026amp; { echo \u0026ldquo;Need a host as argument\u0026rdquo;; exit 1 ;}\nLINE=$(ssh -o StrictHostKeyChecking=yes $1 \u0026rsquo;exit\u0026rsquo; 2\u0026gt;\u0026amp;1 | sed -n \u0026lsquo;/Offending key/ { s/.*://;s/r//;p }\u0026rsquo;)\n[[ -z ${LINE} ]] \u0026amp;\u0026amp; { echo \u0026ldquo;Nothing to clean\u0026rdquo;; exit; }\nsed -i -n \u0026ldquo;$LINE!p\u0026rdquo; ~/.ssh/known_hosts[/code]\n1 Like having to tests bunch of FAI.\n","permalink":"https://blog.chmouel.com/2007/05/30/automate-ssh-known_hosts-cleanup/","summary":"\u003cp\u003eIf you like me, you have to do a lot of installs\u003ca href=\"http://www.informatik.uni-koeln.de/fai/\"\u003e1\u003c/a\u003e of the same test machine with the same IP and have to ssh it you will notice this annoying message :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eIT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSomeone could be eavesdropping on you right now (man-in-the-middle attack)!\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eIt is also possible that the RSA host key has just been changed.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eThe fingerprint for the RSA key sent by the remote host is\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e54:9d:c0:37:3a:80:48:6c:82:ec:d1:84:93:61:24.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePlease contact your system administrator.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAdd correct host key in /home/cboudjnah/.ssh/known_hosts\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eto get rid of this message.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eOffending key in /home/cboudjnah/.ssh/known_hosts:595\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePassword authentication is disabled to avoid\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e man-in-the-middle attacks.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eKeyboard-interactive authentication is disabled to avoid\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eman-in-the-middle attacks.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAgent forwarding is disabled to avoid man-in-the-middle attacks.\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eI have automated the cleanup by a script :\u003cbr\u003e\n[code lang=\u0026ldquo;bash\u0026rdquo;]\u003cbr\u003e\n#!/bin/bash\u003cbr\u003e\nH=$1\u003c/p\u003e","title":"Automate SSH known_hosts cleanup"},{"content":"Pretty good video to look if you like to know more about git and its creation :\nhttp://www.youtube.com/watch?v=4XpnKHJAok8\n","permalink":"https://blog.chmouel.com/2007/05/29/linus-torvalds-on-git/","summary":"\u003cp\u003ePretty good video to look if you like to know more about git and its creation :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://www.youtube.com/watch?v=4XpnKHJAok8\"\u003ehttp://www.youtube.com/watch?v=4XpnKHJAok8\u003c/a\u003e\u003c/p\u003e","title":"Linus Torvalds on GIT"},{"content":"This is a annoying, even if it take 5mn to code thing like that :\n(defun my-dired-rm-rf() \u0026#34;Rm -rf directories\u0026#34; (interactive) (let ((sel (selected-window))) (dolist (curFile (dired-get-marked-files)) (if (yes-or-no-p (concat \u0026#34;Do you want to remove \\\u0026#34;\u0026#34; (file-name-nondirectory curFile) \u0026#34;\\\u0026#34; ? \u0026#34;)) (progn (shell-command (concat \u0026#34;rm -rvf \u0026#34; curFile) \u0026#34;*Removing Directories*\u0026#34;) (kill-buffer \u0026#34;*Removing Directories*\u0026#34;) (select-window sel) (revert-buffer) ) )) )) you discover after a litlle while that if you have did a lilt bit of searching before, you will have discovered a variable call `dired-recursive-deletes` that would do the thing in a much better way.\n","permalink":"https://blog.chmouel.com/2007/02/11/always-search-before-coding/","summary":"\u003cp\u003eThis is a annoying, even if it take 5mn to code thing like that :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-lisp\" data-lang=\"lisp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003edefun\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003emy-dired-rm-rf\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;Rm -rf directories\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003einteractive\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  (\u003cspan style=\"color:#ff79c6\"\u003elet\u003c/span\u003e ((\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003esel\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eselected-window\u003c/span\u003e)))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003edolist\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ecurFile\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003edired-get-marked-files\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t  (\u003cspan style=\"color:#ff79c6\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#50fa7b\"\u003eyes-or-no-p\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003econcat\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;Do you want to remove \\\u0026#34;\u0026#34;\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003efile-name-nondirectory\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ecurFile\u003c/span\u003e) \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\\\u0026#34; ? \u0026#34;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t  (\u003cspan style=\"color:#ff79c6\"\u003eprogn\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\t(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eshell-command\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003econcat\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;rm -rvf \u0026#34;\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ecurFile\u003c/span\u003e) \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;*Removing Directories*\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\t(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ekill-buffer\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;*Removing Directories*\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\t(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eselect-window\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003esel\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\t(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003erevert-buffer\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\t)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t))\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eyou discover after a litlle while that if you have did a lilt bit of searching before, you will have discovered a variable call \u003cstrong\u003e`dired-recursive-deletes`\u003c/strong\u003e that would do the thing in a much better way.\u003c/p\u003e","title":"Always search before coding"},{"content":"Renaming Oracle Database is a pain, coming from OpenSource DB like\nMySQL or PostGres where we do that all the time i did not think that\nOracle have to be such a pain.\nMy only way i can find.\nIf i have the tablespace named tablesp1 and owned by the\nuser user1, and i want to import it to another tablespace\ncalled tablesp2 in an another Oracle 9i tablespace with the user\nname user2.\nI import the tablesp1 in an Oracle 10 (if you are lucky to have\none). Make sure i create the user2 in the Oracle10 DB. I connect as DBA access and i rename the tablespace with :\n[code lang=\u0026ldquo;sql\u0026rdquo;]\nALTER TABLESPACE tablesp1 RENAME TO tablesp2\nALTER TABLESPACE tablesp2 OWNER TO user2\n[/code] Export the Oracle10 tablespace with Oracle 9 exp.\nSometime sometime you may encounter that famous error \u0026lt;i\u0026gt;\u0026#34;EXP-00003 : no storage definition found for segment .....\u0026#34;\u0026lt;/i\u0026gt;. So you have have to do [this][1] as well. \u0026lt;/li\u0026gt; * That's it. The dump should be under tablespace name tablesp2 with owner user2. \u0026lt;/ul\u0026gt; ","permalink":"https://blog.chmouel.com/2007/02/07/import-export-to-different-tablespace-names-with-oracle-9i/","summary":"\u003cp\u003eRenaming Oracle Database is a pain, coming from OpenSource DB like\u003cbr\u003e\nMySQL or PostGres where we do that all the time i did not think that\u003cbr\u003e\nOracle have to be such a pain.\u003c/p\u003e\n\u003cp\u003eMy only way i can find.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIf i have the tablespace named \u003cstrong\u003etablesp1\u003c/strong\u003e and owned by the\u003cbr\u003e\nuser \u003cstrong\u003euser1\u003c/strong\u003e, and i want to import it to another tablespace\u003cbr\u003e\ncalled \u003cstrong\u003etablesp2\u003c/strong\u003e in an another Oracle 9i tablespace with the user\u003cbr\u003e\nname \u003cstrong\u003euser2\u003c/strong\u003e.\u003c/p\u003e","title":"Import Export to different tablespace names with Oracle 9i"},{"content":"A useful svn wrapper scripts. Get a diff of your local repostitory against the upstream repository changes. I wonder why it is not builtins though like a svn status -u but for dif.\n#!/bin/bash IFS=\u0026#34; \u0026#34; for line in `svn status -u`;do [[ $line != \u0026#34; \u0026#34;* ]] \u0026amp;\u0026amp; continue rev=`echo $line|awk \u0026#39;{print $2}\u0026#39;` ff=`echo $line|awk \u0026#39;{print $3}\u0026#39;` svn diff -r${rev}:HEAD $ff done ","permalink":"https://blog.chmouel.com/2007/02/06/svn-diff-against-changes-in-the-remote-repository/","summary":"\u003cp\u003eA useful svn wrapper scripts. Get a diff of your local repostitory against the upstream repository changes. I wonder why it is not builtins though like a svn status -u but for dif.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e#!/bin/bash\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eIFS\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003efor\u003c/span\u003e line in \u003cspan style=\"color:#f1fa8c\"\u003e`\u003c/span\u003esvn status -u\u003cspan style=\"color:#f1fa8c\"\u003e`\u003c/span\u003e;\u003cspan style=\"color:#ff79c6\"\u003edo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ff79c6\"\u003e[[\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$line\u003c/span\u003e !\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;   \u0026#34;\u003c/span\u003e* \u003cspan style=\"color:#ff79c6\"\u003e]]\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003econtinue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003erev\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e`\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eecho\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$line\u003c/span\u003e|awk \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;{print $2}\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e`\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eff\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e`\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eecho\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$line\u003c/span\u003e|awk \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;{print $3}\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e`\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    svn diff -r\u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003erev\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e:HEAD \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$ff\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003edone\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"SVN Diff against changes in the remote repository."},{"content":"I wanted to try the latest cvs snapshot with XFT support, since i did not want to screw up more my workstation i have used packages instead of make install blindy.\nBasically i have a script called ./build.sh\n#!/bin/bash set -e d=$(date \u0026#39;+%Y%m%d\u0026#39;) debpatch=20061218-1 mkdir -p cvs pushd cvs \u0026gt;/dev/null \u0026amp;\u0026amp; { cvs -Q -z3 -d:pserver:anonymous@cvs.savannah.gnu.org:/sources/emacs co -r emacs-unicode-2 emacs } \u0026amp;\u0026amp; popd \u0026gt;/dev/null mkdir -p build [[ -d build/emacs-${d} ]] \u0026amp;\u0026amp; rm -rf build/emacs-${d} cp -al cvs/emacs build/emacs-${d} zcat patches/emacs-snapshot_${debpatch}.diff.gz|patch -p1 -d build/emacs-${d} cat patches/with-font.patch|patch --silent -p1 -d build/emacs-${d} pushd build/emacs-${d} \u0026gt;/dev/null \u0026amp;\u0026amp; { chmod +x debian/rules dch -v \u0026#34;1:${d}-1\u0026#34; \u0026#34;New snapshot.\u0026#34; dch \u0026#34;Build with xft.\u0026#34; fakeroot dpkg-buildpackage -b } \u0026amp;\u0026amp; popd \u0026gt;/dev/null in patches/with-font.patch i have :\n--- c/debian/rules.chmou 2007-01-21 23:21:09.486353750 +1100 +++ c/debian/rules 2007-01-21 23:21:13.914630500 +1100 @@ -393,7 +393,7 @@ # Emacs-gtk confflags emacs_gtk_confflags := ${confflags} emacs_gtk_confflags += --with-x=yes -emacs_gtk_confflags += --with-x-toolkit=gtk +emacs_gtk_confflags += --with-x-toolkit=gtk --enable-font-backend --with-xft # Emacs-nox confflags emacs_nox_confflags := ${confflags} --- c/src/emacs.c.chmou 2007-01-21 23:21:09.486353750 +1100 +++ c/src/emacs.c 2007-01-21 23:22:18.430662500 +1100 @@ -1408,10 +1408,10 @@ = argmatch (argv, argc, \u0026#34;-nl\u0026#34;, \u0026#34;--no-loadup\u0026#34;, 6, NULL, \u0026amp;skip_args); #ifdef USE_FONT_BACKEND - enable_font_backend = 0; - if (argmatch (argv, argc, \u0026#34;-enable-font-backend\u0026#34;, \u0026#34;--enable-font-backend\u0026#34;, - 4, NULL, \u0026amp;skip_args)) enable_font_backend = 1; + if (argmatch (argv, argc, \u0026#34;-disable-font-backend\u0026#34;, \u0026#34;--disable-font-backend\u0026#34;, + 4, NULL, \u0026amp;skip_args)) + enable_font_backend = 0; #endif /* USE_FONT_BACKEND */ #ifdef HAVE_X_WINDOWS @@ -1816,7 +1816,7 @@ { \u0026#34;-unibyte\u0026#34;, \u0026#34;--unibyte\u0026#34;, 81, 0 }, { \u0026#34;-no-multibyte\u0026#34;, \u0026#34;--no-multibyte\u0026#34;, 80, 0 }, { \u0026#34;-nl\u0026#34;, \u0026#34;--no-loadup\u0026#34;, 70, 0 }, - { \u0026#34;-enable-font-backend\u0026#34;, \u0026#34;--enable-font-backend\u0026#34;, 65, 0 }, + { \u0026#34;-disable-font-backend\u0026#34;, \u0026#34;--disable-font-backend\u0026#34;, 65, 0 }, /* -d must come last before the options handled in startup.el. */ { \u0026#34;-d\u0026#34;, \u0026#34;--display\u0026#34;, 60, 1 }, { \u0026#34;-display\u0026#34;, 0, 60, 1 }, i have as well in patches/ the ubuntu (or could be debian) patch downloaded from the ubuntu (or debian archive) archive which is for ubuntu on\nhttp://archive.ubuntu.com/ubuntu/pool/universe/e/emacs-wiki\nIf there is a new version you will need to increase the version in build.sh to match the patch downloaded.\nWhen running build.sh it should produce binary in build/* with xft enabled by default. Make sure to have all the dependencies (dpkg-buildpackages should tell you if there is unresovled one).\nOne screenshot :\n","permalink":"https://blog.chmouel.com/2007/01/21/emacs-nighly-cvs-snapshot-with-xft-on-ubuntu-edgy/","summary":"\u003cp\u003eI wanted to try the latest cvs snapshot with XFT support, since i did not want to screw up more my workstation i have used packages instead of make install blindy.\u003c/p\u003e\n\u003cp\u003eBasically i have a script called ./build.sh\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e#!/bin/bash\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eset\u003c/span\u003e -e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ed\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e$(\u003c/span\u003edate \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;+%Y%m%d\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003edebpatch\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e20061218-1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir -p cvs\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003epushd\u003c/span\u003e cvs \u0026gt;/dev/null \u003cspan style=\"color:#ff79c6\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecvs -Q -z3 -d:pserver:anonymous@cvs.savannah.gnu.org:/sources/emacs co -r emacs-unicode-2 emacs\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e}\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003epopd\u003c/span\u003e \u0026gt;/dev/null\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir -p build\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e[[\u003c/span\u003e -d build/emacs-\u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ed\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e]]\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e rm -rf build/emacs-\u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ed\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecp -al cvs/emacs build/emacs-\u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ed\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ezcat patches/emacs-snapshot_\u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003edebpatch\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e.diff.gz|patch -p1 -d build/emacs-\u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ed\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecat patches/with-font.patch|patch --silent -p1 -d build/emacs-\u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ed\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003epushd\u003c/span\u003e build/emacs-\u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ed\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e \u0026gt;/dev/null \u003cspan style=\"color:#ff79c6\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    chmod +x debian/rules\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    dch -v \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;1:\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ed\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e-1\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;New snapshot.\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    dch \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;Build with xft.\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    fakeroot dpkg-buildpackage -b\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e}\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003epopd\u003c/span\u003e \u0026gt;/dev/null\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003ein patches/with-font.patch i have :\u003c/p\u003e","title":"Emacs nighly cvs snapshot with xft on Ubuntu Edgy"},{"content":"I better to keep that somewhere since i always forget that thing, to do a search and replace from the command line in zsh. you just have to do the :s^FOO^BAR after your expansion\nFor example you just have typed the long command line :\nblah bar FOO=1 FOO=3 FOO=6 cnt=1 you can just type :\n!blah:s^FOO^VALUE^:G and it will be expanded to :\nblah bar VALUE=1 VALUE=3 VALUE=6 cnt=1 ","permalink":"https://blog.chmouel.com/2007/01/10/history-expansion-and-substitions-in-zsh/","summary":"\u003cp\u003eI better to keep that somewhere since i always forget that thing, to do a search and replace from the command line in zsh. you just have to do the :s^FOO^BAR after your expansion\u003c/p\u003e\n\u003cp\u003eFor example you just have typed the long command line :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eblah bar FOO=1 FOO=3 FOO=6 cnt=1\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eyou can just type :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e!blah:s^FOO^VALUE^:G \n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eand it will be expanded to :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eblah bar VALUE=1 VALUE=3 VALUE=6 cnt=1\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"History expansion and substitions in ZSH"},{"content":"To rename bunch of files via regexp i was using before a homegrown python script call rename-regexp.py{#p38} to change bunch of files with a regexp.\nBut since then i discovered wdired which is pretty fantastic to use that from emacs. With the extended ``query-replace-regexp`` from Emacs22 stuff are much easier to rename.\n","permalink":"https://blog.chmouel.com/2007/01/06/rename-bunch-of-file-via-regexp/","summary":"\u003cp\u003eTo rename bunch of files via regexp i was using before a homegrown python script call \u003ca href=\"http://www.chmouel.com/blog/wp-content/uploads/2007/01/rename-regexppy1.txt\"\u003erename-regexp.py\u003c/a\u003e{#p38} to change bunch of files with a regexp.\u003c/p\u003e\n\u003cp\u003eBut since then i discovered \u003ca href=\"http://cris.ukrweb.net/documentation/editors/emacs/gnu_emacs/Wdired.html\"\u003ewdired\u003c/a\u003e which is pretty fantastic to use that from emacs. With the \u003ca href=\"http://steve-yegge.blogspot.com/2006/06/shiny-and-new-emacs-22.html\"\u003eextended\u003c/a\u003e \u003cem\u003e``query-replace-regexp``\u003c/em\u003e from Emacs22 stuff are much easier to rename.\u003c/p\u003e","title":"Rename bunch of file via regexp"},{"content":"pgbench is not the best tools to benchmark postgres but it\u0026rsquo;s\nthe one shipped by default with postgres.\nIt does not do a good job for benchmarking your \u0026ldquo;web apps\u0026rdquo; SQL wise, it will give you some\ngood indication about how fast is your server for postgres.\nHere are some results we have collected using theses options :\npgbench -Uuser -s 10 -c 10 -t 3000 benchmark We configure servers with RAID 1+0 with write-cache and a battery\nbackup, we have tested with postgres 8.1.5 and here are the best\nresults for different type of servers :\nIBM x3650 : 729tps\nHP DL385 : 717tps\nDell PowerEdge 2950: 708tps\n","permalink":"https://blog.chmouel.com/2007/01/06/postgres-options-using-pgbench-tps/","summary":"\u003cp\u003e\u003cstrong\u003epgbench\u003c/strong\u003e is not the best tools to benchmark postgres but it\u0026rsquo;s\u003cbr\u003e\nthe one shipped by default with postgres.\u003cbr\u003e\nIt does not do a good job for benchmarking your \u0026ldquo;web apps\u0026rdquo; SQL wise, it will give you some\u003cbr\u003e\ngood indication about how fast is your server for postgres.\u003c/p\u003e\n\u003cp\u003eHere are some results we have collected using theses options :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epgbench -Uuser  -s 10 -c 10 -t 3000 benchmark\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eWe configure servers with RAID 1+0 with write-cache and a battery\u003cbr\u003e\nbackup, we have tested with postgres 8.1.5 and here are the best\u003cbr\u003e\nresults for different type of servers :\u003c/p\u003e","title":"Benchmarking with PGBench: TPS results."},{"content":"After installing Oracle instant client, if you have them in /usr/local/lib/instantclient_10_2, this is the command line i use :\n./configure \u0026ndash;with-instant-client=/usr/local/lib/instantclient_10_2 \u0026ndash;with-oracle-includes=/usr/local/lib/instantclient_10_2/sdk/include \u0026ndash;with-oracle-libraries=/usr/local/lib/instantclient_10_2 \u0026ndash;with-oci-version=10G\nLet me know ny email if you want the deb for ubuntu linux.\n","permalink":"https://blog.chmouel.com/2007/01/04/compile-tora-with-oracle/","summary":"\u003cp\u003eAfter installing Oracle instant client, if you have them in /usr/local/lib/instantclient_10_2, this is the command line i use :\u003c/p\u003e\n\u003cp\u003e./configure \u0026ndash;with-instant-client=/usr/local/lib/instantclient_10_2 \u0026ndash;with-oracle-includes=/usr/local/lib/instantclient_10_2/sdk/include \u0026ndash;with-oracle-libraries=/usr/local/lib/instantclient_10_2 \u0026ndash;with-oci-version=10G\u003c/p\u003e\n\u003cp\u003eLet me know ny email if you want the deb for ubuntu linux.\u003c/p\u003e","title":"Compile tora with oracle"},{"content":"If you are using a pam_ldap or pam_nis environement and it happend that sqlplus does not want to connect as user but it does as root, waiting for :\nsocket(PF_FILE, SOCK_STREAM, 0) = 3 connect(3, {sa_family=AF_FILE, path=\u0026#34;/var/run/.nscd_socket\u0026#34;}, 110) = -1 ENOENT (No such file or directory) close(3) = 0 open(\u0026#34;/etc/hosts\u0026#34;, O_RDONLY) = 3 fcntl64(3, F_GETFD) = 0 fcntl64(3, F_SETFD, FD_CLOEXEC) = 0 fstat64(3, {st_mode=S_IFREG|0644, st_size=286, ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE |MAP_ANONYMOUS, -1, 0) = 0x45b78000 read(3, \u0026#34;127.0.0.1tlocalhost.localdomaint\u0026#34;..., 4096) = 286 read(3, \u0026#34;\u0026#34;, 4096) = 0 close(3) = 0 munmap(0x45b78000, 4096) = 0 getpid() = 26002 getuid32() = 1121 futex(0x41239198, FUTEX_WAIT, 2, NULL \u0026lt;unfinished\u0026gt; \u0026lt;/unfinished\u0026gt; You just to have make sure to have nscd up and running. dunno what sqlplus does :(\n","permalink":"https://blog.chmouel.com/2007/01/02/sqlplus-timeout-when-connnecting/","summary":"\u003cp\u003eIf you are using a pam_ldap or pam_nis environement and it happend that sqlplus does not want to connect as user but it does as root, waiting for :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esocket(PF_FILE, SOCK_STREAM, \u003cspan style=\"color:#bd93f9\"\u003e0\u003c/span\u003e)         \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e3\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econnect(\u003cspan style=\"color:#bd93f9\"\u003e3\u003c/span\u003e, {sa_family\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003eAF_FILE, path\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;/var/run/.nscd_socket\u0026#34;\u003c/span\u003e}, \u003cspan style=\"color:#bd93f9\"\u003e110\u003c/span\u003e) \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#bd93f9\"\u003e1\u003c/span\u003e ENOENT (No such file \u003cspan style=\"color:#ff79c6\"\u003eor\u003c/span\u003e directory)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eclose(\u003cspan style=\"color:#bd93f9\"\u003e3\u003c/span\u003e)                                \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eopen(\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;/etc/hosts\u0026#34;\u003c/span\u003e, O_RDONLY)            \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e3\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efcntl64(\u003cspan style=\"color:#bd93f9\"\u003e3\u003c/span\u003e, F_GETFD)                     \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efcntl64(\u003cspan style=\"color:#bd93f9\"\u003e3\u003c/span\u003e, F_SETFD, FD_CLOEXEC)         \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efstat64(\u003cspan style=\"color:#bd93f9\"\u003e3\u003c/span\u003e, {st_mode\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003eS_IFREG\u003cspan style=\"color:#ff79c6\"\u003e|\u003c/span\u003e\u003cspan style=\"color:#bd93f9\"\u003e0644\u003c/span\u003e, st_size\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#bd93f9\"\u003e286\u003c/span\u003e, \u003cspan style=\"color:#ff79c6\"\u003e...\u003c/span\u003e}) \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emmap2(NULL, \u003cspan style=\"color:#bd93f9\"\u003e4096\u003c/span\u003e, PROT_READ\u003cspan style=\"color:#ff79c6\"\u003e|\u003c/span\u003ePROT_WRITE, MAP_PRIVATE\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e|\u003c/span\u003eMAP_ANONYMOUS, \u003cspan style=\"color:#ff79c6\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#bd93f9\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#bd93f9\"\u003e0\u003c/span\u003e) \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e0x45b78000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eread(\u003cspan style=\"color:#bd93f9\"\u003e3\u003c/span\u003e, \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;127.0.0.1tlocalhost.localdomaint\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e...\u003c/span\u003e, \u003cspan style=\"color:#bd93f9\"\u003e4096\u003c/span\u003e) \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e286\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eread(\u003cspan style=\"color:#bd93f9\"\u003e3\u003c/span\u003e, \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#bd93f9\"\u003e4096\u003c/span\u003e)                       \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eclose(\u003cspan style=\"color:#bd93f9\"\u003e3\u003c/span\u003e)                                \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emunmap(\u003cspan style=\"color:#bd93f9\"\u003e0x45b78000\u003c/span\u003e, \u003cspan style=\"color:#bd93f9\"\u003e4096\u003c/span\u003e)                \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egetpid()                                \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e26002\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egetuid32()                              \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e1121\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efutex(\u003cspan style=\"color:#bd93f9\"\u003e0x41239198\u003c/span\u003e, FUTEX_WAIT, \u003cspan style=\"color:#bd93f9\"\u003e2\u003c/span\u003e, NULL \u003cspan style=\"color:#ff79c6\"\u003e\u0026lt;\u003c/span\u003eunfinished\u003cspan style=\"color:#ff79c6\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e\u0026lt;/\u003c/span\u003eunfinished\u003cspan style=\"color:#ff79c6\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eYou just to have make sure to have nscd up and running. dunno what sqlplus does :(\u003c/p\u003e","title":"sqlplus timeout when connnecting"},{"content":"Classic my first webpage is still on the web that was back in 98 and that was about Emacs :)\nhttp://membres.lycos.fr/crblinux/html/xemacs.html\nIt is in french thought.\n","permalink":"https://blog.chmouel.com/2006/12/30/my-first-webpage/","summary":"\u003cp\u003eClassic my first webpage is still on the web that was back in 98 and that was about Emacs :)\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://membres.lycos.fr/crblinux/html/xemacs.html\"\u003ehttp://membres.lycos.fr/crblinux/html/xemacs.html\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eIt is in french thought.\u003c/p\u003e","title":"My first webpage"},{"content":"If you want to emulate Control-L in Eshell (the Emacs Shell) like in Xterm, you can use this :\n(defun eshell-show-minimum-output () (interactive) (goto-char (eshell-beginning-of-output)) (set-window-start (selected-window) (save-excursion (goto-char (point-max)) (line-beginning-position))) (eshell-end-of-output)) And add a key bind to it in your custom hook :\n(local-set-key \u0026#34;\\C-l\u0026#34; \u0026#39;eshell-show-minimum-output)\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt; ","permalink":"https://blog.chmouel.com/2006/12/27/xterm-like-control-l-in-eshell/","summary":"\u003cp\u003eIf you want to emulate Control-L in Eshell (the Emacs Shell) like in Xterm, you can use this :\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-lisp\" data-lang=\"lisp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003edefun\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eeshell-show-minimum-output\u003c/span\u003e ()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003einteractive\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003egoto-char\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eeshell-beginning-of-output\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eset-window-start\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eselected-window\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t    (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003esave-excursion\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t      (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003egoto-char\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003epoint-max\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t      (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eline-beginning-position\u003c/span\u003e)))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eeshell-end-of-output\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eAnd add a key bind to it in your custom hook :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-lisp\" data-lang=\"lisp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003elocal-set-key\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\\C-l\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;eshell-show-minimum-output\u003c/span\u003e)\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e\u0026lt;/p\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e\u0026lt;p\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c!-- raw HTML omitted --\u003e","title":"Xterm like Control-L in Eshell"},{"content":"If you like me when running oracle on x86_64 get that damn :\nError loading native library: libnjni9.so\nwhen launching dbca and you have googled the thousands five hundred useless answer. Just add the path of the libs $ORACLE_HOME/lib and $ORACLE_HOME/lib32 to your /etc/ld.so.conf (or /etc/ld.so.conf.d/oracle.conf on RH derivative) and rerun ldconfig.\nIf this is during install just jump to a console after you add this line before it launching dbca and run a ldconfig -v as root.\nDamn oracle\u0026hellip;.\n","permalink":"https://blog.chmouel.com/2006/12/21/error-loading-native-library-libnjni9so/","summary":"\u003cp\u003eIf you like me when running oracle on x86_64 get that damn :\u003c/p\u003e\n\u003cp\u003eError loading native library: libnjni9.so\u003c/p\u003e\n\u003cp\u003ewhen launching dbca and you have googled the thousands five hundred useless answer. Just add the path of the libs $ORACLE_HOME/lib and $ORACLE_HOME/lib32 to your /etc/ld.so.conf (or /etc/ld.so.conf.d/oracle.conf on RH derivative) and rerun ldconfig.\u003c/p\u003e\n\u003cp\u003eIf this is during install just jump to a console after you add this line before it launching dbca and run a ldconfig -v as root.\u003c/p\u003e","title":"Error loading native library: libnjni9.so"},{"content":"Something that i haven\u0026rsquo;t find via goole. By default on RedHat (and derivatives) if you get a dark background the colored ls will be seen really humm bold from a xterm (since i guess there default gnome-terminal has been configured to have a white background ).\nThe solution is to\ncp /etc/DIR_COLORS /etc/DIR_COLORS.xterm or to redefine your dircolors to get the /etc/DIR_COLORS files instead of /etc/DIR_COLORS.xterm in your shell init configuration.\n","permalink":"https://blog.chmouel.com/2006/12/20/how-to-get-bright-ls-colors-on-redhat-with-dark-background/","summary":"\u003cp\u003eSomething that i haven\u0026rsquo;t find via goole. By default on RedHat (and derivatives) if you get a dark background the colored ls will be seen really humm bold from a xterm (since i guess there default gnome-terminal has been configured to have a white background ).\u003c/p\u003e\n\u003cp\u003eThe solution is to\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecp /etc/DIR_COLORS /etc/DIR_COLORS.xterm\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eor to redefine your dircolors to get the /etc/DIR_COLORS files instead of /etc/DIR_COLORS.xterm in your shell init configuration.\u003c/p\u003e","title":"How to get bright LS colors on Redhat with dark background"},{"content":"Here is a simple html derived mode for Cheetah templates files. The font-locking regexp can be improved thought but thatâ€™s a start.\n(define-derived-mode cheetah-mode html-mode \u0026#34;Cheetah\u0026#34; (make-face \u0026#39;cheetah-variable-face) (font-lock-add-keywords nil \u0026#39;( (\u0026#34;\\\\(#\\\\(from\\\\|else\\\\|include\\\\|set\\\\|import\\\\|for\\\\|if\\\\|end\\\\)+\\\\)\\\\\u0026gt;\u0026#34; 1 font-lock-type-face) (\u0026#34;\\\\(#\\\\(from\\\\|for\\\\|end\\\\)\\\\).*\\\\\u0026lt;\\\\(for\\\\|import\\\\|if\\\\|in\\\\)\\\\\u0026gt;\u0026#34; 3 font-lock-type-face) (\u0026#34;\\\\(\\\\$\\\\(?:\\\\sw\\\\|}\\\\|{\\\\|\\\\s_\\\\)+\\\\)\u0026#34; 1 font-lock-variable-name-face)) ) (font-lock-mode 1) ) (setq auto-mode-alist (cons \u0026#39;( \u0026#34;\\\\.tmpl\\\\\u0026#39;\u0026#34; . cheetah-mode ) auto-mode-alist )) ","permalink":"https://blog.chmouel.com/2006/07/31/cheetah-mode-for-emacs/","summary":"\u003cp\u003eHere is a simple html derived mode for \u003ca href=\"http://www.cheetahtemplate.org/\"\u003eCheetah\u003c/a\u003e templates files. The font-locking regexp can be improved thought but thatâ€™s a start.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-lisp\" data-lang=\"lisp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003edefine-derived-mode\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003echeetah-mode\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ehtml-mode\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;Cheetah\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003emake-face\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;cheetah-variable-face\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003efont-lock-add-keywords\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   nil\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#ff79c6\"\u003e\u0026#39;\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     (\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\\\\(#\\\\(from\\\\|else\\\\|include\\\\|set\\\\|import\\\\|for\\\\|if\\\\|end\\\\)+\\\\)\\\\\u0026gt;\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003efont-lock-type-face\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     (\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\\\\(#\\\\(from\\\\|for\\\\|end\\\\)\\\\).*\\\\\u0026lt;\\\\(for\\\\|import\\\\|if\\\\|in\\\\)\\\\\u0026gt;\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e3\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003efont-lock-type-face\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     (\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\\\\(\\\\$\\\\(?:\\\\sw\\\\|}\\\\|{\\\\|\\\\s_\\\\)+\\\\)\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003efont-lock-variable-name-face\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003efont-lock-mode\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#ff79c6\"\u003esetq\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eauto-mode-alist\u003c/span\u003e (\u003cspan style=\"color:#50fa7b\"\u003econs\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e\u0026#39;\u003c/span\u003e( \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\\\\.tmpl\\\\\u0026#39;\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003echeetah-mode\u003c/span\u003e ) \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eauto-mode-alist\u003c/span\u003e ))\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Cheetah Mode for Emacs"},{"content":"Here is some function to launch a gajim window from Emacs :\n(defvar gajim-remote \u0026#34;/usr/bin/gajim-remote\u0026#34;) (defvar gajim-user-list ()) (defun my-gajim-get-list() (save-excursion (with-temp-buffer (call-process gajim-remote nil t nil \u0026#34;list_contacts\u0026#34;) (goto-char (point-min)) (while (re-search-forward \u0026#34;^jid[ ]*:[ ]*\\\\(.*\\\\)$\u0026#34; (point-max) t ) (setq gajim-user-list (append gajim-user-list (list (match-string-no-properties 1))))))) gajim-user-list) (defun my-gajim-talk() (interactive) (let* ((ff (if (not gajim-user-list)(my-gajim-get-list) gajim-user-list)) (answer (completing-read \u0026#34;Jabber: \u0026#34; (mapcar (lambda (tt)(list tt)) ff)))) (message answer) (start-process \u0026#34;*GAJIM*\u0026#34; nil gajim-remote \u0026#34;open_chat\u0026#34; answer) ) ) (global-set-key \u0026#39;[(control x)(j)] \u0026#39;my-gajim-talk) If Emacs had a dbus support that would have been cool.\n","permalink":"https://blog.chmouel.com/2006/07/31/access-gajim-within-emacs/","summary":"\u003cp\u003eHere is some function to launch a gajim window from Emacs :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-lisp\" data-lang=\"lisp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003edefvar\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003egajim-remote\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;/usr/bin/gajim-remote\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003edefvar\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003egajim-user-list\u003c/span\u003e ())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003edefun\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003emy-gajim-get-list\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003esave-excursion\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ewith-temp-buffer\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ecall-process\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003egajim-remote\u003c/span\u003e nil t nil \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;list_contacts\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003egoto-char\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003epoint-min\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ewhile\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ere-search-forward\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;^jid[ ]*:[ ]*\\\\(.*\\\\)$\u0026#34;\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003epoint-max\u003c/span\u003e) t )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        (\u003cspan style=\"color:#ff79c6\"\u003esetq\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003egajim-user-list\u003c/span\u003e (\u003cspan style=\"color:#50fa7b\"\u003eappend\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003egajim-user-list\u003c/span\u003e (\u003cspan style=\"color:#50fa7b\"\u003elist\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ematch-string-no-properties\u003c/span\u003e \u003cspan style=\"color:#bd93f9\"\u003e1\u003c/span\u003e)))))))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003egajim-user-list\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003edefun\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003emy-gajim-talk\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003einteractive\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  (\u003cspan style=\"color:#ff79c6\"\u003elet*\u003c/span\u003e ((\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eff\u003c/span\u003e (\u003cspan style=\"color:#ff79c6\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#50fa7b\"\u003enot\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003egajim-user-list\u003c/span\u003e)(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003emy-gajim-get-list\u003c/span\u003e) \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003egajim-user-list\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eanswer\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ecompleting-read\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;Jabber: \u0026#34;\u003c/span\u003e (\u003cspan style=\"color:#50fa7b\"\u003emapcar\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003elambda\u003c/span\u003e (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ett\u003c/span\u003e)(\u003cspan style=\"color:#50fa7b\"\u003elist\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ett\u003c/span\u003e)) \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eff\u003c/span\u003e))))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003emessage\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eanswer\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    (\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003estart-process\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;*GAJIM*\u0026#34;\u003c/span\u003e nil \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003egajim-remote\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;open_chat\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eanswer\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eglobal-set-key\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;[\u003c/span\u003e(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003econtrol\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ex\u003c/span\u003e)(\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ej\u003c/span\u003e)\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;my-gajim-talk\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIf Emacs had a dbus support that would have been cool.\u003c/p\u003e","title":"Access Gajim within Emacs"},{"content":"This is weird for me :\nd = [\u0026#39;foo\u0026#39;, \u0026#39;bar\u0026#39;, \u0026#39;ba\u0026#39;, \u0026#39;c\u0026#39;] print d f = d f.extend(d) print d give me the result\npython \u0026ldquo;/tmp/a.py\u0026rdquo;\n[\u0026lsquo;foo\u0026rsquo;, \u0026lsquo;bar\u0026rsquo;, \u0026lsquo;ba\u0026rsquo;, \u0026lsquo;c\u0026rsquo;]\n[\u0026lsquo;foo\u0026rsquo;, \u0026lsquo;bar\u0026rsquo;, \u0026lsquo;ba\u0026rsquo;, \u0026lsquo;c\u0026rsquo;, \u0026lsquo;foo\u0026rsquo;, \u0026lsquo;bar\u0026rsquo;, \u0026lsquo;ba\u0026rsquo;, \u0026lsquo;c\u0026rsquo;]\nCompilation finished at Mon Jul 31 16:49:4\nIt seems that extend assign as well the non extended part (d) which is confusing because to merge list i need to use temporary variable.\n","permalink":"https://blog.chmouel.com/2006/07/31/assignement-in-python-with-listextend/","summary":"\u003cp\u003eThis is weird for me :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ed \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;foo\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;bar\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;ba\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;c\u0026#39;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eprint\u003c/span\u003e d\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ef \u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e d\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ef\u003cspan style=\"color:#ff79c6\"\u003e.\u003c/span\u003eextend(d)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eprint\u003c/span\u003e d\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003egive me the result\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003cp\u003epython \u0026ldquo;/tmp/a.py\u0026rdquo;\u003cbr\u003e\n[\u0026lsquo;foo\u0026rsquo;, \u0026lsquo;bar\u0026rsquo;, \u0026lsquo;ba\u0026rsquo;, \u0026lsquo;c\u0026rsquo;]\u003cbr\u003e\n[\u0026lsquo;foo\u0026rsquo;, \u0026lsquo;bar\u0026rsquo;, \u0026lsquo;ba\u0026rsquo;, \u0026lsquo;c\u0026rsquo;, \u0026lsquo;foo\u0026rsquo;, \u0026lsquo;bar\u0026rsquo;, \u0026lsquo;ba\u0026rsquo;, \u0026lsquo;c\u0026rsquo;]\u003c/p\u003e\n\u003cp\u003eCompilation finished at Mon Jul 31 16:49:4\u003c/p\u003e\n\u003cp\u003eIt seems that extend assign as well the non extended part (d) which is confusing because to merge list i need to use temporary variable.\u003c/p\u003e","title":"Assignement in Python with list.extend()"},{"content":"When i have a password comparaison function using crypt(3) i really should remember that the comparaison stop at the 7 bytes, because that stuff is weird for me :\nIn 1: import crypt\nIn [2]: seed=\u0026lsquo;foo!bar\u0026rsquo;\nIn [3]: crypt.crypt(\u0026lsquo;abcdefghaa123456681\u0026rsquo;, seed)\nOut[3]: \u0026lsquo;foEoVhbk7ad7A\u0026rsquo;\nIn [4]: crypt.crypt(\u0026lsquo;abcdefghpax;lalx;al\u0026rsquo;, seed)\nOut[4]: \u0026lsquo;foEoVhbk7ad7A\u0026rsquo;\nIn [5]:\nany stuff after the 6 char will always get ignored by the hash algorithm.\n","permalink":"https://blog.chmouel.com/2006/07/30/crypt3-on-unix-maximal-lenght/","summary":"\u003cp\u003eWhen i have a password comparaison function using \u003ca href=\"http://en.wikipedia.org/wiki/Crypt_%28Unix%29#Library_Function\"\u003ecrypt(3)\u003c/a\u003e i really should remember that the comparaison stop at the 7 bytes, because that stuff is weird for me :\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eIn \u003ca href=\"http://en.wikipedia.org/wiki/Crypt_%28Unix%29#Library_Function\"\u003e1\u003c/a\u003e: import crypt\u003cbr\u003e\nIn [2]: seed=\u0026lsquo;foo!bar\u0026rsquo;\u003cbr\u003e\nIn [3]: crypt.crypt(\u0026lsquo;abcdefghaa123456681\u0026rsquo;, seed)\u003cbr\u003e\nOut[3]: \u0026lsquo;foEoVhbk7ad7A\u0026rsquo;\u003cbr\u003e\nIn [4]: crypt.crypt(\u0026lsquo;abcdefghpax;lalx;al\u0026rsquo;, seed)\u003cbr\u003e\nOut[4]: \u0026lsquo;foEoVhbk7ad7A\u0026rsquo;\u003cbr\u003e\nIn [5]:\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eany stuff after the 6 char will always get ignored by the hash algorithm.\u003c/p\u003e","title":"crypt(3) on unix maximal length"},{"content":"I have finally changed chmouel.com over a new provider. The new\nprovider is called WebHost and i got a VPS with 50GB of\nbandwith and 2GB of storage for 10US$ a month.\nMy first task was to compile python2.4 on that box which look like\nit\u0026rsquo;s based on RH7.3 with heavy customization. Hopefully python really can compile everywhere.\nI would like to thanks Vincent Danen for all his free hosting\nduring all theses years. He has been answering me every\nquestions i had and provided me a nice hosting for all theses years i was in travel.\nI hope to pass by Alberta one day and invite him for the couples\nof hundred beers that i own him now.\nSo now that i have a private server what can i do with that ? not too\nmuch since webdev is not my hobbies (i have to do that at work and i\nfind it a pain in the a***), but well it\u0026rsquo;s cool to have a ssh\nfrom everywhere in the world.\n","permalink":"https://blog.chmouel.com/2006/07/30/chmouelcom-is-moved/","summary":"\u003cp\u003eI have finally changed chmouel.com over a new provider. The new\u003cbr\u003e\nprovider is called \u003ca href=\"http://www.westhost.com/\"\u003eWebHost\u003c/a\u003e and i got a \u003ca href=\"http://en.wikipedia.org/wiki/Virtual_private_server\"\u003eVPS\u003c/a\u003e with 50GB of\u003cbr\u003e\nbandwith and 2GB of storage for 10US$ a month.\u003c/p\u003e\n\u003cp\u003eMy first task was to compile python2.4 on that box which look like\u003cbr\u003e\nit\u0026rsquo;s based on RH7.3 with heavy customization. Hopefully python really can compile everywhere.\u003c/p\u003e\n\u003cp\u003eI would like to thanks \u003ca href=\"http://www.danen.ca\"\u003eVincent Danen\u003c/a\u003e for all his free hosting\u003cbr\u003e\nduring all theses years. He has been answering me every\u003cbr\u003e\nquestions i had and provided me a nice hosting for all theses years i was in travel.\u003cbr\u003e\nI hope to pass by Alberta one day and invite him for the couples\u003cbr\u003e\nof hundred beers that i own him now.\u003c/p\u003e","title":"chmouel.com is moved."},{"content":"Get the size accurately from postgres local filesystem, i guess there is some sql stuff that can do that but that does the job as well for me :\n#!/bin/bash /usr/lib/postgresql/8.1/bin/oid2name -U postgres|while read -a e;do name=${e[1]} oid=${e[0]} [[ $oid == \u0026#34;All\u0026#34; || $oid == \u0026#34;Oid\u0026#34; || -z $oid || -z $name ]] \u0026amp;\u0026amp; continue typeset -a size size=(`du -s /var/lib/postgresql/8.1/main/base/$oid`) size=${size[0]} printf \u0026#34;%-20s %-20s\\n\u0026#34; ${name} ${size} done | sort -n -r -k 2 |awk \u0026#39;{printf \u0026#34;%-20s%20d Mb\\n\u0026#34;, $1, $2 / 1024}\u0026#39; ","permalink":"https://blog.chmouel.com/2006/06/05/get-size-of-postgres-db-from-filesystem/","summary":"\u003cp\u003eGet the size accurately from postgres local filesystem, i guess there is some sql stuff that can do that but that does the job as well for me :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e#!/bin/bash\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/usr/lib/postgresql/8.1/bin/oid2name  -U postgres|\u003cspan style=\"color:#ff79c6\"\u003ewhile\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eread\u003c/span\u003e -a e;\u003cspan style=\"color:#ff79c6\"\u003edo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ee\u003c/span\u003e[1]\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eoid\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ee\u003c/span\u003e[0]\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e[[\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$oid\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;All\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e||\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$oid\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;Oid\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e||\u003c/span\u003e -z \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$oid\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e||\u003c/span\u003e -z \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$name\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e]]\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003econtinue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003etypeset\u003c/span\u003e -a size\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003esize\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=(\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e`\u003c/span\u003edu -s /var/lib/postgresql/8.1/main/base/\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$oid\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e`\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003esize\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003esize\u003c/span\u003e[0]\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eprintf\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;%-20s %-20s\\n\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e \u003cspan style=\"color:#f1fa8c\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003esize\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003edone\u003c/span\u003e | sort -n -r -k \u003cspan style=\"color:#bd93f9\"\u003e2\u003c/span\u003e |awk \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#39;{printf \u0026#34;%-20s%20d Mb\\n\u0026#34;, $1, $2 / 1024}\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Get size of Postgres DB from filesystem"},{"content":"At work we are using Asterisk and Jabber and i am using Gajim as my client. I did a quick patch to have a notification on my desktop when someone call me and i get my big headphones (not that i like the phone very much but well), here is the patch for people who may wants it :\nhttp://trac.gajim.org/ticket/1998\n","permalink":"https://blog.chmouel.com/2006/05/25/jabberasterisk-and-gajim-notification/","summary":"\u003cp\u003eAt work we are using Asterisk and Jabber and i am using Gajim as my client. I did a quick patch to have a notification on my desktop when someone call me and i get my big headphones (not that i like the phone very much but well), here is the patch for people who may wants it :\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://trac.gajim.org/ticket/1998\"\u003ehttp://trac.gajim.org/ticket/1998\u003c/a\u003e\u003c/p\u003e","title":"Jabber/Asterisk and Gajim notification"},{"content":"I am sic of spaces and having svn diff that does not get the spaces removed. So here is a simple script that does the stuff that you can use as your diff-cmd :\n#!/bin/bash for i in $@;do echo $i |grep -q \u0026#34;)\u0026#34; \u0026amp;\u0026amp; continue echo $i |grep -q \u0026#34;(\u0026#34; \u0026amp;\u0026amp; continue t=\u0026#34;$t $i\u0026#34; done diff -bBw $t ","permalink":"https://blog.chmouel.com/2006/05/25/svn-diff-without-spaces/","summary":"\u003cp\u003eI am sic of spaces and having svn diff that does not get the spaces removed. So here is a simple script that does the stuff that you can use as your diff-cmd :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003e#!/bin/bash\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003efor\u003c/span\u003e i in \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$@\u003c/span\u003e;\u003cspan style=\"color:#ff79c6\"\u003edo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eecho\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$i\u003c/span\u003e |grep -q \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;)\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003econtinue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003eecho\u003c/span\u003e \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$i\u003c/span\u003e |grep -q \u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;(\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ff79c6\"\u003econtinue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003et\u003c/span\u003e\u003cspan style=\"color:#ff79c6\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$t\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e \u003c/span\u003e\u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$i\u003c/span\u003e\u003cspan style=\"color:#f1fa8c\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ff79c6\"\u003edone\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ediff -bBw \u003cspan style=\"color:#8be9fd;font-style:italic\"\u003e$t\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"svn diff without spaces"},{"content":"On X86_64 VM Emulation works way better with Xen 3.0 than with Vmware. Xen is pretty awesome compared to Vmware for my use. The only thing i have to figure out is how to get rpmstrap get it workin on Debian base system.\n","permalink":"https://blog.chmouel.com/2006/05/11/x86_64/","summary":"\u003cp\u003eOn X86_64 VM Emulation works way better with Xen 3.0 than with Vmware. Xen is pretty awesome compared to Vmware for my use. The only thing i have to figure out is how to get rpmstrap get it workin on Debian base system.\u003c/p\u003e","title":"X86_64"},{"content":"Remind to myself to use the switch -64 on solaris with crle to tell\nthe linker on solaris to get the linker \u0026lsquo;seeing\u0026rsquo; 64 libraries.\nI wonder why everything is not as simple as linux thought where we\nhave everything in one place with /etc/ld.so.config\n","permalink":"https://blog.chmouel.com/2006/04/29/mixing-64-bytes-and-32-bytes-libraries-on-solaris/","summary":"\u003cp\u003eRemind to myself to use the switch -64 on solaris with crle to tell\u003cbr\u003e\nthe linker on solaris to get the linker \u0026lsquo;seeing\u0026rsquo; 64 libraries.\u003c/p\u003e\n\u003cp\u003eI wonder why everything is not as simple as linux thought where we\u003cbr\u003e\nhave everything in one place with /etc/ld.so.config\u003c/p\u003e","title":"Mixing 64 bytes and 32 Bytes Libraries on Solaris"},{"content":"I have been looking at the What\u0026rsquo;s new __of Python 2.5. There is some cool features inside it :\nConditional Expressions:\nThis stuff basically allow to do standard C idiom (that we found in every kind of derivative language) like\na = condition ? \u0026ldquo;true\u0026rdquo; : \u0026ldquo;false\u0026rdquo;\nthe weird part is that Guido Van-Rossum implemented this syntax :\nx = true_value if condition else false_value\nwhich we will have to get use to. I am not a big fan of this feature since it makes the code more obscure. But still could be useful for little scripts or quick hack.\nUnified try/except/finally:\nI like the inclusion of else in a try finally. I use to put everything in the try which was not really very good looked when now i can really try or else something. Make me easier to port some Java code to python as well and respect the logic of the java program.\nThe with statement:\nThis one is weird for me it\u0026rsquo;s basically a closure of variable allowing to do stuff like this :\nwith expression as variable:\nstuff\n#expression not here anymore\nI am still wondering how and why to use that. But i guess it will come us when i will do some coding in Python 2.5.\nOther interesting stuff:\nSqlite3 library default inclusion. The cool thing about this for Linux vendors is that it does not require the libsqlite3 library but link dynamically via the ctypes module (i guess).\nCtypes allow you to call C dynamic functions via python.\nA fast new XML parser.\nSounds like fun for the new python and there is a lot of other bugfixes so go read it.\n","permalink":"https://blog.chmouel.com/2006/04/09/python-25-beta/","summary":"\u003cp\u003e\u003c!-- raw HTML omitted --\u003eI have been looking at the \u003c!-- raw HTML omitted --\u003e\u003cem\u003e\u003ca href=\"http://docs.python.org/dev/whatsnew/whatsnew25.html\" title=\"Whats new in Python 2.5\"\u003e\u003c!-- raw HTML omitted --\u003eWhat\u0026rsquo;s new\u003c!-- raw HTML omitted --\u003e\u003c/a\u003e\u003c/em\u003e __\u003c!-- raw HTML omitted --\u003eof Python 2.5. There is some cool features inside it :\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ca href=\"http://docs.python.org/dev/whatsnew/node2.html\"\u003e\u003c!-- raw HTML omitted --\u003eConditional Expressions:\u003c!-- raw HTML omitted --\u003e\u003c/a\u003e\u003c/strong\u003e\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e\n\u003cp\u003e\u003c!-- raw HTML omitted --\u003eThis stuff basically allow to do standard C idiom (that we found in every kind of derivative language) like\u003c!-- raw HTML omitted --\u003e\u003c/p\u003e","title":"Python 2.5 Beta"}]