Overview

Namespaces

  • OpenCloud
    • Autoscale
      • Resource
    • CDN
      • 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
      • Enum
      • Exception
      • Resource
      • Upload
    • Orchestration
      • Resource
    • Queues
      • Collection
      • Exception
      • Resource
    • Volume
      • Resource
  • PHP

Classes

  • OpenStack
  • Rackspace
  • Version
  • Overview
  • Namespace
  • Class
  • Tree
  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:     /**
584:      * Creates a new CDN (Poppy) service object
585:      *
586:      * @param string $name    The name of the service as it appears in the Catalog
587:      * @param string $region  The region (DFW, IAD, ORD, LON, SYD)
588:      * @param string $urltype The URL type ("publicURL" or "internalURL")
589:      * @return \OpenCloud\Cdn\Service
590:      * @codeCoverageIgnore
591:      */
592:     public function cdnService($name = null, $region = null, $urltype = null)
593:     {
594:         return ServiceBuilder::factory($this, 'OpenCloud\CDN\Service', array(
595:             'name'    => $name,
596:             'region'  => $region,
597:             'urlType' => $urltype
598:         ));
599:     }
600: }
601: 
API documentation generated by ApiGen 2.8.0