source: trunk/www/Module/Server/Model.php

Last change on this file was 95, checked in by chronos, 10 years ago
  • Upraveno: Soubory různých logických částí systému odděleny do aplikačních modulů.
File size: 12.9 KB
Line 
1<?php
2
3include_once(dirname(__FILE__).'/../../Base/Model.php');
4
5class Server extends Model
6{
7 var $Id;
8 var $Server;
9 var $Task;
10
11 function __construct($System, $Id)
12 {
13 parent::__construct($System);
14 $this->Task = new Task($System);
15 $this->Id = $Id;
16 $DbResult = $this->Database->query('SELECT * FROM `Server` WHERE `Id`='.$Id);
17 if($DbResult->num_rows > 0)
18 {
19 $this->Server = $DbResult->fetch_assoc();
20 $DbResult = $this->Database->query('SELECT * FROM `Database` WHERE `Id`='.$this->Server['Database']);
21 if($DbResult->num_rows > 0) $this->Server['Database'] = $DbResult->fetch_assoc();
22 else $this->Server['Database'] = array('Emulator' => 0);
23 $DbResult = $this->Database->query('SELECT * FROM `Emulator` WHERE `Id`='.$this->Server['Database']['Emulator']);
24 if($DbResult->num_rows > 0) $this->Server['Database']['Emulator'] = $DbResult->fetch_assoc();
25 else $this->Server['Database']['Emulator'] = array('Client' => 0);
26 $DbResult = $this->Database->query('SELECT * FROM `Client` WHERE `Id`='.$this->Server['Database']['Emulator']['Client']);
27 if($DbResult->num_rows > 0) $this->Server['Database']['Emulator']['Client'] = $DbResult->fetch_assoc();
28 else $this->Server['Database']['Emulator']['Client'] = array();
29 }
30 }
31
32 function CreateDatabase()
33 {
34 $this->Database->query('CREATE DATABASE `server'.$this->Id.'_realmd`');
35 $this->Database->query('CREATE USER "server'.$this->Id.'"@"localhost" IDENTIFIED BY "server'.$this->Id.'"');
36 $this->Database->query('GRANT ALL PRIVILEGES ON `server'.$this->Id.'\_realmd` . * TO "server'.$this->Id.'"@"localhost" WITH GRANT OPTION');
37 }
38
39 function DeleteDatabase()
40 {
41 $this->Database->query('DROP DATABASE `server'.$this->Id.'_realmd`');
42 $this->Database->query('DROP USER "server'.$this->Id.'"@"localhost"');
43 }
44
45 function Start()
46 {
47 $this->Lock();
48 $this->SaveConfiguration();
49 $this->Task->Add('Start emulátoru', array(
50 'php www/shell.php ServerLock '.$this->Id,
51 'server/'.$this->Id.'/bin/start.sh',
52 'php www/shell.php ServerUnLock '.$this->Id,
53 ));
54 return('Požadavek na start serveru zařazen.');
55 }
56
57 function Stop()
58 {
59 $this->Lock();
60 $this->Task->Add('Zastavení emulátoru', array(
61 'php www/shell.php ServerLock '.$this->Id,
62 'server/'.$this->Id.'/bin/stop.sh',
63 'php www/shell.php ServerUnLock '.$this->Id,
64 ));
65 return('Požadavek na zastavení serveru zařazen.');
66 }
67
68 function GetState()
69 {
70 $State = array();
71 $State['RealmdPortState'] = $this->System->NetworkPortState('localhost', $this->Server['NetworkPortRealmd']);
72 $State['Online'] = $State['RealmdPortState'];
73 $DbResult = $this->Database->query('SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = "server'.$this->Id.'_realmd"');
74 $DbRow = $DbResult->fetch_row();
75 if($DbRow[0] > 0)
76 {
77 $State['AccountCount'] = $DbRow[0];
78 $DbResult = $this->Database->query('SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = "server'.$this->Id.'_realmd" AND TABLE_NAME = "uptime"');
79 $DbRow = $DbResult->fetch_row();
80 if($DbRow[0] > 0)
81 {
82 $DbResult = $this->Database->query('SELECT uptime FROM server'.$this->Id.'_realmd.uptime AS T ORDER BY T.startstring DESC');
83 $DbRow = $DbResult->fetch_assoc();
84 $State['Uptime'] = $DbRow['uptime'];
85 } else $State['Uptime'] = 0;
86 } else
87 {
88 $State['AccountCount'] = 0;
89 $State['Uptime'] = 0;
90 }
91 $State['UsedMemory'] = $this->GetUsedMemory();
92 return($State);
93 }
94
95 function UpdateRealmlist()
96 {
97 $this->Database->query('TRUNCATE TABLE server'.$this->Id.'_realmd.realmlist');
98 $DbResult = $this->Database->select('Realm', '*', 'Server = '.$this->Id);
99 while($Realm = $DbResult->fetch_assoc())
100 {
101 $this->Database->insert('server'.$this->Id.'_realmd`.`realmlist',
102 array('id' => $Realm['Id'], 'name' => addslashes($Realm['Name']),
103 'address' => $this->Config['Web']['Host'], 'port' => $Realm['NetworkPortWorldd'],
104 'icon' => 0, 'timezone' => 1, 'color' => 0));
105 }
106 }
107
108 function SaveConfiguration()
109 {
110 $this->SetupConfigurationFiles();
111 $this->UpdateRealmlist();
112 $this->UpdateScripts();
113 }
114
115 function UpdateScripts()
116 {
117 $ServerBinDir = '../server/'.$this->Id.'/bin/';
118 if(!file_exists($ServerBinDir)) mkdir($ServerBinDir, 0777, true);
119
120 // Start script
121 $ScriptFileName = '../server/'.$this->Id.'/bin/start.sh';
122 $Content = array
123 (
124 '#!/bin/sh',
125 'if [ -z `ps -ef | grep \'SCREEN -A -m -d -S server'.$this->Id.'-realmd\' | grep -v grep | awk \'{print $2}\'` ]',
126 'then',
127 'screen -A -m -d -S server'.$this->Id.'-realmd emulator/'.$this->Server['Database']['Emulator']['Id'].'/bin/mangos-realmd -c server/'.$this->Id.'/etc/realmd.conf',
128 'fi',
129 );
130 file_put_contents($ScriptFileName, implode("\n", $Content));
131 chmod($ScriptFileName, 0777);
132
133 // Stop script
134 $ScriptFileName = '../server/'.$this->Id.'/bin/stop.sh';
135 $Content = array
136 (
137 '#!/bin/sh',
138 'ps -ef | grep \'SCREEN -A -m -d -S server'.$this->Id.'-realmd\' | grep -v grep | awk \'{print $2}\' | xargs -i kill {}',
139 );
140 file_put_contents($ScriptFileName, implode("\n", $Content));
141 chmod($ScriptFileName, 0777);
142 }
143
144 function SetupConfigurationFiles()
145 {
146 $EmulatorEtcDir = '../emulator/'.$this->Server['Database']['Emulator']['Id'].'/etc/';
147 $ServerEtcDir = '../server/'.$this->Id.'/etc/';
148 $ServerLogDir = '../server/'.$this->Id.'/log/';
149 if(!file_exists($ServerEtcDir)) mkdir($ServerEtcDir, 0777, true);
150 if(!file_exists($ServerLogDir)) mkdir($ServerLogDir, 0777, true);
151
152 // realmd.conf
153 $EmulatorConfig = new MangosConfigurationFile($this->System);
154 $EmulatorConfig->Load($EmulatorEtcDir.'realmd.conf.dist');
155 $EmulatorConfig->ParameterList['LoginDatabaseInfo'] = 'localhost;3306;server'.$this->Id.';server'.$this->Id.';server'.$this->Id.'_realmd';
156 $EmulatorConfig->ParameterList['RealmServerPort'] = $this->Server['NetworkPortRealmd'];
157 $EmulatorConfig->ParameterList['LogsDir'] = 'server/'.$this->Id.'/log';
158 $EmulatorConfig->Save($ServerEtcDir.'realmd.conf');
159 }
160
161 function UpdateState()
162 {
163 $State = $this->GetState();
164 $this->Database->update('Server', 'Id='.$this->Id, array(
165 'Online' => $State['Online'],
166 'AccountCount' => $State['AccountCount'],
167 ));
168 }
169
170 function UpdateStateAll()
171 {
172 $DbResult = $this->Database->select('Server', 'Id');
173 while($DbRow = $DbResult->fetch_assoc())
174 {
175 $Server = new Server($this->System, $DbRow['Id']);
176 $Server->UpdateState();
177 }
178 }
179
180 function NewAccount($Name, $Password, $Password2, $Email, $Expansion)
181 {
182 $Output = '';
183 if(($Password == '') or ($Password2 == '') or ($Name == '') or ($Email == '')) $Output = 'Vyplňte správně všechny údaje.';
184 else if($Password != $Password2) $Output = 'Hesla si neodpovídají.';
185 else
186 {
187 $Name = strtoupper($Name);
188 $DbResult = $this->Database->query('SELECT Id FROM server'.$this->Id.'_realmd.account WHERE username="'.$Name.'"');
189 if($DbResult->num_rows > 0) $Output = 'Účet se zadaným jménem již existuje.';
190 else
191 {
192 $Password = sha1($Name.':'.strtoupper($Password));
193 $this->Database->query('INSERT INTO `server'.$this->Id.'_realmd`.`account` (`username`, `sha_pass_hash`, `email`, `joindate`, `expansion`) VALUES ("'.$Name.'", "'.$Password.'", "'.$Email.'", NOW(), '.$Expansion.')');
194 $Output = 'Nový účet vytvořen.';
195 }
196 }
197 return($Output);
198 }
199
200 function ImportDatabase($Delete = false)
201 {
202 $this->Lock();
203 $CommandList = array(
204 'php www/shell.php ServerLock '.$this->Id,
205 );
206 if($Delete == true)
207 {
208 $CommandList = array_merge($CommandList, array(
209 'mysql --silent --skip-column-names -u server'.$this->Id.' -pserver'.$this->Id.' server'.$this->Id.'_realmd -e "show tables" | gawk \'{print "drop table " $1 ";"}\' | mysql -u server'.$this->Id.' -pserver'.$this->Id.' server'.$this->Id.'_realmd',
210 ));
211 }
212 // Lookup nearest database with full import
213 $DbResult = $this->Database->query('SELECT * FROM `Database` WHERE (`Emulator` <> 0) AND (`Revision` <= '.$this->Server['Database']['Revision'].') AND (`SourceFileName` <> "") ORDER BY `Revision` DESC');
214 $Database = $DbResult->fetch_assoc();
215
216 $CommandList = array_merge($CommandList, array(
217 'mysql --user=server'.$this->Id.' --password=server'.$this->Id.' server'.$this->Id.'_realmd < emulator/'.$Database['Emulator']['Id'].'/share/mangos/sql/realmd.sql',
218 'php www/shell.php ServerDatabaseChange '.$this->Id.' '.$Database['Id'],
219 'php www/shell.php ServerUnLock '.$this->Id,
220 ));
221 $this->Task->Add('Inicializace databáze', $CommandList);
222
223 if($Database['Id'] != $this->Server['Database']['Id'])
224 {
225 $NewDatabaseId = $this->Server['Database']['Id'];
226 $this->Server['Database']['Id'] = $Database['Id'];
227 $this->Update($NewDatabaseId, false, false);
228 }
229 return('Úloha načtení nové databáze zařazena do fronty.');
230 }
231
232 function Update($DatabaseId, $DoBackup = true, $DoStop = true)
233 {
234 $this->Lock();
235 $Output = '';
236
237 // Stop server before update
238 if($DoStop)
239 {
240 $Output .= $this->Stop();
241 }
242
243 // Backup current
244 if($DoBackup)
245 {
246 $Backup = new Backup($this->System, 0);
247 $Output .= '<br />'.$Backup->Create($this->Id);
248 }
249
250 // Do update
251 $Commands = array(
252 'php www/shell.php ServerLock '.$this->Id,
253 );
254 $DbResult = $this->Database->query('SELECT `Revision` FROM `Database` WHERE `Id` = '.$this->Server['Database']['Id']);
255 $DbRow = $DbResult->fetch_assoc();
256 $DatabaseRevisionStart = $DbRow['Revision'];
257 $DbResult = $this->Database->query('SELECT `Revision` FROM `Database` WHERE `Id` = '.$DatabaseId);
258 $DbRow = $DbResult->fetch_assoc();
259 $DatabaseRevisionEnd = $DbRow['Revision'];
260 $DbResult = $this->Database->query('SELECT * FROM `Database` WHERE (`Revision` > '.$DatabaseRevisionStart.') AND (`Revision` <= '.$DatabaseRevisionEnd.') ORDER BY `Revision`');
261 while($DbRow = $DbResult->fetch_assoc())
262 {
263 $Updates = explode("\n", $DbRow['Update']);
264 foreach($Updates as $Update)
265 if($Update != '')
266 {
267 $Parts = explode('|', $Update);
268 if($Parts[0] == 'realmd')
269 $Command = 'mysql --user=server'.$this->Id.' --password=server'.$this->Id.' server'.$this->Id.'_'.$Parts[0].' < database/'.$DbRow['Id'].'/'.$Parts[1];
270 $Commands[] = $Command;
271 }
272 }
273 $Commands = array_merge($Commands, array(
274 'php www/shell.php ServerDatabaseChange '.$this->Id.' '.$DatabaseId,
275 'php www/shell.php ServerUnLock '.$this->Id,
276 ));
277
278 $this->Task->Add('Aktualizace databáze', $Commands);
279 $Output .= '<br />Úloha aktualizace serveru byla přidána do fronty.';
280 return($Output);
281 }
282
283 function Lock()
284 {
285 $this->Database->update('Server', 'Id='.$this->Id, array('Lock' => 1));
286 }
287
288 function UnLock()
289 {
290 $this->Database->update('Server', 'Id='.$this->Id, array('Lock' => 0));
291 }
292
293 function ChangeDatabaseId($Id)
294 {
295 $this->Database->update('Server', 'Id='.$this->Id, array('Database' => $Id));
296 $this->SaveConfiguration();
297 }
298
299 function GetUsedMemory()
300 {
301 $UsedMemory = 0;
302 $DbResult = $this->Database->select('Realm', 'Id', 'Server='.$this->Id);
303 while($DbRow = $DbResult->fetch_assoc())
304 {
305 $Realm = new Realm($this->System, $DbRow['Id']);
306 $UsedMemory += $Realm->GetUsedMemory();
307 }
308 return($UsedMemory);
309 }
310
311 function GetPatchList()
312 {
313 // http://us.version.worldofwarcraft.com/update/PatchSequenceFile.txt
314 $Output = array('[WoW]', 'CurrentBuild='.$this->Server['Database']['Emulator']['Client']['BuildNumber']);
315 $DbResult = $this->Database->query('SELECT * FROM Client WHERE BuildNumber <= '.$this->Server['Database']['Emulator']['Client']['BuildNumber'].' AND Patch != "" ORDER BY BuildNumber');
316 while($DbRow = $DbResult->fetch_assoc())
317 {
318 $Output[] = $DbRow['BuildNumber'].'='.$DbRow['Patch'];
319 }
320 return(implode("\n", $Output));
321 }
322
323 function RealmCount()
324 {
325 $DbResult = $this->Database->query('SELECT COUNT(*) FROM Realm WHERE Server='.$this->Id);
326 $DbRow = $DbResult->fetch_row();
327 return($DbRow[0]);
328 }
329
330 function UpdateRealmlistAccountCount()
331 {
332 $this->Database->query('TRUNCATE TABLE server'.$this->Id.'_realmd.realmcharacters');
333 $DbResult = $this->Database->select('Realm', '*', 'Server = '.$this->Id);
334 while($Realm = $DbResult->fetch_assoc())
335 {
336 $this->Database->query('INSERT INTO server'.$this->Id.'_realmd.realmcharacters (SELECT '.$Realm['Id'].' AS realmid, server'.$this->Id.'_realmd.account.id AS acctid, (SELECT COUNT(*) FROM realm'.$Realm['Id'].'_characters.characters WHERE realm'.$Realm['Id'].'_characters.characters.account = server'.$this->Id.'_realmd.account.id) AS numchars FROM server'.$this->Id.'_realmd.account)');
337 }
338 }
339}
Note: See TracBrowser for help on using the repository browser.