IPv6 in Plesk

I read a post 2 weeks ago here about a way of include ipv6 in plesk in a “persistent” way. I made exactly what the post says and it works. Now I can publish my IPv6 addresses.

Then I saw that my backups stop working with the error in /opt/psa/PMM/sessions/SOME_DATE_HOUR/migration.result:

<?xml version="1.0" encoding="UTF-8"?>
  <execution-result status="error">
    <object name="backup" type="backupowner">
      <message severity="error" code="msgtext">The dump have been invalidated by check-dump operation</message>
    </object>
    <object name="backup" type="backupowner">
      <message severity="error" code="msgtext">Runtime error: The check dump failed with code &#39;1&#39;. The dump can contain invalid data! at /opt/psa/admin/bin/plesk_agent_manager line 638.
</message>
    </object>
  </execution-result>

I found that the backup xml has a DTD and it’s validated after backup. This DTD is at /opt/psa/PMM/plesk.dtd. The patch is here:

--- plesk.dtd.old	2009-10-29 15:09:19.000000000 -0200
+++ plesk.dtd	2009-10-29 14:58:47.000000000 -0200
@@ -316,7 +316,7 @@
      dst: destination record
      opt: optional record (MX priority and PTR subnet) -->
 <!ATTLIST dnsrec
-    type (A|NS|MX|CNAME|PTR|TXT|master|SRV) #REQUIRED
+    type (A|AAAA|NS|MX|CNAME|PTR|TXT|master|SRV) #REQUIRED
     src	 CDATA                   #REQUIRED
     dst  CDATA                   #IMPLIED
     opt  CDATA                   #IMPLIED
--- plesk.xsd.old	2009-10-29 15:18:20.000000000 -0200
+++ plesk.xsd	2009-10-29 15:17:34.000000000 -0200
@@ -1818,6 +1818,7 @@
 				<xs:simpleType>
 					<xs:restriction base="xs:token">
 						<xs:enumeration value="A"/>
+						<xs:enumeration value="AAAA"/>
 						<xs:enumeration value="NS"/>
 						<xs:enumeration value="MX"/>
 						<xs:enumeration value="CNAME"/>
--- restore-specification.xsd.old	2009-10-29 15:18:27.000000000 -0200
+++ restore-specification.xsd	2009-10-29 15:18:01.000000000 -0200
@@ -1814,6 +1814,7 @@
 				<xs:simpleType>
 					<xs:restriction base="xs:token">
 						<xs:enumeration value="A"/>
+						<xs:enumeration value="AAAA"/>
 						<xs:enumeration value="NS"/>
 						<xs:enumeration value="MX"/>
 						<xs:enumeration value="CNAME"/>

I hope this helps some of you that are trying to implement ipv6 in your servers.

Shrink de ext3 com LVM

Para fazer o shrink primeiro você precisa redimensionar o filesystem(resize2fs) e depois a partição(que no caso é LVM então é só redimensionar o LVM com lvreduce).

O grande problema é que no resize2fs você precisa jogar o tamanho da partição e não da para retirar espaço com -25G por exemplo como parâmetro, e o tamanho da partição nunca é igual ao tamanho do filesystem(que no caso possui journaling, etc…).

Qual a solução então. Suponha que temos uma partição com 395Gb e você quer devolver 25G para o VG. Então fação um resize2fs menor que o tamanho que você quer, lvreduce -25G e resize2fs sem parâmetro(que ele faz o resize para o tamanho máximo alocado):

# resize2fs /dev/vg00/home 340G
# lvreduce -L -25G /dev/vg00/home
# resize2fs /dev/vg00/home

Obs. 1: A partição precisa estar desmontada

Obs. 2: MUITO, mas MUITO cuidado com estes comandos. Você pode perder TUDO o que tem no disco. Os comandos resize2fs e lvreduce não são 100% confiáveis. Eu mesmo já perdi coisa(mas eu sempre faço backup antes de rodar isto em produção).

Repositório Ubuntu Intrepid

Resolvi criar um repositório para o intrepid com alguns pacotes indisponíveis e versões novas de outros softwares que desejo manter.

Entre eles atualmente:

- nagios3 (versão 3.0.6)
- php5-eaccelerator (versão 0.9.5.3)
- fwknop-server (1.9.9)

Para ativar o repositório como root digite:


# wget http://www.wsartori.com/repository/wsartori-repository.list --output-document=/etc/apt/sources.list.d/wsartori-repository.list
# wget http://www.wsartori.com/repository/wsartori-repository.key
# apt-key add wsartori-repository.key
# apt-get update

Controlando DNS round-robin de um Blackberry/IPhone

Tive que fazer uma interface de gerenciamento de DNS round-robin para fazer um “poor high-availability”. Consiste em de um telefone celular ou de qualquer browser controlar os servidores que fazem parte de uma entrada round-robin do DNS. Utilizei python para fazer um CGI simples que faz uma consulta no servidor de DNS para ver quais servidores estão atualmente respondendo e a página abre com estes servidores pré-selecionados. Você seleciona os servidores que deverão ser utilizados para a entrada e da um atualizar e ele atualiza via dynamic update no BIND.

Read the rest of this entry »

QEMU/KVM lentidão para instalar o Debian

Estava instalando o debian etch 32bits na minha máquina ubuntu hardy 64bits aqui da Predicta. Quando começa a carregar os pacotes do cd, ele fica MUITO lento e no ALT+F4 aparece:

hda: DSC timeout

A solução é antes de apertar enter em qualquer coisa no menu depois que subir o instalador, de um ALT+F2, de enter e digite:

echo dsc_overlap:0 > /proc/ide/ide0/hda/settings

A busca do Santo Graal: Google File System open-source

Talvez você já ouviu falar do file system que o google desenvolveu. Se ainda não, você pode ver o paper que eles publicaram em http://labs.google.com/papers/gfs.html. O GoogleFS(não vou escrever GFS pois é outro file system) foi aprimorado do BigFile criado por Larry Page e Sergey Brin(co-fundadores do google) no início do google. O mais lindo de tudo o que ele pode fazer é: simplesmente ir acrescentando servidores(na realidade computadores xing-ling mesmo até) na sua rede e eles irem adicionando espaço a um file system “virtual”, sempre tendo redundância em caso de falhas e podendo lidar com work-loads altíssimos. Ele é utilizado como backend por exemplo no GMail, no serviço de buscas do google, entre muitos outros produtos do google. Vou mostrar neste artigo o que da para fazer com ferramentas open-source.


Read the rest of this entry »

Certificação ITIL

* WPG2 CANNOT LOCATE GALLERY2 ITEM ID 26719 *

Fiz o curso de ITIL do dia 10 ao dia 20 de julho. Achei o curso muito legal para aqueles que querem treinar mais o lado gerencial. Fiz a prova hoje(dia 25/07/2007) e passei com 85%. Acertei 34 questões de 40 e fui extremamente bem. Agora sou um profissional certificado ITIL. Queria agradecer primeiramente a professora Monica Keiko Korosue que deu boas dicas para a prova e também aos outros alunos que ajudaram muito dentro e fora das aulas.

Keepalived, ipvs-sync e memory leak

Tenho uma camada de load-balance com Debian, utilizando keepalived com sync de conexão do IPVS(para não perder os estados das conexões).

Acontece que a bosta do IPVS, vai lotando a tabela de conexões e parece que nunca expira as conexões TCP/IP. Já tentei alterar os timeouts do TCP/IP nos proc do linux mais NADA da resultado. Meu próximo passo é testar uns patchs malucos que tem na lista de discussão para ver se resolve. Por enquanto so dando restart. Acontece que meu tráfego só aumenta, e a freqüência dos restarts também :( . Não vou fazer testes em produção ou seja, estou esperando chegar alguns servidores, e vou acabar colocando um CentOS e configurando o Piranha(solução RedHat$$$ para o IPVS,MON,etc…) para fazer isto para mim. Vamos ver no que dá.

Abaixo o gráfico(note que quando os restarts são feitos a memória zera):
CACTI de memória do LVS1

DRBD: Desync, split-brain, como voltar

Estou enfrentando uns paus com o DRBD. Do nada ele mata o sync e fode com tudo. Meu MySQL vai para o saco, CVS para de funcionar, etc… No log mostra um split-brain error e só consigo matar o DRBD rebootando a máquina(éca, mas fazer o que?)… o que eu fiz: no drbd.conf, tem 3 linhas do arquivos de configuração em resource, net:

after-sb-0pri disconnect;
after-sb-1pri disconnect;
after-sb-2pri disconnect;

mudei para:

after-sb-0pri discard-younger-primary;
after-sb-1pri consensus;
after-sb-2pri disconnect;

segundo a documentação do DRBD:

# In case the nodes of your cluster nodes see each other again, after
# an split brain situation in which both nodes where primary
# at the same time, you have two diverged versions of your data.
#
# In case both nodes are secondary you can control DRBD's
# auto recovery strategy by the "after-sb-0pri" options. The
# default is to disconnect.
# "disconnect" ... No automatic resynchronisation, simply disconnect.
# "discard-younger-primary"
# Auto sync from the node that was primary before
# the split brain situation happened.
# "discard-older-primary"
# Auto sync from the node that became primary
# as second during the split brain situation.
# "discard-least-changes"
# Auto sync from the node that touched more
# blocks during the split brain situation.
# "discard-node-NODENAME"
# Auto sync _to_ the named node.
after-sb-0pri disconnect;

# In one of the nodes is already primary, then the auto-recovery
# strategie is controled by the "after-sb-1pri" options.
# "disconnect" ... always disconnect
# "consensus" ... discard the version of the secondary if the outcome
# of the "after-sb-0pri" algorithm would also destroy
# the current secondary's data. Otherwise disconnect.
# "discard-secondary"
# discard the version of the secondary.
# "panic-primary" Always honour the outcome of the "after-sb-0pri"
# algorithm. In case it decides the the current
# secondary has the right data, it panics the
# current primary.
# "suspend-primary" ???
after-sb-1pri disconnect;

# In case both nodes are primary you control DRBD's strategy by
# the "after-sb-2pri" option.
# "disconnect" ... Go to StandAlone mode on both sides.
# "panic" ... Honor the outcome of the "after-sb-0pri" algorithm
# and panic the other node.
after-sb-2pri disconnect;

vamos ver se da resultado. eu aviso :)

Tarifador em C++

Há algum tempo atrás, desenvolvi em C++ um tarifador simples para PABX com saída serial. Com ele, você loga em um banco mysql todas as ligações que sua central faz e recebe. Espero que gostem. Só por curiosidade ele ta rodando até hoje se problemas lá :) .


tarifador-v2.cpp

/*
Author: Wagner Sartori Junior <wsartori@uol.com.br>
Revision: $Id: tarifador-v2.cpp,v 2.0 2004/11/04 17:38:51 greg Exp greg $
GPL License Compatible
*/
 
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>
#include <getopt.h>
 
#include <termios.h>
#include <mysql++/mysql++.h>
 
using namespace std;
 
char __revision__[] = "$Id: tarifador.cpp,v 2.0 2004/11/04 17:38:51 greg Exp greg $";
 
/* Override with -f option */
#define DEFAULT_CONFIG_FILE "/etc/tarifador.conf"
/* Modify with -v/-q options */
static int VERBOSE = 0;
 
/* Default */
#define VERSAO "2.0"
 
#define _POSIX_SOURCE 1
 
#define FALSE 0
#define TRUE 1
 
volatile int STOP=FALSE;
 
static char * USAGE =
   "usage: tarifador [options]\n"
   "\n"
   "options:\n"
   "  -h, --help           this help screen\n"
   "  -d, --daemon         detach and run as a daemon process\n"
   "  -v                   increase verbosity by 1\n"
   "  -q, --quiet          run with no output\n"
   "  -fFILE, --file=FILE  read config from FILE\n"
   "                       (default: " DEFAULT_CONFIG_FILE ")\n"
   "\n"
   "-d implies -q; non-zero verbosity disables -d\n";
 
/* DataBase Variables */
char *dbserver;
char *database;
char *username;
char *password;
/* Serial Variables */
char *device;
char *baudrate;
 
static char * munge_line (char * line) {
	char * c;
 
	c = line+strlen(line)-1;
	if (*c == '\n') *c = (char) 0;
 
	c = strchr(line, '#');
	if (c != NULL) *c = (char) 0;
	else c = line + strlen(line);
 
	c--;
	while (c > line && isspace(*c)) {
		*c = (char) 0;
		c--;
	}
	c++;
	if (c == line) return NULL;
	else return line;
}
 
static void read_config(char * filename) {
	char buf[1024];
	FILE * file;
	char * param;
	char * resul;
	int i;
	int linenum;
 
	file = fopen(filename, "r");
	if (!file) {
		fprintf(stderr, USAGE);
		if (VERBOSE > 0) {
			printf("Erro abrindo arquivo de configura��o %s\n", filename);
			exit(1);
		}
	}
	linenum = 0;
 
	while (!feof(file)) {
		char * line;
 
		if (!fgets(buf, 1024, file)) {
			break;
		}
		linenum++;
 
		line = munge_line(buf);
		if (line == NULL) continue;
 
		if (VERBOSE > 1) {
			printf("valid configfile line(%d): %s\n", linenum, line);
		}
 
		param = strtok(line, "=");
		resul = strtok(NULL, "=");
 
		if (strcmp(param, "dbserver") == 0) {
			dbserver = (char *)malloc(sizeof(char *) * (strlen(resul) + 1));
			strcpy(dbserver, resul);
		} else if (strcmp(param, "database") == 0) {
			database = (char *)malloc(sizeof(char *) * (strlen(resul) + 1));
			strcpy(database, resul);
		} else if (strcmp(param, "username") == 0) {
			username = (char *)malloc(sizeof(char *) * (strlen(resul) + 1));
			strcpy(username, resul);
		} else if (strcmp(param, "password") == 0) {
			password = (char *)malloc(sizeof(char *) * (strlen(resul) + 1));
			strcpy(password, resul);
		} else if (strcmp(param, "device") == 0) {
			device = (char *)malloc(sizeof(char *) * (strlen(resul) + 1));
			strcpy(device, resul);
		} else if (strcmp(param, "baudrate") == 0) {
			baudrate = (char *)malloc(sizeof(char *) * (strlen(resul) + 1));
			strcpy(baudrate, resul);
		}
	}
	fclose(file);
}
 
static void daemonize (void) {
	pid_t pid;
 
	pid = fork();
	if (pid) {
		printf("parent process exiting\n");
		exit(0);
	} else {
		printf("child process detaching\n");
		setsid();
		chdir("/");
		close(0); open("/dev/null", O_RDONLY);
		close(1); open("/dev/null", O_WRONLY);
		close(2); open("/dev/null", O_WRONLY);
	}
}
 
MYSQL *pConnection;
 
int main (int argc, char *argv[]) {
	int fd,c, res;
	struct termios oldtio,newtio;
	char buf[255];
	string Query;
	string linha;
 
	int daemon = 0;
	char * config_file = DEFAULT_CONFIG_FILE;
 
	char * optstring = "dvqhf:";
	struct option longopts[] = {
		{ "daemon", no_argument, NULL, 'd' },
		{ "quiet", no_argument, NULL, 'q' },
		{ "help", no_argument, NULL, 'h' },
		{ "file", required_argument, NULL, 'f' },
		{ NULL, 0, NULL, 0 }
	};
	int opt;
	int longindex = 0;
	opt = getopt_long(argc, argv, optstring, longopts, &longindex);
	while (opt != -1) {
		if (opt == 'd') {
			daemon = 1;
			VERBOSE = 0;
		} else if (opt == 'v') {
			VERBOSE++;
			daemon = 0;
		} else if (opt == 'q') {
			VERBOSE = 0;
		} else if (opt == 'f') {
			config_file = strdup(optarg);
		} else if (opt == 'h' || opt == '?') {
			fprintf(stderr, USAGE);
			exit(1);
		}
		opt = getopt_long(argc, argv, optstring, longopts, &longindex);
	}
 
	read_config(config_file);
	if (VERBOSE > 0) {
		printf("Var: device=%s\n", device);
		printf("Var: baudrate=%s\n", baudrate);
		printf("Var: dbserver=%s\n", dbserver);
		printf("Var: dbserver=%s\n", database);
		printf("Var: dbserver=%s\n", username);
		printf("Var: dbserver=%s\n", password);
	}
 
	fd = open(device, O_RDONLY | O_NOCTTY );
	if (fd < 0) {
		printf("Erro na abertura do device (%s)\n", device);
		exit(1);
	}
	tcgetattr(fd,&oldtio);
	bzero(&newtio, sizeof(newtio));
 
	if (strcmp(baudrate, "2400") == 0) {
		newtio.c_cflag = B2400 | CRTSCTS | CS8 | CLOCAL | CREAD;
	} else if (strcmp(baudrate, "4800") == 0) {
		newtio.c_cflag = B4800 | CRTSCTS | CS8 | CLOCAL | CREAD;
	} else if (strcmp(baudrate, "4800") == 0) {
		newtio.c_cflag = B4800 | CRTSCTS | CS8 | CLOCAL | CREAD;
	} else if (strcmp(baudrate, "9600") == 0) {
		newtio.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
	} else if (strcmp(baudrate, "19200") == 0) {
		newtio.c_cflag = B19200 | CRTSCTS | CS8 | CLOCAL | CREAD;
	} else if (strcmp(baudrate, "38400") == 0) {
		newtio.c_cflag = B38400 | CRTSCTS | CS8 | CLOCAL | CREAD;
	} else {
		printf("Baudrate (%s) not supported.", baudrate);
		exit(1);
	}
 
	newtio.c_iflag = IGNPAR | ICRNL;
	newtio.c_oflag = 0;
	newtio.c_lflag = ICANON;
 
	tcflush(fd, TCIFLUSH);
	tcsetattr(fd,TCSANOW,&newtio);
 
	if (daemon) {
		daemonize();
		syslog(LOG_NOTICE, "Daemon started");
	}
 
	while (STOP==FALSE) {
		res = read(fd,buf,255);
		buf[res]=0;
 
		if (res > 30) {
			linha.empty();
			Query.empty();
			linha = buf;
			if (VERBOSE > 0) {
				cout<<"Linha:"<<linha<<endl;
				cout<<"Data:"<<linha.substr(0,8)<<endl;
				cout<<"Hora:"<<linha.substr(8,8)<<endl;
				cout<<"Linha:"<<linha.substr(17,1)<<endl;
				cout<<"Ramal:"<<linha.substr(21,2)<<endl;
				cout<<"Duracao:"<<linha.substr(28,8)<<endl;
				cout<<"Destino:"<<linha.substr(36,32)<<endl;
				cout<<"Tipo:"<<linha.substr(68,1)<<endl;
				cout<<"================================================"<<endl;
			}
			if (linha.substr(68,1) == "2") {
				pConnection = mysql_init(NULL);
				if(!pConnection) {
					if (daemon) syslog(LOG_ERR, "mysql_init error");
					printf("mysql_init error\n");
					exit(1);
				}
				if(mysql_real_connect(pConnection, dbserver, username, password, database,0,NULL,0) == NULL) {
					if (daemon) syslog(LOG_ERR, "mysql pConnection error");
					printf("mysql pConnection error\n");
					exit(1);
				}
				Query = "INSERT INTO pabx_ligacoes (lin_id, ram_ramal, lig_data, lig_duracao, lig_destino) VALUES ('" + linha.substr(17,1) + "', '" + linha.substr(21,2) + "', '20" + linha.substr(6,2) + "-" + linha.substr(3,2) + "-" + linha.substr(0,2)  + " " + linha.substr(8,8) + "', '" + linha.substr(28,8) + "', '" + linha.substr(36,32) + "');";
				if(mysql_query(pConnection,Query.c_str()) != 0) {
					if (daemon) syslog(LOG_ERR, "Query (%s) error\n", Query.c_str());
					printf("Query (%s) error\n", Query.c_str());
					exit(1);
				}
				mysql_close(pConnection);
			}
		}
		if (buf[0]=='z') STOP=TRUE;
	}
	tcsetattr(fd,TCSANOW,&oldtio);
 
	return 0;
}



tarifador.conf

# Configuracoes do Tarifador
# device = device serial para leitura das tarifas
# dbserver = hostname/ip do servidor de banco de dados
# database = nome do banco de dados
# username = nome do usuario para acesso ao banco de dados
# password = senha de acesso ao banco de dados
device=/dev/ttyS0
baudrate=2400
 
dbserver=server01
database=dbname
username=dbuser
password=dbpass
 
sql=INSERT INTO pabx_ligacoes (lin_id, ram_ramal, lig_data, lig_duracao, lig_destino) VALUES (?, ?, ?, ?, ?);



tarifador.sql

--
-- Estrutura da tabela `pabx_ligacoes`
-- 
 
CREATE TABLE `pabx_ligacoes` (
  `lig_id` int(11) NOT NULL AUTO_INCREMENT,
  `lin_id` int(11) NOT NULL DEFAULT '0',
  `ram_ramal` int(2) NOT NULL DEFAULT '0',
  `lig_data` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `lig_duracao` time NOT NULL DEFAULT '00:00:00',
  `lig_destino` varchar(32) NOT NULL DEFAULT '',
  PRIMARY KEY  (`lig_id`),
  KEY `lin_id` (`lin_id`),
  KEY `ram_ramal` (`ram_ramal`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Tabela de Ligacoes Telefonicas' AUTO_INCREMENT=0;
 
-- --------------------------------------------------------
 
--
-- Estrutura da tabela `pabx_linhas`
-- 
 
CREATE TABLE `pabx_linhas` (
  `lin_id` int(11) NOT NULL AUTO_INCREMENT,
  `lin_linha` int(8) NOT NULL DEFAULT '0',
  `lin_celular` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY  (`lin_id`),
  UNIQUE KEY `lin_linha` (`lin_linha`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Tabela de Linhas Telefonicas' AUTO_INCREMENT=0 ;
 
-- --------------------------------------------------------
 
--
-- Estrutura da tabela `pabx_ramais`
-- 
 
CREATE TABLE `pabx_ramais` (
  `ram_ramal` int(2) NOT NULL DEFAULT '0',
  `fun_id` int(11) DEFAULT NULL,
  PRIMARY KEY  (`ram_ramal`),
  KEY `fun_id` (`fun_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Tabela de Ramais Telefonicos';
 
--
-- Constraints for table `pabx_ligacoes`
--
--ALTER TABLE `pabx_ligacoes`
--  ADD CONSTRAINT `pabx_ligacoes_ibfk_1` FOREIGN KEY (`lin_id`) REFERENCES `pabx_linhas` (`lin_id`),
--  ADD CONSTRAINT `pabx_ligacoes_ibfk_2` FOREIGN KEY (`ram_ramal`) REFERENCES `pabx_ramais` (`ram_ramal`);
 
--
-- Constraints for table `pabx_ramais`
--
--ALTER TABLE `pabx_ramais`
--  ADD CONSTRAINT `pabx_ramais_ibfk_1` FOREIGN KEY (`fun_id`) REFERENCES `funcionarios` (`fun_id`);

Get Adobe Flash playerPlugin by wpburn.com wordpress themes
multifarious