PageRenderTime 46ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/Zend/Service/SqlAzure/Management/Client.php

http://grupal.googlecode.com/
PHP | 609 lines | 316 code | 69 blank | 224 comment | 75 complexity | 5d0e541a4802e6c03955c3bb7295335b MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Service_WindowsAzure
  17. * @subpackage Management
  18. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /**
  23. * @see Zend_Http_Client
  24. */
  25. require_once 'Zend/Http/Client.php';
  26. /**
  27. * @see Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract
  28. */
  29. require_once 'Zend/Service/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
  30. /**
  31. * @see Zend_Service_SqlAzure_Management_ServerInstance
  32. */
  33. require_once 'Zend/Service/SqlAzure/Management/ServerInstance.php';
  34. /**
  35. * @see Zend_Service_SqlAzure_Management_FirewallRuleInstance
  36. */
  37. require_once 'Zend/Service/SqlAzure/Management/FirewallRuleInstance.php';
  38. /**
  39. * @category Zend
  40. * @package Zend_Service_SqlAzure
  41. * @subpackage Management
  42. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  43. * @license http://framework.zend.com/license/new-bsd New BSD License
  44. */
  45. class Zend_Service_SqlAzure_Management_Client
  46. {
  47. /**
  48. * Management service URL
  49. */
  50. const URL_MANAGEMENT = "https://management.database.windows.net:8443";
  51. /**
  52. * Operations
  53. */
  54. const OP_OPERATIONS = "operations";
  55. const OP_SERVERS = "servers";
  56. const OP_FIREWALLRULES = "firewallrules";
  57. /**
  58. * Current API version
  59. *
  60. * @var string
  61. */
  62. protected $_apiVersion = '1.0';
  63. /**
  64. * Subscription ID
  65. *
  66. * @var string
  67. */
  68. protected $_subscriptionId = '';
  69. /**
  70. * Management certificate path (.PEM)
  71. *
  72. * @var string
  73. */
  74. protected $_certificatePath = '';
  75. /**
  76. * Management certificate passphrase
  77. *
  78. * @var string
  79. */
  80. protected $_certificatePassphrase = '';
  81. /**
  82. * Zend_Http_Client channel used for communication with REST services
  83. *
  84. * @var Zend_Http_Client
  85. */
  86. protected $_httpClientChannel = null;
  87. /**
  88. * Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract instance
  89. *
  90. * @var Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract
  91. */
  92. protected $_retryPolicy = null;
  93. /**
  94. * Returns the last request ID
  95. *
  96. * @var string
  97. */
  98. protected $_lastRequestId = null;
  99. /**
  100. * Creates a new Zend_Service_SqlAzure_Management instance
  101. *
  102. * @param string $subscriptionId Subscription ID
  103. * @param string $certificatePath Management certificate path (.PEM)
  104. * @param string $certificatePassphrase Management certificate passphrase
  105. * @param Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
  106. */
  107. public function __construct(
  108. $subscriptionId,
  109. $certificatePath,
  110. $certificatePassphrase,
  111. Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null
  112. ) {
  113. $this->_subscriptionId = $subscriptionId;
  114. $this->_certificatePath = $certificatePath;
  115. $this->_certificatePassphrase = $certificatePassphrase;
  116. $this->_retryPolicy = $retryPolicy;
  117. if (is_null($this->_retryPolicy)) {
  118. $this->_retryPolicy = Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract::noRetry();
  119. }
  120. // Setup default Zend_Http_Client channel
  121. $options = array(
  122. 'adapter' => 'Zend_Http_Client_Adapter_Socket',
  123. 'ssltransport' => 'ssl',
  124. 'sslcert' => $this->_certificatePath,
  125. 'sslpassphrase' => $this->_certificatePassphrase,
  126. 'sslusecontext' => true,
  127. );
  128. if (function_exists('curl_init')) {
  129. // Set cURL options if cURL is used afterwards
  130. $options['curloptions'] = array(
  131. CURLOPT_FOLLOWLOCATION => true,
  132. CURLOPT_TIMEOUT => 120,
  133. );
  134. }
  135. $this->_httpClientChannel = new Zend_Http_Client(null, $options);
  136. }
  137. /**
  138. * Set the HTTP client channel to use
  139. *
  140. * @param Zend_Http_Client_Adapter_Interface|string $adapterInstance Adapter instance or adapter class name.
  141. */
  142. public function setHttpClientChannel($adapterInstance = 'Zend_Http_Client_Adapter_Socket')
  143. {
  144. $this->_httpClientChannel->setAdapter($adapterInstance);
  145. }
  146. /**
  147. * Retrieve HTTP client channel
  148. *
  149. * @return Zend_Http_Client_Adapter_Interface
  150. */
  151. public function getHttpClientChannel()
  152. {
  153. return $this->_httpClientChannel;
  154. }
  155. /**
  156. * Returns the Windows Azure subscription ID
  157. *
  158. * @return string
  159. */
  160. public function getSubscriptionId()
  161. {
  162. return $this->_subscriptionId;
  163. }
  164. /**
  165. * Returns the last request ID.
  166. *
  167. * @return string
  168. */
  169. public function getLastRequestId()
  170. {
  171. return $this->_lastRequestId;
  172. }
  173. /**
  174. * Get base URL for creating requests
  175. *
  176. * @return string
  177. */
  178. public function getBaseUrl()
  179. {
  180. return self::URL_MANAGEMENT . '/' . $this->_subscriptionId;
  181. }
  182. /**
  183. * Perform request using Zend_Http_Client channel
  184. *
  185. * @param string $path Path
  186. * @param string $queryString Query string
  187. * @param string $httpVerb HTTP verb the request will use
  188. * @param array $headers x-ms headers to add
  189. * @param mixed $rawData Optional RAW HTTP data to be sent over the wire
  190. * @return Zend_Http_Response
  191. */
  192. protected function _performRequest(
  193. $path = '/',
  194. $queryString = '',
  195. $httpVerb = Zend_Http_Client::GET,
  196. $headers = array(),
  197. $rawData = null
  198. ) {
  199. // Clean path
  200. if (strpos($path, '/') !== 0) {
  201. $path = '/' . $path;
  202. }
  203. // Clean headers
  204. if (is_null($headers)) {
  205. $headers = array();
  206. }
  207. // Ensure cUrl will also work correctly:
  208. // - disable Content-Type if required
  209. // - disable Expect: 100 Continue
  210. if (!isset($headers["Content-Type"])) {
  211. $headers["Content-Type"] = '';
  212. }
  213. //$headers["Expect"] = '';
  214. // Add version header
  215. $headers['x-ms-version'] = $this->_apiVersion;
  216. // URL encoding
  217. $path = self::urlencode($path);
  218. $queryString = self::urlencode($queryString);
  219. // Generate URL and sign request
  220. $requestUrl = $this->getBaseUrl() . $path . $queryString;
  221. $requestHeaders = $headers;
  222. // Prepare request
  223. $this->_httpClientChannel->resetParameters(true);
  224. $this->_httpClientChannel->setUri($requestUrl);
  225. $this->_httpClientChannel->setHeaders($requestHeaders);
  226. $this->_httpClientChannel->setRawData($rawData);
  227. // Execute request
  228. $response = $this->_retryPolicy->execute(
  229. array($this->_httpClientChannel, 'request'),
  230. array($httpVerb)
  231. );
  232. // Store request id
  233. $this->_lastRequestId = $response->getHeader('x-ms-request-id');
  234. return $response;
  235. }
  236. /**
  237. * Parse result from Zend_Http_Response
  238. *
  239. * @param Zend_Http_Response $response Response from HTTP call
  240. * @return object
  241. * @throws Zend_Service_WindowsAzure_Exception
  242. */
  243. protected function _parseResponse(Zend_Http_Response $response = null)
  244. {
  245. if (is_null($response)) {
  246. require_once 'Zend/Service/SqlAzure/Exception.php';
  247. throw new Zend_Service_SqlAzure_Exception('Response should not be null.');
  248. }
  249. $xml = @simplexml_load_string($response->getBody());
  250. if ($xml !== false) {
  251. // Fetch all namespaces
  252. $namespaces = array_merge($xml->getNamespaces(true), $xml->getDocNamespaces(true));
  253. // Register all namespace prefixes
  254. foreach ($namespaces as $prefix => $ns) {
  255. if ($prefix != '') {
  256. $xml->registerXPathNamespace($prefix, $ns);
  257. }
  258. }
  259. }
  260. return $xml;
  261. }
  262. /**
  263. * URL encode function
  264. *
  265. * @param string $value Value to encode
  266. * @return string Encoded value
  267. */
  268. public static function urlencode($value)
  269. {
  270. return str_replace(' ', '%20', $value);
  271. }
  272. /**
  273. * Builds a query string from an array of elements
  274. *
  275. * @param array Array of elements
  276. * @return string Assembled query string
  277. */
  278. public static function createQueryStringFromArray($queryString)
  279. {
  280. return count($queryString) > 0 ? '?' . implode('&', $queryString) : '';
  281. }
  282. /**
  283. * Get error message from Zend_Http_Response
  284. *
  285. * @param Zend_Http_Response $response Repsonse
  286. * @param string $alternativeError Alternative error message
  287. * @return string
  288. */
  289. protected function _getErrorMessage(Zend_Http_Response $response, $alternativeError = 'Unknown error.')
  290. {
  291. $response = $this->_parseResponse($response);
  292. if ($response && $response->Message) {
  293. return (string)$response->Message;
  294. } else {
  295. return $alternativeError;
  296. }
  297. }
  298. /**
  299. * The Create Server operation adds a new SQL Azure server to a subscription.
  300. *
  301. * @param string $administratorLogin Administrator login.
  302. * @param string $administratorPassword Administrator password.
  303. * @param string $location Location of the server.
  304. * @return Zend_Service_SqlAzure_Management_ServerInstance Server information.
  305. * @throws Zend_Service_SqlAzure_Management_Exception
  306. */
  307. public function createServer($administratorLogin, $administratorPassword, $location)
  308. {
  309. if ($administratorLogin == '' || is_null($administratorLogin)) {
  310. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  311. throw new Zend_Service_SqlAzure_Management_Exception('Administrator login should be specified.');
  312. }
  313. if ($administratorPassword == '' || is_null($administratorPassword)) {
  314. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  315. throw new Zend_Service_SqlAzure_Management_Exception('Administrator password should be specified.');
  316. }
  317. if (is_null($location) && is_null($affinityGroup)) {
  318. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  319. throw new Zend_Service_SqlAzure_Management_Exception('Please specify a location for the server.');
  320. }
  321. $response = $this->_performRequest(self::OP_SERVERS, '',
  322. Zend_Http_Client::POST,
  323. array('Content-Type' => 'application/xml; charset=utf-8'),
  324. '<Server xmlns="http://schemas.microsoft.com/sqlazure/2010/12/"><AdministratorLogin>' . $administratorLogin . '</AdministratorLogin><AdministratorLoginPassword>' . $administratorPassword . '</AdministratorLoginPassword><Location>' . $location . '</Location></Server>');
  325. if ($response->isSuccessful()) {
  326. $xml = $this->_parseResponse($response);
  327. return new Zend_Service_SqlAzure_Management_ServerInstance(
  328. (string)$xml,
  329. $administratorLogin,
  330. $location
  331. );
  332. } else {
  333. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  334. throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  335. }
  336. }
  337. /**
  338. * The Get Servers operation enumerates SQL Azure servers that are provisioned for a subscription.
  339. *
  340. * @return array An array of Zend_Service_SqlAzure_Management_ServerInstance.
  341. * @throws Zend_Service_SqlAzure_Management_Exception
  342. */
  343. public function listServers()
  344. {
  345. $response = $this->_performRequest(self::OP_SERVERS);
  346. if ($response->isSuccessful()) {
  347. $xml = $this->_parseResponse($response);
  348. $xmlServices = null;
  349. if (!$xml->Server) {
  350. return array();
  351. }
  352. if (count($xml->Server) > 1) {
  353. $xmlServices = $xml->Server;
  354. } else {
  355. $xmlServices = array($xml->Server);
  356. }
  357. $services = array();
  358. if (!is_null($xmlServices)) {
  359. for ($i = 0; $i < count($xmlServices); $i++) {
  360. $services[] = new Zend_Service_SqlAzure_Management_ServerInstance(
  361. (string)$xmlServices[$i]->Name,
  362. (string)$xmlServices[$i]->AdministratorLogin,
  363. (string)$xmlServices[$i]->Location
  364. );
  365. }
  366. }
  367. return $services;
  368. } else {
  369. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  370. throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  371. }
  372. }
  373. /**
  374. * The Drop Server operation drops a SQL Azure server from a subscription.
  375. *
  376. * @param string $serverName Server to drop.
  377. * @throws Zend_Service_SqlAzure_Management_Exception
  378. */
  379. public function dropServer($serverName)
  380. {
  381. if ($serverName == '' || is_null($serverName)) {
  382. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  383. throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.');
  384. }
  385. $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName, '', Zend_Http_Client::DELETE);
  386. if (!$response->isSuccessful()) {
  387. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  388. throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  389. }
  390. }
  391. /**
  392. * The Set Server Administrator Password operation sets the administrative password of a SQL Azure server for a subscription.
  393. *
  394. * @param string $serverName Server to set password for.
  395. * @param string $administratorPassword Administrator password.
  396. * @throws Zend_Service_SqlAzure_Management_Exception
  397. */
  398. public function setAdministratorPassword($serverName, $administratorPassword)
  399. {
  400. if ($serverName == '' || is_null($serverName)) {
  401. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  402. throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.');
  403. }
  404. if ($administratorPassword == '' || is_null($administratorPassword)) {
  405. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  406. throw new Zend_Service_SqlAzure_Management_Exception('Administrator password should be specified.');
  407. }
  408. $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName, '?op=ResetPassword',
  409. Zend_Http_Client::POST,
  410. array('Content-Type' => 'application/xml; charset=utf-8'),
  411. '<AdministratorLoginPassword xmlns="http://schemas.microsoft.com/sqlazure/2010/12/">' . $administratorPassword . '</AdministratorLoginPassword>');
  412. if (!$response->isSuccessful()) {
  413. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  414. throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  415. }
  416. }
  417. /**
  418. * The Set Server Firewall Rule operation updates an existing firewall rule or adds a new firewall rule for a SQL Azure server that belongs to a subscription.
  419. *
  420. * @param string $serverName Server name.
  421. * @param string $ruleName Firewall rule name.
  422. * @param string $startIpAddress Start IP address.
  423. * @param string $endIpAddress End IP address.
  424. * @return Zend_Service_SqlAzure_Management_FirewallRuleInstance
  425. * @throws Zend_Service_SqlAzure_Management_Exception
  426. */
  427. public function createFirewallRule($serverName, $ruleName, $startIpAddress, $endIpAddress)
  428. {
  429. if ($serverName == '' || is_null($serverName)) {
  430. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  431. throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.');
  432. }
  433. if ($ruleName == '' || is_null($ruleName)) {
  434. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  435. throw new Zend_Service_SqlAzure_Management_Exception('Rule name should be specified.');
  436. }
  437. if ($startIpAddress == '' || is_null($startIpAddress) || !filter_var($startIpAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
  438. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  439. throw new Zend_Service_SqlAzure_Management_Exception('Start IP address should be specified.');
  440. }
  441. if ($endIpAddress == '' || is_null($endIpAddress) || !filter_var($endIpAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
  442. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  443. throw new Zend_Service_SqlAzure_Management_Exception('End IP address should be specified.');
  444. }
  445. $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName . '/' . self::OP_FIREWALLRULES . '/' . $ruleName, '',
  446. Zend_Http_Client::PUT,
  447. array('Content-Type' => 'application/xml; charset=utf-8'),
  448. '<FirewallRule xmlns="http://schemas.microsoft.com/sqlazure/2010/12/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.microsoft.com/sqlazure/2010/12/ FirewallRule.xsd"><StartIpAddress>' . $startIpAddress . '</StartIpAddress><EndIpAddress>' . $endIpAddress . '</EndIpAddress></FirewallRule>');
  449. if ($response->isSuccessful()) {
  450. return new Zend_Service_SqlAzure_Management_FirewallRuleInstance(
  451. $ruleName,
  452. $startIpAddress,
  453. $endIpAddress
  454. );
  455. } else {
  456. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  457. throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  458. }
  459. }
  460. /**
  461. * The Get Server Firewall Rules operation retrieves a list of all the firewall rules for a SQL Azure server that belongs to a subscription.
  462. *
  463. * @param string $serverName Server name.
  464. * @return Array of Zend_Service_SqlAzure_Management_FirewallRuleInstance.
  465. * @throws Zend_Service_SqlAzure_Management_Exception
  466. */
  467. public function listFirewallRules($serverName)
  468. {
  469. if ($serverName == '' || is_null($serverName)) {
  470. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  471. throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.');
  472. }
  473. $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName . '/' . self::OP_FIREWALLRULES);
  474. if ($response->isSuccessful()) {
  475. $xml = $this->_parseResponse($response);
  476. $xmlServices = null;
  477. if (!$xml->FirewallRule) {
  478. return array();
  479. }
  480. if (count($xml->FirewallRule) > 1) {
  481. $xmlServices = $xml->FirewallRule;
  482. } else {
  483. $xmlServices = array($xml->FirewallRule);
  484. }
  485. $services = array();
  486. if (!is_null($xmlServices)) {
  487. for ($i = 0; $i < count($xmlServices); $i++) {
  488. $services[] = new Zend_Service_SqlAzure_Management_FirewallRuleInstance(
  489. (string)$xmlServices[$i]->Name,
  490. (string)$xmlServices[$i]->StartIpAddress,
  491. (string)$xmlServices[$i]->EndIpAddress
  492. );
  493. }
  494. }
  495. return $services;
  496. } else {
  497. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  498. throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  499. }
  500. }
  501. /**
  502. * The Delete Server Firewall Rule operation deletes a firewall rule from a SQL Azure server that belongs to a subscription.
  503. *
  504. * @param string $serverName Server name.
  505. * @param string $ruleName Rule name.
  506. * @throws Zend_Service_SqlAzure_Management_Exception
  507. */
  508. public function deleteFirewallRule($serverName, $ruleName)
  509. {
  510. if ($serverName == '' || is_null($serverName)) {
  511. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  512. throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.');
  513. }
  514. if ($ruleName == '' || is_null($ruleName)) {
  515. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  516. throw new Zend_Service_SqlAzure_Management_Exception('Rule name should be specified.');
  517. }
  518. $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName . '/' . self::OP_FIREWALLRULES . '/' . $ruleName, '',
  519. Zend_Http_Client::DELETE);
  520. if (!$response->isSuccessful()) {
  521. require_once 'Zend/Service/SqlAzure/Management/Exception.php';
  522. throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  523. }
  524. }
  525. /**
  526. * Creates a firewall rule for Microsoft Services. This is required if access to SQL Azure is required from other services like Windows Azure.
  527. *
  528. * @param string $serverName Server name.
  529. * @param boolean $allowAccess Allow access from other Microsoft Services?
  530. * @throws Zend_Service_SqlAzure_Management_Exception
  531. */
  532. public function createFirewallRuleForMicrosoftServices($serverName, $allowAccess)
  533. {
  534. if ($allowAccess) {
  535. $this->createFirewallRule($serverName, 'MicrosoftServices', '0.0.0.0', '0.0.0.0');
  536. } else {
  537. $this->deleteFirewallRule($serverName, 'MicrosoftServices');
  538. }
  539. }
  540. }