The previous post discussed managing - (creating, updating and deleting) the server entities; we are now at the business end - the monitoring of the server status - which can be migrated to Symfony.
The first area to be covered is the access by command line.
The server status is designed to be updated regularly using a cron task. Which requires a command line interface (CLI).
*/5 * * * * /usr/bin/php /home/phpservermon/webserver/cron/status.cron.php > /var/log/servermon.log 2>&1
The original phpservermon class - status.cron.php is a standard php script application that:
- Includes config.php
- Queries the database for active servers
- Creates a new updater class
- Loops through each of the servers
- Assigns the server details and current status to the updater class.
- Calls the updater getStatus() method to get the current status.
- Calls the updater notify() method to handle (i.e. send required notifications) of the current status
- Save the status to the database.
Command Class
This post covers the creation of the updater class and the evocation from the command line.
The symfony console component is used, this post documents the setup and use - in the Acme Demo bundle, in particular
Command class.
class UpdateCommand extends Command
{
protected function configure()
{
$this
->setName('servermon:update')
->setDescription('Update server status')
->addArgument(
'serverLabel',
InputArgument::OPTIONAL,
'Which server to update?'
)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->container = $this->getApplication()->getKernel()->getContainer();
$serverLabel= $input->getArgument('serverLabel');
$serverUpdate = $this->container = $this->getApplication()->getKernel()->getContainer()->get('server_update');
$serverUpdate->update($serverLabel);
}
}
This is similar to the hello world example - where it takes one optional argument - the server label. It does instantiate a serverUpdate class and calls with any argument (if supplied).
When run from the command line you see:
As suggested in the Symfony documentation the command class does little other than check the arguments and calls a dedicated class to perform the task. This is useful as the server update task can also be called from a controller.
Note: the optional argument - the srervername is an addition to the phpservermon original code, I added it when writing the previous post and have kept it as it is useful for testing.
resources/config/services.yml
services:
server_update:
class: JMPR\ServerMonBundle\Update\ServerUpdate
arguments: [ @doctrine.orm.entity_manager ]
Command class.
class UpdateCommand extends Command
{
protected function configure()
{
$this
->setName('servermon:update')
->setDescription('Update server status')
->addArgument(
'serverLabel',
InputArgument::OPTIONAL,
'Which server to update?'
)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->container = $this->getApplication()->getKernel()->getContainer();
$serverLabel= $input->getArgument('serverLabel');
$serverUpdate = $this->container = $this->getApplication()->getKernel()->getContainer()->get('server_update');
$serverUpdate->update($serverLabel);
}
}
This is similar to the hello world example - where it takes one optional argument - the server label. It does instantiate a serverUpdate class and calls with any argument (if supplied).
When run from the command line you see:
$ app/console --list
Symfony version 2.1.8-DEV - app/dev/debug
...
servermon
servermon: update Update server status
It is located in a subfolder called Command in the bundle, and the class - ends with Command....
servermon
servermon: update Update server status
As suggested in the Symfony documentation the command class does little other than check the arguments and calls a dedicated class to perform the task. This is useful as the server update task can also be called from a controller.
Note: the optional argument - the srervername is an addition to the phpservermon original code, I added it when writing the previous post and have kept it as it is useful for testing.
Update (Service) Class.
The Update class - is a perfect candidate for a Symfony service. It needs a connection to the ORM, which is configured in the service file:resources/config/services.yml
services:
server_update:
class: JMPR\ServerMonBundle\Update\ServerUpdate
arguments: [ @doctrine.orm.entity_manager ]
Dependency injection is used to configure the ORM connection. Fabian has a great introduction blog post on dependency injection (from 2009 but still worth a read). Passed to the class - is the ORM entity manager (@doctrine.orm.entity_manager)
An initial version of the class - which just queries the Server repository to find the matching servers and prints them. As a feature - a server specified on the command line will be checked even if it is not active.
namespace JMPR\ServerMonBundle\Update;
use JMPR\ServerMonBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class ServerUpdate
{
protected $em;
public function __construct($em)
{
$this->em = $em;
}
protected function configure()
{
}
public function update($serverLabel)
{
if ($serverLabel) {
$servers = $this->em->getRepository('JMPRServerMonBundle:MonitorServers')->findByLabel($serverLabel);
echo "update: <". $serverLabel ."> " . count($servers) ." servers matched\n---";
} else {
$servers = $this->em->getRepository('JMPRServerMonBundle:MonitorServers')->findByActive('yes');
echo "update: " . count($servers) ." servers matched\n---";
}
foreach ($servers as $server) {
echo "server: ". $server->getLabel() . ":" . $server->getIp() . "\n---";
}
}
# classes/sm/smUpdaterStatus.php
class smUpdaterStatus extends smCore {
server_mon_update:
pattern: /update
defaults: { _controller: JMPRServerMonBundle:Default:update }
The next post discusses the ServerUpdate and UpdaterStatus classes in detail.
namespace JMPR\ServerMonBundle\Update;
use JMPR\ServerMonBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class ServerUpdate
{
protected $em;
public function __construct($em)
{
$this->em = $em;
}
protected function configure()
{
}
public function update($serverLabel)
{
if ($serverLabel) {
$servers = $this->em->getRepository('JMPRServerMonBundle:MonitorServers')->findByLabel($serverLabel);
echo "update: <". $serverLabel ."> " . count($servers) ." servers matched\n---";
} else {
$servers = $this->em->getRepository('JMPRServerMonBundle:MonitorServers')->findByActive('yes');
echo "update: " . count($servers) ." servers matched\n---";
}
foreach ($servers as $server) {
echo "server: ". $server->getLabel() . ":" . $server->getIp() . "\n---";
}
}
It is interesting at this point to compare this to the original phpservermon class: sfUpdate
# classes/sm/smUpdaterStatus.php
class smUpdaterStatus extends smCore {
}
The smCore class, is purely concerned with instantiating a link to the database - the same functionality provided by the Symfony service container:
abstract class smCore {
public $db;
function __construct() {
// add database handler
$this->db = $GLOBALS['db'];
}
}
So the original smCore class was designed to solve the same problem that the dependency injection addresses.
A final note on this topic - the updater class is called from a controller in response to an update request, the route was added:
A final note on this topic - the updater class is called from a controller in response to an update request, the route was added:
server_mon_update:
pattern: /update
defaults: { _controller: JMPRServerMonBundle:Default:update }
The base.html.twig template edited:
<li><a href="{{ path('server_mon_update')}}">update</a></li>
and the controller action:
public function updateAction()
{
$updater = $this->get('server_update');
$updater->update('');
return $this->redirect($this->generateUrl('server_mon_homepage'));
}
The get method to the service container will construct an updater class and initialise it.
The Article are written by author are very informative and have a unique idea to share. Thanks for sharing this Information with us.
ReplyDeleteWe provide English Speaking Course in Gurgaon at very reasonable price with 100% Success rate by AIBEDUCATION.
Thank you for your outstanding article. You will always find clients coming back to us which is a result of our excellent services. Our goal is to offer unique and specialized services to our clients and in return create a long-lasting working relationship. We provide the Best 2 bhk flat in greater noida west and 3 BHK, 4 BHK Flats, Apartments, Penthouse, Corporate Properties, Commercial Properties in Noida, Greater Noida West, Delhi NCR with Great Discount and Deals. Learn more about Investmango visit our website and call now:- 8076042671
ReplyDelete