Project

General

Profile

Download (8.34 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
  vslb.inc
5
  Copyright (C) 2005-2008 Bill Marquette
6
  All rights reserved.
7

    
8
  Redistribution and use in source and binary forms, with or without
9
  modification, are permitted provided that the following conditions are met:
10

    
11
  1. Redistributions of source code must retain the above copyright notice,
12
  this list of conditions and the following disclaimer.
13

    
14
  2. Redistributions in binary form must reproduce the above copyright
15
  notice, this list of conditions and the following disclaimer in the
16
  documentation and/or other materials provided with the distribution.
17

    
18
  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19
  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
  AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
22
  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
  POSSIBILITY OF SUCH DAMAGE.
28

    
29
 */
30

    
31
/* DISABLE_PHP_LINT_CHECKING */
32

    
33
/* include all configuration functions */
34
require_once("functions.inc");
35
require_once("pkg-utils.inc");
36
require_once("notices.inc");
37

    
38
class Monitor {
39
	private $conf = array();
40
	function __construct($config) {
41
		$this->conf = $config;
42
	}
43

    
44
	public function p() {
45
		return "check {$this->get('proto')}";
46
	}
47
	private function get($var) {
48
		return isset($this->$var) ? $this->$var : "";
49
	}
50
	protected function config($element) {
51
		return isset($this->conf[$element]) ? $this->conf[$element] : "";
52
	}
53
}
54

    
55
class TCPMonitor extends Monitor {
56
	protected $proto = 'tcp';
57
}
58

    
59
class SSLMonitor extends Monitor {
60
	protected $proto = 'ssl';
61
}
62

    
63
class ICMPMonitor extends Monitor {
64
	protected $proto = 'icmp';
65
}
66

    
67
class HTTPMonitor extends Monitor {
68
	protected $proto = 'http';
69
	function __construct($config) {
70
		parent::__construct($config);
71
	}
72
	public function p() {
73
		$method = ($this->code() != "") ? $this->code() : $this->digest();
74
		return "check {$this->proto} {$this->path()} {$this->host()} {$method}";
75
	}
76

    
77
	private function path() {
78
		return $this->config('path') != "" ? "'{$this->config('path')}'" : "";
79
	}
80

    
81
	private function host() {
82
		return $this->config('host') != "" ? "host {$this->config('host')}" : "";
83
	}
84

    
85
	private function code() {
86
		return $this->config('code') != "" ? "code {$this->config('code')}" : "";
87
	}
88

    
89
	private function digest() {
90
		return $this->config('digest') != "" ? "digest {$this->config('digest')}" : "";
91
	}
92
}
93

    
94
class HTTPSMonitor extends HTTPMonitor {
95
	protected $proto = 'https';
96
}
97

    
98
class SendMonitor extends Monitor {
99
	private $proto = 'send';
100
	function __construct($config) {
101
		parent::__construct($config);
102
	}
103
	public function p() {
104
		return "check {$this->proto} {$this->data()} expect {$this->pattern()} {$this->ssl()}";
105
	}
106

    
107

    
108
	private function data() {
109
		return $this->config('send') != "" ? "{$this->config('send')}" : "";
110
	}
111

    
112
	private function pattern() {
113
		return $this->config('expect') != "" ? "{$this->config('expect')}" : "";
114
	}
115

    
116
	private function ssl() {
117
		return $this->config('ssl') == true ? "ssl" : "";
118
	}
119
}
120

    
121
function echo_lbaction($action) {
122
  global $config;
123
  
124
  // Index actions by name
125
  $actions_a = array();
126
  for ($i=0; isset($config['load_balancer']['lbaction'][$i]); $i++)
127
		$actions_a[$config['load_balancer']['lbaction'][$i]['name']] = $config['load_balancer']['lbaction'][$i];
128

    
129
  $ret = "";
130
  $ret .=  "{$actions_a[$action]['direction']} {$actions_a[$action]['type']} {$actions_a[$action]['action']}";
131
  switch($actions_a[$action]['action']) {
132
    case 'append': {
133
      $ret .= " \"{$actions_a[$action]['options']['value']}\" to \"{$actions_a[$action]['options']['akey']}\"";
134
      break;
135
    }
136
    case 'change': {
137
      $ret .= " \"{$actions_a[$action]['options']['akey']}\" to \"{$actions_a[$action]['options']['value']}\"";
138
      break;
139
    }
140
    case 'expect': {
141
      $ret .= " \"{$actions_a[$action]['options']['value']}\" from \"{$actions_a[$action]['options']['akey']}\"";
142
      break;
143
    }
144
    case 'filter': {
145
      $ret .= " \"{$actions_a[$action]['options']['value']}\" from \"{$actions_a[$action]['options']['akey']}\"";
146
      break;
147
    }
148
    case 'hash': {
149
      $ret .= " \"{$actions_a[$action]['options']['akey']}\"";
150
      break;
151
    }
152
    case 'log': {
153
      $ret .= " \"{$actions_a[$action]['options']['akey']}\"";
154
      break;
155
    }
156
  }
157
  return $ret;
158
}
159

    
160
function relayd_configure() {
161
  global $config, $g;
162

    
163
  $vs_a = $config['load_balancer']['virtual_server'];
164
  $pool_a = $config['load_balancer']['lbpool'];
165
  $protocol_a = $config['load_balancer']['lbprotocol'];
166

    
167
  $check_a = array();
168

    
169
  foreach ((array)$config['load_balancer']['monitor_type'] as $type) {
170
    switch($type['type']) {
171
      case 'icmp': {
172
        $mon = new ICMPMonitor($type['options']);
173
	break;
174
      }
175
      case 'tcp': {
176
        $mon = new TCPMonitor($type['options']);
177
	break;
178
      }
179
      case 'http': {
180
        $mon = new HTTPMonitor($type['options']);
181
	break;
182
      }
183
      case 'https': {
184
        $mon = new HTTPSMonitor($type['options']);
185
	break;
186
      }
187
      case 'send': {
188
        $mon = new SendMonitor($type['options']);
189
	break;
190
      }
191
    }
192
    $check_a[$type['name']] = $mon->p();
193
  }
194

    
195

    
196
  $fd = fopen("{$g['varetc_path']}/relayd.conf", "w");
197

    
198
  /* reindex pools by name as we loop through the pools array */
199
  $pools = array();
200
  /* Virtual server pools */
201
  if(is_array($pool_a)) {
202
    for ($i = 0; isset($pool_a[$i]); $i++) {
203
      if(is_array($pool_a[$i]['servers'])) {
204
        $srvtxt = implode(", ", $pool_a[$i]['servers']);
205
        $conf .= "table <{$pool_a[$i]['name']}> { $srvtxt }\n";
206
        /* Index by name for easier fetching when we loop through the virtual servers */
207
        $pools[$pool_a[$i]['name']] = $pool_a[$i];
208
      }
209
    }
210
  }
211
  if(is_array($protocol_a)) {
212
    for ($i = 0; isset($protocol_a[$i]); $i++) {
213
      $proto = "{$protocol_a[$i]['type']} protocol \"{$protocol_a[$i]['name']}\" {\n";
214
      if(is_array($protocol_a[$i]['lbaction'])) {
215
        if($protocol_a[$i]['lbaction'][0] == "") {
216
          continue;
217
        }
218
        for ($a = 0; isset($protocol_a[$i]['lbaction'][$a]); $a++) {
219
          $proto .= "  " . echo_lbaction($protocol_a[$i]['lbaction'][$a]) . "\n";
220
        }
221
      }
222
      $proto .= "}\n";
223
      $conf .= $proto;
224
    }
225
  }
226
  if(is_array($vs_a)) {
227
    for ($i = 0; isset($vs_a[$i]); $i++) {
228
      switch($vs_a[$i]['mode']) {
229
        case 'redirect': {
230
          $conf .= "redirect \"{$vs_a[$i]['name']}\" {\n";
231
          $conf .= "  listen on {$vs_a[$i]['ipaddr']} port {$vs_a[$i]['port']}\n";
232
          $conf .= "  forward to <{$vs_a[$i]['pool']}> port {$pools[$vs_a[$i]['pool']]['port']} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} timeout 1000\n";
233

    
234
          # sitedown MUST use the same port as the primary pool - sucks, but it's a relayd thing
235
          if (isset($vs_a[$i]['sitedown']) &&  $vs_a[$i]['sitedown'] != "")
236
            $conf .= "  forward to <{$vs_a[$i]['sitedown']}> port {$pools[$vs_a[$i]['pool']]['port']} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} timeout 1000\n";
237
          $conf .= "}\n";
238
          break;
239
        }
240
        case 'relay': {
241
          $conf .= "relay \"{$vs_a[$i]['name']}\" {\n";
242
          $conf .= "  listen on {$vs_a[$i]['ipaddr']} port {$vs_a[$i]['port']}\n";
243
          $conf .= "  protocol \"{$vs_a[$i]['relay_protocol']}\"\n";
244
          $conf .= "  forward to <{$vs_a[$i]['pool']}> port {$pools[$vs_a[$i]['pool']]['port']} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} timeout 1000\n";
245

    
246
          if (isset($vs_a[$i]['sitedown']) &&  $vs_a[$i]['sitedown'] != "")
247
            $conf .= "  forward to <{$vs_a[$i]['sitedown']}> port {$pools[$vs_a[$i]['pool']]['port']} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} timeout 1000\n";
248
          $conf .= "}\n";
249
          break;
250
        }
251
      }
252
    }
253
  }
254
  fwrite($fd, $conf);
255
  fclose($fd);
256

    
257
  if (is_process_running('relayd: parent')) {
258
    /*
259
     * XXX: Something breaks our control connection with relayd and makes relayctl stop working
260
     * rule reloads are the current suspect
261
     * mwexec('/usr/local/bin/relayctl stop');
262
     */
263
     mwexec('pkill relayd');
264
  }
265
  if (! empty($vs_a)) {
266
    mwexec("/usr/local/sbin/relayd -f {$g['varetc_path']}/relayd.conf");
267
  }
268
}
269

    
270
?>
(35-35/39)