svn commit: r1028304 - /incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
Author: arkurth Date: Thu Oct 28 14:12:16 2010 New Revision: 1028304 URL: http://svn.apache.org/viewvc?rev=1028304&view=rev Log: VCL-411 Added calls to Windows.pm::post_load and clean_hard_drive to delete the VCL*cmd logon and logoff scripts if they exist. Added call to remove_group_policy_script to delete the file that was specified. Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm?rev=1028304&r1=1028303&r2=1028304&view=diff == --- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original) +++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Thu Oct 28 14:12:16 2010 @@ -751,6 +751,17 @@ sub post_load { =item * + Delete legacy VCL logon/logoff scripts + +=cut + + my $system32_path = $self->get_system32_path(); + if (!$self->delete_files_by_pattern("$system32_path/GroupPolicy/User/Scripts", ".*VCL.*cmd", 2)) { + notify($ERRORS{'WARNING'}, 0, "failed to delete legacy VCL logon and logoff scripts"); + } + +=item * + Check if the imagemeta postoption is set to reboot, reboot if necessary =cut @@ -5441,7 +5452,7 @@ sub delete_capture_configuration_files { # Delete VCL scheduled task if it exists $self->delete_scheduled_task('VCL Startup Configuration'); - ## Remove VCLprepare.cmd and VCLcleanup.cmd lines from scripts.ini file + # Remove VCLprepare.cmd and VCLcleanup.cmd lines from scripts.ini file $self->remove_group_policy_script('logon', 'VCLprepare.cmd'); $self->remove_group_policy_script('logoff', 'VCLcleanup.cmd'); @@ -5753,6 +5764,9 @@ sub remove_group_policy_script { else { $opposite_stage_argument = 'Logon'; } + + # Attempt to delete batch or script files specified by the argument + $self->delete_files_by_pattern("$system32_path/GroupPolicy/User/Scripts", ".*$cmdline_argument.*", 2); # Path to scripts.ini file my $scripts_ini = $system32_path . '/GroupPolicy/User/Scripts/scripts.ini'; @@ -6283,8 +6297,9 @@ sub clean_hard_drive { '$SYSTEMDRIVE/Documents and Settings,.*Temporary Internet Files\\/Content.*\\/.*,10', '$SYSTEMDRIVE,.*pagefile\\.sys,1', '$SYSTEMDRIVE/cygwin/home/root,.*%USERPROFILE%,1', + "$system32_path/GroupPolicy/User/Scripts,.*VCL.*cmd" ); - + # Attempt to stop the AFS service, needed to delete AFS files if ($self->service_exists('TransarcAFSDaemon')) { $self->stop_service('TransarcAFSDaemon');
svn commit: r1028312 - /incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
Author: arkurth Date: Thu Oct 28 14:23:16 2010 New Revision: 1028312 URL: http://svn.apache.org/viewvc?rev=1028312&view=rev Log: VCL-411 Added call to Windows.pm::reserve to delete the VCL*cmd logon and logoff scripts if they exist. This allows images already loaded to be fixed if affected with this problem. Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm?rev=1028312&r1=1028311&r2=1028312&view=diff == --- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original) +++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Thu Oct 28 14:23:16 2010 @@ -751,17 +751,6 @@ sub post_load { =item * - Delete legacy VCL logon/logoff scripts - -=cut - - my $system32_path = $self->get_system32_path(); - if (!$self->delete_files_by_pattern("$system32_path/GroupPolicy/User/Scripts", ".*VCL.*cmd", 2)) { - notify($ERRORS{'WARNING'}, 0, "failed to delete legacy VCL logon and logoff scripts"); - } - -=item * - Check if the imagemeta postoption is set to reboot, reboot if necessary =cut @@ -883,6 +872,7 @@ sub grant_access { my $management_node_keys = $self->data->get_management_node_keys(); my $computer_node_name = $self->data->get_computer_node_name(); + my $system32_path= $self->get_system32_path(); my $remote_ip= $self->data->get_reservation_remote_ip(); my $multiple_users = $self->data->get_imagemeta_usergroupmembercount(); my $request_forimaging = $self->data->get_request_forimaging(); @@ -927,6 +917,11 @@ sub grant_access { return 0; } } ## end if ($request_forimaging) + + # Delete legacy VCL logon/logoff scripts + if (!$self->delete_files_by_pattern("$system32_path/GroupPolicy/User/Scripts", ".*VCL.*cmd", 2)) { + notify($ERRORS{'WARNING'}, 0, "failed to delete legacy VCL logon and logoff scripts"); + } notify($ERRORS{'OK'}, 0, "access has been granted for reservation on $computer_node_name"); return 1;
svn commit: r1028338 - in /incubator/vcl/trunk/web: .ht-inc/images.php .ht-inc/managementnodes.php .ht-inc/privileges.php .ht-inc/utils.php js/images.js
Author: jfthomps Date: Thu Oct 28 14:54:17 2010 New Revision: 1028338 URL: http://svn.apache.org/viewvc?rev=1028338&view=rev Log: VCL-401 add manageMapping resource attribute to control resource mapping utils.php: added getResourcePrivs managementnodes.php: -modified these functions to look at manageMapping attribute instead of manageGroup for mapping privileges: -selectMgmtnodeOption, viewMgmtnodeMapping, submitMgmtnodeMapping images.php: -modified these functions to look at manageMapping attribute instead of manageGroup for mapping privileges: -selectImageOption, viewImageMapping, imageMappingGrid, submitImageMapping, jsonImageMapCompGroups, jsonImageMapImgGroups, AJaddCompGrpToImgGrp, AJremCompGrpFromImgGrp, AJaddImgGrpToCompGrp, and AJremImgGrpFromCompGrp -converted all references to json-comment-filtered to just json and to use sendJSON function privileges.php: -modified viewNodes: -instead of hardcoding resource types, call getResourcePrivs to get them -call getResourcePrivRowHTML instead of printResourcePrivRow and then print the returned HTML and JS -for add resource dialog, loop through resource privs to print checkboxes instead of printing them all directly -modified selectNode: -instead of hardcoding resource types, call getResourcePrivs to get them -due to combining printResourcePrivRow and getResourcePrivRowHTML, needed to add a few str_replace's to prepare html for sending in ajax response -combined printResourcePrivRow and getResourcePrivRowHTML -modified getResourcePrivRowHTML: -added newlines -added manageMapping to checkboxes that don't get printed if don't have proper rights -added check to not print available checkbox for schedule and management node groups -added check to not print manageMapping for schedule groups -removed preg_replace for single quote; moved replacing them to selectNode -modified AJsubmitAddResoucePriv to get resource types from getResourcePrivs instead of hard coding them js/images.js: converted all references to json-comment-filtered to just json Modified: incubator/vcl/trunk/web/.ht-inc/images.php incubator/vcl/trunk/web/.ht-inc/managementnodes.php incubator/vcl/trunk/web/.ht-inc/privileges.php incubator/vcl/trunk/web/.ht-inc/utils.php incubator/vcl/trunk/web/js/images.js Modified: incubator/vcl/trunk/web/.ht-inc/images.php URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/images.php?rev=1028338&r1=1028337&r2=1028338&view=diff == --- incubator/vcl/trunk/web/.ht-inc/images.php (original) +++ incubator/vcl/trunk/web/.ht-inc/images.php Thu Oct 28 14:54:17 2010 @@ -60,9 +60,11 @@ function selectImageOption() { $tmp = getUserResources(array("imageAdmin"), array("manageGroup"), 1); $imgGroupCnt = count($tmp['image']); - # get a count of computer groups user can manage - $tmp = getUserResources(array("computerAdmin"), array("manageGroup"), 1); - $compGroupCnt = count($tmp['computer']); + # get a count of image groups and computer groups user can map + $tmp = getUserResources(array("imageAdmin"), array("manageMapping"), 1); + $imgMapCnt = count($tmp['image']); + $tmp = getUserResources(array("computerAdmin"), array("manageMapping"), 1); + $compMapCnt = count($tmp['computer']); print "Manage Images\n"; print "\n"; @@ -78,12 +80,12 @@ function selectImageOption() { $cont = addContinuationsEntry('viewImageGrouping'); print "Edit "; print "Image Grouping\n"; + } - if($compGroupCnt) { - $cont = addContinuationsEntry('viewImageMapping'); - print "Edit "; - print "Image Mapping\n"; - } + if($imgMapCnt && $compMapCnt) { + $cont = addContinuationsEntry('viewImageMapping'); + print "Edit "; + print "Image Mapping\n"; } if($imgCnt) { @@ -448,12 +450,12 @@ function imageGroupingGrid() { function viewImageMapping() { global $mode; $tmp = getUserResources(array("imageAdmin"), - array("manageGroup"), 1); + array("manageMapping"), 1); $imagegroups = $tmp["image"]; uasort($imagegroups, "sortKeepIndex"); $imagecompmapping = getResourceMapping("image", "computer"); $resources = getUserResources(array("computerAdmin"), - array("manageGroup"), 1); + array("manageMapping"), 1); $compgroups = $resources["computer"]; uasort($compgroups, "sortKeepIndex"); if(! count($imagegroups) || ! count($compgroups)) { @@ -535,10 +537,7 @@ function viewImageMapping() { print "button to map it to that group.\n"; print "Computer Group:\n"; #
svn commit: r1028387 - /incubator/vcl/trunk/web/.ht-inc/requests.php
Author: jfthomps Date: Thu Oct 28 17:09:32 2010 New Revision: 1028387 URL: http://svn.apache.org/viewvc?rev=1028387&view=rev Log: VCL-412 clicking on tomaintenance reload reservation in timetable gives an error modified viewRequestInfo - set $reservation to $request['reservations'][0] if request stateid or laststateid = 18 Modified: incubator/vcl/trunk/web/.ht-inc/requests.php Modified: incubator/vcl/trunk/web/.ht-inc/requests.php URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/requests.php?rev=1028387&r1=1028386&r2=1028387&view=diff == --- incubator/vcl/trunk/web/.ht-inc/requests.php (original) +++ incubator/vcl/trunk/web/.ht-inc/requests.php Thu Oct 28 17:09:32 2010 @@ -1235,7 +1235,7 @@ function detailStatusHTML($reqid) { function viewRequestInfo() { $requestid = getContinuationVar("requestid"); $request = getRequestInfo($requestid); - if($request['forimaging']) + if($request['forimaging'] || $request['stateid'] == 18 || $request['laststateid'] == 18) $reservation = $request['reservations'][0]; else { foreach($request["reservations"] as $res) {
svn commit: r1028392 - in /incubator/vcl/trunk/managementnode/lib/VCL: DataStructure.pm Module.pm Module/OS.pm Module/Provisioning.pm Module/State.pm utils.pm
Author: arkurth Date: Thu Oct 28 17:17:54 2010 New Revision: 1028392 URL: http://svn.apache.org/viewvc?rev=1028392&view=rev Log: VCL-394 Updated core modules to allow a DataStructure and provisioning object to be created without a corresponding reservation. This allows provisioning modules to implement a node_status which can be called as a regular non-object function, while the node_status subroutine uses the DataStructure and other object-oriented functions in the same manner as normal reservations. Updated DataStructure.pm to allow objects to be created by passing an imagerevision ID. Updated this module to populate the image and imagerevision data if it was passed an image, imagerevision, or computer ID argument. Moved subroutines from set_os and os subroutines from Provisioning.pm to Module.pm. Moved set_provisioner and provisioner subroutines to Module.pm. This allows them to be available to all types of modules. Added Module.pm::create_provisioning_object and create_os_object. These are called by State.pm::initialize rather than having the code directly in State.pm::initialize. This allows other objects to create an OS or provisioning object if necessary. Other Updated DataStructure.pm::get_reservation_info_string to display additional data. Removed utils.pm::getdynamicaddress. It has been replaced by code in the OS modules. Updated utils.pm::get_computer_info to add the VM host data under the 'computer' key in the hash it returns. This allows the data it returns to match get_request_info. Modified: incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm incubator/vcl/trunk/managementnode/lib/VCL/Module.pm incubator/vcl/trunk/managementnode/lib/VCL/Module/OS.pm incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning.pm incubator/vcl/trunk/managementnode/lib/VCL/Module/State.pm incubator/vcl/trunk/managementnode/lib/VCL/utils.pm Modified: incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm?rev=1028392&r1=1028391&r2=1028392&view=diff == --- incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm (original) +++ incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm Thu Oct 28 17:17:54 2010 @@ -489,7 +489,7 @@ $SUBROUTINE_MAPPINGS{management_node_pre =cut -my @request_id : Field : Arg('Name' => 'request_id') : Type(scalar) : Get('Name' => 'request_id', 'Private' => 1); +my @request_id : Field : Arg('Name' => 'request_id', 'Default' => 0) : Type(scalar) : Get('Name' => 'request_id', 'Private' => 1); =head3 @reservation_id @@ -498,7 +498,7 @@ my @request_id : Field : Arg('Name' => ' =cut -my @reservation_id : Field : Arg('Name' => 'reservation_id') : Type(scalar) : Get('Name' => 'reservation_id', 'Private' => 1); +my @reservation_id : Field : Arg('Name' => 'reservation_id', 'Default' => 0) : Type(scalar) : Get('Name' => 'reservation_id', 'Private' => 1); =head3 @blockrequest_id @@ -555,6 +555,15 @@ my @computer_id : Field : Arg('Name' => my @image_id : Field : Arg('Name' => 'image_id') : Type(scalar) : Get('Name' => 'image_id', 'Private' => 1); +=head3 @imagerevision_id + + Data type : array of scalars + Description : + +=cut + +my @imagerevision_id : Field : Arg('Name' => 'imagerevision_id') : Type(scalar) : Get('Name' => 'imagerevision_id', 'Private' => 1); + ## =head1 PRIVATE OBJECT METHODS @@ -587,15 +596,27 @@ sub _initialize : Init { # If not deep copied, the separate objects will alter each other's data $self->refresh_request_data(dclone($self->request_data)) if $self->request_data; + # Set the request and reservation IDs in the request data hash if they are undefined + $self->request_data->{id} = ($self->request_id || 0) if (!defined($self->request_data->{id})); + $self->request_data->{RESERVATIONID} = ($self->reservation_id || 0) if (!defined($self->request_data->{RESERVATIONID})); + + my $computer_id = $self->computer_id; + my $image_id = $self->image_id; + my $imagerevision_id = $self->imagerevision_id; + # Get the computer info if the computer_id argument was specified and add it to this object - if ($self->computer_id) { - my $vmhost_info_save = $self->request_data->{reservation}{$self->reservation_id}{computer}{vmhost}; + if ($computer_id) { + my $vmhost_info_save; + if (defined($self->request_data->{reservation}{$self->reservation_id}{computer}{vmhost})) { + $vmhost_info_save = $self->request_data->{reservation}{$self->reservation_id}{computer}{vmhost}; + } notify($ERRORS{'DEBUG'}, 0, "computer ID argument was speci
svn commit: r1028403 [2/2] - in /incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware: VIM_SSH.pm VMware.pm vSphere_SDK.pm
Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm?rev=1028403&r1=1028402&r2=1028403&view=diff == --- incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm (original) +++ incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm Thu Oct 28 18:00:57 2010 @@ -394,7 +394,7 @@ sub get_vm_power_state { -physical compatibility mode (pass-through) raw disk mapping -passes SCSI commands directly to the hardware -cannot participate in snapshots - -sparse2Gb + -sparse2Gb, 2Gbsparse -sparse disk with 2GB maximum extent size -can be used with other VMware products -2GB extent size makes these disks easier to burn to dvd or use on filesystems that don't support large files @@ -447,6 +447,19 @@ sub copy_virtual_disk { # Get the adapter type and disk type arguments if they were specified # If not specified, set the default values my $destination_disk_type = shift || 'thin'; + + # Fix the disk type in case 2gbsparse was passed + if ($destination_disk_type =~ /2gbsparse/i) { + $destination_disk_type = 'sparse2Gb'; + } + + # Check the disk type argument, the string must match exactly or the copy will fail + my @valid_disk_types = qw( eagerZeroedThick flatMonolithic preallocated raw rdm rdmp sparse2Gb sparseMonolithic thick thick2Gb thin ); + if (!grep(/^$destination_disk_type$/, @valid_disk_types)) { + notify($ERRORS{'WARNING'}, 0, "disk type argument is not valid: '$destination_disk_type', it must exactly match (case sensitive) one of the following strings:\n" . join("\n", @valid_disk_types)); + return; + } + my $destination_adapter_type = shift; # If the adapter type was not specified, retrieve it from the source vmdk file @@ -465,13 +478,6 @@ sub copy_virtual_disk { return; } - # Check the disk type argument, the string must match exactly or the copy will fail - my @valid_disk_types = qw( eagerZeroedThick flatMonolithic preallocated raw rdm rdmp sparse2Gb sparseMonolithic thick thick2Gb thin ); - if (!grep(/^$destination_disk_type$/, @valid_disk_types)) { - notify($ERRORS{'WARNING'}, 0, "disk type argument is not valid: '$destination_disk_type', it must exactly match (case sensitive) one of the following strings:\n" . join("\n", @valid_disk_types)); - return; - } - # Get a virtual disk manager object my $service_content = Vim::get_service_content() || return; if (!$service_content->{virtualDiskManager}) { @@ -490,7 +496,7 @@ sub copy_virtual_disk { ); # Get the source vmdk file info so the source adapter and disk type can be displayed - my $source_info = $self->get_file_info($source_path) || return; + my $source_info = $self->_get_file_info($source_path) || return; notify($ERRORS{'DEBUG'}, 0, "source file info:\n" . format_data($source_info)); my @file_names = keys(%{$source_info}); my $info_file_name = $file_names[0]; @@ -590,7 +596,7 @@ sub move_virtual_disk { # Create a datacenter object my $datacenter = Vim::find_entity_view(view_type => 'Datacenter'); - if (!$virtual_disk_manager) { + if (!$datacenter) { notify($ERRORS{'WARNING'}, 0, "failed to create vSphere SDK datacenter object"); return; } @@ -610,7 +616,7 @@ sub move_virtual_disk { # Check if an error occurred if (my $fault = $@) { # Get the source file info - my $source_file_info = $self->get_file_info($source_path)->{$source_path}; + my $source_file_info = $self->_get_file_info($source_path)->{$source_path}; # A FileNotFound fault will be generated if the source vmdk file exists but there is a problem with it if ($fault->isa('SoapFault') && ref($fault->detail) eq 'FileNotFound' && defined($source_file_info->{type}) && $source_file_info->{type} !~ /vmdisk/i) { @@ -632,6 +638,36 @@ sub move_virtual_disk { #/ +=head2 set_file_permissions + + Parameters : + Returns : boolean + Description : + +=cut + +sub set_file_permissions { + my $self = shift; + if (ref($self) !~ /VCL::Module/i) { + notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method
svn commit: r1028405 - /incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm
Author: arkurth Date: Thu Oct 28 18:03:55 2010 New Revision: 1028405 URL: http://svn.apache.org/viewvc?rev=1028405&view=rev Log: VCL-413 Added ManagementNode.pm. It is not yet functional. It will eventually allow the management node's Linux OS to be controlled using the code in Linux.pm. Added: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm (with props) Added: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm?rev=1028405&view=auto == --- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm (added) +++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm Thu Oct 28 18:03:55 2010 @@ -0,0 +1,174 @@ +#!/usr/bin/perl -w +### +# $Id$ +### +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +### + +=head1 NAME + +VCL::Module::OS::Linux::ManagementNode.pm + +=head1 SYNOPSIS + + Needs to be written + +=head1 DESCRIPTION + + This module provides VCL support for the management node's Linux operating + system. + +=cut + +## +package VCL::Module::OS::Linux::ManagementNode; + +# Specify the lib path using FindBin +use FindBin; +use lib "$FindBin::Bin/../../../.."; + +# Configure inheritance +use base qw(VCL::Module::OS::Linux); + +# Specify the version of this module +our $VERSION = '2.00'; + +# Specify the version of Perl to use +use 5.008000; + +use strict; +use warnings; +use diagnostics; + +use VCL::utils; + +## + +=head1 OBJECT METHODS + +=cut + +#/ + +=head2 initialize + + Parameters : + Returns : + Description : + +=cut + +sub initialize { + my $self = shift; + unless (ref($self) && $self->isa('VCL::Module')) { + notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called as an object method"); + return; + } + + my $management_node_hostname = $self->data->get_management_node_hostname() || return; + my $management_node_short_name = $self->data->get_management_node_short_name() || return; + my $management_node_ip_address = $self->data->get_management_node_ipaddress() || return; + + $self->data->set_computer_hostname($management_node_hostname); + $self->data->set_computer_node_name($management_node_short_name); + $self->data->set_computer_short_name($management_node_short_name); + $self->data->set_computer_ip_address($management_node_ip_address); + + #print "\n\n" . format_data($self->data->get_request_data()) . "\n\n"; + return 1; +} + +#/ + +=head2 execute + + Parameters : $command, $display_output (optional) + Returns : array + Description : + +=cut + +sub execute { + my $self = shift; + unless (ref($self) && $self->isa('VCL::Module')) { + notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called as an object method"); + return; + } + + # Get the command argument + my $command = shift; + if (!$command) { + notify($ERRORS{'WARNING'}, 0, "command argument was not specified"); + return; + } + + # Get 2nd display output argument if supplied, or set default value + my $display_output = shift || '0'; + + + # Run the command + my ($exit_status, $output) = run_command($command, $display_output); + if (defined($exit_status) && defined($output)) { + if ($display_output) { + notify($ERRORS{'OK'}, 0, "executed command: '$command', exit s