Небольшие правки кода и добавление описания
parent
67e0e3eeea
commit
46a4a62f68
37
README.md
37
README.md
|
@ -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
33
udavfs3
|
@ -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])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue