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

  • AbstractService
  • Catalog
  • CatalogItem
  • CatalogService
  • Endpoint
  • NovaService
  • ServiceBuilder

Interfaces

  • ServiceInterface
  • 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\Common\Service;
 19: 
 20: use Guzzle\Http\ClientInterface;
 21: use Guzzle\Http\Exception\BadResponseException;
 22: use Guzzle\Http\Url;
 23: use OpenCloud\Common\Base;
 24: use OpenCloud\Common\Exceptions;
 25: use OpenCloud\Common\Http\Message\Formatter;
 26: use OpenCloud\OpenStack;
 27: use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 28: 
 29: abstract class CatalogService extends AbstractService
 30: {
 31:     const DEFAULT_URL_TYPE = 'publicURL';
 32:     const SUPPORTED_VERSION = null;
 33: 
 34:     /**
 35:      * @var string The type of this service, as set in Catalog.
 36:      */
 37:     private $type;
 38: 
 39:     /**
 40:      * @var string The name of this service, as set in Catalog.
 41:      */
 42:     private $name;
 43: 
 44:     /**
 45:      * @var string The chosen region(s) for this service.
 46:      */
 47:     private $region;
 48: 
 49:     /**
 50:      * @var string Either 'publicURL' or 'internalURL'.
 51:      */
 52:     private $urlType;
 53: 
 54:     /**
 55:      * @var bool Indicates whether a service is "regionless" or not. Defaults to FALSE because nearly all services
 56:      *           are region-specific.
 57:      */
 58:     protected $regionless = false;
 59: 
 60:     /**
 61:      * Creates a service object, based off the specified client.
 62:      *
 63:      * The service's URL is defined in the client's serviceCatalog; it
 64:      * uses the $type, $name, $region, and $urlType to find the proper endpoint
 65:      * and set it. If it cannot find a URL in the service catalog that matches
 66:      * the criteria, then an exception is thrown.
 67:      *
 68:      * @param Client $client  Client object
 69:      * @param string $type    Service type (e.g. 'compute')
 70:      * @param string $name    Service name (e.g. 'cloudServersOpenStack')
 71:      * @param string $region  Service region (e.g. 'DFW', 'ORD', 'IAD', 'LON', 'SYD' or 'HKG')
 72:      * @param string $urlType Either 'publicURL' or 'internalURL'
 73:      */
 74:     public function __construct(ClientInterface $client, $type = null, $name = null, $region = null, $urlType = null)
 75:     {
 76:         if (($client instanceof Base || $client instanceof OpenStack) && $client->hasLogger()) {
 77:             $this->setLogger($client->getLogger());
 78:         }
 79: 
 80:         $this->setClient($client);
 81: 
 82:         $this->name = $name ? : static::DEFAULT_NAME;
 83:         $this->region = $region;
 84: 
 85:         $this->region = $region;
 86:         if ($this->regionless !== true && !$this->region) {
 87:             throw new Exceptions\ServiceException(sprintf(
 88:                 'The %s service must have a region set. You can either pass in a region string as an argument param, or'
 89:                 . ' set a default region for your user account by executing User::setDefaultRegion and ::update().',
 90:                 $this->name
 91:             ));
 92:         }
 93: 
 94:         $this->type = $type ? : static::DEFAULT_TYPE;
 95:         $this->urlType = $urlType ? : static::DEFAULT_URL_TYPE;
 96:         $this->setEndpoint($this->findEndpoint());
 97: 
 98:         $this->client->setBaseUrl($this->getBaseUrl());
 99: 
100:         if ($this instanceof EventSubscriberInterface) {
101:             $this->client->getEventDispatcher()->addSubscriber($this);
102:         }
103:     }
104: 
105:     /**
106:      * @return string
107:      */
108:     public function getType()
109:     {
110:         return $this->type;
111:     }
112: 
113:     /**
114:      * @return string
115:      */
116:     public function getRegion()
117:     {
118:         return $this->region;
119:     }
120: 
121:     /**
122:      * @return string
123:      */
124:     public function getName()
125:     {
126:         return $this->name;
127:     }
128: 
129:     /**
130:      * @return string
131:      */
132:     public function getUrlType()
133:     {
134:         return $this->urlType;
135:     }
136: 
137:     /**
138:      * @deprecated
139:      */
140:     public function region()
141:     {
142:         return $this->getRegion();
143:     }
144: 
145:     /**
146:      * @deprecated
147:      */
148:     public function name()
149:     {
150:         return $this->name;
151:     }
152: 
153:     /**
154:      * Returns the URL for the Service
155:      *
156:      * @param  string $path  URL path segment
157:      * @param  array  $query Array of query pairs
158:      * @return Guzzle\Http\Url
159:      */
160:     public function getUrl($path = null, array $query = array())
161:     {
162:         return Url::factory($this->getBaseUrl())
163:             ->addPath($path)
164:             ->setQuery($query);
165:     }
166: 
167:     /**
168:      * @deprecated
169:      */
170:     public function url($path = null, array $query = array())
171:     {
172:         return $this->getUrl($path, $query);
173:     }
174: 
175:     /**
176:      * Returns the /extensions for the service
177:      *
178:      * @api
179:      * @return array of objects
180:      */
181:     public function getExtensions()
182:     {
183:         $ext = $this->getMetaUrl('extensions');
184: 
185:         return (is_object($ext) && isset($ext->extensions)) ? $ext->extensions : array();
186:     }
187: 
188:     /**
189:      * Returns the limits for the service
190:      *
191:      * @return array of limits
192:      */
193:     public function limits()
194:     {
195:         $limits = $this->getMetaUrl('limits');
196: 
197:         return (is_object($limits)) ? $limits->limits : array();
198:     }
199: 
200:     /**
201:      * Extracts the appropriate endpoint from the service catalog based on the
202:      * name and type of a service, and sets for further use.
203:      *
204:      * @return \OpenCloud\Common\Service\Endpoint
205:      * @throws \OpenCloud\Common\Exceptions\EndpointError
206:      */
207:     private function findEndpoint()
208:     {
209:         if (!$this->getClient()->getCatalog()) {
210:             $this->getClient()->authenticate();
211:         }
212: 
213:         $catalog = $this->getClient()->getCatalog();
214: 
215:         // Search each service to find The One
216:         foreach ($catalog->getItems() as $service) {
217:             if ($service->hasType($this->type) && $service->hasName($this->name)) {
218:                 return Endpoint::factory($service->getEndpointFromRegion($this->region), static::SUPPORTED_VERSION, $this->getClient());
219:             }
220:         }
221: 
222:         throw new Exceptions\EndpointError(sprintf(
223:             'No endpoints for service type [%s], name [%s], region [%s] and urlType [%s]',
224:             $this->type,
225:             $this->name,
226:             $this->region,
227:             $this->urlType
228:         ));
229:     }
230: 
231:     /**
232:      * Constructs a specified URL from the subresource
233:      *
234:      * Given a subresource (e.g., "extensions"), this constructs the proper
235:      * URL and retrieves the resource.
236:      *
237:      * @param string $resource The resource requested; should NOT have slashes
238:      *                         at the beginning or end
239:      * @return \stdClass object
240:      */
241:     private function getMetaUrl($resource)
242:     {
243:         $url = clone $this->getBaseUrl();
244:         $url->addPath($resource);
245:         try {
246:             $response = $this->getClient()->get($url)->send();
247: 
248:             return Formatter::decode($response);
249:         } catch (BadResponseException $e) {
250:             // @codeCoverageIgnoreStart
251:             return array();
252:             // @codeCoverageIgnoreEnd
253:         }
254:     }
255: 
256:     /**
257:      * Get the base URL for this service, based on the set URL type.
258:      * @return \Guzzle\Http\Url
259:      * @throws \OpenCloud\Common\Exceptions\ServiceException
260:      */
261:     public function getBaseUrl()
262:     {
263:         $url = ($this->urlType == 'publicURL')
264:             ? $this->endpoint->getPublicUrl()
265:             : $this->endpoint->getPrivateUrl();
266: 
267:         if ($url === null) {
268:             throw new Exceptions\ServiceException(sprintf(
269:                 'The base %s could not be found. Perhaps the service '
270:                 . 'you are using requires a different URL type, or does '
271:                 . 'not support this region.',
272:                 $this->urlType
273:             ));
274:         }
275: 
276:         return $url;
277:     }
278: }
279: 
API documentation generated by ApiGen 2.8.0