Gestion de l’horloge Linux

 Trucs et astuces techniques  Commentaires fermés sur Gestion de l’horloge Linux
Sep 272012
 

Il y a deux horloges principales dans un système Linux :

L’horloge machine : Il s’agit de l’horloge utilisant un quartz dédié (généralement identique à ceux d’une montre bracelet) Cette horloge fonctionne d’une manière indépendante des programmes et même lorsque la machine est éteinte. elle a une précision de l’ordre de la seconde.
A divers endroits cette horloge est communément appelée l’horloge machine (« hardware clock »), l’heure temps réelle (« real time clock »), le RTC, l’horloge BIOS ou l’horloge CMOS.

L’horloge système : C’est l’horloge gérée par le noyau Linux et contrôlée par un timer. (Attention, Linux peut utiliser plusieurs clocksource différentes selon la configuration)
L’heure système est le nombre de secondes écoulées depuis Epoch (le 1er janvier 1970 00:00:00 UTC)
L’heure système est initialisée avec la valeur de l’horloge machine au démarrage de Linux, l’horloge machine n’est ensuite plus utilisée.
Le timestamp unix a la structure suivante :
struct timeval {
time_t tv_sec; /* secondes */
suseconds_t tv_usec; /* microsecondes */
};

On peut remarquer que le timestamp est toujours UTC. C’est seulement au moment de l’affichage que l’on calcule la date et l’heure locale en tenant compte de la timezone (fuseau horaire plus ajustement heure d’été/d’hiver). Attention la timezone est une variable d’environnement et un ensemble de règles du paquet tzdata. Il existe une structure timezone historique qui est obsolète

struct timezone {
int tz_minuteswest; /* minutes à l'ouest de Greenwich */
int tz_dsttime; /* type de changement horaire */
};

l’argument tz doit en général être NULL. Le champ tz_dsttime n’a jamais été utilisé sous Linux, il n’a jamais été géré, et ne le sera jamais par la libc ou glibc.

la fonction gettimeofday() retourne le timestamp.

Historiquement le timestamp est 32bits () mais sur debian squeeze 64 bits
sizeof time_t = 8
sizeof suseconds_t = 8

Ce sont donc « déjà » des entiers 64 bits signés.

Pour corriger la dérive de l’horloge, il existe une fonction adjtime() qui ajuste graduellement l’horloge système en l’accélérant ou la ralentissant à un rythme constant de 0.5ms/s.
int adjtime(const struct timeval *delta, struct timeval *olddelta);
si delta est NULL olddelta est peuplé avec le temps à ajuster restant.

La commande ntpdate utilise adjtime() si l’écart entre l’horloge locale et l’horloge de référence est inférieur à +-128 ms. Cela permet de recaler l’horloge tout en gardant un timestamp monotone. (qui ne reviens jamais en arrière et sans saut dans le futur) Au delà, comme il faudrait plus de 5 minutes pour recaler l’horloge , celle ci est réglée de façon abrupte.
Tout nouvel appel à adjtime avec un décalage non NULL conserve le décalage déjà effectué mais fait perdre le décalage restant à faire.
L’utilisation de ntpdate pendant la période d’ajustement induit de légères erreurs de mesure du delta à cause du fait que l’horloge est déjà en cours d’accélération ou de ralentissement. Il vaut donc mieux attendre que adjtime ait fini avant de faire à nouveau appel à ntpdate.

Enfin il exite une fonction permettant de modifier de façon permanente la derive de l’horloge soft.
by adjusting the rate at which the system time is advanced with each timer interrupt, using adjtimex(8).

Routage et bridging pour HVM Xen sur Dedibox.

 Trucs et astuces techniques  Commentaires fermés sur Routage et bridging pour HVM Xen sur Dedibox.
Mai 222011
 

SVP lisez le post Routage et bridging pour PVM Xen sur Dedibox. avant de lire celui-ci.

ATTENTION !
lisez tout avant de manipuler, il y a moyen de perdre la main sur la machine hôte assez facilement.

Les HVM diffèrent un peu des machines PVM. En particulier dans la déclaration du bridging.
Pour faire le bridging, les PVM utilisent une interface vif qui est bridgée sur peth0.
Dans le cas des HVM, une interface vif est bien crée mais elle me semble inutilisée. Une autre interface tap est également crée et est elle aussi bridgée sur peth0
cependant à la diférence des vif qui sont créées avec une mac fe:ff:ff:ff:ff:ff les interfaces tap sont créées avec des mac randomisées.
Cela serait sans la moindre importance si le noyau Linux n’avait l’idée stupide d’affecter à un bridge la mac la plus basse de toutes les interfaces connectées au bridge en question.
Donc, si la mac randomisée pour votre tap est plus petite que celle de votre eth0 (la mac de mon eth0 commence par BC pas de chance) vous perdrez la main sur votre machine hôte (en plus, vous diffusez un mac illégale, alors soyez heureux si online.net ne vous blackliste pas pour tentative de spoofing. )

La solution : Modifier le script de création de l’interface virtuelle pour mettre la mac de la tap à fe:ff:ff:ff:ff:ff ( fe au début pour éviter le ff partout qui est l’adresse de broadcast. Personnellement, j’aurais plutôt mis le fe à la fin mais comme j’ai vu partout comme ça, je suppose qu’il y a une bonne raison…. ou pas…. enfin, bon ça marche comme ça tant qu’il n’existe pas de cartes réseau dont la mac commence en ff, y’a de la marge…)
Pour cela, éditez le script /etc/xen/scripts/qemu-ifup et modifier le comme suit

#!/bin/sh

echo -c 'config qemu network with xen bridge for '
echo $*

#patch pcdwarf 
echo "La configuration actuelle de $1 est "
ip link show $1
echo "Passage de la mac de $1 a fe:ff:ff:ff:ff:ff"
ip link set $1 addr fe:ff:ff:ff:ff:ff
echo "La configuration actuelle de $1 est maintenant"
ip link show $1

echo "activation de $1"
ifconfig $1 0.0.0.0 up

echo "Ajout de $1 au bridge $2"
brctl addif $2 $1

#elements facultatifs pour faire du routage
#echo "Activation du proxy ARP pour $1" 
#echo 1 >/proc/sys/net/ipv4/conf/$1/proxy_arp


Les éléments facultatifs pour le routage serviront a faciliter le routage des machines windows mais ne doivent pas être activés sans en comprendre toutes les implications.

La suite un peu plus tard…. 🙂

Mai 222011
 

Tout ce qui suit concerne l’utilisation de Xen4 sur une base Debian 6.0 (Squeeze) sur architecture amd64 avec les serveurs dédiés « dedibox » proposés par online.net
Il est (très) probable que cela soit spécifique à cette distribution / ce datacenter.

Attention : Online.net tire à vue sur les gros lourdauds qui font n’importe quoi avec leur config réseau (et ils ont raison de le faire… )
aussi, avant d’appliquer bêtement ce tuto, tachez de comprendre un petit peu ce que vous faites.
un petit ip --help et man ip ne seront pas trop pour éviter les boulettes.
Vigilence extrème et plus que jamais : RTFM !

Remarque importante : Ce qui suit concerne les PVM (ParaVirtualized Machine). Pour les HVM avec Qemu, voir un autre (futur) post.

Il y a 2 problèmes importants :

  • Premièrement le respect de la mac imposée par le datacenter pour configurer l’interface de la machine virtuelle
  • Deuxièmement, le routage un poil bizare utilisé pour les IP failover.

Concernant le mode bridge : il n’y a pas trop de souci.
Vous devez demander l’allocation d’une adresse MAC au datacenter, puis il suffit de spécifier l’adresse mac dans le fichier de configuration de la VM.
exemple :
vif = [ 'ip=88.190.XXX.XXX,mac=00:16:3e:00:XX:XX' ]

Sur votre machine hôte, il vous faudra aussi avoir dans /etc/xen/xend-config.sxp les lignes suivantes :

(network-script network-bridge)
(vif-script vif-bridge)

Dès que vous aurez fini l’installation de votre PVM (je suppose que vous maitrisez déjà debootstrap) il faut impérativement ajouter quelques lignes dans les bons fichiers pour tenir compte du routage un peu particulier que pratique online.net

Il est probable (voir certain) que l’ip failover soit dans un VLAN différent de votre ip principale sur ce serveur. Or, comme il ne s’agit que d’une redirection, l’adresse du routeur reste celle qui sert à votre machine Hote, laquelle n’est ‘logiquement’ pas joignable depuis le reseau de l’ip-failover.

Disons par exemple que votre VM a une ip en 88.190.AAA.BBB mais que votre machine hote est en 88.190.CCC.DDD
La paserelle de la machine hote est logiquement 88.190.CCC.1.
La paserelle de votre VM devrait etre 88.190.AAA.1 si AAA était un VLAN « normal », mais dans ce cas il s’agit bien de 88.190.CCC.1.
Problème si vous specifiez dans le /etc/network/interfaces de votre VM

auto eth0
iface eth0 inet static
address 88.190.CCC.DDD
netmask 255.255.255.0
gateway 88.190.AAA.1

Ca ne peut pas marcher car le reseau AAA de la gateway n’est pas joignable.

Pour corriger ce problème, j’ai vu maintes fois sur le net la configuration suivante

auto eth0
iface eth0 inet static
address 88.190.CCC.DDD
netmask 255.255.0.0
gateway 88.190.AAA.1

Ça fonctionne mais avec l’inconvénient majeur que vous vous fermez l’accès à toutes les machines qui sont dans 88.190.0.0/16 mais pas dans 88.192.AAA.0/24.
Bref, c’est de la bidouille.

La configuration qui me parait la plus juste est la suivante :

  • Dire que la machine est seule dans son vlan et DOIT communiquer avec le routeur pour toutes les autres.
  • Spécifier une exception pour que l’ip du routeur soit déclarée joignable directement par eth0
  • Spécifier le routeur comme route par défaut (c’est à dire pour tout le trafic d’après le netmask )


auto eth0
iface eth0 inet static
address 88.190.CCC.DDD
netmask 255.255.255.255
post-up ip route add 88.190.AAA.1 dev eth0
post-up ip route add default via 88.190.AAA.1

Ça fonctionne à un détail près : Si vous avez des échanges entre plusieurs de vos VM (au hasard, un serveur web et un serveur SQL), ces infos passeront systématiquement par le routeur plutôt que de s’échanger directement entre les box. Outre la fait que cela peut impacter négativement les performances, le vrai problème est que le trafic va sortir de votre machine hôte, et pourra donc potentiellement être sniffé par tout équipement situé entre votre box et le routeur, ce qui vous contraindra à crypter les échanges.
Vous pouvez contourner cette limitation en ajoutant des routes spécifiques pour ces machines là
ajoutez simplement des lignes post-up dans votre fichier /etc/network/interfaces

Generateur de sparse-file

 Trucs et astuces techniques  Commentaires fermés sur Generateur de sparse-file
Mai 192011
 
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <ctype.h>


const char * strtera="To";
const char * strgiga="Go";
const char * strmega="Mo";
const char * strkilo="Ko";
const char * stroctets="octets";
const char * strunkwn="inconnu";

#define TERA 1099511627776
#define GIGA 1073741824
#define MEGA 1048576
#define KILO 1024

const long tera = TERA;
const long giga = GIGA;
const long mega = MEGA;
const long kilo = KILO;

long unit=0;

char buffer[4096];
unsigned long size=0;
const char * filename = NULL;
int justdoit = false;



const char* strofunit(const long u)
{   switch (u)
    {   case TERA : return strtera;
        case GIGA : return strgiga;
        case MEGA : return strgiga;
        case KILO : return strkilo;
        case 1 :    return stroctets;
        default : return strunkwn;
    }
}

void usage(void)
{
    fprintf(stderr, "\n");
    fprintf(stderr, "usage :  zerogen -f filename -s size \n");
    fprintf(stderr, "    size peut tre specit avec une unit comme '12G' or '125M' \n");
    fprintf(stderr, "    Si l'unit n'est pas spcifie avec size, elle peut l'etre avec -u (mais pas les deux)\n");
    fprintf(stderr, "    En l'absence de toute unit, la taille est considre tre en octets.\n");
    fprintf(stderr, "    La taille ne doit en aucun cas depasser 8To (comportement imprvisible dans ce cas).\n");
    fprintf(stderr, "    \n");
    fprintf(stderr, "    zerogen ne modifiera pas les fichiers qui existent dja\n");
    fprintf(stderr, "    \n");
    fprintf(stderr, "    exemple :  \n");
    fprintf(stderr, "                zerogen -f disk.img -s 20G\n");
    fprintf(stderr, "                zerogen -f disk2.img -s 20 -u G\n");
    fprintf(stderr, "    \n");

}    


int getarg(int argc, char* argv[] )
{   
    int c;
    int tmp;
    char tmp2;

    if (!argc) return false;

    while ( (c = getopt(argc, argv, "jS:s:u:f:")) != EOF )
    {   
        switch(c)
        {   case 'j' :  justdoit=true;
                        break;
    
            case 's' :
            case 'S' :  if (size)
                        {   printf("Erreur : la taille est specifie plusieurs fois\n");
                            return false;                        
                        }
                        tmp = sscanf(optarg,"%lu%c", &size, &tmp2);
                        if ( ! tmp ) return false;
                        if ( tmp == 2 )
                        switch ( toupper(tmp2) )
                        {   case 'T' : unit = tera; break;
                            case 'G' : unit = giga; break;
                            case 'M' : unit = mega; break;
                            case 'K' : unit = kilo; break;
                            case 'O' : unit = 1; break;
                        }                
                        break;

            case 'u' :  if (unit)
                        {   printf("Erreur : Conflit d'units\n");
                            return false;
                        }
                        switch ( toupper(optarg[0]) )
                        {   case 'T' : unit = tera; break;
                            case 'G' : unit = giga; break;
                            case 'M' : unit = mega; break;
                            case 'K' : unit = kilo; break;
                            case 'O' : unit = 1; break;
                        }
                        break;

            case 'f' :  filename = optarg;
                        break;

            case '?' :  perror("Option inconnue\n");
                        return false;
        }
    }

    

    if ( !filename )
    {   fprintf(stderr,"fichier non specifie : utilisez l'option -f \"fichier\"\n");
        return false;
    }

    if ( ! size )
    {   fprintf(stderr, "taille non spcifie : utiliser l'option -s taille \n");
        return false;
    }


    if ( !unit )
    {   fprintf(stderr,"unit non specifie : On considere que la taille specifiee est en octets\n");
        unit=1;
    }
    
    if ( !unit )
    {   fprintf(stderr,"unit non specifie : utilisez l'option -uO -uK -uM -uG -uT pour specifier octets, kilo, mega, giga\n");
        return false;
    }
    
    return true;
                        
}


int main (int argc, char* argv[])
{   FILE* f;
    int w;
    assert( sizeof(long) == 8 );
    assert( sizeof(size_t) == 8);

    memset(buffer, 0, 4096);

    if ( ! getarg(argc, argv) ) 
    {   usage();
        return 1;
    }

    f = fopen(filename, "r");
    if (f && !justdoit)
    {   fclose(f);
        fprintf(stderr,"Le fichier existe dj specifiez -j pour passer outre (-j comme just do it)\n");        
        return 1;
    }

    if (f && !justdoit) fclose(f);
    
    printf("Cration du fichier [%s] de taille %lu %s\n", filename, size, strofunit(unit));
    f = fopen(filename, "w");
    assert(f);
    
    fseek(f, (size*unit)-1 , SEEK_SET);
    w=fwrite(buffer, 1, 1, f);
    assert(w);
    fclose (f);
    return 0;
}



liste des paquets qui vont bien pour serveur web

 Trucs et astuces techniques  Commentaires fermés sur liste des paquets qui vont bien pour serveur web
Mai 132011
 


apt-get update
apt-get remove --purge vim-tiny --assume-yes --force-yes
apt-get install vim --assume-yes --force-yes
sed -i 's/^# alias/alias/ ; s/^# export/export/ ; s/^# eval/eval/' /root/.bashrc
sed -i 's/^.*syntax on/syntax on/' /etc/vim/vimrc
apt-get install htop gcc g++ make binutils htop tree iftop pipebench dialog whiptail mutt --assume-yes --force-yes
apt-get install freebsd-manpages manpages-fr manpages-fr-dev aespipe cowsay rsync locales --assume-yes --force-yes
apt-get install apache2 libapache2-mod-php5 php5 php5-cli --assume-yes --force-yes
apt-get install mysql-server php5-mysql --assume-yes --force-yes

voici la version condensée en une seule ligne

apt-get update ; apt-get remove --purge vim-tiny --assume-yes --force-yes ; apt-get install vim --assume-yes --force-yes ; sed -i 's/^# alias/alias/ ; s/^# export/export/ ; s/^# eval/eval/' /root/.bashrc ; sed -i 's/^.*syntax on/syntax on/' /etc/vim/vimrc ; apt-get install htop gcc g++ make binutils htop tree iftop pipebench dialog whiptail mutt --assume-yes --force-yes ; apt-get install freebsd-manpages manpages-fr manpages-fr-dev aespipe cowsay rsync locales ntpdate --assume-yes --force-yes ; apt-get install apache2 libapache2-mod-php5 php5 php5-cli --assume-yes --force-yes ; apt-get install mysql-server php5-mysql --assume-yes --force-yes

Installation de serveur debian squeeze par debootstrap

 Trucs et astuces techniques  Commentaires fermés sur Installation de serveur debian squeeze par debootstrap
Mai 092011
 

demarrer le serveur en mode rescue/live-CD ou autre medium de ce genre

dans /usr/lib/debootstrap s’assurer que le le script squeeze existe (au besoin faire pointer sur lenny) c’est la liste des paquets de base et elle est simillaire par contre le nom du script determine ensuite le nom de version

cd /root
cfdisk /dev/sda
mke2fs -j /dev/sda1
mkswap /dev/sda2
pvcreate /dev/sda3
vgcreate vg0 /dev/sda3
lvcreate vg0 --name=srv -L120G
mke2fs -j /dev/vg0/srv
mount /dev/sda1 /mnt
debootstrap --arch=amd64 squeeze /mnt
mount --bind /dev/ /mnt/dev
mount --bind /proc /mnt/proc
chroot /mnt
apt-get remove --purge vim-tiny --assume-yes --force-yes
apt-get update
apt-get install vim --assume-yes --force-yes
sed -i 's/^# alias/alias/ ; s/^# export/export/ ; s/^# eval/eval/' /root/.bashrc
sed -i 's/^.*syntax on/syntax on/' /etc/vim/vimrc
exit
chroot /mnt
apt-get install htop gcc g++ make binutils htop tree iftop pipebench --assume-yes --force-yes
apt-get install makedev --assume-yes --force-yes
exit
umount /mnt/dev
chroot /mnt
cd /dev
rm -Rf .udev
MAKEDEV generic std
cd /root
apt-get install linux-image-2.6.32-5-amd64 grub2 --assume-yes --force-yes
mount /sys
grub-install /dev/sda --force
update-grub
apt-get install dialog lvm2 whiptail freebsd-manpages manpages-fr manpages-fr-dev aespipe cowsay rsync locales --assume-yes --force-yes
(
echo "# /etc/fstab: static file system information."
echo "#"
echo "# "
echo "proc /proc proc defaults 0 0"
echo "/dev/sda1 / ext3 errors=remount-ro 0 1"
echo "/dev/sda2 none swap sw 0 0"
echo "/dev/vg0/srv /srv ext3 noatime,nodiratime 0 0"
) >/etc/fstab
(
NET="IPa.IPb.IPc"
echo "# Used by ifup(8) and ifdown(8). See the interfaces(5) manpage or"
echo "# /usr/share/doc/ifupdown/examples for more information."
echo
echo
echo "auto lo"
echo "iface lo inet loopback"
echo
echo "auto eth0"
echo "iface eth0 inet static"
echo " address $NET.222"
echo " netmask 255.255.255.0"
echo " network $NET.0"
echo " broadcast $NET.255"
echo " gateway $NET.1"
echo
echo
) >/etc/network/interfaces
apt-get install openssh-server
passwd
exit
[ DESACTIVER LE MODE RESCUE]
reboot

Postfix Virtual map

 Trucs et astuces techniques  Commentaires fermés sur Postfix Virtual map
Jan 262011
 

Pour régénérer les databases il faut utiliser la commande « postmap »
exemple :

postmap /etc/postfix/virtual.cf

cela permet de parser le fichier virtual.cf pour régénérer un fichier database

/etc/init.d/postfix restart

Consulter ensuite /var/log/mail.info et /var/log/mail.err

Directives pour mod_auth_mysql debian lenny

 Trucs et astuces techniques  Commentaires fermés sur Directives pour mod_auth_mysql debian lenny
Jan 132011
 

Impossible de trouver de la doc récente sur internet.
Le mieux est d’aller directement voir dans le code source quelles sont les directives acceptées.

Auth_MySQL_Info host, user and password of the MySQL database
AuthMySQL_DefaultHost Default MySQL host
AuthMySQL_DefaultUser Default MySQL user
AuthMySQL_DefaultPassword Default MySQL password
Auth_MySQL_DefaultPort Default MySQL server port
Auth_MySQL_DefaultSocket Default MySQL server socket
Auth_MySQL_General_DB default database for MySQL authentication
AuthMySQL_DefaultDB default database for MySQL authentication
AuthMySQL_Host database host
Auth_MySQL_Host database host
Auth_MySQL_Socket database host socket
AuthMySQL_Socket database host socket
Auth_MySQL_Port database host port
AuthMySQL_Port database host port
Auth_MySQL_Username database user
AuthMySQL_User database user
Auth_MySQL_Password database password
AuthMySQL_Password database password
Auth_MySQL_DB database name
AuthMySQL_DB database name
Auth_MySQL_Password_Table Name of the MySQL table containing the password/user-name combination
AuthMySQL_Password_Table Name of the MySQL table containing the password/user-name combination
Auth_MySQL_Group_Table Name of the MySQL table containing the group-name/user-name combination; can be the same as the password-table.
Auth_MySQL_Group_Clause Additional WHERE clause for group/user-name lookup
AuthMySQL_Group_Table Name of the MySQL table containing the group-name/user-name combination; can be the same as the password-table.
Auth_MySQL_Password_Field The name of the field in the MySQL password table
AuthMySQL_Password_Field The name of the field in the MySQL password table
Auth_MySQL_Password_Clause Additional WHERE clause for group password/user-name lookup
Auth_MySQL_Username_Field The name of the user-name field in the MySQL password (and possibly group) table(s).
AuthMySQL_Username_Field The name of the user-name field in the MySQL password (and possibly group) table(s).
Auth_MySQL_Group_Field The name of the group field in the MySQL group table; must be set if you want to use groups.
AuthMySQL_Group_Field The name of the group field in the MySQL group table; must be set if you want to use groups.
Auth_MySQL_Group_User_Field The name of the user-name field in the MySQL group table; defaults to the same as the username field for the password table.
AuthMySQL_Group_User_Field The name of the user-name field in the MySQL group table; defaults to the same as the username field for the password table.
Auth_MySQL_Empty_Passwords Enable (on) or disable (off) empty password strings; in which case any user password is accepted.
AuthMySQL_Empty_Passwords Enable (on) or disable (off) empty password strings; in which case any user password is accepted.
Auth_MySQL_Authoritative When ‘on’ the MySQL database is taken to be authoritative and access control is not passed along to other db or access modules.
AuthMySQL_Authoritative When ‘on’ the MySQL database is taken to be authoritative and access control is not passed along to other db or access modules.
AuthMySQL_AllowOverride Allow directory overrides of configuration
Auth_MySQL_Encrypted_Passwords When ‘on’ the password in the password table are taken to be crypt()ed using your machines crypt() function.
AuthMySQL_Encrypted_Passwords When ‘on’ the password in the password table are taken to be crypt()ed using your machines crypt() function.
Auth_MySQL_Scrambled_Passwords When ‘on’ the password in the password table are taken to be scramble()d using mySQL’s password() function.
AuthMySQL_Scrambled_Passwords When ‘on’ the password in the password table are taken to be scramble()d using mySQL’s password() function.
Auth_MySQL_Encryption_Types Encryption types to use
AuthMySQL_Encryption_Types Encryption types to use
Auth_MySQL_Non_Persistent Use non-persistent MySQL links
AuthMySQL_Persistent Use non-persistent MySQL links
Auth_MySQL Enable MySQL authentication
AuthMySQL Enable MySQL authentication

Raid 3ware Rebuild

 Trucs et astuces techniques  Commentaires fermés sur Raid 3ware Rebuild
Déc 082010
 

Dans tw_cli , commencer par retirer le disque defaillant avec
/cx/px remove
Remplacer le disque (ou pas) puis rescanner le disque avec
/cx rescan
enfin lancer le rebuild avec
/cx/ux start rebuild disk=n
avec n le numero du port px où est connecté de disque (La doc n’est absolument pas claire à ce sujet)