public static function createSampleDowntime($severity = 'OUTAGE', $classification = 'SCHEDULED') { $downtime = new Downtime(); $downtime->setDescription("A sample skeleton downtime"); $downtime->setSeverity($severity); $downtime->setClassification($classification); return $downtime; }
function newDowntime($downtimeXml) { $downtime = new Downtime(); foreach ($downtimeXml->attributes() as $key => $value) { switch ($key) { case "ID": $promId = (int) $value; break; case "PRIMARY_KEY": $primaryKey = (string) $value; break; case "CLASSIFICATION": $classification = (string) $value; break; } } // Get the largest v4 downtime PK which is an integer appended by the string 'G0' // slice off the 'G0' and get the integer value. $v4pk = (int) substr($primaryKey, 0, strlen($primaryKey) - 2); if ($v4pk > $GLOBALS['largestV4DowntimePK']) { $GLOBALS['largestV4DowntimePK'] = $v4pk; } $downtime->setClassification($classification); $downtime->setDescription((string) $downtimeXml->DESCRIPTION); $downtime->setSeverity((string) $downtimeXml->SEVERITY); $startDate = new DateTime("@" . (string) $downtimeXml->START_DATE); $downtime->setStartDate($startDate); $endDate = new DateTime("@" . (string) $downtimeXml->END_DATE); $downtime->setEndDate($endDate); $insertDate = new DateTime("@" . (string) $downtimeXml->INSERT_DATE); $downtime->setInsertDate($insertDate); $downtime->setPrimaryKey($primaryKey); return $downtime; }
/** * Show how Bidirectional relationships must be correctly managed in * userland/application code. (See Doctrine the tutorial: * "Consistency of bi-directional references on the inverse side of a * relation have to be managed in userland application code. Doctrine * cannot magically update your collections to be consistent."). */ public function testDowntimeEndpoint_BidirectionalJoinConsistencyManagement() { print __METHOD__ . "\n"; // create a linked entity graph as beow: // // se (1 service) // / | \ // el1 el2 el3 (3 endpoints) // \ | / // dt1 (1 downtime) $se = TestUtil::createSampleService('service1'); $el1 = TestUtil::createSampleEndpointLocation(); $el2 = TestUtil::createSampleEndpointLocation(); $el3 = TestUtil::createSampleEndpointLocation(); $se->addEndpointLocationDoJoin($el1); $se->addEndpointLocationDoJoin($el2); $se->addEndpointLocationDoJoin($el3); $dt1 = new Downtime(); $dt1->setDescription('downtime description'); $dt1->setSeverity("WARNING"); $dt1->setClassification("UNSCHEDULED"); $dt1->addEndpointLocation($el1); $dt1->addEndpointLocation($el2); $dt1->addEndpointLocation($el3); // persist and flush $this->em->persist($se); $this->em->persist($el1); $this->em->persist($el2); $this->em->persist($el3); $this->em->persist($dt1); $this->em->flush(); // Now delete the relationship between dt1 and el1 + el2 using OWNING // SIDE ONLY; since downtime is the OWNING side we must remove el1 + el2 // from downtime to actually delete the relationships in the DB // (on the subsequent flush). Since we have only removed the relationship // on the downtime side, our in-mem entity model is now inconsistent ! $dt1->getEndpointLocations()->removeElement($el1); //$el1->getDowntimes()->removeElement($dt1); $dt1->getEndpointLocations()->removeElement($el2); //$el2->getDowntimes()->removeElement($dt1); $this->em->flush(); // Entity model in DB now looks like this: // se // / | \ // el1 el2 el3 // / // dt1 (note FKs/relationships have been removed) // Assert that there are still three EndpointLocations and one Downtimes in the database $testConn = $this->getConnection(); $result = $testConn->createQueryTable('results_table', "SELECT * FROM EndpointLocations"); $this->assertTrue($result->getRowCount() == 3); $result = $testConn->createQueryTable('results_table', "SELECT * FROM Downtimes"); $this->assertTrue($result->getRowCount() == 1); $result = $testConn->createQueryTable('results_table', "SELECT * FROM Downtimes_EndpointLocations"); $this->assertTrue($result->getRowCount() == 1); // Assert that our in-mem entity model is now inconsistent with DB // when VIEWED FROM THE ENDPOINT SIDE. $this->assertEquals(1, count($el1->getDowntimes())); $this->assertEquals(1, count($el2->getDowntimes())); $this->assertEquals(1, count($el3->getDowntimes())); // Assert that our in-mem entity model is consistent with DB // when VIEWED FROM THE DOWNTIME SIDE: // dt1 still has el3 linked (as expected) but not el1 or el2. // Note we use first() method to fetch first array collection entry! // (calling get(0) would not work as expected because the collection // is a map so array key values are preserved - el3 was added 3rd so it // preserves its zero-offset key value of 2). $this->assertEquals(1, count($dt1->getEndpointLocations())); $this->assertSame($el3, $dt1->getEndpointLocations()->first()); $this->assertSame($el3, $dt1->getEndpointLocations()->get(2)); // Next lines keep our in-mem inverse side consistent with DB. If we // didn't do this, then our first assertion on the following lines below // would fail! This shows that you have to keep your bi-directional // relationships consistent in userland/application code, doctrine // won't do this for you! $el1->getDowntimes()->removeElement($dt1); $el2->getDowntimes()->removeElement($dt1); // After updating the 'in-memory' entity model, check that el1 and el2 // have no linked downtimes while el3 still has dt linked. // This mirrors what we have in the DB. $this->assertEquals(0, count($el1->getDowntimes())); $this->assertEquals(0, count($el2->getDowntimes())); $this->assertEquals(1, count($el3->getDowntimes())); // our collection key value is still same $this->assertSame($el3, $dt1->getEndpointLocations()->get(2)); }
/** * Test the <code>$serviceDAO->removeEndpoint($endpoint)</code> method. */ public function testServiceDAORemoveEndpoint() { print __METHOD__ . "\n"; // create a linked entity graph as beow: // // se -----| (1 service) // / | \ | // el1 el2 el3 | (3 endpoints) // | \ | / | // dt0 dt1 ----| (1 downtime) $dt1 = new Downtime(); $dt1->setDescription('downtime description'); $dt1->setSeverity("WARNING"); $dt1->setClassification("UNSCHEDULED"); $dt0 = new Downtime(); $dt0->setDescription('downtime description'); $dt0->setSeverity("WARNING"); $dt0->setClassification("UNSCHEDULED"); $se = TestUtil::createSampleService('service1'); $el1 = TestUtil::createSampleEndpointLocation(); $el2 = TestUtil::createSampleEndpointLocation(); $el3 = TestUtil::createSampleEndpointLocation(); $se->addEndpointLocationDoJoin($el1); $se->addEndpointLocationDoJoin($el2); $se->addEndpointLocationDoJoin($el3); //$se->_addDowntime($dt1); // we don't call this in client code ! $dt1->addEndpointLocation($el1); $dt1->addEndpointLocation($el2); $dt1->addEndpointLocation($el3); $dt1->addService($se); $dt0->addEndpointLocation($el1); //$dt0->addService($se); // note we don't add this relationship for purposes of the test // persist and flush $this->em->persist($se); $this->em->persist($el1); $this->em->persist($el2); $this->em->persist($el3); $this->em->persist($dt1); $this->em->persist($dt0); $this->em->flush(); // create DAO to test $serviceDao = new ServiceDAO(); $serviceDao->setEntityManager($this->em); // remove first endpoint causing dt0 to be orphaned $serviceDao->removeEndpoint($el1); $this->em->flush(); // Assert expected object graph // se -----| (1 service) // | \ | // el2 el3 | (2 endpoints) // | / | // dt0 dt1-----| (2 downtime) // $testConn = $this->getConnection(); $result = $testConn->createQueryTable('results_table', "SELECT * FROM EndpointLocations"); $this->assertTrue($result->getRowCount() == 2); $result = $testConn->createQueryTable('results_table', "SELECT * FROM Downtimes"); $this->assertTrue($result->getRowCount() == 2); $result = $testConn->createQueryTable('results_table', "SELECT * FROM Downtimes_EndpointLocations"); $this->assertTrue($result->getRowCount() == 2); // Assert expected object graph in ORM Mem $this->assertEquals(1, count($el2->getDowntimes())); $this->assertEquals(1, count($el3->getDowntimes())); $this->assertEquals(2, count($se->getEndpointLocations())); $this->assertEquals(1, count($se->getDowntimes())); $this->assertEquals(2, count($dt1->getEndpointLocations())); $this->assertEquals(1, count($dt1->getServices())); // remove another el $serviceDao->removeEndpoint($el2); $this->em->flush(); // Assert expected object graph in DB // se -----| (1 service) // \ | // el3 | (1 endpoints) // / | // dt0 dt1-----| (2 downtime) // $testConn = $this->getConnection(); $result = $testConn->createQueryTable('results_table', "SELECT * FROM EndpointLocations"); $this->assertTrue($result->getRowCount() == 1); $result = $testConn->createQueryTable('results_table', "SELECT * FROM Downtimes"); $this->assertTrue($result->getRowCount() == 2); $result = $testConn->createQueryTable('results_table', "SELECT * FROM Downtimes_EndpointLocations"); $this->assertTrue($result->getRowCount() == 1); // Assert expected object graph in ORM Mem $this->assertEquals(1, count($el3->getDowntimes())); $this->assertEquals(1, count($se->getEndpointLocations())); $this->assertEquals(1, count($se->getDowntimes())); $this->assertEquals(1, count($dt1->getEndpointLocations())); $this->assertEquals(1, count($dt1->getServices())); // remove another el $serviceDao->removeEndpoint($el3); $this->em->flush(); // Assert expected object graph in DB // se -----| (1 service) // | // | (1 endpoints) // | // dt0 dt1-----| (2 downtime) // $testConn = $this->getConnection(); $result = $testConn->createQueryTable('results_table', "SELECT * FROM EndpointLocations"); $this->assertTrue($result->getRowCount() == 0); $result = $testConn->createQueryTable('results_table', "SELECT * FROM Downtimes"); $this->assertTrue($result->getRowCount() == 2); $result = $testConn->createQueryTable('results_table', "SELECT * FROM Downtimes_EndpointLocations"); $this->assertTrue($result->getRowCount() == 0); // Assert expected object graph in ORM Mem $this->assertEquals(0, count($se->getEndpointLocations())); $this->assertEquals(1, count($se->getDowntimes())); $this->assertEquals(0, count($dt1->getEndpointLocations())); $this->assertEquals(1, count($dt1->getServices())); }
/** * Array * ( * [DOWNTIME] => Array * ( * [SEVERITY] => OUTAGE * [DESCRIPTION] => Test * [START_TIMESTAMP] => 20/03/2013 00:00 * [END_TIMESTAMP] => 23/03/2013 00:00 * ) * [Impacted_Services] => Array * ( * [0] => 824 * [1] => 825 * [2] => 2146 * ) * [Impacted_Endpoints] => Array * ( * [0] => 54 * [1] => 15 * [2] => 26 * ) * Adds a downtime * @param Array $values Downtime values, shown above * @param \User $user User making the request * @return \Downtime $dt The new downtime */ public function addDowntime($values, \User $user = null) { //Check the portal is not in read only mode, throws exception if it is $this->checkPortalIsNotReadOnlyOrUserIsAdmin($user); require_once __DIR__ . '/ServiceService.php'; $serviceService = new \org\gocdb\services\ServiceService(); $serviceService->setEntityManager($this->em); // Get the affected services $services = array(); foreach ($values['Impacted_Services'] as $service) { $services[] = $serviceService->getService($service); } // Get the affected endpoints $endpoints = array(); foreach ($values['Impacted_Endpoints'] as $endpoint) { $endpoints[] = $serviceService->getEndpoint($endpoint); } if (count($services) == 0) { throw new \Exception("A downtime must affect at least one service"); } // Check that each endpoint belongs to one of the services. // It is an error if an endpoint does not belong to one of the services. foreach ($endpoints as $checkEndpoint) { $endpointBelongsToService = false; foreach ($services as $checkService) { if (in_array($checkEndpoint, $checkService->getEndpointLocations()->toArray())) { $endpointBelongsToService = true; } } if (!$endpointBelongsToService) { throw new \Exception('Error, affected endpoint is not owned by an affected service'); } } // get the affected sites $sites = array(); foreach ($services as $se) { $site = $se->getParentSite(); if (!in_array($site, $sites)) { $sites[] = $site; } } if (count($sites) != 1) { // if there are multiple affected services from multiple sites, // the gui must either enforce single site selection // or prevent selecting 'define DT in site timezone' if selecting // multiple sites (i.e. utc only when selecting services from multiple sites). throw new \Exception("Downtime creation for multiple sites not supported yet"); } // Check the user has a role covering the passed SEs $this->authorization($services, $user); $this->validate($values['DOWNTIME']); $startStr = $values['DOWNTIME']['START_TIMESTAMP']; $endStr = $values['DOWNTIME']['END_TIMESTAMP']; //echo($startStr. ' '.$endStr); // 14/05/2015 16:16 14/05/2015 16:17 d/m/Y H:i // did the user specify the downtime info in utc (default) or in site's local timezone? /*$requestUtcOrSiteTimezone = $values['DOWNTIME']['DEFINE_TZ_BY_UTC_OR_SITE']; $tzStr = 'UTC'; // the timezone label specified by the user (e.g. 'UTC' or 'Europe/London') if($requestUtcOrSiteTimezone == 'site'){ // if there are multiple affected services from multiple sites, // we assume utc - the gui must therefore either enforce single site selection // or prevent selecting 'define DT in site timezone' if selecting // multiple sites (i.e. utc only when selecting services from multiple sites). // get the site timezone label if(count($sites) > 1){ $tzStr = 'UTC'; // if many sites are affected (not implemented yet), assume UTC } else { $siteTzOrNull = $sites[0]->getTimezoneId(); if( !empty($siteTzOrNull)){ $tzStr = $siteTzOrNull; } else { $tzStr = 'UTC'; } } } // convert start and end into UTC $UTC = new \DateTimeZone("UTC"); if($tzStr != 'UTC'){ // specify dateTime in source TZ $sourceTZ = new \DateTimeZone($tzStr); $start = \DateTime::createFromFormat($this::FORMAT, $startStr, $sourceTZ); $end = \DateTime::createFromFormat($this::FORMAT, $endStr, $sourceTZ); // reset the TZ to UTC $start->setTimezone($UTC); $end->setTimezone($UTC); } else { $start = \DateTime::createFromFormat($this::FORMAT, $startStr, $UTC); $end = \DateTime::createFromFormat($this::FORMAT, $endStr, $UTC); }*/ $start = \DateTime::createFromFormat($this::FORMAT, $startStr, new \DateTimeZone("UTC")); $end = \DateTime::createFromFormat($this::FORMAT, $endStr, new \DateTimeZone("UTC")); $this->validateDates($start, $end); // calculate classification $nowPlus1Day = new \DateTime(null, new \DateTimeZone('UTC')); $oneDay = \DateInterval::createFromDateString('1 days'); if ($start > $nowPlus1Day->add($oneDay)) { $class = "SCHEDULED"; } else { $class = "UNSCHEDULED"; } $this->em->getConnection()->beginTransaction(); try { $dt = new \Downtime(); $dt->setClassification($class); $dt->setDescription($values['DOWNTIME']['DESCRIPTION']); $dt->setSeverity($values['DOWNTIME']['SEVERITY']); $dt->setStartDate($start); $dt->setEndDate($end); $dt->setInsertDate(new \DateTime(null, new \DateTimeZone('UTC'))); // Create a new pk and persist/flush to sync in-mem object state // with DB - is needed so that the call to v4DowntimePK->getId() actually // returns a value (we can still rollback no probs if an issue occurs // to remove the Downtime) $v4DowntimePk = new \PrimaryKey(); $this->em->persist($v4DowntimePk); $this->em->flush(); $dt->setPrimaryKey($v4DowntimePk->getId() . 'G0'); //Create a link to the services foreach ($services as $service) { $dt->addService($service); } //Create a link to the affected endpoints (if any endpoints were selected) foreach ($endpoints as $endpoint) { $dt->addEndpointLocation($endpoint); } $this->em->persist($dt); $this->em->flush(); $this->em->getConnection()->commit(); } catch (\Exception $e) { $this->em->getConnection()->rollback(); $this->em->close(); throw $e; } return $dt; }