public function save(Default_Model_VOMS $value) { global $application; $data = array(); if (!isnull($value->getVoID())) { $data['void'] = $value->getVoID(); } if (!isnull($value->getHostname())) { $data['hostname'] = $value->getHostname(); } if (!isnull($value->getHttpsPort())) { $data['https_port'] = $value->getHttpsPort(); } if (!isnull($value->getVomsesPort())) { $data['vomses_port'] = $value->getVomsesPort(); } if (!isnull($value->getIsAdmin())) { $data['is_admin'] = $this->pgBool($value->getIsAdmin()); } if (!isnull($value->getMemberListUrl())) { $data['member_list_url'] = $value->getMemberListUrl(); } $q1 = array('void = ?', 'hostname = ?'); $q2 = array($value->void, $value->hostname); $select = $this->getDbTable()->select(); for ($i = 0; $i < count($q1); $i++) { $select->where($q1[$i], $q2[$i]); } $new_entry = count($this->getDbTable()->fetchAll($select)) == 0; if ($new_entry) { $this->getDbTable()->insert($data); } else { $s = array(); for ($i = 0; $i < count($q1); $i++) { $s[] = $this->getDbTable()->getAdapter()->quoteInto($q1[$i], $q2[$i]); } $this->getDbTable()->update($data, $s); } }
private function syncEGIVOs() { if ($this->gridops_is_down()) { error_log("EGI Operations portal is in downtime. EGI VO sync aborted"); ExternalDataNotification::sendNotification('VO::syncEGIVOs', "EGI Operations portal is in downtime. EGI VO sync aborted", ExternalDataNotification::MESSAGE_TYPE_ERROR); return false; } db()->setFetchMode(Zend_Db::FETCH_OBJ); $rs = db()->query("SELECT id, name, enabled, url FROM vo_sources WHERE name = 'EGI Operations Portal'")->fetchAll(); $enabled = false; $uri = null; if (count($rs) > 0) { $rs = $rs[0]; if (filter_var($rs->enabled, FILTER_VALIDATE_BOOLEAN) === true) { $enabled = true; } $uri = $rs->url; } if (!$enabled) { error_log("EGI Operations Portal VO source is disabled; will not sync"); ExternalDataNotification::sendNotification('VO::syncEGIVOs', "EGI Operations Portal VO source is disabled; will not sync", ExternalDataNotification::MESSAGE_TYPE_ERROR); return false; } $inTransaction = false; try { // get entries $ch = curl_init(); if (is_null($uri)) { $uri = "http://operations-portal.egi.eu/xml/voIDCard/all/true"; } curl_setopt($ch, CURLOPT_URL, $uri); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, 181, 1 | 2); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSLCERT, APPLICATION_PATH . '/../bin/sec/usercert.pem'); curl_setopt($ch, CURLOPT_SSLKEY, APPLICATION_PATH . '/../bin/sec/userkey.pem'); $headers = apache_request_headers(); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $xml = curl_exec($ch); if ($xml === false) { error_log("error in syncEGIVOs: " . var_export(curl_error($ch), true)); ExternalDataNotification::sendNotification('VO::syncEGIVOs', var_export(curl_error($ch), true), ExternalDataNotification::MESSAGE_TYPE_ERROR); return false; } @curl_close($ch); // sort entries $xf = APPLICATION_PATH . '/../bin/sort_vos.xsl'; $xsl = new DOMDocument(); $xsl->load($xf); $proc = new XSLTProcessor(); $proc->registerPHPFunctions(); $proc->importStylesheet($xsl); $xml2 = new DOMDocument(); $xml2->loadXML($xml, LIBXML_NSCLEAN | LIBXML_COMPACT); $xml = $proc->transformToXml($xml2); /* NOT needed since the EGI OPS VO dump XML schema change * // convert sciclass IDs to discipline IDs $xsl = new DOMDocument(); db()->setFetchMode(Zend_Db::FETCH_BOTH); $xsltable = db()->query('SELECT array_to_string(array_agg(\'<xsl:when test=". = \' || sciclassid::text || \'"><xsl:text>\' || disciplineid::text || \'</xsl:text></xsl:when>\'),E\'\n\') FROM disc_to_sciclass;')->fetchAll(); $xsltable = $xsltable[0]; $xsltable = $xsltable[0]; $xsltable2 = db()->query('SELECT array_to_string(array_agg(\'<xsl:when test=". = \' || sciclassid::text || \'"><xsl:text>\' || parentid::text || \'</xsl:text></xsl:when>\'),E\'\n\') FROM disc_to_sciclass;')->fetchAll(); $xsltable2 = $xsltable2[0]; $xsltable2 = $xsltable2[0]; $xsltable3 = db()->query('SELECT array_to_string(array_agg(\'<xsl:when test=". = \' || sciclassid::text || \'"><xsl:text>\' || ord::text || \'</xsl:text></xsl:when>\'),E\'\n\') FROM disc_to_sciclass;')->fetchAll(); $xsltable3 = $xsltable3[0]; $xsltable3 = $xsltable3[0]; $xsldata = '<' . '?xml version="1.0" encoding="UTF-8"?' . '> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml"/> <xsl:strip-space elements="*" /> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="//Disciplines/Discipline/@id"> <xsl:attribute name="id"> <xsl:choose> ' . ' ' . $xsltable . ' <xsl:otherwise> <xsl:value-of select="." /> </xsl:otherwise> </xsl:choose> </xsl:attribute> <xsl:attribute name="parentid"> <xsl:choose> ' . ' ' . $xsltable2 . ' <xsl:otherwise> <xsl:text></xsl:text> </xsl:otherwise> </xsl:choose> </xsl:attribute> <xsl:attribute name="order"> <xsl:choose> ' . ' ' . $xsltable3 . ' <xsl:otherwise> <xsl:text></xsl:text> </xsl:otherwise> </xsl:choose> </xsl:attribute> </xsl:template> </xsl:stylesheet> '; $xsl->loadXML($xsldata); $proc = new XSLTProcessor(); $proc->registerPHPFunctions(); $proc->importStylesheet($xsl); $xml2 = new DOMDocument(); $xml2->loadXML($xml, LIBXML_NSCLEAN | LIBXML_COMPACT); $xml = $proc->transformToXml($xml2); */ // cache entries // keep a backup of the old file, in order to revert it in case the transaction fails @exec("mv -f " . $this->vofile . ".old " . $this->vofile . ".old.bak"); @exec("cp " . $this->vofile . " " . $this->vofile . ".old"); $f = fopen($this->vofile, "w"); fwrite($f, $xml); fclose($f); // update database if ($this->validateXMLCache($xml) && @md5_file($this->vofile) !== @md5_file($this->vofile . ".old")) { error_log("Sync'ing EGI VOs..."); db()->beginTransaction(); $inTransaction = true; db()->query("ALTER TABLE vos DISABLE TRIGGER tr_vos_99_refresh_permissions"); db()->query("ALTER TABLE vos DISABLE TRIGGER rtr__vos_cache_delta"); db()->query("ALTER TABLE egiops.vo_contacts DISABLE TRIGGER tr_egiops_vo_contacts_99_refresh_permissions"); db()->query("DELETE FROM egiops.vo_contacts"); // will be repopulated later on db()->query("DELETE FROM egiops.vos"); $xmlobj = new SimpleXMLElement($xml); $xvos = $xmlobj->xpath("//VoDump/IDCard"); // add new VOs and update existing VOs foreach ($xvos as $xvo) { $att = $xvo->attributes(); $vd = strval($xvo->ValidationDate); if (substr($vd, 0, 4) === "0000") { $vd = null; } $xdiscs = $xvo->xpath("./Disciplines"); $xdiscs = $this->parseDisc($xdiscs[0]); $discs = array(); foreach ($xdiscs as $xdisc) { $discs[] = $xdisc["id"]; } db()->query("INSERT INTO egiops.vos (name, scope, validated, description, homepage, enrollment, aup, domainname, disciplineid, alias, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, (?)::int[], ?, ?)", array(strtolower(trim($att["Name"])), trim($xvo->Scope), $vd, trim($xvo->Description), trim($xvo->HomepageUrl), trim($xvo->EnrollmentUrl), trim($xvo->AUP), trim($xvo->Discipline), php_to_pg_array($discs, false), trim($att["Alias"]), trim($att["Status"]))); } db()->query("UPDATE vos SET\n\t\t\t\t\tscope = x.scope,\n\t\t\t\t\tvalidated = x.validated,\n\t\t\t\t\tdescription = x.description,\n\t\t\t\t\thomepage = x.homepage,\n\t\t\t\t\tenrollment = x.enrollment,\n\t\t\t\t\taup = x.aup,\n\t\t\t\t\tdomainid = COALESCE((SELECT id FROM domains WHERE LOWER(SUBSTRING(domains.name,1,10)) = LOWER(SUBSTRING(x.domainname,1,10))), 8),\n\t\t\t\t\tdisciplineid = x.disciplineid,\n\t\t\t\t\talias = x.alias,\n\t\t\t\t\tstatus = x.status\n\t\t\t\t\tFROM egiops.vos as x WHERE vos.name = x.name AND vos.sourceid = (SELECT id FROM vo_sources WHERE name = 'EGI Operations Portal')"); db()->query("INSERT INTO vos (name,scope,validated,description,homepage,enrollment,aup,domainid,disciplineid,alias,status,sourceid) SELECT name,scope,validated,description,homepage,enrollment,aup,COALESCE((SELECT id FROM domains WHERE LOWER(SUBSTRING(name,1,10)) = LOWER(SUBSTRING(domainname,1,10))), 8),x.disciplineid,alias,status,(SELECT id FROM vo_sources WHERE name = 'EGI Operations Portal') AS sourceid FROM egiops.vos AS x WHERE NOT EXISTS (SELECT * FROM vos AS y WHERE y.name = x.name AND y.sourceid = (SELECT id FROM vo_sources WHERE name = 'EGI Operations Portal'))"); db()->query("UPDATE vos SET deleted = TRUE WHERE sourceid = 1 AND LOWER(name) NOT IN (SELECT LOWER(name) FROM egiops.vos) AND NOT deleted"); db()->query("UPDATE vos SET deleted = FALSE, deletedon = NULL WHERE sourceid = 1 AND LOWER(name) IN (SELECT LOWER(name) FROM egiops.vos) AND deleted"); foreach ($xvos as $xvo) { // sync vo / middleware relations. Remove existing and repopulate $att = $xvo->attributes(); db()->setFetchMode(Zend_Db::FETCH_OBJ); db()->query('DELETE FROM vo_middlewares WHERE void = (SELECT id FROM vos WHERE name = ? AND sourceid = 1)', array(strtolower(trim($att["Name"]))))->fetchAll(); if ($xvo->Middlewares) { if (strval($xvo->Middlewares->attributes()->gLite) == "1") { db()->query('INSERT INTO vo_middlewares (void, middlewareid) VALUES ((SELECT id FROM vos WHERE name = ? AND sourceid = 1), 1)', array(strtolower(trim($att["Name"]))))->fetchAll(); } if (strval($xvo->Middlewares->attributes()->ARC) == "1") { db()->query('INSERT INTO vo_middlewares (void, middlewareid) VALUES ((SELECT id FROM vos WHERE name = ? AND sourceid = 1), 2)', array(strtolower(trim($att["Name"]))))->fetchAll(); } if (strval($xvo->Middlewares->attributes()->UNICORE) == "1") { db()->query('INSERT INTO vo_middlewares (void, middlewareid) VALUES ((SELECT id FROM vos WHERE name = ? AND sourceid = 1), 3)', array(strtolower(trim($att["Name"]))))->fetchAll(); } if (strval($xvo->Middlewares->attributes()->GLOBUS) == "1") { db()->query('INSERT INTO vo_middlewares (void, middlewareid) VALUES ((SELECT id FROM vos WHERE name = ? AND sourceid = 1), 4)', array(strtolower(trim($att["Name"]))))->fetchAll(); } } // sync vo_resources. db()->query("SAVEPOINT sync_egi_vos_resources"); $release_resources_savepoint = true; try { db()->query("DELETE FROM vo_resources WHERE void = (SELECT id FROM vos WHERE name = ? AND sourceid = 1)", array(strtolower(trim($att["Name"]))))->fetchAll(); if ($xvo->Ressources) { $xres = $xmlobj->xpath("//VoDump/IDCard[translate(@Name,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')='" . strtoupper(trim($att["Name"])) . "']/Ressources/*"); foreach ($xres as $xr) { db()->query("INSERT INTO vo_resources (void, name, value) SELECT (SELECT id FROM vos WHERE name = ? AND sourceid = 1 AND NOT deleted), ?, ? WHERE NOT EXISTS (SELECT * FROM vo_resources WHERE void = (SELECT id FROM vos WHERE name = ? AND sourceid = 1 AND NOT deleted) AND name = ?)", array(strtolower(trim($att["Name"])), strval($xr->getName()), strval($xr), strtolower(trim($att["Name"])), strval($xr->getName())))->fetchAll(); } } } catch (Exception $e) { error_log("Error while syncing EGI vo resources for VO " . $att["Name"]); $release_resources_savepoint = false; db()->query("ROLLBACK TO SAVEPOINT sync_egi_vos_resources"); } if ($release_resources_savepoint) { db()->query("RELEASE SAVEPOINT sync_egi_vos_resources"); } // sync vo / contacts relations. $xcontacts = $xvo->xpath("./Contacts/Individuals/Contact"); foreach ($xcontacts as $xcontact) { db()->query("INSERT INTO egiops.vo_contacts (vo, name, role, email, dn) VALUES (?,?,?,?,?);", array(strtolower(trim($att["Name"])), str_replace("'", '’', trim($xcontact->Name)), trim($xcontact->Role), trim($xcontact->Email), str_replace("'", '’', trim($xcontact->DN)))); } // sync vo / voms relations. db()->query('DELETE FROM vomses WHERE void = (SELECT id FROM vos WHERE name = ? AND sourceid = 1)', array(strtolower(trim($att["Name"])))); $void = db()->query("SELECT id FROM vos WHERE name = ?", array(strtolower(trim($att["Name"]))))->fetchAll(); $void = $void[0]->id; $xvomses = $xvo->xpath("./gLiteConf/VOMSServers/VOMS_Server"); foreach ($xvomses as $xvoms) { $voms = new Default_Model_VOMS(); $voms->void = $void; $voms->httpsPort = strval($xvoms->attributes()->HttpsPort); $voms->vomsesPort = strval($xvoms->attributes()->VomsesPort); $voms->isAdmin = strval($xvoms->attributes()->IsVomsAdminServer); $voms->memberListUrl = strval($xvoms->attributes()->MembersListUrl); $voms->hostname = strval($xvoms->hostname); $voms->save(); } } db()->commit(); db()->query("ALTER TABLE vos ENABLE TRIGGER tr_vos_99_refresh_permissions"); db()->query("ALTER TABLE egiops.vo_contacts ENABLE TRIGGER tr_egiops_vo_contacts_99_refresh_permissions"); db()->query("ALTER TABLE vos ENABLE TRIGGER rtr__vos_cache_delta"); db()->query("SELECT rebuild_fulltext_index('vos');"); db()->query("NOTIFY clean_cache;"); db()->query("SELECT request_permissions_refresh()"); error_log("EGI VOs sync'ed"); } else { // no need to sync @exec("rm -f " . $this->vofile . ".old.bak"); return false; } } catch (Exception $e) { $xml = false; if ($inTransaction) { $db = db(); @$db->rollBack(); } db()->query("ALTER TABLE vos ENABLE TRIGGER tr_vos_99_refresh_permissions"); db()->query("ALTER TABLE egiops.vo_contacts ENABLE TRIGGER tr_egiops_vo_contacts_99_refresh_permissions"); db()->query("ALTER TABLE vos ENABLE TRIGGER rtr__vos_cache_delta"); db()->query("SELECT request_permissions_refresh()"); // transaction failed. revert XML files to previous state @exec("mv -f " . $this->vofile . ".old " . $this->vofile); @exec("mv -f " . $this->vofile . ".old.bak " . $this->vofile . ".old"); error_log('Error while syncing EGI VOs: ' . $e); ExternalDataNotification::sendNotification('VO::syncEGIVOs', $e->getMessage(), ExternalDataNotification::MESSAGE_TYPE_ERROR); } @exec("rm -f " . $this->vofile . ".old.bak"); return $xml; }