Overview
  • Namespace
  • Class

Namespaces

  • OpenCloud
    • Autoscale
      • Resource
    • CloudMonitoring
      • Collection
      • Exception
      • Resource
    • Common
      • Collection
      • Constants
      • Exceptions
      • Http
        • Message
      • Log
      • Resource
      • Service
    • Compute
      • Constants
      • Exception
      • Resource
    • Database
      • Resource
    • DNS
      • Collection
      • Resource
    • Identity
      • Constants
      • Resource
    • Image
      • Enum
      • Resource
        • JsonPatch
        • Schema
    • LoadBalancer
      • Collection
      • Enum
      • Resource
    • Networking
      • Resource
    • ObjectStore
      • Constants
      • Exception
      • Resource
      • Upload
    • Orchestration
      • Resource
    • Queues
      • Collection
      • Exception
      • Resource
    • Volume
      • Resource

Classes

  • OpenCloud\Volume\Resource\Snapshot
  • OpenCloud\Volume\Resource\Volume
  • OpenCloud\Volume\Resource\VolumeType
  1 <?php
  2 /**
  3  * Copyright 2012-2014 Rackspace US, Inc.
  4  *
  5  * Licensed under the Apache License, Version 2.0 (the "License");
  6  * you may not use this file except in compliance with the License.
  7  * You may obtain a copy of the License at
  8  *
  9  * http://www.apache.org/licenses/LICENSE-2.0
 10  *
 11  * Unless required by applicable law or agreed to in writing, software
 12  * distributed under the License is distributed on an "AS IS" BASIS,
 13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  * See the License for the specific language governing permissions and
 15  * limitations under the License.
 16  */
 17 
 18 namespace OpenCloud;
 19 
 20 use Guzzle\Http\Url;
 21 use OpenCloud\Common\Exceptions;
 22 use OpenCloud\Common\Http\Client;
 23 use OpenCloud\Common\Http\Message\Formatter;
 24 use OpenCloud\Common\Http\Message\RequestSubscriber;
 25 use OpenCloud\Common\Lang;
 26 use OpenCloud\Common\Log\Logger;
 27 use OpenCloud\Common\Service\Catalog;
 28 use OpenCloud\Common\Service\ServiceBuilder;
 29 use OpenCloud\Identity\Resource\Tenant;
 30 use OpenCloud\Identity\Resource\Token;
 31 use OpenCloud\Identity\Resource\User;
 32 use OpenCloud\Identity\Service as IdentityService;
 33 use Psr\Log\LoggerInterface;
 34 
 35 define('RACKSPACE_US', 'https://identity.api.rackspacecloud.com/v2.0/');
 36 define('RACKSPACE_UK', 'https://lon.identity.api.rackspacecloud.com/v2.0/');
 37 
 38 /**
 39  * The main client of the library. This object is the central point of negotiation between your application and the
 40  * API because it handles all of the HTTP transactions required to perform operations. It also manages the services
 41  * for your application through convenient factory methods.
 42  */
 43 class OpenStack extends Client
 44 {
 45     /**
 46      * @var array Credentials passed in by the user
 47      */
 48     private $secret = array();
 49 
 50     /**
 51      * @var string The token produced by the API
 52      */
 53     private $token;
 54 
 55     /**
 56      * @var string The unique identifier for who's accessing the API
 57      */
 58     private $tenant;
 59 
 60     /**
 61      * @var \OpenCloud\Common\Service\Catalog The catalog of services which are provided by the API
 62      */
 63     private $catalog;
 64 
 65     /**
 66      * @var LoggerInterface The object responsible for logging output
 67      */
 68     private $logger;
 69 
 70     /**
 71      * @var string The endpoint URL used for authentication
 72      */
 73     private $authUrl;
 74 
 75     /**
 76      * @var \OpenCloud\Identity\Resource\User
 77      */
 78     private $user;
 79 
 80     public function __construct($url, array $secret, array $options = array())
 81     {
 82         if (isset($options['logger']) && $options['logger'] instanceof LoggerInterface) {
 83             $this->setLogger($options['logger']);
 84         }
 85 
 86         $this->setSecret($secret);
 87         $this->setAuthUrl($url);
 88 
 89         parent::__construct($url, $options);
 90 
 91         $this->addSubscriber(RequestSubscriber::getInstance());
 92         $this->setDefaultOption('headers/Accept', 'application/json');
 93     }
 94 
 95     /**
 96      * Set the credentials for the client
 97      *
 98      * @param array $secret
 99      * @return $this
100      */
101     public function setSecret(array $secret = array())
102     {
103         $this->secret = $secret;
104 
105         return $this;
106     }
107 
108     /**
109      * Get the secret.
110      *
111      * @return array
112      */
113     public function getSecret()
114     {
115         return $this->secret;
116     }
117 
118     /**
119      * Set the token. If a string is passed in, the SDK assumes you want to set the ID of the full Token object
120      * and sets this property accordingly. For any other data type, it assumes you want to populate the Token object.
121      * This ambiguity arises due to backwards compatibility.
122      *
123      * @param  string $token
124      * @return $this
125      */
126     public function setToken($token)
127     {
128         $identity = IdentityService::factory($this);
129 
130         if (is_string($token)) {
131             if (!$this->token) {
132                 $this->setTokenObject($identity->resource('Token'));
133             }
134             $this->token->setId($token);
135         } else {
136             $this->setTokenObject($identity->resource('Token', $token));
137         }
138 
139         return $this;
140     }
141 
142     /**
143      * Get the token ID for this client.
144      *
145      * @return string
146      */
147     public function getToken()
148     {
149         return ($this->getTokenObject()) ? $this->getTokenObject()->getId() : null;
150     }
151 
152     /**
153      * Set the full token object
154      */
155     public function setTokenObject(Token $token)
156     {
157         $this->token = $token;
158     }
159 
160     /**
161      * Get the full token object.
162      */
163     public function getTokenObject()
164     {
165         return $this->token;
166     }
167 
168     /**
169      * @deprecated
170      */
171     public function setExpiration($expiration)
172     {
173         $this->getLogger()->warning(Logger::deprecated(__METHOD__, '::getTokenObject()->setExpires()'));
174         if ($this->getTokenObject()) {
175             $this->getTokenObject()->setExpires($expiration);
176         }
177 
178         return $this;
179     }
180 
181     /**
182      * @deprecated
183      */
184     public function getExpiration()
185     {
186         $this->getLogger()->warning(Logger::deprecated(__METHOD__, '::getTokenObject()->getExpires()'));
187         if ($this->getTokenObject()) {
188             return $this->getTokenObject()->getExpires();
189         }
190     }
191 
192     /**
193      * Set the tenant. If an integer or string is passed in, the SDK assumes you want to set the ID of the full
194      * Tenant object and sets this property accordingly. For any other data type, it assumes you want to populate
195      * the Tenant object. This ambiguity arises due to backwards compatibility.
196      *
197      * @param  mixed $tenant
198      * @return $this
199      */
200     public function setTenant($tenant)
201     {
202         $identity = IdentityService::factory($this);
203 
204         if (is_numeric($tenant) || is_string($tenant)) {
205             if (!$this->tenant) {
206                 $this->setTenantObject($identity->resource('Tenant'));
207             }
208             $this->tenant->setId($tenant);
209         } else {
210             $this->setTenantObject($identity->resource('Tenant', $tenant));
211         }
212 
213         return $this;
214     }
215 
216     /**
217      * Returns the tenant ID only (backwards compatibility).
218      *
219      * @return string
220      */
221     public function getTenant()
222     {
223         return ($this->getTenantObject()) ? $this->getTenantObject()->getId() : null;
224     }
225 
226     /**
227      * Set the full Tenant object for this client.
228      *
229      * @param OpenCloud\Identity\Resource\Tenant $tenant
230      */
231     public function setTenantObject(Tenant $tenant)
232     {
233         $this->tenant = $tenant;
234     }
235 
236     /**
237      * Get the full Tenant object for this client.
238      *
239      * @return OpenCloud\Identity\Resource\Tenant
240      */
241     public function getTenantObject()
242     {
243         return $this->tenant;
244     }
245 
246     /**
247      * Set the service catalog.
248      *
249      * @param  mixed $catalog
250      * @return $this
251      */
252     public function setCatalog($catalog)
253     {
254         $this->catalog = Catalog::factory($catalog);
255 
256         return $this;
257     }
258 
259     /**
260      * Get the service catalog.
261      *
262      * @return array
263      */
264     public function getCatalog()
265     {
266         return $this->catalog;
267     }
268 
269     /**
270      * @param LoggerInterface $logger
271      *
272      * @return $this
273      */
274     public function setLogger(LoggerInterface $logger)
275     {
276         $this->logger = $logger;
277 
278         return $this;
279     }
280 
281     /**
282      * @return LoggerInterface
283      */
284     public function getLogger()
285     {
286         if (null === $this->logger) {
287             $this->setLogger(new Common\Log\Logger);
288         }
289 
290         return $this->logger;
291     }
292 
293     /**
294      * @return bool
295      */
296     public function hasLogger()
297     {
298         return (null !== $this->logger);
299     }
300 
301     /**
302      * @deprecated
303      */
304     public function hasExpired()
305     {
306         $this->getLogger()->warning(Logger::deprecated(__METHOD__, 'getTokenObject()->hasExpired()'));
307 
308         return $this->getTokenObject() && $this->getTokenObject()->hasExpired();
309     }
310 
311     /**
312      * Formats the credentials array (as a string) for authentication
313      *
314      * @return string
315      * @throws Common\Exceptions\CredentialError
316      */
317     public function getCredentials()
318     {
319         if (!empty($this->secret['username']) && !empty($this->secret['password'])) {
320             $credentials = array('auth' => array(
321                 'passwordCredentials' => array(
322                     'username' => $this->secret['username'],
323                     'password' => $this->secret['password']
324                 )
325             ));
326 
327             if (!empty($this->secret['tenantName'])) {
328                 $credentials['auth']['tenantName'] = $this->secret['tenantName'];
329             } elseif (!empty($this->secret['tenantId'])) {
330                 $credentials['auth']['tenantId'] = $this->secret['tenantId'];
331             }
332 
333             return json_encode($credentials);
334         } else {
335             throw new Exceptions\CredentialError(
336                 Lang::translate('Unrecognized credential secret')
337             );
338         }
339     }
340 
341     /**
342      * @param $url
343      * @return $this
344      */
345     public function setAuthUrl($url)
346     {
347         $this->authUrl = Url::factory($url);
348 
349         return $this;
350     }
351 
352     /**
353      * @return Url
354      */
355     public function getAuthUrl()
356     {
357         return $this->authUrl;
358     }
359 
360     /**
361      * Sets the current user based on the generated token.
362      *
363      * @param $data Object of user data
364      */
365     public function setUser(User $user)
366     {
367         $this->user = $user;
368     }
369 
370     /**
371      * @return \OpenCloud\Identity\Resource\User
372      */
373     public function getUser()
374     {
375         return $this->user;
376     }
377 
378     /**
379      * Authenticate the tenant using the supplied credentials
380      *
381      * @return void
382      * @throws AuthenticationError
383      */
384     public function authenticate()
385     {
386         // OpenStack APIs will return a 401 if an expired X-Auth-Token is sent,
387         // so we need to reset the value before authenticating for another one.
388         $this->updateTokenHeader('');
389 
390         $identity = IdentityService::factory($this);
391         $response = $identity->generateToken($this->getCredentials());
392 
393         $body = Formatter::decode($response);
394 
395         $this->setCatalog($body->access->serviceCatalog);
396         $this->setTokenObject($identity->resource('Token', $body->access->token));
397         $this->setUser($identity->resource('User', $body->access->user));
398 
399         if (isset($body->access->token->tenant)) {
400             $this->setTenantObject($identity->resource('Tenant', $body->access->token->tenant));
401         }
402 
403         // Set X-Auth-Token HTTP request header
404         $this->updateTokenHeader($this->getToken());
405     }
406 
407     /**
408      * @deprecated
409      */
410     public function getUrl()
411     {
412         return $this->getBaseUrl();
413     }
414 
415     /**
416      * Convenience method for exporting current credentials. Useful for local caching.
417      * @return array
418      */
419     public function exportCredentials()
420     {
421         if ($this->hasExpired()) {
422             $this->authenticate();
423         }
424 
425         return array(
426             'token'      => $this->getToken(),
427             'expiration' => $this->getExpiration(),
428             'tenant'     => $this->getTenant(),
429             'catalog'    => $this->getCatalog()
430         );
431     }
432 
433     /**
434      * Convenience method for importing credentials. Useful for local caching because it reduces HTTP traffic.
435      *
436      * @param array $values
437      */
438     public function importCredentials(array $values)
439     {
440         if (!empty($values['token'])) {
441             $this->setToken($values['token']);
442             $this->updateTokenHeader($this->getToken());
443         }
444         if (!empty($values['expiration'])) {
445             $this->setExpiration($values['expiration']);
446         }
447         if (!empty($values['tenant'])) {
448             $this->setTenant($values['tenant']);
449         }
450         if (!empty($values['catalog'])) {
451             $this->setCatalog($values['catalog']);
452         }
453     }
454 
455     /**
456      * Sets the X-Auth-Token header. If no value is explicitly passed in, the current token is used.
457      *
458      * @param  string $token Value of header.
459      * @return void
460      */
461     private function updateTokenHeader($token)
462     {
463         $this->setDefaultOption('headers/X-Auth-Token', (string) $token);
464     }
465 
466     /**
467      * Creates a new ObjectStore object (Swift/Cloud Files)
468      *
469      * @param string $name    The name of the service as it appears in the Catalog
470      * @param string $region  The region (DFW, IAD, ORD, LON, SYD)
471      * @param string $urltype The URL type ("publicURL" or "internalURL")
472      * @return \OpenCloud\ObjectStore\Service
473      */
474     public function objectStoreService($name = null, $region = null, $urltype = null)
475     {
476         return ServiceBuilder::factory($this, 'OpenCloud\ObjectStore\Service', array(
477             'name'    => $name,
478             'region'  => $region,
479             'urlType' => $urltype
480         ));
481     }
482 
483     /**
484      * Creates a new Compute object (Nova/Cloud Servers)
485      *
486      * @param string $name    The name of the service as it appears in the Catalog
487      * @param string $region  The region (DFW, IAD, ORD, LON, SYD)
488      * @param string $urltype The URL type ("publicURL" or "internalURL")
489      * @return \OpenCloud\Compute\Service
490      */
491     public function computeService($name = null, $region = null, $urltype = null)
492     {
493         return ServiceBuilder::factory($this, 'OpenCloud\Compute\Service', array(
494             'name'    => $name,
495             'region'  => $region,
496             'urlType' => $urltype
497         ));
498     }
499 
500     /**
501      * Creates a new Orchestration (Heat) service object
502      *
503      * @param string $name    The name of the service as it appears in the Catalog
504      * @param string $region  The region (DFW, IAD, ORD, LON, SYD)
505      * @param string $urltype The URL type ("publicURL" or "internalURL")
506      * @return \OpenCloud\Orchestration\Service
507      * @codeCoverageIgnore
508      */
509     public function orchestrationService($name = null, $region = null, $urltype = null)
510     {
511         return ServiceBuilder::factory($this, 'OpenCloud\Orchestration\Service', array(
512             'name'    => $name,
513             'region'  => $region,
514             'urlType' => $urltype
515         ));
516     }
517 
518     /**
519      * Creates a new Volume (Cinder) service object
520      *
521      * @param string $name    The name of the service as it appears in the Catalog
522      * @param string $region  The region (DFW, IAD, ORD, LON, SYD)
523      * @param string $urltype The URL type ("publicURL" or "internalURL")
524      * @return \OpenCloud\Volume\Service
525      */
526     public function volumeService($name = null, $region = null, $urltype = null)
527     {
528         return ServiceBuilder::factory($this, 'OpenCloud\Volume\Service', array(
529             'name'    => $name,
530             'region'  => $region,
531             'urlType' => $urltype
532         ));
533     }
534 
535     /**
536      * Creates a new Rackspace "Cloud Identity" service.
537      *
538      * @return \OpenCloud\Identity\Service
539      */
540     public function identityService()
541     {
542         $service = IdentityService::factory($this);
543         $this->authenticate();
544 
545         return $service;
546     }
547 
548     /**
549      * Creates a new Glance service
550      *
551      * @param string $name    The name of the service as it appears in the Catalog
552      * @param string $region  The region (DFW, IAD, ORD, LON, SYD)
553      * @param string $urltype The URL type ("publicURL" or "internalURL")
554      * @return Common\Service\ServiceInterface
555      */
556     public function imageService($name = null, $region = null, $urltype = null)
557     {
558         return ServiceBuilder::factory($this, 'OpenCloud\Image\Service', array(
559             'name'    => $name,
560             'region'  => $region,
561             'urlType' => $urltype
562         ));
563     }
564 
565     /**
566      * Creates a new Networking (Neutron) service object
567      *
568      * @param string $name    The name of the service as it appears in the Catalog
569      * @param string $region  The region (DFW, IAD, ORD, LON, SYD)
570      * @param string $urltype The URL type ("publicURL" or "internalURL")
571      * @return \OpenCloud\Networking\Service
572      * @codeCoverageIgnore
573      */
574     public function networkingService($name = null, $region = null, $urltype = null)
575     {
576         return ServiceBuilder::factory($this, 'OpenCloud\Networking\Service', array(
577             'name'    => $name,
578             'region'  => $region,
579             'urlType' => $urltype
580         ));
581     }
582 }
583 
API documentation generated by ApiGen