Merge pull request #1026 from danrl/mwan
[project/luci.git] / applications / luci-app-lxc / luasrc / controller / lxc.lua
1 --[[
2
3 LuCI LXC module
4
5 Copyright (C) 2014, Cisco Systems, Inc.
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11         http://www.apache.org/licenses/LICENSE-2.0
12
13 Author: Petar Koretic <petar.koretic@sartura.hr>
14
15 ]]--
16
17 module("luci.controller.lxc", package.seeall)
18
19 require "ubus"
20 local conn = ubus.connect()
21 if not conn then
22     error("Failed to connect to ubus")
23 end
24
25
26 function fork_exec(command)
27         local pid = nixio.fork()
28         if pid > 0 then
29                 return
30         elseif pid == 0 then
31                 -- change to root dir
32                 nixio.chdir("/")
33
34                 -- patch stdin, out, err to /dev/null
35                 local null = nixio.open("/dev/null", "w+")
36                 if null then
37                         nixio.dup(null, nixio.stderr)
38                         nixio.dup(null, nixio.stdout)
39                         nixio.dup(null, nixio.stdin)
40                         if null:fileno() > 2 then
41                                 null:close()
42                         end
43                 end
44
45                 -- replace with target command
46                 nixio.exec("/bin/sh", "-c", command)
47         end
48 end
49
50 function index()
51         page = node("admin", "services", "lxc")
52         page.target = cbi("lxc")
53         page.title = _("LXC Containers")
54         page.order = 70
55
56         page = entry({"admin", "services", "lxc_create"}, call("lxc_create"), nil)
57         page.leaf = true
58
59         page = entry({"admin", "services", "lxc_action"}, call("lxc_action"), nil)
60         page.leaf = true
61
62         page = entry({"admin", "services", "lxc_get_downloadable"}, call("lxc_get_downloadable"), nil)
63         page.leaf = true
64
65         page = entry({"admin", "services", "lxc_configuration_get"}, call("lxc_configuration_get"), nil)
66         page.leaf = true
67
68         page = entry({"admin", "services", "lxc_configuration_set"}, call("lxc_configuration_set"), nil)
69         page.leaf = true
70
71 end
72
73 function lxc_get_downloadable()
74         luci.http.prepare_content("application/json")
75
76         local f = io.popen('uname -m', 'r')
77         local target = f:read('*a')
78         f:close()
79         target = target:gsub("^%s*(.-)%s*$", "%1")
80
81         local templates = {}
82
83         local f = io.popen('lxc-create -n just_want_to_list_available_lxc_templates -t download -- --list', 'r')
84
85         for line in f:lines() do
86                 local dist,version = line:match("^(%S+)%s+(%S+)%s+" .. target .. "%s+default%s+%S+$")
87                 if dist~=nil and version~=nil then templates[#templates + 1] = dist .. ":" .. version end
88         end
89
90         f:close()
91         luci.http.write_json(templates)
92 end
93
94 function lxc_create(lxc_name, lxc_template)
95         luci.http.prepare_content("text/plain")
96
97         local uci = require("uci").cursor()
98
99         local url = uci:get("lxc", "lxc", "url")
100
101         if not pcall(dofile, "/etc/openwrt_release") then
102                 return luci.http.write("1")
103         end
104
105         local f = io.popen('uname -m', 'r')
106         local target = f:read('*a')
107         f:close()
108         target = target:gsub("^%s*(.-)%s*$", "%1")
109
110         local lxc_dist = lxc_template:gsub("(.*):(.*)", '%1')
111         local lxc_release = lxc_template:gsub("(.*):(.*)", '%2')
112
113         local data = conn:call("lxc", "create", { name = lxc_name, template = "download", args = { "--server", url,  "--no-validate", "--dist", lxc_dist, "--release", lxc_release, "--arch", target } } )
114
115         luci.http.write(data)
116 end
117
118 function lxc_action(lxc_action, lxc_name)
119         luci.http.prepare_content("application/json")
120
121         local data, ec = conn:call("lxc", lxc_action, lxc_name and { name = lxc_name} or {} )
122
123         luci.http.write_json(ec and {} or data)
124 end
125
126 function lxc_get_config_path()
127         local f = io.open("/etc/lxc/lxc.conf", "r")
128         local content = f:read("*all")
129         f:close()
130         local ret = content:match('^%s*lxc.lxcpath%s*=%s*([^%s]*)')
131         if ret then
132                 return ret .. "/"
133         else
134                 return "/srv/lxc/"
135         end
136 end
137
138 function lxc_configuration_get(lxc_name)
139         luci.http.prepare_content("text/plain")
140
141         local f = io.open(lxc_get_config_path() .. lxc_name .. "/config", "r")
142         local content = f:read("*all")
143         f:close()
144
145         luci.http.write(content)
146 end
147
148 function lxc_configuration_set(lxc_name)
149         luci.http.prepare_content("text/plain")
150
151         local lxc_configuration = luci.http.formvalue("lxc_configuration")
152
153         if lxc_configuration == nil then
154                 return luci.http.write("1")
155         end
156
157         local f, err = io.open(lxc_get_config_path() .. lxc_name .. "/config","w+")
158         if not f then
159                 return luci.http.write("2")
160         end
161
162         f:write(lxc_configuration)
163         f:close()
164
165         luci.http.write("0")
166 end
167