PageRenderTime 54ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/branches/1.0/observers/class.DNSEventObserver.php

http://scalr.googlecode.com/
PHP | 289 lines | 213 code | 31 blank | 45 comment | 26 complexity | 7fcea2e36420e20a0a33549c7f9aac57 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, GPL-3.0
  1. <?php
  2. class DNSEventObserver extends EventObserver
  3. {
  4. public $ObserverName = 'DNS';
  5. function __construct()
  6. {
  7. parent::__construct();
  8. $this->DNSZoneController = new DNSZoneControler();
  9. }
  10. public function OnRebootComplete(RebootCompleteEvent $event)
  11. {
  12. $farminfo = $this->DB->GetRow("SELECT * FROM farms WHERE id=?", array($this->FarmID));
  13. $this->AddInstanceToDNS($farminfo, $event->InstanceInfo);
  14. }
  15. public function OnNewMysqlMasterUp(NewMysqlMasterUpEvent $event)
  16. {
  17. // Reload instance info
  18. $instanceinfo = $this->DB->GetRow("SELECT * FROM farm_instances WHERE id=?",
  19. array($event->InstanceInfo['id'])
  20. );
  21. if ($instanceinfo['isactive'] != 1)
  22. return;
  23. $DBFarmRole = DBFarmRole::Load($this->FarmID, $instanceinfo['ami_id']);
  24. if ($DBFarmRole->GetSetting(DBFarmRole::SETTING_EXCLUDE_FROM_DNS) != 1)
  25. return;
  26. try
  27. {
  28. $zones = $this->DB->GetAll("SELECT * FROM zones WHERE farmid='{$this->FarmID}' AND status IN (?,?)", array(ZONE_STATUS::ACTIVE, ZONE_STATUS::PENDING));
  29. if (count($zones) == 0)
  30. return;
  31. $ami_info = $this->DB->GetRow("SELECT * FROM ami_roles WHERE ami_id=?", array($instanceinfo['ami_id']));
  32. foreach ($zones as $zone)
  33. {
  34. if (!$zone['id'])
  35. continue;
  36. $records_attrs = array();
  37. // We must update:
  38. // 'int-ROLE_NAME-master IN A INTERNAL_IP'
  39. // 'ext-ROLE_NAME-master IN A PUBLIC_IP'
  40. // records
  41. if ($instanceinfo["isdbmaster"] == 1)
  42. {
  43. $records_attrs[] = array("int-{$instanceinfo['role_name']}-master", $instanceinfo["internal_ip"], 20);
  44. $records_attrs[] = array("ext-{$instanceinfo['role_name']}-master", $instanceinfo['external_ip'], 20);
  45. if ($instanceinfo["role_name"] != ROLE_ALIAS::MYSQL)
  46. {
  47. $records_attrs[] = array("int-mysql-master", $instanceinfo["internal_ip"], 20);
  48. $records_attrs[] = array("ext-mysql-master", $instanceinfo['external_ip'], 20);
  49. }
  50. }
  51. // Adding new records to database
  52. foreach ($records_attrs as $record_attrs)
  53. {
  54. $this->DB->Execute("REPLACE INTO records SET zoneid='{$zone['id']}', rtype='A', ttl=?, rvalue=?, rkey=?, issystem='1'",
  55. array($record_attrs[2], $record_attrs[1], $record_attrs[0]));
  56. }
  57. // Remove old role-slave and mysql-slave records for this instance
  58. $this->DB->Execute("DELETE FROM records WHERE zoneid=? AND rtype='A' AND rkey LIKE '%-slave' AND (rvalue=? OR rvalue=?) AND issystem='1'",
  59. array($zone['id'], $instanceinfo["internal_ip"], $instanceinfo['external_ip'])
  60. );
  61. // Update DNS zone on Nameservers
  62. if (!$this->DNSZoneController->Update($zone["id"]))
  63. $this->Logger->error(_("Cannot update zone in DNSEventObserver"));
  64. else
  65. $this->Logger->info("Instance {$instanceinfo['instance_id']} added to DNS zone '{$zone['zone']}'");
  66. }
  67. }
  68. catch(Exception $e)
  69. {
  70. $this->Logger->fatal("DNS zone update failed: ".$e->getMessage());
  71. }
  72. }
  73. /**
  74. * Public IP address for instance changed
  75. *
  76. * @param array $instanceinfo
  77. * @param string $new_ip_address
  78. */
  79. public function OnIPAddressChanged(IPAddressChangedEvent $event)
  80. {
  81. // Get farm info
  82. $farminfo = $this->DB->GetRow("SELECT * FROM farms WHERE id=?", array($this->FarmID));
  83. if ($farminfo['status'] != 1)
  84. return;
  85. $DBFarmRole = DBFarmRole::Load($this->FarmID, $event->InstanceInfo['ami_id']);
  86. if ($DBFarmRole->GetSetting(DBFarmRole::SETTING_EXCLUDE_FROM_DNS) != 1)
  87. $this->AddInstanceToDNS($farminfo, $event->InstanceInfo);
  88. }
  89. /**
  90. * Farm launched
  91. *
  92. * @param bool $mark_instances_as_active
  93. */
  94. public function OnFarmLaunched(FarmLaunchedEvent $event)
  95. {
  96. // Get list of all zones for current farm
  97. $zones = $this->DB->GetAll("SELECT * FROM zones WHERE farmid='{$this->FarmID}'");
  98. if (count($zones) < 1)
  99. return;
  100. // Foreach zone set status - Active
  101. foreach ((array)$zones as $zone)
  102. {
  103. $this->DNSZoneController->Update($zone["id"]);
  104. if ($zone["status"] != ZONE_STATUS::PENDING)
  105. $this->DB->Execute("UPDATE zones SET status=? WHERE id='{$zone['id']}'", array(ZONE_STATUS::ACTIVE));
  106. }
  107. }
  108. /**
  109. * Farm terminated
  110. *
  111. * @param bool $remove_zone_from_DNS
  112. * @param bool $keep_elastic_ips
  113. */
  114. public function OnFarmTerminated(FarmTerminatedEvent $event)
  115. {
  116. if (!$event->RemoveZoneFromDNS)
  117. return;
  118. // Get list of all zones for current farm
  119. $zones = $this->DB->GetAll("SELECT * FROM zones WHERE farmid='{$this->FarmID}'");
  120. foreach ((array)$zones as $zone)
  121. {
  122. // Remove dynamic A records (pointed to instances)
  123. $this->DB->Execute("DELETE FROM records WHERE rtype='A' AND
  124. issystem='1' AND
  125. zoneid='{$zone['id']}'"
  126. );
  127. }
  128. // Set status for zones - INACTIVE
  129. $this->DB->Execute("UPDATE zones SET status=? WHERE farmid='{$this->FarmID}'",
  130. array(ZONE_STATUS::INACTIVE)
  131. );
  132. }
  133. /**
  134. * Instance sent hostUp event
  135. *
  136. * @param array $instanceinfo
  137. */
  138. public function OnHostUp(HostUpEvent $event)
  139. {
  140. $farminfo = $this->DB->GetRow("SELECT * FROM farms WHERE id=?", array($this->FarmID));
  141. $DBFarmRole = DBFarmRole::Load($this->FarmID, $event->InstanceInfo['ami_id']);
  142. if ($DBFarmRole->GetSetting(DBFarmRole::SETTING_EXCLUDE_FROM_DNS) != 1)
  143. $this->AddInstanceToDNS($farminfo, $event->InstanceInfo);
  144. }
  145. /**
  146. * Instance terminated
  147. *
  148. * @param array $instanceinfo
  149. */
  150. public function OnHostDown(HostDownEvent $event)
  151. {
  152. //
  153. // Remove terminated instance from DNS records
  154. //
  155. $farminfo = $this->DB->GetRow("SELECT * FROM farms WHERE id=?", array($this->FarmID));
  156. if ($farminfo['status'] != FARM_STATUS::RUNNING)
  157. return;
  158. try
  159. {
  160. $zones = $this->DB->GetAll("SELECT DISTINCT(zoneid) FROM records WHERE rvalue='{$event->InstanceInfo['external_ip']}' OR rvalue='{$event->InstanceInfo['internal_ip']}' GROUP BY zoneid");
  161. foreach ($zones as $zone)
  162. {
  163. $zoneinfo = $this->DB->GetRow("SELECT * FROM zones WHERE id='{$zone['zoneid']}'");
  164. if (!$zoneinfo)
  165. continue;
  166. $this->DB->Execute("DELETE FROM records WHERE
  167. rtype='A' AND
  168. issystem='1' AND
  169. zoneid=? AND
  170. (rvalue=? OR rvalue=?)",
  171. array($zoneinfo['id'], $event->InstanceInfo['external_ip'], $event->InstanceInfo['internal_ip'])
  172. );
  173. //TODO: Check affected rows.
  174. if (!$this->DNSZoneController->Update($zoneinfo["id"]))
  175. $this->Logger->warn("[FarmID: {$farminfo['id']}] Cannot remove terminated instance '{$event->InstanceInfo['instance_id']}' ({$event->InstanceInfo['external_ip']}) from DNS zone '{$zoneinfo['zone']}'");
  176. else
  177. $this->Logger->info("[FarmID: {$farminfo['id']}] Terminated instance '{$event->InstanceInfo['instance_id']}' (ExtIP: {$event->InstanceInfo['external_ip']}, IntIP: {$event->InstanceInfo['internal_ip']}) removed from DNS zone '{$zoneinfo['zone']}'");
  178. }
  179. }
  180. catch(Exception $e)
  181. {
  182. $this->Logger->warn(new FarmLogMessage($farminfo['id'], "Update DNS zone on 'OnHostDown'' event failed: {$e->getMessage()}"));
  183. }
  184. }
  185. /**
  186. * Add A records to DNS zone for instance
  187. *
  188. * @param array $farminfo
  189. * @param array $instanceinfo
  190. */
  191. private function AddInstanceToDNS($farminfo, $instanceinfo)
  192. {
  193. // Reload instance info
  194. $instanceinfo = $this->DB->GetRow("SELECT * FROM farm_instances WHERE id=?",
  195. array($instanceinfo['id'])
  196. );
  197. if ($instanceinfo['isactive'] != 1)
  198. return;
  199. try
  200. {
  201. $zones = $this->DB->GetAll("SELECT * FROM zones WHERE farmid='{$farminfo['id']}' AND status IN (?,?)", array(ZONE_STATUS::ACTIVE, ZONE_STATUS::PENDING));
  202. if (count($zones) == 0)
  203. return;
  204. foreach ($zones as $zone)
  205. {
  206. if (!$zone['id'])
  207. continue;
  208. $records_attrs = array();
  209. $ami_info = $this->DB->GetRow("SELECT * FROM ami_roles WHERE ami_id=?", array($instanceinfo['ami_id']));
  210. $replace = false;
  211. $role_name = $zone["role_name"];
  212. if ($instanceinfo["replace_iid"])
  213. {
  214. $old_instance_info = $this->DB->GetRow("SELECT role_name FROM farm_instances
  215. WHERE instance_id=?",
  216. array($instanceinfo["replace_iid"])
  217. );
  218. if ($old_instance_info['role_name'] == $zone["role_name"])
  219. $role_name = $instanceinfo['role_name'];
  220. }
  221. $this->Logger->info(new FarmLogMessage($farminfo['id'], "Instance {$instanceinfo['instance_id']}. Is DB Master = {$instanceinfo['isdbmaster']}"));
  222. $instance_records = DNSZoneControler::GetInstanceDNSRecordsList($instanceinfo, $role_name, $ami_info['alias']);
  223. $this->Logger->info(new FarmLogMessage($farminfo['id'], "Adding system A records to zone {$zone['zone']}"));
  224. // Adding new records to database
  225. foreach ($instance_records as $record_attrs)
  226. {
  227. $this->DB->Execute("REPLACE INTO records SET zoneid='{$zone['id']}', rtype='A', ttl=?, rvalue=?, rkey=?, issystem='1'",
  228. array($record_attrs['ttl'], $record_attrs['rvalue'], $record_attrs['rkey']));
  229. }
  230. // Update DNS zone on Nameservers
  231. if (!$this->DNSZoneController->Update($zone["id"]))
  232. $this->Logger->error("Cannot update zone in DNSEventObserver");
  233. else
  234. $this->Logger->info("Instance {$instanceinfo['instance_id']} added to DNS zone '{$zone['zone']}'");
  235. }
  236. }
  237. catch(Exception $e)
  238. {
  239. $this->Logger->fatal("DNS zone update failed: ".$e->getMessage());
  240. }
  241. }
  242. }
  243. ?>