m_lxc.php 5.58 KB
Newer Older
1
2
<?php

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/* 
 ----------------------------------------------------------------------
 AlternC - Web Hosting System
 Copyright (C) 2000-2013 by the AlternC Development Team.
 https://alternc.org/
 ----------------------------------------------------------------------
 LICENSE

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License (GPL)
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 To read the license please visit http://www.gnu.org/copyleft/gpl.html
 ----------------------------------------------------------------------
 Purpose of file: Manage LXC-based virtual machine through an inetd-based protocol
 ----------------------------------------------------------------------
*/

François Serman's avatar
François Serman committed
27
include_once(dirname(__FILE__) . '/vm.class.php');
28

29
30
31
32
33
34
35

/**
 * Manage AlternC's virtual machine start/stop using our own inetd-based protocol.
 */
class m_lxc implements vm {


36
37
38
39
40
  public $IP;
  public $PORT;
  public $TIMEOUT = 5;
  public $error = array();

41
42
43
44

  /** 
   * Constructor, initialize the class informations from AlternC's variables
   */
45
  function m_lxc() {
Alan Garcia's avatar
Alan Garcia committed
46
47
48
49
    $this->IP   = variable_get('lxc_ip', '', "IP address of the Alternc's LXC server. If empty, no LXC server.", array(array('desc'=>'IP address','type'=>'ip')));
    $this->PORT = variable_get('lxc_port', '6504', "Port of the Alternc's LXC server", array(array('desc'=>'Port','type'=>'integer')));
    $this->KEY  = variable_get('lxc_key', '', "Shared key with the Alternc's LXC server", array(array('desc'=>'Shared key','type'=>'string')));
    $this->maxtime = variable_get('lxc_maxtime', '4', "How many hours do we allow to have a server before shutting it down", array(array('desc'=>'Max time','type'=>'integer')));
50
51
52
  }


53
54
55
  /**
   * HOOK: add the "Console Access" to AlternC's main menu
   */
56
  function hook_menu() {
57
    if ( empty($this->IP)) return ; // No menu if no server
58
59

    $obj = array(
60
      'title'       => _("Console access"),
61
62
63
64
65
66
67
68
      'ico'         => 'images/ssh.png',
      'link'        => 'vm.php',
      'pos'         => 95,
     ) ;

     return $obj;
  }

69
70
71
72

  /**
   * HOOK: remove VM history for AlternC account
   */
73
74
75
76
77
78
79
  function hook_admin_del_member() {
    global $db,$err,$cuid;
    $err->log("lxc","alternc_del_member");
    $db->query("DELETE FROM vm_history WHERE uid='$cuid'");
    return true;
  }

80

81
82
83
84
85
86
87
  /** 
   * Send a message to a remote VM manager instance
   * $params are the parameters to send as serialized data
   * to the listening server. 
   * Return the unserialized response data, if the message has been sent successfully
   * or FALSE if an error occurred. In that case $error[] is set.
   */
Alan Garcia's avatar
Alan Garcia committed
88
  private function sendMessage($params) {
89
    global $L_FQDN,$hooks;
Alan Garcia's avatar
Alan Garcia committed
90
    $fp = @fsockopen($this->IP, $this->PORT, $errno, $errstr, $this->TIMEOUT);
91
    if (!$fp) {
Alan Garcia's avatar
Alan Garcia committed
92
93
94
      $this->error[] = 'Unable to connect';
      return FALSE;
    }
95
96
97
    // Authenticate:
    $params['server']=$L_FQDN;
    $params['key']=$this->KEY;
98
99
100
101
102
103
    // MySQL Host for this user ? 
    $moreparams=$hooks->invoke("lxc_params",array($params));
    foreach($moreparams as $p) {
      foreach($p as $k=>$v) 
	$params[$k]=$v;
    }
Alan Garcia's avatar
Alan Garcia committed
104

105
106
    $msg = serialize($params);
    if (fwrite ($fp, $msg."\n") < 0) {
Alan Garcia's avatar
Alan Garcia committed
107
108
109
110
      $this->error[] = 'Unable to send data';
      return FALSE;
    }
    $resp = '';
111
    $resp = fgets($fp, 8192);
Alan Garcia's avatar
Alan Garcia committed
112
113
    fclose ($fp);

114
    $data = @unserialize($resp);
Alan Garcia's avatar
Alan Garcia committed
115
  
116
    if (isset($data['error']) && $data['error']>0) {
Alan Garcia's avatar
Alan Garcia committed
117
118
      $this->error[] = $data['msg'];
      return FALSE;
119
    } else {
Alan Garcia's avatar
Alan Garcia committed
120
121
122
123
      return $resp;
    }
  }

124
125
126
127
128
129

  /** 
   * START a Virtual Machine on the remote VM manager
   * for user $login having hashed password $pass and uid $uid
   */
  public function start($login = FALSE, $pass = FALSE, $uid = FALSE) {
Alan Garcia's avatar
Alan Garcia committed
130
131
    global $mem, $db, $err, $mysql;

132
    if ($this->getvm() !== FALSE) {
Alan Garcia's avatar
Alan Garcia committed
133
134
135
      $err->raise('lxc', _('VM already started'));
      return FALSE;
    }
Benjamin Sonntag's avatar
Benjamin Sonntag committed
136
    unset($this->error);
Alan Garcia's avatar
Alan Garcia committed
137
138
139
140
141
142
143
144
145

    $login = $login ? $login : $mem->user['login'];
    $pass  = $pass  ? $pass  : $mem->user['pass'];
    $uid   = $uid   ? $uid   : $mem->user['uid'];

    $msgg = array('action'=>'start', 'login'=>$login, 'pass' => $pass, 'uid'=> $uid);  
    $msgg['mysql_host'] = $mysql->dbus->Host;

    $res = $this->sendMessage($msgg);
146
    if ($res === FALSE) {
Alan Garcia's avatar
Alan Garcia committed
147
      return $this->error;
148
    } else {
Alan Garcia's avatar
Alan Garcia committed
149
150
151
152
153
154
155
      $data = unserialize($res);
      $error = $data['error'];
      $hostname = $data['hostname'];
      $msg = $data['msg'];
      $date_start = 'NOW()';
      $uid = $mem->user['uid'];

156
      if ((int)$data['error'] != 0) {
Alan Garcia's avatar
Alan Garcia committed
157
158
159
160
161
162
163
164
165
        $err->raise('lxc', _($data['msg']));
        return FALSE;
      }
      $db->query("INSERT INTO vm_history (ip,date_start,uid,serialized_object) VALUES ('$hostname', $date_start, '$uid', '$res')");
      return $res;
    }
  }


166
167
168
169
  /**
   * 
   */
  public function getvm($login = FALSE) {
Alan Garcia's avatar
Alan Garcia committed
170
    global $db, $mem, $cuid;
Alan Garcia's avatar
Alan Garcia committed
171

172
173
174
175
176
    $login = $login ? $login : $mem->user['login'];
    $msgg = array('action'=>'get', 'login'=>$login);  
    $res = $this->sendMessage($msgg);
    if (!$res) return FALSE;
    return unserialize($res);
Alan Garcia's avatar
Alan Garcia committed
177
178
  }

Alan Garcia's avatar
Alan Garcia committed
179

180
181
182
183
  /** 
   * Stop the currently running VM
   */
  public function stop() {
Alan Garcia's avatar
Alan Garcia committed
184
185
186
187
188
    global $db, $mem;
    $vm = $this->getvm();
    if ($vm === FALSE)
      return FALSE;

189
190
191
    if ($this->sendMessage(array('action' => 'stop', 'vm' => $vm['vm'])) === FALSE)
      return FALSE;
    return TRUE;
Alan Garcia's avatar
Alan Garcia committed
192
  }
193
194
195
196



} // class m_lxc