1: <?php
2:
3: namespace Himedia\Padocc\Task\Extended;
4:
5: use Himedia\Padocc\AttributeProperties;
6: use Himedia\Padocc\Task\Base\Environment;
7: use Himedia\Padocc\Task\Base\HTTP;
8: use Himedia\Padocc\Task\Base\Link;
9:
10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48:
49: class B2CSwitchSymlink extends SwitchSymlink
50: {
51: 52: 53: 54:
55: private $oHTTPTask;
56:
57: 58: 59:
60: protected function init()
61: {
62: parent::init();
63:
64: $this->aAttrProperties = array_merge(
65: $this->aAttrProperties,
66: array(
67: 'sysopsnotifications' => AttributeProperties::BOOLEAN,
68: 'addSQLTwBuild' => AttributeProperties::BOOLEAN,
69: 'clusterRemoving' => AttributeProperties::BOOLEAN,
70: 'clusterReintegration' => AttributeProperties::BOOLEAN
71: )
72: );
73:
74: $this->oNumbering->addCounterDivision();
75:
76: $aMappingAAI = array('qa' => 'qa', 'prod' => 'web');
77: $sEnv = $this->oProperties->getProperty('environment_name');
78: $sAppParameter = (isset($aMappingAAI[$sEnv]) ? $aMappingAAI[$sEnv] : $sEnv);
79: $sURL = 'http://aai.twenga.com/push.php?server=${WEB_SERVERS}&app=' . $sAppParameter;
80: $aAttributes = array('url' => $sURL);
81: $this->oHTTPTask = HTTP::getNewInstance($aAttributes, $this->oProject, $this->oDIContainer);
82: $this->oNumbering->removeCounterDivision();
83: }
84:
85: 86: 87: 88:
89: public static function getTagName ()
90: {
91: return 'b2cswitchsymlink';
92: }
93:
94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104:
105: public function check ()
106: {
107: parent::check();
108:
109: $aAttrToInit = array('sysopsnotifications', 'addSQLTwBuild', 'clusterRemoving', 'clusterReintegration');
110: foreach ($aAttrToInit as $sAttrName) {
111: if (! isset($this->aAttValues[$sAttrName])) {
112: $this->aAttValues[$sAttrName] = 'false';
113: }
114: }
115: }
116:
117: 118: 119: 120: 121: 122:
123: protected function preExecute ()
124: {
125: parent::preExecute();
126:
127: $this->getLogger()->info('+++');
128: if ($this->aAttValues['sysopsnotifications'] == 'true') {
129: $sEnv = $this->oProperties->getProperty('environment_name');
130: $sID = $this->oProperties->getProperty('execution_id');
131: $this->sendSysopsNotification('MEP-activation', 2, "Deploy to $sEnv servers (#$sID) is switching...");
132: }
133: $this->getLogger()->info('---');
134: }
135:
136: 137: 138: 139: 140: 141:
142: protected function centralExecute ()
143: {
144: $this->getLogger()->info('+++');
145: if ($this->oProperties->getProperty('with_symlinks') === 'true') {
146: if ($this->oProperties->getProperty(Environment::SERVERS_CONCERNED_WITH_BASE_DIR) == '') {
147: $this->getLogger()->info('No release found.');
148: } else {
149: $this->oProperties->setProperty('with_symlinks', 'false');
150: $this->checkTargets();
151:
152:
153: $aServers = $this->processPath('${WEB_SERVERS}');
154: foreach ($aServers as $sServer) {
155: $this->getLogger()->info("Switch '$sServer' server:+++");
156:
157: if ($this->aAttValues['clusterRemoving'] == 'true') {
158: $this->setCluster($sServer, false);
159: }
160:
161:
162: $aAttributes = array(
163: 'src' => $this->aAttValues['src'],
164: 'target' => $this->aAttValues['target'],
165: 'server' => $sServer
166: );
167: $oLinkTask = Link::getNewInstance($aAttributes, $this->oProject, $this->oDIContainer);
168: $oLinkTask->setUp();
169: $oLinkTask->execute();
170:
171: $this->restartServerApache($sServer);
172: $this->clearServerSmartyCaches($sServer);
173: if ($this->aAttValues['clusterReintegration'] == 'true') {
174: $this->setCluster($sServer, true);
175: }
176: $this->getLogger()->info('---');
177: }
178:
179:
180:
181:
182: $aAllServers = $this->expandPath($this->aAttValues['server']);
183: $aDiff = array_diff($aAllServers, $aServers);
184: if (count($aDiff) > 0) {
185: $this->getLogger()->info('Switch other servers: ' . implode(', ', $aDiff) . '.+++');
186: $this->oProperties->setProperty('remaining_servers_to_switch', implode(' ', $aDiff));
187: $aAttributes = array(
188: 'src' => $this->aAttValues['src'],
189: 'target' => $this->aAttValues['target'],
190: 'server' => '${remaining_servers_to_switch}'
191: );
192: $oLinkTask = Link::getNewInstance($aAttributes, $this->oProject, $this->oDIContainer);
193: $oLinkTask->setUp();
194: $oLinkTask->execute();
195: $this->getLogger()->info('---');
196: }
197:
198: $this->oProperties->setProperty('with_symlinks', 'true');
199: }
200: } else {
201: $this->getLogger()->info("Mode 'withsymlinks' is off: nothing to do.");
202: }
203: $this->getLogger()->info('---');
204: }
205:
206: 207: 208: 209: 210: 211:
212: protected function postExecute ()
213: {
214: $sEnv = $this->oProperties->getProperty('environment_name');
215: $sRollbackID = $this->oProperties->getProperty('rollback_id');
216: $sID = $sRollbackID !== '' ? $sRollbackID : $this->oProperties->getProperty('execution_id');
217: $this->getLogger()->info('+++');
218:
219: if ($this->aAttValues['addSQLTwBuild'] == 'true') {
220: $this->addSQLTwBuild($sID, $sEnv);
221: }
222: if ($this->aAttValues['sysopsnotifications'] == 'true') {
223: $this->sendSysopsNotification('MEP-activation', 0, "Deploy to $sEnv servers (#$sID) finished.");
224: }
225: $this->oHTTPTask->execute();
226:
227: $this->getLogger()->info('---');
228: parent::postExecute();
229: }
230:
231: 232: 233: 234: 235: 236: 237:
238: private function sendSysopsNotification ($sService, $iStatus, $sMessage)
239: {
240: $this->getLogger()->info("Send notification to Sysops: '$sMessage'+++");
241: $sCmd = "/home/prod/twenga/tools/send_nsca_fs3.sh $sService $iStatus \"$sMessage\"";
242: $this->oShell->execSSH($sCmd, 'fs3:foo');
243: $this->getLogger()->info('---');
244: }
245:
246: 247: 248: 249: 250: 251: 252:
253: private function addSQLTwBuild ($sID, $sEnv)
254: {
255: $aTypes = array('qa' => 'Q', 'bct' => 'B', 'internal' => 'I', 'preprod' => 'X', 'prod' => 'P');
256: if (! isset($aTypes[$sEnv])) {
257: throw new \DomainException("Environment not handled: '$sEnv'!");
258: }
259: $this->getLogger()->info("Add Twenga build number $sID into 'TWENGABUILD' SQL table.+++");
260: $sCmd = "/home/prod/twenga/tools/add_twengabuild $sID " . $aTypes[$sEnv];
261: $this->oShell->execSSH($sCmd, 'fs3:foo');
262: $this->getLogger()->info('---');
263: }
264:
265: 266: 267: 268: 269:
270: private function restartServerApache ($sServer)
271: {
272: $this->getLogger()->info("Restart Apache webserver '$sServer'.+++");
273: $sToExec = $this->processSimplePath($sServer . ':/root/apache_restart');
274: $aResult = $this->oShell->execSSH('sudo %s', $sToExec);
275: $this->getLogger()->info(implode("\n", $aResult) . '---');
276: }
277:
278: 279: 280: 281: 282:
283: private function clearServerSmartyCaches ($sServer)
284: {
285: $this->getLogger()->info("Clear Smarty caches of server '$sServer':+++");
286:
287: $sCmd = "/home/prod/twenga/tools/clear_cache $sServer smarty";
288: if (strcasecmp(strrchr($sServer, '.'), '.us1') === 0) {
289: $sCmd = 'export FORCE_TWENGA_DC=US && ' . $sCmd . ' && export FORCE_TWENGA_DC=\'\'';
290: }
291: $aResult = $this->oShell->execSSH($sCmd, 'fs3:foo');
292: $this->getLogger()->info(strip_tags(implode("\n", $aResult)) . '---');
293: }
294:
295: 296: 297: 298: 299: 300: 301: 302:
303: private function setCluster ($sServer, $bStatus)
304: {
305: $aMsgs = ($bStatus ? array('Reintegrate', 'into', '-e') : array('Remove', 'from', '-d'));
306:
307: if (preg_match('/wwwtest/i', $sServer) !== 1) {
308: $this->getLogger()->info($aMsgs[0] . " '$sServer' server $aMsgs[1] the cluster.+++");
309: $sCmd = "/home/prod/twenga/tools/wwwcluster -s $sServer $aMsgs[2]";
310: try {
311: $aResult = $this->oShell->exec($sCmd);
312: $sResult = implode("\n", $aResult);
313: if ($sResult != '') {
314: $this->getLogger()->info($sResult);
315: }
316: } catch (\RuntimeException $oException) {
317: if ($oException->getCode() == 2) {
318: $sResult = '[WARNING] ' . $oException->getMessage();
319: $this->getLogger()->warning($sResult);
320: } else {
321: throw $oException;
322: }
323: }
324: $this->getLogger()->info('---');
325: } else {
326: $this->getLogger()->info(" '$sServer' server is not handled by the cluster.");
327: }
328: }
329:
330: 331: 332:
333: public function setUp ()
334: {
335: parent::setUp();
336: $this->getLogger()->info('+++');
337: $this->oHTTPTask->setUp();
338: $this->getLogger()->info('---');
339: }
340: }
341: