Hate to say it, but Powershell is cool!

Just to put it out there.
Some history.

There was Powershell. At first, I didnt quite understand its potential, and role in the Microsoft product suite. Then came the ‘not-quite-headless’ windows server. (I was like: oooh, It looks like Microsoft is Changing/learning and stripping overhead (read things that can potentially break, need maintenance, costs resources and money). Still I didn’t quite understand the PowerShell potential.

Last month a team member needed to install Oracle Fail Safe on a Microsoft 2012 box. He needed to run a Powershell script to set some things right and that didn’t quite work. Hating the fact not being of any help, I figured, lets spend some time on learning Powershell. Its time I (ex-Windows NT4,2K,2K3 guy) understand this puppy.

Then I came across this site: Microsoft Virtual Academy and followed the course.
Conclusion: Powershell (V3) is way more cool then I anticipated! Why?

At first I thought another Linux shell clone was being created. But don’t let yourself (like I was at first) be fooled by the Linux looking Pipe approach. Its not text being redirected, its objects. For those not understanding objects: Instead of sending  the ‘thingy description (text or parameter)’ over the pipe, its sending you the whole thing.

The simplest way to explain this is by example. The following command gets the directory (as an object), pipes the object to the select method, then we select object properties to output and manipulate “@{…}” some output while we are at it. (There are aliases for dir or ls if you prefer that and would have worked instead of get-childitem)

This Object approach makes you wickedly flexible as you can see.

Another cool thing is that you are not bound to the console. You can output to the console, but there are several nice, cool options. For example: output an Get-Help article to a window with the -ShowWindow parameter. Or output the table above to an Gridview.


If this wasnt cool enough yet, there are tons of very cool features that are incorperated. A few of many are: Updateable help-system, Remoting to PSsessions on machines, Remoting using sessions locally, Importing PS management modules from remote machines (so you dont need to install them), An PS webapplication for remote -mobile- management using powershell. Yeah, the list continues.

Microsoft lose the need for the explorer process and you regain my trust ;-)Definitely worth looking into is the free (Yeah ITS FREE) getting started training by Microsoft.


Back to Oracle Enterprise Linux
(Without the cool management interface, but still the OS I prefer in my backend)

Fix the inline images -bug- in glpi knowledgebase (htmLawed.php)

GLPI uses the htmLawed filter to clean inserted HTML code. Documentation on this framework can be found here: http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/

Problem with this framework in GLPI is that it does not match image tags properly when they contain inline base64 information.

Here is a simple fix to overcome this problem. The htmLawed.php file can be located in %glpi_root%/lib/htmlawed/htmLawed.php. Open it with your favorite editor. Next locate line: 47. Somewhere arround that area you should find the following.

Web - sftp___nagios@glpi.amis.nl_var_www_glpi_prod_lib_htmlawed_htmLawed.php - A_2013-10-29_12-34-30

Add ‘data’ at the end of the marked line.

$x = (isset($C['schemes'][2]) && strpos($C['schemes'], ':')) ? strtolower($C['schemes']) : 'href: aim, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, telnet; *:file, http, https, data';

The above will stop htmLawed from adding disabled: to the data: in the src=”” tag.

The next step is a bit trickier.

Now we need to actually change the hl_tag function. In the file locate the hl_tag($t) function somewhere around line:407. In this codeblock we are looking for the regular expression marked in the image below:

Web - sftp___nagios@glpi.amis.nl_var_www_glpi_prod_lib_htmlawed_htmLawed.php - A_2013-10-29_12-38-10

This is the expression that doenst match the valid <img> tags within the htmLawed. We dont want to create leaks here, so all we need to do is introduce an exception for our images. You can do so by replacing the text with the following:

Web - sftp___nagios@glpi.amis.nl_var_www_glpi_test_lib_htmlawed_htmLawed.php - A_2013-10-29_12-49-27

In code:

if(!preg_match('`^<(/?)([a-zA-Z][a-zA-Z1-6]*)([^>]*?)\s?>$`m', $t, $m)){
if(strstr($t, 'data:image')){
return $t;
return str_replace(array('<', '>'), array('&lt;', '&gt;'), $t);
}elseif(!isset($C['elements'][($e = strtolower($m[2]))])){
return (($C['keep_bad']%2) ? str_replace(array('<', '>'), array('&lt;', '&gt;'), $t) : '');

After this, the images should show up just fine

GLPI - Knowledge base_2013-10-29_12-50-51

I hope this was helpfull :)

Update GLPI tickets with requesters group

When using GLPI it can be very usefull to automatically assign a group based on the ticket requester. This allows you to use the reporting module and report for instance based on dept group.  A problem is that GLPI doenst ‘yet’ allow for a business rule to be created. For this reason we wrote a little script to process this for us.

Business Rules:
0. GLPI version : 0.83.7
1. GLPI uses the mailgate that creates tickets of known users.
2. All known users are assigned to at least one group
3. Groups are structured based on a hybrid model: Geo Group > Cust type > Customer name.
4. Script only seeks customer groups and then assigns them uniquely to the ticket.
5. Script will be triggered by cron
6. All actions will be reported in a mail
7. If no actions where executed, no mail will be send.

$usr = 'john'; $pas = 'doe'; $db = 'glpi_0837';</pre>
$db = new mysqli("localhost", $usr, $pas, $db);
 printf("Connect Failed %s\n", mysqli_connect_error());
/* Get all the tickets */
$s1 = 'select t.id, t.users_id_recipient from glpi_tickets t';
$r1 = $db->query($s1);
while($row = $r1->fetch_array(MYSQLI_ASSOC)){
 // check to see if ticket has a group assigned //
 $s2 = "select * from glpi_groups_tickets where tickets_id = '{$row['id']}' and type = '1'";
 $res1 = $db->query($s2);
 // Update the tickets without a group assignment.
 if($res1->num_rows == 0){
 // There is no group for this ticket so find the applicable group and assign it
 $s3 = "select ti.id as tid,
 tu.id as tuid,
 gr.id as gid,
 gr.name as group_name,
 FROM glpi_tickets ti, glpi_tickets_users tu, glpi_groups gr, glpi_users us, glpi_groups_users gu
 WHERE ti.id = tu.tickets_id
 AND tu.type = 1
 AND tu.users_id = us.id
 AND tu.users_id = gu.users_id
 AND gu.groups_id = gr.id
 AND ti.id = '{$row['id']}'";
 if($res2 = $db->query($s3)){
 if($res2->num_rows > 0){
 while($row1 = $res2->fetch_array(MYSQLI_ASSOC)){
 $groups[$row1['tid']][$row1['gid']] = $row1['group_name'];
 $messages[$row['id']][] = "INFO: Updated ticket:{$row1['tid']} with group {$row1['gid']}:{$row1['group_name']}";
 $messages[$row['id']][] = 'ERROR: No group assigned to requester!';
 $messages[$row['id']][] = "INFO: Please assign groups to the requester in this ticket.";
 $messages[$row['id']][] = "ERROR: SQL errorno: {$db->errno} met melding: {$db->error} is opgetreden";
 //$messages[$row['id']][] = 'INFO: Ticket allready has a group assigned';

// Generate a mailmessage
$message = 'INFO: Script running at: https://glpi.amis.nl/salami/automated_tasks/assign_actor_groups.php <br/>';
$ecount = 0;
 foreach($messages as $key => $val){
 foreach($val as $k => $v){
 $message .= "ON Ticket: $key : {$v} <br/>";
 $ecount ++;
 $mail = true;
 $mail = false;

// Insert the associations
 foreach($groups as $key => $val){
 foreach($val as $k => $v){
 $sql = "insert into glpi_groups_tickets(tickets_id, groups_id, type) values('{$key}','{$k}','1');";
 //$message .= "INFO: Group $k:$v assigned to ticket $key<br/>";
 $message .= "ERROR: Failed to associate $k:$v to ticket $key<br/>";
 $message .= "ON General : Finished... <br/>";
 $message .= "ON General : Did nothing, but finished with succes... <br/>";
if($ecount > 0){
 $message .= "ON General : INFO: Please correct the reported errors <br/>";

$to = 'AMIS Support <support@amis.nl>';

$subject = 'Automated ticket - groups assignment';

// To send HTML mail, the Content-type header must be set
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

// Additional headers
$headers .= 'From: Monitor <monitor@amis.nl>' . "\r\n";

// Mail it
 mail($to, $subject, $message, $headers);
//echo $message;


Simply run this script

What is cloud you ask?

In the past months I have heard various answers on the question: ‘whats the definition of cloud.’
When I learned a student  wrote a scripture on the subject and passed with: ‘its actually colocation’, I knew it was time to get involved.


Here I am, trying to formulate one, ‘ultra-short’ conclusive answer to the question: ‘What is Cloud’.

Used subject: Dropbox, an application that allows you to store, access and share specific content. Broadly used as an ‘Cloud’ example. An solution that hugely simplifies a huge amount of infrastructural decisions that need to be taken to make this functionality widely available and widely usable and understood. Decisions like: how should data be accessed, how should data be transported, how and where should data be stored, do we differentiate jurisprudence based on geo location, how should this data be encrypted, is this 3rd party allowed to access this content, how to guarantee accessibility to your data, how to backup this data, how should the user interact with its data, how to counter abuse, virals etc, etc.

My definition: “Cloud: A hugely simplified web solution that provides in a very specific customer need.”

Any improvements on the subject?

Let me know :)

Lessons learned :)

Reminder to self…

“Never move too fast”
Its often better to slow down, take a moment, consider all the options, formulate a short term goal, move forward and reflect.

Check_VM for Oracle VM and Nagios.

Personal backup…

Refinements might be added if bugs or improvements are found. So keep an eye out for newer versions ;-)

This script might also be compatible with other  Xen clones.

# Author : Chris Gralike
# Company: AMIS Services BV
# Simple but effective Oracle VM check command for use with nagios
# This command checks the state of any given VM machine using the XM command.
# It will try to match the friendly name as well as the system name.
# It will return OK - and usefull metadata on succes, NOK on failure.
# usage : check_xm vmname
# ########################

use strict;                     # Good practice
use warnings;                   # Good practice

my (@data, @values, @name, $vmname, $vmcheck, $i, $result);

# Get the command parameters
if( ($#ARGV + 1) == 1 ) {
$vmname = $ARGV['0'];
print "usage: ./check_xm vmname \n";
exit 1;

# Perform the actual test
open(XM, "xm list|");
$i = 0;
if($i > 0){
# Split the output in portions
@data = split(" ", $_);
# Get the human readable name
@name = split('_', $data['0']);
$name['1'] = 'dezeisnietingebruik!';
if(($vmname eq $name['1']) || ($vmname eq $data['0'])){
print "OK - $data['0'] is active with Id:$data['1'] $data['3']CPUs $data['2']M \n";
exit 0;
close XM;

# If the loop was finished without result, then there is a problem!
print "NOK - $vmname is not running on this server\n";
exit 2;

Essence of Business Intelligence?

You can only effectively control the breaks and throttle, when you know the type of car you are driving, type of breaks and throttle and how to handle them, break and throttle effect when you use them, current speed, effective speed limit, the environment you drive the car in, the reason to why you are driving at all….

Oh, you get the point…

Some nice articles to get you going (sadly most are written in Dutch).



Extract all content to disk from a SPS2007 content DB using PHP

Today I ran into a problem. We needed to migrate a huge amount of data from an old SharePoint 2007 content database without the availability of the MOSS front-end. All i had was the database and a corrupted sharepoint install that wasnt going to help me allot.

To overcome this problem I decided to write a little PHP application that would do this task for me. I allready had WAMP setup on my desktop, so i figured this to be the quickest route. Then i figured, maybe other people face this problem as well. So here it is, the code, and some helpers to get you going.

* @name           : index.php - MSSql Content connector
* @Author        : Chris Gralike
* @version        :
* @copyright     : WETFYWTDWI - what ever ** you want to do with it, no guarantees :)
*  This script ONLY READS the database tables, so dont give it more permissions :)

// What to search for in the directory structure.
$search = '';
// Where too put the files
$createdir = './Downloaded';
// What server too connect to.
$ServerName = 'amisnt05.amis.local';
// Database connection parameters.
$connectionInfo = array('Database' => 'MOSS_PROD_WSS_Content_WebApp02',
'UID' => 'php_login',
'PWD' => 'welcome12345678');
// This can be a very long task to complete, so disable the timelimit.
// Create a connection
$conn = sqlsrv_connect($ServerName, $connectionInfo)
or die( print_r( sqlsrv_errors(), true));

// The SQL statment to query the AllDocs tables.
$tsql = "SELECT dbo.AllDocs.Id,
dbo.AllDocStreams.Id as StreamId,
FROM dbo.AllDocs
RIGHT OUTER JOIN dbo.AllDocStreams ON dbo.AllDocs.Id = dbo.AllDocStreams.Id
WHERE AllDocs.DirName LIKE '%{$search}%'
AND AllDocs.SetupPath IS NULL
AND AllDocs.Extension != ''
// The result set
$result = sqlsrv_query($conn, $tsql);

// Process the results
while($row = sqlsrv_fetch_array($result,  SQLSRV_FETCH_ASSOC)){
// When create is true, then it will create the folders in
// in the foreach
$create = false;
$dirptr = $createdir;

// Find the folders and recreate them starting from the searchstring.
$folders = explode('/', $row['DirName']);
foreach ($folders as $val){
if($val == $search || $create == true || empty($search)){
$create = true;
$dirptr .= '/'.$val;
echo "INFO: created $dirptr <br/>";
echo "WARN: skipping $dirptr allready exists. <br />";

// Recreate the file
$filepath = $dirptr.'/'.$row['LeafName'];
if($fp = fopen($filepath,'w')){
fwrite($fp, $row['Content']);
echo "INFO: file {$row['LeafName']} written. <br />";
echo "ERROR: file {$row['LeafName']} could not be written in $filepath. <br />";
// Close the database connection.

Simply configure the first vars in the script and run the file. It might take a huge while before you get some output.

TIP: Use the $search to narrow down the query a bit.
It searches the DirName (I.e. Site\DocLib\Folder\SubFolder\)

The output will look like this.

INFO: created ./Downloaded/SearchCenter
INFO: created ./Downloaded/SearchCenter/Pages
INFO: file facetedsearch.aspx written.
WARN: skipping ./Downloaded/SearchCenter allready exists.
WARN: skipping ./Downloaded/SearchCenter/Pages allready exists.
INFO: file resultskeyword.aspx written.

Then please leave a comment :-)

WARNING!: YOU NEED THE Microsoft MSSQL DRIVER FOR PHP, not the old php equivalent.
here are some tips on where to get it. My version was php 5.3.8

First off, mssql isnt supported out of the box anymore. when using PHP 5.2 and up, you need to get the Microsoft for PHP driver. Check this site for more information : http://sqlsrvphp.codeplex.com/

Its a bit of an hassle ill give you that.
Challenge: I needed 1.5hours to find the correct Lib,Install,Coding info and get it working.

Basically it requires you to download the native client, the drivers and an correct update of the php.ini your wamp instance is using.

Tip: Use <?php phpinfo() ?> to find the right version for your PHP compilation.
Search for : PHP Extension Build : API20090626,TS,VC9


Be sure to verify the SQL query inside the $tsql=” var and alter it accordingly. The other part should be pretty straight forward.

networkmapping to sharepoint using VBS.

Some details need allot explaining, so ill just reference to the sources containing the needed information.

First, make sure the Clients WebClient is configured correctly. Configured incorrectly the WebClient will cause headaches. So make sure you read and understand “basic Authentication, and SSL.” Then read this: http://blogs.msdn.com/b/robert_mcmurray/archive/2008/01/17/webdav-redirector-registry-settings.aspx

Next figure out, what version of windows you are running. There are differences between XP (usually working just fine), Vista, Win7, Win8. Afterward read this: http://support.microsoft.com/kb/9410503

finally create a script to test your environment:

Dim objNetwork
Set objNetwork = CreateObject("Wscript.Network")
objNetwork.MapNetworkDrive "G:", "\\your.sharepoint.link.tld@SSL\site\Shared Documents\"
Wscript.Echo "Script completed!"

Cant wait…

After reading this benchmark: http://blog.centreon.com/public/Centreon_Engine_Benchmarks.pdf, I was wondering. isn’t it strange that their own benchmark is telling us they beat the good-old-nagios on all elements?

Do not get me wrong, I still believe that Centreon is a wonderful product. But i cant ignore the fact that the Nagios Core / Nagios XI are on the move as well.  And for some reason I get the feeling they are referring to history. Last time I was informed,  Nagios employed a team of developers as well in developing Nagios XI. And next to that, Nagios also enables OS programmers to commit code: http://www.nagios.org/contribute.

Please dear Centreon, don’t spoil your good name and stick to the facts. You have a great product, no need for bashing. Next to that, don’t use a translate without review in your benchmark documents.

Having that said, what happed to Icinga?

It seams that Icinga is well on their way as well seeing this sheet: https://www.icinga.org/nagios/feature-comparison/

Anyway, any monitoring needs?

It seems a crossroad is nearing in which you are forced to pick a side and stick by it.

And yet somehow, I cant suppress a feeling of sadness about this development.
Goodbye years of scripting, hacking and rewriting happiness, Hello ‘next-next-finish’ world ;-)

Any insights?
Please share them with us web reading it-guy folk  :=)


Get every new post delivered to your Inbox.

Join 52 other followers