Небольшие правки кода и добавление описания

master
inpos 2017-02-19 14:19:54 +03:00
parent 67e0e3eeea
commit 46a4a62f68
2 changed files with 55 additions and 15 deletions

View File

@ -1,4 +1,39 @@
# udavfs3 # udavfs3
Файловая система (FUSE), хранящая данные в базе данных (PostgreSQL) Файловая система (FUSE), хранящая данные в базе данных (PostgreSQL)
База данных и пользователь с полным доступом к ней должны быть созданы на сервере. База данных и пользователь с полным доступом к ней (если их ещё нет) должны быть созданы на сервере:
```
su - postrges
createuser -S -E -P fs_user
createdb -E UTF-8 -O fs_user fs_db
```
Скрипт необходимо скопировать в папку исполняемых файлов (например, /usr/local/bin) и сделать исполняемым:
```
cp udavfs3 /usr/local/bin/
chmod +x /usr/local/bin/udavfs3
```
Вручную монтируем следующей командой:
`udavfs3 "host=srv_hostname dbname=fs_db user=fs_user password=fs_user_password" /mount/point/path [-o mount_options]`
mount_options имеют смысл только для вновь созданной базы данных.
Если мы монтируем уже инициализированную файловую систему, mount_options игнорируются.
Список опций mount_options:
* fsid - уникальная (в рамках конкретного сервера) строка без пробелов. Из данной строки сформируется sha1-хэш, который и будет
уникальным идентификатором ФС для операционной системы.
* blocksize - размер блока ФС в байтах. Обычно используется 4096 (4 КБ).
* fssize - размер файловой системы. Можно использовать окончание еденицы измерения (k,m,g,t). Минимальный размер - 4 МБ.
Обратите внимание, что максимальный размер неограничен, но постарайтесь не выйти за пределы свободного места
папки с базой данных сервера PostgreSQL. Или продумайте возможность последующего увеличения размера свободного
места в этой папке до её полного заполнения.
Если мы хотим, чтобы система монтировала нашу ФС при старте, то добавляем в /etc/fstab следующую строку:
`udavfs3#"host=srv_hostname dbname=fs_db user=fs_user password=fs_user_password" /mount/point/path fuse _netdev 0 0`
Чтобы ФС была доступна всем пользователям надо установить 'user_allow_other' в /etc/fuse.conf
Сервер с базой данных (PostgreSQL) может находиться где угодно.

33
udavfs3
View File

@ -5,6 +5,7 @@
# UdavFS mount_option: # UdavFS mount_option:
# blocksize=<bytes> # blocksize=<bytes>
# fssize=<size>[k|m|g|t] # fssize=<size>[k|m|g|t]
# fsid=<uniq_name>
# #
# Option 'user_allow_other' MUST be set in /etc/fuse.conf # Option 'user_allow_other' MUST be set in /etc/fuse.conf
@ -500,7 +501,14 @@ class NoSuchRowError(Exception):
return 'Query produced 0 result rows' return 'Query produced 0 result rows'
def usage(): def usage():
raise SystemExit('Usage: %s "host=dbhost dbname=database user=dbuser password=dbpass" <mountpoint> [-o mount_options]\nUdavFS mount_option:\n\tblocksize=<bytes>\n\tfssize=<size>[k|m|g|t]\n\nOption \'user_allow_other\' MUST be set in /etc/fuse.conf' % sys.argv[0]) raise SystemExit('''\
Usage: %s "host=dbhost dbname=database user=dbuser password=dbpass" <mountpoint> [-o mount_options]
UdavFS mount_option:
fsid=<uniq_string>
blocksize=<bytes>
fssize=<size>[k|m|g|t]
Option 'user_allow_other' MUST be set in /etc/fuse.conf''' % sys.argv[0])
if __name__ == '__main__': if __name__ == '__main__':
@ -510,25 +518,22 @@ if __name__ == '__main__':
usage() usage()
conn_str = sys.argv[1] conn_str = sys.argv[1]
options = {x.split('=')[0].strip(): len(x.split('=')) > 1 and x.split('=')[1].strip() or True for x in sys.argv[4].split(',') } options = {x.split('=')[0].strip(): len(x.split('=')) > 1 and x.split('=')[1].strip() or True for x in sys.argv[4].split(',') }
if 'fsname' not in options.keys():
print('fsname MUST be in mountoptions\n')
usage()
fsname = options['fsname']
del options['fsname']
fsid = sha1(bytes(fsname.strip(), 'UTF-8')).hexdigest()
db = psycopg2.connect(conn_str) db = psycopg2.connect(conn_str)
db.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) db.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
cursor = db.cursor() cursor = db.cursor()
try: try:
cursor.execute('SELECT bs, size FROM fsinfo WHERE fsid=%s', (fsid,)) cursor.execute('SELECT fsid, bs, size FROM fsinfo WHERE fsid=%s', (fsid,))
blocksize, fssize = cursor.fetchone() fsid, blocksize, fssize = cursor.fetchone()
except: except:
if 'create' not in options.keys(): if 'fsid' not in options.keys():
print('Filesystem "%s" does not exist\n' % (fsname,)) print('fsid MUST be in mountoptions\n')
usage() usage()
del options['create'] fsname = options['fsid']
del options['fsid']
fsid = sha1(bytes(fsname.strip(), 'UTF-8')).hexdigest()
if 'blocksize' not in options.keys(): if 'blocksize' not in options.keys():
print('blocksize mountoption MUST be specified\n') print('blocksize mountoption MUST be specified\n')
usage() usage()
@ -541,7 +546,7 @@ if __name__ == '__main__':
mod1 = {'k': 1024, 'm': 1024 ** 2, 'g': 1024 ** 3, 't': 1024 ** 4} mod1 = {'k': 1024, 'm': 1024 ** 2, 'g': 1024 ** 3, 't': 1024 ** 4}
fssize = options['fssize'].lower() fssize = options['fssize'].lower()
del options['fssize'] del options['fssize']
if fssize[-1] in mod1.keys(): if fssize[-1].lower() in mod1.keys():
fssize = math.ceil((int(fssize[:-1]) * mod1[fssize[-1]]) / blocksize) * blocksize fssize = math.ceil((int(fssize[:-1]) * mod1[fssize[-1]]) / blocksize) * blocksize
if fssize < 4194304: if fssize < 4194304:
raise SystemExit('Filesystem size less than 4MB.\n') raise SystemExit('Filesystem size less than 4MB.\n')
@ -549,7 +554,7 @@ if __name__ == '__main__':
db.close() db.close()
del db del db
m_params = [ 'fsname=udavfs', 'nonempty', 'default_permissions', 'allow_other' ] m_params = [ 'fsname=udavfs3', 'nonempty', 'default_permissions', 'allow_other' ]
m_params.extend(options) m_params.extend(options)
mountpoint = os.path.abspath(sys.argv[2]) mountpoint = os.path.abspath(sys.argv[2])