1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 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\Service\Catalog;
27: use OpenCloud\Common\Service\ServiceBuilder;
28: use OpenCloud\Identity\Resource\Tenant;
29: use OpenCloud\Identity\Resource\Token;
30: use OpenCloud\Identity\Resource\User;
31: use OpenCloud\Identity\Service as IdentityService;
32:
33: define('RACKSPACE_US', 'https://identity.api.rackspacecloud.com/v2.0/');
34: define('RACKSPACE_UK', 'https://lon.identity.api.rackspacecloud.com/v2.0/');
35:
36: 37: 38: 39: 40:
41: class OpenStack extends Client
42: {
43: 44: 45:
46: private $secret = array();
47:
48: 49: 50:
51: private $token;
52:
53: 54: 55:
56: private $tenant;
57:
58: 59: 60:
61: private $catalog;
62:
63: 64: 65:
66: private $logger;
67:
68: 69: 70:
71: private $authUrl;
72:
73: 74: 75:
76: private $user;
77:
78: public function __construct($url, array $secret, array $options = array())
79: {
80: $this->setSecret($secret);
81: $this->setAuthUrl($url);
82:
83: parent::__construct($url, $options);
84:
85: $this->addSubscriber(RequestSubscriber::getInstance());
86: $this->setDefaultOption('headers/Accept', 'application/json');
87: }
88:
89: 90: 91: 92: 93: 94:
95: public function setSecret(array $secret = array())
96: {
97: $this->secret = $secret;
98:
99: return $this;
100: }
101:
102: 103: 104: 105: 106:
107: public function getSecret()
108: {
109: return $this->secret;
110: }
111:
112: 113: 114: 115: 116: 117: 118: 119:
120: public function setToken($token)
121: {
122: $identity = IdentityService::factory($this);
123:
124: if (is_string($token)) {
125:
126: if (!$this->token) {
127: $this->setTokenObject($identity->resource('Token'));
128: }
129: $this->token->setId($token);
130: } else {
131: $this->setTokenObject($identity->resource('Token', $token));
132: }
133:
134: return $this;
135: }
136:
137: 138: 139: 140: 141:
142: public function getToken()
143: {
144: return ($this->getTokenObject()) ? $this->getTokenObject()->getId() : null;
145: }
146:
147: 148: 149:
150: public function setTokenObject(Token $token)
151: {
152: $this->token = $token;
153: }
154:
155: 156: 157:
158: public function getTokenObject()
159: {
160: return $this->token;
161: }
162:
163: 164: 165:
166: public function setExpiration($expiration)
167: {
168: $this->getLogger()->deprecated(__METHOD__, '::getTokenObject()->setExpires()');
169: if ($this->getTokenObject()) {
170: $this->getTokenObject()->setExpires($expiration);
171: }
172:
173: return $this;
174: }
175:
176: 177: 178:
179: public function getExpiration()
180: {
181: $this->getLogger()->deprecated(__METHOD__, '::getTokenObject()->getExpires()');
182: if ($this->getTokenObject()) {
183: return $this->getTokenObject()->getExpires();
184: }
185: }
186:
187: 188: 189: 190: 191: 192: 193: 194:
195: public function setTenant($tenant)
196: {
197: $identity = IdentityService::factory($this);
198:
199: if (is_numeric($tenant)) {
200:
201: if (!$this->tenant) {
202: $this->setTenantObject($identity->resource('Tenant'));
203: }
204: $this->tenant->setId($tenant);
205: } else {
206: $this->setTenantObject($identity->resource('Tenant', $tenant));
207: }
208:
209: return $this;
210: }
211:
212: 213: 214: 215: 216:
217: public function getTenant()
218: {
219: return ($this->getTenantObject()) ? $this->getTenantObject()->getId() : null;
220: }
221:
222: 223: 224: 225: 226:
227: public function setTenantObject(Tenant $tenant)
228: {
229: $this->tenant = $tenant;
230: }
231:
232: 233: 234: 235: 236:
237: public function getTenantObject()
238: {
239: return $this->tenant;
240: }
241:
242: 243: 244: 245: 246: 247:
248: public function setCatalog($catalog)
249: {
250: $this->catalog = Catalog::factory($catalog);
251:
252: return $this;
253: }
254:
255: 256: 257: 258: 259:
260: public function getCatalog()
261: {
262: return $this->catalog;
263: }
264:
265: 266: 267: 268:
269: public function setLogger(Common\Log\LoggerInterface $logger)
270: {
271: $this->logger = $logger;
272:
273: return $this;
274: }
275:
276: 277: 278:
279: public function getLogger()
280: {
281: if (null === $this->logger) {
282: $this->setLogger(new Common\Log\Logger);
283: }
284:
285: return $this->logger;
286: }
287:
288: 289: 290:
291: public function hasExpired()
292: {
293: $this->getLogger()->deprecated(__METHOD__, 'getTokenObject()->hasExpired()');
294:
295: return $this->getTokenObject() && $this->getTokenObject()->hasExpired();
296: }
297:
298: 299: 300: 301: 302: 303:
304: public function getCredentials()
305: {
306: if (!empty($this->secret['username']) && !empty($this->secret['password'])) {
307:
308: $credentials = array('auth' => array(
309: 'passwordCredentials' => array(
310: 'username' => $this->secret['username'],
311: 'password' => $this->secret['password']
312: )
313: ));
314:
315: if (!empty($this->secret['tenantName'])) {
316: $credentials['auth']['tenantName'] = $this->secret['tenantName'];
317: } elseif (!empty($this->secret['tenantId'])) {
318: $credentials['auth']['tenantId'] = $this->secret['tenantId'];
319: }
320:
321: return json_encode($credentials);
322: } else {
323: throw new Exceptions\CredentialError(
324: Lang::translate('Unrecognized credential secret')
325: );
326: }
327: }
328:
329: 330: 331: 332:
333: public function setAuthUrl($url)
334: {
335: $this->authUrl = Url::factory($url);
336:
337: return $this;
338: }
339:
340: 341: 342:
343: public function getAuthUrl()
344: {
345: return $this->authUrl;
346: }
347:
348: 349: 350: 351: 352:
353: public function setUser(User $user)
354: {
355: $this->user = $user;
356: }
357:
358: 359: 360:
361: public function getUser()
362: {
363: return $this->user;
364: }
365:
366: 367: 368: 369: 370: 371:
372: public function authenticate()
373: {
374: $identity = IdentityService::factory($this);
375: $response = $identity->generateToken($this->getCredentials());
376:
377: $body = Formatter::decode($response);
378:
379: $this->setCatalog($body->access->serviceCatalog);
380: $this->setTokenObject($identity->resource('Token', $body->access->token));
381: $this->setUser($identity->resource('User', $body->access->user));
382:
383: if (isset($body->access->token->tenant)) {
384: $this->setTenantObject($identity->resource('Tenant', $body->access->token->tenant));
385: }
386:
387:
388: $this->updateTokenHeader();
389: }
390:
391: 392: 393:
394: public function getUrl()
395: {
396: return $this->getBaseUrl();
397: }
398:
399: 400: 401: 402:
403: public function exportCredentials()
404: {
405: if ($this->hasExpired()) {
406: $this->authenticate();
407: }
408:
409: return array(
410: 'token' => $this->getToken(),
411: 'expiration' => $this->getExpiration(),
412: 'tenant' => $this->getTenant(),
413: 'catalog' => $this->getCatalog()
414: );
415: }
416:
417: 418: 419: 420: 421:
422: public function importCredentials(array $values)
423: {
424: if (!empty($values['token'])) {
425: $this->setToken($values['token']);
426: $this->updateTokenHeader();
427: }
428: if (!empty($values['expiration'])) {
429: $this->setExpiration($values['expiration']);
430: }
431: if (!empty($values['tenant'])) {
432: $this->setTenant($values['tenant']);
433: }
434: if (!empty($values['catalog'])) {
435: $this->setCatalog($values['catalog']);
436: }
437: }
438:
439: 440: 441: 442: 443: 444:
445: private function ($token = null)
446: {
447: $token = $token ? : $this->getToken();
448: $this->setDefaultOption('headers/X-Auth-Token', (string)$token);
449: }
450:
451: 452: 453: 454: 455: 456: 457: 458:
459: public function objectStoreService($name = null, $region = null, $urltype = null)
460: {
461: return ServiceBuilder::factory($this, 'OpenCloud\ObjectStore\Service', array(
462: 'name' => $name,
463: 'region' => $region,
464: 'urlType' => $urltype
465: ));
466: }
467:
468: 469: 470: 471: 472: 473: 474: 475:
476: public function computeService($name = null, $region = null, $urltype = null)
477: {
478: return ServiceBuilder::factory($this, 'OpenCloud\Compute\Service', array(
479: 'name' => $name,
480: 'region' => $region,
481: 'urlType' => $urltype
482: ));
483: }
484:
485: 486: 487: 488: 489: 490: 491: 492: 493:
494: public function orchestrationService($name = null, $region = null, $urltype = null)
495: {
496: return ServiceBuilder::factory($this, 'OpenCloud\Orchestration\Service', array(
497: 'name' => $name,
498: 'region' => $region,
499: 'urlType' => $urltype
500: ));
501: }
502:
503: 504: 505: 506: 507: 508: 509: 510:
511: public function volumeService($name = null, $region = null, $urltype = null)
512: {
513: return ServiceBuilder::factory($this, 'OpenCloud\Volume\Service', array(
514: 'name' => $name,
515: 'region' => $region,
516: 'urlType' => $urltype
517: ));
518: }
519:
520: 521: 522: 523: 524:
525: public function identityService()
526: {
527: $service = IdentityService::factory($this);
528: $this->authenticate();
529:
530: return $service;
531: }
532:
533: 534: 535: 536: 537: 538: 539: 540:
541: public function imageService($name = null, $region = null, $urltype = null)
542: {
543: return ServiceBuilder::factory($this, 'OpenCloud\Image\Service', array(
544: 'name' => $name,
545: 'region' => $region,
546: 'urlType' => $urltype
547: ));
548: }
549: }
550: