Completed
Pull Request — master (#145)
by Vitaly
02:44
created

Openstack::createCollector()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
namespace phpbu\App\Backup\Sync;
3
4
use GuzzleHttp\Psr7\Stream;
5
use OpenStack\ObjectStore\v1\Models\Container;
6
use OpenStack\ObjectStore\v1\Service as ObjectStoreService;
7
use GuzzleHttp\Client;
8
use OpenStack\Common\Transport\HandlerStack;
9
use OpenStack\Common\Transport\Utils;
10
use OpenStack\Identity\v2\Service;
11
use phpbu\App\Backup\Collector;
12
use phpbu\App\Backup\Sync;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, phpbu\App\Backup\Sync\Sync.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
13
use phpbu\App\Backup\Target;
14
use phpbu\App\Result;
15
use phpbu\App\Util;
16
17
/**
18
 * OpenStack Swift Sync
19
 *
20
 * @package    phpbu
21
 * @subpackage Backup
22
 * @author     Vitaly Baev <[email protected]>
23
 * @author     Sebastian Feldmann <[email protected]>
24
 * @copyright  Sebastian Feldmann <[email protected]>
25
 * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
26
 * @link       http://phpbu.de/
27
 * @since      Class available since Release 5.1
28
 */
29
class Openstack extends Sync
30
{
31
    use Clearable;
32
33
    /**
34
     * OpenStack identify url
35
     *
36
     * @var string
37
     */
38
    protected $authUrl;
39
40
    /**
41
     * OpenStack region
42
     *
43
     * @var string
44
     */
45
    protected $region;
46
47
    /**
48
     * @var string
49
     */
50
    protected $username;
51
52
    /**
53
     * @var string
54
     */
55
    protected $password;
56
57
    /**
58
     * Object Store container name
59
     *
60
     * @var string
61
     */
62
    protected $containerName;
63
64
    /**
65
     * OpenStack service name
66
     *
67
     * @var string
68
     */
69
    protected $serviceName;
70
71
    /**
72
     * Max stream upload size, files over this size have to be uploaded as Dynamic Large Objects
73
     *
74
     * @var int
75
     */
76
    protected $maxStreamUploadSize = 5368709120;
77
78
    /**
79
     * Path where to copy the backup.
80
     *
81
     * @var string
82
     */
83
    protected $path = '';
84
85
    /**
86
     * @var Container
87
     */
88
    protected $container;
89
90
    /**
91
     * @return string
92
     */
93
    public function getPath(): string
94
    {
95
        return $this->path;
96
    }
97
98
    /**
99
     * (non-PHPDoc)
100
     *
101
     * @see    \phpbu\App\Backup\Sync::setup()
102
     * @param  array $config
103
     * @throws \phpbu\App\Backup\Sync\Exception
104
     * @throws \phpbu\App\Exception
105
     */
106 9
    public function setup(array $config)
107
    {
108 9
        if (!class_exists('\\OpenStack\\OpenStack')) {
109
            throw new Exception('OpeStack SDK not loaded: use composer to install "php-opencloud/openstack"');
110
        }
111
112
        // check for mandatory options
113 9
        $this->validateConfig($config, ['auth_url', 'region', 'username', 'password', 'container_name']);
114
115 4
        $this->authUrl       = $config['auth_url'];
116 4
        $this->region        = $config['region'];
117 4
        $this->username      = $config['username'];
118 4
        $this->password      = $config['password'];
119 4
        $this->containerName = $config['container_name'];
120 4
        $this->serviceName   = Util\Arr::getValue($config, 'service_name', 'swift');
121 4
        if (Util\Arr::getValue($config, 'path')) {
122 1
            $this->path = Util\Path::withTrailingSlash(Util\Path::replaceDatePlaceholders($config['path']));
123 1
            $this->path = substr($this->path, 0, 1) == '/' ? substr($this->path, 1) : $this->path;
124
        }
125
126 4
        $this->setUpClearable($config);
127 4
    }
128
129
    /**
130
     * Execute the sync.
131
     *
132
     * @see    \phpbu\App\Backup\Sync::sync()
133
     * @param  \phpbu\App\Backup\Target $target
134
     * @param  \phpbu\App\Result        $result
135
     * @throws \phpbu\App\Backup\Sync\Exception
136
     * @throws \OpenStack\Common\Error\BadResponseError
137
     */
138
    public function sync(Target $target, Result $result)
139
    {
140
        if (!$this->container) {
141
            $this->connect($result);
142
        }
143
144
        try {
145
            if ($target->getSize() > $this->maxStreamUploadSize) {
146
                // use Dynamic Large Objects
147
                $uploadOptions = [
148
                    'name'   => $this->getUploadPath($target),
149
                    'stream' => new Stream(fopen($target->getPathname(), 'r')),
150
                ];
151
                $this->container->createLargeObject($uploadOptions);
152
            } else {
153
                // create an object
154
                $uploadOptions = [
155
                    'name' => $this->getUploadPath($target),
156
                    'content' => file_get_contents($target->getPathname()),
157
                ];
158
                $this->container->createObject($uploadOptions);
159
            }
160
        } catch (\Exception $e) {
161
            throw new Exception($e->getMessage(), null, $e);
162
        }
163
        // run remote cleanup
164
        $this->cleanup($target, $result);
165
        $result->debug('upload: done');
166
    }
167
168
    /**
169
     * Simulate the sync execution.
170
     *
171
     * @param \phpbu\App\Backup\Target $target
172
     * @param \phpbu\App\Result        $result
173
     */
174 1
    public function simulate(Target $target, Result $result)
175
    {
176 1
        $result->debug(
177 1
            'sync backup to OpenStack' . PHP_EOL
178 1
            . '  region:   ' . $this->region . PHP_EOL
179 1
            . '  key:      ' . $this->username . PHP_EOL
180 1
            . '  password:    ********' . PHP_EOL
181 1
            . '  container: ' . $this->containerName
182 1
            . '  path: "' . $this->path . '"' . PHP_EOL
183
        );
184
185 1
        $this->simulateRemoteCleanup($target, $result);
186 1
    }
187
188
    /**
189
     * Creates collector for OpenStack
190
     *
191
     * @param \phpbu\App\Backup\Target $target
192
     * @return \phpbu\App\Backup\Collector
193
     */
194
    protected function createCollector(Target $target): Collector
195
    {
196
        return new Collector\OpenStack($target, $this->container, $this->path);
197
    }
198
199
    /**
200
     * @param ObjectStoreService $service
201
     * @param Result             $result
202
     * @return \OpenStack\ObjectStore\v1\Models\Container
203
     * @throws \OpenStack\Common\Error\BadResponseError
204
     */
205
    protected function getOrCreateContainer(ObjectStoreService $service, Result $result)
206
    {
207
        if (!$service->containerExists($this->containerName)) {
208
            $result->debug('create container');
209
            return $service->createContainer(['name' => $this->containerName]);
210
        }
211
        return $service->getContainer($this->containerName);
212
    }
213
214
    /**
215
     * Get the upload path
216
     *
217
     * @param \phpbu\App\Backup\Target $target
218
     * @return string
219
     */
220 2
    public function getUploadPath(Target $target)
221
    {
222 2
        return $this->path . $target->getFilename();
223
    }
224
225
    /**
226
     * @param Result $result
227
     * @return void
228
     * @throws \OpenStack\Common\Error\BadResponseError
229
     */
230
    protected function connect(Result $result)
231
    {
232
        $httpClient = new Client([
233
            'base_uri' => Utils::normalizeUrl($this->authUrl),
234
            'handler'  => HandlerStack::create(),
235
        ]);
236
237
        $options = [
238
            'authUrl'         => $this->authUrl,
239
            'region'          => $this->region,
240
            'username'        => $this->username,
241
            'password'        => $this->password,
242
            'identityService' => Service::factory($httpClient),
243
        ];
244
245
        $openStack = new \OpenStack\OpenStack($options);
246
        $objectStoreService = $openStack->objectStoreV1(['catalogName' => $this->serviceName]);
247
        $this->container = $this->getOrCreateContainer($objectStoreService, $result);
248
    }
249
}
250