Passed
Push — develop ( bce914...037e9d )
by Портнов
04:55
created

CloudProvisioning::azureProvisioning()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 66
Code Lines 53

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 53
c 1
b 0
f 0
dl 0
loc 66
rs 9.0254
cc 4
nc 5
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * MikoPBX - free phone system for small business
4
 * Copyright © 2017-2021 Alexey Portnov and Nikolay Beketov
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with this program.
17
 * If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
namespace MikoPBX\Core\System;
21
22
use MikoPBX\Common\Models\LanInterfaces;
23
use MikoPBX\Common\Models\PbxSettings;
24
use MikoPBX\Core\System\Configs\SSHConf;
25
26
class CloudProvisioning
27
{
28
    public const PBX_SETTING_KEY = 'CloudProvisioning';
29
    public static function start():void
30
    {
31
        if(PbxSettings::findFirst('key="'.self::PBX_SETTING_KEY.'"')){
32
            // Уже отработали ранее.
33
            return;
34
        }
35
        $cp = new self();
36
        $resultProvisioning = $cp->googleProvisioning();
37
        if(!$resultProvisioning){
38
            $resultProvisioning = $cp->azureProvisioning();
39
        }
40
41
        $setting = PbxSettings::findFirst('key="'.self::PBX_SETTING_KEY.'"');
42
        if(!$setting){
43
            $setting = new PbxSettings();
44
            $setting->key = self::PBX_SETTING_KEY;
45
        }
46
        $setting->value = $resultProvisioning ? '1' : '0';
47
        $setting->save();
48
        unset($setting);
49
    }
50
51
    private function updateSshPassword(string $data=''):void{
52
        if(empty($data)){
53
            $data = md5(time());
54
        }
55
        $this->updatePbxSettings('SSHPassword', $data);
56
        $confSsh = new SSHConf();
57
        $confSsh->updateShellPassword();
58
    }
59
60
    /**
61
     * Обновление пароля к SSH.
62
     * @param $keyName
63
     * @param $data
64
     */
65
    private function updatePbxSettings($keyName, $data):void{
66
        $setting = PbxSettings::findFirst('key="'.$keyName.'"');
67
        if(!$setting){
68
            $setting = new PbxSettings();
69
            $setting->key = $keyName;
70
        }
71
        $setting->value = $data;
72
        $result = $setting->save();
73
        if($result){
74
            Util::sysLogMsg(__CLASS__, "Update $keyName ... ");
75
        }else{
76
            Util::sysLogMsg(__CLASS__, "FAIL Update $keyName ... ");
77
        }
78
        unset($setting);
79
    }
80
81
    /**
82
     * Обновление ключей ssh.
83
     * @param string $data
84
     */
85
    private function updateSSHKeys(string $data):void{
86
        if(empty($data)){
87
            return;
88
        }
89
        $this->updatePbxSettings('SSHAuthorizedKeys', $data);
90
    }
91
92
    /**
93
     * Обновление имени хост.
94
     */
95
    private function updateLanSettings($hostname, $extipaddr):void{
96
        /** @var LanInterfaces $lanData */
97
        $lanData = LanInterfaces::findFirst();
98
        if($lanData){
0 ignored issues
show
introduced by
$lanData is of type MikoPBX\Common\Models\LanInterfaces, thus it always evaluated to true.
Loading history...
99
            if(!empty($extipaddr)){
100
                $lanData->extipaddr = $extipaddr;
101
                $lanData->topology  = 'private';
102
            }
103
            if(!empty($hostname)){
104
                $lanData->hostname  = $hostname;
105
            }
106
            $result = $lanData->save();
107
            if($result){
108
                Util::sysLogMsg(__CLASS__, 'Update LAN... '.$hostname.'  '. $extipaddr);
109
            }else{
110
                Util::sysLogMsg(__CLASS__, 'FAIL Update LAN... '.$hostname.'  '. $extipaddr);
111
            }
112
        }else{
113
            Util::sysLogMsg(__CLASS__, 'LAN not found... '.$hostname.'  '. $extipaddr);
114
        }
115
    }
116
117
    /**
118
     * Настройка машины для Google Claod.
119
     */
120
    public function googleProvisioning():bool
121
    {
122
        $curl    = curl_init();
123
        $url     = 'http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true';
124
        curl_setopt($curl, CURLOPT_URL, $url);
125
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
126
        curl_setopt($curl, CURLOPT_TIMEOUT, 1);
127
        curl_setopt($curl, CURLOPT_HTTPHEADER, ['Metadata-Flavor:Google']);
128
        $resultRequest = curl_exec($curl);
129
        $http_code     = (int)curl_getinfo($curl, CURLINFO_HTTP_CODE);
130
        curl_close($curl);
131
        if($http_code === 0){
132
            return false;
133
        }
134
        $data = json_decode($resultRequest, true);
0 ignored issues
show
Bug introduced by
It seems like $resultRequest can also be of type true; however, parameter $json of json_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

134
        $data = json_decode(/** @scrutinizer ignore-type */ $resultRequest, true);
Loading history...
135
        $this->updateSSHKeys($data['attributes']['ssh-keys']??'');
136
137
        $hostname = $data['name']??'';
138
        $extipaddr= $data['networkInterfaces'][0]['accessConfigs'][0]['externalIp']??'';
139
        $this->updateLanSettings($hostname, $extipaddr);
140
        $this->updateSshPassword();
141
        return true;
142
    }
143
144
    /**
145
     * Настройка машины для Azure Claod.
146
     */
147
    public function azureProvisioning():bool
148
    {
149
        $baseUrl = 'http://168.63.129.16/machine';
150
        $timeout = 4;
151
152
        $curl = curl_init();
153
        $url  = "{$baseUrl}?comp=goalstate";
154
        curl_setopt($curl, CURLOPT_URL, $url);
155
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
156
        curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
157
        curl_setopt($curl, CURLOPT_HTTPHEADER, ['x-ms-version: 2012-11-30']);
158
        $resultRequest = curl_exec($curl);
159
        $http_code     = (int)curl_getinfo($curl, CURLINFO_HTTP_CODE);
160
        curl_close($curl);
161
162
        if($http_code === 0){
163
            $setting = new PbxSettings();
164
            $setting->key = self::PBX_SETTING_KEY;
165
            $setting->save();
166
            $setting->value = '0';
167
            unset($setting);
168
            // It is not azure;
169
            return false;
170
        }
171
172
        $xml = simplexml_load_string($resultRequest);
0 ignored issues
show
Bug introduced by
It seems like $resultRequest can also be of type true; however, parameter $data of simplexml_load_string() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

172
        $xml = simplexml_load_string(/** @scrutinizer ignore-type */ $resultRequest);
Loading history...
173
        $xmlDocument = $this->getAzureXmlResponse($xml->Container->ContainerId, $xml->Container->RoleInstanceList->RoleInstance->InstanceId);
174
        $url="{$baseUrl}?comp=health";
175
        $headers = [
176
            'x-ms-version: 2012-11-30',
177
            'x-ms-agent-name: WALinuxAgent',
178
            'Content-Type: text/xml;charset=utf-8',
179
        ];
180
181
        $curl = curl_init();
182
        curl_setopt($curl, CURLOPT_URL, $url);
183
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
184
        curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
185
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
186
        curl_setopt($curl, CURLOPT_POST, true);
187
        curl_setopt($curl, CURLOPT_POSTFIELDS, $xmlDocument);
188
189
        curl_exec($curl);
190
        $http_code     = (int)curl_getinfo($curl, CURLINFO_HTTP_CODE);
191
        $result = false;
192
        if($http_code === 200){
193
            $result = true;
194
        }
195
        $curl = curl_init();
196
        $url  = "http://169.254.169.254/metadata/instance?api-version=2020-09-01";
197
        curl_setopt($curl, CURLOPT_URL, $url);
198
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
199
        curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
200
        curl_setopt($curl, CURLOPT_HTTPHEADER, ['Metadata:true']);
201
        $resultRequest = curl_exec($curl);
202
        curl_close($curl);
203
204
        $arrKeys = [];
205
        $jsonData = json_decode($resultRequest, true);
0 ignored issues
show
Bug introduced by
It seems like $resultRequest can also be of type true; however, parameter $json of json_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

205
        $jsonData = json_decode(/** @scrutinizer ignore-type */ $resultRequest, true);
Loading history...
206
        $publicKeys = $jsonData['compute']['publicKeys']??[];
207
        foreach ($publicKeys as $keeData){
208
            $arrKeys[]= $keeData['keyData'];
209
        }
210
        $this->updateSSHKeys(implode(PHP_EOL, $arrKeys));
211
        $this->updateSshPassword();
212
        return $result;
213
    }
214
215
    /**
216
     * Возвращает строку XML для ответа о готовкности машины.
217
     * @param $containerId
218
     * @param $instanceId
219
     * @return string
220
     */
221
    private function getAzureXmlResponse($containerId, $instanceId):string
222
    {
223
        return '<Health>
224
  <GoalStateIncarnation>1</GoalStateIncarnation>
225
  <Container>
226
    <ContainerId>'.$containerId.'</ContainerId>
227
    <RoleInstanceList>
228
      <Role>
229
        <InstanceId>'.$instanceId.'</InstanceId>
230
        <Health>
231
          <State>Ready</State>
232
        </Health>
233
      </Role>
234
    </RoleInstanceList>
235
  </Container>
236
</Health>';
237
    }
238
}