1: <?php
2: 3: 4: 5: 6: 7: 8: 9:
10:
11: namespace OpenCloud;
12:
13: use OpenCloud\Common\Constants\Header;
14: use OpenCloud\Common\Constants\Mime;
15: use OpenCloud\Common\Http\Client;
16: use OpenCloud\Common\Http\Message\RequestSubscriber;
17: use OpenCloud\Common\Lang;
18: use OpenCloud\Common\Exceptions;
19: use OpenCloud\Common\Service\ServiceBuilder;
20: use OpenCloud\Common\Service\Catalog;
21: use OpenCloud\Common\Http\Message\Formatter;
22: use Guzzle\Http\Url;
23:
24: define('RACKSPACE_US', 'https://identity.api.rackspacecloud.com/v2.0/');
25: define('RACKSPACE_UK', 'https://lon.identity.api.rackspacecloud.com/v2.0/');
26:
27: 28: 29: 30: 31:
32: class OpenStack extends Client
33: {
34: 35: 36:
37: private $secret = array();
38:
39: 40: 41:
42: private $token;
43:
44: 45: 46:
47: private $expiration;
48:
49: 50: 51:
52: private $tenant;
53:
54: 55: 56:
57: private $catalog;
58:
59: 60: 61:
62: private $logger;
63:
64: 65: 66:
67: private $authUrl;
68:
69: public function __construct($url, array $secret, array $options = array())
70: {
71: $this->getLogger()->info(Lang::translate('Initializing OpenStack client'));
72:
73: $this->setSecret($secret);
74: $this->setAuthUrl($url);
75:
76: parent::__construct($url, $options);
77:
78: $this->addSubscriber(RequestSubscriber::getInstance());
79: $this->setDefaultOption('headers/Accept', 'application/json');
80: }
81:
82: 83: 84: 85: 86: 87:
88: public function setSecret(array $secret = array())
89: {
90: $this->secret = $secret;
91:
92: return $this;
93: }
94:
95: 96: 97: 98: 99:
100: public function getSecret()
101: {
102: return $this->secret;
103: }
104:
105: 106: 107: 108: 109: 110:
111: public function setToken($token)
112: {
113: $this->token = $token;
114:
115: return $this;
116: }
117:
118: 119: 120: 121: 122:
123: public function getToken()
124: {
125: return $this->token;
126: }
127:
128: 129: 130: 131: 132: 133:
134: public function setExpiration($expiration)
135: {
136: $this->expiration = $expiration;
137:
138: return $this;
139: }
140:
141: 142: 143: 144: 145:
146: public function getExpiration()
147: {
148: return $this->expiration;
149: }
150:
151: 152: 153: 154: 155: 156:
157: public function setTenant($tenant)
158: {
159: $this->tenant = $tenant;
160:
161: return $this;
162: }
163:
164: 165: 166: 167: 168:
169: public function getTenant()
170: {
171: return $this->tenant;
172: }
173:
174: 175: 176: 177: 178: 179:
180: public function setCatalog($catalog)
181: {
182: $this->catalog = Catalog::factory($catalog);
183:
184: return $this;
185: }
186:
187: 188: 189: 190: 191:
192: public function getCatalog()
193: {
194: return $this->catalog;
195: }
196:
197: 198: 199: 200:
201: public function setLogger(Common\Log\LoggerInterface $logger)
202: {
203: $this->logger = $logger;
204: return $this;
205: }
206:
207: 208: 209:
210: public function getLogger()
211: {
212: if (null === $this->logger) {
213: $this->setLogger(new Common\Log\Logger);
214: }
215: return $this->logger;
216: }
217:
218: 219: 220: 221: 222:
223: public function hasExpired()
224: {
225: return !$this->expiration || (time() > $this->expiration);
226: }
227:
228: 229: 230: 231: 232: 233:
234: public function getCredentials()
235: {
236: if (!empty($this->secret['username']) && !empty($this->secret['password'])) {
237:
238: $credentials = array('auth' => array(
239: 'passwordCredentials' => array(
240: 'username' => $this->secret['username'],
241: 'password' => $this->secret['password']
242: )
243: ));
244:
245: if (!empty($this->secret['tenantName'])) {
246: $credentials['auth']['tenantName'] = $this->secret['tenantName'];
247: } elseif (!empty($this->secret['tenantId'])) {
248: $credentials['auth']['tenantId'] = $this->secret['tenantId'];
249: }
250:
251: return json_encode($credentials);
252:
253: } else {
254: throw new Exceptions\CredentialError(
255: Lang::translate('Unrecognized credential secret')
256: );
257: }
258: }
259:
260: 261: 262: 263:
264: public function setAuthUrl($url)
265: {
266: $this->authUrl = $url;
267: return $this;
268: }
269:
270: 271: 272:
273: public function getAuthUrl()
274: {
275: return Url::factory($this->authUrl)->addPath('tokens');
276: }
277:
278: 279: 280: 281: 282: 283:
284: public function authenticate()
285: {
286: $headers = array(Header::CONTENT_TYPE => Mime::JSON);
287: $response = $this->post($this->getAuthUrl('tokens'), $headers, $this->getCredentials())->send();
288: $body = Formatter::decode($response);
289:
290:
291: $this->setToken($body->access->token->id);
292: $this->setExpiration(strtotime($body->access->token->expires));
293: $this->setCatalog($body->access->serviceCatalog);
294:
295:
296: $this->setDefaultOption('headers/X-Auth-Token', (string) $this->getToken());
297:
298: 299: 300: 301: 302: 303:
304: if (isset($body->access->token->tenant)) {
305: $this->setTenant($body->access->token->tenant->id);
306: }
307: }
308:
309: 310: 311:
312: public function getUrl()
313: {
314: return $this->getBaseUrl();
315: }
316:
317: 318: 319: 320:
321: public function exportCredentials()
322: {
323: if ($this->hasExpired()) {
324: $this->authenticate();
325: }
326: return array(
327: 'token' => $this->getToken(),
328: 'expiration' => $this->getExpiration(),
329: 'tenant' => $this->getTenant(),
330: 'catalog' => $this->getCatalog()
331: );
332: }
333:
334: 335: 336: 337: 338:
339: public function importCredentials(array $values)
340: {
341: if (!empty($values['token'])) {
342: $this->setToken($values['token']);
343: }
344: if (!empty($values['expiration'])) {
345: $this->setExpiration($values['expiration']);
346: }
347: if (!empty($values['tenant'])) {
348: $this->setTenant($values['tenant']);
349: }
350: if (!empty($values['catalog'])) {
351: $this->setCatalog($values['catalog']);
352: }
353: }
354:
355: 356: 357: 358: 359: 360: 361: 362:
363: public function objectStoreService($name = null, $region = null, $urltype = null)
364: {
365: return ServiceBuilder::factory($this, 'OpenCloud\ObjectStore\Service', array(
366: 'name' => $name,
367: 'region' => $region,
368: 'urlType' => $urltype
369: ));
370: }
371:
372: 373: 374: 375: 376: 377: 378: 379:
380: public function computeService($name = null, $region = null, $urltype = null)
381: {
382: return ServiceBuilder::factory($this, 'OpenCloud\Compute\Service', array(
383: 'name' => $name,
384: 'region' => $region,
385: 'urlType' => $urltype
386: ));
387: }
388:
389: 390: 391: 392: 393: 394: 395: 396: 397:
398: public function orchestrationService($name = null, $region = null, $urltype = null)
399: {
400: return ServiceBuilder::factory($this, 'OpenCloud\Orchestration\Service', array(
401: 'name' => $name,
402: 'region' => $region,
403: 'urlType' => $urltype
404: ));
405: }
406:
407: 408: 409: 410: 411: 412: 413: 414:
415: public function volumeService($name = null, $region = null, $urltype = null)
416: {
417: return ServiceBuilder::factory($this, 'OpenCloud\Volume\Service', array(
418: 'name' => $name,
419: 'region' => $region,
420: 'urlType' => $urltype
421: ));
422: }
423:
424: }
425: