1. Server

The server is a daemon monitoring devices temperatures.

Devices are separated in shelves. Each shelf contains a set of devices. Each device has a type (HDD, SSD, CPU).

Fan speed is determined from the temperature of the device which is in most need of cooling.

For each type of device, an effective temperature is determined from the maximum temperature of all the devices of this type. With this temperature, an effective fan speed is determined. We then have an effective fan speed for each device type, the highest fan speed is then defined as the speed for the entire shelf.

1.1. Examples

Start the server:

# fand server

Start and listen on 0.0.0.0:1234:

# fand server -a 0.0.0.0 -P 1234

Start and show very verbose logging:

# fand server -vvv

1.2. Configuration file

Default configuration file is read from either /etc/fand.ini, the FAND_CONFIG environment variable, or ./fand.ini. There is also a -c parameter to specify the config file path.

The configuration is in the ini format.

It must have a [DEFAULT] section wich contain a shelves key listing shelves names to use. This section also contains default configuration for fan speed.

For each shelf, a section with its name has to be defined. It will contain a devices key listing devices assigned to this shelf. It can also override fan speed defined in [DEFAULT].

Example configuration file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# Example configuration file for fand

# DEFAULT section, mandatory
[DEFAULT]

# List shelves, comma separated, mandatory
# Each shelf must have a section with its name
shelves = shelf1, shelf2

# Default hdd_temps configuration
# Dictionnary: `temperature in deg C: speed in percentage`
# Example here: if the drive is at 37 deg C, corresponding speed is 30%
#               if the drive is at 30 deg C, corresponding speed is 25%
#               if the drive is < 37 deg C, corresponding speed is 25%
hdd_temps = 0: 25, 37: 30, 38: 40, 39: 50, 40: 75, 41: 100

# Default ssd_temps configuration
# Same format as hdd_temps, but the values are for SSD rather than HDD
ssd_temps = 0: 25, 60: 40, 62.5: 50, 65: 70, 67.5: 90, 70: 100

# Default cpu_temps configuration
# Same format as hdd_temps, but the values are for the CPU rather than HDD
cpu_temps = 0: 25, 75: 40, 80: 60, 85: 80, 90: 100

# Configuration for shelf shelf1
[shelf1]

# List of devices in shelf shelf1, mandatory, newline separated
# Each line is `serial; position`
# serial: serial number of the device
# position: position information about the drive, used to help locate it
devices = AD7E4EE5B03693D6; drive 1,1
          F63414EF35A424FB; drive 1,2
	  C198DB33426BE180; system drive

# Configuration for shelf shelf2
[shelf2]

# List of devices
devices = 062110D2532377B5; small drive 2,1
          FFBEB97C6ED5953B; system drive

# Override hdd_temps for this shelf
# This configuration will be used for this shelf only
hdd_temps = 0: 40, 37: 50, 38: 60, 39: 75, 40: 85, 41: 100

1.3. Python API

fand.server.REQUEST_HANDLERS

Dictionnary assigning a Request to a function

1.3.1. Device

class fand.server.Device(serial: str, position: str)[source]

Class handling devices to get temperature from

Parameters:
  • serial – Device serial number
  • position – Device positionning information
find() → fand.server.Device._DeviceWrapper[source]

Search device on the system

position = None

Device positionning information

serial = None

Device serial number

temperature

Current drive temperature

type

DeviceType

update() → None[source]

Update device informations

class Device.DeviceType[source]

Bases: enum.Enum

Enumeration of device types, to identify Device objects

CPU = 4

System CPU

HDD = 2

HDD

NONE = 1

Unknown device

SSD = 3

SSD

1.3.2. Shelf

class fand.server.Shelf(identifier: str, devices: Iterable[fand.server.Device], sleep_time: float = 60, hdd_temps: Optional[Dict[float, float]] = None, ssd_temps: Optional[Dict[float, float]] = None, cpu_temps: Optional[Dict[float, float]] = None)[source]

Class handling shelf data

Parameters:
  • identifier – Shelf identifier (name)
  • devices – Iterable of Device objects
  • sleep_time – How many seconds to wait between each shelf update
  • hdd_temps – Dictionnary in the format temperature: speed, temperature in Celcius, speed in percent, must have a 0 deg key
  • ssd_temps – Dictionnary in the format temperature: speed, temperature in Celcius, speed in percent, must have a 0 deg key
  • cpu_temps – Dictionnary in the format temperature: speed, temperature in Celcius, speed in percent, must have a 0 deg key
Raises:

ShelfTemperatureBadValue – One of the temps dictionnary is invalid

pwm

Get shelf PWM value

Reading get the effective PWM value. Changing override the PWM value.

Raises:ShelfPwmBadValue – Invalid value
pwm_expire

Set the PWM override expiration date, defaults to local timezone

Raises:ShelfPwmExpireBadValue – Invalid value
rpm

Shelf fan speed RPM

Raises:ShelfRpmBadValue – Invalid value
update() → None[source]

Update shelf data

1.3.3. add_shelf

fand.server.add_shelf(shelf: fand.server.Shelf) → None[source]

Add a Shelf to the dictionnary of known shelves

Parameters:shelf – Shelf to add

1.3.4. listen_client

fand.server.listen_client(client_socket: socket.socket) → None[source]

Listen for client requests until the connection is closed

Parameters:client_socket – Socket to listen to

1.3.5. read_config

fand.server.read_config(config_file: Optional[str] = None) → Iterable[fand.server.Shelf][source]

Read configuration from a file, returns an iterable of shelves

Parameters:config_file – Configuration file to use, defaults to the FAND_CONFIG environment variable or ./fand.ini or /etc/fand.ini
Raises:ServerNoConfigError – Configuration not found

1.3.6. shelf_thread

fand.server.shelf_thread(shelf: fand.server.Shelf) → None[source]

Monitor a shelf

Stops when fand.util.terminating() is True or when an unexpected exception occur.

Parameters:shelf – Shelf to monitor

1.3.7. main

fand.server.main() → NoReturn[source]

Entry point of the module

1.3.8. daemon

fand.server.daemon(config_file: Optional[str] = None, address: str = 'build-17980832-project-622900-fand', port: int = 9999) → None[source]

Main function

Parameters:
  • config_file – Configuration file to use, defaults to the FAND_CONFIG environment variable or ./fand.ini or /etc/fand.ini
  • address – Address of the interface to listen on, defaults to hostname
  • port – Port to listen on
Raises:

ListeningError – Error while listening for new connections