Back to Home

The Tale of the Raspberry and the External HDD. The first development experience for the platform

raspberry pi · raspbian · samba · python · mount · shares · external hdd

The Tale of the Raspberry and the External HDD. The first development experience for the platform

Good day, Habr! A couple of weeks ago the geek's hands were combed - I wanted to buy a rather sensational and well-known single-board mini-computer Raspberry Pi. The model was chosen the “coolest" - version "B" with 512Mb of RAM on board.

This post is about something else. After all the manipulations with the setup, I wanted to try the machine, so to speak, “in action”. The idea arose almost immediately. At home, I have 3 computers, 2 smartphones, a budget router, and an external 2Tb hard drive - Seagate Expansion External. The HDD connection interface is USB. The router of the connectors has only Ethernet and a hole for the power cord. All my devices connect to the router only via WiFi, and none can work in constant mode. But then Raspberry appears. The miniature size of the board allows you to place a system of the form [HDD <= USB => RPi <= Ethernet => DIR300NRU (router) <= WiFi => LAN] directly on the windowsill and use the disk on the local network, and its meager power consumption allows you to keep it turned on almost constantly . RPi runs the Linux OS family, namely, I installed Raspbian on it. It would seem that installing a samba server and sharing the drive ... but that would be too easy. The final task has become more complicated: it is necessary to make an external drive available on the local network, only if my smartphone is currently connected to this network, otherwise the drive will be unmounted, thereby reducing the load and its power consumption. So we will write a daemon, and we will write in Python. Go!

First thing, first thing ... samba!


First you need to configure samba and iron. We hook hard to Raspberry via USB, Raspberry to the router via Ethernet. We plug everything into a power outlet. We connect via SSH to RPi, I use PuTTY under Windows as a client.
In Raspbian “out of the box” there is no way to connect the NTFS-partition of the disk for writing, it is mounted only as Read-Only and does not allow access to itself on the local network.
It doesn’t matter, now install the necessary driver:
pi@raspberrypi ~ $ sudo apt-get install ntfs-3g

Next, we need to know the name of the partition to mount, we find out like this:
pi@raspberrypi ~ $ sudo fdisk -l

And we get something like this:
Disk / dev / sda: 2000.4 GB, 2000398931968 bytes
255 heads, 63 sectors / track, 243201 cylinders, total 3907029164 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical / physical): 512 bytes / 512 bytes
I / O size (minimum / optimal): 512 bytes / 512 bytes
Disk identifier: 0x0006573a

Device Boot Start End Blocks Id System
/ dev / sda1 2048 409602047 204800000 83 Linux
/ dev / sda2 409602048 419842047 5120000 82 Linux swap / Solaris
/ dev / sda3 419842048 3907028991 1743593472 7 HPFS / NTFS / exFAT

My external HDD has the name sda, the partition is called sda3, you may have something else. Remember it.
Then we look where to mount. By default, the drive is automatically mounted in / media / VolumeName. I decided not to bother and leave it there. The path to the directory is: / media / DataR.

Now configure the samba server itself. Open the configuration file for writing:
pi@raspberrypi ~ $ sudo nano /etc/samba/smb.conf

You can read about the configuration in detail on the network, I just give my configuration file:
[global]
workgroup = WORKGROUP
server string = RPi Fileserver
netbios name = fileserver
dns proxy = no
log file = /var/log/samba/log.%m
max log size = 1000
syslog = 0
panic action = /usr/share/samba/panic-action %d
encrypt passwords = true
passdb backend = smbpasswd
obey pam restrictions = yes
unix password sync = yes
passwd program = /usr/bin/passwd %u
passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssucce$
pam password change = yes
map to guest = bad user
#======================= Share Definitions =======================
[ExternalHDD]
comment = HDD Seagate Expansion External 2Tb
path = /media/DataR
writable = yes
printable = no
guest ok = yes
read only = no


Customized? Move on. Check the performance of the entire structure. We mount the partition (first, unmount it, just in case), restart the samba server.
pi@raspberrypi ~ $ sudo umount /media/DataR
pi@raspberrypi ~ $ sudo mount /dev/sda3 /media/DataR
pi@raspberrypi ~ $ sudo /etc/init.d/samba restart

If no errors are observed, then try to find a server on the network. If everything is fine here, then move on.

Writing a script


We will write in Python. The interpreter is already available to us preinstalled on Raspbian. I decided to write immediately in the console:
pi@raspberrypi ~ $ nano shrdsk.py

What we need:
  • Check if IP is available on LAN
  • Execute system commands
  • Wait a while
  • Loop this whole thing

So, first of all, import the necessary modules:
import socket as s # сократили имя
from time import sleep # функция ожидания
from os import system # функция исполнения консольных команд
from errno import * # модуль с номерами ошибок

Further, everything will fit in a small infinite loop:
while 1:
    sock=s.socket(s.AF_INET,s.SOCK_STREAM) # открываем сокет
    try:
        sock.connect(('192.168.0.14',1001)) # пытаемся соединиться с нашим устройством, IP на нём нужно прописать статический, порт выбрать любой свободный
        system('mount /dev/sda3 /media/DataR') # коннект удался, монтируем раздел
        system('/etc/init.d/samba restart') # и расшариваем
    except socket.error, v:
        # произошла ошибка, тут 2 варианта:
        if v[0]==ECONNREFUSED: # 1 - IP существует, но отвергает соединение (НО существует же!)
            system('mount /dev/sda3 /media/DataR') # монтируем
            system('/etc/init.d/samba restart') # шарим
        else: # 2 - такого IP нет
            system('umount /media/DataR') # размонтируем
            system('/etc/init.d/samba stop') # закрываем сервер
    sock.close() # после каждого прогона закрываем за собой сокет
    sleep(60) # и ждём 60 секунд

This is a minimally workable option, but I decided to modify it a bit, adding the ability to configure and output debugging messages to the console. The finished version looks like this:
# Coding: utf8
# Author: HeffCodeX
# Version: 1.0
# !!!!!!!!!!!!!!!!!!!!
# !START ME WITH ROOT!
# !!!!!!!!!!!!!!!!!!!!
###
# socket config:
HOST='192.168.0.14' # host to detect
PORT=1001 # any random port
WAITING=60 # time to wait between connections (in secs)
###
# mount config:
MOUNT=1 # do mount/umount (1/0)
DEV='sda3' # device (without "/dev/")
DIR='/media/DataR' # directory to mount
###
import socket as s
from time import sleep
from os import system
from errno import *
while (1):
        sock=s.socket(s.AF_INET,s.SOCK_STREAM)
        try:
                print "connecting..."
                sock.connect((HOST,PORT))
                print "socket ok"
                if MOUNT:
                        print "mount device"
                        system("mount /dev/%s %s"%(DEV,DIR))
                print "samba restart:"
                system("/etc/init.d/samba restart")
        except s.error, v:
                print "socket err"
                if v[0]==ECONNREFUSED:
                        if MOUNT:
                                print "mount device"
                                system("mount /dev/%s %s"%(DEV,DIR))
                        print "samba restart:"
                        system("/etc/init.d/samba restart")
                else:
                        if MOUNT:
                                print "umount device"
                                system("umount %s"%DIR)
                        print "samba stop:"
                        system("/etc/init.d/samba stop")
        sock.close()
        print "waiting..."
        sleep(WAITING)

Summary

It turned out that you can configure absolutely everything, and also disable (once) mounting the partition. It remains to register a static IP on the device to connect to our local network and that's it, a kind of disk access key is ready! For full automation, you can add a script to startup at startup. Open the rc.local system file:
pi@raspberrypi ~ $ sudo nano /etc/rc.local

And add the following line to it:
su pi -c "python /home/pi/shrdsk.py"

The path, of course, indicate your own.
That's all, thanks for reading ! This was my first development experience for Raspberry Pi, and for Linux in general.

UPD1: thanks for prompting about reboot and autostart, threw out the first, corrected the second

Read Next