Linux Quimper

Un serveur pour les futures installs party


(Fanch) #1

Bonjour à vous,

Certains le savaient déjà, Linux Quimper utilise un serveur pour ses installs-party pour faciliter les installs, mises à jours et téléchargements.

Ce serveur devrait prendre en charge :
- Un cache web et http pour les gros téléchargements en toute transparance avec Squid
- L’installation d’Ubuntu par le réseau exclusivement grace à PXE
- Les dépots courants (ubuntu, debian, slitaz et archlinux) en toute transparance afin d’alléger le trafic internet
- Un connexion gigabit
- La distribution d’ip de 10.9.0.50 à 10.9.3.254 et la résolution locale des noms en .lq
- L’accès au serveur où qu’il soit par tunnel SSH
- Un enregistrement par webcam de l’install sur toute la journée
- Un espace de stockage (web et samba) pour les dépots et distributions à télécharger mis à jour juste avant l’install.

Page du projet : http://www.linuxquimper.org/wiki/doku.php?id=serveur_install_party (La listes des lives s’y trouve)

Fanch

[édit par piero : wiki]


(Fanch) #2

Le dépot local

J’ai actuelement le depot de Feisty, et toute demande des depots ubuntu est redirigée sur le depot du serveur (où il n’y a que feisty). Vous l’aurez compris, mon souci est pour les autres distribution, car un depot contient plusieurs distribution (dapper, edgy…).

Comment faire en sorte que le poste client soit redirigé sur le dépot internet ubuntu lorsque les fichiers ne sont pas sur le serveur local ?

PS; Actuelement, j’utilise juste bind pour rediriger les client (qui demandent archive.ubuntu.com) vers l’ip local du serveur. Le depot local est accessible en http comme en ftp.

A vos idées :slight_smile:

Fanch


(Fanch) #3

Bon, il semblerait qu’une solution de base ai été trouvée.

Il s’agit d’utiliser un proxy pour apt (apt-proxy) en plus de apt-mirror , en effet les deux systèmes utilisent une arboresence identique aux depots.

Il me reste plus qu’a utiliser ce proxy de façon transparente uniquement pour les adresses des dépots. (peut-être avec shorewall)

Fanch


(vincent) #4

Tiens, c’est ingénieux ça. On va voir si ça fonctionne bien :D.


(Fanch) #5

Non ça fonctionne pas AddiKt1ve !! :smiley:

Mais qu’est ce que je m’amuse !! :confused:

J’ai décidé de passer le systeme ( / ) en raid 5 sur des partitions des 500Go. (Au lieu d’utiliser 2 disques 4Go supplemantaires).
Mais maintenant je parviens plus à installer le systeme d’amorce (grub ou lilo)… :confused:

A suivre… :wink:

Fanch


(infothema) #6

Salut Fanch,

Souhaitant également monter un serveur de dépots pour Ubuntu, pourrais-tu m’indiquer la syntaxe de cette belle commande de rapatriment :slight_smile:


(Fanch) #7

Bonjour infothema,

En realité j’utilise pluieurs chose pour le dépot local qui sert aux installs party :

[b]1) APT-MIRROR

  • apt-mirror pour récuperer toute l’arborecence d’un dépot (ou presque)
  • Un modification du script apt-miror pour recuperer certains fichiers supplémentaires

Avec ce programme, on a les dépots souhaités.[/b]

  1. SQUID
  • Ce proxy va permetre de capter le flux http pour le cache en autre mais aussi pour pouvoir utiliser jesred
  1. JESRED
  • Ce script va permettre de rediriger suivant l’url, la requete squid vers un script php (comme de l’url rewritting)
  1. Script php http://127.0.0.1/repository.php
  • Ce script maison va retourner le fichier local ou distant suivant sa disponnibilité et sa date
  1. Redirection grace à iptable de toutes les requetes http vers squid.

(staif) #8

Y’a pas à dire Fanch, t’es mon dieu !!! :slight_smile:


(irimi) #9

Super initiative ! J’ai hâte de voir ça en action, ça doit dégommer sec les install en gigabit !


(vincent) #10

Bah il était en place à Landrévarzec ; mais en wifi le débit ne dépassait pas les 2Mo/s très peu stables (j’étais plutôt à 17ko/s la plupart du temps ; serveur saturé ?).

Sinon Fanch, tu peux mettre à disposition le script pour infothema :slight_smile: ?


(infothema) #11

Merci AddiKT1ve de relancer sur le script :wink: … c’est le genre de truc hyper utile


(Fanch) #12

Qui vous fait croire que c’est open source ? :stuck_out_tongue:

[code]<?
/******************************************************

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License 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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


APT-PROXY-FANCH (LINUXQUIMPER)
Le 21/11/2007
Par Fanch pour LinuxQuimper.org

Ce script est à appeler ainsi :
http://127.0.0.1/repository.php/?http://archive.ubuntu.com/ubuntu/dists/gutsy/Contents-i386.gz
ou
http://127.0.0.1/repository.php/?archive.ubuntu.com/ubuntu/dists/gutsy/Contents-i386.gz

******************************************************/

/******************************************************

Variables de configuration

******************************************************/
$start_script = time();
$numberaleatoire = rand(0,99);
$i=1;
$repositories[$i] = Array(
“name” => “Depot Ubuntu”,
“url” => “http://archive.ubuntu.com/”, //Ne pas oublier le / à la fin
“path” => “/mnt/storage-secure/repositories/mirror/archive.ubuntu.com/”, //Ne pas oublier le / à la fin
“active” => true
);
$i++;

$config = Array(
“sendRemoteAlways” => false,
“sendLocalAlways” => false,
“checkRemotly” => true, //Verifier le fichier distant
“checkRemoteIfLocalAge” => 0, //Age du fichier local maximum avant vérification distante
“checkLocal” => true //Verifier le fichier local
);

define(“DEBUG_ON”, false);
define(“FILE_DEBUG”, “/var/log/proxyaptfanch.log”);
register_shutdown_function (“shutdown_script”);

/*******************************************************
Recuperation de l’url
*/
$urlInput = $_ENV[“QUERY_STRING”];
if(substr($urlInput,0,7) != “http://”)
$urlInput = “http://”.$urlInput;
$urlInput = parseUrl($urlInput);
/
/

logg("###> “.date(“d-m-Y H:i:s”).”<### Demande de l’url ".$urlInput[“url”]);

//Recuperation de l’id du repository
$idRepo = findRepository($urlInput[“url”]);
logg(“Repository correspondant trouvé : “.$idRepo.” (”.$repositories[$idRepo][“name”].")" );

//Recuperation des info locales
if($config[“checkLocal”]){
$infoFileLocal = getInfoFileLocal();
logg(“Récuperation des information du fichier local (time:”.date(“d-m-Y H:i:s”,$infoFileLocal[‘time’])." “.$infoFileLocal[‘time’].” size:".$infoFileLocal[‘size’]." type:".$infoFileLocal[‘type’].")");
}
//Recuperation des info distants
if($config[“checkRemotly”]){
$infoFileDistant = getInfoFileDistant();
logg(“Récuperation des information du fichier distant (time:”.date(“d-m-Y H:i:s”,$infoFileDistant[‘time’])." “.$infoFileDistant[‘time’].” size:".$infoFileDistant[‘size’]." type:".$infoFileDistant[‘type’].")");
}

//Toujours envoyer le fichier distant ?
if($config[“sendRemoteAlways”]){
streamFileDistant();

//Toujours envoyer le fichier local ?
}elseif($config[“sendLocalAlways”]){
streamFileLocal();

//Rien trouvé
}elseif((empty($infoFileLocal[“time”]) && empty($infoFileDistant[“time”]))){
logg("!!! 404 Fichier introuvable distant et local !!!");
header(“HTTP/1.0 404 Not Found”);

//Repertoire ou fichier texte
}elseif(is_dir($repositories[$idRepo][“path”].$urlInput[‘filepath’]) || $infoFileDistant[‘size’]==0 ||$infoFileDistant[‘time’]==-1 || $infoFileDistant[“type”] == “text/html; charset=UTF-8”){
streamWebUrl();

//Fichier distant plus recent
}elseif( (time()-$infoFileLocal[“time”]) > $config[“checkRemoteIfLocalAge”] && $infoFileDistant[“time”] > $infoFileLocal[“time”]){
streamFileDistant();

//Sinon envoyer fichier local
}else{
streamFileLocal();
}
logg(date(“d-m-Y H:i:s”)." ------ Fin d’envoi");
exit;

function streamWebUrl(){
global $urlInput;
logg(date(“d-m-Y H:i:s”)." ------ Debut de l’envoi du flux URL (".$urlInput[“url”].")");
readfile($urlInput[“url”]);
}

function streamFileLocal(){
global $urlInput,$repositories,$infoFileLocal,$idRepo;
if(empty($idRepo))
$idRepo=findRepository($urlInput[“url”]);
if(empty($idRepo))
return false; //Interdit, ce fichier n’est pas le mirroir
if(empty($infoFileLocal))
$infoFileLocal=getInfoFileLocal($urlInput[‘filepath’],$idRepo);
logg(date(“d-m-Y H:i:s”)." ------ Debut de l’envoi du fichier local (".$repositories[$idRepo][“path”].$urlInput[‘filepath’].")");
header(“Content-Type: “.$infoFileLocal[‘type’].”\n” );
header(‘Content-Description: File Transfer’);
header(‘Content-Length: ‘. $infoFileLocal[‘size’]);
header(‘Content-Disposition: attachment; filename="’.$urlInput[‘file’].’"’);
header(‘Pragma: no-cache’);
header(‘Expires: 0’);

readfile($repositories[$idRepo]["path"].$urlInput['filepath']);

}

function streamFileDistant(){
global $urlInput,$repositories,$infoFileDistant,$idRepo;
if(empty($idRepo))
$idRepo=findRepository($urlInput[“url”]);
if(empty($infoFileDistant))
$infoFileDistant=getInfoFileDistant($urlInput[“url”],$idRepo);

logg(date("d-m-Y H:i:s")." ------ Debut de l'envoi du fichier distant (".$urlInput["url"].")");
header("Content-Type: ".$infoFileDistant['type']."\\n" );
header('Content-Description: File Transfer');
header('Content-Length: '. $infoFileDistant['size']);
header( "Content-Disposition: attachment; filename='".$urlInput['file']."'" ); 
header('Pragma: no-cache'); 
header('Expires: 0');

readfile($urlInput["url"]);

}

function getInfoFileDistant(){
global $urlInput,$repositories,$idRepo;
if(empty($idRepo))
$idRepo=findRepository($urlInput[“url”]);
$repo = $repositories[$idRepo];
$ch = curl_init(); // create cURL handle (ch)
if (!$ch) {
die(“Couldn’t initialize a cURL handle”);
}
// set some cURL options
curl_setopt($ch, CURLOPT_URL, $urlInput[“url”]);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_FILETIME, true);
curl_setopt($ch, CURLOPT_NOBODY, TRUE);
// execute
curl_exec($ch);

$curl_return = curl_getinfo($ch);
if($curl_return['http_code']==200){
	//Le fichier existe
	$ret['path'] = $urlInput["url"];
	$ret['time'] = $curl_return['filetime'];
	$ret['type'] = $curl_return['content_type'];
	$ret['size'] = $curl_return['download_content_length'];

	return $ret;
}else{
	return $curl_return['http_code'];
}

}

function getInfoFileLocal(){
global $urlInput,$repositories,$idRepo;
if(empty($idRepo))
$idRepo=findRepository($urlInput[“url”]);

$pathFile = $repositories[$idRepo]["path"].str_replace($repositories[$idRepo]["url"],"",$urlInput["url"]);
if(file_exists($pathFile) && !is_dir($pathFile)){
	//Le fichier existe
	$ret['path'] = $pathFile;
	$ret['time'] = filemtime($pathFile);
	$ret['type'] = mime_content_type($pathFile);
	$ret['size'] = filesize($pathFile);
	return $ret;
}else{
	return false;
}

}

function findRepository($url){
global $repositories;
if(!empty($repositories)){
foreach($repositories as $idRepo => $repo){
if(preg_match("|^".$repo[“url”]."|",$url))
return $idRepo;
}
}
return false;
}

function parseUrl($url){
if(!preg_match(’|^http://.+$|’, $url))
return false;
preg_match(’|^((http://)?([^/]+))/((.)/)?(([^\.]+)(\.([^\.]+(\.[^\.]+)))?)$|’, $url, $matches);
$ret[‘url’] = $matches[0];
$ret[‘server’] = $matches[3];
$ret[‘urlserver’] = $matches[1];
$ret[‘folder’] = $matches[5];
$ret[‘file’] = $matches[6];
$ret[‘filepath’] = $matches[4].$matches[6];
$ret[‘filename’] = $matches[7];
$ret[‘ext’] = $matches[9];
return $ret;
}
function shutdown_script(){
$statut = connection_status();

if($statut==2){
	logg(date("d-m-Y H:i:s")." ------ Timeout liaison perdu entre le demandeur et ce script");
}elseif($statut==1){
	logg(date("d-m-Y H:i:s")." ------ Arret volontaire par l'utilisateur demandeur");
}elseif($statut==0){

}

}

function logg($texte){
global $start_script,$numberaleatoire;
if(!empty($_ENV[‘HTTP_X_FORWARDED_FOR’]))
$ip = $_ENV[‘HTTP_X_FORWARDED_FOR’];
else
$ip = $_ENV[‘REMOTE_ADDR’];
$flog = fopen(FILE_DEBUG,“a”); //concatene au fichier
$rc = fputs($flog,"[".$ip.".".$numberaleatoire."] “.$texte.”
");
$rc = fclose($flog);
if(DEBUG_ON)
echo $texte;
}

?>[/code]
C’est libre ! Faites en ce que vous voulez :wink:
Fanch


(irimi) #13

Du coup mets le code en GPL ! Au moins ce script sera libre et le restera !

Comment faire :

http://www.gnu.org/licenses/gpl-howto.fr.html

En gros, tu dois mettre au tout début du commentaire un texte de Copyright (eh oui !), que tu fais suivre d’un truc du genre :

[code] This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License 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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA[/code]

Tu peux mettre le lien officiel vers la GPL :

http://www.gnu.org/licenses/gpl.txt

ça permet aux gens de savoir à quoi ils s’engagent en utilisant/modifiant/échangeant le script.

Dans le cas d’un programme compilé, il faut obligatoirement adjoindre le code source aux binaires, ou au moins l’URL où on peut trouver ce code source. C’est obligatoire.

Luxe : lorsque le script démarre, mettre un texte indiquant qu’il est en GNU GPL (ou au moins “free software”).

On prône le libre, autant faire les choses dans les règles de l’art :wink:


(Fanch) #14

Merci Irimi pour l’info !

Voila une bonne chose de faite. :wink:


(Fanch) #15

Mise à zero du serveur suite au nouveau materiel généreusement offert par René et Piero.

  1. Le serveur propose en PXE le live d’ubuntu Intrepid et permet son installation
  2. Le serveur met en cache le trafic internet (jusqu’a 800Mo par fichiers)

A suivre.

Fanch


(vincent) #16

Manque plus que les dépôts locaux :)…


(saitMoh) #17

Est-ce que le serveur a suffisamment de port USB pour brancher un disque externe ? Si oui, on pourrait y brancher mon disque qui contient un miroir de Debian (i386/amd64) et rediriger ftp.*.debian.org sur le dépôt local mais en désactivant le script qui vérifie le serveur distant. Mon miroir est mis à jour à 04h30 tous les jours et comme je ne prends pas security.debian.org, les paquets ne sont pas troués.

PS: Il serait bien que ceux utilisent/(veulent installer) d’autres distribution viennent avec un miroir de celles-ci ou suffisamment de DVD pour faire l’installation sans réseau.


(vincent) #18

J’ai ça pour ArchLinux, mais il n’est ni complet, ni à jour. Faudrait que je relance le truc :).


(Fanch) #19

Donc pour squid, la methode reste simple enfin je crois.
On redirige toutes les URL demandées par squid vers un script php (ou python ou…)

Ce dernier recoit en entrée l’url demandé
Il en revoit en retour à squid, la nouvelle URL en fonction de la présence local (et/ou distante)

L’utilisation de caches USB sera tout à fait possible en préparant au préalable le script de reecriture/redirection d’URL squid

A suivre.


(vincent) #20

Plop Fanch.

Si tu trouves le temps, tu pourrais nous poster les divers fichiers de conf. utiles au serveur ? On en a récupéré un qui pourrait faire office de serveur de secours au cas où tu ne puisses pas te déplacer lors d’une install :).