summaryrefslogtreecommitdiffstats
path: root/zvolcreator.rb
blob: e811d1f3d2d6b5b76a40e32d0fcb067001b97888 (plain)
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#!/usr/bin/env ruby

require 'zfs'
require 'socket'
require 'json'
require 'uuid'

require_relative 'zfs_monkeypatch'
load File.dirname($0) + "/" + 'config.rb'

puts "Filesystem base: #{Config[:basefs]}"
puts "Default user quota: #{Config[:default_user_quota]}"
puts "Socket path: #{Config[:socketpath]}"
sockdir = File.dirname(Config[:socketpath])
puts "Socket directory: #{sockdir}"

# Check if socket directory exists, if not - create if with apropriate options
Dir.mkdir(sockdir, 0700) if not File.exists?(sockdir)
File.umask(0077)

puts "Setting up UUID generator"
UUID.state_file = false

puts "Starting socket server"
server = UNIXServer.open(Config[:socketpath])
loop do
    Thread.start(server.accept) do |client|
        begin
            puts "Accepted new client connection"
            uuid = UUID.new
            puts "Sending our greeting"
            client.puts({:status => 0, :content => {:app => "zvolcreator", :apiversion => 0}}.to_json)
            response = JSON.parse(client.gets)
            puts "Client response: #{response}"
            raise ArgumentError.new("Bad status") if response["status"] != 0

            puts "Sending basic server info"
            client.puts({:status => 0, :content => {:basefs => Config[:basefs], :default_user_quota => Config[:default_user_quota]}}.to_json)
            response = JSON.parse(client.gets)
            puts "Client response: #{response}"
            raise ArgumentError.new("Bad status") if response["status"] != 0
            raise ArgumentError.new("No user specified") if not response["content"]["user"]
            raise ArgumentError.new("Volume size not specified") if not response["content"]["volsize"]
            # poor man's check for nasty characters in usernames
            raise ArgumentError.new("Invalid characters in username") if response["content"]["user"] =~ /[\/\\ ]/

            userfs = Config[:basefs] + "/" + response["content"]["user"].to_s
            
            ZFS(userfs).create(:zfsopts => ["quota=#{Config[:default_user_quota]}"])
            volpath = userfs + "/" + uuid.generate
            ZFS(volpath).create(:sparse => true, :volume => response["content"]["volsize"])
            client.puts({:status => 0, :content => {:volpath => volpath}}.to_json)
            client.close
        rescue JSON::ParserError, ArgumentError => e
            puts "Error: #{e.to_s}"
            client.puts({:status => 1, :content => e.to_s})
            client.close
            Thread.kill
        end
    end
end