diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 6c376be7f..9e88dd884 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -387,8 +387,8 @@ CREATE TABLE `Monitors` ( -- -- Table structure for table `States` --- Added IsActive to track custom run states --- +-- PP - Added IsActive to track custom run states +-- Also made sure Name is unique DROP TABLE IF EXISTS `States`; CREATE TABLE `States` ( @@ -396,8 +396,11 @@ CREATE TABLE `States` ( `Name` varchar(64) NOT NULL default '', `Definition` text NOT NULL, `IsActive` tinyint(3) unsigned NOT NULL default '0', - PRIMARY KEY (`Id`) + PRIMARY KEY (`Id`), + UNIQUE KEY (`Name`) ) ENGINE=@ZM_MYSQL_ENGINE@; +INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1'); + -- -- Table structure for table `Servers` diff --git a/db/zm_update-1.28.99.sql b/db/zm_update-1.28.99.sql index 3ddd0c77d..6e1313ba3 100644 --- a/db/zm_update-1.28.99.sql +++ b/db/zm_update-1.28.99.sql @@ -342,7 +342,7 @@ SET @s = (SELECT IF( PREPARE stmt FROM @s; EXECUTE stmt; --- The States table will be updated to have a new column called IsActive +-- PP:The States table will be updated to have a new column called IsActive -- used to keep track of which custom state is active (if any) SET @s = (SELECT IF( (SELECT COUNT(*) @@ -358,6 +358,23 @@ SET @s = (SELECT IF( PREPARE stmt FROM @s; EXECUTE stmt; +-- PP:If default state does not exist, create it and set its IsActive to 1 +INSERT INTO States (Name,Definition,IsActive) + SELECT * FROM (SELECT 'default', '', '1') AS tmp + WHERE NOT EXISTS ( + SELECT Name FROM States WHERE Name = 'default' + ) LIMIT 1; + +-- PP:Start with a sane isActive state +UPDATE States SET IsActive = '0'; +UPDATE States SET IsActive = '1' WHERE Name = 'default'; + +-- PP:Finally convert States to make sure Names are unique +-- If duplicate states existed while upgrading, that is +-- very likely an error that ZM allowed earlier, so +-- we are picking up the first one and deleting the others +ALTER IGNORE TABLE States ADD UNIQUE (Name); + SET @s = (SELECT IF( (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES diff --git a/scripts/zmpkg.pl.in b/scripts/zmpkg.pl.in index 46ea825c4..8170d534c 100644 --- a/scripts/zmpkg.pl.in +++ b/scripts/zmpkg.pl.in @@ -105,6 +105,8 @@ if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ ) } } $dbh = zmDbConnect() if ! $dbh; +# PP - Sane state check +isActiveSanityCheck(); # Move to the right place chdir( $Config{ZM_PATH_WEB} ) @@ -151,19 +153,17 @@ if ( $command eq "state" ) } } $sth->finish(); - #PP - lets go ahead and modify States DB - - Debug ("Marking $store_state as Enabled"); - # PP - Zero out other states being active - resetStates(); # PP - Now mark a specific state as active + resetStates(); + Info ("Marking $store_state as Enabled"); $sql = "update States set IsActive = '1' where Name = ?"; $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); $res = $sth->execute( $store_state ) or Fatal( "Can't execute: ".$sth->errstr() ); + # PP - zero out other states isActive $command = "restart"; } @@ -173,8 +173,6 @@ if ( $command =~ /^(start|stop|restart)$/ ) # We have to detaint to keep perl from complaining $command = $1; - # PP - if we are not switching to a custom state, zero out all isActive - resetStates() if (!$store_state); if ( systemdRunning() && !calledBysystem() ) { qx(@BINDIR@/zmsystemctl.pl $command); @@ -307,15 +305,66 @@ if ( $command eq "logrot" ) exit( $retval ); -# PP - when the system is restarted/started/stopped, it will -# not be in a custom state, so lets keep the DB consistent +# PP - Make sure isActive is on and only one +sub isActiveSanityCheck +{ + + Info ("Sanity checking States table..."); + $dbh = zmDbConnect() if ! $dbh; + + # PP - First, make sure default exists and there is only one + my $sql = "select Name from States where Name = 'default'"; + my $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() + or Fatal( "Can't execute: ".$sth->errstr() ); + + if ($sth->rows != 1) # PP - no row, or too many rows. Either case is an error + { + Info( "Fixing States table - either no default state or duplicate default states" ); + $sql = "delete from States where Name = 'default'"; + $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute() + or Fatal( "Can't execute: ".$sth->errstr() ); + $sql = "insert into States (Name,Definition,IsActive) VALUES ('default','','1');"; + $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute() + or Fatal( "Can't execute: ".$sth->errstr() ); + } + + + # PP - Now make sure no two states have IsActive=1 + $sql = "select Name from States where IsActive = '1'"; + $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute() + or Fatal( "Can't execute: ".$sth->errstr() ); + + if ( $sth->rows != 1 ) + { + Info( "Fixing States table so only one run state is active" ); + resetStates(); + $sql = "update States set IsActive='1' WHERE Name='default'"; + $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute() + or Fatal( "Can't execute: ".$sth->errstr() ); + + + } +} + + +# PP - zeroes out isActive for all states sub resetStates { $dbh = zmDbConnect() if ! $dbh; my $sql = "update States set IsActive = '0'"; my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute() + my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); } diff --git a/web/skins/classic/views/js/state.js b/web/skins/classic/views/js/state.js index 42750580e..9935eb0db 100644 --- a/web/skins/classic/views/js/state.js +++ b/web/skins/classic/views/js/state.js @@ -1,5 +1,6 @@ function checkState( element ) { + var form = element.form; var minIndex = running?2:1; @@ -13,13 +14,24 @@ function checkState( element ) form.saveBtn.disabled = false; form.deleteBtn.disabled = false; } + if ( form.newState.value != '' ) form.saveBtn.disabled = false; + + // PP if we are in 'default' state, disable delete + // you can still save + if (element.value.toLowerCase() == 'default' ) + { + form.saveBtn.disabled = false; + form.deleteBtn.disabled = true; + } + } function saveState( element ) { var form = element.form; + form.view.value = currentView; form.action.value = 'save'; form.submit(); diff --git a/web/skins/classic/views/state.php b/web/skins/classic/views/state.php index 84ffb954d..e55e4e234 100644 --- a/web/skins/classic/views/state.php +++ b/web/skins/classic/views/state.php @@ -26,7 +26,6 @@ if ( !canEdit( 'System' ) ) $running = daemonCheck(); $states = dbFetchAll( "select * from States" ); - $focusWindow = true; xhtmlHeaders(__FILE__, translate('RunState') ); @@ -76,14 +75,16 @@ if ( empty($_REQUEST['apply']) )