Dec 18

Adding Path variables for Node.js and npm

I broke the LinkedIn Node.js group discussion board otherwise I would have put this information there. I have finally worked out what the problem is with the path set up when trying to use Node Package Manager (npm) on the IBM i. The problem started with how I was trying to set the PATH variable in the shell, it appears that the BASH shell does not like the ‘export PATH=$PATH:/newpath’ request, it always sends back an invalid identifier message and does not set the PATH variable. After some Google work I found a number of forum posts where others had fallen into this trap, the problem is the way that BASH interprets the $variable settings.

I am not really clear on why the BASH shell is the problem but I did find a work around. If you set the variable and then export it the variable is correctly set for the environment, so ‘PATH=$PATH:/newpath’ and then ‘export PATH’ works just fine. This was not the end of it though because even though I has set the PATH variable correctly for the environment the npm requests did not run and complained about libstdc++.a not being found! Running the request in the ../Node/bin directory did allow the request to run correctly but being outside that directory did not. I did some more research and found that the way to get around this is to set the LD_LIBRARY_PATH so it picks up the objects in the ../Node/bin library. This is done as above by setting the variable and then exporting it ie: ‘LD_LIBRARY_PATH=/QOpenSys/QIBM/ProdData/Node/bin’ and then ‘export LD_LIBRARY_PATH’

I will now build a .profile in my home directory to set these on starting the terminal session..

Chris…

Dec 17

Node.js up and running on IBM i

We have Node.js up and running on two of our systems. Our initial attempt failed due to a problem with PTF’s on V7R1 but with IBM’s help we finally got everything up and running.

We have 2 working instances of Node.js running, one on V7R1 and one on V7R2. I have listed below some of the actions we took as part of the installation so that others should be able to follow, we did spend a lot of time and effort getting to a working setup with many of them being dead ends so we have left those out..

First of all you need to make sure you get TR9 installed, I would strongly suggest that you also download and install the latest CUM and PTF groups. When you read the documentation on the IBM Developer website you will notice that it asks for SF99368 at level 31 for V7R1 and SF99713 level 5 for V7R2, these are not available at present so just get the latest for your OS and for V7R1 install and additional PTF SI55522. It does not install on V6R1 so upgrade if you want to try it out.

Now that you have your System running the latest PTF’s and TR9 you can start to install the Node.js LPP from IBM. You will need a SWMA contract to get the download from the IBM ESS website, it is available under the SS1 downloads as 5733-OPS. It is available as a .udf file which can be used with an IMGCLG to install. If you don’t have the ability to set up an IMGCLG you could download the file, unzip everything and then go to the .udf file (note the package has a directory which ends in .udf!) once you have the file you should be able to convert the content to a .iso file and use it in the DVD drive of the IBM i. (Note: we struggled to find a way to convert the .udf to a .iso but a google search does show some options on how to achieve it, for us setting up the IMGCLG was by far the easiest route.)

You install the LPP using the IBM LICPGM commands, it will install the Node.js objects in the IFS ready for use. We created a link to the directory (ln -s /QOpenSys/QIBM/ProdData/Node/bin /Node) to make things easier as typing the path in every time was a real chore. You could amend the paths etc but we had varying success with that.

To test everything works you can use npm -v (npm is the node package manager) which should return the version installed (1.4.14). If that works you now have Node.js up and running.. Next we wanted to test the ability to install packages, the documentation does mention this requires some additional open source binaries to be installed. The best instructions we found for doing this are on the YIPS site. They are a little daunting when you first look at all of the command line stuff you have to do, but after some careful thought and review they are very simple to follow. (The YIPs site was down when we wrote this so we could not verify the link). We installed the curl,python and gcc binaries because we wanted to have as much covered as possible for testing. (Note about the aix versions, as you are only installing on V7R1 and above, aix6 are the ones you need.)

Once you have the binaries installed you can then go ahead and test installing a few packages, we did twilio and express, express is considered a good start for most. If you have any problems check out the node.js group (sub group of IBM i Professionals) on LinkedIn, someone will probably help you faster there than anywhere else at this time.

I would also recommend a couple of other things to do as part of setting up the environment ready for your first test. I installed SSHD and putty for the terminal, it is far better than using QSH or qp2term on the IBM i and it appears faster?? I also used RDi as the editor for creating the scripts for testing (plenty of test scripts out there on Google) because it was much easier than trying to use any editor in the shell (vi etc) or using edtf from a command line. Maybe at sometime IBM will provide a code parser for RDi? I am sure other IDE’s can be used as well just as long as you set up shared folders etc on your IBM i.

We have already seen a few flaky things happening which have cleared up and further retries of the same command and I am sure there are going to be others, it is very new and we expect to break a few things as we go along. As we find things out we will post our progress and post some sample scripts we use to investigate the various features on node.js on IBM i, not sure how far we will take this but it does seem pretty powerful technology so far.. Next we need some documentation on the os400 features :-)

Chris…

Dec 13

Linking IBMi data to a Gauge in PHP

We were thinking about how to create a new interface for one of our old utilities using PHP and decided that using a JavaScript based gauge would probably be a good start. There are plenty of free and chargeable JavaScript utilities out there that would do what we wanted, the one we settled on was a HTML5 Canvas implementation developed by Mykhailo Stadnyk. He has placed the code on the web and agreed to anyone running the code under a MIT license which basically allows you to copy and use the code where ever you want. If you would like to use the code it is available here, simply copy the javascript file into your directory structure and include.

We made a couple changes to the javascript code as it calls a remote HTTP server to pull back a font so we found a substitute font and installed it on the PC. There are a couple of examples available which can be used to demonstrate the gauge in action which again we used as the basis for our test. The only other point we should mention is that the demo does rely on HTML5 and canvas, if it is not supported in your browser the test will not work!

The method used to get the data from the IBMi is to call a Service Program through the i5_program_call available in the Aura i5_toolkit. Below is the C Program to return the information, it just calls the QWCRSSTS API and returns the Pct_Processing_Unit_Used value as can be seen in the code below.


#include <stdio.h> /* Standard I/O */
#include <stdlib.h> /* Standard library */
#include <string.h> /* String handlers */
#include <qusec.h> /* Error Code */
#include <errno.h> /* Error Num Conversion */
#include <decimal.h> /* Decimal support */
#include <qusec.h> /* Error Code */
#include <qwcrssts.h> /* System Status */
#pragma comment(copyright,"Copyright @ Shield Advanced Solutions Ltd 1998-2001")

typedef _Packed struct EC_x{
Qus_EC_t EC;
char Exception_Data[1024];
} EC_t;

int Get_Svr_Status(char *CPU_Util,char *reset) {
double Cpu_Pct;
char Reset[10] = "*NO "; /* Reset CPU % */
Qwc_SSTS0200_t Buf; /* System Status Struct */
EC_t Error_Code = {0}; /* Error Code Struct */

Error_Code.EC.Bytes_Provided = sizeof(Error_Code);
// reset the CPU Utilization?
if(*reset == 'Y')
memcpy(Reset,"*YES ",10);
QWCRSSTS(&Buf,
sizeof(Buf),
"SSTS0200",
Reset,
&Error_Code);
if(Error_Code.EC.Bytes_Available > 0) {
sprintf(CPU_Util,"99999");
return -1;
}
// Just set up the CPU Utilization here
Cpu_Pct = (double)Buf.Pct_Processing_Unit_Used / 10;
sprintf(CPU_Util,"%f",Cpu_Pct);
return 1;
}

The web page is generated using the following code.


<?php
/*
Copyright © 2010, Shield Advanced Solutions Ltd
All rights reserved.

http://www.shieldadvanced.ca/

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

- Neither the name of the Shield Advanced Solutions, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/
// start the session to allow session variables to be stored and addressed
session_start();
require_once("scripts/functions.php");
// load up the config data
if(!isset($_SESSION['server'])) {
load_config();
}
$conn = 0;
$_SESSION['conn_type'] = 'non_encrypted';
if(!connect($conn)) {
if(isset($_SESSION['Err_Msg'])) {
echo($_SESSION['Err_Msg']);
$_SESSION['Err_Msg'] = "";
}
echo("Failed to connect");
}
// get the information
get_cpu_util($conn);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html style="width:100%;height:100%">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Gauge Test</title>
<script src="jscripts/gauge.js"></script>
<style>body{padding:0;margin:0;background:#222}</style>
</head>
<body style="width:100%;height:100%">
<canvas id="gauge"></canvas>
<div id="console"></div>
<script>
var gauge = new Gauge({
renderTo : 'gauge',
width : document.body.offsetWidth,
height : document.body.offsetHeight,
glow : true,
units : 'Cpu Utilization',
title : false,
minValue : 0,
maxValue : 110,
majorTicks : ['0','10','20','30','40','50','60','70','80','90','100','110'],
minorTicks : 2,
strokeTicks : false,
highlights : [
{ from : 0, to : 50, color : 'rgba(240, 230, 140, .25)' },
{ from : 50, to : 70, color : 'rgba(255, 215, 0, .45)' },
{ from : 70, to : 90, color : 'rgba(255, 165, 0, .65)' },
{ from : 90, to : 100, color : 'rgba(255, 0, 0, .85)' },
{ from : 100, to : 110, color : 'rgba(178, 34, 34, .99)' }
],
colors : {
plate : '#fff',
majorTicks : '#f5f5f5',
minorTicks : '#ddd',
title : '#fff',
units : '#0bb',
numbers : '#0aa',
needle : { start : 'rgba(240, 128, 128, 1)', end : 'rgba(255, 160, 122, .9)' }
}
});
gauge.onready = function() {
gauge.setValue( <?php echo($_SESSION['CPU_Util']); ?> );
};

gauge.draw();

window.onresize= function() {
gauge.updateConfig({
width : document.body.offsetWidth,
height : document.body.offsetHeight
});
};
</script>
<?php ?>
</html>

To call the Service Program we created a function ‘get_cpu_util()’ which is called every time the page is refreshed. Here is the code for the get_cpu_util function.


function get_cpu_util($conn) {
$desc = array (array ("Name" => "CPU_Util", "io" => I5_INOUT, "type" => I5_TYPE_CHAR, "length" => "5"),
array ("Name" => "Reset_Status", "io" => I5_IN, "type" => I5_TYPE_CHAR, "length" => "1") );
$prog = i5_program_prepare("PHPTSTSRV(Get_Svr_Status)", $desc,$conn);
if ($prog == FALSE) {
$errorTab = i5_error ();
echo "Program prepare failed Display_Server_Status <br>";
var_dump($errorTab);
var_dump($conn);
die ();
}
$parmOut = array("CPU_Util" => "cpu_util");
$parameter = array("CPU_UTIL" => "", "Reset_Status" => "N");
$ret = i5_program_call($prog, $parameter, $parmOut);
if (!$ret) {
throw_error("i5_program_call failed Retrieve_Status <br>");
exit();
}
// close the program call
i5_program_close($prog);
$_SESSION['CPU_Util'] = $cpu_util;

return 1;
}

The majority of the work is done in the Javascript section above with just the data extraction from the IBMi being carried out using the i5_toolkit. We have used the same connection function that we used in our other tests but instead of asking for the profile and password we added it to the config file so no sign on screen is presented before the connection is made.

The above code resulted in the following output on our systems. The actual CPU utilization differs because it is near impossible to request the page and refresh the 5250 screen at the same time. We also noticed that the returned value is always greater than the actual value shown in the WRKACTJOB screens, but the test was more about showing the gauge working using IBMi data than ensuring we saw the same data in both interfaces.

5250 Work with Active Jobs

5250 Work with Active Jobs

Gauge showing CPU Utilization %

Gauge showing CPU Utilization %

We feel this is where modernization of the IBMi and its applications should begin, making simple tools and utilities that use the IBMi data and display it in a web based interface means you can access those interfaces from many devices. We only show the output in a PC based browser but with some simple CSS and checking code you could make sure it is correctly displayed on most devices.

Happy PHP’ing.

Chris..

Aug 13

New HA4i / RAP interface progressing


We have had a number of comments about the new interface we developed for DR4i which is our Disaster Recovery solution for the IBM i and many asking when we will provide the same kind of monitoring interface for our RAP product.

We have been developing a new release of RAP which should be available in the 4th qtr of this year and took the opportunity to clean up the product and add the new apply technology we developed for the DR4i product. This gave us the ability to use the same PHP code on the new product as we developed for DR4i to show the apply processes. However the sending system status has to be collected as well, which requires additional code to complete. We did consider a couple of options to handle this with the data being pulled from both systems via PHP using sepearate EasyCom Server installs back to a single HTTP server, but after some deliberation we decided to use a new transport mechanism which is part of RAP to pull the data back to the target system before dispatching it to the PHP/HTTP server. This save on complexity and cost as you now only need a single HTTP or EasyCom server instance which is running on the target system.

The first changes we made were to add the status for the additional servers which already run on the source system, we had 2 servers for the object replication process and added a new server for the status distribution (This will also provide some level of synchronization from target to source when fully developed). Next we needed to show the object replication status and what the audit journal state was, we liked the splitting of the journals on DR4i so it was a fairly simple decision to add the Audit Journal in the same manner. Once we had this in place we just needed to add some additional data screens to show the information related to the monitors such as a list of profile and object replication errors plus any waiting object replication requests.

Here are the new screens so far. First is the sign on screen, because we have some Javascript functionality built in we needed to sense if it was going to work, the sign on screen now shows a warning if Javascript is disabled. An important design requirement is that anything which requires Javascript is not critical to the overall feel of the interface, as we are primarily using this as a monitoring interface we can ignore any buttons or screen displays which do not work when Javascript is disabled or provide alternative methods to complete the task.

SignOn

Sign On Screen

Next we have the main display, you can now see the source servers and the object replication status all in one place, much better than having to use 2 systems and multiple screen to get the information!

Main screen

Main Monitoring screen

If we have any profile errors you can get a list to see what they are, not a lot of data and pretty simple but it is not meant to be hard…

Profile_Error

List of Profile Errors

The last screen we developed was the object replication errors, this shows the details about the error plus any relevant information such as the command used or the path to the object.

Object_Error

List of Object Errors

We are still working on additional functionality but feel we are heading in the right direction, using EasyCom as the PHP i5_Toolkit server is definitely working out for us and it will be suggested to anyone who is going to run our PHP based interfaces. Next task will be to extract and show a list of the objects which are waiting replication.

If you would like to know more about the PHP EasyCom server or any of our products, please let us know and we will happily show you what we are doing.

Chris…