Dec 18, 2012

Portable Fedora 17 on a USB key

Intro, AKA the "tl;dr" part you can skip 

 

A few weeks ago I have become very upset about the laptops provided by my employer (Dell on Win7) and my main client (Dell on WinXP). They all came with all sorts of checking, locking and logging software that resulted in crappy performances and low autonomy. Also, I don't carry both PC with me every day so I had to keep them synchronized or use a removable device. But the tools themselves were attached to Windows.
So I decided to install a personal portable Linux ("do or do not; there is no try" via @MasterYoda). With USB keys now being so ridiculously cheap, 16GB from a trustworthy vendor for €12, this is the way to go.
My first attempts were with Live USB creator tools that take an iso image from a live distribution, copy it to a USB key and add a persistent storage area. That was terrible. This persistent layer is far from solid and couldn't be trusted, whatever the distribution.
Then I went for normal install of Fedora 17 on USB, even if it lacks all the optimizations of a live distribution. And it works great. It's light, fast, responsive, battery-saving. I used it more than 2 hours straight, dev + music, and still had 50% left. I love my portable Fedora so much that it hurts when I think how I was doing without it "back in the days".

Now, the interesting part 

 

Here's my set up :
  • Fedora 17 x64, installed from Live CD
  • 16 GB SanDisk USB key
  • 500 MB partition for /boot
  • 2 logical volumes :
    • 5 GB for /  (go for 7GB if you need LibreOffice)
    • the rest LUKS encrypted for /home
  • no swap
I will not explain how to install, there are enough tutorials around. Just be careful which target device you select.

 

tmpfs

All the changes described below are focused on limiting the write accesses to the file system, to give your USB key or SSD a bigger life span, by moving the temporary files to tmpfs. tmpfs allows you to mount a filesystem in memory. All the items you usually don't need to be persistent (after a stop/start) like locks, some logs, cache, ... don't need to be written on a disk.
Some tips I found myself, some were gathered from various web sites, in particular :
  • http://wiki.debian.org/DebianAcerOne
  • http://forums.mozillazine.org/viewtopic.php?f=8&t=2115257

 

Moving /var/cache to tmpfs

Not everything in /var/cache can be stored in memory. Some cache needs to be written to disk if you use it frequently like yum and man :

move /var/cache/yum to /var/yum
edit /etc/yum.conf

move /var/cache/man to /var/man
edit /etc/man_db.conf

 

Editing /etc/fstab

Now we can edit /etc/fstab to use tmpfs for a few temporary directories. The "noatime" for ext4 saves a lot of i/o by not saving the last access time to a file.

/dev/mapper/your-lv-name /  ext4    defaults        1 1
UUID=your-boot-fs-uuid /boot  ext4    defaults,noatime        1 2
/dev/mapper/luks-your-luks-fs-id /home     ext4    defaults,noatime        1 2
tmpfs    /tmp    tmpfs    defaults,noatime    0 0
tmpfs    /var/lock    tmpfs    defaults,noatime    0 0
tmpfs    /var/tmp    tmpfs    defaults,noatime    0 0
tmpfs    /var/spool    tmpfs    defaults,noatime    0 0
tmpfs    /var/cache    tmpfs    defaults,noatime    0 0


/var/run can not be stored in tmpfs because systemd uses it very early in the boot process, before the file system is mounted into memory.

Restart.
If the system is not booting, then there is an error in your fstab and systemd was not able to mount one or more file systems. Enter the maintenance shell and correct the problem.
Some commands that can help you out : blkid, vgdisplay -v your-vg-name, mount, df, ...

 

Optimizing Firefox

You can configure Firefox to keep its cache in memory instead of writing it on the disk.
Open a new tab, then go to "about:config". Swear that you know what you're doing and that you'll be careful. (promise !)
Search for "browser.cache.disk.enable" and set it to "false".

Update (20130513) : It has been 6 months now and I have not had any problem yet. The upgrade process to Fedora 18 went like a breeze.

Nov 28, 2012

Enhancing MT user experience with JavaScript; Part 2

This is a repost from : https://communities.bmc.com/communities/docs/DOC-21818
If you are a BMC Remedy AR System user/admin/developer, you really should participate to Communities, there are many things to learn, fast.

This is the second part of a series dedicated to demonstrate how JavaScript can be used to enhance user experience on AR System forms. Provided examples are all designed for MidTier 7.6.04 or 8.0.0.
In the first part, we saw how to call a JS function from active link, how to call active links from a JS function, and then how we could use that to provide a simple client-side form validation.

Binding extra event handlers to fields

Active links can be set to be executed on return, gain/loose focus, menu select ... It already covers a lot of usual needs.

Now, with what we saw in the first part, we have all we need to add more events.

For example, the "run process" command below adds a handler function for the "onkeyup" event of the field 700000002, which calls "TheGuideName" guide :
javascript document.getElementById('arid_WIN_0_700000002').onkeyup=function(){ arInvokeGuide(0,"$SERVER$","TheGuideName");}

The list of events you can handle is on the w3c page for scripts.

Second example : on-the-fly regular expression validator

Let's use this to create a better client-side validation.

We want the validation to be done as the user types. It shouldn't display any indicator if the tested value is null. Oh, and the users like round corners and shadows.



Yay, that looks better !
The .def file is available here.
Simply import it and open the "_TUT:JavaScript2" form.

So, how does it work ? 

Remember the "checkValue" function we defined in the web header view in the first part of this document ?
Let's change it just a little, to get the tested value back into an AR System field.
Why do we want the value back ?
First, because it demonstrates how you can set a field from JS. Simply setting the <field selector>.value with JS won't do because the MT keeps a record of fields and their values. You need to call the "S" function to update it.
Second, because if you don't, you won't be able to check if the value is null or not (just test it ).
To make it look a little prettier than the standard AR System forms, the field is customized via CSS, still in the web header content property of the view :
The checkValue function is called when the "onkeyup" occurs. To do it, we execute this javascript in a "Run Process" action, when you select the field format in the menu.
javascript document.getElementById('arid_WIN_0_700000002').onkeyup=function(){ checkValue(this.value,"i","$RegExp$","$SERVER$","_TUT:JavaScript2_ResultOK","_TUT:JavaScript2_ResultKO");}
It says, Ok get me the field 700000002. It has a "onkeyup" property. Assign it with a value that happens to be a function (that's a fun thing in JS). The function calls "checkValue". The first parameter is the value of the field that it's attached to.

The downside

As you see, we can do a lot of things if we start to put a little JS in our AR System forms.
BUT
  • it requires non-Remedy skills to maintain
  • your code is expecting very specific things from the HTML generated by the MidTier : the ID for the fields, the F & S functions, arInvokeGuide, ... They all could be dropped in the next MT version 
  • the documenting programs like ARInside won't know about your JavaScript, just like when you execute Direct SQL commands

Nov 16, 2012

Enhancing MT user experience with JavaScript; Part 1

This is the first part (hopefully) of a series dedicated to demonstrate how JavaScript can be used to enhance user experience on AR System forms. Provided examples are all designed for MidTier 7.6.04 or 8.0.0.

The Mid-Tier and AR System in general are great pieces of software, excellent toolboxes to create apps and workflows real fast.
Sometimes though you can stumble upon a requirement that is very complicated, or simply impossible, to answer with basic active links. In this case you have two options :
  • drop the requirement
  • use JavaScript

The basics

You probably already know how to execute a JavaScript function. If not, you may want to take a look here.
To do this, you execute a "run process" command starting with "javascript".
javascript alert("Hello world");

Now, maybe you also know how to get back into AR System workflow from JavaScript. If not, you can read this.
The core JS code of the MidTier exposes 3 functions for you to call from your own JS code :
  • arInvokeEntryPoint ("windowID","serverName","guideName") — Executes the specified entry point guide as long as the application list field (ID 1575) is also available and visible on the same form that contains the view field.
  • arInvokeGuide ("windowID","serverName","guideName") — Executes the specified guide.
  • arInvokeForm ("windowID","serverName","guideName","mode") — Executes the specified form in New or Search mode. Valid values for mode are New and Search.

Finally, did you know you can add some HTML, JS or CSS in your views ?
In DevStudio, display the properties of a view. You can see the "web header content" and the "web footer content" properties. You can insert your JS code here, or import an external .js file hosted on your MTs.

First sample : simple regular expression validator

We now have a complete access to JavaScript to make our users' work a little easier.
The example I chose to show you is something that is often asked : client-side form validation.
As you may already know, there are some nice AR plugins out there that allow you to validate user inputs. But this is done on the server side, and requires a round trip.

The attached .def is to be imported on any 7.6.04+ AR System server.
You will find a display-only form named "_TUT:JavaScript1", with 3 fields.
The first one is a selection field with a label. It has only one value, "email", but you can add more if you want to test your own regular expressions.
When you select "email", a regular expression is written in the RegExp field. I know it is not strictly correct for an email validation, but hey it's just an example.
Then write something in the 3rd field, and press enter to test it against a regular expression above.

So, how does it work ?

The magic is stored in the web header property of the view :
What does this do ?
When the "checkValue" function is called, it very basically tests the "value" parameter against the "regexp" regular expression.
If the test is positive, it calls the guide "positiveGuide".
Else, it calls the guide "negativeGuide".
Nothing too complicated here.
The only thing you have to be aware of is the recent first parameter of the arInvokeGuide function, that will hold the Window ID. This parameter is required starting version 7.6.04. Before this version only the two last parameters, server and guide name, were required. Beware if you are in a pop-up, a pop-in, or an inline form.
On return in the "Value" field, an active link executes this run process action :
javascript checkValue("$Value$","i" ,"$RegExp$","$SERVER$","_TUT:JavaScript1_ResultOK","_TUT:JavaScript1_ResultKO");

What's next ?

This still looks 2000ish.
In the next part, I will explain how to bind new event handlers to AR System fields. Using this, the example will show you how to make an "on-the-fly" validation of user input.

Oct 31, 2012

How to consume AR System 8 web services with jQuery

... and a few years later ...
I said farewell to good old Flex and turned to the now hyped JavaScript. Yeah right I would not have thought that would happen a few years back. With the various browsers and their JS engines becoming more mature and FAST with each new release, it's hard to avoid it. Node.js, running on v8 (Chromiums's JS engine), is even doing a great job on the server side with its monothreaded, asynchronous conception. Anyway I thought I would share some tips on consuming a BMC Remedy ITSM 8 Out-of-the-Box SOAP web service with jQuery.

The function "getIncidentsList" is pretty straight forward. Instead of using a jQuery plugin or another library that would provide a SOAP client class that could handle any complex WS structure, I chose to directly send the XML in a SOAP message.
  function getIncidentsList(credentials)
  {
   $.mobile.loading('show');
   var wsURL='/arsys/services/ARService?server=' + credentials.server + '&webService=HPD_IncidentInterface_WS';
   var soapMessage ='\
          \
          \
          ' + credentials.username + '\
          ' + credentials.password + '\
          \
          \
          \
          \
          \'Assignee Login ID\'="' + credentials.username + '" AND \'Status\'<5\
          0\
          50\
          \
          \
       ';
   var jqxhr = $.ajax({
    url: wsURL,
    beforeSend: function( xhr ){
      xhr.setRequestHeader(
      "SOAPAction",
      "POST"
      );
    },
    type: "POST",
    dataType: "xml",
    data: soapMessage,
    success: callSuccess,
    error: callError,
    contentType: "text/xml; charset=\"utf-8\""    
   });
   return false;
  }
  
  function callSuccess(request,status)
  {
   $.mobile.loading('hide');
   $(request).find("ns0\\:getListValues").each(function()
   {
    $("#incidentslist").append('
  • '+$(this).find("ns0\\:Incident_Number").text()+'-'+$(this).find("ns0\\:Priority").text()+'

    '+$(this).find("ns0\\:Summary").text()+'

  • '); }); $.mobile.changePage($("#incidentspage")); } function callError(request,status,error) { $.mobile.loading('hide'); alert("error : " + error); }
    This code works when you serve it in an html file stored on a mid-tier. Simply pass the "credentials" array : username, password, server. Hmmm it tastes like Flex. Why ?
    • because I use jQuery's asynchronous calls features ($.ajax)
    • because both Flex (ActionScript) and JavaScript are dialects of ECMAScript
    The "$.mobile" comes with jQuery Mobile.