From b1c230e228e8817a009bd74a019dcc0fa62a06b4 Mon Sep 17 00:00:00 2001
From: Têko MIHINTO <tmihinto@Tekos-Mac-mini.local>
Date: Dec 02 2018 22:24:53 +0000
Subject:  First commit of IPA and 389-ds Monitoring Tool ( SLIM ).


Signed-off-by: Têko MIHINTO <tmihinto@redhat.com>

---

diff --git a/montool/agent/389-ds_monitor.sh b/montool/agent/389-ds_monitor.sh
new file mode 100644
index 0000000..0e038dc
--- /dev/null
+++ b/montool/agent/389-ds_monitor.sh
@@ -0,0 +1,267 @@
+#!/bin/sh
+# BEGIN COPYRIGHT BLOCK
+# Copyright (C) 2018 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details. 
+# END COPYRIGHT BLOCK
+#
+
+. /usr/share/dirsrv/data/DSSharedLib
+
+SERVID=${SERVID}
+BINDDN=${BINDDN:-"cn=Directory Manager"}
+BINDPW=${BINDPW:-""}
+VERBOSE=${VERBOSE:-0}
+NB_SAMPLES=${NB_SAMPLES:-10} # Number of LDAP entries to keep.
+
+INTERVAL=${INTERVAL:-5} # Default monitoring interval is 5 seconds.
+
+#
+# DO NOT MODIFY
+#
+GLOBAL_MONITOR_ENTRY="cn=monitor"
+#MONITORING_ENTRY="cn=Monitoring Tool, cn=monitor"
+CONFIG_FILE=""
+HOST=""
+PORT="-1"
+LDAP_PID="-1"
+
+# To log debug messages
+
+logMessage(){
+if [ $VERBOSE -ne 0 ]
+then
+    echo $1
+fi
+}
+
+# Basic checks:
+runBasicChecks(){
+
+CONFIG_FILE=/etc/dirsrv/slapd-${SERVID}/dse.ldif
+logMessage "Configuration file is $CONFIG_FILE"
+
+if [ ! -f $CONFIG_FILE ]
+    then
+        echo "Configuration file " $CONFIG_FILE "not found!"
+        echo "Exiting..."
+        exit 1
+fi
+# TODO
+# Check presence of LDAP tools / gzip / top ...
+
+}
+
+setGloblalVariables(){
+
+# Set local variables:
+PORT=$(grep -i 'nsslapd-port' $CONFIG_FILE | awk '{print $2}' )
+HOST=$(grep -i 'nsslapd-localhost' $CONFIG_FILE | awk '{print $2}' )
+logMessage "PID file is /var/run/dirsrv/slapd-${SERVID}.pid"
+LDAP_PID=$( cat /var/run/dirsrv/slapd-${SERVID}.pid ) 
+logMessage "HOST is $HOST"
+logMessage "PORT is $PORT" 
+logMessage "PROCESS ID is $LDAP_PID" 
+
+}
+
+checkMonitoringEntries(){
+# If the entry "cn=Certificates,$MONITORING_ENTRY" exists, then its parent is already present.
+ldapsearch -xLLL -D "$BINDDN" -w "$BINDPW" -b "cn=Certificates,$MONITORING_ENTRY" -h $HOST -p $PORT -sbase  1.1
+res=$?
+if [ $res -eq 0 ]
+    then
+    logMessage "Entry $MONITORING_ENTRY already created"
+    logMessage "Entry cn=Certificates,$MONITORING_ENTRY already created"
+    else
+    logMessage "Monitoring entries are missing... Will create them."
+    logMessage "Adding entry $MONITORING_ENTRY..."
+    ldapmodify -x -D "$BINDDN" -w "$BINDPW" -h $HOST -p $PORT -a << EOF
+dn: $MONITORING_ENTRY
+objectClass: ldapSubentry
+objectClass: applicationProcess
+objectClass: top
+description: Entry to store CPU and memory usage data.
+
+EOF
+    res=$?
+    logMessage "LDAP ADD result code is: $res"
+    if [ $res -ne 0 ]
+    then
+        if [ $res -eq 68 ] # Already exists (68)
+        then
+            logMessage "Entry $MONITORING_ENTRY already created"
+        else
+            logMessage "Cannot create entry $MONITORING_ENTRY ! Exiting..."
+            exit $res
+        fi
+    fi
+    logMessage "Adding entry cn=Certificates,$MONITORING_ENTRY..."
+ldapmodify -x -D "$BINDDN" -w "$BINDPW" -h $HOST -p $PORT -a << EOF
+dn: ou=Certificates, $MONITORING_ENTRY
+objectClass: ldapSubentry
+objectClass: organizationalUnit
+objectClass: top
+description: Entry to store certificate data.
+
+EOF
+    res=$?
+    logMessage "LDAP ADD result code is: $res"
+    if [ $res -ne 0 ]
+    then
+        if [ $res -eq 68 ] # Already exists (68)
+        then
+            logMessage "Entry cn=Certificates,$MONITORING_ENTRY already created"
+        else
+            logMessage "Cannot create entry cn=Certificates,$MONITORING_ENTRY ! Exiting..."
+            exit $res
+        fi
+    fi
+fi
+}
+
+
+doMonitoring(){
+
+# Grab data every "$INTERVAL" seconds:
+
+# LDAP process
+cpu_ldap="-1"
+cpu_global="-1"
+mem_ldap="-1"
+# Global info
+cpu_global_user="-1"
+cpu_global_sys="-1"
+cpu_global_idle="-1"
+mem_global_total="-1"
+mem_global_used="-1"
+mem_global_free="-1"
+mem_global_avail="-1"
+
+
+logMessage "Starting monitoring loop..."
+
+slot=0
+
+while [ true ]
+    do
+    # Reset $slot once we reach the number of samples
+    if [ $slot -eq $NB_SAMPLES ]
+        then
+        logMessage "Resetting the slot number."
+        slot=0
+    fi
+
+    slot=$( expr $slot + 1 )
+    logMessage "Replacing data at slot NUMBER $slot"
+
+# computed by top ( more accurate than ps ) and I only keep the second iteration
+# as the first one is usually less accurate:
+#[root@alps2 ~]# top -b -n 2 -d 5 | grep "^ 2240 " | awk '{print $9 , $10}'
+# 0.0 5.3
+# 0.2 5.3
+#[root@alps2 ~]#
+#
+
+#
+#   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                                                                                                                                   
+# # top -b -n 1 | grep "^ 2240 "
+# 2240 dirsrv    20   0  921060  96764  34680 S   0.0  5.3  63:26.22 ns-slapd
+#
+# CPU is $9 and MEM is $10
+
+# TODO ==> How to skip the first iteration but not wait for too long?
+# # top -p $LDAP_PID -b -n 2 -d 2.5 | grep "ns-slapd" | awk '{print $9 , $10}'
+#0.0 3.3
+#0.4 3.3
+# # top -p $LDAP_PID -b -n 2 -d 0.5 | grep "ns-slapd" | awk '{print $9 , $10}'
+#0.0 3.3
+#0.0 3.3
+# #
+
+data_ldap=$(top -p $LDAP_PID -b -n 1 | grep "ns-slapd" | awk '{print $9 , $10}') #
+logMessage  "top output ==> $data_ldap" 
+cpu_ldap=$( echo $data_ldap | awk '{print $1}' )
+mem_ldap=$( echo $data_ldap | awk '{print $2}' )
+logMessage  "LDAP process CPU:  $cpu_ldap" 
+logMessage  "LDAP process MEM:  $mem_ldap"
+
+#
+# %Cpu(s): 18.6 us,  4.3 sy,  0.1 ni, 76.0 id,  0.1 wa,  0.7 hi,  0.4 si,  0.0 st
+
+cpu_global=$( top -b -n 1 | grep ^%Cpu | awk '{print $2, $4, $8}' )
+logMessage "top output ==>  $cpu_global" 
+cpu_global_user=$( echo $cpu_global | awk '{print $1}' )
+cpu_global_sys=$( echo $cpu_global | awk '{print $2}' )
+# # echo "%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st" |grep ^%Cpu | awk '{print $2, $4, $8}'
+# 0.0 0.0 id,
+#
+# There could be issue if idle CPU is at 100%
+# To fix by using other separators as user and system CPU could also be 100%
+cpu_global_idle=$( echo $cpu_global | awk '{print $3}' )
+if [ "$cpu_global_idle" = "id," ]
+then
+	cpu_global_idle="100" 
+fi
+
+logMessage "Host total CPU User: $cpu_global_user" 
+logMessage "Host total CPU Sys : $cpu_global_sys"
+logMessage "Host total CPU Idle: $cpu_global_idle" 
+
+# Memory in KB ( -k is the default option )
+# $ free | grep ^Mem: | awk '{print $2, $3, $4, $7}'
+# 11988864 3207184 6094304 8586224
+
+mem_global=$( free | grep ^Mem: | awk '{print $2, $3, $4, $7}' )
+logMessage "free output ==> $mem_global"
+
+mem_global_total=$( echo $mem_global | awk '{print $1}' )
+mem_global_used=$( echo $mem_global | awk '{print $2}' )
+mem_global_free=$( echo $mem_global | awk '{print $3}' )
+mem_global_avail=$( echo $mem_global | awk '{print $4}' )
+logMessage "Host total memory (KB)    : $mem_global_total" 
+logMessage "Host used memory (KB)     : $mem_global_used" 
+logMessage "Host free memory (KB)     : $mem_global_free" 
+logMessage "Host available memory (KB): $mem_global_avail" 
+
+# Build the LDAP entry:
+current_date=$( date +%s )
+# Format is "description;<SLOT>: <DATE>#<CPU_LDAP>:<MEM_LDAP>#<CPU_USER>:<CPU_SYS>:<CPU:IDLE>#<MEM_TOTAL>:<MEM_USED>:<MEM_FREE>:<MEM_AVAILABLE>
+entry_attr="description;$slot"
+entry_attr_latest="description;latest"
+entry_val="$current_date#$cpu_ldap:$mem_ldap#$cpu_global_user:$cpu_global_sys:$cpu_global_idle#$mem_global_total:$mem_global_used:$mem_global_free:$mem_global_avail"
+
+logMessage "Entry attribute is : $entry_attr"
+logMessage "Entry value is     : $entry_val"
+
+# Run the LDAP modification
+ldapmodify -x -D "$BINDDN" -w "$BINDPW" -h $HOST -p $PORT << EOF
+dn: $GLOBAL_MONITOR_ENTRY
+changeType: modify
+replace: $entry_attr
+$entry_attr: $entry_val
+-
+replace: $entry_attr_latest
+$entry_attr_latest: $entry_val
+
+EOF
+
+#
+# Wait until the delay is over.
+sleep $INTERVAL
+
+done
+
+}
+
+
+# Step 1
+runBasicChecks
+# Step 2
+setGloblalVariables
+# Step 3
+#checkMonitoringEntries
+# Step 4
+doMonitoring
diff --git a/montool/controllers/configuration.js b/montool/controllers/configuration.js
new file mode 100644
index 0000000..e3a1538
--- /dev/null
+++ b/montool/controllers/configuration.js
@@ -0,0 +1,25 @@
+
+// Configuration controller.
+angular.module('monitoring.tool.controllers').controller('ConfigurationCtrl', ['InformationFactory', '$scope', function (InformationFactory, $scope) {
+
+        $scope.viewType = 'tuning';
+        $scope.tuning_items = InformationFactory.getInfoData().slice();
+
+        $scope.setView = function (viewType) {
+            $scope.viewType = viewType;
+        };
+
+        $scope.tuning_config = {
+            selectionMatchProp: "attribute",
+            itemsAvailable: true,
+            showCheckboxes: false
+        };
+
+        $scope.tuning_columns = [
+            {header: "Attribute", itemField: "attribute"},
+            {header: "Value", itemField: "value"},
+            {header: "Recommendation", itemField: "recommendation", htmlTemplate: "recommendation_template.html" },
+            {header: "Reason", itemField: "reason"}
+        ];
+
+    }]);
diff --git a/montool/controllers/dashboard.js b/montool/controllers/dashboard.js
new file mode 100644
index 0000000..3ae58f9
--- /dev/null
+++ b/montool/controllers/dashboard.js
@@ -0,0 +1,313 @@
+
+"use strict";
+
+angular.module('monitoring.tool.controllers').controller('DashboardCtrl', ['InformationFactory', 'LoginFactory', '$scope', '$interval',
+    function (InformationFactory, LoginFactory, $scope, $interval) {
+
+        $scope.notification = {
+            type: 'info',
+            isPersistent: false,
+            header: 'Monitoring Tool Notification.',
+            message: 'Click on the Refresh Icon or enable the Automatic Refresh.'
+        };
+
+// https://docs.angularjs.org/api/ng/service/$interval#examples
+
+        var loadData;
+        function startRefreshing() {
+            // Don't start a new refresh if we are already refreshing data.
+            if (angular.isDefined(loadData))
+                return;
+
+            loadData = $interval(function () {
+                $scope.handleRefresh();
+            }, 3000); // 3 seconds.
+        }
+
+
+
+        function stopRefreshing() {
+            if (angular.isDefined(loadData)) {
+                $interval.cancel(loadData);
+                loadData = undefined;
+            }
+        }
+
+
+        $scope.$on('$destroy', function () {
+            // Make sure that the interval is destroyed too.
+            stopRefreshing();
+        });
+
+        $scope.handleAutomaticRefresh = function (state) {
+            //console.log ("$scope.automaticRefresh = " + $scope.automaticRefresh  );
+            //if ($scope.automaticRefresh) {
+            if (state) {
+                startRefreshing();
+            } else {
+                stopRefreshing();
+            }
+        };
+
+        $scope.handleRefresh = function () {
+            var t0 = performance.now();
+            LoginFactory.sendData(LoginFactory.getServerInfo(), 'MONITOR');
+            updateCards();
+            updateCPUchart();
+            updateListOfConnections();
+            var t1 = performance.now();
+            var total = Math.round(LoginFactory.getDuration() + (t1 - t0));
+            $scope.notification.message = "Computing new data took " + total + " milliseconds.";
+        };
+
+
+        function updateListOfConnections() {
+            $scope.connections = [];
+            var arrayOfCnx = Array.from(InformationFactory.getListOfConnections());
+            //console.log(arrayOfCnx);
+            var len = arrayOfCnx.length;
+            for (var i = 0; i < len; i++) {
+                $scope.connections.push(arrayOfCnx[i]);
+            }
+        }
+
+        function convertDate(myDate) {
+            if (!myDate) {
+                return;
+            }
+            var _year = parseInt(myDate.substring(0, 4), 10);
+            // IMPORTANT! Month goes from 0 to 11
+            // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC#Syntax
+            //var _month = parseInt(myDate.substring(4, 6), 10) - 1;
+            var _month = parseInt(myDate.substring(4, 6), 10);
+            var _day = parseInt(myDate.substring(6, 8), 10);
+            var _hour = addLeadingZero(parseInt(myDate.substring(8, 10), 10));
+            var _min = addLeadingZero(parseInt(myDate.substring(10, 12), 10));
+            var _sec = addLeadingZero(parseInt(myDate.substring(12, 14), 10));
+            //var utcDate = new Date(Date.UTC(_year, _month, _day, _hour, _min, _sec));
+            //return utcDate;
+            return _year + '/' + _month + '/' + _day + ' ' + _hour + ':' + _min + ':' + _sec + ' (GMT)';
+        }
+
+        function addLeadingZero(number) {
+            if (number < 10) {
+                return '0' + number;
+            } else {
+                return number;
+            }
+        }
+
+        function updateCards() {
+            //var version = InformationFactory.getMonitoringAttribute('version');
+            var start = convertDate(InformationFactory.getMonitoringAttribute('starttime'));
+            var current = convertDate(InformationFactory.getMonitoringAttribute('currenttime'));
+            $scope.information.info = [
+                "Version: " + InformationFactory.getMonitoringAttribute('version'),
+                "Startup Time on Server: " + start,
+                "Current Time on Server: " + "<b>" + current + " </b>"
+            ];
+            //
+            $scope.instance_info.info = [
+                "Host: " + InformationFactory.getHost(),
+                "Port: " + InformationFactory.getPort(),
+                "Secure Port: " + InformationFactory.getSecurePort()
+            ];
+
+            $scope.res_summary.info = [
+                "Current connections: " + "<a href='/views/monitoring.html#/dashboard#connections'><b>"
+                        + InformationFactory.getMonitoringAttribute('currentconnections') + " </b></a>",
+                "Total connections: " + InformationFactory.getMonitoringAttribute('totalconnections'),
+                "Ops Initiated / Ops Completed: " + InformationFactory.getMonitoringAttribute('opsinitiated')
+                        + ' / ' + InformationFactory.getMonitoringAttribute('opscompleted')
+            ];
+        }
+
+
+        $scope.information = {
+            "title": "389-ds Directory Server",
+            "href": "",
+            //"iconClass": "fa fa-info-circle",
+            "notifications": [],
+            "info": [
+                "Version: ",
+                "Startup Time on Server: ",
+                "Current Time on Server: "
+            ]
+        };
+
+        $scope.instance_info = {
+            "title": "Instance Information",
+            "href": "",
+            //"iconClass": "fa fa-info-circle",
+            "notifications": [],
+            "info": [
+                "Host: ",
+                "Port: ",
+                "Secure Port: "
+            ]
+        };
+
+        $scope.res_summary = {
+            "title": "Resource Summary",
+            "href": "",
+            //"iconClass": "fa fa-info-circle",
+            "notifications": [],
+            "info": [
+                "Current connections: ",
+                "Total connections: ",
+                "Ops Initiated / Ops Completed: "
+            ]
+        };
+
+// For the CPU usage of the LDAP process.
+        $scope.CPUconfig = {
+            title: 'CPU Usage',
+            units: '%'
+        };
+        $scope.CPUdonutConfig = {
+            chartId: 'chartCPU',
+            thresholds: {'warning': '60', 'error': '85'}
+        };
+        $scope.CPUSparklineConfig = {
+            'chartId': 'CPUSparkline',
+            'tooltipType': 'percentage',
+            'units': '%'
+        };
+
+        var CPUdates = ['CPUdates'];
+        var memoryDates = ['memoryDates'];
+        var CPUvalues = ['CPUvalues'];
+        var memoryValues = ['memoryValues'];
+
+        $scope.CPUdata = {
+            dataAvailable: true,
+            used: 0,
+            total: 100,
+            xData: CPUdates,
+            yData: CPUvalues
+        };
+
+// For the memory usage of the LDAP process.
+        $scope.memoryConfig = {
+            title: 'Memory Usage',
+            units: '%'
+        };
+        $scope.memoryDonutConfig = {
+            chartId: 'chartMemory',
+            thresholds: {'warning': '60', 'error': '85'}
+        };
+        $scope.memorySparklineConfig = {
+            'chartId': 'memorySparkline',
+            'tooltipType': 'percentage',
+            'units': '%'
+        };
+
+
+        $scope.memoryData = {
+            dataAvailable: true,
+            used: 0,
+            total: 100,
+            xData: memoryDates,
+            yData: memoryValues
+        };
+
+        $scope.centerLabel = 'used';
+        $scope.custShowXAxis = false;
+        $scope.custShowYAxis = true;
+        $scope.custChartHeight = 120;
+
+        var previous_description = '';
+
+        function updateCPUchart() {
+            var description = InformationFactory.getMonitoringAttribute('description;latest');
+            if (!description) {
+                console.log("No data collected yet.");
+                return;
+            }
+            if (description === previous_description) { // Monitoring Agent has been likely stopped.
+                console.log("Monitoring Agent is likely stopped.");
+                return;
+            }
+
+            //console.log("description = " + description);
+            previous_description = description;
+
+            //description;latest: 1521330708#0.0:2.4#3.0:3.0:93.9#1814740:866644:135464:663840
+            //Format is "description;<SLOT>: <DATE>#<CPU_LDAP>:<MEM_LDAP>#<CPU_USER>:<CPU_SYS>:<CPU:IDLE>#<MEM_TOTAL>:<MEM_USED>:<MEM_FREE>:<MEM_AVAILABLE>
+            var arrayOfStrings = description.split('#');
+            //console.log("arrayOfStrings[0] = " + arrayOfStrings[0]);
+            //console.log("arrayOfStrings[1] = " + arrayOfStrings[1]);
+            //console.log("arrayOfStrings[2] = " + arrayOfStrings[2]);
+            var ldap_cpu_and_mem = (arrayOfStrings[1]).split(':');
+            var ldap_cpu_used = Math.round(ldap_cpu_and_mem[0]);
+            var ldap_mem_used = Math.round(ldap_cpu_and_mem[1]);
+            //
+            var sys_cpu_data = (arrayOfStrings[2]).split(':');
+            var sys_mem_data = (arrayOfStrings[3]).split(':');
+            var sys_cpu_used = sys_cpu_data[0];
+            // Convert the memory values from KB to MB.
+            var sys_mem_global = Math.round(sys_mem_data[0] / 1024);
+            var sys_mem_used = Math.round(sys_mem_data[1] / 1024);
+            //
+            $scope.CPUdata.used = ldap_cpu_used;
+            $scope.memoryData.used = ldap_mem_used;
+            //
+            $scope.sysRes_CPUdata.used = sys_cpu_used;
+            $scope.sysRes_MEMdata.used = sys_mem_used;
+            $scope.sysRes_MEMdata.total = sys_mem_global;
+
+            var _date = new Date();
+            var _time_milliseconds = parseInt(arrayOfStrings[0], 10) * 1000;
+            _date.setTime(_time_milliseconds);
+            //console.log("_date = " + _date.toString());
+            if ($scope.CPUdata.xData.length === 10) { // Keep data to 10 max.                
+                $scope.CPUdata.xData.splice(1, 1); // Remove the second element. First element MUST be the name of the data.
+            }
+            // Let's play it safe and do the check for the memory data array as well.
+            if ($scope.memoryData.xData.length === 10) { // Keep data to 10 max.                
+                $scope.memoryData.xData.splice(1, 1); // Remove the second element. First element MUST be the name of the data.                                
+            }
+            $scope.CPUdata.xData.push(_date);
+            $scope.CPUdata.yData.push(ldap_cpu_used);
+            $scope.memoryData.xData.push(_date);
+            $scope.memoryData.yData.push(ldap_mem_used);
+            //var test = Math.round(Math.random() * 100);
+            //$scope.memoryData.yData.push(test);
+        }
+
+// System resources.
+
+        $scope.sysRes_CPUtitle = 'CPU Usage';
+        $scope.sysRes_CPUunits = '%';
+
+        $scope.sysRes_MEMtitle = 'Memory';
+        $scope.sysRes_MEMunits = 'MB';
+
+        $scope.sysRes_DISKtitle = 'Disk Usage (TODO)';
+        $scope.sysRes_DISKunits = 'GB';
+
+        $scope.sysRes_IOtitle = 'Disk I/O (TODO)';
+        $scope.sysRes_IOunits = 'I/Ops';
+
+// Put some fake initial values.
+        $scope.sysRes_CPUdata = {
+            'used': '0',
+            'total': '100'
+        };
+        $scope.sysRes_MEMdata = {
+            'used': '0',
+            'total': '1024'
+        };
+        $scope.sysRes_DISKdata = {
+            'used': '100',
+            'total': '1024'
+        };
+        $scope.sysRes_IOdata = {
+            'used': '320',
+            'total': '500'
+        };
+        $scope.sysRes_layoutInline = {
+            'type': 'inline'
+        };
+
+    }]);
diff --git a/montool/controllers/login.js b/montool/controllers/login.js
new file mode 100644
index 0000000..b7d183f
--- /dev/null
+++ b/montool/controllers/login.js
@@ -0,0 +1,70 @@
+
+
+"use strict";
+
+//angular.module('monitoring.tool.controllers').controller('LoginPageCtrl', ['LoginFactory', '$scope', '$location',
+angular.module('monitoring.tool.controllers').controller('LoginPageCtrl', LoginPageCtrl);
+
+LoginPageCtrl.$inject = ['LoginFactory', '$scope', '$http', '$location'];
+
+
+function LoginPageCtrl(LoginFactory, $scope, $http, $location) {
+
+    $scope.showLoginPage = function () {
+        console.log("###### In showLoginPage() #########");
+        angular.element(document.querySelector("#loginLink")).addClass("hidden");
+        angular.element(document.querySelector("#loginPage")).removeClass("hidden");
+    };
+
+    $scope.goToLoginPage = function () {
+        $location.path("home");
+    };
+
+    $scope.hideLoginPage = function () {
+        angular.element(document.querySelector("#loginLink")).removeClass("hidden");
+        angular.element(document.querySelector("#loginPage")).addClass("hidden");
+    };
+
+    $scope.closeCallback = function () {
+        angular.element(document.querySelector("#loginNotification")).addClass("hidden");
+    };
+
+    //$scope.server = LoginFactory.getServerInfo();
+    //$scope.server.user = LoginFactory.getUser();
+    $scope.server = {
+        'user': 'cn=Directory Manager',
+        'password': '',
+        'host': 'localhost',
+        'port': 389,
+        'connection': 'clear'
+    };
+    //console.log("In angular.module('monitoring.tool.controllers').controller ==> LoginPageCtrl");
+    //console.log("$scope.server = " + JSON.stringify($scope.server));
+    $scope.handleLogin = function () {
+        LoginFactory.updateServerInfo($scope.server);
+        //$window.location.href = "./views/monitoring.html";
+
+        LoginFactory.sendData(LoginFactory.getServerInfo(), 'AUTHENTICATE', null);
+        var errMessage = LoginFactory.getBindErrorMessage();
+        console.log("errMessage = " + "#" + errMessage + "#");
+        if ('' === errMessage) {
+            //LoginFactory.sendData(LoginFactory.getServerInfo(), 'CHECK_IPA', null);
+            LoginFactory.sendData(LoginFactory.getServerInfo(), 'CONFIG', null);
+            LoginFactory.sendData(LoginFactory.getServerInfo(), 'MONITOR', null);
+            /* var certID;
+             for (certID = 1; certID <= 10; certID++) {
+             LoginFactory.sendData(LoginFactory.getServerInfo(), 'CERTIFICATES', certID);
+             }*/
+            $scope.hideLoginPage();
+            $location.path("dashboard");
+            
+        } else {
+            $scope.bindErrorMessage = errMessage;
+            angular.element(document.querySelector("#loginNotification")).removeClass("hidden");
+        }
+    };
+
+    console.log("LoginFactory.getServerInfo() = " + JSON.stringify(LoginFactory.getServerInfo()));
+
+}
+;
\ No newline at end of file
diff --git a/montool/controllers/logs.js b/montool/controllers/logs.js
new file mode 100644
index 0000000..03870bf
--- /dev/null
+++ b/montool/controllers/logs.js
@@ -0,0 +1,195 @@
+//
+// Logs Controller.
+//
+
+"use strict";
+
+angular.module('monitoring.tool.controllers').controller('LogsCtrl', ['InformationFactory',
+    '$scope', '$timeout', '$uibModal', '$rootScope',
+    function (InformationFactory, $scope, $timeout, $uibModal, $rootScope) {
+
+        console.log('InformationFactory.getMonitoringAttribute(nsslapd-accesslog) = '
+                + InformationFactory.getMonitoringAttribute('nsslapd-accesslog'));
+
+
+        $scope.launchLogconvWizard = function () {
+
+            var logconvWizardDoneListener,
+                    logconvModalInstance = $uibModal.open({
+                        animation: true,
+                        backdrop: 'static',
+                        templateUrl: 'views/wizards/logconv/wizard-logconv.html',
+                        controller: 'LogconvController',
+                        size: 'lg'
+                    });
+
+            var closeLogconvWizard = function (e, reason) {
+                updateLogconvData();
+                logconvModalInstance.dismiss(reason);
+                logconvWizardDoneListener();
+            };
+
+            logconvModalInstance.result.then(function () { }, function () { });
+
+            logconvWizardDoneListener = $rootScope.$on('wizard.done', closeLogconvWizard);
+        };
+
+
+        $scope.notification = {
+            type: 'info',
+            isPersistent: false,
+            header: 'Monitoring Tool Notification.',
+            message: 'Click on the Log Converter Icon to parse 389-ds logs.'
+        };
+
+        $scope.information = {
+            "title": "Global Information",
+            "href": "",
+            "iconClass": "fa fa-info-circle",
+            "notifications": [],
+            "info": [
+                "Total Log Lines Analysed: ",
+                "Start of Logs: ",
+                "End of Logs: ",
+                "Processed Log Time: ",
+                "Restarts: ",
+                "Peak Concurrent Connections: ",
+                "Total Connections: "
+            ]
+        };
+
+
+        $scope.operations = {
+            "title": "LDAP Operations",
+            "href": "",
+            "iconClass": "fa fa-info-circle",
+            "notifications": [],
+            "info": [
+                "Searches: ",
+                "Adds: ",
+                "Modifications: ",
+                "Deletes: ",
+                "Mod RDNs: ",
+                "Compares: ",
+                "Binds: "
+            ]
+        };
+
+        $scope.fdTitles = {
+            "taken": "FDs Taken",
+            "returned": "FDs Returned",
+            "highest": "Highest FD Taken"
+        };
+        $scope.fdTakenData = {
+            'used': 0,
+            'total': 0
+        };
+        $scope.fdReturnedData = {
+            'used': 0,
+            'total': 0
+        };
+        $scope.fdHighestData = {
+            'used': 0,
+            'total': 0
+        };
+
+        $scope.fdTakenFooter = '<strong>' + $scope.fdTakenData.used + '</strong>';
+        $scope.fdReturnedFooter = '<strong>' + $scope.fdReturnedData.used + '</strong>';
+        $scope.fdHighestFooter = '<strong>' + $scope.fdHighestData.used + '</strong>';
+
+
+        function updateLogconvData() {
+
+            //console.log("InformationFactory.getLogconvData = " + InformationFactory.getLogconvData());
+            var logConvData = InformationFactory.getLogconvData();
+            if (logConvData && logConvData.length > 0) {
+                var parsedInfo = JSON.parse(logConvData);
+                //console.log("logconv data = " + JSON.stringify(parsedInfo));
+                $scope.actualCommand = parsedInfo.actualCommand;
+                $scope.information.info = [
+                    "Total Log Lines Analysed: " + parsedInfo.totalLines,
+                    "Start of Logs: " + parsedInfo.start,
+                    "End of Logs: " + parsedInfo.end,
+                    "Processed Log Time: " + parsedInfo.duration,
+                    "Restarts: " + parsedInfo.restarts,
+                    "Peak Concurrent Connections: " + parsedInfo.peakCnx,
+                    "Total Connections: " + parsedInfo.totalCnx
+                ];
+
+                //console.log("parsedInfo.searches.split(' ')[0] = #" + parsedInfo.searches.split(' ')[0] + "#");
+                $scope.operations.info = [
+                    "Searches: " + parsedInfo.searches,
+                    "Modifications: " + parsedInfo.mods,
+                    "Adds: " + parsedInfo.adds,
+                    "Deletes: " + parsedInfo.dels,
+                    "Mod RDNs: " + parsedInfo.modRdn,
+                    "Compares: " + parsedInfo.comparisons,
+                    "Binds: " + parsedInfo.binds
+                ];
+
+                if (!parsedInfo.searches) {
+                    return;
+                }
+                var searches_val = parseInt(parsedInfo.searches.split(' ')[0]);
+                var mods_val = parseInt(parsedInfo.mods.split(' ')[0]);
+                var adds_val = parseInt(parsedInfo.adds.split(' ')[0]);
+                var dels_val = parseInt(parsedInfo.dels.split(' ')[0]);
+                var modRdn_val = parseInt(parsedInfo.modRdn.split(' ')[0]);
+                var comparisons_val = parseInt(parsedInfo.comparisons.split(' ')[0]);
+                var binds_val = parseInt(parsedInfo.binds.split(' ')[0]);
+
+                $scope.logConvData = [
+                    ['Searches', searches_val],
+                    ['Modifications', mods_val],
+                    ['Adds', adds_val],
+                    ['Deletes', dels_val],
+                    ['Mod RDNs', modRdn_val],
+                    ['Compares', comparisons_val],
+                    ['Binds', binds_val]
+                ];
+
+                var fdTaken_val = parseInt(parsedInfo.fdTaken.split(' ')[0]);
+                var fdReturned_val = parseInt(parsedInfo.fdReturned.split(' ')[0]);
+                var fdHighest_val = parseInt(parsedInfo.fdHighest.split(' ')[0]);
+                var maxValue = Math.max(fdTaken_val, fdReturned_val, fdHighest_val);
+                $scope.fdTakenData.used = fdTaken_val;
+                $scope.fdTakenData.total = maxValue;
+                $scope.fdReturnedData.used = fdReturned_val;
+                $scope.fdReturnedData.total = maxValue;
+                $scope.fdHighestData.used = fdHighest_val;
+                $scope.fdHighestData.total = maxValue;
+                $scope.fdTakenFooter = '<strong>' + $scope.fdTakenData.used + '</strong>';
+                $scope.fdReturnedFooter = '<strong>' + $scope.fdReturnedData.used + '</strong>';
+                $scope.fdHighestFooter = '<strong>' + $scope.fdHighestData.used + '</strong>';
+            }
+        }
+
+
+        $scope.logConvConfig = {
+            'chartId': 'chartOne',
+            'legend': {"show": true},
+            'colors': {
+                'Searches': '#0088ce', // blue
+                'Modifications': '#3f9c35', // green
+                'Adds': '#ec7a08', // orange
+                'Deletes': '#cc0000', // red
+                'Mod RDN': '#00ffff',
+                'Compares': '#8000ff',
+                'Binds': '#ff00bf'
+            },
+            donut: {
+                title: "Operations"
+            }
+        };
+
+        $scope.logConvData = [
+            ['Searches', 0],
+            ['Modifications', 0],
+            ['Adds', 0],
+            ['Deletes', 0],
+            ['Mod RDNs', 0],
+            ['Compares', 0],
+            ['Binds', 0]
+        ];
+
+    }]);
\ No newline at end of file
diff --git a/montool/controllers/monitoringTool.js b/montool/controllers/monitoringTool.js
new file mode 100644
index 0000000..3883434
--- /dev/null
+++ b/montool/controllers/monitoringTool.js
@@ -0,0 +1,369 @@
+//
+// Main controller.
+// 
+
+"use strict";
+
+//angular.module('monitoring.tool.controllers', []);
+
+angular.module('monitoring.tool.controllers',
+        ['patternfly.navigation', 'patternfly.card', 'patternfly.views',
+            'patternfly.charts', 'patternfly.table', 'patternfly.notification',
+            'patternfly.toolbars', 'patternfly.modals', 'patternfly.wizard',
+            'ui.router']);
+
+
+
+
+//
+// Information factory
+//
+angular.module('monitoring.tool.controllers').factory('InformationFactory', function () {
+
+    var informationObject = {};
+    var configItems = [];
+    //var monitorItems = [];
+    //var currentConnections = [];
+    var version, currentTime, startTime,
+            host, port, TLSport,
+            currentCNX, totalCNX, opsCompleted, opsInitiated,
+            description, listOfConnections, accessLogFile;
+    var IPAcertificates = [];
+    //
+    var logconvData;
+
+    informationObject.addItem = function (item) {
+        configItems.push(item);
+    };
+
+    informationObject.storeLogconvData = function (data) {
+        //logconvData = JSON.parse(data);
+        logconvData = data;
+        console.log('logconvData ==> '+ logconvData);
+    };
+    informationObject.getLogconvData = function () {
+        return logconvData;
+    };
+    //informationObject.addMonitorItem = function (item) {
+    //    monitorItems.push(item);
+    //};
+
+    informationObject.updateMonitorData = function (infoMonitorData) { // infoMonitorData is a parsed JSON
+        for (var attr in infoMonitorData) {
+            switch (attr) {
+                case 'connection' :
+                    listOfConnections = infoMonitorData[attr];
+                    //console.log(infoMonitorData[attr]);
+                    break;
+                case 'version' :
+                    version = infoMonitorData[attr];
+                    break;
+                case 'currenttime' :
+                    currentTime = infoMonitorData[attr];
+                    break;
+                case 'starttime' :
+                    startTime = infoMonitorData[attr];
+                    break;
+                case 'currentconnections' :
+                    currentCNX = infoMonitorData[attr];
+                    break;
+                case 'totalconnections' :
+                    totalCNX = infoMonitorData[attr];
+                    break;
+                case 'opsinitiated' :
+                    opsInitiated = infoMonitorData[attr];
+                    break;
+                case 'opscompleted' :
+                    opsCompleted = infoMonitorData[attr];
+                    break;
+                case 'description;latest':
+                    description = infoMonitorData[attr];
+                    break;
+                default:
+                //console.log("Unused attribute " + attr);
+                //informationObject.addMonitorItem({attr: infoMonitorData[attr]});
+            }
+        }
+    };
+
+    informationObject.updateData = function (infoData) { // infoData is a parsed JSON
+
+        for (var attr in infoData) {
+            var rec = 'ok';
+            switch (attr) {
+                case 'dn':
+                case 'controls':
+                    break;
+                case 'nsslapd-accesslog': // Used for the Log Converter.
+                    accessLogFile = infoData[attr];
+                    break;
+                case 'nsslapd-localhost':
+                    host = infoData[attr];
+                    break;
+                case 'nsslapd-port':
+                    port = infoData[attr];
+                    break;
+                case 'nsslapd-secureport':
+                    TLSport = infoData[attr];
+                    //console.log("TLSport = " + TLSport);
+                    break;
+
+                case 'nsslapd-enquote-sup-oc':
+
+                    if ('on' === infoData[attr]) {
+                        rec = 'warning';
+                    }
+                    informationObject.addItem({recommendation: rec, attribute: attr, value: infoData[attr],
+                        reason: 'Deprecated and will be removed in a future version.'});
+                    break;
+
+                case 'nsslapd-ndn-cache-enabled':
+                    if ('off' === infoData[attr]) {
+                        rec = 'warning';
+                    }
+                    informationObject.addItem({recommendation: rec, attribute: attr, value: infoData[attr],
+                        reason: 'Improves performance.'});
+                    break;
+
+                case 'nsslapd-allow-anonymous-access':
+                    if ('on' === infoData[attr]) {
+                        rec = 'error';
+                    }
+                    informationObject.addItem({recommendation: rec, attribute: attr, value: infoData[attr],
+                        reason: 'Security issues (DOS,...)'});
+                    break;
+
+                case 'nsslapd-minssf':
+                    if ('0' === infoData[attr]) {
+                        rec = 'warning';
+                    }
+                    informationObject.addItem({recommendation: rec, attribute: attr, value: infoData[attr],
+                        reason: 'No minimum setting for the key strength.'});
+                    break;
+                default:
+                    informationObject.addItem({recommendation: '', attribute: attr, value: infoData[attr],
+                        reason: 'TODO'});
+            }
+        }
+
+    };
+
+
+
+    informationObject.updateCertsData = function (certData, certID) {
+        IPAcertificates[certID] = certData;
+        //console.log("IPAcertificates[certID] = " + certID + " : " + JSON.stringify(IPAcertificates[certID]));
+        //console.log("IPAcertificates[certID].dn = " + certID + " : " + (IPAcertificates[certID]).dn);
+
+        //for (var attr in certData) {
+        //console.log("attr: val = " + attr + " : " + certData[attr]);
+        //}
+    };
+
+
+    informationObject.getMonitoringAttribute = function (attribute) {
+        var value;
+        switch (attribute) {
+            case 'version' :
+                value = version;
+                break;
+            case 'currenttime' :
+                value = currentTime;
+                break;
+            case 'starttime' :
+                value = startTime;
+                break;
+            case 'currentconnections' :
+                value = currentCNX;
+                break;
+            case 'totalconnections' :
+                value = totalCNX;
+                break;
+            case 'opsinitiated' :
+                value = opsInitiated;
+                break;
+            case 'opscompleted' :
+                value = opsCompleted;
+                break;
+            case 'description;latest' :
+                value = description;
+                break;
+            case 'nsslapd-accesslog' :
+                value = accessLogFile;
+                break;
+            default:
+                value = '';
+        }
+        return value;
+    };
+
+
+    informationObject.getHost = function () {
+        return host;
+    };
+    informationObject.getPort = function () {
+        return port;
+    };
+    informationObject.getSecurePort = function () {
+        return TLSport;
+    };
+    informationObject.getInfoData = function () {
+        return configItems;
+    };
+    /*informationObject.getMonitorData = function () {
+     return monitorItems;
+     };*/
+    informationObject.getListOfConnections = function () {
+        return listOfConnections;
+    };
+    informationObject.getListOfCertificates = function () {
+        return IPAcertificates;
+    };
+
+    return informationObject;
+});
+
+
+
+angular.module('monitoring.tool.controllers').factory('LoginFactory', ['InformationFactory', function (InformationFactory) {
+
+        var loginObject = {};
+        var bindErrorMessage = '';
+        var duration = 0;
+
+        var serverInfo = {
+            'user': 'cn=Directory Manager',
+            'password': '',
+            'host': 'localhost',
+            'port': 389,
+            'connection': 'clear'
+        };
+
+        loginObject.getUser = function () {
+            return serverInfo.user;
+        };
+
+        loginObject.updateServerInfo = function (_server) {
+            console.log("Setting user value to " + _server.user);
+            serverInfo = {
+                'user': _server.user,
+                'password': _server.password,
+                'host': _server.host,
+                'port': _server.port,
+                'connection': _server.connection
+            };
+        };
+
+
+        loginObject.getHostname = function () {
+            return serverInfo.host;
+        };
+
+        loginObject.getServerInfo = function () {
+            return serverInfo;
+        };
+
+        loginObject.setBindErrorMessage = function (msg) {
+            bindErrorMessage = msg;
+        };
+
+        loginObject.getBindErrorMessage = function () {
+            return bindErrorMessage;
+        };
+
+        loginObject.getDuration = function () {
+            return duration;
+        };
+
+        loginObject.sendData = function (data, operation, certID) {
+            var t0 = performance.now();
+            var XHR = new XMLHttpRequest();
+            var urlEncodedData = "";
+            var urlEncodedDataPairs = [];
+            var name;
+
+            // Turn the data object into an array of URL-encoded key/value pairs.
+            for (name in data) {
+                urlEncodedDataPairs.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name]));
+            }
+
+            // Combine the pairs into a single string and replace all %-encoded spaces to 
+            // the '+' character; matches the behaviour of browser form submissions.
+            urlEncodedData = urlEncodedDataPairs.join('&').replace(/%20/g, '+');
+
+            // Define what happens on successful data submission
+            XHR.addEventListener('load', function (event) {
+                //alert('Yeah! Data sent and response loaded.');
+                //console.log("Data sent and response loaded.");
+            });
+
+            XHR.onreadystatechange = function () {//Call a function when the state changes.
+                if (XHR.readyState === XMLHttpRequest.DONE && XHR.status === 200) {
+                    // Request finished. Do processing here.
+                    var response = XHR.responseText;
+                    if (response && response.length > 0) {
+                        var retrieved = JSON.parse(XHR.responseText);
+                        //console.log("retrieved = " + JSON.stringify(retrieved));
+                        if ('AUTHENTICATE' === operation) {
+                            //LoginFactory.setBindErrorMessage(retrieved.lde_message);
+                            loginObject.setBindErrorMessage(retrieved.lde_message);
+                            //console.log("retrieved.lde_message = " + retrieved.lde_message);
+                        } else if ('CONFIG' === operation) {
+                            var configArray = JSON.parse(XHR.responseText);
+                            InformationFactory.updateData(configArray);
+                            //console.log("configArray = " + JSON.stringify(configArray));
+                            //console.log("configArray [nsslapd-require-secure-binds] = " + configArray['nsslapd-require-secure-binds']);
+                        } else if ('MONITOR' === operation) {
+                            var monitorArray = JSON.parse(XHR.responseText);
+                            //console.log("monitorArray = " + JSON.stringify(monitorArray));
+                            InformationFactory.updateMonitorData(monitorArray);
+                        } else if ('CHECK_IPA' === operation) {
+                            var IPAarray = JSON.parse(XHR.responseText);
+                            console.log("IPAarray = " + JSON.stringify(IPAarray));
+                            //InformationFactory.updateMonitorData(monitorArray);
+                        } else if ('CERTIFICATES' === operation) {
+                            var certsArray = JSON.parse(XHR.responseText);
+                            //console.log("certsArray = " + JSON.stringify(certsArray));
+                            InformationFactory.updateCertsData(certsArray, certID);
+                        }
+                    }
+                    var t1 = performance.now();
+                    duration = t1 - t0;
+                    //console.log("Collecting new data too " + duration + " milliseconds.");
+                }
+            };
+
+            // Define what happens in case of error
+            XHR.addEventListener('error', function (event) {
+                alert('Got a error while sending the XMLHttpRequest.');
+            });
+
+            // Set up our request
+            if ('AUTHENTICATE' === operation) {
+                // TOFIX!!!
+                // Making it synchronous so that we have time to get the error message.
+                XHR.open('POST', '/api/v1/montool/authenticate', false);
+            } else if ('CONFIG' === operation) {
+                XHR.open('POST', '/api/v1/montool/search/CONFIG');
+            } else if ('MONITOR' === operation) {
+                XHR.open('POST', '/api/v1/montool/search/MONITOR');
+            } else if ('CHECK_IPA' === operation) {
+                // Make it synchronous as we need to know if we can search for the certificates.
+                // TODO ==> Find a better way.
+                XHR.open('POST', '/api/v1/montool/search/CHECK_IPA');
+            } else if ('CERTIFICATES' === operation) {
+                XHR.open('POST', '/api/v1/montool/search/certificates/' + certID);
+            }
+            // Add the required HTTP header for form data POST requests
+            XHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+            //XHR.setRequestHeader('Content-Type', 'application/json');
+
+            // Finally, send our data.
+            XHR.send(urlEncodedData);
+            //console.log(JSON.stringify(urlEncodedData));
+
+        };
+
+        return loginObject;
+    }]);
+
diff --git a/montool/controllers/navigation.js b/montool/controllers/navigation.js
new file mode 100644
index 0000000..fa518de
--- /dev/null
+++ b/montool/controllers/navigation.js
@@ -0,0 +1,110 @@
+
+"use strict";
+
+//angular.module('monitoring.tool.controllers',['patternfly.navigation','ui.router'])
+
+angular.module('monitoring.tool.controllers')
+        .config(function ($stateProvider, $urlRouterProvider) {
+
+            $urlRouterProvider.otherwise('home');
+
+            $stateProvider
+                    .state('home', {
+                      url: '/home',
+                      templateUrl: 'views/login.html',
+                      controller: 'LoginPageCtrl'
+                    })
+                    .state('dashboard', {
+                        url: '/dashboard',
+                        templateUrl: 'views/dashboard.html',
+                        controller: 'DashboardCtrl'
+                    })
+                    .state('configuration', {
+                        url: '/config',
+                        templateUrl: 'views/configuration.html',
+                        controller: 'ConfigurationCtrl'
+                    })
+                    .state('topology', {
+                        url: '/topology',
+                        templateUrl: 'views/topology.html',
+                        controller: 'TopologyCtrl'
+                    })
+                    .state('security', {
+                        url: '/security',
+                        templateUrl: 'views/security.html',
+                        controller: 'SecurityCtrl'
+                    })
+                    .state('logs', {
+                        url: '/logs',
+                        templateUrl: 'views/logs.html',
+                        controller: 'LogsCtrl'
+                    })
+                    .state('troubleshoot', {
+                        url: '/troubleshoot',
+                        templateUrl: 'views/troubleshoot.html',
+                        controller: 'TroubleshootCtrl'
+                    });
+        })
+        .controller('vertNavWithRouterController', ['$scope', '$location',
+            function ($scope, $location) {
+
+                $scope.navigationItems = [
+
+                    {
+                        title: "Home",
+                        iconClass: "fa fa-home",
+                        uiSref: "home",
+                        //uiSrefActive: "active"
+                        uiSrefOptions: {uiSrefActive: 'active'}
+                        // https://ui-router.github.io/ng1/docs/0.3.1/index.html#/api/ui.router.state.directive:ui-sref
+                        // You can specify options to pass to $state.go() using the ui-sref-opts attribute.
+                        // Options are restricted to location, inherit, and reload.
+
+                    },
+                    {
+                        title: "Dashboard",
+                        iconClass: "fa fa-dashboard",
+                        uiSref: "dashboard"
+                    },
+                    {
+                        title: "Configuration",
+                        iconClass: "fa fa-cogs",
+                        uiSref: "configuration"
+                    },
+                    {
+                        title: "Topology",
+                        iconClass: "fa fa-object-group",
+                        uiSref: "topology"
+                    },
+                    {
+                        title: "Security",
+                        iconClass: "fa fa-shield",
+                        uiSref: "security"
+                    },
+                    {
+                        title: "Log Analysis",
+                        iconClass: "fa fa-bar-chart",
+                        uiSref: "logs"
+                    }, {
+                        title: "Troubleshoot",
+                        iconClass: "pficon pficon-maintenance",
+                        uiSref: "troubleshoot"
+                    },
+                    {
+                        title: "Logout",
+                        iconClass: "fa fa-sign-out"
+                    }
+                ];
+
+                $scope.handleNavigateClickRouter = function (item) {
+                    if (item.title === "Logout") {
+                        //$scope.hideVerticalNav();
+                        console.log("User has logged out!");
+                        $location.path("home");
+                    } else if (item.title === "Home") {
+                        console.log("In Home Page :-)");
+                    }
+                };
+
+            }
+        ]);
diff --git a/montool/controllers/security.js b/montool/controllers/security.js
new file mode 100644
index 0000000..1821f5a
--- /dev/null
+++ b/montool/controllers/security.js
@@ -0,0 +1,163 @@
+
+// Security controller.
+angular.module('monitoring.tool.controllers').controller('SecurityCtrl', ['InformationFactory', 'LoginFactory', '$scope',
+    function (InformationFactory, LoginFactory, $scope) {
+
+
+        var certID;
+        for (certID = 1; certID <= 10; certID++) {
+            LoginFactory.sendData(LoginFactory.getServerInfo(), 'CERTIFICATES', certID);
+        }
+
+        $scope.eventText = '';
+        var handleClick = function (item, e) {
+            var details = '';
+            for (var attr in item) {
+                var val = item[attr];
+                if ('$$hashKey' === attr) {
+                    continue;
+                }
+                details = details + attr + ' : ' + item[attr] + '\n';
+            }
+            $scope.eventText = details;
+        };
+
+        var handleDblClick = function (item, e) {
+            $scope.certificateInfo = [
+                {name: 'Name', value: item.dn},
+                {name: 'Expiration Date', value: item.expiration},
+                {name: 'Serial Number', value: item.serialno},
+                {name: 'Issuer Name', value: item.issuerName}
+            ];
+
+            $scope.isModalOpen = true;
+        };
+
+        $scope.demoShowCertsExpiringIn2019 = function () {
+            for (var i in $scope.items) {
+                var cert = $scope.items[i];
+                var _expirationDate = cert.notAfter;
+                var _year = parseInt(_expirationDate.substring(0, 4), 10);
+                if (2019 === _year) {
+                    cert.futureExpiration = _year;
+                }
+            }
+        };
+
+
+        $scope.config = {
+            selectItems: false,
+            itemsAvailable: true,
+            multiSelect: false,
+            dblClick: false,
+            selectionMatchProp: 'name',
+            selectedItems: [],
+            showSelectBox: false,
+            onClick: handleClick,
+            onDblClick: handleDblClick
+        };
+
+        $scope.items = [];
+        var i;
+        // TODO: Don't rely on the indexes. Use the length.
+        for (i = 1; i <= 10; i++) {
+            var certificate = InformationFactory.getListOfCertificates()[i];
+            if (!certificate) {
+                console.log("No certificate found!");
+                continue;
+            }
+            var subjectName = certificate.subjectName;
+            var toDisplay = (subjectName.split(',')[0]).split('=')[1];
+            if (toDisplay.includes('.')) {
+                toDisplay = toDisplay.split('.')[0];
+            }
+            var expirationDate = convertDate(certificate.notAfter);
+            //console.log("JSON CERT = " + JSON.stringify(certificate));
+            console.log("expirationDate = " + expirationDate);
+            $scope.items.push({
+                name: toDisplay,
+                expiration: expirationDate,
+                //
+                serialno: certificate.serialno,
+                dn: certificate.dn,
+                notBefore: certificate.notBefore,
+                notAfter: certificate.notAfter,
+                duration: certificate.duration,
+                extension: certificate.extension,
+                subjectName: certificate.subjectName,
+                issuerName: certificate.issuerName,
+                userCertificate: certificate.userCertificate,
+                version: certificate.version,
+                algorithmId: certificate.algorithmId,
+                signingAlgorithmId: certificate.signingAlgorithmId,
+                certStatus: certificate.certStatus
+            });
+        }
+
+        // The 2 following functions are copied from the Dashboard controller.
+        // TODO ==> to merge to as a factory function.
+
+        function convertDate(myDate) {
+            if (!myDate) {
+                return;
+            }
+            var _year = parseInt(myDate.substring(0, 4), 10);
+            // IMPORTANT! Month goes from 0 to 11
+            // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC#Syntax
+            //var _month = parseInt(myDate.substring(4, 6), 10) - 1;
+            var _month = parseInt(myDate.substring(4, 6), 10);
+            var _day = parseInt(myDate.substring(6, 8), 10);
+            var _hour = addLeadingZero(parseInt(myDate.substring(8, 10), 10));
+            var _min = addLeadingZero(parseInt(myDate.substring(10, 12), 10));
+            var _sec = addLeadingZero(parseInt(myDate.substring(12, 14), 10));
+            //var utcDate = new Date(Date.UTC(_year, _month, _day, _hour, _min, _sec));
+            //return utcDate;
+            return _year + '/' + _month + '/' + _day + ' ' + _hour + ':' + _min + ':' + _sec + ' (GMT)';
+        }
+
+        function addLeadingZero(number) {
+            if (number < 10) {
+                return '0' + number;
+            } else {
+                return number;
+            }
+        }
+
+
+
+        $scope.imgAlt = "Patternfly Symbol";
+        $scope.imgSrc = "images/logo-alt.svg";
+        $scope.title = "Certificate Details";
+
+        //$scope.openModal = function () {
+        //  $scope.isModalOpen = true;
+        //};
+        $scope.onModalClose = function () {
+            $scope.isModalOpen = false;
+        };
+
+
+        var performEmptyStateAction = function (action) {
+            $scope.eventText = action.name + "\r\n" + $scope.eventText;
+        };
+
+        $scope.emptyStateConfig = {
+            icon: 'pficon-warning-triangle-o',
+            title: 'No Items Available',
+            info: "This is the Empty State component. The goal of a empty state pattern is to provide a good first impression that helps users to achieve their goals. It should be used when a view is empty because no objects exists and you want to guide the user to perform specific actions.",
+            helpLink: {
+                label: 'For more information please see',
+                urlLabel: 'pfExample',
+                url: '#/api/patternfly.views.component:pfEmptyState'
+            }
+        };
+
+        $scope.emptyStateActionButtons = [
+            {
+                name: 'Main Action',
+                title: 'Perform an action',
+                actionFn: performEmptyStateAction,
+                type: 'main'
+            }
+        ];
+    }]);
\ No newline at end of file
diff --git a/montool/controllers/test.js b/montool/controllers/test.js
new file mode 100644
index 0000000..214bffd
--- /dev/null
+++ b/montool/controllers/test.js
@@ -0,0 +1,37 @@
+angular.module( 'patternfly.charts' ).controller( 'ChartCtrl', function( $scope ) {
+  $scope.used = 950;
+  $scope.total = 1000;
+  $scope.available =  $scope.total - $scope.used;
+ 
+  $scope.chartConfig = patternfly.c3ChartDefaults().getDefaultDonutConfig('MHz Used');
+  $scope.chartConfig.data = {
+    type: "donut",
+    columns: [
+      ["Used", $scope.used],
+      ["Available", $scope.total - $scope.used]
+    ],
+    groups: [
+      ["used", "available"]
+    ],
+    order: null
+  };
+ 
+  $scope.getChart = function (chart) {
+    $scope.chart = chart;
+  };
+ 
+  $scope.focusUsed = function () {
+    $scope.chart.focus("Used");
+  };
+ 
+  $scope.updateAvailable = function (val) {
+    $scope.available =  $scope.total - $scope.used;
+  };
+ 
+  $scope.submitform = function (val) {
+    console.log("submitform");
+    $scope.used = val;
+    $scope.updateAvailable();
+    $scope.chartConfig.data.columns = [["Used",$scope.used],["Available",$scope.available]];
+  };
+});
diff --git a/montool/controllers/topology.js b/montool/controllers/topology.js
new file mode 100644
index 0000000..9e65f8d
--- /dev/null
+++ b/montool/controllers/topology.js
@@ -0,0 +1,12 @@
+//
+// Topology Controller.
+//
+
+"use strict";
+
+angular.module('monitoring.tool.controllers').controller('TopologyCtrl', ['LoginFactory', '$scope', function (LoginFactory, $scope) {
+        $scope.handleTest = function () {
+            console.log("TopologyCtrl ==> LoginFactory.getServerInfo() = " + JSON.stringify(LoginFactory.getServerInfo()));
+        };
+        console.log("################");
+    }]);
diff --git a/montool/controllers/troubleshoot.js b/montool/controllers/troubleshoot.js
new file mode 100644
index 0000000..0e26ace
--- /dev/null
+++ b/montool/controllers/troubleshoot.js
@@ -0,0 +1,160 @@
+//
+// Troubleshoot Component.
+//
+
+"use strict";
+
+angular.module('monitoring.tool.controllers').component('itemExpansion', {
+    bindings: {
+        item: '<'
+    },
+    templateUrl: 'views/troubleshoot/item-expansion.html',
+    controller: function () {
+        //'use strict';
+        var ctrl = this;
+    }
+});
+
+
+//
+// Troubleshoot Controller.
+//
+
+angular.module('monitoring.tool.controllers').controller('TroubleshootCtrl', ['$scope', '$uibModal', '$rootScope',
+    function ($scope, $uibModal, $rootScope) {
+
+        // General
+        $scope.viewType = 'tools';
+
+        $scope.setView = function (viewType) {
+            $scope.viewType = viewType;
+        };
+
+        // Tools
+
+        $scope.customScope = {
+            toggleExpandItemField: function (item, field) {
+                if (item.isExpanded && item.expandField === field) {
+                    item.isExpanded = false;
+                } else {
+                    item.isExpanded = true;
+                    item.expandField = field;
+                }
+            },
+            collapseItem: function (item) {
+                item.isExpanded = false;
+            },
+            isItemExpanded: function (item, field) {
+                return item.isExpanded && item.expandField === field;
+            }
+        };
+
+        $scope.configTroubleshoot = {
+            selectionMatchProp: 'name',
+            selectedItems: [],
+            itemsAvailable: true,
+            showSelectBox: false,
+            useExpandingRows: true,
+            compoundExpansionOnly: true
+        };
+
+        $scope.itemsTroubleshoot = [
+            {
+                name: "Check Certificates",
+                id: "check-certs",
+                typeIcon: "pficon pficon-orders"
+            },
+            {
+                name: "Expired Certificates",
+                id: "expired-certs",
+                typeIcon: "pficon pficon-security"
+            },
+            {
+                name: "Replication Conflicts",
+                id: "repl-conflicts",
+                typeIcon: "pficon pficon-infrastructure"
+            },
+            {
+                name: "Replication Synchronization Issues",
+                id: "repl-sync",
+                typeIcon: "pficon pficon-topology"
+            },
+            {
+                name: "CSN Converter",
+                id: "csn-conv",
+                typeIcon: "pficon pficon-applications"
+            },
+            {
+                name: "LDAP DB Verification",
+                id: "db-verif",
+                typeIcon: "fa fa-database"
+            },
+            {
+                name: "IPA Consistency Check",
+                id: "ipa-check",
+                typeIcon: "pficon pficon-applications"
+            },
+            {
+                name: "IPA Status Information",
+                id: "ipa-status",
+                typeIcon: "pficon pficon-info"
+            }
+        ];
+
+
+        var performAction = function (action, item) {
+            launchSelectedWizard(item.name);
+            console.log('launchSelectedWizard(item.name) ==> item.name = ' + item.name);
+        };
+
+
+
+        $scope.actionButtons = [
+            {
+                name: 'Launch Wizard',
+                title: 'Click to launch the Wizard',
+                actionFn: performAction
+            }
+        ];
+
+        var launchSelectedWizard = function (name) {
+
+            var currentUrl = '';
+            var currentController = '';
+
+            if (name === 'Check Certificates') {
+                currentUrl = 'views/wizards/checkcerts/wizard-checkcerts.html';
+                currentController = 'CheckCertsController';
+            } else if (name === 'Expired Certificates') {
+                currentUrl = 'views/wizards/expiredcerts/wizard-expiredcerts.html';
+                currentController = 'ExpiredCertsController';
+            } else if (name === 'Replication Synchronization Issues') {
+                currentUrl = 'views/wizards/replication/replcheck/wizard-replcheck.html';
+                currentController = 'ReplicationCheckController';
+            } else if (name === 'CSN Converter') {
+                currentUrl = 'views/wizards/replication/csn/wizard-csn.html';
+                currentController = 'CsnConverterController';
+            }
+
+
+            var wizardDoneListener,
+                    modalInstance = $uibModal.open({
+                        animation: true,
+                        backdrop: 'static',
+                        templateUrl: currentUrl,
+                        controller: currentController,
+                        size: 'lg'
+                    });
+
+            var closeWizard = function (e, reason) {
+                modalInstance.dismiss(reason);
+                wizardDoneListener();
+            };
+
+            modalInstance.result.then(function () { }, function () { });
+
+            wizardDoneListener = $rootScope.$on('wizard.done', closeWizard);
+        };
+
+    }
+]);
\ No newline at end of file
diff --git a/montool/controllers/wizards/checkcerts.js b/montool/controllers/wizards/checkcerts.js
new file mode 100644
index 0000000..bf8a85e
--- /dev/null
+++ b/montool/controllers/wizards/checkcerts.js
@@ -0,0 +1,205 @@
+/* 
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+angular.module('monitoring.tool.controllers').controller('CheckCertsController', [
+    'LoginFactory', '$scope', '$timeout', '$rootScope',
+    function (LoginFactory, $scope, $timeout, $rootScope) {
+
+        $scope.checkCertsComplete = false;
+        $scope.connectionVerified = false;
+        $scope.connectionCommandComplete = true;
+
+        $scope.notificationConnection = {
+            type: 'info',
+            isPersistent: false,
+            header: 'Command: ',
+            message: ''
+        };
+
+        var initializeCheckCertsWizard = function () {
+
+            $scope.checkcerts = {
+                host: LoginFactory.getHostname(),
+                user: 'root',
+                verbose: false,
+                debug: false
+            };
+
+            $scope.secondaryLoadInformation = 'Loading Check Certificates Wizard...';
+            $scope.checkcertsWizardReady = false;
+            $timeout(function () {
+                $scope.checkcertsWizardReady = true;
+                //}, 1500);
+            }, 1000);
+
+            $scope.nextButtonTitle = "Next >";
+
+        };
+
+
+        $scope.checkConnection = function () {
+            console.log('Checking the connection...');
+            //$scope.connectionVerified = false;
+            checkConnectionToHost();
+        };
+
+        $scope.nextCallback = function (step) {
+
+            if (step.stepId === 'options') {
+                runCheckCertsCommand();
+                console.log(' ===============>>>> HERE 123567');
+            }
+            return true;
+        };
+
+        $scope.backCallback = function (step) {
+            return true;
+        };
+
+        $scope.stepChanged = function (step, index) {
+            if (step.stepId === 'output') {
+                $scope.nextButtonTitle = "Close";
+            } else {
+                $scope.nextButtonTitle = "Next >";
+            }
+        };
+
+        $scope.cancelCheckcertsWizard = function () {
+            $rootScope.$emit('wizard.done', 'cancel');
+        };
+
+        $scope.finishedCheckcertsWizard = function () {
+            $rootScope.$emit('wizard.done', 'done');
+            return true;
+        };
+
+        initializeCheckCertsWizard();
+
+        // Check connection to the host.
+        var checkConnectionToHost = function () {
+
+            $scope.notificationConnection.type = 'info';
+            $scope.notificationConnection.header = 'Command: ';
+            $scope.notificationConnection.message = '$ /usr/bin/ssh ' + $scope.checkcerts.user + '@'
+                    + $scope.checkcerts.host + ' -o BatchMode=yes -o ConnectTimeout=10 id';
+
+            $scope.connectionVerified = false;
+            $scope.connectionCommandComplete = false;
+
+            var params = {
+                host: $scope.checkcerts.host,
+                user: $scope.checkcerts.user
+            };
+
+            var urlEncodedData_cnx = "";
+            var urlEncodedDataPairs_cnx = [];
+            var name;
+            for (name in params) {
+                urlEncodedDataPairs_cnx.push(encodeURIComponent(name) + '=' + encodeURIComponent(params[name]));
+            }
+
+            urlEncodedData_cnx = urlEncodedDataPairs_cnx.join('&').replace(/%20/g, '+');
+
+            var xhr = new XMLHttpRequest();
+            xhr.open('POST', '/api/v1/montool/common/verify-access/', true);
+
+            xhr.responseType = 'text';
+
+            xhr.onload = function () {
+                if (xhr.readyState === XMLHttpRequest.DONE) {
+                    if (xhr.status === 200) {
+                        var commandRes = xhr.responseText;
+                        console.log(commandRes);
+                        $timeout(function () {
+                            $scope.notificationConnection.header = 'Result: ';
+                        });
+                        if (commandRes.startsWith('STDOUT: ')) {
+                            $timeout(function () {
+                                $scope.notificationConnection.type = 'success';
+                                $scope.notificationConnection.message = commandRes.substring(7);
+                                // Enable the 'Next' button:
+                                $scope.connectionVerified = true;
+                            });
+                        } else if (commandRes.startsWith('STDERR: ')) {
+                            $timeout(function () {
+                                $scope.notificationConnection.type = 'danger';
+                                $scope.notificationConnection.message = commandRes.substring(7);
+                                // Disable the 'Next' button:
+                                $scope.connectionVerified = false;
+                            });
+                        }
+                        // Command completed
+                        $scope.connectionCommandComplete = true;
+                    }
+                }
+            };
+
+            xhr.addEventListener('error', function (event) {
+                alert('Got an error while sending the XMLHttpRequest.');
+            });
+            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+            xhr.send(urlEncodedData_cnx);
+
+        };
+
+
+        // Run the command
+
+        var runCheckCertsCommand = function () {
+
+            var params = {
+                host: $scope.checkcerts.host,
+                //user: $scope.checkcerts.user,
+                verbose: $scope.checkcerts.verbose,
+                debug: $scope.checkcerts.debug
+            };
+
+            var urlEncodedData_cmd = "";
+            var urlEncodedDataPairs_cmd = [];
+            var name;
+            for (name in params) {
+                urlEncodedDataPairs_cmd.push(encodeURIComponent(name) + '=' + encodeURIComponent(params[name]));
+            }
+
+            urlEncodedData_cmd = urlEncodedDataPairs_cmd.join('&').replace(/%20/g, '+');
+
+            $scope.checkCertsCommandComplete = false;
+
+            var xhr = new XMLHttpRequest();
+            xhr.open('POST', '/api/v1/montool/checkcerts/run-checkcerts', true);
+
+            xhr.onreadystatechange = function () {
+                if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
+                    // Request finished. Do processing here.
+                    var response = xhr.responseText;
+                    if (response && response.length > 0) {
+                        var cmdOutput = xhr.responseText;
+                        $timeout(function () {
+                            $scope.checkCertsCommandComplete = true;
+                            $scope.checkcerts.output=cmdOutput;
+                        });
+                        console.log(cmdOutput);
+                    }
+                }
+            };
+
+            // Define what happens in case of error
+            xhr.addEventListener('error', function (event) {
+                alert('Got an error while sending the XMLHttpRequest.');
+            });
+
+            // Add the required HTTP header for form data POST requests
+            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+
+            // Finally, send our data.
+            xhr.send(urlEncodedData_cmd);
+            //console.log(JSON.stringify(urlEncodedData));
+        };
+
+
+    }
+]);
diff --git a/montool/controllers/wizards/csn.js b/montool/controllers/wizards/csn.js
new file mode 100644
index 0000000..45f6abc
--- /dev/null
+++ b/montool/controllers/wizards/csn.js
@@ -0,0 +1,286 @@
+
+///////////////////////////////////////////
+// Controller for the CSN wizard.
+///////////////////////////////////////////
+
+angular.module('monitoring.tool.controllers').controller('CsnConverterController',
+        ['$scope', '$timeout', '$rootScope', 'pfViewUtils',
+            function ($scope, $timeout, $rootScope) {
+
+                $scope.csn = {};
+                $scope.working = false;
+                $scope.commandComplete = false;
+                var notificationErrorMessage = '';
+
+                $scope.csnToolbarActionsConfig = {
+                    primaryActions: [
+                        {
+                            name: 'Remove Selected Items',
+                            title: 'Remove the selected items from the table',
+                            actionFn: removeSelectedItems
+                        },
+                        {
+                            name: 'Empty Table',
+                            title: 'Remove all items from the table',
+                            actionFn: removeAllItems
+                        }
+                    ]
+                };
+
+                $scope.csnToolbarConfig = {
+                    actionsConfig: $scope.csnToolbarActionsConfig,
+                    isTableView: true
+                };
+
+                function removeAllItems() {
+                    // https://stackoverflow.com/questions/1232040/how-do-i-empty-an-array-in-javascript
+                    $scope.csnItems.length = 0;
+                }
+
+                function removeSelectedItems() {
+
+                    //var selectedItems = $scope.csnItems.filter(item => {
+                    //    item.isSelected === true;
+                    //});
+                    //var selectedItems = $filter('filter')($scope.allItems, {selected: true});
+
+                    //if (!selectedItems) {
+                    //selectedItems = [];
+                    //}
+                    var newArray = [];
+                    $scope.csnItems.forEach(function (element) {
+                        if (element.isSelected === false) { // Keep unselected elements.
+                            newArray.push(element);
+                            //var index = $scope.csnItems.indexOf(element);
+                            //$scope.csnItems = $scope.csnItems.splice(index, 1);
+                            //console.log("Removing data at index " + index);
+                        }
+                    });
+
+                    $scope.csnItems = newArray.slice();
+
+                    /*console.log("List of indexes = " + indices);
+                     indices.forEach(function (index) {
+                     console.log("Removing data at index " + index);
+                     
+                     if (index > -1) { // index should be always positive as the element should be present in the list
+                     // but we never know ;-)
+                     $scope.csnItems = $scope.csnItems.splice(index, 1);
+                     console.log("Removing data at index " + index);
+                     }
+                     });*/
+
+                    /*$timeout(function () {
+                     $scope.csnItems = $scope.csnItems.filter(function (element) {
+                     return (element.isSelected === false);
+                     });
+                     });*/
+
+                }
+
+
+                $scope.csnItems = [{
+                        csnValue: '1234567890ABCDEFAAAA',
+                        time: '21:54:28 28/8/2018',
+                        replicaId: 7,
+                        seqNumber: 4,
+                        isSelected: false
+                    },
+                    {
+                        csnValue: '1234567890ABCDEF4321',
+                        time: '21:54:28 28/8/2018',
+                        replicaId: 4,
+                        seqNumber: 7,
+                        isSelected: false
+
+                    }];
+
+                $scope.notificationCsn = {
+                    type: 'info',
+                    isPersistent: false,
+                    header: 'Message: ',
+                    message: ''
+                };
+
+                $scope.csnEmptyStateConfig = {
+                    icon: 'pficon-warning-triangle-o',
+                    title: 'No Items Available',
+                    info: "No CSN has been added yet.\n"
+                            + "Please use the Add Button to add a new CSN."
+                };
+
+                $scope.csn = {
+                    textView: '',
+                    value: ''
+                };
+
+                $scope.csnColumns = [
+                    {header: "CSN Value", itemField: "csnValue"},
+                    {header: "Time GMT", itemField: "time"},
+                    {header: "Replica Id", itemField: "replicaId"},
+                    {header: "Sequence Number", itemField: "seqNumber"}
+                ];
+
+                $scope.csnConfig = {
+                    onCheckBoxChange: handleCheckBoxChange,
+                    selectionMatchProp: "csnValue",
+                    itemsAvailable: false,
+                    showCheckboxes: true
+                };
+
+                $scope.secondaryLoadInformation = 'Loading CSN Converter Wizard...';
+                $scope.csnWizardReady = false;
+                $timeout(function () {
+                    $scope.csnWizardReady = true;
+                    //}, 1500);
+                }, 1000);
+                $scope.nextButtonTitle = "Next >";
+
+
+                function handleCheckBoxChange(item) {
+                    //$timeout(function () {
+                    item.isSelected = item.selected;
+                    //});
+                    console.log(item.csnValue + ' checked: ' + item.selected);
+                }
+
+
+                var isCsnValid = function (aCsn) {
+                    // A valid CSN has 20 characters.
+                    // From https://access.redhat.com/solutions/3536761
+                    /*A CSN is a 16 character hexadecimal string including the date, the replica id,
+                     *  the sequence number, and an additional number.
+                     *  More precisely:
+                     *  a) first 8 digits representing the date and time of the update generated in the supplier.
+                     *  It's the number of seconds from January 1st 1970.
+                     *  b) the next 4 characters represent the number of change that took place during that second,
+                     *   since we can have several updates per second.
+                     *  c) the following 4 characters are the replica ID.
+                     *  d) the latest 4 characters are reserved but not used for the moment,
+                     *  and they are always shown as "0000".
+                     */
+
+                    // Only Hexadecimal:
+                    //if ((aCsn.match(/^[0-9a-fA-F]+$/)) === null) {
+                    if ((aCsn.match(/^[0-9A-F]+$/i)) === null) {
+                        notificationErrorMessage = 'The value "' + aCsn + '" is not a valid CSN! It contains invalid characters.';
+                        return false;
+                    }
+                    // Length:
+                    console.log('Data length is ' + aCsn.length);
+                    if (aCsn.length !== 20) {
+                        notificationErrorMessage = 'The value "' + aCsn + '" is not a valid CSN! Its length is too short.';
+                        return false;
+                    }
+                    // CSN is a valid one:
+                    return true;
+                };
+
+                $scope.addCsn = function () {
+
+                    var currentCsn = $scope.csn.value;
+                    $scope.working = true;
+                    var isValid = isCsnValid(currentCsn);
+                    var array = $scope.csnItems.filter(function (item) {
+                        console.log('currentCsn.toUpperCase() = ' + currentCsn.toUpperCase());
+                        console.log('item.csnValue.toUpperCase() = ' + item.csnValue.toUpperCase());
+                        //return (parseInt(currentCsn, 16) === parseInt(item.csnValue, 16));
+                        return (currentCsn.toUpperCase() === item.csnValue.toUpperCase());
+                    });
+                    var alreadyExists = !(array.length === 0);
+                    console.log('alreadyExists  ' + alreadyExists);
+
+                    //var index = $scope.csnItems.indexOf(currentCsn);
+                    //console.log('$scope.csnItems.indexOf(currentCsn) = ' + index);
+
+                    /*if (isValid === false) {
+                     errMsg = 'The value "' + currentCsn + '" is not a valid CSN!';
+                     }*/
+                    if (alreadyExists) {
+                        notificationErrorMessage = 'The value "' + currentCsn + '" is already added!';
+                    }
+                    if ((isValid === false) || (alreadyExists === true)) {
+                        $timeout(function () {
+                            $scope.notificationCsn.type = 'danger';
+                            $scope.notificationCsn.message = notificationErrorMessage;
+                            $scope.working = false;
+                        });
+                        return;
+                    }
+
+                    // Decode the CSN:
+                    var t = parseInt(currentCsn.substring(0, 8), 16); // Time
+                    var s = parseInt(currentCsn.substring(8, 12), 16); // Sequence number
+                    var r = parseInt(currentCsn.substring(12, 16), 16); // Replica ID
+                    var d = new Date(0); // Set the date to the epoch
+                    d.setUTCSeconds(t);
+
+                    $timeout(function () {
+                        $scope.notificationCsn.type = 'success';
+                        $scope.notificationCsn.message = 'CSN "' + currentCsn + ' is successfully added.';
+                        $scope.csnItems.push(
+                                {
+                                    csnValue: $scope.csn.value,
+                                    time: d.toUTCString(),
+                                    replicaId: r,
+                                    seqNumber: s,
+                                    isSelected: false
+                                });
+                        $scope.working = false;
+                    }, 200);
+                };
+
+                $scope.clearData = function () {
+                    $scope.csn.value = '';
+                };
+
+
+                var showTextView = function () {
+                    var text = '';
+                    $scope.csnItems.forEach(function (element) {
+                        text = text + '=======================\n'
+                                + 'CSN Value: ' + element.csnValue + '\n'
+                                + 'Time GMT: ' + element.time + '\n'
+                                + 'Replica ID: ' + element.replicaId + '\n'
+                                + 'Sequence Number: ' + element.seqNumber + '\n';
+                    });
+
+                    $timeout(function () {
+                        $scope.csn.textView = text;
+                    });
+
+                };
+
+
+                $scope.nextCallback = function (step) {
+
+                    if (step.stepId === 'convert-csn') {
+                        showTextView();
+                    }
+                    return true;
+                };
+
+                $scope.backCallback = function (step) {
+                    return true;
+                };
+
+                $scope.stepChanged = function (step, index) {
+                    if (step.stepId === 'text-view') {
+                        $scope.nextButtonTitle = "Close";
+                    } else {
+                        $scope.nextButtonTitle = "Next >";
+                    }
+                };
+
+                $scope.cancelCsnWizard = function () {
+                    $rootScope.$emit('wizard.done', 'cancel');
+                };
+
+                $scope.finishedCsnWizard = function () {
+                    $rootScope.$emit('wizard.done', 'done');
+                    return true;
+                };
+
+
+            }
+        ]);
diff --git a/montool/controllers/wizards/expiredcerts.js b/montool/controllers/wizards/expiredcerts.js
new file mode 100644
index 0000000..93f2980
--- /dev/null
+++ b/montool/controllers/wizards/expiredcerts.js
@@ -0,0 +1,403 @@
+/* 
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+angular.module('monitoring.tool.controllers').controller('ExpiredCertsController', ['LoginFactory', '$scope', '$timeout', '$rootScope',
+    function (LoginFactory, $scope, $timeout, $rootScope) {
+
+        $scope.data = {};
+        $scope.rootAccessComplete = false;
+        $scope.connectionCommandComplete = false;
+        $scope.detailsCommandsComplete = false;
+        $scope.statusCommandsComplete = false;
+
+        var initializeWizard = function () {
+            $scope.data = {
+                defaultHost: LoginFactory.getHostname(),
+                currentHost: LoginFactory.getHostname(),
+                name: '',
+                description: '',
+                lorem: 'default setting',
+                ipsum: ''
+            };
+            $scope.secondaryLoadInformation = 'Loading IPA Checkup Wizard...';
+            $scope.wizardReady = false;
+            $timeout(function () {
+                $scope.wizardReady = true;
+                //}, 1500);
+            }, 1000);
+            $scope.nextButtonTitle = "Next >";
+
+        };
+
+        var startDeploy = function () {
+            $timeout(function () { }, 10000);
+            $scope.deployInProgress = true;
+        };
+
+        /*
+         $scope.firstStepNextTooltip = "First step next";
+         $scope.firstStepPrevTooltip = "First step back";
+         $scope.secondStepNextTooltip = "Second step next";
+         $scope.secondStepPrevTooltip = "Second step back";
+         $scope.reviewStepNextTooltip = "Review step next";
+         $scope.reviewStepPrevTooltip = "Review step back";
+         */
+
+        $scope.nextCallback = function (step) {
+            // call startdeploy after deploy button is clicked on review-summary tab
+            if (step.stepId === 'details-host') {
+                checkRootAccess();
+            } else if (step.stepId === 'details-root-access') {
+                getServerDetails();
+            } else if (step.stepId === 'details-server-info') {
+                getServerStatus();
+            } else if (step.stepId === 'review-summary') {
+                startDeploy();
+            }
+            return true;
+        };
+
+        $scope.backCallback = function (step) {
+            return true;
+        };
+
+        $scope.stepChanged = function (step, index) {
+            /*if (step.stepId === 'review-summary') {
+                $scope.nextButtonTitle = "Deploy";
+            } else*/ if (step.stepId === 'test-ipa-functions') {
+                $scope.nextButtonTitle = 'Close';
+            } else {
+                $scope.nextButtonTitle = 'Next >';
+            }
+        };
+        $scope.cancelDeploymentWizard = function () {
+            $rootScope.$emit('wizard.done', 'cancel');
+        };
+        $scope.finishedWizard = function () {
+            $rootScope.$emit('wizard.done', 'done');
+            return true;
+        };
+
+        initializeWizard();
+        // Make sure to define the notifications AFTER running "initializeWizard()".
+        // Otherwise $scope.data.currentHost will be undefined.         
+        $scope.notificationCommand = {
+            type: 'info',
+            isPersistent: false,
+            header: 'Command: ',
+            message: ''
+        };
+
+        $scope.notificationResult = {
+            type: 'info',
+            isPersistent: false,
+            header: 'Result: ',
+            message: ''
+        };
+
+        //
+        // Host
+        //
+        $scope.hostReviewTemplate = "views/wizards/expiredcerts/review-template.html";
+        $scope.details = {
+            hostname: 'defaultHost'
+        };
+        $scope.hostInfoComplete = true; // Default choice is the login host or "localhost".
+        $scope.hostFocusSelectors = ['#serverName'];
+        $scope.hostOnShow = function () {
+        };
+
+        $scope.hostUpdateNextButtonState = function () {
+            if ($scope.details.hostname === 'defaultHost') {
+                $scope.data.currentHost = $scope.data.defaultHost;
+                $scope.hostInfoComplete = true;
+            } else {
+                $scope.data.currentHost = $scope.data.anotherServer;
+                $scope.hostInfoComplete = angular.isDefined($scope.data.anotherServer)
+                        && $scope.data.anotherServer.length > 0;
+            }
+            /*$scope.notificationCommand = {
+             type: 'info',
+             isPersistent: false,
+             header: 'Command: ',
+             message: 'ssh root@' + $scope.data.currentHost + ' -o BatchMode=yes -o ConnectTimeout=10 id'
+             };*/
+            //$scope.notificationCommand.message = 'ssh root@' + $scope.data.currentHost + ' -o BatchMode=yes -o ConnectTimeout=10 id';
+
+        };
+
+        //
+        // Root access
+        //
+        var checkRootAccess = function () {
+            //$scope.checkRootAccess = function () {
+
+            $scope.notificationCommand.message = 'ssh root@' + $scope.data.currentHost + ' -o BatchMode=yes -o ConnectTimeout=10 id';
+            $scope.notificationResult.message = 'Checking Root Access...';
+            $scope.notificationResult.type = 'info';
+            $scope.rootAccessComplete = false; // Need to check the root access first.
+            $scope.connectionCommandComplete = false;
+
+            console.log("$scope.data.currentHost = " + $scope.data.currentHost);
+            console.log("$scope.data.anotherServer = " + $scope.data.anotherServer);
+            var xhr = new XMLHttpRequest();
+            xhr.open('GET', '/api/v1/montool/check-root-access/' + $scope.data.currentHost, true);
+            // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send#Example_GET
+            // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseText
+            // If specified, responseType must be empty string or "text"
+            xhr.responseType = 'text';
+
+            xhr.onload = function () {
+                if (xhr.readyState === XMLHttpRequest.DONE) {
+                    if (xhr.status === 200) {
+                        var commandRes = xhr.responseText;
+                        console.log(commandRes);
+                        if (commandRes.startsWith('STDOUT: ')) {
+                            // Need to use '$timeout' to make sure that the changes are reflected in the UI.
+                            // https://stackoverflow.com/questions/39310992/difference-between-settimeout-in-javascript-and-timeout-service-in-angularjs
+                            // https://www.patternfly.org/angular-patternfly/#/api/patternfly.table.component:pfTableView-with-Toolbar
+                            // ==> script.js 
+                            $timeout(function () {
+                                $scope.notificationResult.type = 'success';
+                                $scope.notificationResult.message = commandRes.substring(7);
+                                // Enable the 'Next' button:
+                                $scope.rootAccessComplete = true;
+                            });
+                        } else if (commandRes.startsWith('STDERR: ')) {
+                            $timeout(function () {
+                                $scope.notificationResult.type = 'danger';
+                                $scope.notificationResult.message = commandRes.substring(7);
+                                // Disable the 'Next' button:
+                                $scope.rootAccessComplete = false;
+                            });
+                        }
+                        // Command completed
+                        $scope.connectionCommandComplete = true;
+                        console.log("$scope.connectionCommandComplete = " + $scope.connectionCommandComplete);
+                    }
+                }
+            };
+
+            xhr.send(null);
+        };
+
+        //
+        // Server details
+        //
+
+        $scope.detailsAndStatusConfig = {
+            showSelectBox: false,
+            selectItems: false,
+            multiSelect: false,
+            dblClick: false,
+            dragEnabled: false,
+            selectionMatchProp: 'name',
+            selectedItems: [],
+            itemsAvailable: true,
+            useExpandingRows: true
+        };
+
+        $scope.detailsItems = [
+            {
+                name: "versionCommand",
+                command: "# ipa --version",
+                mainOutput: "",
+                additionalOutput: "",
+                disableRowExpansion: true
+            },
+            {
+                name: "uptimeCommand",
+                command: "# uptime [-p]",
+                mainOutput: "",
+                additionalOutput: "",
+                disableRowExpansion: true
+            },
+            {
+                name: "ipaPackagesCommand",
+                command: "# rpm -qa | grep ipa-",
+                mainOutput: "",
+                additionalOutput: ""
+            },
+            {
+                name: "hostnamectlStatusCommand",
+                command: "# hostnamectl status",
+                mainOutput: "",
+                additionalOutput: ""
+            }
+        ];
+
+        function getCommandByName(step, cmdName) {
+            if ('Details' === step) {
+                return $scope.detailsItems.find(command => command.name === cmdName);
+            } else if ('Status' === step) {
+                return $scope.statusItems.find(command => command.name === cmdName);
+            }
+        }
+
+        var getServerDetails = function () {
+            $scope.detailsCommandsComplete = false;
+
+            var xhr = new XMLHttpRequest();
+            xhr.open('GET', '/api/v1/montool/command/' + $scope.data.currentHost + ' DETAILS', true);
+            xhr.responseType = 'text';
+            xhr.onload = function () {
+                if (xhr.readyState === XMLHttpRequest.DONE) {
+                    if (xhr.status === 200) {
+                        var details = xhr.responseText;
+                        var parsedDetails = JSON.parse(details);
+                        console.log("Server details data = " + JSON.stringify(parsedDetails));
+                        var version = parsedDetails.version;
+                        var uptime = parsedDetails.uptime;
+                        var hostStatus = parsedDetails.hostStatus;
+                        var packages = parsedDetails.packages;
+                        //if (!(uptime === '')) {
+                        $timeout(function () {
+                            //uptime = uptime.replace(/(?:\r\n|\r|\n)/g, '<br>');
+                            getCommandByName('Details', 'versionCommand').mainOutput = version;
+                            getCommandByName('Details', 'uptimeCommand').mainOutput = uptime;
+                            getCommandByName('Details', 'ipaPackagesCommand').additionalOutput = packages.split('\n').slice();
+                            getCommandByName('Details', 'hostnamectlStatusCommand').additionalOutput = hostStatus.split('\n').slice();
+                        });
+                        //}
+                        /*if (!(hostStatus === '')) {
+                         $timeout(function () {
+                         getCommandByName('hostnamectlStatusCommand').additionalOutput = hostStatus.split('\n').slice();
+                         });
+                         }
+                         if (!(packages === '')) {
+                         $timeout(function () {
+                         //packages = packages.replace(/(?:\r\n|\r|\n)/g, '<br>');
+                         getCommandByName('ipaPackagesCommand').additionalOutput = packages.split('\n').slice();
+                         });
+                         }*/
+
+                        // Command completed
+                        $scope.detailsCommandsComplete = true;
+                    }
+                }
+            };
+            xhr.send(null);
+        };
+
+        //
+        // Server status
+        //
+        $scope.statusItems = [
+            {
+                name: "serverTimeCommand",
+                command: "# date -u '+%Y-%m-%d %H:%M:%S %Z'",
+                mainOutput: "",
+                additionalOutput: "",
+                typeIcon: "pficon pficon-info",
+                disableRowExpansion: true
+            },
+            {
+                name: "numberTrackedCertsCommand",
+                command: "# getcert list | grep 'Number of certificates and requests being tracked:'",
+                mainOutput: "",
+                additionalOutput: "",
+                typeIcon: "pficon pficon-ok",
+                disableRowExpansion: true
+            },
+            {
+                name: "numberExpiredCertsCommand",
+                command: "# getcert list | grep -E 'certificate:|expires:'",
+                mainOutput: "",
+                typeIcon: "pficon pficon-ok",
+                additionalOutput: ""
+            },
+            {
+                name: "ipaStatusCommand",
+                command: "# ipactl status",
+                mainOutput: "",
+                typeIcon: "pficon pficon-ok",
+                additionalOutput: ""
+            }
+        ];
+
+
+        var getServerStatus = function () {
+            $scope.statusCommandsComplete = false;
+            var xhr = new XMLHttpRequest();
+            xhr.open('GET', '/api/v1/montool/command/' + $scope.data.currentHost + ' STATUS', true);
+            xhr.responseType = 'text';
+            xhr.onload = function () {
+                if (xhr.readyState === XMLHttpRequest.DONE) {
+                    if (xhr.status === 200) {
+                        var statusInfo = xhr.responseText;
+                        var parsedStatusInfo = JSON.parse(statusInfo);
+                        console.log("Server status info = " + JSON.stringify(parsedStatusInfo));
+                        var serverTime = parsedStatusInfo.serverTime;
+                        var expiredCerts = parsedStatusInfo.expiredCerts;
+                        var trackedCerts = parsedStatusInfo.trackedCerts;
+                        var ipaStatus = parsedStatusInfo.ipaStatus;
+                        //var expiredCerts2 = expiredCerts.split('\n').slice();
+
+                        $timeout(function () {
+                            getCommandByName('Status', 'serverTimeCommand').mainOutput = serverTime;
+                            getCommandByName('Status', 'numberExpiredCertsCommand').additionalOutput = expiredCerts.split('certificate: ').slice();
+                            getCommandByName('Status', 'numberTrackedCertsCommand').mainOutput = trackedCerts;
+                            getCommandByName('Status', 'ipaStatusCommand').additionalOutput = ipaStatus.split('\n').slice();
+                        });
+                        // Command completed
+                        $scope.statusCommandsComplete = true;
+                    }
+                }
+            };
+            xhr.send(null);
+        };
+    }
+]);
+
+
+
+angular.module('monitoring.tool.controllers').controller('DetailsReviewController', ['$rootScope', '$scope',
+    function ($rootScope, $scope) {
+        'use strict';
+        // Find the data!
+        var next = $scope;
+        while (angular.isUndefined($scope.data)) {
+            next = next.$parent;
+            if (angular.isUndefined(next)) {
+                $scope.data = {};
+            } else {
+                $scope.data = next.$ctrl.wizardData;
+            }
+        }
+    }
+]);
+angular.module('monitoring.tool.controllers').controller('SecondStepController', ['$rootScope', '$scope',
+    function ($rootScope, $scope) {
+        'use strict';
+        $scope.focusSelectors = ['.invalid-classname', '#step-two-new-lorem'];
+    }
+]);
+
+angular.module('monitoring.tool.controllers').controller('FinalStepsController', ['$rootScope', '$scope', '$timeout',
+    function ($rootScope, $scope, $timeout) {
+        'use strict';
+       /* $scope.pageShown = false;
+        $scope.onShow = function () {
+            $scope.pageShown = true;
+            $timeout(function () {
+                $scope.pageShown = false; // done so the next time the page is shown it updates
+            });
+        }; */
+    }
+]);
+
+angular.module('monitoring.tool.controllers').controller('DeploymentController', ['$rootScope', '$scope', '$timeout',
+    function ($rootScope, $scope, $timeout) {
+        'use strict';
+        $scope.onShow = function () {
+            $scope.deploymentComplete = false;
+            $timeout(function () {
+                $scope.deploymentComplete = true;
+            }, 2500);
+        };
+    }
+]);
diff --git a/montool/controllers/wizards/logconv.js b/montool/controllers/wizards/logconv.js
new file mode 100644
index 0000000..ac2703b
--- /dev/null
+++ b/montool/controllers/wizards/logconv.js
@@ -0,0 +1,429 @@
+/* 
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+/* 
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+///////////////////////////////////////////
+// Controllers for the replcheck wizard.
+///////////////////////////////////////////
+
+angular.module('monitoring.tool.controllers').controller('LogconvController', [
+    'LoginFactory', 'InformationFactory', '$scope', '$timeout', '$rootScope',
+    function (LoginFactory, InformationFactory, $scope, $timeout, $rootScope) {
+
+        //$scope.logconv = {};
+        $scope.logconvComplete = false;
+        $scope.connectionVerified = false;
+        $scope.connectionCommandComplete = true;
+        $scope.logconvLogsItems = [];
+        $scope.logconvOptionsItems = [
+            {option: 'e', description: 'Error Code stats'},
+            {option: 'f', description: 'Failed Login Stats'},
+            {option: 'c', description: 'Connection Code Stats'},
+            {option: 'i', description: 'Client Stats'},
+            {option: 'b', description: 'Bind Stats'},
+            {option: 'a', description: 'Search Base Stats'},
+            {option: 'l', description: 'Search Filter Stats'},
+            {option: 't', description: 'Etime Stats'},
+            {option: 'n', description: 'Nentries Stats'},
+            {option: 'x', description: 'Extended Operations'},
+            {option: 'r', description: 'Most Requested Attribute Stats'},
+            {option: 'g', description: 'Abandoned Operation Stats'},
+            {option: 'j', description: 'Recommendations'},
+            {option: 'u', description: 'Unindexed Search Stats'},
+            {option: 'y', description: 'Connection Latency Stats'},
+            {option: 'p', description: 'Open Connection ID Stats'},
+            {option: 'U', description: 'Unindexed Search Summary'}
+        ];
+
+        $scope.notificationConnection = {
+            type: 'info',
+            isPersistent: false,
+            header: 'Command: ',
+            message: ''
+        };
+
+        $scope.notificationLogsInfo = {
+            type: 'info',
+            isPersistent: false,
+            header: 'Command: ',
+            message: 'stat -c "%n %s %U %a" <LOGS_DIRECTORY> | grep -v "access.rotationinfo"'
+        };
+
+
+        /*$scope.logconvToolbarActionsConfig = {
+         primaryActions: [
+         {
+         name: 'Select All Logs',
+         title: 'Select all the access logs',
+         actionFn: selectAllLogs
+         },
+         {
+         name: 'Deselect All Logs',
+         title: 'Deselect all the access logs',
+         actionFn: deselectAllLogs
+         }
+         ]
+         };
+         
+         $scope.logconvToolbarConfig = {
+         actionsConfig: $scope.logconvToolbarActionsConfig,
+         isTableView: true
+         };
+         
+         function selectAllLogs() {
+         
+         }
+         function deselectAllLogs() {
+         
+         }*/
+
+        $scope.logconvEmptyStateConfig = {
+            icon: 'pficon-warning-triangle-o',
+            title: 'No Items Available',
+            info: "No access log has been added yet.\n"
+        };
+
+        $scope.logconvLogsColumns = [
+            {header: "Log File", itemField: "logFile"},
+            {header: "Size", itemField: "size"},
+            {header: "Owner", itemField: "owner"},
+            {header: "Permissions", itemField: "permissions"}
+        ];
+
+        $scope.logconvLogsConfig = {
+            onCheckBoxChange: handleCheckBoxChangeLogsList,
+            selectionMatchProp: "logFile",
+            itemsAvailable: false,
+            showCheckboxes: true
+        };
+
+        function handleCheckBoxChangeLogsList(item) {
+            console.log(item.logFile + ' checked: ' + item.selected);
+            var index = $scope.logconv.listOfLogs.indexOf(item.logFile);
+            if (item.selected === true) { // Add the log if not present in the list.
+                if (index === -1) {
+                    $scope.logconv.listOfLogs.push(item.logFile);
+                }
+            } else { // Remove the log if it is in the list.
+                if (index > -1) {
+                    $scope.logconv.listOfLogs.splice(index, 1);
+                }
+            }
+            //console.log('$scope.logconv.listOfLogs = ' + $scope.logconv.listOfLogs);
+        }
+
+
+        $scope.logconvOptionsColumns = [
+            {header: "Option", itemField: "option"},
+            {header: "Description", itemField: "description"}
+        ];
+
+        $scope.logconvOptionsConfig = {
+            onCheckBoxChange: handleCheckBoxChangeOptions,
+            selectionMatchProp: "option",
+            itemsAvailable: true,
+            showCheckboxes: true
+        };
+
+        function handleCheckBoxChangeOptions(item) {
+            console.log(item.option + ' checked: ' + item.selected);
+            var index = $scope.logconv.options.indexOf(item.option);
+            if (item.selected === true) { // Add the log if not present in the list.
+                if (index === -1) {
+                    $scope.logconv.options.push(item.option);
+                }
+            } else { // Remove the log if it is in the list.
+                if (index > -1) {
+                    $scope.logconv.options.splice(index, 1);
+                }
+            }
+            console.log('$scope.logconv.options = ' + $scope.logconv.options);
+        }
+
+
+
+        $scope.logsListOnShow = function () {
+            runLogconvCommand('GET_LIST_OF_LOGS');
+        };
+
+        $scope.runLogconvOnShow = function () {
+            runLogconvCommand('RUN_LOG_CONV');
+        };
+
+        var initializeLogconvWizard = function () {
+
+            // Eg: nsslapd-accesslog: /var/log/dirsrv/slapd-<INSTANCE_NAME>/access
+            var logsDir = InformationFactory.getMonitoringAttribute('nsslapd-accesslog');
+            if (logsDir) {
+                logsDir = logsDir.slice(0, -('/access'.length));
+                console.log('Logs directory = ' + logsDir);
+            } else {
+                logsDir = '';
+                console.log('Logs directory is not defined.');
+            }
+
+            $scope.logconv = {
+                monitoredHost: LoginFactory.getHostname(), // Stick to the host that the user logs to.
+                //linuxUser: 'dirsrv',
+                linuxUser: 'root',
+                accessLogDirectory: logsDir,
+                options: [],
+                listOfLogs: []
+            };
+
+            $scope.secondaryLoadInformation = 'Loading Log Converter Wizard...';
+            $scope.logconvWizardReady = false;
+            $timeout(function () {
+                $scope.logconvWizardReady = true;
+                //}, 1500);
+            }, 1000);
+
+            $scope.nextButtonTitle = "Next >";
+
+        };
+
+
+        $scope.checkConnection = function () {
+            console.log('Checking the connection...');
+            //$scope.connectionVerified = false;
+            checkConnectionToHost();
+        };
+
+        $scope.nextCallback = function (step) {
+            return true;
+        };
+
+        $scope.backCallback = function (step) {
+            return true;
+        };
+
+        $scope.stepChanged = function (step, index) {
+            if (step.stepId === 'options') {
+                $scope.nextButtonTitle = "Run >";
+            } else if (step.stepId === 'output') {
+                $scope.nextButtonTitle = "Show Data";
+            } else {
+                $scope.nextButtonTitle = "Next >";
+            }
+        };
+
+        $scope.cancelLogconvWizard = function () {
+            $rootScope.$emit('wizard.done', 'cancel');
+        };
+
+        $scope.finishedLogconvWizard = function () {
+            $rootScope.$emit('wizard.done', 'done');
+            return true;
+        };
+
+        initializeLogconvWizard();
+
+        // Check connection to the host.
+        var checkConnectionToHost = function () {
+
+            $scope.notificationConnection.type = 'info';
+            $scope.notificationConnection.header = 'Command: ';
+            $scope.notificationConnection.message = '$ /usr/bin/ssh ' + $scope.logconv.linuxUser + '@'
+                    + $scope.logconv.monitoredHost + ' -o BatchMode=yes -o ConnectTimeout=10 id';
+
+            $scope.connectionVerified = false;
+            $scope.connectionCommandComplete = false;
+
+            var params = {
+                host: $scope.logconv.monitoredHost,
+                user: $scope.logconv.linuxUser
+            };
+
+            var urlEncodedData_cnx = "";
+            var urlEncodedDataPairs_cnx = [];
+            var name;
+            for (name in params) {
+                urlEncodedDataPairs_cnx.push(encodeURIComponent(name) + '=' + encodeURIComponent(params[name]));
+            }
+
+            urlEncodedData_cnx = urlEncodedDataPairs_cnx.join('&').replace(/%20/g, '+');
+
+            var xhr = new XMLHttpRequest();
+            xhr.open('POST', '/api/v1/montool/common/verify-access/', true);
+
+            xhr.responseType = 'text';
+
+            xhr.onload = function () {
+                if (xhr.readyState === XMLHttpRequest.DONE) {
+                    if (xhr.status === 200) {
+                        var commandRes = xhr.responseText;
+                        console.log(commandRes);
+                        $timeout(function () {
+                            $scope.notificationConnection.header = 'Result: ';
+                        });
+
+                        if (commandRes.startsWith('STDOUT: ')) {
+                            $timeout(function () {
+                                $scope.notificationConnection.type = 'success';
+                                $scope.notificationConnection.message = commandRes.substring(7);
+                                // Enable the 'Next' button:
+                                $scope.connectionVerified = true;
+                            });
+                        } else if (commandRes.startsWith('STDERR: ')) {
+                            $timeout(function () {
+                                $scope.notificationConnection.type = 'danger';
+                                $scope.notificationConnection.message = commandRes.substring(7);
+                                // Disable the 'Next' button:
+                                $scope.connectionVerified = false;
+                            });
+                        }
+                        // Command completed
+                        $scope.connectionCommandComplete = true;
+                    }
+                }
+            };
+
+            xhr.addEventListener('error', function (event) {
+                alert('Got an error while sending the XMLHttpRequest.');
+            });
+            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+            xhr.send(urlEncodedData_cnx);
+
+        };
+
+
+        // Run the command
+        var runLogconvCommand = function (commandToRun) {
+
+            // Clear any previous items first:
+            $scope.logconvLogsItems.length = 0;
+
+            var params = {
+                host: $scope.logconv.monitoredHost,
+                user: $scope.logconv.linuxUser,
+                logsDirectory: $scope.logconv.accessLogDirectory,
+                logsList: $scope.logconv.listOfLogs,
+                options: $scope.logconv.options,
+                command: commandToRun
+            };
+
+            console.log('logsList: ' + $scope.logconv.listOfLogs);
+            console.log('options:' + $scope.logconv.options);
+
+            var urlEncodedData_cmd = "";
+            var urlEncodedDataPairs_cmd = [];
+            var name;
+            for (name in params) {
+                urlEncodedDataPairs_cmd.push(encodeURIComponent(name) + '=' + encodeURIComponent(params[name]));
+            }
+
+            urlEncodedData_cmd = urlEncodedDataPairs_cmd.join('&').replace(/%20/g, '+');
+
+            $scope.logsListCommandComplete = false;
+            $scope.logconvCommandComplete = false;
+
+            var xhr = new XMLHttpRequest();
+            xhr.open('POST', '/api/v1/montool/logconv/run-logconv', true);
+
+            xhr.onreadystatechange = function () {
+                if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
+                    // Request finished. Do processing here.
+                    var response = xhr.responseText;
+                    if (response && response.length > 0) {
+                        //var cmdOutput = xhr.responseText;
+                        $timeout(function () {
+                            if (commandToRun === 'GET_LIST_OF_LOGS') {
+                                parseLogconvOutput_logsList(response);
+                                $scope.logsListCommandComplete = true;
+                            } else if (commandToRun === 'RUN_LOG_CONV') {
+                                //var dataArray = JSON.parse(response);
+                                //console.log('dataArray.mods = ' + dataArray.mods);
+                                //console.log('response = ' + response);
+                                InformationFactory.storeLogconvData(response);
+                                $scope.logconvCommandComplete = true;
+                                $scope.logconv.output = response;
+                            }
+                            //console.log("InformationFactory.getLogconvData() = " + InformationFactory.getLogconvData());
+                        });
+                    }
+                }
+            };
+
+            // Define what happens in case of error
+            xhr.addEventListener('error', function (event) {
+                alert('Got an error while sending the XMLHttpRequest.');
+            });
+
+            // Add the required HTTP header for form data POST requests
+            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+
+            // Finally, send our data.
+            xhr.send(urlEncodedData_cmd);
+            //console.log(JSON.stringify(urlEncodedData));
+
+        };
+
+
+        function parseLogconvOutput_logsList(logconvOutput) {
+            var result = logconvOutput.split('\n').slice();
+            console.log('result[0] = ' + result[0]);
+            console.log('result[12] = ' + result[12]);
+            console.log('result[13] = ' + result[13]);
+            console.log('result[14] = ' + result[14]);
+            //console.log('result[1] = ' + result[1]);
+            //console.log('result[2] = ' + result[2]);
+            //console.log('logconvOutput.substring(7) =' + logconvOutput.substring(7));
+            //console.log('logconvOutput =' + logconvOutput);
+
+            if (result[0] === 'STDOUT') { // Error code of the "stat" command was 0.
+                $scope.notificationLogsInfo.type = 'info';
+                $scope.notificationLogsInfo.message = 'The command '
+                        + ' ( stat -c "%n %s %U %a" ./access* | grep -v "access.rotationinfo" ) '
+                        + 'was run successfully.';
+                // Name                   Size    Owner   Permissions   
+                // access.20180830-162332 1941142 dirsrv 600
+                var i;
+                for (i = 0; i < result.length; i++) {
+                    var line = result[i];
+                    console.log('result[' + i + '] = ' + result[i]);
+                    var data = line.split(' ');
+                    // Quick sanity check:
+                    if (data.length !== 4) {
+                        console.log('data.length = ' + data.length);
+                        continue;
+                    }
+
+                    $scope.logconvLogsItems.push(
+                            {
+                                logFile: data[0].substring(2),
+                                size: computeLogSize(parseInt(data[1], 10)),
+                                owner: data[2],
+                                permissions: data[3],
+                                sizeInBytes: data[1] // Not displayed. Used only for sorting purpose.
+                            });
+                }
+            } else if (result[0] === 'STDERR') {
+                $scope.notificationLogsInfo.type = 'danger';
+                $scope.notificationLogsInfo.message = logconvOutput.substring(8);
+            }
+
+        }
+
+        function computeLogSize(size) {
+            if (size > 0) {
+                var i = Math.floor(Math.log(size) / Math.log(1024));
+                return (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i];
+            } else {
+                return '0 B';
+            }
+        }
+
+
+    }
+]);
diff --git a/montool/controllers/wizards/replcheck.js b/montool/controllers/wizards/replcheck.js
new file mode 100644
index 0000000..e5819f0
--- /dev/null
+++ b/montool/controllers/wizards/replcheck.js
@@ -0,0 +1,164 @@
+/* 
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+///////////////////////////////////////////
+// Controllers for the replcheck wizard.
+///////////////////////////////////////////
+
+angular.module('monitoring.tool.controllers').controller('ReplicationCheckController', ['$scope', '$timeout', '$rootScope',
+    function ($scope, $timeout, $rootScope) {
+
+        $scope.replcheck = {};
+        $scope.replCheckComplete = false;
+
+        $scope.notificationCommand = {
+            type: 'info',
+            isPersistent: false,
+            header: 'Command: ',
+            message: ''
+        };
+
+        var initializeReplicationCheckWizard = function () {
+            $scope.replcheck = {
+                supplier: 'localhost:1389',
+                replica: 'localhost:2389',
+                binddn: 'cn=Directory Manager',
+                password: '',
+                suffix: 'dc=TekoSoft,dc=com',
+                replicaConnType: 'ldap',
+                supplierConnType: 'ldap'
+            };
+            $scope.secondaryLoadInformation = 'Loading Replication Check Wizard...';
+            $scope.replCheckWizardReady = false;
+            $timeout(function () {
+                $scope.replCheckWizardReady = true;
+                //}, 1500);
+            }, 1000);
+            $scope.nextButtonTitle = "Next >";
+
+        };
+
+
+
+        $scope.nextCallback = function (step) {
+
+            if (step.stepId === 'suffix') {
+                runReplcheckCommand();
+            }
+            return true;
+        };
+
+        $scope.backCallback = function (step) {
+            return true;
+        };
+
+        $scope.stepChanged = function (step, index) {
+            if (step.stepId === 'output') {
+                $scope.nextButtonTitle = "Close";
+            } else {
+                $scope.nextButtonTitle = "Next >";
+            }
+        };
+
+        $scope.cancelReplCheckWizard = function () {
+            $rootScope.$emit('wizard.done', 'cancel');
+        };
+
+        $scope.finishedReplCheckWizard = function () {
+            $rootScope.$emit('wizard.done', 'done');
+            return true;
+        };
+
+        $scope.handleConnectionType = function () {
+            switch ($scope.replcheck.connection) {
+                case 'clear':
+                case 'startTLS':
+                    $scope.replcheck.supplierConnType = 'ldap';
+                    $scope.replcheck.replicaConnType = 'ldap';
+                    break;
+                case 'TLS':
+                    $scope.replcheck.supplierConnType = 'ldaps';
+                    $scope.replcheck.replicaConnType = 'ldaps';
+                    break;
+                case 'LDAPI':
+                    $scope.replcheck.supplierConnType = 'ldapi';
+                    $scope.replcheck.replicaConnType = 'ldap';
+                    break;
+                default:
+                    console.log("Invalid value for the type of connection ==> " + $scope.replcheck.connection);
+            }
+        };
+
+        initializeReplicationCheckWizard();
+
+        // Run the command
+
+        var runReplcheckCommand = function () {
+
+            $scope.replCheckComplete = false;
+
+            $scope.notificationCommand.message = '/usr/bin/ds-replcheck -D "' + $scope.replcheck.binddn + '" -w <PASSWORD>'
+                    + ' -m ' + $scope.replcheck.supplierConnType + '://' + $scope.replcheck.supplier
+                    + ' -r ' + $scope.replcheck.replicaConnType + '://' + $scope.replcheck.replica
+                    + ' -b "' + $scope.replcheck.suffix + '"';
+
+
+            var cmdOptions = {
+                binddn: $scope.replcheck.binddn,
+                password: $scope.replcheck.password,
+                supplierUrl: $scope.replcheck.supplierConnType + '://' + $scope.replcheck.supplier,
+                replicaUrl: $scope.replcheck.replicaConnType + '://' + $scope.replcheck.replica,
+                suffix: $scope.replcheck.suffix
+            };
+
+            var urlEncodedData = "";
+            var urlEncodedDataPairs = [];
+            var name;
+
+            // Turn the data object into an array of URL-encoded key/value pairs.
+            for (name in cmdOptions) {
+                urlEncodedDataPairs.push(encodeURIComponent(name) + '=' + encodeURIComponent(cmdOptions[name]));
+            }
+
+            // Combine the pairs into a single string and replace all %-encoded spaces to 
+            // the '+' character; matches the behaviour of browser form submissions.
+            urlEncodedData = urlEncodedDataPairs.join('&').replace(/%20/g, '+');
+
+            var xhr = new XMLHttpRequest();
+            xhr.open('POST', '/api/v1/montool/command/ds-replcheck', true);
+
+            xhr.onreadystatechange = function () {//Call a function when the state changes.
+                if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
+                    // Request finished. Do processing here.
+                    var response = xhr.responseText;
+                    if (response && response.length > 0) {
+                        var cmdOutput = xhr.responseText;
+                        $timeout(function () {
+                            $scope.replcheck.output = cmdOutput;
+                            $scope.replCheckComplete = true;
+                        });
+                        console.log(cmdOutput);
+                    }
+                }
+            };
+
+            // Define what happens in case of error
+            xhr.addEventListener('error', function (event) {
+                alert('Got an error while sending the XMLHttpRequest.');
+            });
+
+            // Add the required HTTP header for form data POST requests
+            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+
+            // Finally, send our data.
+            xhr.send(urlEncodedData);
+            //console.log(JSON.stringify(urlEncodedData));
+
+        };
+    }
+]);
diff --git a/montool/css/logconv.css b/montool/css/logconv.css
new file mode 100644
index 0000000..306b523
--- /dev/null
+++ b/montool/css/logconv.css
@@ -0,0 +1,10 @@
+
+#list-of-logs {
+    overflow: scroll;
+        height: 300px;
+
+}
+
+#scrolltest {
+  min-height:101%;
+}
diff --git a/montool/css/login.css b/montool/css/login.css
new file mode 100644
index 0000000..26d6b45
--- /dev/null
+++ b/montool/css/login.css
@@ -0,0 +1,16 @@
+body {
+  padding-bottom: 100px;
+}
+
+.icons .fa, .icons .glyphicon, .icons .pficon {
+  font-size: 14px;
+  margin-right: 5px;
+  text-align: center;
+  width: 14px;
+}
+.icons .icon-class {
+  display: inline-block;
+}
+.icons li {
+  margin: 0 0 7px;
+}
diff --git a/montool/css/topology.css b/montool/css/topology.css
new file mode 100644
index 0000000..436e8df
--- /dev/null
+++ b/montool/css/topology.css
@@ -0,0 +1,51 @@
+.pf-topology-svg g.Pod text {
+   font-family: FontAwesome;
+   font-size: 16px;
+   fill: #1186C1;
+ }
+ 
+  .pf-topology-svg g.Node text {
+   fill: #636363;
+ }
+ 
+  .pf-topology-svg g.Service text {
+   fill: #ff7f0e;
+ }
+ 
+  .pf-topology-svg g.ReplicationController text {
+   fill: #9467bd;
+   font-size: 20px;
+ }
+ 
+  .pf-topology-svg line.ReplicationControllerPod {
+   stroke-linecap: round;
+   stroke-dasharray: 5, 2;
+ }
+ 
+ 
+ .pf-topology-svg line.ContainerServiceContainerGroup, .pf-topology-svg line.ContainerReplicatorContainerGroup, .pf-topology-svg line.ContainerServiceContainerRoute,
+  .pf-topology-svg line.ContainerGroupContainerService, .pf-topology-svg line.ContainerGroupContainerReplicator {
+   stroke-linecap: round;
+   stroke-dasharray: 5.5;
+ }
+ 
+ 
+.pf-topology-svg g.Container text.glyph {
+   font-size: 18px;
+ }
+ 
+  .pf-topology-svg g.ContainerGroup text.glyph {
+   font-size: 28px;
+ }
+ 
+  .pf-topology-svg g.Vm text.glyph, .pf-topology-svg g.Host text.glyph {
+   fill: #636363;
+ }
+ 
+  .pf-topology-svg g.ContainerNode text.glyph {
+   font-size: 18px;
+ }
+ 
+  .pf-topology-svg g.ContainerManager text.glyph {
+   font-size: 18px;
+ }
diff --git a/montool/css/troubleshoot.css b/montool/css/troubleshoot.css
new file mode 100644
index 0000000..6b82239
--- /dev/null
+++ b/montool/css/troubleshoot.css
@@ -0,0 +1,13 @@
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/* 
+    Created on : Aug 18, 2018, 2:21:57 AM
+    Author     : Têko Mihinto <tmihinto@redhat.com>
+*/
+
+.nav-tabs > li.active > a {
+  font-size: 18px;
+}
\ No newline at end of file
diff --git a/montool/images/Logo_Horizontal_Reversed.svg b/montool/images/Logo_Horizontal_Reversed.svg
new file mode 100644
index 0000000..5d7d0dc
--- /dev/null
+++ b/montool/images/Logo_Horizontal_Reversed.svg
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 600 121.3" style="enable-background:new 0 0 600 121.3;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFFFFF;}
+	.st1{fill:url(#SVGID_1_);}
+</style>
+<g>
+	<path class="st0" d="M164.88,75.64V45.16h12.97c1.91,0,3.52,0.28,4.83,0.84c1.31,0.56,2.37,1.3,3.18,2.21
+		c0.81,0.91,1.4,1.94,1.76,3.09c0.36,1.15,0.54,2.31,0.54,3.49c0,0.74-0.08,1.49-0.26,2.25c-0.17,0.76-0.43,1.5-0.78,2.21
+		c-0.35,0.72-0.8,1.38-1.35,2.01c-0.55,0.62-1.21,1.17-1.97,1.65c-0.76,0.47-1.64,0.85-2.63,1.11c-0.99,0.27-2.1,0.41-3.32,0.41
+		h-7.13v11.23H164.88z M178.1,58.83c0.75,0,1.37-0.12,1.88-0.36c0.5-0.25,0.92-0.55,1.23-0.94c0.32-0.38,0.55-0.82,0.69-1.29
+		c0.14-0.48,0.22-0.96,0.22-1.45c0-0.44-0.06-0.9-0.18-1.38c-0.12-0.47-0.33-0.9-0.63-1.3c-0.3-0.4-0.72-0.72-1.24-0.98
+		c-0.52-0.26-1.17-0.39-1.96-0.39h-7.38v8.08H178.1z"/>
+	<path class="st0" d="M228.45,75.64l-2.34-6.31h-11.66l-2.32,6.31h-6.27l11.58-30.49h5.69l11.58,30.49H228.45z M221.24,56.04
+		c-0.15-0.37-0.32-0.81-0.5-1.32c-0.17-0.51-0.33-0.98-0.45-1.43c-0.11,0.44-0.26,0.91-0.44,1.43c-0.18,0.51-0.35,0.95-0.51,1.32
+		l-2.99,7.93h7.87L221.24,56.04z"/>
+	<path class="st0" d="M267.52,50.83v24.81h-5.82V50.83h-8.65v-5.68h23.1v5.68H267.52z"/>
+	<path class="st0" d="M312.76,50.83v24.81h-5.82V50.83h-8.65v-5.68h23.11v5.68H312.76z"/>
+	<path class="st0" d="M345.49,75.64V45.16h20.63v5.59h-14.79v6.4h8.7v5.57h-8.7v7.36h15.7v5.57H345.49z"/>
+	<path class="st0" d="M391.55,75.64V45.16h14.04c1.91,0,3.51,0.26,4.8,0.8c1.28,0.53,2.32,1.24,3.11,2.12
+		c0.78,0.88,1.35,1.89,1.68,3.04c0.34,1.15,0.51,2.35,0.51,3.59c0,0.86-0.13,1.74-0.37,2.62c-0.25,0.89-0.62,1.73-1.11,2.52
+		c-0.49,0.8-1.1,1.51-1.84,2.16c-0.73,0.65-1.58,1.15-2.55,1.49l5.86,12.14h-6.56l-5.65-11.38h-6.09v11.38H391.55z M405.68,58.7
+		c0.74,0,1.37-0.11,1.88-0.33c0.5-0.22,0.91-0.51,1.22-0.88c0.31-0.37,0.54-0.79,0.67-1.28c0.13-0.48,0.2-0.99,0.2-1.51
+		c0-0.48-0.06-0.96-0.18-1.44c-0.12-0.48-0.33-0.9-0.62-1.28c-0.29-0.37-0.7-0.67-1.21-0.9c-0.51-0.23-1.16-0.34-1.95-0.34h-8.29
+		v7.95H405.68z"/>
+	<path class="st0" d="M459.54,75.64l-11.99-17.78c-0.2-0.29-0.41-0.66-0.64-1.09c-0.23-0.43-0.43-0.83-0.6-1.2
+		c0.05,0.32,0.07,0.71,0.1,1.15c0.02,0.44,0.03,0.82,0.03,1.15v17.78h-5.8V45.16h5.48l11.7,17.56c0.18,0.29,0.39,0.64,0.63,1.07
+		c0.24,0.43,0.45,0.84,0.63,1.23c-0.04-0.41-0.07-0.83-0.09-1.24c-0.03-0.42-0.04-0.77-0.04-1.06V45.16h5.78v30.49H459.54z"/>
+	<path class="st0" d="M490.75,75.64V45.16h20.26v5.59h-14.42v6.4h9.15v5.57h-9.15v12.93H490.75z"/>
+	<path class="st0" d="M534.67,75.64V45.16h5.84v24.83h14.59v5.66H534.67z"/>
+	<path class="st0" d="M583.03,75.64V63.76l-11.2-18.6h6.62l7.46,12.46l7.46-12.46H600l-11.19,18.6v11.88H583.03z"/>
+</g>
+<g>
+	<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="63.8196" y1="3.8115" x2="63.8196" y2="121.713">
+		<stop  offset="0" style="stop-color:#83D3E8"/>
+		<stop  offset="1" style="stop-color:#248AC8"/>
+	</linearGradient>
+	<path class="st1" d="M63.96,0.24l0.01-0.11L63.92,0.2L63.9,0.18L63.92,0l-0.1,0.1L63.72,0l0.02,0.18L63.72,0.2l-0.05-0.07
+		l0.01,0.11L0.19,62.84l25.14,35.93l19.42-4.5l19.07,27.04l19.07-27.04l19.42,4.5l15.57-22.25l9.57-13.67L63.96,0.24z M61.89,7.59
+		l-8.67,81.96L36.27,66.24L61.89,7.59z M35.44,65.1L24.78,50.43L61.8,4.75L35.44,65.1z M52.85,91.13l-7.58,1.76L32.53,74.81
+		l3.18-7.27L52.85,91.13z M63.62,3.63l0.2-0.46l0.2,0.46l8.97,88.12l-0.03-0.02l-8.79,13.1l-9.51-13.11l-0.01,0.01L63.62,3.63z
+		 M74.42,89.55L65.75,7.59l25.62,58.65L74.42,89.55z M91.93,67.54l3.18,7.27L82.37,92.88l-7.58-1.76L91.93,67.54z M65.84,4.76
+		l37.02,45.67L92.2,65.1L65.84,4.76z M25.85,97.38L1.78,62.98L57.8,7.75L23.24,50.39L34.88,66.4l-3.74,8.56l12.85,18.23L25.85,97.38
+		z M63.82,119.19L46.04,93.97l7.6-1.76l0.13,0.18l-0.08,0.06l10.53,14.52l9.76-14.54l-0.08-0.06L74,92.21l7.6,1.76L63.82,119.19z
+		 M116.89,75.8l-15.1,21.58l-18.13-4.2L96.5,74.96l-3.74-8.56l11.64-16.01L69.84,7.75l56.02,55.23L116.89,75.8z"/>
+</g>
+</svg>
diff --git a/montool/images/brand.svg b/montool/images/brand.svg
new file mode 100644
index 0000000..aeb9611
--- /dev/null
+++ b/montool/images/brand.svg
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="270px" height="10px" viewBox="0 0 270 10" enable-background="new 0 0 270 10" xml:space="preserve">
+<g>
+	<g>
+		<path fill="#FFFFFF" d="M121.965,9.413h-4.883V0.656h4.883v0.903h-3.862V4.38h3.63v0.898h-3.63V8.5h3.862V9.413z"/>
+		<path fill="#FFFFFF" d="M130.988,9.413h-1.158l-4.789-7.352h-0.046c0.062,0.864,0.095,1.655,0.095,2.374v4.978h-0.94V0.656h1.15
+			l4.774,7.317h0.045c-0.006-0.107-0.022-0.453-0.051-1.041c-0.028-0.582-0.039-0.998-0.028-1.254V0.656h0.951v8.753h-0.003V9.413
+			L130.988,9.413z"/>
+		<path fill="#FFFFFF" d="M136.339,9.413h-1.018V1.561h-2.771V0.656h6.564v0.903h-2.771v7.852h-0.002v0.002H136.339z"/>
+		<path fill="#FFFFFF" d="M145.554,9.413h-4.877V0.656h4.877v0.903h-3.859V4.38h3.631v0.898h-3.631V8.5h3.859V9.413z"/>
+		<path fill="#FFFFFF" d="M148.761,5.769v3.641h-1.018V0.656h2.402c1.074,0,1.865,0.204,2.379,0.614
+			c0.514,0.412,0.771,1.032,0.771,1.858c0,1.156-0.586,1.94-1.764,2.349l2.383,3.934h-1.207l-2.121-3.645h-1.826V5.769
+			L148.761,5.769z M148.761,4.897h1.396c0.719,0,1.244-0.142,1.582-0.428c0.334-0.286,0.504-0.714,0.504-1.285
+			c0-0.582-0.17-0.997-0.512-1.254c-0.34-0.255-0.889-0.381-1.643-0.381h-1.324v3.349h-0.004V4.897z"/>
+		<path fill="#FFFFFF" d="M161.124,3.209c0,0.884-0.301,1.567-0.904,2.046c-0.605,0.477-1.475,0.714-2.6,0.714h-1.031v3.444h-1.016
+			V0.656h2.27C160.03,0.656,161.124,1.504,161.124,3.209z M156.589,5.092h0.92c0.898,0,1.555-0.146,1.959-0.435
+			c0.4-0.293,0.604-0.759,0.604-1.404c0-0.577-0.188-1.006-0.568-1.295c-0.381-0.279-0.973-0.423-1.773-0.423h-1.139v3.557H156.589z
+			"/>
+		<path fill="#FFFFFF" d="M164.22,5.769v3.641h-1.02V0.656h2.402c1.074,0,1.865,0.204,2.383,0.614
+			c0.512,0.412,0.771,1.032,0.771,1.858c0,1.156-0.588,1.94-1.762,2.349l2.379,3.934h-1.205l-2.119-3.645h-1.826v0.002H164.22z
+			 M164.22,4.897h1.395c0.719,0,1.244-0.142,1.582-0.428c0.334-0.286,0.504-0.714,0.504-1.285c0-0.582-0.17-0.997-0.51-1.254
+			c-0.34-0.255-0.887-0.381-1.645-0.381h-1.322v3.349h-0.004V4.897z"/>
+		<path fill="#FFFFFF" d="M171.03,9.413V0.656h1.018v8.753h-1.018V9.413z"/>
+		<path fill="#FFFFFF" d="M179.636,7.081c0,0.773-0.281,1.374-0.838,1.805c-0.561,0.434-1.318,0.646-2.277,0.646
+			c-1.039,0-1.836-0.134-2.395-0.4V8.147c0.357,0.152,0.75,0.272,1.174,0.357c0.422,0.088,0.844,0.131,1.258,0.131
+			c0.68,0,1.188-0.129,1.531-0.384c0.346-0.257,0.514-0.62,0.514-1.073c0-0.304-0.061-0.556-0.184-0.748
+			c-0.119-0.194-0.318-0.375-0.607-0.537c-0.285-0.162-0.721-0.351-1.301-0.558c-0.816-0.29-1.398-0.636-1.748-1.036
+			c-0.352-0.398-0.525-0.92-0.525-1.562c0-0.674,0.254-1.211,0.764-1.611c0.508-0.398,1.178-0.599,2.014-0.599
+			c0.869,0,1.672,0.161,2.398,0.48l-0.316,0.884c-0.725-0.3-1.428-0.454-2.109-0.454c-0.539,0-0.959,0.114-1.266,0.347
+			c-0.303,0.231-0.453,0.553-0.453,0.965c0,0.305,0.057,0.551,0.168,0.745c0.115,0.195,0.303,0.372,0.566,0.533
+			c0.268,0.161,0.672,0.34,1.221,0.535c0.92,0.327,1.551,0.679,1.896,1.056C179.462,5.995,179.636,6.483,179.636,7.081z"/>
+		<path fill="#FFFFFF" d="M186.556,9.413h-4.881V0.656h4.881v0.903h-3.863V4.38h3.633v0.898h-3.633V8.5h3.863V9.413z"/>
+		<path fill="#FFFFFF" d="M197.677,9.413l-1.09-2.785h-3.51l-1.078,2.785h-1.031l3.463-8.793h0.854l3.443,8.793H197.677z
+			 M196.267,5.71l-1.018-2.712c-0.131-0.345-0.271-0.766-0.406-1.263c-0.09,0.383-0.211,0.804-0.377,1.263l-1.031,2.712H196.267z"/>
+		<path fill="#FFFFFF" d="M205.733,3.209c0,0.884-0.303,1.567-0.908,2.046c-0.607,0.477-1.473,0.714-2.596,0.714h-1.031v3.444
+			h-1.021V0.656h2.273C204.642,0.656,205.733,1.504,205.733,3.209z M201.2,5.092h0.914c0.902,0,1.557-0.146,1.961-0.435
+			c0.398-0.293,0.605-0.759,0.605-1.404c0-0.577-0.189-1.006-0.57-1.295c-0.381-0.279-0.969-0.423-1.773-0.423H201.2V5.092
+			L201.2,5.092z"/>
+		<path fill="#FFFFFF" d="M213.366,3.209c0,0.884-0.307,1.567-0.908,2.046c-0.607,0.477-1.473,0.714-2.598,0.714h-1.031v3.444h-1.02
+			V0.656h2.271C212.269,0.656,213.366,1.504,213.366,3.209z M208.827,5.092h0.918c0.904,0,1.559-0.146,1.959-0.435
+			c0.404-0.293,0.604-0.759,0.604-1.404c0-0.577-0.188-1.006-0.566-1.295c-0.381-0.279-0.971-0.423-1.773-0.423h-1.141V5.092
+			L208.827,5.092z"/>
+		<path fill="#FFFFFF" d="M215.44,9.413V0.656h1.021v7.832h3.857V9.41h-4.879V9.413z"/>
+		<path fill="#FFFFFF" d="M222.052,9.413V0.656h1.021v8.753h-1.021V9.413z"/>
+		<path fill="#FFFFFF" d="M229.466,1.44c-0.959,0-1.721,0.32-2.279,0.959c-0.557,0.642-0.834,1.518-0.834,2.633
+			c0,1.146,0.27,2.031,0.807,2.656c0.537,0.621,1.303,0.937,2.299,0.937c0.611,0,1.309-0.108,2.09-0.327v0.891
+			c-0.605,0.229-1.355,0.343-2.244,0.343c-1.289,0-2.285-0.396-2.988-1.181c-0.699-0.776-1.051-1.891-1.051-3.333
+			c0-0.902,0.17-1.69,0.506-2.371c0.336-0.678,0.824-1.202,1.461-1.569s1.387-0.551,2.248-0.551c0.918,0,1.719,0.168,2.408,0.504
+			l-0.432,0.875C230.798,1.594,230.13,1.44,229.466,1.44z"/>
+		<path fill="#FFFFFF" d="M239.204,9.413l-1.09-2.785h-3.512l-1.074,2.785h-1.031l3.459-8.793h0.857l3.445,8.793H239.204z
+			 M237.798,5.71l-1.018-2.712c-0.133-0.345-0.27-0.766-0.406-1.263c-0.088,0.383-0.215,0.804-0.377,1.263l-1.033,2.712H237.798z"/>
+		<path fill="#FFFFFF" d="M244.401,9.413h-1.016V1.561h-2.773V0.656h6.564v0.903h-2.771v7.852h-0.004V9.413z"/>
+		<path fill="#FFFFFF" d="M248.743,9.413V0.656h1.018v8.753h-1.018V9.413z"/>
+		<path fill="#FFFFFF" d="M260.005,5.021c0,1.402-0.354,2.503-1.062,3.305c-0.707,0.806-1.691,1.206-2.955,1.206
+			c-1.291,0-2.285-0.396-2.988-1.186c-0.699-0.789-1.051-1.901-1.051-3.338c0-1.424,0.354-2.532,1.057-3.312
+			c0.699-0.785,1.703-1.18,2.99-1.18c1.262,0,2.24,0.399,2.951,1.2C259.655,2.513,260.005,3.614,260.005,5.021z M253.03,5.021
+			c0,1.186,0.25,2.085,0.754,2.697c0.508,0.613,1.242,0.922,2.203,0.922c0.973,0,1.705-0.311,2.201-0.918
+			c0.494-0.615,0.738-1.516,0.738-2.702c0-1.179-0.244-2.072-0.736-2.681c-0.49-0.61-1.223-0.914-2.189-0.914
+			c-0.969,0-1.705,0.306-2.213,0.918C253.282,2.96,253.03,3.851,253.03,5.021z"/>
+		<path fill="#FFFFFF" d="M269.044,9.413h-1.162l-4.783-7.352h-0.049c0.061,0.864,0.094,1.655,0.094,2.374v4.978H262.2V0.656h1.152
+			l4.771,7.319h0.049c-0.012-0.108-0.025-0.455-0.055-1.041c-0.027-0.582-0.041-0.998-0.029-1.256V0.656h0.951v8.755h0.006v0.002
+			H269.044z"/>
+	</g>
+	<g>
+		<path fill="#FFFFFF" d="M7.533,3.368c0,1.013-0.298,1.796-0.896,2.348C6.04,6.269,5.191,6.544,4.093,6.544H3.403v3.008H0.954
+			V0.485h3.139c1.145,0,2.005,0.25,2.58,0.75C7.246,1.736,7.533,2.447,7.533,3.368z M3.403,4.547h0.447
+			c0.368,0,0.66-0.103,0.877-0.31s0.326-0.492,0.326-0.856c0-0.612-0.339-0.918-1.018-0.918H3.403V4.547z"/>
+		<path fill="#FFFFFF" d="M17.652,9.552l-0.446-1.699h-2.944l-0.459,1.699h-2.691l2.958-9.104h3.268l2.995,9.104H17.652z
+			 M16.697,5.843l-0.39-1.489c-0.092-0.33-0.202-0.758-0.333-1.283c-0.13-0.525-0.216-0.901-0.257-1.128
+			c-0.037,0.211-0.111,0.558-0.221,1.042c-0.108,0.483-0.353,1.437-0.729,2.857H16.697z"/>
+		<path fill="#FFFFFF" d="M28.423,9.552h-2.449V2.488H23.76V0.485h6.871v2.003h-2.208V9.552z"/>
+		<path fill="#FFFFFF" d="M39.037,9.552h-2.449V2.488h-2.214V0.485h6.871v2.003h-2.208V9.552z"/>
+		<path fill="#FFFFFF" d="M51.035,9.552h-5.382V0.485h5.382V2.45h-2.933v1.427h2.716v1.966h-2.716v1.711h2.933V9.552z"/>
+		<path fill="#FFFFFF" d="M58.184,6.253v3.299h-2.449V0.485h2.97c2.464,0,3.696,0.893,3.696,2.679c0,1.05-0.513,1.862-1.538,2.437
+			l2.642,3.951h-2.777l-1.922-3.299H58.184z M58.184,4.41h0.459c0.855,0,1.284-0.378,1.284-1.135c0-0.625-0.42-0.937-1.26-0.937
+			h-0.483V4.41z"/>
+		<path fill="#FFFFFF" d="M76.072,9.552H72.86L69.55,3.164h-0.057c0.079,1.004,0.118,1.771,0.118,2.301v4.086h-2.17V0.485h3.2
+			l3.299,6.301h0.037c-0.059-0.914-0.086-1.648-0.086-2.202V0.485h2.183v9.066H76.072z"/>
+		<path fill="#FFFFFF" d="M83.557,9.552h-2.412V0.485h5.356V2.45h-2.944v1.73h2.716v1.965h-2.716V9.552z"/>
+		<path fill="#FFFFFF" d="M91.102,9.552V0.485h2.449v7.088h3.49v1.979H91.102z"/>
+		<path fill="#FFFFFF" d="M104.842,3.846l1.562-3.361h2.654l-2.983,5.525v3.541h-2.468V6.085l-2.983-5.6h2.667L104.842,3.846z"/>
+	</g>
+</g>
+</svg>
diff --git a/montool/images/canvas-dot-grid.png b/montool/images/canvas-dot-grid.png
new file mode 100644
index 0000000..8b856e6
--- /dev/null
+++ b/montool/images/canvas-dot-grid.png
@@ -0,0 +1,553 @@
+
+
+
+
+
+
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+  <link rel="dns-prefetch" href="https://assets-cdn.github.com">
+  <link rel="dns-prefetch" href="https://avatars0.githubusercontent.com">
+  <link rel="dns-prefetch" href="https://avatars1.githubusercontent.com">
+  <link rel="dns-prefetch" href="https://avatars2.githubusercontent.com">
+  <link rel="dns-prefetch" href="https://avatars3.githubusercontent.com">
+  <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com">
+  <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/">
+
+
+
+  <link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/frameworks-a4bf54bef6fb.css" integrity="sha512-pL9Uvvb7LMqGC8jv/AyqZ7Ya6/HTgkhZzKwEsHOdsfaW2pr3fgzqjgKUSJfYkZ/klxwHrcu+tZwtNDTuw8vH6Q==" media="all" rel="stylesheet" />
+  <link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/github-ff93979e5482.css" integrity="sha512-/5OXnlSCjEzfMa9X79lZMViWQy2OYtTlyuDAoudSAguMY3k4uAaC+iuUxYq1iVbMjA0bVVD5cipR4Odv9A1kog==" media="all" rel="stylesheet" />
+  
+  
+  <link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/site-40fcabbe0152.css" integrity="sha512-QPyrvgFSff4TPraGjRVwjjUuUYhkKKzPUBEwcArwfkdRwAHGF0V7+v1hPmMZbnJKdXTWicSkRiGOTvEiNmCISg==" media="all" rel="stylesheet" />
+  
+
+  <meta name="viewport" content="width=device-width">
+  
+  <title>patternfly.github.io/canvas-dot-grid.png at master · patternfly/patternfly.github.io · GitHub</title>
+    <meta name="description" content="GitHub is where people build software. More than 28 million people use GitHub to discover, fork, and contribute to over 79 million projects.">
+  <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub">
+  <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub">
+  <meta property="fb:app_id" content="1401488693436528">
+
+    
+    <meta content="https://avatars0.githubusercontent.com/u/6391110?s=400&amp;v=4" property="og:image" /><meta content="GitHub" property="og:site_name" /><meta content="object" property="og:type" /><meta content="patternfly/patternfly.github.io" property="og:title" /><meta content="https://github.com/patternfly/patternfly.github.io" property="og:url" /><meta content="Contribute to patternfly.github.io development by creating an account on GitHub." property="og:description" />
+
+  <link rel="assets" href="https://assets-cdn.github.com/">
+  
+  <meta name="pjax-timeout" content="1000">
+  
+  <meta name="request-id" content="E18A:47CE:439433:81432C:5A9DA1BE" data-pjax-transient>
+  
+
+  <meta name="selected-link" value="repo_source" data-pjax-transient>
+
+    <meta name="google-site-verification" content="KT5gs8h0wvaagLKAVWq8bbeNwnZZK1r1XQysX3xurLU">
+  <meta name="google-site-verification" content="ZzhVyEFwb7w3e0-uOTltm8Jsck2F5StVihD0exw2fsA">
+  <meta name="google-site-verification" content="GXs5KoUUkNCoaAZn7wPN-t01Pywp9M3sEjnt_3_ZWPc">
+    <meta name="google-analytics" content="UA-3769691-2">
+
+<meta content="collector.githubapp.com" name="octolytics-host" /><meta content="github" name="octolytics-app-id" /><meta content="https://collector.githubapp.com/github-external/browser_event" name="octolytics-event-url" /><meta content="E18A:47CE:439433:81432C:5A9DA1BE" name="octolytics-dimension-request_id" /><meta content="iad" name="octolytics-dimension-region_edge" /><meta content="iad" name="octolytics-dimension-region_render" />
+<meta content="https://github.com/hydro_browser_events" name="hydro-events-url" />
+<meta content="/&lt;user-name&gt;/&lt;repo-name&gt;/blob/show" data-pjax-transient="true" name="analytics-location" />
+
+
+
+
+  <meta class="js-ga-set" name="dimension1" content="Logged Out">
+
+
+  
+
+      <meta name="hostname" content="github.com">
+    <meta name="user-login" content="">
+
+      <meta name="expected-hostname" content="github.com">
+    <meta name="js-proxy-site-detection-payload" content="ZGQ0ODZjZjQ2NWQxYWZhZDliMGIxZWFlNTc4MGYwY2I2NWMyNTVhM2I5NTAxOTMwZTNkNjM0YzFiMjUyZmVhNnx7InJlbW90ZV9hZGRyZXNzIjoiODguMTgwLjIzMS4xNTIiLCJyZXF1ZXN0X2lkIjoiRTE4QTo0N0NFOjQzOTQzMzo4MTQzMkM6NUE5REExQkUiLCJ0aW1lc3RhbXAiOjE1MjAyODAwMDQsImhvc3QiOiJnaXRodWIuY29tIn0=">
+
+    <meta name="enabled-features" content="UNIVERSE_BANNER,FREE_TRIALS,MARKETPLACE_INSIGHTS,MARKETPLACE_INSIGHTS_CONVERSION_PERCENTAGES,JS_ROLLUP">
+
+  <meta name="html-safe-nonce" content="e53add15bc461e52ebc46eba47787e291c82443a">
+
+  <meta http-equiv="x-pjax-version" content="811390db952ac49fc91417abafad5742">
+  
+
+      <link href="https://github.com/patternfly/patternfly.github.io/commits/master.atom" rel="alternate" title="Recent Commits to patternfly.github.io:master" type="application/atom+xml">
+
+  <meta name="description" content="Contribute to patternfly.github.io development by creating an account on GitHub.">
+  <meta name="go-import" content="github.com/patternfly/patternfly.github.io git https://github.com/patternfly/patternfly.github.io.git">
+
+  <meta content="6391110" name="octolytics-dimension-user_id" /><meta content="patternfly" name="octolytics-dimension-user_login" /><meta content="69969961" name="octolytics-dimension-repository_id" /><meta content="patternfly/patternfly.github.io" name="octolytics-dimension-repository_nwo" /><meta content="true" name="octolytics-dimension-repository_public" /><meta content="false" name="octolytics-dimension-repository_is_fork" /><meta content="69969961" name="octolytics-dimension-repository_network_root_id" /><meta content="patternfly/patternfly.github.io" name="octolytics-dimension-repository_network_root_nwo" /><meta content="false" name="octolytics-dimension-repository_explore_github_marketplace_ci_cta_shown" />
+
+
+    <link rel="canonical" href="https://github.com/patternfly/patternfly.github.io/blob/master/components/angular-patternfly/dist/docs/img/canvas-dot-grid.png" data-pjax-transient>
+
+
+  <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats">
+
+  <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors">
+
+  <link rel="mask-icon" href="https://assets-cdn.github.com/pinned-octocat.svg" color="#000000">
+  <link rel="icon" type="image/x-icon" class="js-site-favicon" href="https://assets-cdn.github.com/favicon.ico">
+
+<meta name="theme-color" content="#1e2327">
+
+
+  <meta name="u2f-support" content="true">
+
+<link rel="manifest" href="/manifest.json" crossOrigin="use-credentials">
+
+  </head>
+
+  <body class="logged-out env-production emoji-size-boost page-blob">
+    
+
+  <div class="position-relative js-header-wrapper ">
+    <a href="#start-of-content" tabindex="1" class="px-2 py-4 show-on-focus js-skip-to-content">Skip to content</a>
+    <div id="js-pjax-loader-bar" class="pjax-loader-bar"><div class="progress"></div></div>
+
+    
+    
+    
+
+
+
+        <header class="Header header-logged-out  position-relative f4 py-3" role="banner">
+  <div class="container-lg d-flex px-3">
+    <div class="d-flex flex-justify-between flex-items-center">
+      <a class="header-logo-invertocat my-0" href="https://github.com/" aria-label="Homepage" data-ga-click="(Logged out) Header, go to homepage, icon:logo-wordmark">
+        <svg aria-hidden="true" class="octicon octicon-mark-github" height="32" version="1.1" viewBox="0 0 16 16" width="32"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
+      </a>
+
+    </div>
+
+    <div class="HeaderMenu HeaderMenu--bright d-flex flex-justify-between flex-auto">
+        <nav class="mt-0">
+          <ul class="d-flex list-style-none">
+              <li class="ml-2">
+                <a href="/features" class="js-selected-navigation-item HeaderNavlink px-0 py-2 m-0" data-ga-click="Header, click, Nav menu - item:features" data-selected-links="/features /features/project-management /features/code-review /features/project-management /features/integrations /features">
+                  Features
+</a>              </li>
+              <li class="ml-4">
+                <a href="/business" class="js-selected-navigation-item HeaderNavlink px-0 py-2 m-0" data-ga-click="Header, click, Nav menu - item:business" data-selected-links="/business /business/security /business/customers /business">
+                  Business
+</a>              </li>
+
+              <li class="ml-4">
+                <a href="/explore" class="js-selected-navigation-item HeaderNavlink px-0 py-2 m-0" data-ga-click="Header, click, Nav menu - item:explore" data-selected-links="/explore /trending /trending/developers /integrations /integrations/feature/code /integrations/feature/collaborate /integrations/feature/ship showcases showcases_search showcases_landing /explore">
+                  Explore
+</a>              </li>
+
+              <li class="ml-4">
+                    <a href="/marketplace" class="js-selected-navigation-item HeaderNavlink px-0 py-2 m-0" data-ga-click="Header, click, Nav menu - item:marketplace" data-selected-links=" /marketplace">
+                      Marketplace
+</a>              </li>
+              <li class="ml-4">
+                <a href="/pricing" class="js-selected-navigation-item HeaderNavlink px-0 py-2 m-0" data-ga-click="Header, click, Nav menu - item:pricing" data-selected-links="/pricing /pricing/developer /pricing/team /pricing/business-hosted /pricing/business-enterprise /pricing">
+                  Pricing
+</a>              </li>
+          </ul>
+        </nav>
+
+      <div class="d-flex">
+          <div class="d-lg-flex flex-items-center mr-3">
+            <div class="header-search scoped-search site-scoped-search js-site-search" role="search">
+  <!-- '"` --><!-- </textarea></xmp> --></option></form><form accept-charset="UTF-8" action="/patternfly/patternfly.github.io/search" class="js-site-search-form" data-scoped-search-url="/patternfly/patternfly.github.io/search" data-unscoped-search-url="/search" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div>
+    <label class="form-control header-search-wrapper js-chromeless-input-container">
+        <a href="/patternfly/patternfly.github.io/blob/master/components/angular-patternfly/dist/docs/img/canvas-dot-grid.png" class="header-search-scope no-underline">This repository</a>
+      <input type="text"
+        class="form-control header-search-input js-site-search-focus js-site-search-field is-clearable"
+        data-hotkey="s"
+        name="q"
+        value=""
+        placeholder="Search"
+        aria-label="Search this repository"
+        data-unscoped-placeholder="Search GitHub"
+        data-scoped-placeholder="Search"
+        autocapitalize="off">
+        <input type="hidden" class="js-site-search-type-field" name="type" >
+    </label>
+</form></div>
+
+          </div>
+
+        <span class="d-inline-block">
+            <div class="HeaderNavlink px-0 py-2 m-0">
+              <a class="text-bold text-white no-underline" href="/login?return_to=%2Fpatternfly%2Fpatternfly.github.io%2Fblob%2Fmaster%2Fcomponents%2Fangular-patternfly%2Fdist%2Fdocs%2Fimg%2Fcanvas-dot-grid.png" data-ga-click="(Logged out) Header, clicked Sign in, text:sign-in">Sign in</a>
+                <span class="text-gray">or</span>
+                <a class="text-bold text-white no-underline" href="/join?source=header-repo" data-ga-click="(Logged out) Header, clicked Sign up, text:sign-up">Sign up</a>
+            </div>
+        </span>
+      </div>
+    </div>
+  </div>
+</header>
+
+  </div>
+
+  <div id="start-of-content" class="show-on-focus"></div>
+
+    <div id="js-flash-container">
+</div>
+
+
+
+  <div role="main" class="application-main ">
+        <div itemscope itemtype="http://schema.org/SoftwareSourceCode" class="">
+    <div id="js-repo-pjax-container" data-pjax-container >
+      
+
+
+
+
+
+  
+
+
+
+  <div class="pagehead repohead instapaper_ignore readability-menu experiment-repo-nav  ">
+    <div class="repohead-details-container clearfix container">
+
+      <ul class="pagehead-actions">
+  <li>
+      <a href="/login?return_to=%2Fpatternfly%2Fpatternfly.github.io"
+    class="btn btn-sm btn-with-count tooltipped tooltipped-n"
+    aria-label="You must be signed in to watch a repository" rel="nofollow">
+    <svg aria-hidden="true" class="octicon octicon-eye" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg>
+    Watch
+  </a>
+  <a class="social-count" href="/patternfly/patternfly.github.io/watchers"
+     aria-label="12 users are watching this repository">
+    12
+  </a>
+
+  </li>
+
+  <li>
+      <a href="/login?return_to=%2Fpatternfly%2Fpatternfly.github.io"
+    class="btn btn-sm btn-with-count tooltipped tooltipped-n"
+    aria-label="You must be signed in to star a repository" rel="nofollow">
+    <svg aria-hidden="true" class="octicon octicon-star" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74z"/></svg>
+    Star
+  </a>
+
+    <a class="social-count js-social-count" href="/patternfly/patternfly.github.io/stargazers"
+      aria-label="1 user starred this repository">
+      1
+    </a>
+
+  </li>
+
+  <li>
+      <a href="/login?return_to=%2Fpatternfly%2Fpatternfly.github.io"
+        class="btn btn-sm btn-with-count tooltipped tooltipped-n"
+        aria-label="You must be signed in to fork a repository" rel="nofollow">
+        <svg aria-hidden="true" class="octicon octicon-repo-forked" height="16" version="1.1" viewBox="0 0 10 16" width="10"><path fill-rule="evenodd" d="M8 1a1.993 1.993 0 0 0-1 3.72V6L5 8 3 6V4.72A1.993 1.993 0 0 0 2 1a1.993 1.993 0 0 0-1 3.72V6.5l3 3v1.78A1.993 1.993 0 0 0 5 15a1.993 1.993 0 0 0 1-3.72V9.5l3-3V4.72A1.993 1.993 0 0 0 8 1zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3 10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3-10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg>
+        Fork
+      </a>
+
+    <a href="/patternfly/patternfly.github.io/network" class="social-count"
+       aria-label="8 users forked this repository">
+      8
+    </a>
+  </li>
+</ul>
+
+      <h1 class="public ">
+  <svg aria-hidden="true" class="octicon octicon-repo" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg>
+  <span class="author" itemprop="author"><a href="/patternfly" class="url fn" rel="author">patternfly</a></span><!--
+--><span class="path-divider">/</span><!--
+--><strong itemprop="name"><a href="/patternfly/patternfly.github.io" data-pjax="#js-repo-pjax-container">patternfly.github.io</a></strong>
+
+</h1>
+
+    </div>
+    
+<nav class="reponav js-repo-nav js-sidenav-container-pjax container"
+     itemscope
+     itemtype="http://schema.org/BreadcrumbList"
+     role="navigation"
+     data-pjax="#js-repo-pjax-container">
+
+  <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
+    <a href="/patternfly/patternfly.github.io" class="js-selected-navigation-item selected reponav-item" data-hotkey="g c" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches repo_packages /patternfly/patternfly.github.io" itemprop="url">
+      <svg aria-hidden="true" class="octicon octicon-code" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M9.5 3L8 4.5 11.5 8 8 11.5 9.5 13 14 8 9.5 3zm-5 0L0 8l4.5 5L6 11.5 2.5 8 6 4.5 4.5 3z"/></svg>
+      <span itemprop="name">Code</span>
+      <meta itemprop="position" content="1">
+</a>  </span>
+
+    <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
+      <a href="/patternfly/patternfly.github.io/issues" class="js-selected-navigation-item reponav-item" data-hotkey="g i" data-selected-links="repo_issues repo_labels repo_milestones /patternfly/patternfly.github.io/issues" itemprop="url">
+        <svg aria-hidden="true" class="octicon octicon-issue-opened" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"/></svg>
+        <span itemprop="name">Issues</span>
+        <span class="Counter">3</span>
+        <meta itemprop="position" content="2">
+</a>    </span>
+
+  <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
+    <a href="/patternfly/patternfly.github.io/pulls" class="js-selected-navigation-item reponav-item" data-hotkey="g p" data-selected-links="repo_pulls checks /patternfly/patternfly.github.io/pulls" itemprop="url">
+      <svg aria-hidden="true" class="octicon octicon-git-pull-request" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg>
+      <span itemprop="name">Pull requests</span>
+      <span class="Counter">3</span>
+      <meta itemprop="position" content="3">
+</a>  </span>
+
+    <a href="/patternfly/patternfly.github.io/projects" class="js-selected-navigation-item reponav-item" data-hotkey="g b" data-selected-links="repo_projects new_repo_project repo_project /patternfly/patternfly.github.io/projects">
+      <svg aria-hidden="true" class="octicon octicon-project" height="16" version="1.1" viewBox="0 0 15 16" width="15"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg>
+      Projects
+      <span class="Counter" >0</span>
+</a>
+
+
+  <a href="/patternfly/patternfly.github.io/pulse" class="js-selected-navigation-item reponav-item" data-selected-links="repo_graphs repo_contributors dependency_graph pulse /patternfly/patternfly.github.io/pulse">
+    <svg aria-hidden="true" class="octicon octicon-graph" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M16 14v1H0V0h1v14h15zM5 13H3V8h2v5zm4 0H7V3h2v10zm4 0h-2V6h2v7z"/></svg>
+    Insights
+</a>
+
+</nav>
+
+
+  </div>
+
+<div class="container new-discussion-timeline experiment-repo-nav  ">
+  <div class="repository-content ">
+
+    
+  <a href="/patternfly/patternfly.github.io/blob/e9122785ea16a4ef3b51ea1585f9c87561bcfe7c/components/angular-patternfly/dist/docs/img/canvas-dot-grid.png" class="d-none js-permalink-shortcut" data-hotkey="y">Permalink</a>
+
+  <!-- blob contrib key: blob_contributors:v21:24b3db7c3f882f2500b7d10ebd373b8b -->
+
+  <div class="file-navigation">
+    
+<div class="select-menu branch-select-menu js-menu-container js-select-menu float-left">
+  <button class=" btn btn-sm select-menu-button js-menu-target css-truncate" data-hotkey="w"
+    
+    type="button" aria-label="Switch branches or tags" aria-expanded="false" aria-haspopup="true">
+      <i>Branch:</i>
+      <span class="js-select-button css-truncate-target">master</span>
+  </button>
+
+  <div class="select-menu-modal-holder js-menu-content js-navigation-container" data-pjax>
+
+    <div class="select-menu-modal">
+      <div class="select-menu-header">
+        <svg aria-label="Close" class="octicon octicon-x js-menu-close" height="16" role="img" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg>
+        <span class="select-menu-title">Switch branches/tags</span>
+      </div>
+
+      <div class="select-menu-filters">
+        <div class="select-menu-text-filter">
+          <input type="text" aria-label="Filter branches/tags" id="context-commitish-filter-field" class="form-control js-filterable-field js-navigation-enable" placeholder="Filter branches/tags">
+        </div>
+        <div class="select-menu-tabs">
+          <ul>
+            <li class="select-menu-tab">
+              <a href="#" data-tab-filter="branches" data-filter-placeholder="Filter branches/tags" class="js-select-menu-tab" role="tab">Branches</a>
+            </li>
+            <li class="select-menu-tab">
+              <a href="#" data-tab-filter="tags" data-filter-placeholder="Find a tag…" class="js-select-menu-tab" role="tab">Tags</a>
+            </li>
+          </ul>
+        </div>
+      </div>
+
+      <div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="branches" role="menu">
+
+        <div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
+
+
+            <a class="select-menu-item js-navigation-item js-navigation-open "
+               href="/patternfly/patternfly.github.io/blob/gh-pages/components/angular-patternfly/dist/docs/img/canvas-dot-grid.png"
+               data-name="gh-pages"
+               data-skip-pjax="true"
+               rel="nofollow">
+              <svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"/></svg>
+              <span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
+                gh-pages
+              </span>
+            </a>
+            <a class="select-menu-item js-navigation-item js-navigation-open selected"
+               href="/patternfly/patternfly.github.io/blob/master/components/angular-patternfly/dist/docs/img/canvas-dot-grid.png"
+               data-name="master"
+               data-skip-pjax="true"
+               rel="nofollow">
+              <svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"/></svg>
+              <span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
+                master
+              </span>
+            </a>
+        </div>
+
+          <div class="select-menu-no-results">Nothing to show</div>
+      </div>
+
+      <div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="tags">
+        <div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
+
+
+        </div>
+
+        <div class="select-menu-no-results">Nothing to show</div>
+      </div>
+
+    </div>
+  </div>
+</div>
+
+    <div class="BtnGroup float-right">
+      <a href="/patternfly/patternfly.github.io/find/master"
+            class="js-pjax-capture-input btn btn-sm BtnGroup-item"
+            data-pjax
+            data-hotkey="t">
+        Find file
+      </a>
+      <clipboard-copy
+            for="blob-path"
+            role="button"
+            aria-label="Copy file path to clipboard"
+            class="btn btn-sm BtnGroup-item tooltipped tooltipped-s"
+            data-copied-hint="Copied!">
+        Copy path
+      </clipboard-copy>
+    </div>
+    <div id="blob-path" class="breadcrumb">
+      <span class="repo-root js-repo-root"><span class="js-path-segment"><a href="/patternfly/patternfly.github.io" data-pjax="true"><span>patternfly.github.io</span></a></span></span><span class="separator">/</span><span class="js-path-segment"><a href="/patternfly/patternfly.github.io/tree/master/components" data-pjax="true"><span>components</span></a></span><span class="separator">/</span><span class="js-path-segment"><a href="/patternfly/patternfly.github.io/tree/master/components/angular-patternfly" data-pjax="true"><span>angular-patternfly</span></a></span><span class="separator">/</span><span class="js-path-segment"><a href="/patternfly/patternfly.github.io/tree/master/components/angular-patternfly/dist" data-pjax="true"><span>dist</span></a></span><span class="separator">/</span><span class="js-path-segment"><a href="/patternfly/patternfly.github.io/tree/master/components/angular-patternfly/dist/docs" data-pjax="true"><span>docs</span></a></span><span class="separator">/</span><span class="js-path-segment"><a href="/patternfly/patternfly.github.io/tree/master/components/angular-patternfly/dist/docs/img" data-pjax="true"><span>img</span></a></span><span class="separator">/</span><strong class="final-path">canvas-dot-grid.png</strong>
+    </div>
+  </div>
+
+
+  <include-fragment class="commit-tease" src="/patternfly/patternfly.github.io/contributors/master/components/angular-patternfly/dist/docs/img/canvas-dot-grid.png">
+    <div>
+      Fetching contributors&hellip;
+    </div>
+
+    <div class="commit-tease-contributors">
+      <img alt="" class="loader-loading float-left" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32-EAF2F5.gif" width="16" />
+      <span class="loader-error">Cannot retrieve contributors at this time</span>
+    </div>
+</include-fragment>
+
+  <div class="file">
+    <div class="file-header">
+  <div class="file-actions">
+
+    <div class="BtnGroup">
+      <a href="/patternfly/patternfly.github.io/raw/master/components/angular-patternfly/dist/docs/img/canvas-dot-grid.png" class="btn btn-sm BtnGroup-item" id="raw-url">Download</a>
+      <a href="/patternfly/patternfly.github.io/commits/master/components/angular-patternfly/dist/docs/img/canvas-dot-grid.png" class="btn btn-sm BtnGroup-item" rel="nofollow">History</a>
+    </div>
+
+        <a class="btn-octicon tooltipped tooltipped-nw"
+           href="https://desktop.github.com"
+           aria-label="Open this file in GitHub Desktop"
+           data-ga-click="Repository, open with desktop, type:mac">
+            <svg aria-hidden="true" class="octicon octicon-device-desktop" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M15 2H1c-.55 0-1 .45-1 1v9c0 .55.45 1 1 1h5.34c-.25.61-.86 1.39-2.34 2h8c-1.48-.61-2.09-1.39-2.34-2H15c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm0 9H1V3h14v8z"/></svg>
+        </a>
+
+        <!-- '"` --><!-- </textarea></xmp> --></option></form><form accept-charset="UTF-8" action="/patternfly/patternfly.github.io/delete/master/components/angular-patternfly/dist/docs/img/canvas-dot-grid.png" class="inline-form" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /><input name="authenticity_token" type="hidden" value="sOGGyhdGIzW/TNRA2MyHlbms9ZlaFYOUXBV9gXeVt9dJ1HO1RpYHPKBiJ6DnyVtwRRJeyjoKicf/I51Yu1ckqg==" /></div>
+          <button class="btn-octicon btn-octicon-danger tooltipped tooltipped-nw" type="submit"
+            aria-label="You must be signed in to make or propose changes" data-disable-with>
+            <svg aria-hidden="true" class="octicon octicon-trashcan" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M11 2H9c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1H2c-.55 0-1 .45-1 1v1c0 .55.45 1 1 1v9c0 .55.45 1 1 1h7c.55 0 1-.45 1-1V5c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 12H3V5h1v8h1V5h1v8h1V5h1v8h1V5h1v9zm1-10H2V3h9v1z"/></svg>
+          </button>
+</form>  </div>
+
+  <div class="file-info">
+    100 Bytes
+  </div>
+</div>
+
+    
+
+  <div itemprop="text" class="blob-wrapper data type-text">
+      <div class="image">
+          <span class="border-wrap"><img src="/patternfly/patternfly.github.io/blob/master/components/angular-patternfly/dist/docs/img/canvas-dot-grid.png?raw=true" alt="canvas-dot-grid.png"></span>
+      </div>
+  </div>
+
+  </div>
+
+  <button type="button" data-facebox="#jump-to-line" data-facebox-class="linejump" data-hotkey="l" class="d-none">Jump to Line</button>
+  <div id="jump-to-line" style="display:none">
+    <!-- '"` --><!-- </textarea></xmp> --></option></form><form accept-charset="UTF-8" action="" class="js-jump-to-line-form" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div>
+      <input class="form-control linejump-input js-jump-to-line-field" type="text" placeholder="Jump to line&hellip;" aria-label="Jump to line" autofocus>
+      <button type="submit" class="btn">Go</button>
+</form>  </div>
+
+
+  </div>
+  <div class="modal-backdrop js-touch-events"></div>
+</div>
+
+    </div>
+  </div>
+
+  </div>
+
+      
+<div class="footer container-lg px-3" role="contentinfo">
+  <div class="position-relative d-flex flex-justify-between py-6 mt-6 f6 text-gray border-top border-gray-light ">
+    <ul class="list-style-none d-flex flex-wrap ">
+      <li class="mr-3">&copy; 2018 <span title="0.39502s from unicorn-2513954578-lrvmf">GitHub</span>, Inc.</li>
+        <li class="mr-3"><a href="https://help.github.com/articles/github-terms-of-service/" data-ga-click="Footer, go to terms, text:terms">Terms</a></li>
+        <li class="mr-3"><a href="https://github.com/site/privacy" data-ga-click="Footer, go to privacy, text:privacy">Privacy</a></li>
+        <li class="mr-3"><a href="https://help.github.com/articles/github-security/" data-ga-click="Footer, go to security, text:security">Security</a></li>
+        <li class="mr-3"><a href="https://status.github.com/" data-ga-click="Footer, go to status, text:status">Status</a></li>
+        <li><a href="https://help.github.com" data-ga-click="Footer, go to help, text:help">Help</a></li>
+    </ul>
+
+    <a href="https://github.com" aria-label="Homepage" class="footer-octicon" title="GitHub">
+      <svg aria-hidden="true" class="octicon octicon-mark-github" height="24" version="1.1" viewBox="0 0 16 16" width="24"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
+</a>
+    <ul class="list-style-none d-flex flex-wrap ">
+        <li class="mr-3"><a href="https://github.com/contact" data-ga-click="Footer, go to contact, text:contact">Contact GitHub</a></li>
+      <li class="mr-3"><a href="https://developer.github.com" data-ga-click="Footer, go to api, text:api">API</a></li>
+      <li class="mr-3"><a href="https://training.github.com" data-ga-click="Footer, go to training, text:training">Training</a></li>
+      <li class="mr-3"><a href="https://shop.github.com" data-ga-click="Footer, go to shop, text:shop">Shop</a></li>
+        <li class="mr-3"><a href="https://github.com/blog" data-ga-click="Footer, go to blog, text:blog">Blog</a></li>
+        <li><a href="https://github.com/about" data-ga-click="Footer, go to about, text:about">About</a></li>
+
+    </ul>
+  </div>
+</div>
+
+
+
+  <div id="ajax-error-message" class="ajax-error-message flash flash-error">
+    <svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M8.865 1.52c-.18-.31-.51-.5-.87-.5s-.69.19-.87.5L.275 13.5c-.18.31-.18.69 0 1 .19.31.52.5.87.5h13.7c.36 0 .69-.19.86-.5.17-.31.18-.69.01-1L8.865 1.52zM8.995 13h-2v-2h2v2zm0-3h-2V6h2v4z"/></svg>
+    <button type="button" class="flash-close js-ajax-error-dismiss" aria-label="Dismiss error">
+      <svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg>
+    </button>
+    You can't perform that action at this time.
+  </div>
+
+
+    
+    <script crossorigin="anonymous" integrity="sha512-6oz7cTsS3E5enQjh4gWKU23tC78zIZqVJ1o5zMLCsAv5EEnmNsopwszDz7zx5IGWXU+H+sqeC5pHbt1Yxmh+sw==" src="https://assets-cdn.github.com/assets/frameworks-ea8cfb713b12.js" type="application/javascript"></script>
+    
+    <script async="async" crossorigin="anonymous" integrity="sha512-XIAj1gPRKJF0vtrYESzNJv9c4z9oufRgfOICoaz2NFI5TH35i4TrSbF1T7gg7kkwhKIKxf6l2W48wy25TetwSg==" src="https://assets-cdn.github.com/assets/github-5c8023d603d1.js" type="application/javascript"></script>
+    
+    
+    
+    
+  <div class="js-stale-session-flash stale-session-flash flash flash-warn flash-banner d-none">
+    <svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M8.865 1.52c-.18-.31-.51-.5-.87-.5s-.69.19-.87.5L.275 13.5c-.18.31-.18.69 0 1 .19.31.52.5.87.5h13.7c.36 0 .69-.19.86-.5.17-.31.18-.69.01-1L8.865 1.52zM8.995 13h-2v-2h2v2zm0-3h-2V6h2v4z"/></svg>
+    <span class="signed-in-tab-flash">You signed in with another tab or window. <a href="">Reload</a> to refresh your session.</span>
+    <span class="signed-out-tab-flash">You signed out in another tab or window. <a href="">Reload</a> to refresh your session.</span>
+  </div>
+  <div class="facebox" id="facebox" style="display:none;">
+  <div class="facebox-popup">
+    <div class="facebox-content" role="dialog" aria-labelledby="facebox-header" aria-describedby="facebox-description">
+    </div>
+    <button type="button" class="facebox-close js-facebox-close" aria-label="Close modal">
+      <svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg>
+    </button>
+  </div>
+</div>
+
+  
+
+  </body>
+</html>
+
diff --git a/montool/images/favicon.ico b/montool/images/favicon.ico
new file mode 100644
index 0000000..7a85a1c
Binary files /dev/null and b/montool/images/favicon.ico differ
diff --git a/montool/images/logo-alt.svg b/montool/images/logo-alt.svg
new file mode 100644
index 0000000..34c6980
--- /dev/null
+++ b/montool/images/logo-alt.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="37px" height="35px" viewBox="0 0 37 35" enable-background="new 0 0 37 35" xml:space="preserve">
+<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="231.8955" y1="-269.5547" x2="231.8955" y2="-301.7199" gradientTransform="matrix(1 0 0 -1 -213.5 -268.5)">
+	<stop  offset="0" style="stop-color:#60EFFF"/>
+	<stop  offset="1" style="stop-color:#1F89C7"/>
+</linearGradient>
+<path fill="url(#SVGID_1_)" d="M36.792,17.992L18.398,0L0,17.992l7.333,10.39l5.595-1.285l5.503,7.737l5.493-7.724l5.533,1.27
+	L36.792,17.992z M17.634,3.336L15.25,25.355l-4.549-6.205L17.634,3.336z M10.202,18.47l-2.833-3.866l9.743-11.833L10.202,18.47z
+	 M14.495,25.562L14.495,25.562l0.265,0.365l-1.52,0.348l-3.507-4.93l0.626-1.424L14.495,25.562z M18.396,3.044l2.395,23.345
+	l-2.4,3.288L16,26.389L18.396,3.044z M22.296,25.562l4.181-5.702l0.654,1.485l-3.517,4.944l-1.58-0.362l0.264-0.363L22.296,25.562z
+	 M21.542,25.355L19.189,3.318l6.946,15.77L21.542,25.355z M19.744,2.767l9.679,11.837l-2.787,3.802L19.744,2.767z M7.647,27.56
+	l-6.692-9.48L14.051,5.278l-7.605,9.302l3.417,4.661l-0.964,2.188l3.572,5.023L7.647,27.56z M18.432,33.573l-4.733-6.653
+	l1.528-0.352l3.162,4.351l3.173-4.351l1.592,0.367L18.432,33.573z M24.384,26.466l3.581-5.037l-0.99-2.248l3.372-4.6l-7.605-9.302
+	l13.095,12.801l-6.692,9.48L24.384,26.466z"/>
+</svg>
diff --git a/montool/images/logo.svg b/montool/images/logo.svg
new file mode 100644
index 0000000..a04f0f9
--- /dev/null
+++ b/montool/images/logo.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="73px" height="69px" viewBox="0 0 73 69" enable-background="new 0 0 73 69" xml:space="preserve">
+<g>
+	<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="36.2046" y1="2.1504" x2="36.2046" y2="68.6623">
+		<stop  offset="0" style="stop-color:#60EFFF"/>
+		<stop  offset="1" style="stop-color:#1F89C7"/>
+	</linearGradient>
+	<path fill="url(#SVGID_1_)" d="M36.287,0.137l0.008-0.063l-0.031,0.039l-0.012-0.012L36.262,0l-0.057,0.056L36.148,0l0.011,0.101
+		l-0.013,0.012l-0.03-0.039l0.007,0.063L0,35.447l14.307,20.267l11.05-2.538l10.848,15.255l10.85-15.255l11.05,2.538l8.861-12.554
+		l5.444-7.713L36.287,0.137z M35.108,4.282L30.174,50.52l-9.642-13.151L35.108,4.282z M20.059,36.725l-6.068-8.277L35.057,2.683
+		L20.059,36.725z M29.967,51.407l-4.313,0.99l-7.251-10.193l1.807-4.104L29.967,51.407z M36.092,2.051l0.113-0.258l0.114,0.257
+		l5.102,49.711l-0.015-0.01l-4.999,7.387l-5.409-7.396l-0.007,0.004L36.092,2.051z M42.237,50.521L37.303,4.281l14.576,33.087
+		L42.237,50.521z M52.201,38.101l1.808,4.104l-7.251,10.193l-4.312-0.99L52.201,38.101z M37.355,2.684L58.42,28.448l-6.067,8.277
+		L37.355,2.684z M14.605,54.935L0.907,35.53L32.779,4.374L13.114,28.425l6.623,9.03l-2.127,4.83l7.312,10.28L14.605,54.935z
+		 M36.205,67.235L26.086,53.009l4.326-0.992l0.072,0.099l-0.045,0.034l5.988,8.191l5.552-8.201l-0.048-0.032L42,52.017l4.324,0.992
+		L36.205,67.235z M66.4,42.762l-8.594,12.173l-10.317-2.369l7.312-10.28l-2.127-4.83l6.622-9.03L39.633,4.374L71.504,35.53
+		L66.4,42.762z"/>
+</g>
+</svg>
diff --git a/montool/server.js b/montool/server.js
new file mode 100644
index 0000000..5a39b1d
--- /dev/null
+++ b/montool/server.js
@@ -0,0 +1,712 @@
+// server.js
+//
+"use strict";
+
+var express = require('express');
+var monTool = express();
+var fs = require('fs');
+
+var bodyParser = require('body-parser');
+var path = require('path');
+
+var assert = require('assert');
+var ldap = require('ldapjs');
+
+//monTool.use(express.static(__dirname + 'montool'));
+//monTool.use(express.static('montool'));
+//monTool.use(express.static(__dirname + '/controllers'));
+//monTool.use(express.static(__dirname + '/css'));
+//monTool.use(express.static(__dirname + '/images'));
+//monTool.use(express.static(__dirname + '/views'));
+
+var myKey = fs.readFileSync('../MonToolData/alias/key.pem');
+var myCert = fs.readFileSync('../MonToolData/alias/server.crt');
+var options = {
+    key: myKey,
+    cert: myCert
+};
+
+var http = require('http');
+var https = require('https');
+
+//monTool.use(express.static('montool'));
+
+monTool.use(bodyParser.urlencoded({extended: true}));
+monTool.use(bodyParser.json());
+
+// https://stackoverflow.com/questions/5710358/how-to-retrieve-post-query-parameters
+monTool.use(express.json());       // to support JSON-encoded bodies
+monTool.use(express.urlencoded({extended: true})); // to support URL-encoded bodies
+
+monTool.use(express.static(path.join(__dirname, 'montool')));
+
+/*monTool.get('*', function (req, res) {
+ //res.sendFile('/views/login.html');
+ //  res.sendFile(__dirname + '/views/login.html');
+ res.sendFile('/views/index.html', {root: __dirname});
+ //  console.log(__dirname + '/views/login.html');
+ //res.sendfile('./views/index.html'); // load the single view file (angular will handle the page changes on the front-end)
+ });*/
+
+
+monTool.post('/api/v1/montool/authenticate', function (request, result) {
+
+    // data_id will be CONFIG or MONITOR
+    //console.log("Got a REQUEST! ");
+    //console.log("REQUEST = " + JSON.stringify(request.body));
+
+    var _request = JSON.stringify(request.body);
+    var info = JSON.parse(_request);
+    var host = info.host;
+    var port = info.port;
+    var user = info.user;
+    var password = info.password;
+
+    var _url = 'ldap://' + host + ':' + port;
+    var client = ldap.createClient({
+        url: _url,
+        connectTimeout: 5000, // Five seconds.
+        timeout: 5000
+    });
+
+    //console.log("Binding to " + _url);
+    client.bind(user, password, function (err) {
+        //assert.ifError(err);
+        //console.log("BIND error = " + err);
+        result.send(err);
+    });
+
+    // UNBIND!!!
+    client.unbind(function (err) {
+        //assert.ifError(err);
+        //console.log(err);
+        //console.log("### Unbinding In Authenticate REST route");
+    });
+
+});
+
+
+
+
+monTool.post('/api/v1/montool/search/:data_id', function (request, result) {
+
+    // data_id will be CONFIG, MONITOR or CERTIFICATES
+    //console.log("Got a REQUEST !!! ");
+    //console.log("REQUEST = " + JSON.stringify(request.body));
+
+    var _request = JSON.stringify(request.body);
+    var info = JSON.parse(_request);
+    //
+    var host = info.host;
+    var port = info.port;
+    var user = info.user;
+    var password = info.password;
+    //
+    var _data_id = request.params.data_id;
+    //console.log("_data_id = " + _data_id);
+
+    var _url = 'ldap://' + host + ':' + port;
+    var client = ldap.createClient({
+        url: _url,
+        connectTimeout: 5000, // Five seconds.
+        timeout: 5000
+    });
+
+    //console.log("Binding to " + _url);
+    client.bind(user, password, function (err) {
+        //assert.ifError(err);
+        //  console.log(err);
+    });
+
+// TODO ==> Move this section to switch-case statement!
+    if ('CONFIG' === _data_id) {
+        var config_opts = {
+            filter: '(objectClass=*)',
+            scope: 'base',
+            attributes: ['nsslapd-enquote-sup-oc', 'nsslapd-schemacheck',
+                'nsslapd-syntaxcheck', 'nsslapd-dn-validate-strict',
+                'nsslapd-rewrite-rfc1274', 'nsslapd-return-exact-case',
+                'nsslapd-ssl-check-hostname', 'nsslapd-validate-cert',
+                'nsslapd-allow-unauthenticated-binds',
+                'nsslapd-require-secure-binds',
+                'nsslapd-allow-anonymous-access', 'nsslapd-minssf',
+                'nsslapd-localuser', 'nsslapd-localhost', 'nsslapd-secureport',
+                'nsslapd-ndn-cache-enabled', 'nsslapd-port', 'nsslapd-accesslog']
+        };
+
+        client.search('cn=config', config_opts, function (err, res) {
+            //assert.ifError(err);
+            res.on('searchEntry', function (ldapEntry) {
+                //console.log('entry: ' + JSON.stringify(ldapEntry.object));
+                // http://expressjs.com/en/api.html#res.json
+                result.json(ldapEntry.object);
+            });
+            res.on('error', function (err) {
+                //console.error('error: ' + err.message);
+            });
+            res.on('end', function (ldapResult) {
+                //console.log('status: ' + ldapResult.status);
+            });
+        });
+    } else if ('MONITOR' === _data_id) {
+        var monitor_opts = {
+            filter: '(objectClass=*)',
+            scope: 'base',
+            attributes: ['version', 'threads', 'starttime', 'currenttime',
+                'currentconnections', 'totalconnections', 'opsinitiated',
+                'opscompleted', 'description;latest', 'connection']
+                    //attributes: ['description;latest']
+        };
+
+        client.search('cn=monitor', monitor_opts, function (err, res) {
+            //assert.ifError(err);
+            res.on('searchEntry', function (ldapEntry) {
+                //console.log('entry: ' + JSON.stringify(ldapEntry.object));
+                result.json(ldapEntry.object);
+            });
+            res.on('error', function (err) {
+                //console.error('error: ' + err.message);
+            });
+            res.on('end', function (ldapResult) {
+                //console.log('status: ' + ldapResult.status);
+            });
+        });
+
+        //console.log("### HERE 1");
+        client.unbind(function (err) {
+            //assert.ifError(err);
+            //console.log(err);
+            //console.log("### HERE 2");
+
+        });
+    } else if ('CHECK_IPA' === _data_id) {
+
+        var ipa_opts = {
+            filter: '(nsslapd-backend=ipaca)',
+            scope: 'base',
+            attributes: ['nsslapd-backend']
+        };
+
+        client.search('cn=config', ipa_opts, function (err, res) {
+            //assert.ifError(err);
+            res.on('searchEntry', function (ldapEntry) {
+                //console.log('entry: ' + JSON.stringify(ldapEntry.object));
+                if (ldapEntry) {
+                    result.json(ldapEntry.object);
+                }
+            });
+            res.on('error', function (err) {
+                if (err) {
+                    result.send(err);
+                }
+            });
+            res.on('end', function (ldapResult) {
+                //console.log('status: ' + ldapResult.status);
+            });
+        });
+
+        //console.log("### HERE 1");
+        client.unbind(function (err) {
+            //assert.ifError(err);
+            //console.log(err);
+            //console.log("### HERE 2");
+
+        });
+    }
+
+//TODO ==>  UNBIND NOT WORKING !!!
+// Use the destroy (hidden) function?
+    client.unbind(function (err) {
+        //assert.ifError(err);      
+    });
+});
+
+
+
+monTool.post('/api/v1/montool/search/certificates/:cert_id', function (request, result) {
+
+    var _request = JSON.stringify(request.body);
+    var info = JSON.parse(_request);
+    //
+    var host = info.host;
+    var port = info.port;
+    var user = info.user;
+    var password = info.password;
+    //
+    var cert_id = request.params.cert_id;
+    var baseDN = 'cn=' + cert_id + ',ou=certificateRepository,ou=ca,o=ipaca';
+    var certBaseDN = 'ou=certificateRepository,ou=ca,o=ipaca';
+    var _url = 'ldap://' + host + ':' + port;
+
+    var client = ldap.createClient({
+        url: _url,
+        connectTimeout: 5000, // Five seconds.
+        timeout: 5000
+    });
+
+    //console.log("Binding to " + _url);
+    client.bind(user, password, function (err) {
+        //assert.ifError(err);
+        //  console.log(err);
+    });
+    //
+    // TODO ==> Fix this HACK by sending the whole result in 1 go.
+    // For the moment run a search for each certificate :-(
+    // Failing to send the results with scope = sub...
+
+    //console.log(" CERT_ID = " + cert_id);
+    var certs_attrs = 'objectClass serialno notBefore notAfter '
+            + 'duration extension subjectName '
+            + 'issuerName userCertificate version algorithmId '
+            + 'signingAlgorithmId certStatus';
+
+    var certs_opts = {
+        filter: '(certStatus=*)',
+        scope: 'base',
+        attributes: ['objectClass', 'serialno', 'notBefore', 'notAfter',
+            'duration', 'extension', 'subjectName',
+            //'issuerName', 'version', 'algorithmId',
+            'issuerName', 'userCertificate', 'version', 'algorithmId',
+            //'signingAlgorithmId', 'publicKeyData', 'certStatus']
+            'signingAlgorithmId', 'certStatus']
+
+    };
+
+
+    client.search(baseDN, certs_opts, function (err, res) {
+        res.on('searchEntry', function (ldapEntry) {
+            result.json(ldapEntry.object);
+        });
+
+        res.on('error', function (err) {
+            //console.error('error: ' + err.message);
+        });
+        res.on('end', function (ldapResult) {
+            //console.log('status: ' + ldapResult.status);
+        });
+    });
+
+    client.unbind(function (err) {
+    });
+
+    // https://dzone.com/articles/understanding-execfile-spawn-exec-and-fork-in-node
+    // 
+    // ldapsearch -h -p -D -w -b "ou=certificateRepository,ou=ca,o=ipaca" -s one "(certStatus=*)"  > /tmp/res.ldif 2>&1
+    // $ du -sh /tmp/res.ldif 
+    // 28K	/tmp/res.ldif
+    // $
+    // ==>  The default buffer of 200 KB should be more than enough.
+
+    const {execFile} = require('child_process');
+    const child = execFile('/usr/bin/ldapsearch',
+            ['-h', host, '-p', port, '-D', user, '-w', password, '-b', certBaseDN,
+                '-s', 'one', '(certStatus=*)', 'objectClass', 'serialno',
+                'notBefore', 'notAfter', 'duration', 'extension', 'subjectName',
+                'issuerName', 'userCertificate', 'version',
+                'algorithmId', 'signingAlgorithmId', 'certStatus'
+            ],
+            //{maxBuffer: 100 * 1024 * 1024},
+                    (error, stdout, stderr) => {
+                if (error) {
+                    console.log(stderr);
+                    //throw error;
+                    return;
+                }
+                console.log(stdout);
+            });
+
+});
+
+
+monTool.get('/api/v1/montool/check-root-access/:host', function (request, result) {
+
+    var _host = request.params.host;
+
+    const {execFile} = require('child_process');
+    const child = execFile('/usr/bin/ssh',
+            ['root@' + _host, '-o', 'BatchMode=yes', '-o', 'ConnectTimeout=10', 'id'],
+            (error, stdout, stderr) => {
+        if (error) {
+            var errMsg = 'STDERR: ' + stderr;
+            //console.log(errMsg);
+            //throw error;
+            result.send(errMsg);
+        } else {
+            var message = 'STDOUT: ' + stdout;
+            //console.log(message);
+            result.send(message);
+        }
+    });
+
+});
+
+
+monTool.post('/api/v1/montool/common/verify-access/', function (request, result) {
+
+    var _request = JSON.stringify(request.body);
+    var data = JSON.parse(_request);
+    var host = data.host;
+    var user = data.user;
+
+    var output = '';
+
+    const {execFile} = require('child_process');
+    const child = execFile('/usr/bin/ssh',
+            [user + '@' + host, '-o', 'BatchMode=yes', '-o', 'ConnectTimeout=10', 'id'],
+            (error, stdout, stderr) => {
+        if (error) {
+            var errMsg = 'STDERR: ' + stderr;
+            //console.log(errMsg);
+            //throw error;
+            result.send(errMsg);
+        } else {
+            var message = 'STDOUT: ' + stdout;
+            //console.log(message);
+            result.send(message);
+        }
+    });
+
+});
+
+
+monTool.post('/api/v1/montool/logconv/run-logconv', function (request, result) {
+
+    var _request = JSON.stringify(request.body);
+    var data = JSON.parse(_request);
+    var host = data.host;
+    var user = data.user;
+    var logsDirectory = data.logsDirectory;
+    var logsList = data.logsList.split(',');
+    var options = data.options.split(',');
+    var command = data.command;
+    //
+    var stdout_data = 'STDOUT\n';
+    var stderr_data = 'STDERR\n';
+    const {spawn} = require('child_process');
+    var logsToParse = '';
+    var selectedOptions = '';
+    //
+    console.log('data ==> ' + data.toString());
+    console.log('logsDirectory ==> ' + logsDirectory);
+    console.log('logsList ==> ' + logsList);
+    console.log('options ==> ' + options);
+    var actualCommand;
+    var totalLines, start, end, duration, restarts, peakCnx, totalCnx;
+    var searches, mods, adds, dels, modRdn, comparisons, binds;
+    var fdTaken, fdReturned, fdHighest;
+    //
+    var commandToRun = '';
+    //
+    if (command === 'GET_LIST_OF_LOGS') {
+        commandToRun = 'cd ' + logsDirectory + ' ; stat -c "%n %s %U %a" ./access* | grep -v "access.rotationinfo"';
+    } else if (command === 'RUN_LOG_CONV') {
+        logsList.forEach(function (log) {
+            logsToParse += ' ./' + log;
+        });
+        options.forEach(function (opt) {
+            selectedOptions += opt;
+        });
+        if (selectedOptions !== '') {
+            selectedOptions = '-' + selectedOptions;
+        }
+        console.log('logsToParse = ' + logsToParse);
+        console.log('selectedOptions = ' + selectedOptions);
+        commandToRun = 'cd ' + logsDirectory + ' ; /usr/bin/logconv.pl ' + selectedOptions + logsToParse;
+    }
+
+    const logConverter = spawn('/usr/bin/ssh',
+            [user + '@' + host, '-o', 'BatchMode=yes', '-o', 'ConnectTimeout=10',
+                commandToRun]);
+    logConverter.stdout.on('data', (data) => {
+        console.log(`stdout: ${data}`);
+        stdout_data = stdout_data + `${data}`;
+    });
+    logConverter.stderr.on('data', (data) => {
+        console.log(`stderr: ${data}`);
+        stderr_data = stderr_data + `${data}`;
+    });
+    logConverter.on('close', (code) => {
+        if ((command === 'GET_LIST_OF_LOGS')) {
+            if (code === 0) {
+                result.send(stdout_data);
+            } else {
+                result.send(stderr_data);
+            }
+        } else if (command === 'RUN_LOG_CONV') {
+            //result.send(stdout_data);
+            processLogconvOutput();
+            sendLogconvResult();
+        }
+        console.log('logconv.pl process exited with code ' + code);
+    });
+
+    function processLogconvOutput() {
+
+        //logConverter.stdout.on('data', (data) => {
+        //console.log(`stdout: ${data}`);
+        //var lines = `${data}`.split('\n');
+        var lines = stdout_data.split('\n');
+
+        for (var i = 0; i < lines.length; i++) {
+            //console.log(typeof lines[i]);
+            //console.log('Length of lines[i] ==> ' + lines[i].length);
+
+            var currentLine = lines[i];
+            if (currentLine.startsWith('Command: logconv.pl')) {
+                actualCommand = currentLine;
+                console.log('actualCommand = ' + actualCommand);
+            } else if (currentLine.startsWith('Total Log Lines Analysed:')) {
+                totalLines = (currentLine.split(':')[1]).trim();
+                console.log('totalLines = ' + totalLines);
+            } else if (currentLine.startsWith('Start of Logs:')) {
+                start = (currentLine.split(':')[1]).trim();
+            } else if (currentLine.startsWith('End of Logs:')) {
+                end = (currentLine.split(':')[1]).trim();
+            } else if (currentLine.startsWith('Processed Log Time:')) {
+                duration = (currentLine.split(':')[1]).trim();
+            } else if (currentLine.startsWith('Restarts:')) {
+                restarts = (currentLine.split(':')[1]).trim();
+            } else if (currentLine.startsWith('Peak Concurrent Connections:')) {
+                peakCnx = (currentLine.split(':')[1]).trim();
+            } else if (currentLine.startsWith('Total Connections:')) {
+                totalCnx = (currentLine.split(':')[1]).trim();
+                // LDAP Operations.
+            } else if (currentLine.startsWith('Searches:')) {
+                searches = (currentLine.split(':')[1]).trim();
+            } else if (currentLine.startsWith('Modifications:')) {
+                mods = (currentLine.split(':')[1]).trim();
+            } else if (currentLine.startsWith('Adds:')) {
+                adds = (currentLine.split(':')[1]).trim();
+            } else if (currentLine.startsWith('Deletes:')) {
+                dels = (currentLine.split(':')[1]).trim();
+            } else if (currentLine.startsWith('Mod RDNs:')) {
+                modRdn = (currentLine.split(':')[1]).trim();
+            } else if (currentLine.startsWith('Compares:')) {
+                comparisons = (currentLine.split(':')[1]).trim();
+            } else if (currentLine.startsWith('Binds:')) {
+                binds = (currentLine.split(':')[1]).trim();
+            }
+            // File descriptors
+            else if (currentLine.startsWith('FDs Taken:')) {
+                fdTaken = (currentLine.split(':')[1]).trim();
+            } else if (currentLine.startsWith('FDs Returned:')) {
+                fdReturned = (currentLine.split(':')[1]).trim();
+            } else if (currentLine.startsWith('Highest FD Taken:')) {
+                fdHighest = (currentLine.split(':')[1]).trim();
+            }
+        }
+    }
+
+    function sendLogconvResult() {
+        // Build the JSON object:
+        var logData = new Object();
+        logData.actualCommand = actualCommand;
+        logData.totalLines = totalLines;
+        logData.start = start;
+        logData.end = end;
+        logData.duration = duration;
+        logData.restarts = restarts;
+        logData.peakCnx = peakCnx;
+        logData.totalCnx = totalCnx;
+        // LDAP operations.
+        logData.searches = searches;
+        logData.mods = mods;
+        logData.adds = adds;
+        logData.dels = dels;
+        logData.modRdn = modRdn;
+        logData.comparisons = comparisons;
+        logData.binds = binds;
+        //
+        logData.fdTaken = fdTaken;
+        logData.fdReturned = fdReturned;
+        logData.fdHighest = fdHighest;
+        //var information = JSON.stringify(logData);
+        result.json(logData);
+    }
+
+});
+
+monTool.get('/api/v1/montool/command/:hostAndCommand', function (request, result) {
+
+    var _hostAndCommand = request.params.hostAndCommand;
+    var index = _hostAndCommand.indexOf(' ');
+    var length = _hostAndCommand.length;
+    var host = _hostAndCommand.substring(0, index);
+    var command = _hostAndCommand.substring(index + 1, length);
+    console.log("_hostAndCommand = #" + _hostAndCommand + '#');
+    console.log("host = #" + host + '#');
+    console.log("command = #" + command + '#');
+    var detailsData = new Object();
+    detailsData.version = '';
+    detailsData.uptime = '';
+    detailsData.hostStatus = '';
+    detailsData.packages = '';
+    var statusData = new Object();
+    statusData.serverTime = '';
+    statusData.expiredCerts = '';
+    statusData.trackedCerts = '';
+    statusData.ipaStatus = '';
+    const SEPARATOR = '"COMMAND_SEPARATOR"';
+    const cmdSeparator = ' ; echo ' + SEPARATOR + ' ; ';
+    const detailsCommands = '/usr/bin/ipa --version' + cmdSeparator +
+            '/usr/bin/uptime ; /usr/bin/uptime -p' + cmdSeparator +
+            '/usr/bin/rpm -qa | grep ipa-' + cmdSeparator +
+            '/usr/bin/hostnamectl status';
+    const statusCommands = '/usr/bin/date -u "+%Y-%m-%d %H:%M:%S %Z"' + cmdSeparator +
+            '/usr/bin/getcert list | grep -E "certificate:|expires:"' + cmdSeparator +
+            '/usr/bin/getcert list | grep "Number of certificates and requests being tracked:"' + cmdSeparator +
+            '/usr/sbin/ipactl status';
+    //console.log('detailsCommands = ' + detailsCommands);
+    console.log('statusCommands = ' + statusCommands);
+    const {execFile} = require('child_process');
+    switch (command) {
+        //if (command === 'DETAILS') {
+
+        case 'DETAILS' :
+            // Uptime:
+            var child_1 = execFile('/usr/bin/ssh',
+                    ['root@' + host, '-o', 'BatchMode=yes', '-o', 'ConnectTimeout=10',
+                        detailsCommands],
+                    (error, stdout, stderr) => {
+                if (!error) {
+                    console.log('STDOUT: ' + stdout);
+                    var detailsArray = stdout.split('COMMAND_SEPARATOR');
+                    detailsData.version = (detailsArray[0]).replace(/^\s*[\r\n]/g, ''); //replace(/^\s*[\r\n]/gm, '')
+                    detailsData.uptime = (detailsArray[1]).replace(/^\s*[\r\n]/g, '');
+                    detailsData.packages = (detailsArray[2]).replace(/^\s*[\r\n]/g, '');
+                    detailsData.hostStatus = (detailsArray[3]).replace(/^\s*[\r\n]/g, '');
+                }
+                //getHostStatus();
+                console.log('detailsData.packages ==> ' + detailsData.version);
+                console.log('detailsData.uptime ==> ' + detailsData.uptime);
+                console.log('detailsData.packages ==> ' + detailsData.packages);
+                console.log('detailsData.hostStatus ==> ' + detailsData.hostStatus);
+                result.json(detailsData);
+            });
+            break;
+        case 'STATUS' :
+            var child_2 = execFile('/usr/bin/ssh',
+                    ['root@' + host, '-o', 'BatchMode=yes', '-o', 'ConnectTimeout=10',
+                        statusCommands],
+                    (error, stdout, stderr) => {
+                console.log('STDOUT_STATUS: ' + stdout);
+                console.log('STDERR_STATUS: ' + stderr);
+                if (!error) {
+                    console.log('STDOUT: ' + stdout);
+                    var statusArray = stdout.split('COMMAND_SEPARATOR');
+                    statusData.serverTime = (statusArray[0]).replace(/^\s*[\r\n]/g, '');
+                    statusData.expiredCerts = (statusArray[1]).replace(/^\s*[\r\n]/g, '');
+                    statusData.trackedCerts = (statusArray[2]).replace(/^\s*[\r\n]/g, '');
+                    statusData.ipaStatus = (statusArray[3]).replace(/^\s*[\r\n]/g, '');
+                }
+                //getHostStatus();
+                console.log('statusData.serverTime ==> ' + statusData.serverTime);
+                console.log('statusData.expiredCerts ==> ' + statusData.expiredCerts);
+                console.log('statusData.trackedCerts ==> ' + statusData.trackedCerts);
+                console.log('statusData.ipaStatus ==> ' + statusData.ipaStatus);
+                result.json(statusData);
+            });
+            break;
+        default:
+            console.log('Invalid call with command "' + command + '"');
+    }
+
+
+});
+
+
+monTool.post('/api/v1/montool/checkcerts/run-checkcerts', function (request, result) {
+
+    var _request = JSON.stringify(request.body);
+    var data = JSON.parse(_request);
+    var host = data.host;
+    var debug = data.debug;
+    var verbose = data.verbose;
+    var errorMsg = '';
+    var output = '';
+    var debugOption = '';
+    var verboseOption = '';
+    //
+    console.log('debug = '+ debug);
+    console.log('TYPEOFDEBUG = '+ typeof debug);
+    if (debug === 'true') {
+        debugOption = '--debug';
+    }
+    if (verbose === 'true') {
+        verboseOption = '--verbose';
+    }
+
+    var command = '/usr/bin/python /var/monitoringTool/agent/scripts/ipa-checkcerts.py'
+            + ' ' + debugOption + ' ' + verboseOption;
+    console.log("COMMAND = " + command);
+    const {spawn} = require('child_process');
+
+    const checkCerts = spawn('/usr/bin/ssh',
+            ['root@' + host, '-o', 'BatchMode=yes', '-o', 'ConnectTimeout=10',
+                command]);
+    checkCerts.stdout.on('data', (data) => {
+        console.log(`stdout: ${data}`);
+        output = output + `${data}`;
+    });
+    checkCerts.stderr.on('data', (data) => {
+        console.log(`stderr: ${data}`);
+        errorMsg = errorMsg + `${data}`;
+    });
+    checkCerts.on('close', (code) => {
+        result.send(errorMsg + output);
+        console.log(`ipa-checkcerts.py process exited with code ${code}`);
+    });
+});
+
+
+monTool.post('/api/v1/montool/command/ds-replcheck', function (request, result) {
+
+    var _request = JSON.stringify(request.body);
+    var data = JSON.parse(_request);
+    var supplierUrl = data.supplierUrl;
+    var replicaUrl = data.replicaUrl;
+    var binddn = data.binddn;
+    var password = data.password;
+    var suffix = data.suffix;
+    var errorMsg = '';
+    var output = '';
+    var command = '/usr/bin/ds-replcheck -D "' + binddn + '" -w ' + password
+            + ' -m ' + supplierUrl + ' -r ' + replicaUrl + ' -b "' + suffix + '"';
+    console.log("COMMAND = " + command);
+    const {spawn} = require('child_process');
+    // TODO!!!
+    // Make sure 389-ds packages are installed and run this command WITHOUT ssh !!
+    const dsReplCheck = spawn('/usr/bin/ssh',
+    // Use dirsrv@localhost
+            ['root@localhost', '-o', 'BatchMode=yes', '-o', 'ConnectTimeout=10',
+                command]);
+    dsReplCheck.stdout.on('data', (data) => {
+        console.log(`stdout: ${data}`);
+        output = output + `${data}`;
+    });
+    dsReplCheck.stderr.on('data', (data) => {
+        console.log(`stderr: ${data}`);
+        errorMsg = errorMsg + `${data}`;
+    });
+    dsReplCheck.on('close', (code) => {
+        result.send(errorMsg + output);
+        console.log(`ds-replcheck process exited with code ${code}`);
+    });
+});
+
+monTool.use(function (request, result) {
+    result.status(404).send({url: request.originalUrl + ' not found!!'});
+});
+
+http.createServer(monTool).listen(2018);
+https.createServer(options, monTool).listen(1974);
+//monTool.listen(1974);
+console.log("Monitoring Tool Application started.");
+console.log("__dirname = " + __dirname);
+const {execFile} = require('child_process');
+const child = execFile('node', ['--version'], (error, stdout, stderr) => {
+    if (error) {
+        throw error;
+    }
+    console.log("Node.js version is : " + stdout);
+});
\ No newline at end of file
diff --git a/montool/views/config/cache.html b/montool/views/config/cache.html
new file mode 100644
index 0000000..0eed523
--- /dev/null
+++ b/montool/views/config/cache.html
@@ -0,0 +1,12 @@
+<br>
+<br>
+<br>
+<br>
+<div class="card-pf card-pf-accented card-pf-aggregate-status" style="height: 89px;">
+    <div class="card-pf-body" style="height: 50px;">
+        <span class="pficon pficon-pending fa-3x"></span>
+        <p class="card-pf-aggregate-status-notifications">
+            State: TODO - Show cache usage and recommendations.            
+        </p>        
+    </div>
+</div>
diff --git a/montool/views/config/config.html b/montool/views/config/config.html
new file mode 100644
index 0000000..41625df
--- /dev/null
+++ b/montool/views/config/config.html
@@ -0,0 +1,22 @@
+
+
+<div>
+    <!--div ng-controller="ConfigurationCtrl" class="row example-container"-->
+
+        <script type="text/ng-template" id="recommendation_template.html">
+            <span ng-if="value === 'error'" class="pficon pficon-error-circle-o"></span>
+            <span ng-if="value === 'warning'" class="pficon pficon-warning-triangle-o"></span>
+            <span ng-if="value === 'ok'" class="pficon pficon-ok"></span>
+        {{value}}
+        </script>
+        <br>
+        <br>
+        <div class="col-md-12">
+            <pf-table-view config="tuning_config"
+                           columns="tuning_columns"
+                           items="tuning_items">
+            </pf-table-view>
+        </div>
+
+    <!--/div-->
+</div>
\ No newline at end of file
diff --git a/montool/views/config/tuning.html b/montool/views/config/tuning.html
new file mode 100644
index 0000000..be57183
--- /dev/null
+++ b/montool/views/config/tuning.html
@@ -0,0 +1,13 @@
+
+<br>
+<br>
+<br>
+<br>
+<div class="card-pf card-pf-accented card-pf-aggregate-status" style="height: 89px;">
+    <div class="card-pf-body" style="height: 50px;">
+        <span class="pficon pficon-pending fa-3x"></span>
+        <p class="card-pf-aggregate-status-notifications">
+            State: TODO - Show tuning data and recommendations.            
+        </p>        
+    </div>
+</div>
diff --git a/montool/views/configuration.html b/montool/views/configuration.html
new file mode 100644
index 0000000..00ca0c0
--- /dev/null
+++ b/montool/views/configuration.html
@@ -0,0 +1,19 @@
+
+
+
+<div style="background-color: #fff; margin: -20px;">
+    <ul class="nav nav-tabs nav-justified">
+        <!--li ng-class="{'active': viewType === 'tuning'}"><a href="#/config/tuning.html" ng-click="setView('tuning')">System Tuning</a></li>
+        <li ng-class="{'active': viewType === 'cache'}"><a href="#/config/cache.html" ng-click="setView('cache')">Cache Usage</a></li>
+        <li ng-class="{'active': viewType === 'config'}"><a href="#" ng-click="setView('config')">Configuration</a></li-->
+
+        <!-- EMPTY href issue : https://github.com/angular/angular/issues/7294 -->
+
+        <li ng-class="{'active': viewType === 'tuning'}"><a href="" ng-click="setView('tuning')">System Tuning</a></li>
+        <li ng-class="{'active': viewType === 'cache'}"><a href="" ng-click="setView('cache')">Cache Usage</a></li>
+        <li ng-class="{'active': viewType === 'config'}"><a href="" ng-click="setView('config')">Configuration</a></li>
+    </ul>
+    <div ng-if="viewType === 'tuning'" ng-include="'views/config/tuning.html'"></div>
+    <div ng-if="viewType === 'cache'" ng-include="'views/config/cache.html'"></div>
+    <div ng-if="viewType === 'config'" ng-include="'views/config/config.html'"></div>
+</div>
\ No newline at end of file
diff --git a/montool/views/dashboard.html b/montool/views/dashboard.html
new file mode 100644
index 0000000..9d29e5d
--- /dev/null
+++ b/montool/views/dashboard.html
@@ -0,0 +1,147 @@
+
+
+<div class="container-fluid">
+
+    <div>
+        <pf-inline-notification pf-notification-type="notification.type"
+                                pf-notification-header="notification.header"
+                                pf-notification-message="notification.message"
+                                pf-notification-persistent="notification.isPersistent"
+                                pf-notification-remove="removeNotification()">
+        </pf-inline-notification>
+    </div>
+
+    <div class="controls">        
+        <button type="button"  ng-click="handleRefresh()" style="margin-right: 50px">
+            <span class="fa fa-refresh"></span>
+        </button>
+
+        <label>Automatic Refresh</label>
+        <!--input class="bootstrap-switch" id="bootstrap-switch-state" type="checkbox" checked data-off-color="danger"-->
+        <!--input id="automaticSwitch" class="bootstrap-switch" ng-model="automaticRefresh"  type="checkbox"  data-off-color="danger" ng-change="handleAutomaticRefresh()"-->
+        <input id="automaticSwitch" class="bootstrap-switch" type="checkbox"  data-off-color="danger">
+
+        <script>
+                    //jQuery(".bootstrap-switch").bootstrapSwitch();                  
+        </script>
+        <script>
+                    $("[id='automaticSwitch']").bootstrapSwitch();
+                    //alert("Changed");
+                    // https://stackoverflow.com/questions/18830219/bootstrap-switch-checked-event
+                    // https://forums.asp.net/t/2077001.aspx?AngularJS+How+to+call+controller+function+from+outside+of+controller+component
+                    $('#automaticSwitch').on('switchChange.bootstrapSwitch', function (event, state) {
+                        //alert("Real change!");
+                        console.log("automaticSwitch State = " + state);
+                        //automaticRefresh = state;
+                        //angular.element($('#automaticSwitch')).scope().automaticRefresh = state;
+                        angular.element($('#automaticSwitch')).scope().handleAutomaticRefresh(state);
+                        //angular.element(document.getElementById('automaticSwitch')).scope().handleAutomaticRefresh();
+                    });
+
+                    /*$('#automaticSwitch').change(function () {
+                     var input = $('input');
+                     input.val('xxx');
+                     input.trigger('input'); // Use for Chrome/Firefox/Edge
+                     input.trigger('change'); // Use for Chrome/Firefox/Edge + IE11
+                     });*/
+
+
+        </script>
+    </div>
+
+    <!--div>
+        <form class="form-horizontal">
+            <div class="form-group">
+               
+                <label class="col-sm-2 control-label" for="automatic">Automatic Refresh</label>
+                <div class="col-sm-10">
+                    <input id="automatic" ng-model="automaticRefresh" type="checkbox" ng-change="handleAutomaticRefresh()">
+                </div>
+            </div>
+        </form>
+    </div-->
+
+
+
+    <div class="row">
+        <div class="col-xs-12 col-sm-6 col-md-5 col-lg-4">
+            <!--label>General Information</label-->
+            <pf-info-status-card status="information" html-content="true" show-top-border="true"></pf-info-status-card>
+        </div>
+        <div class="col-xs-12 col-sm-6 col-md-5 col-lg-4">
+            <!--label>Current Resource Usage</label-->
+            <pf-info-status-card status="instance_info" show-top-border="true"></pf-info-status-card>
+        </div>
+        <div class="col-xs-12 col-sm-6 col-md-5 col-lg-4">
+            <!--label>Resource Summary</label-->
+            <pf-info-status-card status="res_summary" html-content="true" show-top-border="true"></pf-info-status-card>
+        </div>
+    </div>
+
+    <!--div class="row">
+        <div class="col-xs-12 col-sm-6 col-md-5 col-lg-4">
+            <label>LDAP Operations</label>
+            <pf-aggregate-status-card status="information" show-top-border="true"></pf-aggregate-status-card>
+        </div>
+        <div class="col-xs-12 col-sm-6 col-md-5 col-lg-4">
+            <label>CPU Usage</label>
+            <pf-aggregate-status-card status="information" show-top-border="true"></pf-aggregate-status-card>
+        </div>
+        <div class="col-xs-12 col-sm-6 col-md-5 col-lg-4">
+            <label>Memory Usage</label>
+            <pf-aggregate-status-card status="information" show-top-border="true"></pf-aggregate-status-card>
+        </div>
+    </div-->
+
+    <div class="row">
+        <div class="col-md-6">
+            <pf-utilization-trend-chart config="CPUconfig"
+                                        chart-data="CPUdata" center-label="centerLabel"
+                                        donut-config="CPUdonutConfig" sparkline-config="CPUSparklineConfig"
+                                        sparkline-chart-height="custChartHeight"
+                                        show-sparkline-x-axis="custShowXAxis"
+                                        show-sparkline-y-axis="custShowYAxis">
+            </pf-utilization-trend-chart>
+        </div>
+
+        <div class="col-md-6">
+            <pf-utilization-trend-chart config="memoryConfig"
+                                        chart-data="memoryData" center-label="centerLabel"
+                                        donut-config="memoryDonutConfig" sparkline-config="memorySparklineConfig"
+                                        sparkline-chart-height="custChartHeight"
+                                        show-sparkline-x-axis="custShowXAxis"
+                                        show-sparkline-y-axis="custShowYAxis">
+            </pf-utilization-trend-chart>
+        </div>
+
+    </div>
+
+    <div class="row">
+        <!--div class="col-md-12"-->
+        <pf-card head-title="System Resources"  show-top-border="true">
+            <pf-utilization-bar-chart chart-data=sysRes_CPUdata chart-title=sysRes_CPUtitle layout=layoutInline units=sysRes_CPUunits
+                                      threshold-error="85" threshold-warning="60"></pf-utilization-bar-chart>
+            <pf-utilization-bar-chart chart-data=sysRes_MEMdata chart-title=sysRes_MEMtitle layout=layoutInline units=sysRes_MEMunits 
+                                      threshold-error="85" threshold-warning="60"></pf-utilization-bar-chart>
+            <pf-utilization-bar-chart chart-data=sysRes_DISKdata chart-title=sysRes_DISKtitle layout=layoutInline units=sysRes_DISKunits
+                                      threshold-error="85" threshold-warning="60"></pf-utilization-bar-chart>
+            <pf-utilization-bar-chart chart-data=sysRes_IOdata chart-title=sysRes_IOtitle layout=layoutInline units=sysRes_IOunits
+                                      threshold-error="85" threshold-warning="60"></pf-utilization-bar-chart>
+        </pf-card>
+        <!--/div-->
+    </div>
+
+
+    <div id="connections" class="row">
+        <label>Current Connections</label>
+        <ul class="list-group">
+            <li class="list-group-item" ng-repeat="cnx in connections"ng-model="connections">{{cnx}}</li>
+            <!--li class="list-group-item">Dapibus ac facilisis in</li>
+            <li class="list-group-item">Morbi leo risus</li>
+            <li class="list-group-item">Porta ac consectetur ac</li>
+            <li class="list-group-item">Vestibulum at eros</li-->
+        </ul>
+    </div>
+
+
+</div>
diff --git a/montool/views/login.html b/montool/views/login.html
new file mode 100644
index 0000000..e828d12
--- /dev/null
+++ b/montool/views/login.html
@@ -0,0 +1,135 @@
+
+
+
+<!--div class="card-pf card-pf-accented card-pf-aggregate-status" style="height: 89px;" ng-controller="ShowLoginPageController">
+    <div class="card-pf-body" style="height: 50px;">
+        <span class="pficon pficon-pending fa-3x"></span>
+        <p class="card-pf-aggregate-status-notifications">
+            State: TODO - Use PatternFly <i>pfTopology</i>.
+            <br>
+            <br>
+            <a href="https://www.patternfly.org/angular-patternfly/#/api/patternfly.charts.component:pfTopology" target="_blank">Angular PatternFly - pfTopology
+                <i class="fa fa-external-link" aria-hidden="true"></i>
+            </a>
+            <br>
+            <br>
+
+            <button ng-click="showLoginPage()" type="submit" class="btn btn-primary btn-block btn-lg">Check LDAP Server info using LoginFactory</button>
+            <br>
+            <br>
+
+        <p>{{server| json }}</p>
+
+    </div>
+</div-->
+
+<div class="login-pf login-pf-page" style="background-color:#000;" ng-controller="LoginPageCtrl">
+    <!--div  class="login-pf login-pf-page" style="background-color:#000;" ng-controller="LoginPageCtrl"-->
+    <div class="container-fluid">
+        <div class="row">
+            <div class="col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3 col-lg-6 col-lg-offset-3">
+                <header class="login-pf-page-header">
+                    <img class="login-pf-brand" src="../images/Logo_Horizontal_Reversed.svg" alt="logo" />
+                    <p>Welcome to IPA and RHDS Monitoring Tool!</p>
+                    <p id="loginLink" class="login-pf-signup"><a href="" ng-click="showLoginPage()" >Click here to connect to the LDAP Server</a></p>
+
+                    <div id="loginNotification" class="col-md-12 hidden">
+                        <pf-toast-notification notification-type="danger" header="LDAP Error Message" message="{{bindErrorMessage}}"
+                                               close-callback="closeCallback" show-close="true">
+                        </pf-toast-notification>
+                    </div>
+                </header>
+                <!--div id="389-ds_logo">
+                    <img src="../images/389-logo-wallpaper-1080p.svg" alt="389-ds logo" />
+                </div-->
+
+                <div id="loginPage" class="row hidden">
+                    <!--div class="col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2 col-lg-8 col-lg-offset-2"-->
+                    <div class="col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2 col-lg-10 col-lg-offset-1">
+                        <div class="card-pf">
+                            <header class="login-pf-header">
+                                <!--select class="selectpicker"-->
+                                <!--select>
+                                    <option>English</option>
+                                    <option>French</option>
+                                    <option>Italian</option>
+                                </select-->
+                                <h1>Log In to Your LDAP Instance</h1>
+                            </header>
+                            <!--form class="form-horizontal" role="form" ng-controller="MonitoringToolCtrl"-->
+                            <form class="form-horizontal" role="form">
+                                <div class="form-group">
+                                    <label for="inputUsername" class="col-sm-2 col-md-2 control-label">Username</label>
+                                    <div class="col-sm-10 col-md-10">
+                                        <!--input type="text" class="form-control" id="inputUsername" placeholder="" tabindex="1" ng-model="server.user"-->
+                                        <input type="text" class="form-control" id="inputUsername" tabindex="1" ng-model="server.user">
+                                    </div>
+                                </div>
+                                <div class="form-group">
+                                    <label for="inputPassword" class="col-sm-2 col-md-2 control-label">Password</label>
+                                    <div class="col-sm-10 col-md-10">
+                                        <input type="password" class="form-control" id="inputPassword" tabindex="2" ng-model="server.password">
+                                    </div>
+                                </div>
+                                <div class="form-group">
+                                    <label for="hostName" class="col-sm-2 col-md-2 control-label" >Host</label>
+                                    <div class="col-sm-10 col-md-10">
+                                        <input type="text" class="form-control" id="hostname" tabindex="3" ng-model="server.host">
+                                    </div>
+                                </div>
+                                <div class="form-group">
+                                    <label for="portNumber" class="col-sm-2 col-md-2 control-label" >Port</label>
+                                    <div class="col-sm-10 col-md-10">
+                                        <input type="number" class="form-control" id="portNumber" tabindex="4" value="389" ng-model="server.port">
+                                    </div>
+                                </div>
+
+                                <div class="form-group">
+                                    <label for="connection" class="col-sm-2 col-md-2 control-label" >Connection</label>
+                                    <div class="col-sm-10 col-md-10">
+
+                                        <select pf-bootstrap-select ng-model="server.connection" id="connection">
+                                            <option value="clear"  ng-selected="true" selected>Unprotected connection (LDAP)</option>
+                                            <option value="TLS" disabled>TLS encryption (LDAPS)</option>
+                                            <option value="startTLS" disabled>StartTLS over LDAP</option>
+                                        </select>
+                                    </div>
+                                </div>
+
+
+                                <!--div class="form-group">
+                                    <label class="sr-only" for="exampleInputEmail1">Email address</label>
+                                    <input type="email" class="form-control  input-lg" id="exampleInputEmail1" placeholder="Email address">
+                                </div>
+                                <div class="form-group">
+                                    <label class="sr-only"  for="exampleInputPassword1">Password
+                                    </label>
+                                    <input type="password" class="form-control input-lg" id="exampleInputPassword1" placeholder="Password">
+                                </div>
+                                <div class="form-group login-pf-settings">
+                                    <label class="checkbox-label">
+                                        <input type="checkbox"> Keep me logged in for 30 days
+                                    </label>
+                                    <a href="#">Forgot password?</a>
+                                </div-->
+                                <!--button type="submit" class="btn btn-primary btn-block btn-lg">Log In</button-->
+                                <button ng-click="handleLogin()" type="submit" class="btn btn-primary btn-block btn-lg" tabindex="5">Log In</button>
+                                <!--p>{{server| json }}</p-->
+                            </form>
+                            <p class="login-pf-signup">Want to analyze 389-ds logs?<a href="">Click here</a></p>
+                        </div><!-- card -->
+                        <footer class="login-pf-page-footer">
+                            <ul class="login-pf-page-footer-links list-unstyled">
+                                <li><a class="login-pf-page-footer-link" href="#">Terms of Use</a></li>
+                                <li><a class="login-pf-page-footer-link" href="#">Help</a></li>
+                                <li><a class="login-pf-page-footer-link" href="#">Privacy Policy</a></li>
+                            </ul>
+                        </footer>
+                    </div><!-- col -->
+                </div><!-- row -->
+            </div><!-- col -->
+        </div><!-- login-pf-page -->
+    </div><!--row-->
+</div><!--container-->
+
+
diff --git a/montool/views/logs.html b/montool/views/logs.html
new file mode 100644
index 0000000..4fb5f7a
--- /dev/null
+++ b/montool/views/logs.html
@@ -0,0 +1,52 @@
+
+
+<div class="container-fluid">
+
+    <div>
+        <pf-inline-notification pf-notification-type="notification.type"
+                                pf-notification-header="notification.header"
+                                pf-notification-message="notification.message"
+                                pf-notification-persistent="notification.isPersistent"
+                                pf-notification-remove="removeNotification()">
+        </pf-inline-notification>
+    </div>
+
+    <div class="controls">        
+        <button type="button"  ng-click="launchLogconvWizard()" style="margin-right: 50px">
+            <span class="fa pficon-on-running"></span>
+            Log Converter
+        </button>
+        <label>{{actualCommand}}</label>
+        <br>
+        <br>
+    </div>
+
+
+    <div class="row">
+        <div class="col-xs-6">
+            <pf-info-status-card status="information" show-top-border="true"></pf-info-status-card>
+        </div>
+        <div class="col-xs-6">
+            <pf-info-status-card status="operations" show-top-border="true"></pf-info-status-card>
+        </div>
+    </div>
+
+    <div class="row">
+        <!--div class="col-xs-6 text-center"-->
+        <div class="col-xs-6">
+            <label>LDAP Operations</label>
+            <pf-donut-chart config="logConvConfig" data="logConvData"></pf-donut-chart>
+        </div>
+        <div class="col-xs-6">
+            <label>File Descriptors</label>
+            <pf-donut-chart config="logConvConfig" data="logConvData"></pf-donut-chart>
+            <pf-utilization-bar-chart chart-data=fdTakenData chart-title=fdTitles.taken 
+                                      chart-footer=fdTakenFooter layout=layoutInline>                                          
+            </pf-utilization-bar-chart>
+            <pf-utilization-bar-chart chart-data=fdReturnedData chart-title=fdTitles.returned
+                                      chart-footer=fdReturnedFooter layout=layoutInline></pf-utilization-bar-chart>
+            <pf-utilization-bar-chart chart-data=fdHighestData chart-title=fdTitles.highest
+                                      chart-footer=fdHighestFooter layout=layoutInline></pf-utilization-bar-chart>            
+        </div>
+    </div>
+</div>
diff --git a/montool/views/monitoring.html b/montool/views/monitoring.html
new file mode 100644
index 0000000..a03401a
--- /dev/null
+++ b/montool/views/monitoring.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+
+<html lang="en-us" class="layout-pf layout-pf-fixed" ng-app="monitoring.tool.controllers">
+    <!--html lang="en-us" class="layout-pf layout-pf-fixed" ng-app="monitoring.tool.controllers" ng-strict-di="true"-->
+
+    <head>
+        <base href="/">
+        <title>IPA and RHDS Monitoring Tool</title>
+        <!--link rel="stylesheet" href="../node_modules/angular-patternfly/node_modules/patternfly/dist/css/patternfly.min.css"-->
+        <!--link rel="stylesheet" href="../node_modules/angular-patternfly/node_modules/patternfly/dist/css/patternfly.css"-->
+        <!--link rel="stylesheet" href="../node_modules/angular-patternfly/node_modules/patternfly/dist/css/patternfly-additions.min.css"-->
+        <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/patternfly/3.41.3/css/patternfly.min.css">
+        <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/patternfly/3.41.3/css/patternfly-additions.min.css">
+        <!--link rel="stylesheet" type="text/css" href="../css/login.css">
+        <link rel="stylesheet" type="text/css" href="../css/topology.css"-->
+        <link rel="shortcut icon" href="../images/favicon.ico">
+
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/jquery.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/bootstrap.min.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/bootstrap-select.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/jquery-ui.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/jquery.dataTables.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/dataTables.select.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/moment.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/d3.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/c3.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/patternfly-settings.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/patternfly-settings-colors.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/patternfly-settings-charts.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/angular.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/angular-dragdrop.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/angular-datatables.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/angular-datatables.select.min.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/angular-sanitize.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/angular-animate.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/ui-bootstrap-tpls.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/angular-bootstrap-prettify.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/lodash.min.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/angular-patternfly.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/angular-ui-router.min.js"></script>
+        <script src="https://www.patternfly.org/angular-patternfly/grunt-scripts/angular-drag-and-drop-lists.js"></script>
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/3.3.4/js/bootstrap-switch.min.js"></script>
+
+        <script src="../controllers/monitoringTool.js"></script>
+        <script src="../controllers/navigation.js"></script>
+        <script src="../controllers/login.js"></script>
+        <script src="../controllers/dashboard.js"></script>
+        <script src="../controllers/configuration.js"></script>
+        <script src="../controllers/topology.js"></script>
+        <script src="../controllers/security.js"></script>
+        <script src="../controllers/logs.js"></script>
+        <script src="../controllers/troubleshoot.js"></script>
+        <script src="../controllers/wizards/checkcerts.js"></script>
+        <script src="../controllers/wizards/expiredcerts.js"></script>
+        <script src="../controllers/wizards/replcheck.js"></script>
+        <script src="../controllers/wizards/csn.js"></script>
+        <script src="../controllers/wizards/logconv.js"></script>
+
+    </head>
+
+    <body>
+        <!--div ng-controller="showDemoController">
+            <button class="btn btn-primary" id="showVerticalNavWithRouter" ng-click="loginPage()">Show Vertical Navigation with UIRouter</button>
+            <label class="example-info-text">This will display the vertical nav bar and some mock content over the content of this page.</label>
+            <label class="example-info-text">Exit the demo to return back to this page.</label>
+        </div-->
+
+
+        <div id="verticalNavWithRouterLayout" class="faux-layout" ng-controller="vertNavWithRouterController">
+            <pf-vertical-navigation items="navigationItems" brand-alt="IPA and RHDS Monitoring Tool"
+                                    show-badges="true" update-active-items-on-click="true"
+                                    navigate-callback="handleNavigateClickRouter">
+                <div>
+
+                    <ul class="nav navbar-nav navbar-right navbar-iconic">
+                        <li class="dropdown">
+                        </li>
+                        <li class="dropdown">
+                            <a class="dropdown-toggle nav-item-iconic" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
+                                <span title="Help" class="fa pficon-help"></span>
+                                <span class="caret"></span>
+                            </a>
+                            <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
+                                <li><a href="">Help</a></li>
+                                <li><a href="">About</a></li>
+                            </ul>
+                        </li>
+                        <li class="dropdown">
+                            <a class="dropdown-toggle nav-item-iconic" id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
+                                <span title="Username" class="fa pficon-user"></span>
+                                <span class="caret"></span>
+                            </a>
+                            <ul class="dropdown-menu" aria-labelledby="dropdownMenu2">
+                                <li><a href="">Preferences</a></li>
+                                <li><a href="">Logout</a></li>
+                            </ul>
+                        </li>
+                    </ul>
+                </div>
+            </pf-vertical-navigation>
+            <div id="contentContainer" class="container-fluid container-cards-pf container-pf-nav-pf-vertical example-page-container">
+                <!--div id="contentContainer"-->
+                <ui-view>
+                    <!-- Content will be added here -->
+                </ui-view>
+            </div>
+        </div>
+
+    </body>
+</html>
\ No newline at end of file
diff --git a/montool/views/security.html b/montool/views/security.html
new file mode 100644
index 0000000..13b596a
--- /dev/null
+++ b/montool/views/security.html
@@ -0,0 +1,86 @@
+
+
+
+<div>      
+    <button ng-click="demoShowCertsExpiringIn2019()" class="btn btn-default" style="margin:10px;">
+        Show Certificates which will expire in 2019
+    </button>
+</div>
+<div class="row row-cards-pf" style="height: 89px;">
+    <pf-card-view id="exampleCardView"
+                  config="config"
+                  page-config="pageConfig"
+                  empty-state-config="emptyStateConfig"
+                  items="items"
+                  empty-state-action-buttons="emptyStateActionButtons">
+        <!--div class="card-pf card-pf-view "-->
+
+        <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3">
+            <div class="card-pf card-pf-view card-pf-view-select card-pf-view-single-select">
+                <div class="card-pf-body">
+                    <div class="card-pf-top-element">
+                        <!--span class="fa fa-birthday-cake card-pf-icon-circle"></span-->
+                        <span class="fa fa-lock card-pf-icon-circle"></span>
+                    </div>
+                    <h3 class="card-pf-title text-center">
+                        <span>{{item.name}}</span>
+                    </h3>
+                    <div class="card-pf-items text-center">
+                        <div class="card-pf-item">
+                            <!--span class="pficon pficon-locked"></span-->
+                            <span class="fa fa-id-badge"></span>
+                            <span class="card-pf-item-text">{{item.serialno}}</span>
+                        </div>
+                        <div class="card-pf-item">
+                            <span class="fa fa-check"></span>
+                        </div>
+                    </div>
+                    <p class="card-pf-info text-center"><strong>Expires On {{item.expiration}} </strong></p>
+                    <h2>
+                        <span style="background-color:red;"><strong>{{item.futureExpiration}} </strong></span>
+                    </h2>
+                </div>
+                <!--div class="card-pf-view-checkbox">
+                    <input type="checkbox">
+                </div-->
+            </div>
+        </div>
+    </pf-card-view>
+</div>
+
+
+<div>
+    <pf-about-modal is-open="isModalOpen" on-close="onModalClose()" additional-info="additionalInfo"
+                    product-info="certificateInfo" title="title" copyright="copyright" img-alt="imgAlt" img-src="imgSrc">
+
+    </pf-about-modal>
+</div>
+
+
+<hr class="col-md-12">
+<div class="col-md-12">
+    <label class="events-label">Certificate Details </label>
+</div>
+<div class="col-md-12">
+    <textarea rows="10" class="col-md-12">{{eventText}}</textarea>
+</div>
+
+<script>
+            /*$(function () {
+             // matchHeight the contents of each .card-pf and then the .card-pf itself
+             $(".row-cards-pf > [class*='col'] > .card-pf > .card-pf-body").matchHeight();
+             });*/
+            $(document).ready(function () {
+                // Card Single Select
+                $('.card-pf-view-single-select').click(function () {
+                    if ($(this).hasClass('active'))
+                    {
+                        $(this).removeClass('active');
+                    } else
+                    {
+                        $('.card-pf-view-single-select').removeClass('active');
+                        $(this).addClass('active');
+                    }
+                });
+            });
+</script>
\ No newline at end of file
diff --git a/montool/views/topology.html b/montool/views/topology.html
new file mode 100644
index 0000000..944f909
--- /dev/null
+++ b/montool/views/topology.html
@@ -0,0 +1,22 @@
+
+<div class="card-pf card-pf-accented card-pf-aggregate-status" style="height: 89px;">
+    <div class="card-pf-body" style="height: 50px;">
+        <span class="pficon pficon-pending fa-3x"></span>
+        <p class="card-pf-aggregate-status-notifications">
+            State: TODO - Use PatternFly <i>pfTopology</i>.
+            <br>
+            <br>
+            <a href="https://www.patternfly.org/angular-patternfly/#/api/patternfly.charts.component:pfTopology" target="_blank">Angular PatternFly - pfTopology
+                <i class="fa fa-external-link" aria-hidden="true"></i>
+            </a>
+            <br>
+            <br>
+
+            <button ng-click="handleTest()" type="submit" class="btn btn-primary btn-block btn-lg">Check LDAP Server info using LoginFactory</button>
+            <br>
+            <br>
+
+        <p>{{server| json }}</p>
+
+    </div>
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot.html b/montool/views/troubleshoot.html
new file mode 100644
index 0000000..d224a1d
--- /dev/null
+++ b/montool/views/troubleshoot.html
@@ -0,0 +1,12 @@
+
+<link href="../css/troubleshoot.css" rel="stylesheet">
+
+<div style="background-color: #fff; margin: -20px;">
+    <ul class="nav nav-tabs nav-justified">        
+        <!-- EMPTY href issue : https://github.com/angular/angular/issues/7294 -->
+        <li ng-class="{'active': viewType === 'tools'}"><a href="" ng-click="setView('tools')">Tools</a></li>
+        <li ng-class="{'active': viewType === 'insights'}"><a href="" ng-click="setView('insights')">Red Hat Insights</a></li>
+    </ul>
+    <div ng-if="viewType === 'tools'" ng-include="'views/troubleshoot/tools.html'"></div>
+    <div ng-if="viewType === 'insights'" ng-include="'views/troubleshoot/insights.html'"></div>
+</div>
diff --git a/montool/views/troubleshoot/cause/check-certs.html b/montool/views/troubleshoot/cause/check-certs.html
new file mode 100644
index 0000000..59e57bd
--- /dev/null
+++ b/montool/views/troubleshoot/cause/check-certs.html
@@ -0,0 +1,3 @@
+<div >
+    This could caused by software bugs, incomplete upgrades, direct modifications of the LDAP and NSS databases, ...    
+</div>
diff --git a/montool/views/troubleshoot/cause/csn-conv.html b/montool/views/troubleshoot/cause/csn-conv.html
new file mode 100644
index 0000000..50fb077
--- /dev/null
+++ b/montool/views/troubleshoot/cause/csn-conv.html
@@ -0,0 +1,3 @@
+<div >
+    Replication CSN ( Change Sequence Number ) could be hard to interpret.
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot/cause/db-verif.html b/montool/views/troubleshoot/cause/db-verif.html
new file mode 100644
index 0000000..94ec5f4
--- /dev/null
+++ b/montool/views/troubleshoot/cause/db-verif.html
@@ -0,0 +1,3 @@
+<div>
+    Some bugs could lead to corrupted LDAP databases.
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot/cause/expired-certs.html b/montool/views/troubleshoot/cause/expired-certs.html
new file mode 100644
index 0000000..69553e6
--- /dev/null
+++ b/montool/views/troubleshoot/cause/expired-certs.html
@@ -0,0 +1,13 @@
+<div >
+    There are cases when the IdM Server internal certificates do not renew properly, for example when:
+    <ul style="list-style-type:disc">
+        <li>The IdM Server that is responsible for renewing internal certificates (CA Renewal Master) is offline
+            <br>
+            or is not part of the deployment any more (from RHEL-7.4, verify with ipa config-show)
+            <br>
+        </li>
+        <li>
+            The IdM CA Renewal Master stopped tracking due to a misconfiguration or bug.
+        </li>
+    </ul>
+</div>
diff --git a/montool/views/troubleshoot/cause/ipa-check.html b/montool/views/troubleshoot/cause/ipa-check.html
new file mode 100644
index 0000000..1b8d26c
--- /dev/null
+++ b/montool/views/troubleshoot/cause/ipa-check.html
@@ -0,0 +1,3 @@
+<div>
+    There could be synchronization issues between IPA servers due to bugs or administrative actions.
+</div>
diff --git a/montool/views/troubleshoot/cause/ipa-status.html b/montool/views/troubleshoot/cause/ipa-status.html
new file mode 100644
index 0000000..7a6e0dc
--- /dev/null
+++ b/montool/views/troubleshoot/cause/ipa-status.html
@@ -0,0 +1,3 @@
+<div>
+    Some IPA services could be stopped.
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot/cause/repl-conflicts.html b/montool/views/troubleshoot/cause/repl-conflicts.html
new file mode 100644
index 0000000..c9ce775
--- /dev/null
+++ b/montool/views/troubleshoot/cause/repl-conflicts.html
@@ -0,0 +1,17 @@
+<div>
+    Multi-master replication uses an eventually-consistency replication model.
+    <br>
+    This means that the same entries can be changed on different servers.
+    <br>
+    When replication occurs between these two servers, the conflicting changes need to be resolved.
+    <br>
+    Mostly, resolution occurs automatically, based on the time stamp associated with the change on each server.
+    <br>
+    The most recent change takes precedence.
+    <br>
+    However, there are some cases where conflicts require manual intervention in order to reach a resolution.
+    <br>
+    Entries with a change conflict that cannot be resolved automatically by the replication process
+    <br>
+    contain the nsds5ReplConflict conflict marker attribute and the ldapSubEntry object class. 
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot/cause/repl-sync.html b/montool/views/troubleshoot/cause/repl-sync.html
new file mode 100644
index 0000000..16b3c3b
--- /dev/null
+++ b/montool/views/troubleshoot/cause/repl-sync.html
@@ -0,0 +1,3 @@
+<div>
+    In certain situations, an administrator wants to compare if two Directory Servers are synchronized. 
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot/fix/check-certs.html b/montool/views/troubleshoot/fix/check-certs.html
new file mode 100644
index 0000000..0af6d93
--- /dev/null
+++ b/montool/views/troubleshoot/fix/check-certs.html
@@ -0,0 +1,12 @@
+<div>
+    <b>IPA cert checker</b>
+    <br>
+    <i>GNU General Public License v3.0</i>
+    <br>
+    <br>
+    <a href="https://github.com/rcritten/checkcerts" target="_blank">        
+        Tool to check FreeIPA certificates     
+        <i class="fa fa-external-link" aria-hidden="true">
+        </i>
+    </a>  
+</div>
diff --git a/montool/views/troubleshoot/fix/csn-conv.html b/montool/views/troubleshoot/fix/csn-conv.html
new file mode 100644
index 0000000..e7809bf
--- /dev/null
+++ b/montool/views/troubleshoot/fix/csn-conv.html
@@ -0,0 +1,10 @@
+<div>
+    <b>Red Hat KCS Article:</b>
+    <br>
+    <br>
+    <a href="https://access.redhat.com/solutions/3536761" target="_blank">        
+        How to decode replication CSN ?
+        <i class="fa fa-external-link" aria-hidden="true">
+        </i>
+    </a>  
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot/fix/db-verif.html b/montool/views/troubleshoot/fix/db-verif.html
new file mode 100644
index 0000000..050a810
--- /dev/null
+++ b/montool/views/troubleshoot/fix/db-verif.html
@@ -0,0 +1,11 @@
+<div>
+    <b>Red Hat Directory Server Documentation</b>
+    <br>
+    <br>
+    <a href="https://access.redhat.com/documentation/en-us/red_hat_directory_server/10/html/configuration_command_and_file_reference/shell_scripts#dbverify"
+       target="_blank">        
+        dbverify (Checks for Corrupt Databases)
+        <i class="fa fa-external-link" aria-hidden="true">
+        </i>
+    </a>  
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot/fix/expired-certs.html b/montool/views/troubleshoot/fix/expired-certs.html
new file mode 100644
index 0000000..468d4f1
--- /dev/null
+++ b/montool/views/troubleshoot/fix/expired-certs.html
@@ -0,0 +1,10 @@
+<div>
+    <b>Red Hat KCS Article:</b>
+    <br>
+    <br>
+    <a href="https://access.redhat.com/articles/3353041" target="_blank">        
+        Certificate Renewal in Identity-Management
+        <i class="fa fa-external-link" aria-hidden="true">
+        </i>
+    </a>  
+</div>
diff --git a/montool/views/troubleshoot/fix/ipa-check.html b/montool/views/troubleshoot/fix/ipa-check.html
new file mode 100644
index 0000000..5f69e3c
--- /dev/null
+++ b/montool/views/troubleshoot/fix/ipa-check.html
@@ -0,0 +1,12 @@
+<div>
+    <b>checkipaconsistency aka cipa</b>
+    <br>
+    <i>GNU General Public License v3.0</i>
+    <br>
+    <br>
+    <a href="https://github.com/peterpakos/checkipaconsistency" target="_blank">        
+        Tool to check consistency across FreeIPA servers
+        <i class="fa fa-external-link" aria-hidden="true">
+        </i>
+    </a>  
+</div>
diff --git a/montool/views/troubleshoot/fix/ipa-status.html b/montool/views/troubleshoot/fix/ipa-status.html
new file mode 100644
index 0000000..1de0952
--- /dev/null
+++ b/montool/views/troubleshoot/fix/ipa-status.html
@@ -0,0 +1,11 @@
+<div>
+    <b>Red Hat Directory Server Documentation</b>
+    <br>
+    <br>
+    <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/linux_domain_identity_authentication_and_policy_guide/basic-usage"
+       target="_blank">        
+        THE BASICS OF MANAGING THE IDM SERVER AND SERVICES
+        <i class="fa fa-external-link" aria-hidden="true">
+        </i>
+    </a>  
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot/fix/repl-conflicts.html b/montool/views/troubleshoot/fix/repl-conflicts.html
new file mode 100644
index 0000000..c0fd147
--- /dev/null
+++ b/montool/views/troubleshoot/fix/repl-conflicts.html
@@ -0,0 +1,17 @@
+<div>
+    <b>Red Hat KCS Articles:</b>
+    <br>
+    <br>
+    <a href="https://access.redhat.com/solutions/2083603" target="_blank">
+        How to delete "nsuniqueid=xxxx+uidxxxx" conflicting entries in IPA?
+        <i class="fa fa-external-link" aria-hidden="true">
+        </i>
+    </a>
+    <br>
+    <br>
+    <a href="https://access.redhat.com/solutions/204783" target="_blank">       
+        Why do "nsuniqueid=xxxx+uidxxxx" entries exist in my RHDS? How can I delete them?
+        <i class="fa fa-external-link" aria-hidden="true">
+        </i>
+    </a>
+</div>
diff --git a/montool/views/troubleshoot/fix/repl-sync.html b/montool/views/troubleshoot/fix/repl-sync.html
new file mode 100644
index 0000000..20b9665
--- /dev/null
+++ b/montool/views/troubleshoot/fix/repl-sync.html
@@ -0,0 +1,11 @@
+<div>
+    <b>Red Hat Directory Server Documentation</b>
+    <br>
+    <br>
+    <a href="https://access.redhat.com/documentation/en-us/red_hat_directory_server/10/html/configuration_command_and_file_reference/shell_scripts#ds-replcheck"
+       target="_blank">        
+        ds-replcheck (Check Replication Status Between Two Databases)
+        <i class="fa fa-external-link" aria-hidden="true">
+        </i>
+    </a>  
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot/insights.html b/montool/views/troubleshoot/insights.html
new file mode 100644
index 0000000..1c47792
--- /dev/null
+++ b/montool/views/troubleshoot/insights.html
@@ -0,0 +1,19 @@
+<div class="card-pf card-pf-accented card-pf-aggregate-status" style="height: 89px;">
+    <div class="card-pf-body" style="height: 50px;">
+        <span class="pficon pficon-pending fa-3x"></span>
+        <p class="card-pf-aggregate-status-notifications">
+            State: TODO - Connect to Red Hat Insights.
+            <br>
+            <br>
+            <br>
+            <a href="https://access.redhat.com/articles/3293461" target="_blank">Understanding Red Hat Insights - Webhooks Integration
+                <i class="fa fa-external-link" aria-hidden="true"></i>
+            </a>
+            <br>
+            <br>
+            <a href="https://access.redhat.com/r/insights/docs/#api-Webhooks" target="_blank">Webhooks API
+                <i class="fa fa-external-link" aria-hidden="false"></i>
+            </a>           
+        </p>        
+    </div>
+</div>
diff --git a/montool/views/troubleshoot/issue/check-certs.html b/montool/views/troubleshoot/issue/check-certs.html
new file mode 100644
index 0000000..93a0e77
--- /dev/null
+++ b/montool/views/troubleshoot/issue/check-certs.html
@@ -0,0 +1,7 @@
+
+<div >
+    <b>IPA Certificates checkup.</b>
+    <br>
+    <br>
+    How to check IPA certificates?
+</div>
diff --git a/montool/views/troubleshoot/issue/csn-conv.html b/montool/views/troubleshoot/issue/csn-conv.html
new file mode 100644
index 0000000..d349f8a
--- /dev/null
+++ b/montool/views/troubleshoot/issue/csn-conv.html
@@ -0,0 +1,6 @@
+<div >
+    <b>How to convert a CSN to a more readable information?</b>
+    <br>
+    <br>
+    Need to extract relevant information from a CSN ( Change Sequence Number ).
+</div>
diff --git a/montool/views/troubleshoot/issue/db-verif.html b/montool/views/troubleshoot/issue/db-verif.html
new file mode 100644
index 0000000..83b6b54
--- /dev/null
+++ b/montool/views/troubleshoot/issue/db-verif.html
@@ -0,0 +1,6 @@
+<div >
+    <b>How to check if LDAP databases are corrupted?</b>
+    <br>
+    <br>
+    Need to verify the integrity of the LDAP database files.
+</div>
diff --git a/montool/views/troubleshoot/issue/expired-certs.html b/montool/views/troubleshoot/issue/expired-certs.html
new file mode 100644
index 0000000..cbe13dd
--- /dev/null
+++ b/montool/views/troubleshoot/issue/expired-certs.html
@@ -0,0 +1,7 @@
+
+<div >
+    <b>Expired Certificates.</b>
+    <br>
+    <br>
+    How to renew IPA expired certificates?
+</div>
diff --git a/montool/views/troubleshoot/issue/ipa-check.html b/montool/views/troubleshoot/issue/ipa-check.html
new file mode 100644
index 0000000..98e6360
--- /dev/null
+++ b/montool/views/troubleshoot/issue/ipa-check.html
@@ -0,0 +1,6 @@
+<div >
+    <b>How to check consistency across IPA servers?</b>
+    <br>
+    <br>
+    Need to check if data are synchronized among IPA servers.
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot/issue/ipa-status.html b/montool/views/troubleshoot/issue/ipa-status.html
new file mode 100644
index 0000000..df45cfe
--- /dev/null
+++ b/montool/views/troubleshoot/issue/ipa-status.html
@@ -0,0 +1,6 @@
+<div >
+    <b>How to check the status of IPA services?</b>
+    <br>
+    <br>
+    Need to get the status of all the services that make up IPA.
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot/issue/repl-conflicts.html b/montool/views/troubleshoot/issue/repl-conflicts.html
new file mode 100644
index 0000000..a2910be
--- /dev/null
+++ b/montool/views/troubleshoot/issue/repl-conflicts.html
@@ -0,0 +1,6 @@
+<div >
+    <b>How to resolve LDAP replication conflicts?</b>
+    <br>
+    <br>
+    Need to resolve replication conflicts by deleting or renaming some entries.
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot/issue/repl-sync.html b/montool/views/troubleshoot/issue/repl-sync.html
new file mode 100644
index 0000000..cb4093b
--- /dev/null
+++ b/montool/views/troubleshoot/issue/repl-sync.html
@@ -0,0 +1,6 @@
+<div >
+    <b>How to check LDAP replication status between two databases?</b>
+    <br>
+    <br>
+    Need to compare two Directory Server instances to identify if they are synchronized.
+</div>
\ No newline at end of file
diff --git a/montool/views/troubleshoot/item-expansion.html b/montool/views/troubleshoot/item-expansion.html
new file mode 100644
index 0000000..4004f87
--- /dev/null
+++ b/montool/views/troubleshoot/item-expansion.html
@@ -0,0 +1,13 @@
+
+<div ng-if="$ctrl.item.expandField === 'issue'" ng-include="'views/troubleshoot/issue/'
+            + $ctrl.item.id + '.html'">    
+</div>
+<div ng-if="$ctrl.item.expandField === 'cause'" ng-include="'views/troubleshoot/cause/'
+     + $ctrl.item.id + '.html'">    
+</div>
+<div ng-if="$ctrl.item.expandField === 'fix'" ng-include="'views/troubleshoot/fix/'
+     + $ctrl.item.id + '.html'">    
+</div>
+
+<!--div ng-if="$ctrl.item.expandField === 'nodes'" ng-include="'views/listview/examples/nodes-content.html'"></div>
+<div ng-if="$ctrl.item.name === 'Expired Certificates' && $ctrl.item.expandField === 'fix'" ng-include="'views/config/cache.html'"></div-->
\ No newline at end of file
diff --git a/montool/views/troubleshoot/tools.html b/montool/views/troubleshoot/tools.html
new file mode 100644
index 0000000..e21da4b
--- /dev/null
+++ b/montool/views/troubleshoot/tools.html
@@ -0,0 +1,55 @@
+<div ng-controller="TroubleshootCtrl" class="row example-container">
+    <div class="col-md-12 list-view-container example-list-view">
+        <pf-list-view id="toolsListView"
+                      config="configTroubleshoot"
+                      items="itemsTroubleshoot"
+                      action-buttons="actionButtons"
+                      update-menu-action-for-item-fn="updateMenuActionForItemFn"
+                      menu-class-for-item-fn="getMenuClass"
+                      hide-menu-for-item-fn="hideMenuActions"
+                      custom-scope="customScope">
+            <div class="list-view-pf-left">
+                <span class="{{item.typeIcon}} list-view-pf-icon-sm"></span>
+            </div>
+            <div class="list-view-pf-body">
+                <div class="list-view-pf-description">
+                    <div class="list-group-item-heading">
+                        {{item.name}}
+                    </div>
+                    <!--div class="list-group-item-text">
+                        The following snippet of text is <a href="#">rendered as link text</a>.
+                    </div-->
+                </div>
+                <div class="list-view-pf-additional-info">
+                    <div class="list-view-pf-additional-info-item">
+                        <div class="list-view-pf-expand" ng-click="$ctrl.customScope.toggleExpandItemField(item, 'issue')">
+                            <span class="fa fa-angle-right" ng-class="{'fa-angle-down': $ctrl.customScope.isItemExpanded(item, 'issue')}"></span>
+                            <span class="pficon pficon-messages"></span>
+                           Issue
+                        </div>
+                    </div>
+                    <div class="list-view-pf-additional-info-item">
+                        <div class="list-view-pf-expand" ng-click="$ctrl.customScope.toggleExpandItemField(item, 'cause')">
+                            <span class="fa fa-angle-right" ng-class="{'fa-angle-down': $ctrl.customScope.isItemExpanded(item, 'cause')}"></span>
+                            <span class="pficon pficon-info"></span>
+                            Cause
+                        </div>
+                    </div>
+                    <div class="list-view-pf-additional-info-item">
+                        <div class="list-view-pf-expand" ng-click="$ctrl.customScope.toggleExpandItemField(item, 'fix')">
+                            <span class="fa fa-angle-right" ng-class="{'fa-angle-down': $ctrl.customScope.isItemExpanded(item, 'fix')}"></span>
+                            <span class="pficon pficon-maintenance"></span>
+                            Fix
+                        </div>
+                    </div>               
+                </div>
+            </div>
+            <list-expanded-content>
+                <div class="close">
+                    <span class="pficon pficon-close" ng-click="$parent.$ctrl.customScope.collapseItem($parent.item)"></span>
+                </div>
+                <item-expansion item="$parent.item"></item-expansion>
+            </list-expanded-content>
+        </pf-list-view>
+    </div>
+</div>
diff --git a/montool/views/wizards/checkcerts/wizard-checkcerts.html b/montool/views/wizards/checkcerts/wizard-checkcerts.html
new file mode 100644
index 0000000..4135e7c
--- /dev/null
+++ b/montool/views/wizards/checkcerts/wizard-checkcerts.html
@@ -0,0 +1,117 @@
+
+<pf-wizard wizard-title="Wizard - Check IPA Certificates"
+           wizard-ready="checkcertsWizardReady"
+           on-finish="finishedCheckcertsWizard()"
+           on-cancel="cancelCheckcertsWizard()"
+           next-title="nextButtonTitle"
+           next-callback="nextCallback"
+           back-callback="backCallback"
+           wizard-done="checkcertsComplete"
+           sidebar-class="example-wizard-sidebar"
+           step-class="example-wizard-step"
+           loading-secondary-information="secondaryLoadInformation"
+           on-step-changed="stepChanged(step, index)">
+
+    <pf-wizard-step step-title="Host"
+                    substeps="false" step-id="host" step-priority="0"
+                    show-review="false" show-review-details="false" allow-click-nav="true">        
+        <div>
+            <form class="form-horizontal">
+                <pf-form-group pf-label="Host"
+                               required pf-label-class="col-sm-3" pf-input-class="col-sm-5">
+                    <input id="host" name="host" ng-model="checkcerts.host"
+                           value="{{checkcerts.host}}" type="text" required/>
+                </pf-form-group>
+                <pf-form-group pf-label="User"
+                               required pf-label-class="col-sm-3" pf-input-class="col-sm-5">
+                    <input id="user" name="user" ng-model="checkcerts.user" type="text"
+                           value="{{checkcerts.user}}" required disabled/>
+                </pf-form-group>                
+            </form>
+        </div>       
+    </pf-wizard-step>
+
+    <!--next-enabled="connectionVerified"-->
+    <pf-wizard-step step-title="Root Access" 
+                    substeps="false" step-id="root-access" step-priority="1"
+                    on-show="checkConnection"
+                    show-review="false" show-review-details="false" allow-click-nav="true">
+        <div>
+            <pf-inline-notification pf-notification-type="notificationConnection.type"
+                                    pf-notification-header="notificationConnection.header"
+                                    pf-notification-message="notificationConnection.message"
+                                    pf-notification-persistent="notificationConnection.isPersistent">
+            </pf-inline-notification>
+        </div>
+        <div ng-if="!connectionCommandComplete">
+            <div class="spinner spinner-lg blank-slate-pf-icon"></div>
+            <div style="text-align:center">
+                <b>SSH Connection in progress...</b>
+            </div>
+        </div>             
+    </pf-wizard-step>
+
+    <pf-wizard-step step-title="Options"
+                    substeps="false" step-id="options" step-priority="2"
+                    show-review="false" show-review-details="false" allow-click-nav="true">
+        <!--div class="col-md-12  text-center">
+            <div>
+                <label class="checkbox-inline">
+                    <input type="checkbox" ng-model="checkcerts.verbose">
+                    Verbose Mode
+                    </input>
+                </label>
+            </div>
+            <div>
+                <div>
+                    <label class="checkbox-inline">
+                        <input type="checkbox" ng-model="checkcerts.debug">
+                        Debug Mode
+                        </input>
+                    </label>        
+                </div>
+            </div>
+        </div-->
+
+        <div class="col-md-12" style="padding-top: 12px;">
+            <div class="form-group">
+                <label class="checkbox-inline">
+                    <input type="checkbox" ng-model="checkcerts.verbose">
+                    Verbose mode
+                    </input>
+                </label>
+            </div>
+            <div class="form-group">
+                <label class="checkbox-inline">
+                    <input type="checkbox" ng-model="checkcerts.debug">
+                    Enable IPA API debugging output
+                    </input>
+                </label>
+            </div>
+        </div>
+    </pf-wizard-step>
+
+    <pf-wizard-step step-title="Output"
+                    substeps="false" step-id="output" step-priority="3"
+                    show-review="false" show-review-details="false" allow-click-nav="true">      
+        <div ng-if="!checkCertsCommandComplete">
+            <div class="spinner spinner-lg blank-slate-pf-icon"></div>
+            <!--div style="text-align:center"-->
+            <div class="text-center">
+                <b>Getting IPA Cert Checker Output...</b>
+            </div>
+        </div>
+        <div ng-if="checkCertsCommandComplete">
+            <form class="form-horizontal">
+                <!--pf-form-group pf-label="Output" pf-label-class="col-sm-2" pf-input-class="col-sm-12"-->
+                <pf-form-group pf-label="Output" pf-input-class="col-sm-12">
+                    <textarea style="background-color: white; color: black;"
+                              id="output" name="output" ng-model="checkcerts.output" rows="15" readonly>
+                        {{checkcerts.output}}
+                    </textarea>
+                </pf-form-group>
+            </form>
+        </div>
+
+    </pf-wizard-step>
+</pf-wizard>
\ No newline at end of file
diff --git a/montool/views/wizards/cipa/wizard-cipa.html b/montool/views/wizards/cipa/wizard-cipa.html
new file mode 100644
index 0000000..4a8af5a
--- /dev/null
+++ b/montool/views/wizards/cipa/wizard-cipa.html
@@ -0,0 +1,103 @@
+<pf-wizard wizard-title="Wizard - Check Replication Status Between Two Databases"
+           wizard-ready="replCheckWizardReady"
+           on-finish="finishedReplCheckWizard()"
+           on-cancel="cancelReplCheckWizard()"
+           next-title="nextButtonTitle"
+           next-callback="nextCallback"
+           back-callback="backCallback"
+           wizard-done="replCheckComplete"
+           sidebar-class="example-wizard-sidebar"
+           step-class="example-wizard-step"
+           loading-secondary-information="secondaryLoadInformation"
+           on-step-changed="stepChanged(step, index)">
+
+    <pf-wizard-step step-title="LDAP URLs"
+                    substeps="false" step-id="ldap-urls" step-priority="0"
+                    show-review="false" show-review-details="false" allow-click-nav="true">        
+        <div>
+            <form class="form-horizontal">
+                <pf-form-group pf-label="Supplier &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+                               &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{replcheck.supplierConnType}}://"
+                               required pf-label-class="col-sm-3" pf-input-class="col-sm-5">
+                    <input id="supplier" name="supplier" ng-model="replcheck.supplier" type="text" required/>
+                </pf-form-group>
+                <pf-form-group pf-label="Replica &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+                               &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{replcheck.replicaConnType}}://"
+                               required pf-label-class="col-sm-3" pf-input-class="col-sm-5">
+                    <input id="replica" name="replica" ng-model="replcheck.replica" type="text" value="{{replcheck.supplierConnType}}://" required/>
+                </pf-form-group>
+                <div class="form-group">
+                    <label for="connection" class="col-sm-2 col-md-2 control-label" >Connection</label>
+                    <div class="col-sm-10 col-md-10">
+                        <select pf-bootstrap-select ng-model="replcheck.connection" id="connection" ng-change="handleConnectionType()">
+                            <option value="clear"  ng-selected="true" selected>Unprotected connection (LDAP)</option>
+                            <option value="TLS">TLS encryption (LDAPS)</option>
+                            <option value="startTLS">StartTLS over LDAP</option>
+                            <option value="LDAPI">LDAP over IPC (LDAPI)</option>
+                        </select>  
+                    </div>
+                </div>
+            </form>
+        </div>
+    </pf-wizard-step>
+
+    <pf-wizard-step step-title="Bind User Credentials"
+                    substeps="false" step-id="bind-user" step-priority="1"
+                    show-review="false" show-review-details="false" allow-click-nav="true">        
+        <div>
+            <form class="form-horizontal">
+                <pf-form-group pf-label="Bind DN" required pf-label-class="col-sm-2" pf-input-class="col-sm-5">
+                    <input id="binddn" name="binddn" ng-model="replcheck.binddn" type="text" required/>
+                </pf-form-group>
+                <pf-form-group pf-label="Password" required pf-label-class="col-sm-2" pf-input-class="col-sm-5">
+                    <input id="password" name="password" ng-model="replcheck.password" type="password" required/>
+                </pf-form-group>                
+            </form>
+
+        </div>
+
+    </pf-wizard-step>
+    <pf-wizard-step step-title="LDAP Suffix"
+                    substeps="false" step-id="suffix" step-priority="2"
+                    show-review="false" show-review-details="false" allow-click-nav="true">        
+        <div>
+            <form class="form-horizontal">
+                <pf-form-group pf-label="Suffix" required pf-label-class="col-sm-2" pf-input-class="col-sm-8">
+                    <input id="suffix" name="suffix" ng-model="replcheck.suffix" type="text" required/>
+                </pf-form-group>
+            </form>
+        </div>
+
+    </pf-wizard-step>
+
+    <pf-wizard-step step-title="Output"
+                    substeps="false" step-id="output" step-priority="3"
+                    show-review="false" show-review-details="false" allow-click-nav="true">      
+        <div>
+            <pf-inline-notification pf-notification-type="notificationCommand.type"
+                                    pf-notification-header="notificationCommand.header"
+                                    pf-notification-message="notificationCommand.message"
+                                    pf-notification-persistent="notificationCommand.isPersistent"
+                                    pf-notification-remove="removeNotification()">
+            </pf-inline-notification>
+        </div>
+        <div ng-if="!commandComplete">
+                <div class="spinner spinner-lg blank-slate-pf-icon"></div>
+                <div style="text-align:center">
+                    <b>Getting ds-replcheck Output...</b>
+                </div>
+            </div>
+        <div ng-if="commandComplete">
+            <form class="form-horizontal">
+                <!--pf-form-group pf-label="Output" pf-label-class="col-sm-2" pf-input-class="col-sm-12"-->
+                <pf-form-group pf-label="Output" pf-input-class="col-sm-12">
+                    <textarea style="background-color: white; color: black;"
+                              id="output" name="output" ng-model="replcheck.output" rows="15" readonly>
+                        {{replcheck.output}}
+                    </textarea>
+                </pf-form-group>
+            </form>
+        </div>
+
+    </pf-wizard-step>
+</pf-wizard>
\ No newline at end of file
diff --git a/montool/views/wizards/expiredcerts/final-step.html b/montool/views/wizards/expiredcerts/final-step.html
new file mode 100644
index 0000000..b099b6e
--- /dev/null
+++ b/montool/views/wizards/expiredcerts/final-step.html
@@ -0,0 +1,45 @@
+<div ng-controller="FinalStepsController">
+    <pf-wizard-step step-title="Final Steps" 
+                    substeps="true"
+                    step-id="final-steps" step-priority="3" allow-click-nav="false">
+
+        <pf-wizard-substep step-title="Reset Time & Date"
+                           next-enabled="true"
+                           step-id="reset-time-date"
+                           step-priority="0"
+                           on-show=""
+                           review-template="{{hostReviewTemplate}}"
+                           show-review-details="false">
+            <strong>Work in progress - Final step 4.0...</strong>
+        </pf-wizard-substep>
+
+        <pf-wizard-substep step-title="Restart IPA" next-enabled="true"
+                           step-id="restart-ipa" step-priority="1" show-review="false"
+                           show-review-details="false"
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+            <strong>Work in progress - Final step 4.1...</strong>
+        </pf-wizard-substep>
+
+        <pf-wizard-substep step-title="Restart Certmonger" next-enabled="true"
+                           step-id="restart-certmonger"
+                           step-priority="2" show-review="true" show-review-details="false" 
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+            <strong>Work in progress - Final step 4.2...</strong>
+        </pf-wizard-substep>
+
+        <pf-wizard-substep step-title="Test IPA Admin User" next-enabled="true"
+                           step-id="test-ipa-admin-user"
+                           step-priority="3" show-review="true" show-review-details="false" 
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+            <strong>Work in progress - Final step 4.3...</strong>
+        </pf-wizard-substep>
+
+        <pf-wizard-substep step-title="Test IPA Functions" next-enabled="true"
+                           step-id="test-ipa-functions"
+                           step-priority="4" show-review="true" show-review-details="false" 
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+            <strong>Work in progress - Final step 4.4...</strong>
+        </pf-wizard-substep>
+
+    </pf-wizard-step>
+</div>
\ No newline at end of file
diff --git a/montool/views/wizards/expiredcerts/review-second-template.html b/montool/views/wizards/expiredcerts/review-second-template.html
new file mode 100644
index 0000000..d1ae713
--- /dev/null
+++ b/montool/views/wizards/expiredcerts/review-second-template.html
@@ -0,0 +1,12 @@
+<div ng-controller="DetailsReviewController">
+  <form class="form">
+    <div class="wizard-pf-review-item">
+      <span class="wizard-pf-review-item-label">Lorem:</span>
+      <span class="wizard-pf-review-item-value">{{data.lorem}}</span>
+    </div>
+    <div class="wizard-pf-review-item">
+      <span class="wizard-pf-review-item-label">Ipsum:</span>
+      <span class="wizard-pf-review-item-value">{{data.ipsum}}</span>
+    </div>
+  </form>
+</div>
\ No newline at end of file
diff --git a/montool/views/wizards/expiredcerts/review-template.html b/montool/views/wizards/expiredcerts/review-template.html
new file mode 100644
index 0000000..8aa38e1
--- /dev/null
+++ b/montool/views/wizards/expiredcerts/review-template.html
@@ -0,0 +1,12 @@
+<div ng-controller="DetailsReviewController">
+  <form class="form">
+    <div class="wizard-pf-review-item">
+      <span class="wizard-pf-review-item-label">Name:</span>
+      <span class="wizard-pf-review-item-value">{{data.name}}</span>
+    </div>
+    <div class="wizard-pf-review-item">
+      <span class="wizard-pf-review-item-label">Description:</span>
+      <span class="wizard-pf-review-item-value">{{data.description}}</span>
+    </div>
+  </form>
+</div>
\ No newline at end of file
diff --git a/montool/views/wizards/expiredcerts/second-step.html b/montool/views/wizards/expiredcerts/second-step.html
new file mode 100644
index 0000000..e988ef1
--- /dev/null
+++ b/montool/views/wizards/expiredcerts/second-step.html
@@ -0,0 +1,61 @@
+<div ng-controller="SecondStepController">
+
+    <pf-wizard-step step-title="CA Subsystem"
+                    substeps="true" step-id="ca-subsystem" step-priority="1"
+                    show-review="true" show-review-details="false" allow-click-nav="false">        
+
+        <pf-wizard-substep step-title="Last Validity Time"
+                           next-enabled="true"
+                           step-id="last-validity-time"
+                           step-priority="0"
+                           on-show=""
+                           review-template="{{hostReviewTemplate}}"
+                           show-review-details="false">
+            <strong>Work in progress - Step 2.0...</strong>
+        </pf-wizard-substep>
+
+        <!--pf-wizard-substep step-title="Root User Access" next-enabled="rootAccessComplete"-->
+        <pf-wizard-substep step-title="Revert System Clock" next-enabled="true"
+                           step-id="revert-system-clock" step-priority="1" show-review="false"
+                           show-review-details="false"
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+            <strong>Work in progress - Step 2.1...</strong>
+        </pf-wizard-substep>
+
+        <pf-wizard-substep step-title="Certificates Renewal" next-enabled="true"
+                           step-id="certificates-renewal"
+                           step-priority="2" show-review="true" show-review-details="false" 
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+            <strong>Work in progress - Step 2.2...</strong>
+        </pf-wizard-substep>
+
+        <pf-wizard-substep step-title="Trust Permissions" next-enabled="true"
+                           step-id="trust-permissions"
+                           step-priority="3" show-review="false" show-review-details="false" 
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+            <strong>Work in progress - Step 2.3...</strong>
+        </pf-wizard-substep>
+
+        <pf-wizard-substep step-title="IPA CA Config File" next-enabled="true"
+                           step-id="ipa-ca-config-file"
+                           step-priority="4" show-review="false" show-review-details="false" 
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+            <strong>Work in progress - Step 2.4...</strong>
+        </pf-wizard-substep>
+
+        <pf-wizard-substep step-title="Test CA operation" next-enabled="true"
+                           step-id="test-ca-operation"
+                           step-priority="5" show-review="false" show-review-details="false" 
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+            <strong>Work in progress - Step 2.5...</strong>
+        </pf-wizard-substep>
+
+        <pf-wizard-substep step-title="IPA Agent Certificate" next-enabled="true"
+                           step-id="ipa-agent-certificate"
+                           step-priority="6" show-review="false" show-review-details="false" 
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+            <strong>Work in progress - Step 2.6...</strong>
+        </pf-wizard-substep>
+
+    </pf-wizard-step>
+</div>
\ No newline at end of file
diff --git a/montool/views/wizards/expiredcerts/third-step.html b/montool/views/wizards/expiredcerts/third-step.html
new file mode 100644
index 0000000..fe5f0e6
--- /dev/null
+++ b/montool/views/wizards/expiredcerts/third-step.html
@@ -0,0 +1,26 @@
+<div ng-controller="SecondStepController">
+
+    <pf-wizard-step step-title="DS & Apache"
+                    substeps="true" step-id="ds-apache" step-priority="2"
+                    show-review="true" show-review-details="false" allow-click-nav="false">        
+
+        <pf-wizard-substep step-title="DS Certificate"
+                           next-enabled="true"
+                           step-id="ds-certificate"
+                           step-priority="0"
+                           on-show=""
+                           review-template="{{hostReviewTemplate}}"
+                           show-review-details="false">
+            <strong>Work in progress - Step 3.0...</strong>
+        </pf-wizard-substep>
+
+
+        <pf-wizard-substep step-title="Apache Certificate" next-enabled="true"
+                           step-id="apache-certificate" step-priority="1" show-review="false"
+                           show-review-details="false"
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+            <strong>Work in progress - Step 3.1...</strong>
+        </pf-wizard-substep>
+        
+    </pf-wizard-step>
+</div>
\ No newline at end of file
diff --git a/montool/views/wizards/expiredcerts/wizard-expiredcerts.html b/montool/views/wizards/expiredcerts/wizard-expiredcerts.html
new file mode 100644
index 0000000..38fc48a
--- /dev/null
+++ b/montool/views/wizards/expiredcerts/wizard-expiredcerts.html
@@ -0,0 +1,163 @@
+<pf-wizard wizard-title="Wizard - Check and fix IPA Certificates"
+           wizard-ready="wizardReady"
+           on-finish="finishedWizard()"
+           on-cancel="cancelDeploymentWizard()"
+           next-title="nextButtonTitle"
+           next-callback="nextCallback"
+           back-callback="backCallback"
+           wizard-done="deployComplete || deployInProgress"
+           sidebar-class="example-wizard-sidebar"
+           step-class="example-wizard-step"
+           loading-secondary-information="secondaryLoadInformation"
+           on-step-changed="stepChanged(step, index)">
+
+    <pf-wizard-step step-title="Checkup" next-tooltip="firstStepNextTooltip" prev-tooltip="firstStepPrevTooltip" 
+                    substeps="true" step-id="details" step-priority="0"
+                    show-review="true" show-review-details="true" allow-click-nav="false">        
+        <div>
+            <pf-wizard-substep step-title="Host"
+                               next-enabled="hostInfoComplete"
+                               step-id="details-host"
+                               step-priority="0"
+                               on-show="hostOnShow"
+                               focus-selectors="hostFocusSelectors"
+                               review-template="{{hostReviewTemplate}}"
+                               show-review-details="true">
+                <form class="form-horizontal">
+                    <label class="radio">
+                        <input type="radio" ng-model="details.hostname" value="defaultHost" 
+                               ng-change="hostUpdateNextButtonState()">
+                        {{data.defaultHost}}
+                        </input>
+                    </label>
+                    <label class="radio">
+                        <input type="radio" ng-model="details.hostname" value="anotherServer"
+                               ng-change="hostUpdateNextButtonState()">
+                        Another Server
+                        </input>                              
+                    </label>          
+                    <pf-form-group pf-label="Host" pf-label-class="col-sm-3 col-md-2" pf-input-class="col-sm-9 col-md-10" required>
+                        <input id="serverName" name="anotherServer" ng-model="data.anotherServer" type="text" 
+                               ng-disabled="details.hostname === 'defaultHost'" ng-change="hostUpdateNextButtonState()" required/>
+                    </pf-form-group>
+                </form>
+            </pf-wizard-substep>
+        </div>
+
+        <!--pf-wizard-substep step-title="Root User Access" next-enabled="rootAccessComplete"-->
+        <pf-wizard-substep step-title="Root User Access" next-enabled="true"
+                           step-id="details-root-access" step-priority="1" show-review="true"
+                           show-review-details="true"
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+
+            <pf-inline-notification pf-notification-type="notificationCommand.type"
+                                    pf-notification-header="notificationCommand.header"
+                                    pf-notification-message="notificationCommand.message"
+                                    pf-notification-persistent="notificationCommand.isPersistent"
+                                    pf-notification-remove="removeNotification()">
+            </pf-inline-notification>
+
+            <!--div class="wizard-pf-process blank-slate-pf" ng-if="!deploymentComplete"-->
+            <div ng-if="!connectionCommandComplete">
+                <div class="spinner spinner-lg blank-slate-pf-icon"></div>
+                <div style="text-align:center">
+                    <b>SSH Connection in progress...</b>
+                </div>
+            </div>
+            <div ng-if="connectionCommandComplete">
+                <pf-inline-notification pf-notification-type="notificationResult.type"
+                                        pf-notification-header="notificationResult.header"
+                                        pf-notification-message="notificationResult.message"
+                                        pf-notification-persistent="notificationResult.isPersistent"
+                                        pf-notification-remove="removeNotification()">
+                </pf-inline-notification>
+            </div>
+
+        </pf-wizard-substep>
+
+        <pf-wizard-substep step-title="Server Details" next-enabled="true" step-id="details-server-info"
+                           step-priority="2" show-review="true" show-review-details="true" 
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+            <div ng-if="!detailsCommandsComplete">
+                <div class="spinner spinner-lg blank-slate-pf-icon"></div>
+                <div style="text-align:center">
+                    <b>Getting Server Details ...</b>
+                </div>
+            </div>
+
+            <div class="col-md-12 list-view-container example-list-view" ng-if="detailsCommandsComplete">
+                <pf-list-view id="detailsListView"
+                              config="detailsAndStatusConfig"
+                              items="detailsItems">
+                    <div class="list-view-pf-description">
+                        <div class="list-group-item-heading">
+                            {{item.command}}
+                        </div>
+                    </div>
+                    <div class="list-view-pf-additional-info">
+                        <div class="list-view-pf-additional-info-item">
+                            {{item.mainOutput}}
+                        </div>                       
+                    </div>
+                    <list-expanded-content>
+                        <div class="col-md-12">
+                            <div>
+                                <li class="list-group-item" ng-repeat="line in $parent.item.additionalOutput">{{line}}</li>
+                            </div>
+                        </div>
+                    </list-expanded-content>
+                </pf-list-view>
+            </div>
+        </pf-wizard-substep>
+
+
+
+
+        <pf-wizard-substep step-title="Server Status" next-enabled="true" step-id="details-server-status"
+                           step-priority="3" show-review="true" show-review-details="true" 
+                           review-template="views/wizards/expiredcerts/review-second-template.html">
+
+            <div ng-if="!statusCommandsComplete">
+                <div class="spinner spinner-lg blank-slate-pf-icon"></div>
+                <div style="text-align:center">
+                    <b>Getting Server Status Information ...</b>
+                </div>
+            </div>
+
+            <div class="col-md-12 list-view-container example-list-view" ng-if="statusCommandsComplete">
+                <pf-list-view id="statusListView"
+                              config="detailsAndStatusConfig"
+                              items="statusItems">
+                    <div class="list-view-pf-left">
+                        <span class="{{item.typeIcon}} list-view-pf-icon-sm"></span>
+                    </div>
+                    <div class="list-view-pf-description">
+                        <div class="list-group-item-heading">
+                            {{item.command}}
+                        </div>
+                    </div>
+                    <div class="list-view-pf-additional-info">
+                        <div class="list-view-pf-additional-info-item">
+                            {{item.mainOutput}}
+                        </div>                       
+                    </div>
+                    <list-expanded-content>
+                        <div class="col-md-12">
+                            <div>                                
+                                <li class="list-group-item" ng-repeat="line in $parent.item.additionalOutput">{{line}}</li>
+                            </div>
+                        </div>
+                    </list-expanded-content>
+                </pf-list-view>
+            </div>
+        </pf-wizard-substep>
+
+    </pf-wizard-step>
+
+    <!--step-priority="1"-->
+    <div ng-include="'views/wizards/expiredcerts/second-step.html'"></div>
+    <!--step-priority="2"-->
+    <div ng-include="'views/wizards/expiredcerts/third-step.html'"></div>
+    <!--step-priority="3"-->
+    <div ng-include="'views/wizards/expiredcerts/final-step.html'"></div>
+</pf-wizard>
\ No newline at end of file
diff --git a/montool/views/wizards/logconv/wizard-logconv.html b/montool/views/wizards/logconv/wizard-logconv.html
new file mode 100644
index 0000000..4009aee
--- /dev/null
+++ b/montool/views/wizards/logconv/wizard-logconv.html
@@ -0,0 +1,131 @@
+<link href="../../css/logconv.css" rel="stylesheet">
+
+<pf-wizard wizard-title="Wizard - Analyze Access Logs of a Directory Server"
+           wizard-ready="logconvWizardReady"
+           on-finish="finishedLogconvWizard()"
+           on-cancel="cancelLogconvWizard()"
+           next-title="nextButtonTitle"
+           next-callback="nextCallback"
+           back-callback="backCallback"
+           wizard-done="logconvComplete"
+           sidebar-class="example-wizard-sidebar"
+           step-class="example-wizard-step"
+           loading-secondary-information="secondaryLoadInformation"
+           on-step-changed="stepChanged(step, index)">
+
+    <pf-wizard-step step-title="Linux User" next-enabled="connectionVerified"
+                    substeps="false" step-id="linux-user" step-priority="0"
+                    show-review="false" show-review-details="false" allow-click-nav="true">        
+        <div>
+            <form class="form-horizontal">
+                <pf-form-group pf-label="Monitored Host"
+                               required pf-label-class="col-sm-3" pf-input-class="col-sm-5">
+                    <input id="host" name="host" ng-model="logconv.monitoredHost"
+                           value="{{logconv.monitoredHost}}" type="text" required disabled/>
+                </pf-form-group>
+                <pf-form-group pf-label="Linux User"
+                               required pf-label-class="col-sm-3" pf-input-class="col-sm-5">
+                    <input id="user" name="user" ng-model="logconv.linuxUser" type="text"
+                           value="{{logconv.linuxUser}}" required/>
+                </pf-form-group>                
+            </form>
+        </div>
+        <div>
+            <pf-inline-notification pf-notification-type="notificationConnection.type"
+                                    pf-notification-header="notificationConnection.header"
+                                    pf-notification-message="notificationConnection.message"
+                                    pf-notification-persistent="notificationConnection.isPersistent">
+            </pf-inline-notification>
+        </div>
+        <div ng-if="!connectionCommandComplete">
+            <div class="spinner spinner-lg blank-slate-pf-icon"></div>
+            <div style="text-align:center">
+                <b>SSH Connection in progress...</b>
+            </div>
+        </div>
+        <div class="col-md-5">
+            <button ng-click="checkConnection()">Check Connection to activate Next Step</button>
+        </div>
+    </pf-wizard-step>
+
+
+    <pf-wizard-step step-title="Logs List"
+                    substeps="false" step-id="logs-list" step-priority="1"
+                    on-show="logsListOnShow"
+                    show-review="false" show-review-details="false" allow-click-nav="true">
+        <div>
+            <pf-inline-notification pf-notification-type="notificationLogsInfo.type"
+                                    pf-notification-header="notificationLogsInfo.header"
+                                    pf-notification-message="notificationLogsInfo.message"
+                                    pf-notification-persistent="notificationLogsInfo.isPersistent">
+            </pf-inline-notification>
+        </div>
+        <div ng-if="!logsListCommandComplete">
+            <div class="spinner spinner-lg blank-slate-pf-icon"></div>
+            <div style="text-align:center">
+                <b>Getting the list of access logs...</b>
+            </div>
+        </div>
+
+        <div  id="list-of-logs" class="row col-md-12">
+            <div id="scrolltest">
+
+                <!--div>
+                    <pf-toolbar id="logconvToolbar" config="logconvToolbarConfig"></pf-toolbar>
+                </div-->
+                <div>
+                    <pf-table-view id="logconvLogsTableView"
+                                   config="logconvLogsConfig"
+                                   columns="logconvLogsColumns"
+                                   items="logconvLogsItems">
+                    </pf-table-view>
+                </div>
+            </div>
+        </div>                
+    </pf-wizard-step>
+
+    <pf-wizard-step step-title="logconv Options"
+                    substeps="false" step-id="options" step-priority="2"
+                    show-review="false" show-review-details="false" allow-click-nav="true">        
+        <div>
+            <pf-table-view id="logconvOptionsTableView"
+                           config="logconvOptionsConfig"
+                           columns="logconvOptionsColumns"
+                           items="logconvOptionsItems">
+            </pf-table-view>
+        </div>
+
+    </pf-wizard-step>
+
+    <pf-wizard-step step-title="Output"
+                    on-show="runLogconvOnShow" next-enabled="logconvCommandComplete"
+                    substeps="false" step-id="output" step-priority="3"
+                    show-review="false" show-review-details="false" allow-click-nav="true">      
+        <div>
+            <pf-inline-notification pf-notification-type="notificationCommand.type"
+                                    pf-notification-header="notificationCommand.header"
+                                    pf-notification-message="notificationCommand.message"
+                                    pf-notification-persistent="notificationCommand.isPersistent"
+                                    pf-notification-remove="removeNotification()">
+            </pf-inline-notification>
+        </div>
+        <div ng-if="!logconvCommandComplete">
+            <div class="spinner spinner-lg blank-slate-pf-icon"></div>
+            <div style="text-align:center">
+                <b>Getting logconv.pl Output...</b>
+            </div>
+        </div>
+        <div ng-if="logconvCommandComplete">
+            <form class="form-horizontal">
+                <!--pf-form-group pf-label="Output" pf-label-class="col-sm-2" pf-input-class="col-sm-12"-->
+                <pf-form-group pf-label="Output" pf-input-class="col-sm-12">
+                    <textarea style="background-color: white; color: black;"
+                              id="output" name="output" ng-model="logconv.output" rows="15" readonly>
+                        {{logconv.output}}
+                    </textarea>
+                </pf-form-group>
+            </form>
+        </div>
+
+    </pf-wizard-step>
+</pf-wizard>
\ No newline at end of file
diff --git a/montool/views/wizards/replication/csn/wizard-csn.html b/montool/views/wizards/replication/csn/wizard-csn.html
new file mode 100644
index 0000000..a19c5dc
--- /dev/null
+++ b/montool/views/wizards/replication/csn/wizard-csn.html
@@ -0,0 +1,82 @@
+<pf-wizard wizard-title="Wizard - Decode Replication CSN"
+           wizard-ready="csnWizardReady"
+           on-finish="finishedCsnWizard()"
+           on-cancel="cancelCsnWizard()"
+           next-title="nextButtonTitle"
+           next-callback="nextCallback"
+           back-callback="backCallback"
+           wizard-done="csnComplete"
+           sidebar-class="example-wizard-sidebar"
+           step-class="example-wizard-step"
+           loading-secondary-information="secondaryLoadInformation"
+           on-step-changed="stepChanged(step, index)">
+
+    <pf-wizard-step step-title="Convert CSN"
+                    substeps="false" step-id="convert-csn" step-priority="0"
+                    show-review="false" show-review-details="false" allow-click-nav="true">    
+
+        <div>
+            <pf-inline-notification pf-notification-type="notificationCsn.type"
+                                    pf-notification-header="notificationCsn.header"
+                                    pf-notification-message="notificationCsn.message"
+                                    pf-notification-persistent="notificationCsn.isPersistent"
+                                    pf-notification-remove="removeCsnNotification()">
+            </pf-inline-notification>
+        </div>
+
+        <!--div class="col-md-12"-->
+        <div>
+            <form name="csnForm">
+                <div class="form-group" pf-input-class="col-sm-5">
+                    <!--label class="control-label col-sm-2"><b>CSN</b></label-->
+                    <!-- Remove the 'required' from the input filed to avoid errors when input is empty.-->                    
+                    <input class="col-sm-5" name="value" ng-model="csn.value" type="text"
+                           placeholder="CSN Value"
+                           pf-remaining-chars-count chars-max-limit="20" block-input-at-max-limit="true"/>
+                </div>
+                <pf-form-buttons pf-on-cancel="clearData()" pf-on-save="addCsn()" pf-working="working"></pf-form-buttons>
+            </form>
+        </div>
+
+        <!--div >
+            <form class="form-horizontal pull-left">
+                <pf-form-group pf-label="CSN" required pf-label-class="col-sm-2" pf-input-class="col-sm-5">
+                    <input id="suffix" name="suffix" ng-model="csn.value" type="text" required
+                           placeholder="CSN Value"
+                           pf-remaining-chars-count chars-max-limit="16" block-input-at-max-limit="true"/>
+
+                </pf-form-group>
+                <pf-form-buttons  pf-on-cancel="cancel()" pf-on-save="save(item)" pf-working="working"></pf-form-buttons>
+            </form>
+        </div-->
+
+        <hr class="col-md-12">
+
+        <div  class="row col-md-12">
+            <div>
+                <pf-toolbar id="cnsToolbar" config="csnToolbarConfig"></pf-toolbar>
+            </div>
+            <div>
+                <pf-table-view id="csnTableView"
+                               config="csnConfig"
+                               columns="csnColumns"
+                               items="csnItems">
+                </pf-table-view>
+            </div>
+        </div>
+        
+    </pf-wizard-step>
+
+    <pf-wizard-step step-title="Text View"
+                    substeps="false" step-id="text-view" step-priority="1"
+                    show-review="false" show-review-details="false" allow-click-nav="true">        
+        <div>
+            <textarea class="col-md-12" style="background-color: white; color: black;"
+                      id="textView" name="output" ng-model="csn.textView" rows="15" readonly>
+                {{csn.textView}}
+            </textarea>
+        </div>
+
+    </pf-wizard-step>
+
+</pf-wizard>
\ No newline at end of file
diff --git a/montool/views/wizards/replication/replcheck/wizard-replcheck.html b/montool/views/wizards/replication/replcheck/wizard-replcheck.html
new file mode 100644
index 0000000..783c204
--- /dev/null
+++ b/montool/views/wizards/replication/replcheck/wizard-replcheck.html
@@ -0,0 +1,103 @@
+<pf-wizard wizard-title="Wizard - Check Replication Status between two Databases"
+           wizard-ready="replCheckWizardReady"
+           on-finish="finishedReplCheckWizard()"
+           on-cancel="cancelReplCheckWizard()"
+           next-title="nextButtonTitle"
+           next-callback="nextCallback"
+           back-callback="backCallback"
+           wizard-done="replCheckComplete"
+           sidebar-class="example-wizard-sidebar"
+           step-class="example-wizard-step"
+           loading-secondary-information="secondaryLoadInformation"
+           on-step-changed="stepChanged(step, index)">
+
+    <pf-wizard-step step-title="LDAP URLs"
+                    substeps="false" step-id="ldap-urls" step-priority="0"
+                    show-review="false" show-review-details="false" allow-click-nav="true">        
+        <div>
+            <form class="form-horizontal">
+                <pf-form-group pf-label="Supplier &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+                               &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{replcheck.supplierConnType}}://"
+                               required pf-label-class="col-sm-3" pf-input-class="col-sm-5">
+                    <input id="supplier" name="supplier" ng-model="replcheck.supplier" type="text" required/>
+                </pf-form-group>
+                <pf-form-group pf-label="Replica &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+                               &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{replcheck.replicaConnType}}://"
+                               required pf-label-class="col-sm-3" pf-input-class="col-sm-5">
+                    <input id="replica" name="replica" ng-model="replcheck.replica" type="text" value="{{replcheck.supplierConnType}}://" required/>
+                </pf-form-group>
+                <div class="form-group">
+                    <label for="connection" class="col-sm-2 col-md-2 control-label" >Connection</label>
+                    <div class="col-sm-10 col-md-10">
+                        <select pf-bootstrap-select ng-model="replcheck.connection" id="connection" ng-change="handleConnectionType()">
+                            <option value="clear"  ng-selected="true" selected>Unprotected connection (LDAP)</option>
+                            <option value="TLS">TLS encryption (LDAPS)</option>
+                            <option value="startTLS">StartTLS over LDAP</option>
+                            <option value="LDAPI">LDAP over IPC (LDAPI)</option>
+                        </select>  
+                    </div>
+                </div>
+            </form>
+        </div>
+    </pf-wizard-step>
+
+    <pf-wizard-step step-title="Bind User Credentials"
+                    substeps="false" step-id="bind-user" step-priority="1"
+                    show-review="false" show-review-details="false" allow-click-nav="true">        
+        <div>
+            <form class="form-horizontal">
+                <pf-form-group pf-label="Bind DN" required pf-label-class="col-sm-2" pf-input-class="col-sm-5">
+                    <input id="binddn" name="binddn" ng-model="replcheck.binddn" type="text" required/>
+                </pf-form-group>
+                <pf-form-group pf-label="Password" required pf-label-class="col-sm-2" pf-input-class="col-sm-5">
+                    <input id="password" name="password" ng-model="replcheck.password" type="password" required/>
+                </pf-form-group>                
+            </form>
+
+        </div>
+
+    </pf-wizard-step>
+    <pf-wizard-step step-title="LDAP Suffix"
+                    substeps="false" step-id="suffix" step-priority="2"
+                    show-review="false" show-review-details="false" allow-click-nav="true">        
+        <div>
+            <form class="form-horizontal">
+                <pf-form-group pf-label="Suffix" required pf-label-class="col-sm-2" pf-input-class="col-sm-8">
+                    <input id="suffix" name="suffix" ng-model="replcheck.suffix" type="text" required/>
+                </pf-form-group>
+            </form>
+        </div>
+
+    </pf-wizard-step>
+
+    <pf-wizard-step step-title="Output"
+                    substeps="false" step-id="output" step-priority="3"
+                    show-review="false" show-review-details="false" allow-click-nav="true">      
+        <div>
+            <pf-inline-notification pf-notification-type="notificationCommand.type"
+                                    pf-notification-header="notificationCommand.header"
+                                    pf-notification-message="notificationCommand.message"
+                                    pf-notification-persistent="notificationCommand.isPersistent"
+                                    pf-notification-remove="removeNotification()">
+            </pf-inline-notification>
+        </div>
+        <div ng-if="!replCheckComplete">
+                <div class="spinner spinner-lg blank-slate-pf-icon"></div>
+                <div style="text-align:center">
+                    <b>Getting ds-replcheck Output...</b>
+                </div>
+            </div>
+        <div ng-if="replCheckComplete">
+            <form class="form-horizontal">
+                <!--pf-form-group pf-label="Output" pf-label-class="col-sm-2" pf-input-class="col-sm-12"-->
+                <pf-form-group pf-label="Output" pf-input-class="col-sm-12">
+                    <textarea style="background-color: white; color: black;"
+                              id="output" name="output" ng-model="replcheck.output" rows="15" readonly>
+                        {{replcheck.output}}
+                    </textarea>
+                </pf-form-group>
+            </form>
+        </div>
+
+    </pf-wizard-step>
+</pf-wizard>
\ No newline at end of file

