From 0f71144a25b13f434078ffcbc2d8a8ff3cbdc171 Mon Sep 17 00:00:00 2001 From: Romain Quetiez Date: Fri, 8 Jan 2010 15:24:57 +0000 Subject: [PATCH] Trac#56 Improvements to the SOAP web services and to the first operation CreateIncidentTicket SVN:trunk[230] --- core/action.class.inc.php | 15 +- core/attributedef.class.inc.php | 41 ++++ core/event.class.inc.php | 135 +++++++++++- pages/testlist.inc.php | 216 +++++++++++++++---- toolkit.php | 3 + webservices/itop.wsdl | 4 - webservices/itop.wsdl.php | 21 ++ webservices/itop.wsdl.tpl | 173 ++++++++++++++++ webservices/soapserver.php | 17 +- webservices/webservices.class.inc.php | 288 +++++++++++++++++++++++--- 10 files changed, 815 insertions(+), 98 deletions(-) delete mode 100644 webservices/itop.wsdl create mode 100644 webservices/itop.wsdl.php create mode 100644 webservices/itop.wsdl.tpl diff --git a/core/action.class.inc.php b/core/action.class.inc.php index 80bdb5861..68c12a759 100644 --- a/core/action.class.inc.php +++ b/core/action.class.inc.php @@ -72,7 +72,7 @@ abstract class ActionNotification extends Action "description" => "Notification (abstract)", "key_type" => "autoincrement", "key_label" => "", - "name_attcode" => "", + "name_attcode" => "name", "state_attcode" => "", "reconc_keys" => array(), "db_table" => "priv_action_notification", @@ -116,7 +116,7 @@ class ActionEmail extends ActionNotification "description" => "Action: Email notification", "key_type" => "autoincrement", "key_label" => "", - "name_attcode" => "", + "name_attcode" => "name", "state_attcode" => "", "reconc_keys" => array(), "db_table" => "priv_action_email", @@ -215,18 +215,19 @@ class ActionEmail extends ActionNotification $sHeaders .= "Bcc: $sBCC\r\n"; } - $sOverview = "TO:$sTo, FROM:$sFrom, REPLY-TO:$sReplyTo, CC:$sCC, BCC:$sBCC, SUBJECT:$sSubject, BODY:$sBody"; - // Mail it if (mail($sTo, $sSubject, $sBody, $sHeaders)) { - $oLog = new EventNotification(); - $oLog->Set('message', 'Email sent successfully'); + $oLog = new EventNotificationEmail(); $oLog->Set('userinfo', UserRights::GetUser()); $oLog->Set('trigger_id', $oTrigger->GetKey()); $oLog->Set('action_id', $this->GetKey()); $oLog->Set('object_id', $aContextArgs['this->id']); - $oLog->Set('overview', $sOverview); + $oLog->Set('to', $sTo); + $oLog->Set('cc', $sCC); + $oLog->Set('bcc', $sBCC); + $oLog->Set('subject', $sSubject); + $oLog->Set('body', $sBody); $oLog->DBInsertNoReload(); } else diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index c73479268..6beed31b2 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -475,6 +475,47 @@ class AttributeInteger extends AttributeDBField } } +/** + * Map a boolean column to an attribute + * + * @package iTopORM + * @author Romain Quetiez + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.itop.com + * @since 1.0 + * @version $itopversion$ + */ +class AttributeBoolean extends AttributeInteger +{ + static protected function ListExpectedParams() + { + return parent::ListExpectedParams(); + //return array_merge(parent::ListExpectedParams(), array()); + } + + public function GetType() {return "Boolean";} + public function GetTypeDesc() {return "Boolean";} + public function GetEditClass() {return "Integer";} + protected function GetSQLCol() {return "TINYINT(1)";} + + public function MakeRealValue($proposedValue) + { + if ((int)$proposedValue) return true; + return false; + } + public function ScalarToSQL($value) + { + assert(is_bool($value)); + if ($value) return 1; + return 0; + } + public function SQLToScalar($value) + { + // Use cast (int) or intval() ? + return (int)$value; + } +} + /** * Map a varchar column (size < ?) to an attribute * diff --git a/core/event.class.inc.php b/core/event.class.inc.php index b50e7a4c5..833879e54 100644 --- a/core/event.class.inc.php +++ b/core/event.class.inc.php @@ -32,18 +32,15 @@ class Event extends cmdbAbstractObject ); MetaModel::Init_Params($aParams); //MetaModel::Init_InheritAttributes(); - MetaModel::Init_AddAttribute(new AttributeString("message", array("label"=>"Message", "description"=>"one line description", "allowed_values"=>null, "sql"=>"message", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); - MetaModel::Init_AddAttribute(new AttributeDate("date", array("label"=>"date", "description"=>"date and time at which the changes have been recorded", "allowed_values"=>null, "sql"=>"date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()))); - MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("label"=>"misc. info", "description"=>"caller's defined information", "allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("label"=>"user info", "description"=>"identification of the user that was doing the action that triggered this event", "allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); //MetaModel::Init_InheritFilters(); - MetaModel::Init_AddFilterFromAttribute("message"); MetaModel::Init_AddFilterFromAttribute("date"); // Display lists - MetaModel::Init_SetZListItems('details', array('finalclass', 'date', 'message')); // Attributes to be displayed for the complete details - MetaModel::Init_SetZListItems('list', array('finalclass', 'date', 'message')); // Attributes to be displayed for a list + MetaModel::Init_SetZListItems('details', array('finalclass', 'date', 'userinfo')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('list', array('finalclass', 'date')); // Attributes to be displayed for a list // Search criteria // MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form // MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form @@ -74,15 +71,14 @@ class EventNotification extends Event MetaModel::Init_AddAttribute(new AttributeExternalKey("trigger_id", array("targetclass"=>"Trigger", "jointype"=> "", "label"=>"Trigger", "description"=>"user account", "allowed_values"=>null, "sql"=>"trigger_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeExternalKey("action_id", array("targetclass"=>"Action", "jointype"=> "", "label"=>"user", "description"=>"user account", "allowed_values"=>null, "sql"=>"action_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("object_id", array("label"=>"Object id", "description"=>"object id (class defined by the trigger ?)", "allowed_values"=>null, "sql"=>"object_id", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); - MetaModel::Init_AddAttribute(new AttributeText("overview", array("label"=>"Overview", "description"=>"Complete view of the resulting email", "allowed_values"=>null, "sql"=>"overview", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_InheritFilters(); MetaModel::Init_AddFilterFromAttribute("trigger_id"); MetaModel::Init_AddFilterFromAttribute("action_id"); // Display lists - MetaModel::Init_SetZListItems('details', array('date', 'message', 'userinfo', 'trigger_id', 'action_id', 'object_id', 'overview')); // Attributes to be displayed for the complete details - MetaModel::Init_SetZListItems('list', array('date', 'message')); // Attributes to be displayed for a list + MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'trigger_id', 'action_id', 'object_id')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('list', array('date', 'userinfo')); // Attributes to be displayed for a list // Search criteria // MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form // MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form @@ -90,5 +86,126 @@ class EventNotification extends Event } +class EventNotificationEmail extends EventNotification +{ + public static function Init() + { + $aParams = array + ( + "category" => "core/cmdb", + "name" => "Email emission event", + "description" => "Trace of an email that has been sent", + "key_type" => "autoincrement", + "key_label" => "", + "name_attcode" => "", + "state_attcode" => "", + "reconc_keys" => array(), + "db_table" => "priv_event_email", + "db_key_field" => "id", + "db_finalclass_field" => "", + "display_template" => "", + ); + MetaModel::Init_Params($aParams); + MetaModel::Init_InheritAttributes(); + MetaModel::Init_AddAttribute(new AttributeText("to", array("label"=>"TO", "description"=>"TO", "allowed_values"=>null, "sql"=>"to", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeText("cc", array("label"=>"CC", "description"=>"CC", "allowed_values"=>null, "sql"=>"cc", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeText("bcc", array("label"=>"BCC", "description"=>"BCC", "allowed_values"=>null, "sql"=>"bcc", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeText("subject", array("label"=>"Subject", "description"=>"Subject", "allowed_values"=>null, "sql"=>"subject", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeText("body", array("label"=>"Body", "description"=>"Body", "allowed_values"=>null, "sql"=>"body", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + + MetaModel::Init_InheritFilters(); + + // Display lists + MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'trigger_id', 'action_id', 'object_id', 'to', 'cc', 'bcc', 'subject', 'body')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'subject')); // Attributes to be displayed for a list + // Search criteria +// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form +// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form + } + +} + +class EventIssue extends Event +{ + public static function Init() + { + $aParams = array + ( + "category" => "core/cmdb", + "name" => "Issue event", + "description" => "Trace of an issue (warning, error, etc.)", + "key_type" => "autoincrement", + "key_label" => "", + "name_attcode" => "", + "state_attcode" => "", + "reconc_keys" => array(), + "db_table" => "priv_event_issue", + "db_key_field" => "id", + "db_finalclass_field" => "", + "display_template" => "", + ); + MetaModel::Init_Params($aParams); + MetaModel::Init_InheritAttributes(); + MetaModel::Init_AddAttribute(new AttributeString("issue", array("label"=>"Issue", "description"=>"What happened", "allowed_values"=>null, "sql"=>"issue", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeString("impact", array("label"=>"Impact", "description"=>"What are the consequences", "allowed_values"=>null, "sql"=>"impact", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeString("page", array("label"=>"Page", "description"=>"HTTP entry point", "allowed_values"=>null, "sql"=>"page", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeText("arguments_post", array("label"=>"Posted arguments", "description"=>"HTTP POST arguments", "allowed_values"=>null, "sql"=>"arguments_post", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeText("arguments_get", array("label"=>"URL arguments", "description"=>"HTTP GET arguments", "allowed_values"=>null, "sql"=>"arguments_get", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeText("callstack", array("label"=>"Callstack", "description"=>"Call stack", "allowed_values"=>null, "sql"=>"callstack", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeBlob("data", array("label"=>"Data", "description"=>"More information", "allowed_values"=>null, "sql"=>"data", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); + + MetaModel::Init_InheritFilters(); + MetaModel::Init_AddFilterFromAttribute("issue"); + MetaModel::Init_AddFilterFromAttribute("impact"); + + // Display lists + MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'issue', 'impact', 'page', 'arguments_post', 'arguments_get', 'callstack', 'data')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'issue', 'impact')); // Attributes to be displayed for a list + // Search criteria +// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form +// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form + } +} + + +class EventWebService extends Event +{ + public static function Init() + { + $aParams = array + ( + "category" => "core/cmdb", + "name" => "Web service event", + "description" => "Trace of an web service call", + "key_type" => "autoincrement", + "key_label" => "", + "name_attcode" => "", + "state_attcode" => "", + "reconc_keys" => array(), + "db_table" => "priv_event_webservice", + "db_key_field" => "id", + "db_finalclass_field" => "", + "display_template" => "", + ); + MetaModel::Init_Params($aParams); + MetaModel::Init_InheritAttributes(); + MetaModel::Init_AddAttribute(new AttributeString("verb", array("label"=>"Verb", "description"=>"Name of the operation", "allowed_values"=>null, "sql"=>"verb", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + //MetaModel::Init_AddAttribute(new AttributeStructure("arguments", array("label"=>"Arguments", "description"=>"Operation arguments", "allowed_values"=>null, "sql"=>"data", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeBoolean("result", array("label"=>"Result", "description"=>"Overall success/failure", "allowed_values"=>null, "sql"=>"result", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeText("log_info", array("label"=>"Info log", "description"=>"Result info log", "allowed_values"=>null, "sql"=>"log_info", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeText("log_warning", array("label"=>"Warning log", "description"=>"Result warning log", "allowed_values"=>null, "sql"=>"log_warning", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeText("log_error", array("label"=>"Error log", "description"=>"Result error log", "allowed_values"=>null, "sql"=>"log_error", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeText("data", array("label"=>"Data", "description"=>"Result data", "allowed_values"=>null, "sql"=>"data", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + + MetaModel::Init_InheritFilters(); + + // Display lists + MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'verb', 'result', 'log_info', 'log_warning', 'log_error', 'data')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'verb', 'result')); // Attributes to be displayed for a list + // Search criteria +// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form +// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form + } +} ?> diff --git a/pages/testlist.inc.php b/pages/testlist.inc.php index 81803829d..862e41206 100644 --- a/pages/testlist.inc.php +++ b/pages/testlist.inc.php @@ -1174,32 +1174,146 @@ class TestItopWebServices extends TestWebServices } } + $aWebServices = array( + array( + 'verb' => 'GetVersion', + 'expected result' => true, + 'explain result' => 'n/a', + 'args' => array(), + ), array( 'verb' => 'CreateIncidentTicket', + 'expected result' => true, + 'explain result' => 'ok, but link attribute unknown', 'args' => array( + 'admin', /* sLogin */ + 'admin', /* sPassword */ + 'Server', /* sType */ 'desc of ticket', /* sDescription */ 'initial situation blah blah blah', /* sInitialSituation */ - array('id' => 1), /* aCallerDesc */ - array('id' => 2), /* aCustomerDesc */ - array('id' => 1), /* aWorkgroupDesc */ + 'very grave', /* sImpact */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aCallerDesc */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aWorkgroupDesc */ array( - array( - 'class' => 'logInfra', - 'search' => array('id' => 108), - 'link_values' => array('impactoche' => 'plus que critique'), + new SOAPLinkCreationSpec( + 'logInfra', + array(new SOAPSearchCondition('id', 108)), + array(new SOAPAttributeValue('impacting', 'very critical')) ), - array( - 'class' => 'bizDevice', - 'search' => array('name' => 'Router03'), - 'link_values' => array('impact' => 'ouais bof'), + new SOAPLinkCreationSpec( + 'bizDevice', + array(new SOAPSearchCondition('name', 'Router03')), + array(new SOAPAttributeValue('impact', 'who cares')) ), ), /* aImpact */ 'low' /* sSeverity */ ), ), + array( + 'verb' => 'CreateIncidentTicket', + 'expected result' => true, + 'explain result' => 'ok, but CI unknown', + 'args' => array( + 'admin', /* sLogin */ + 'admin', /* sPassword */ + 'Desktop', /* sType */ + 'PC burning', /* sDescription */ + 'The power supply suddenly started to warm up', /* sInitialSituation */ + 'The agent could not do his job', /* sImpact */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aCallerDesc */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aWorkgroupDesc */ + array( + new SOAPLinkCreationSpec( + 'logInfra', + array(new SOAPSearchCondition('id', 99999)), + array(new SOAPAttributeValue('impact', 'very critical')) + ), + ), /* aImpact */ + 'low' /* sSeverity */ + ), + ), + array( + 'verb' => 'CreateIncidentTicket', + 'expected result' => false, + 'explain result' => 'ok, no CI to attach', + 'args' => array( + 'admin', /* sLogin */ + 'admin', /* sPassword */ + 'Network', /* sType */ + 'Houston not reachable', /* sDescription */ + 'Tried to join the shuttle', /* sInitialSituation */ + 'Could not talk to my wife', /* sImpact */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aCallerDesc */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aWorkgroupDesc */ + array( + ), /* aImpact */ + 'low' /* sSeverity */ + ), + ), + array( + 'verb' => 'CreateIncidentTicket', + 'expected result' => false, + 'explain result' => 'caller unknown', + 'args' => array( + 'admin', /* sLogin */ + 'admin', /* sPassword */ + 'Network', /* sType */ + 'Houston not reachable', /* sDescription */ + 'Tried to join the shuttle', /* sInitialSituation */ + 'Could not talk to my wife', /* sImpact */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1000))), /* aCallerDesc */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aWorkgroupDesc */ + array( + ), /* aImpact */ + 'low' /* sSeverity */ + ), + ), + array( + 'verb' => 'CreateIncidentTicket', + 'expected result' => false, + 'explain result' => 'wrong password', + 'args' => array( + 'admin', /* sLogin */ + 'xxxxx', /* sPassword */ + 'Network', /* sType */ + 'Houston not reachable', /* sDescription */ + 'Tried to join the shuttle', /* sInitialSituation */ + 'Could not talk to my wife', /* sImpact */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aCallerDesc */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aWorkgroupDesc */ + array( + ), /* aImpact */ + 'low' /* sSeverity */ + ), + ), + array( + 'verb' => 'CreateIncidentTicket', + 'expected result' => false, + 'explain result' => 'wrong login', + 'args' => array( + 'xxxxx', /* sLogin */ + 'yyyyy', /* sPassword */ + 'Network', /* sType */ + 'Houston not reachable', /* sDescription */ + 'Tried to join the shuttle', /* sInitialSituation */ + 'Could not talk to my wife', /* sImpact */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aCallerDesc */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */ + new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aWorkgroupDesc */ + array( + ), /* aImpact */ + 'low' /* sSeverity */ + ), + ), ); + class TestSoap extends TestSoapWebService { static public function GetName() {return 'Test SOAP';} @@ -1207,34 +1321,56 @@ class TestSoap extends TestSoapWebService protected function DoExecute() { - $this->m_SoapClient = new SoapClient( -// null, - "http://localhost:81/trunk/webservices/Itop.wsdl", + global $aSOAPMapping; + + // this file is generated dynamically with location = here + $sWsdlUri = 'http'.(empty($_SERVER['HTTPS']) ? '' : 's').'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/../webservices/itop.wsdl.php'; + + ini_set("soap.wsdl_cache_enabled","0"); + $this->m_SoapClient = new SoapClient + ( + $sWsdlUri, array( - //'location' => 'http://localhost:81/trunk/webservices/soapserver.php', - //'uri' => 'http://test-itop/', - 'login' => 'admin', - 'password' => 'admin', - // note: using the classmap functionality lead to APACHE fault on the server side - //'classmap' => array('stdClass' => 'ItopError'), + //'uri' => 'http://soap-itop/', + 'classmap' => $aSOAPMapping, 'trace' => 1, ) ); + if (false) + { + print "
\n"; 
+			print_r($this->m_SoapClient->__getTypes());
+			print "
\n"; + } + global $aWebServices; - $aWebService = $aWebServices[0]; + foreach ($aWebServices as $iPos => $aWebService) + { + echo "

SOAP call #$iPos ".$aWebService['explain result']."

\n"; + try + { + $oRes = call_user_func_array(array($this->m_SoapClient, $aWebService['verb']), $aWebService['args']); + } + catch(SoapFault $e) + { + print "
\n"; 
+				print "Request: \n".htmlspecialchars($this->m_SoapClient->__getLastRequest()) ."\n"; 
+				print "Response: \n".htmlspecialchars($this->m_SoapClient->__getLastResponse())."\n"; 
+				print "
"; + print "Response in HTML:

".$this->m_SoapClient->__getLastResponse()."

"; + return false; + } -// $oRes = $this->m_SoapClient->CreateIncidentTicket(); - $oRes = call_user_func_array(array($this->m_SoapClient, $aWebService['verb']), $aWebService['args']); - - echo "
\n";
-		print_r($oRes);
-		echo "
\n"; - -print "
\n"; 
-print "Request: \n".htmlspecialchars($this->m_SoapClient->__getLastRequest()) ."\n"; 
-print "Response: \n".htmlspecialchars($this->m_SoapClient->__getLastResponse())."\n"; 
-print "
"; + echo "
\n";
+			print_r($oRes);
+			echo "
\n"; + + print "
\n"; 
+			print "Request: \n".htmlspecialchars($this->m_SoapClient->__getLastRequest()) ."\n"; 
+			print "Response: \n".htmlspecialchars($this->m_SoapClient->__getLastResponse())."\n"; 
+			print "
"; + } return true; } @@ -1249,14 +1385,16 @@ class TestWebServicesDirect extends TestBizModel protected function DoExecute() { - global $aWebServices; - $aWebService = $aWebServices[0]; - $oWebServices = new WebServices(); - $oRes = call_user_func_array(array($oWebServices, $aWebService['verb']), $aWebService['args']); - echo "
\n";
-		print_r($oRes);
-		echo "
\n"; + + global $aWebServices; + foreach ($aWebServices as $aWebService) + { + $oRes = call_user_func_array(array($oWebServices, $aWebService['verb']), $aWebService['args']); + echo "
\n";
+			print_r($oRes);
+			echo "
\n"; + } return true; } } diff --git a/toolkit.php b/toolkit.php index b71abae3c..707bdb520 100644 --- a/toolkit.php +++ b/toolkit.php @@ -15,6 +15,9 @@ echo "

Itop consultant

\n"; echo "Check model, Create DB, Update DB (new class, new attribute)
\n"; echo "Backup and restore (shortcut)
\n"; echo "Objects schema (shortcut)
\n"; +echo "

Web services

\n"; +echo "Available functions
\n"; +echo "WSDL (dynamically generated)
\n"; echo "

Not working or deprecated

\n"; echo "Data generator
\n"; echo "ITop finder
\n"; diff --git a/webservices/itop.wsdl b/webservices/itop.wsdl deleted file mode 100644 index ba9027337..000000000 --- a/webservices/itop.wsdl +++ /dev/null @@ -1,4 +0,0 @@ - - -Create an incident ticket from a monitoring system -Some CIs might be specified (by their name/IP) \ No newline at end of file diff --git a/webservices/itop.wsdl.php b/webservices/itop.wsdl.php new file mode 100644 index 000000000..db107fae2 --- /dev/null +++ b/webservices/itop.wsdl.php @@ -0,0 +1,21 @@ + diff --git a/webservices/itop.wsdl.tpl b/webservices/itop.wsdl.tpl new file mode 100644 index 000000000..32f6edf19 --- /dev/null +++ b/webservices/itop.wsdl.tpl @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Get the current version of Itop + As this service is very simple, it is a test to get trained for more complex operations + + + + + + + Create a ticket, return information about reconciliation on external keys and the created ticket + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webservices/soapserver.php b/webservices/soapserver.php index c644cb1b3..bd263bc21 100644 --- a/webservices/soapserver.php +++ b/webservices/soapserver.php @@ -20,18 +20,17 @@ require_once('../application/startup.inc.php'); require('./webservices.class.inc.php'); +// this file is generated dynamically with location = here +$sWsdlUri = 'http'.(empty($_SERVER['HTTPS']) ? '' : 's').'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/../webservices/itop.wsdl.php'; -// pb ? - login_web_page::DoLogin(); // Check user rights and prompt if needed -// Main program +ini_set("soap.wsdl_cache_enabled","0"); -$oSoapServer = new SoapServer( - null, - //"http://localhost:81/trunk/webservices/Itop.wsdl", // to be a file generated dynamically with location = here +$oSoapServer = new SoapServer +( + $sWsdlUri, array( - 'uri' => 'http://test-itop/', - // note: using the classmap and no WSDL spec causes a fault in APACHE (looks like an infinite loop) - //'classmap' => array('ItopErrorSOAP' => 'ItopError') + 'classmap' => $aSOAPMapping ) ); // $oSoapServer->setPersistence(SOAP_PERSISTENCE_SESSION); @@ -51,6 +50,6 @@ else echo "
  • $sFunc
  • \n"; } echo "\n"; - echo ""; + echo "

    Here the WSDL file

    "; } ?> diff --git a/webservices/webservices.class.inc.php b/webservices/webservices.class.inc.php index f8f1864ec..e17163ed0 100644 --- a/webservices/webservices.class.inc.php +++ b/webservices/webservices.class.inc.php @@ -1,5 +1,7 @@ m_bStatus = true; + $this->m_aResult = array(); $this->m_aErrors = array(); $this->m_aWarnings = array(); $this->m_aInfos = array(); } + public function ToSoapStructure() + { + $aResults = array(); + foreach($this->m_aResult as $sLabel => $aData) + { + $aValues = array(); + foreach($aData as $sKey => $value) + { + $aValues[] = new SoapResultData($sKey, $value); + } + $aResults[] = new SoapResultMessage($sLabel, $aValues); + } + $aInfos = array(); + foreach($this->m_aInfos as $sMessage) + { + $aInfos[] = new SoapLogMessage($sMessage); + } + $aWarnings = array(); + foreach($this->m_aWarnings as $sMessage) + { + $aWarnings[] = new SoapLogMessage($sMessage); + } + $aErrors = array(); + foreach($this->m_aErrors as $sMessage) + { + $aErrors[] = new SoapLogMessage($sMessage); + } + + $oRet = new SOAPResult( + $this->m_bStatus, + $aResults, + new SOAPResultLog($aErrors), + new SOAPResultLog($aWarnings), + new SOAPResultLog($aInfos) + ); + + return $oRet; + } + /** * Did the current processing encounter a stopper issue ? * @@ -67,21 +109,37 @@ class WebServiceResult return $this->m_bStatus; } + /** + * Add result details - object reference + * + * @param string sLabel + * @param object oObject + */ + public function AddResultObject($sLabel, $oObject) + { + $this->m_aResult[$sLabel] = array( + 'id' => $oObject->GetKey(), + 'name' => $oObject->GetName(), + 'url' => $oObject->GetHyperlink(), + ); + } + /** * Log an error * - * @param description $sDescription + * @param string sDescription */ public function LogError($sDescription) { $this->m_aErrors[] = $sDescription; - $this->m_bStatus = false; + // Note: SOAP do transform false into null + $this->m_bStatus = 0; } /** * Log a warning * - * @param description $sDescription + * @param string sDescription */ public function LogWarning($sDescription) { @@ -91,8 +149,8 @@ class WebServiceResult /** * Log an error or a warning * - * @param string $sDescription - * @param boolean $bIsStopper + * @param string sDescription + * @param boolean bIsStopper */ public function LogIssue($sDescription, $bIsStopper = true) { @@ -109,15 +167,77 @@ class WebServiceResult { $this->m_aInfos[] = $sDescription; } + + protected static function LogToText($aLog) + { + return implode("\n", $aLog); + } + + public function GetInfoAsText() + { + return self::LogToText($this->m_aInfos); + } + + public function GetWarningsAsText() + { + return self::LogToText($this->m_aWarnings); + } + + public function GetErrorsAsText() + { + return self::LogToText($this->m_aErrors); + } + + public function GetReturnedDataAsText() + { + $sRet = ''; + foreach ($this->m_aResult as $sKey => $value) + { + $sRet .= "===== $sKey =====\n"; + $sRet .= print_r($value, true); + } + return $sRet; + } +} + + +class WebServiceResultFailedLogin extends WebServiceResult +{ + public function __construct($sLogin) + { + parent::__construct(); + $this->LogError("Wrong credentials: '$sLogin'"); + } } class WebServices { + /** + * Helper to log a service delivery + * + * @param string sVerb + * @param array aArgs + * @param WebServiceResult oRes + * + */ + protected function LogUsage($sVerb, $oRes) + { + $oLog = new EventWebService(); + $oLog->Set('userinfo', UserRights::GetUser()); + $oLog->Set('verb', $sVerb); + $oLog->Set('result', $oRes->IsOk()); + $oLog->Set('log_info', $oRes->GetInfoAsText()); + $oLog->Set('log_warning', $oRes->GetWarningsAsText()); + $oLog->Set('log_error', $oRes->GetErrorsAsText()); + $oLog->Set('data', $oRes->GetReturnedDataAsText()); + $oLog->DBInsertNoReload(); + } + /** * Helper to set an external key * * @param string sAttCode - * @param array aCallerDesc + * @param array aExtKeyDesc * @param DBObject oTargetObj * @param WebServiceResult oRes * @@ -190,6 +310,11 @@ class WebServices $aItemsNotFound = array(); foreach ($aLinkList as $aItemData) { + if (!array_key_exists('class', $aItemData)) + { + $oRes->LogWarning("Linked object descriptor: missing 'class' specification"); + continue; // skip + } $sTargetClass = $aItemData['class']; if (!MetaModel::IsValidClass($sTargetClass)) { @@ -273,6 +398,84 @@ class WebServices return $aItemsNotFound; } + + static protected function SoapStructToExternalKeySearch(SoapExternalKeySearch $oExternalKeySearch) + { + $aRes = array(); + foreach($oExternalKeySearch->conditions as $oSearchCondition) + { + $aRes[$oSearchCondition->attcode] = $oSearchCondition->value; + } + return $aRes; + } + + static protected function SoapStructToLinkCreationSpec(SoapLinkCreationSpec $oLinkCreationSpec) + { + $aRes = array + ( + 'class' => $oLinkCreationSpec->class, + 'search' => array(), + 'link_values' => array(), + ); + + foreach($oLinkCreationSpec->conditions as $oSearchCondition) + { + $aRes['search'][$oSearchCondition->attcode] = $oSearchCondition->value; + } + + foreach($oLinkCreationSpec->attributes as $oAttributeValue) + { + $aRes['link_values'][$oAttributeValue->attcode] = $oAttributeValue->value; + } + + return $aRes; + } + + + /** + * Get the server version (TODO: get it dynamically, where ?) + * + * @return WebServiceResult + */ + public function GetVersion() + { + return "0.8"; + } + + public function CreateIncidentTicket($sLogin, $sPassword, $sType, $sDescription, $sInitialSituation, $sImpact, $oCallerDesc, $oCustomerDesc, $oWorkgroupDesc, $aSOAPImpactedCIs, $sSeverity) + { + if (!UserRights::Login($sLogin, $sPassword)) + { + $oRes = new WebServiceResultFailedLogin($sLogin); + $this->LogUsage(__FUNCTION__, $oRes); + + return $oRes->ToSoapStructure(); + } + + $aCallerDesc = self::SoapStructToExternalKeySearch($oCallerDesc); + $aCustomerDesc = self::SoapStructToExternalKeySearch($oCustomerDesc); + $aWorkgroupDesc = self::SoapStructToExternalKeySearch($oWorkgroupDesc); + $aImpactedCIs = array(); + foreach($aSOAPImpactedCIs as $oImpactedCIs) + { + $aImpactedCIs[] = self::SoapStructToLinkCreationSpec($oImpactedCIs); + } + + $oRes = $this->_CreateIncidentTicket + ( + $sType, + $sDescription, + $sInitialSituation, + $sImpact, + $aCallerDesc, + $aCustomerDesc, + $aWorkgroupDesc, + $aImpactedCIs, + $sSeverity + ); + return $oRes->ToSoapStructure(); + } + /** * Create an incident ticket from a monitoring system * Some CIs might be specified (by their name/IP) @@ -287,36 +490,61 @@ class WebServices * * @return WebServiceResult */ - function CreateIncidentTicket($sDescription, $sInitialSituation, $aCallerDesc, $aCustomerDesc, $aWorkgroupDesc, $aImpactedCIs, $sSeverity) + protected function _CreateIncidentTicket($sType, $sDescription, $sInitialSituation, $sImpact, $aCallerDesc, $aCustomerDesc, $aWorkgroupDesc, $aImpactedCIs, $sSeverity) { + $oRes = new WebServiceResult(); - new CMDBChange(); - $oMyChange = MetaModel::NewObject("CMDBChange"); - $oMyChange->Set("date", time()); - $oMyChange->Set("userinfo", "Administrator"); - $iChangeId = $oMyChange->DBInsertNoReload(); - - $oNewTicket = MetaModel::NewObject('bizIncidentTicket'); - $oNewTicket->Set('title', $sDescription); - $oNewTicket->Set('initial_situation', $sInitialSituation); - $oNewTicket->Set('severity', $sSeverity); - - $this->SetExternalKey('org_id', $aCustomerDesc, $oNewTicket, $oRes); - $this->SetExternalKey('caller_id', $aCallerDesc, $oNewTicket, $oRes); - $this->SetExternalKey('workgroup_id', $aWorkgroupDesc, $oNewTicket, $oRes); - - $aDevicesNotFound = $this->AddLinkedObjects('impacted_infra_manual', 'logInfra', $aImpactedCIs, $oNewTicket, $oRes); - if (count($aDevicesNotFound) > 0) + try { - $oTargetObj->Set('impact', implode(', ', $aDevicesNotFound)); + new CMDBChange(); + $oMyChange = MetaModel::NewObject("CMDBChange"); + $oMyChange->Set("date", time()); + $oMyChange->Set("userinfo", "Administrator"); + $iChangeId = $oMyChange->DBInsertNoReload(); + + $oNewTicket = MetaModel::NewObject('bizIncidentTicket'); + $oNewTicket->Set('type', $sType); + $oNewTicket->Set('title', $sDescription); + $oNewTicket->Set('initial_situation', $sInitialSituation); + $oNewTicket->Set('severity', $sSeverity); + + $this->SetExternalKey('org_id', $aCustomerDesc, $oNewTicket, $oRes); + $this->SetExternalKey('caller_id', $aCallerDesc, $oNewTicket, $oRes); + $this->SetExternalKey('workgroup_id', $aWorkgroupDesc, $oNewTicket, $oRes); + + $aDevicesNotFound = $this->AddLinkedObjects('impacted_infra_manual', 'logInfra', $aImpactedCIs, $oNewTicket, $oRes); + if (count($aDevicesNotFound) > 0) + { + $oNewTicket->Set('impact', $sImpact.' - Related CIs: '.implode(', ', $aDevicesNotFound)); + } + else + { + $oNewTicket->Set('impact', $sImpact); + } + + if (!$oNewTicket->CheckToInsert()) + { + $oRes->LogError("The ticket could not be created due to forbidden values (or inconsistent values)"); + } + + if ($oRes->IsOk()) + { + $iId = $oNewTicket->DBInsertTrackedNoReload($oMyChange); + $oRes->LogInfo("Created ticket #$iId"); + $oRes->AddResultObject('created', $oNewTicket); + } + } + catch (CoreException $e) + { + $oRes->LogError($e->getMessage()); + } + catch (Exception $e) + { + $oRes->LogError($e->getMessage()); } - if ($oRes->IsOk()) - { - $iId = $oNewTicket->DBInsertTrackedNoReload($oMyChange); - $oRes->LogInfo("Created ticket #$iId"); - } + $this->LogUsage(__FUNCTION__, $oRes); return $oRes; } }