~tcuthbert/wordpress/openstack-objectstorage

« back to all changes in this revision

Viewing changes to src/OpenStack/Bootstrap.php

  • Committer: Jacek Nykis
  • Date: 2015-02-11 15:35:31 UTC
  • Revision ID: jacek.nykis@canonical.com-20150211153531-hmy6zi0ov2qfkl0b
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
 
 
3
/*
 
4
 * (c) Copyright 2012-2014 Hewlett-Packard Development Company, L.P.
 
5
 * (c) Copyright 2014      Rackspace US, Inc.
 
6
 *
 
7
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 
8
 * not use this file except in compliance with the License. You may obtain
 
9
 * a copy of the License at
 
10
 *
 
11
 *      http://www.apache.org/licenses/LICENSE-2.0
 
12
 *
 
13
 * Unless required by applicable law or agreed to in writing, software
 
14
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
15
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
16
 * License for the specific language governing permissions and limitations
 
17
 * under the License.
 
18
 */
 
19
 
 
20
namespace OpenStack;
 
21
 
 
22
use OpenStack\Identity\v2\IdentityService;
 
23
use OpenStack\ObjectStore\v1\Resource\StreamWrapper;
 
24
use OpenStack\ObjectStore\v1\Resource\StreamWrapperFS;
 
25
 
 
26
/**
 
27
 * Bootstrapping services.
 
28
 *
 
29
 * There is no requirement that this class be used. OpenStack is
 
30
 * built to be flexible, and any individual component can be
 
31
 * used directly, with one caveat: No explicit `require` or
 
32
 * `include` calls are made.
 
33
 *
 
34
 * This class provides the following services:
 
35
 *
 
36
 * - Configuration: "global" settings are set here.
 
37
 *   See the setConfiguration() method to see how they
 
38
 *   can be set, and the config() and hasConfig() methods to see
 
39
 *   how configuration might be checked.
 
40
 * - Stream Wrappers: This class can initialize a set of stream
 
41
 *   wrappers which will make certain OpenStack services available
 
42
 *   through the core PHP stream support.
 
43
 *
 
44
 * Configuration
 
45
 *
 
46
 * Configuration directives can be merged into the existing confiuration
 
47
 * using the setConfiguration method.
 
48
 *
 
49
 *     <?php
 
50
 *     $config = array(
 
51
 *       // We use Guzzle, which defaults to CURL, for a transport layer.
 
52
 *       'transport' => 'OpenStack\Common\Transport\Guzzle\GuzzleAdapter',
 
53
 *       // Set the HTTP max wait time to 500 seconds.
 
54
 *       'transport.timeout' => 500,
 
55
 *     );
 
56
 *     Bootstrap::setConfiguration($config);
 
57
 *
 
58
 *     // Check and get params.
 
59
 *     if (Bootstrap::hasConf('transport.timeout') {
 
60
 *       $to = Bootstrap::conf('transport.timeout');
 
61
 *     }
 
62
 *
 
63
 *     // Or get a param with a default value:
 
64
 *     $val = Bootstrap::conf('someval', 'default value');
 
65
 *
 
66
 *     // $val will be set to 'default value' because there
 
67
 *     // is no 'someval' configuration param.
 
68
 *
 
69
 *     ?>
 
70
 *
 
71
 * STREAM WRAPPERS
 
72
 *
 
73
 * Stream wrappers allow you to use the built-in file manipulation
 
74
 * functions in PHP to interact with other services. Specifically,
 
75
 * the OpenStack stream wrappers allow you to use built-in file commands
 
76
 * to access Object Storage (Swift) and other OpenStack services using
 
77
 * commands like file_get_contents() and fopen().
 
78
 *
 
79
 * It's awesome. Trust me.
 
80
 */
 
81
class Bootstrap
 
82
{
 
83
    const VERSION = '0.0.1';
 
84
 
 
85
    public static $config = [
 
86
        // The transport implementation. By default, we use the Guzzle Client
 
87
        'transport' => 'OpenStack\Common\Transport\Guzzle\GuzzleAdapter',
 
88
    ];
 
89
 
 
90
    /**
 
91
     * @var \OpenStack\Identity\v2\IdentityService An identity services object
 
92
     *   created from the global settings.
 
93
     */
 
94
    public static $identity = null;
 
95
 
 
96
    /**
 
97
     * @var \OpenStack\Common\Transport\ClientInterface A transport client for requests.
 
98
     */
 
99
    public static $transport = null;
 
100
 
 
101
    /**
 
102
     * Register stream wrappers for OpenStack.
 
103
     *
 
104
     * This registers the ObjectStorage stream wrappers, which allow you to access
 
105
     * ObjectStorage through standard file access mechanisms.
 
106
     *
 
107
     *     // Enable stream wrapper.
 
108
     *     Bootstrap::useStreamWrappers();
 
109
     *
 
110
     *     // Create a context resource.
 
111
     *     $cxt = stream_context_create(array(
 
112
     *       'tenantid' => '12de21',
 
113
     *       'username' => 'foobar',
 
114
     *       'password' => 'f78saf7hhlll',
 
115
     *       'endpoint' => 'https://identity.hpcloud.com' // <-- not real URL!
 
116
     *     ));
 
117
     *
 
118
     *     // Get the contents of a Swift object.
 
119
     *     $content = file_get_contents('swift://public/notes.txt', 'r', false, $cxt);
 
120
     */
 
121
    public static function useStreamWrappers()
 
122
    {
 
123
        self::enableStreamWrapper(
 
124
            StreamWrapper::DEFAULT_SCHEME,
 
125
            'OpenStack\ObjectStore\v1\Resource\StreamWrapper'
 
126
        );
 
127
        self::enableStreamWrapper(
 
128
            StreamWrapperFS::DEFAULT_SCHEME,
 
129
            'OpenStack\ObjectStore\v1\Resource\StreamWrapperFS'
 
130
        );
 
131
    }
 
132
 
 
133
    /**
 
134
     * Register a stream wrapper according to its scheme and class
 
135
     *
 
136
     * @param $scheme Stream wrapper's scheme
 
137
     * @param $class  The class that contains stream wrapper functionality
 
138
     */
 
139
    private static function enableStreamWrapper($scheme, $class)
 
140
    {
 
141
        if (in_array($scheme, stream_get_wrappers())) {
 
142
            stream_wrapper_unregister($scheme);
 
143
        }
 
144
 
 
145
        stream_wrapper_register($scheme, $class);
 
146
    }
 
147
 
 
148
    /**
 
149
     * Set configuration directives for OpenStack.
 
150
     *
 
151
     * This merges the provided associative array into the existing
 
152
     * configuration parameters (Bootstrap::$config).
 
153
     *
 
154
     * All of the OpenStack classes share the same configuration. This
 
155
     * ensures that a stable runtime environment is maintained.
 
156
     *
 
157
     * Common configuration directives:
 
158
     *
 
159
     * - 'transport': The namespaced classname for the transport that
 
160
     *   should be used. Example: \OpenStack\Common\Transport\Guzzle\GuzzleAdapter
 
161
     * - 'transport.debug': The integer 1 for enabling debug, 0 for
 
162
     *   disabling. Enabling will turn on verbose debugging output
 
163
     *   for any transport that supports it.
 
164
     * - 'transport.timeout': An integer value indicating how long
 
165
     *   the transport layer should wait for an HTTP request. A
 
166
     *   transport MAY ignore this parameter, but the ones included
 
167
     *   with the library honor it.
 
168
     * - 'transport.ssl_verify': Set this to false to turn off SSL certificate
 
169
     *   verification. This is NOT recommended, but is sometimes necessary for
 
170
     *   certain proxy configurations.
 
171
     * - 'transport.proxy': Set the proxy as a string.
 
172
     * - 'username' and 'password'
 
173
     * - 'tenantid'
 
174
     * - 'endpoint': The full URL to identity services. This is used by stream
 
175
     *   wrappers.
 
176
     *
 
177
     * @param array $array An associative array of configuration directives.
 
178
     */
 
179
    public static function setConfiguration($array)
 
180
    {
 
181
        self::$config = $array + self::$config;
 
182
    }
 
183
 
 
184
    /**
 
185
     * Get a configuration option.
 
186
     *
 
187
     * Get a configuration option by name, with an optional default.
 
188
     *
 
189
     * @param string $name    The name of the configuration option to get.
 
190
     * @param mixed  $default The default value to return if the name is not found.
 
191
     *
 
192
     * @return mixed The value, if found; or the default, if set; or null.
 
193
     */
 
194
    public static function config($name = null, $default = null)
 
195
    {
 
196
        // If no name is specified, return the entire config array.
 
197
        if (empty($name)) {
 
198
            return self::$config;
 
199
        }
 
200
 
 
201
        // If the config value exists, return that.
 
202
        if (isset(self::$config[$name])) {
 
203
            return self::$config[$name];
 
204
        }
 
205
 
 
206
        // Otherwise, just return the default value.
 
207
        return $default;
 
208
    }
 
209
 
 
210
    /**
 
211
     * Check whether the given configuration option is set.
 
212
     *
 
213
     *     if (Bootstrap::hasConfig('transport')) {
 
214
     *       syslog(LOG_INFO, 'An alternate transport is supplied.');
 
215
     *     }
 
216
     *
 
217
     * @param string $name The name of the item to check for.
 
218
     *
 
219
     * @return boolean true if the named option is set, false otherwise. Note that
 
220
     *                 the value may be falsey (false, 0, etc.), but if the value is null, this
 
221
     *                 will return false.
 
222
     */
 
223
    public static function hasConfig($name)
 
224
    {
 
225
        return isset(self::$config[$name]);
 
226
    }
 
227
 
 
228
    /**
 
229
     * Get a \OpenStack\Identity\v2\IdentityService object from the bootstrap config.
 
230
     *
 
231
     * A factory helper function that uses the bootstrap configuration to create
 
232
     * a ready to use \OpenStack\Identity\v2\IdentityService object.
 
233
     *
 
234
     * @param bool $force Whether to force the generation of a new object even if
 
235
     *                    one is already cached.
 
236
     *
 
237
     * @return \OpenStack\Identity\v2\IdentityService An authenticated ready to use
 
238
     *                                                \OpenStack\Identity\v2\IdentityService object.
 
239
     * @throws \OpenStack\Common\Exception When the needed configuration to authenticate
 
240
     *                              is not available.
 
241
     */
 
242
    public static function identity($force = false)
 
243
    {
 
244
        $transport = self::transport();
 
245
 
 
246
        // If we already have an identity make sure the token is not expired.
 
247
        if ($force || is_null(self::$identity) || self::$identity->isExpired()) {
 
248
 
 
249
            // Make sure we have an endpoint to use
 
250
            if (!self::hasConfig('endpoint')) {
 
251
                throw new Exception('Unable to authenticate. No endpoint supplied.');
 
252
            }
 
253
 
 
254
            // User cannot be an empty string, so we need
 
255
            // to do more checking than self::hasConfig(), which returns true
 
256
            // if an item exists and is an empty string.
 
257
            $user = self::config('username', null);
 
258
 
 
259
            // Check if we have a username/password
 
260
            if (!empty($user) && self::hasConfig('password')) {
 
261
                $is = new IdentityService(self::config('endpoint'), $transport);
 
262
                $is->authenticateAsUser($user, self::config('password'), self::config('tenantid', null), self::config('tenantname', null));
 
263
                self::$identity = $is;
 
264
            } else {
 
265
                throw new Exception('Unable to authenticate. No user credentials supplied.');
 
266
            }
 
267
        }
 
268
 
 
269
        return self::$identity;
 
270
    }
 
271
 
 
272
    /**
 
273
     * Get a transport client.
 
274
     *
 
275
     * @param  boolean $reset Whether to recreate the transport client if one already exists.
 
276
     *
 
277
     * @return \OpenStack\Common\Transport\ClientInterface A transport client.
 
278
     */
 
279
    public static function transport($reset = false)
 
280
    {
 
281
        if (is_null(self::$transport) || $reset == true) {
 
282
            $options = [
 
283
                'ssl_verify' => self::config('ssl_verify', true),
 
284
                'timeout' => self::config('timeout', 0),          // 0 is no timeout.
 
285
                'debug' => self::config('debug', 0),
 
286
            ];
 
287
            $proxy = self::config('proxy', false);
 
288
            if ($proxy) {
 
289
                $options['proxy'] = $proxy;
 
290
            }
 
291
 
 
292
            $class = self::config('transport');
 
293
            self::$transport = $class::create($options);
 
294
        }
 
295
 
 
296
        return self::$transport;
 
297
    }
 
298
}