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\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