Project

General

Profile

Download (8.28 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("config.inc");
35

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

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

    
53
class TCPMonitor extends Monitor {
54
	protected $proto = 'tcp';
55
}
56

    
57
class SSLMonitor extends Monitor {
58
	protected $proto = 'ssl';
59
}
60

    
61
class ICMPMonitor extends Monitor {
62
	protected $proto = 'icmp';
63
}
64

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

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

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

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

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

    
92
class HTTPSMonitor extends HTTPMonitor {
93
	protected $proto = 'https';
94
}
95

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

    
105

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

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

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

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

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

    
158
function relayd_configure() {
159
  global $config, $g;
160

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

    
165
  $check_a = array();
166

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

    
193

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

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

    
232
          # sitedown MUST use the same port as the primary pool - sucks, but it's a relayd thing
233
          if (isset($vs_a[$i]['sitedown']) &&  $vs_a[$i]['sitedown'] != "")
234
            $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";
235
          $conf .= "}\n";
236
          break;
237
        }
238
        case 'relay': {
239
          $conf .= "relay \"{$vs_a[$i]['name']}\" {\n";
240
          $conf .= "  listen on {$vs_a[$i]['ipaddr']} port {$vs_a[$i]['port']}\n";
241
          $conf .= "  protocol \"{$vs_a[$i]['relay_protocol']}\"\n";
242
          $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";
243

    
244
          if (isset($vs_a[$i]['sitedown']) &&  $vs_a[$i]['sitedown'] != "")
245
            $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";
246
          $conf .= "}\n";
247
          break;
248
        }
249
      }
250
    }
251
  }
252
  fwrite($fd, $conf);
253
  fclose($fd);
254

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

    
268
?>
(37-37/41)