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.

    May 19, 2010

    How to consume AR System web services with Flex

    Note : This post was copied from BMCDN

    I can't just give the source because it won't make much sense (that's to not tell it's a horrible mess ...), but here are a few copy/paste that could help :

    First, you will need to import these :
    import mx.rpc.soap.SOAPHeader;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.soap.LoadEvent;
    import mx.rpc.soap.WebService;


    I declared these variables :

    public var _webServiceFields:WebService; // web service
    public var _webServiceFieldsLoaded:Boolean = false; // flag noting when wsdl has been loaded


    Then, you initialize your webservices and declare the events and their handlers (if you already know Flex, it's likely to be familiar to you ). FIELD_WS holds the complete URL for the WSDL file. You have to add the header for authentication.

    public function FieldsInit():void 
    {
    _webServiceFields = new WebService();
    _webServiceFields.wsdl = FIELDS_WS;
    var q1:QName=new QName("http://soapinterop.org/xsd","AuthenticationInfo");
    var header1:SOAPHeader = new SOAPHeader(q1, {userName:FIELDS_USER, password:FIELDS_PWD});
    _webServiceFields.addHeader(header1);
    // add listeners
    _webServiceFields.addEventListener(LoadEvent.LOAD, load_listener_fields);
    _webServiceFields.addEventListener(ResultEvent.RESULT, result_listener_fields);
    _webServiceFields.addEventListener(FaultEvent.FAULT, fault_listener);
    // load wsdl
    _webServiceFields.loadWSDL();
    }


    The fault listener is pretty generic :
    public function fault_listener(event:FaultEvent):void 
    {
    debug += event.fault.faultCode + "\n"+ event.fault.faultString + "\n"+ event.fault.faultDetail;texteditor.text = debug;
    }


    The load listener starts once loadWSDL() is done, and calls the GetField function below.
    public function load_listener_fields(event:LoadEvent):void 
    {
    debug +="WS Loaded ... Retrieving fields\n";
    _webServiceFieldsLoaded = true;GetFields();
    }


    The result listener fires when the result has been received.
    public function result_listener_fields(event:ResultEvent):void 
    {
    var i:int = 0;
    while (i < event.target.OpGetList.lastResult.list.length)
    {
    fields.addItem(event.target.OpGetList.lastResult.list.source[i].chrChamp);
    debug += "- " + event.target.OpGetList.lastResult.list.source[i].chrChamp + "\n";
    i++;
    }
    debug +=fields.length + " fields found\n";
    DataInit();
    }

    Finally, this function unleashes the power of your creation :
    public function GetFields():void 
    {
    if (_webServiceFieldsLoaded)
    {
    // is wsdl is loaded
    _webServiceFields.OpGetList(_source_Fieldstag);
    }
    else
    {
    FieldsInit();
    callLater(GetFields); // wait a frame and try again
    }
    }


    NB : Since then I have used Flex + WS in a production environment, and it's pretty reliable. But as an afterthought, I would have rather made it a datavisualization plugin.

    Nov 20, 2008

    Tour de Flex

    Tour de Flex is a desktop application for exploring Flex capabilities and resources, including the core Flex components, Adobe AIR and data integration, as well as a variety of third-party components, effects, skins, and more.

    Tour de Flex has three primary purposes:
    • Provide non-Flex developers with a good overview of what is possible in Flex in a “look and see” environment
    • Provide Flex developers with an illustrated reference tool
    • Provide commercial and non-commercial Flex developers a place to showcase their work



    Oct 20, 2008

    Still learning Flex - FlexChess

    Hey, I have had a good time these days, making this little chess game. I was thinking about making it a client for a real online chess project based on webservices. I'll just keep it in my "possible projects for bored times" case. It's already rather busy in there, but I do the dust from time to time.




    The Eclipse project zip is available here. Comments are in french.

    While I was looking for some inspiration, Alexandre directed me to this fantastic site. The guys at chesscube made a great 100% Flex chess site. The only thing that is boring me is the lack of design innovation. It just looks too much like another Flex site, and they are overusing this bling-bling reflection fashion for every single image. That's it for the negative part. All the rest is very, clear, easy, fluent, the chess board is extremely readable. That all makes it one of my favourite sites now.

    Jan 10, 2008

    Reading and extracting data from a word file attached to an email

    [Description]
    A customer receives intervention requests via email and wants to have them pushed as tickets in ITSM v7. These requests come a attached word files with a standard format.

    ITSM v7 runs on version 7.0.1 of ARS on Solaris.
    The customer won't change the format for a regular ARS-template-shaped email.

    [Solution]

    1/ Download antiword sources here and compile

    Antiword allows us to display the text contained in a word file.
    It is maintained as a package in various linux distributions like Debian or Fedora, and even available in Cygwin, but not on Solaris.
    It compiled like a charm on Solaris once gcc was installed.

    2/ Write a perl/bash+awk/foobar/... script

    I did this with perl, overusing conditions and regular expressions to generate a string that looks like this :
    field1=value1(separator)field2=value2(separator)field3=value3(separator)...

    The field identifier must be unique, and your (separator) must not be found in a value. I used ";" but something more complex like "@X@Y@Z@" or "Wh@t3v3R" for example would be a better choice.

    3/ Create an ARS form

    This is were attachments will be pushed and analyzed.
    You need :
    - a long field for the post-treatment string,
    - an attachment pool with one attachment field,
    - a temporary display only integer field,
    - a temporary display only character field [0],
    - an AttachmentID character field [40],
    - one field per word field

    4/ Push attachments to your form

    Add a filter to your "AR System Email Attachments" that pushes the document to your form if its name matches whatever its name should match.

    5/ Add filters to your ARS form

    - the first filter saves the .doc file into your temporary folder and executes your script to get the big string out of it and set it into the long field.
    - one filter per field :
    * set the location of the first occurence of the researched field name into the temporary integer field (STRSTR)
    Tmp_Int = STRSTR($String$, "headerdate=")
    * set the substring of the string starting from the fieldname to the end into the temporary character field (SUBSTR)
    Tmp_Char = SUBSTR($String$, $Tmp_Int$)
    * set the location of the first occurence of your separator into the temporary integer field (STRSTR)
    Tmp_Int = STRSTR($Tmp_Char$, "")
    * you have the beginning and the end of the value you are searching for, set the substring into the corresponding field of your form (SUBSTR)
    headerdate = SUBSTR($Tmp_Char$, + 1 , $Tmp_Int$ - 1)

    6/ Push the fields to a new ticket

    A last filter must now be able to push the data into the HPD:Interface_Create form.

    You can see my perl script here.